Merge tag 'thermal-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 3 Oct 2022 22:33:38 +0000 (15:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 3 Oct 2022 22:33:38 +0000 (15:33 -0700)
Pull thermal control updates from Rafael Wysocki:
 "The most significant part of this update is the thermal control DT
  initialization rework from Daniel Lezcano and the following conversion
  of drivers to use the new API introduced by it

  Apart from that, the maximum number of trip points in a thermal zone
  is increased and there are some fixes and code cleanups

  Specifics:

   - Rework the device tree initialization, convert the drivers to the
     new API and remove the old OF code (Daniel Lezcano)

   - Fix return value to -ENODEV when searching for a specific thermal
     zone which does not exist (Daniel Lezcano)

   - Fix the return value inspection in of_thermal_zone_find() (Dan
     Carpenter)

   - Fix kernel panic when KASAN is enabled as it detects use after free
     when unregistering a thermal zone (Daniel Lezcano)

   - Move the set_trip ops inside the therma sysfs code (Daniel Lezcano)

   - Remove unnecessary error message as it is already shown in the
     underlying function (Jiapeng Chong)

   - Rework the monitoring path and move the locks upper in the call
     stack to fix some potentials race windows (Daniel Lezcano)

   - Fix lockdep_assert() warning introduced by the lock rework (Daniel
     Lezcano)

   - Do not lock thermal zone mutex in the user space governor (Rafael
     Wysocki)

   - Revert the Mellanox 'hotter thermal zone' feature because it is
     already handled in the thermal framework core code (Daniel Lezcano)

   - Increase maximum number of trip points in the thermal core (Sumeet
     Pawnikar)

   - Replace strlcpy() with unused retval with strscpy() in the core
     thermal control code (Wolfram Sang)

   - Use module_pci_driver() macro in the int340x processor_thermal
     driver (Shang XiaoJing)

   - Use get_cpu() instead of smp_processor_id() in the intel_powerclamp
     thermal driver to prevent it from crashing and remove unused
     accounting for IRQ wakes from it (Srinivas Pandruvada)

   - Consolidate priv->data_vault checks in int340x_thermal (Rafael
     Wysocki)

   - Check the policy first in cpufreq_cooling_register() (Xuewen Yan)

   - Drop redundant error message from da9062-thermal (zhaoxiao)

   - Drop of_match_ptr() from thermal_mmio (Jean Delvare)"

* tag 'thermal-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (55 commits)
  thermal: core: Increase maximum number of trip points
  thermal: int340x: processor_thermal: Use module_pci_driver() macro
  thermal: intel_powerclamp: Remove accounting for IRQ wakes
  thermal: intel_powerclamp: Use get_cpu() instead of smp_processor_id() to avoid crash
  thermal: int340x_thermal: Consolidate priv->data_vault checks
  thermal: cpufreq_cooling: Check the policy first in cpufreq_cooling_register()
  thermal: Drop duplicate words from comments
  thermal: move from strlcpy() with unused retval to strscpy()
  thermal: da9062-thermal: Drop redundant error message
  thermal/drivers/thermal_mmio: Drop of_match_ptr()
  thermal: gov_user_space: Do not lock thermal zone mutex
  Revert "mlxsw: core: Add the hottest thermal zone detection"
  thermal/core: Fix lockdep_assert() warning
  thermal/core: Move the mutex inside the thermal_zone_device_update() function
  thermal/core: Move the thermal zone lock out of the governors
  thermal/governors: Group the thermal zone lock inside the throttle function
  thermal/core: Rework the monitoring a bit
  thermal/core: Rearm the monitoring only one time
  thermal/drivers/qcom/spmi-adc-tm5: Remove unnecessary print function dev_err()
  thermal/of: Remove old OF code
  ...

1409 files changed:
.mailmap
Documentation/ABI/testing/sysfs-bus-bcma
Documentation/ABI/testing/sysfs-bus-fcoe
Documentation/ABI/testing/sysfs-bus-iio-proximity
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/ABI/testing/sysfs-platform-chipidea-usb2
Documentation/ABI/testing/sysfs-power
Documentation/RCU/checklist.rst
Documentation/RCU/lockdep.rst
Documentation/RCU/rcu_dereference.rst
Documentation/RCU/whatisRCU.rst
Documentation/admin-guide/README.rst
Documentation/admin-guide/acpi/dsdt-override.rst [deleted file]
Documentation/admin-guide/hw-vuln/spectre.rst
Documentation/admin-guide/kdump/vmcoreinfo.rst
Documentation/admin-guide/mm/damon/usage.rst
Documentation/admin-guide/mm/hugetlbpage.rst
Documentation/block/index.rst
Documentation/block/ublk.rst [new file with mode: 0644]
Documentation/bpf/instruction-set.rst
Documentation/bpf/map_cgroup_storage.rst
Documentation/conf.py
Documentation/core-api/asm-annotations.rst [moved from Documentation/asm-annotations.rst with 97% similarity]
Documentation/core-api/cpu_hotplug.rst
Documentation/core-api/index.rst
Documentation/core-api/irq/irq-domain.rst
Documentation/core-api/wrappers/atomic_bitops.rst [new file with mode: 0644]
Documentation/core-api/wrappers/atomic_t.rst [new file with mode: 0644]
Documentation/core-api/wrappers/memory-barriers.rst [new file with mode: 0644]
Documentation/devicetree/bindings/arm/amlogic/amlogic,meson-gx-ao-secure.yaml
Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
Documentation/devicetree/bindings/display/bridge/analogix,anx7814.yaml
Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml
Documentation/devicetree/bindings/display/panel/sgd,gktw70sdae4se.yaml
Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
Documentation/devicetree/bindings/i2c/renesas,riic.yaml
Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml
Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
Documentation/devicetree/bindings/mailbox/amlogic,meson-gxbb-mhu.yaml
Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml
Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml
Documentation/devicetree/bindings/media/amlogic,meson-gx-ao-cec.yaml
Documentation/devicetree/bindings/memory-controllers/fsl/imx8m-ddrc.yaml
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml
Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
Documentation/devicetree/bindings/opp/opp-v2-qcom-level.yaml
Documentation/devicetree/bindings/phy/amlogic,axg-mipi-dphy.yaml
Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb2-phy.yaml
Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml
Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.yaml
Documentation/devicetree/bindings/reset/amlogic,meson-reset.yaml
Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml
Documentation/devicetree/bindings/rng/amlogic,meson-rng.yaml
Documentation/devicetree/bindings/serial/amlogic,meson-uart.yaml
Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.yaml
Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
Documentation/devicetree/bindings/spi/amlogic,meson6-spifc.yaml
Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml
Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
Documentation/devicetree/bindings/watchdog/amlogic,meson-gxbb-wdt.yaml
Documentation/doc-guide/sphinx.rst
Documentation/driver-api/driver-model/devres.rst
Documentation/driver-api/isa.rst
Documentation/fb/udlfb.rst
Documentation/filesystems/caching/backend-api.rst
Documentation/filesystems/ext4/super.rst
Documentation/filesystems/f2fs.rst
Documentation/filesystems/idmappings.rst
Documentation/filesystems/qnx6.rst
Documentation/filesystems/spufs/spufs.rst
Documentation/filesystems/xfs-delayed-logging-design.rst
Documentation/firmware-guide/acpi/enumeration.rst
Documentation/firmware-guide/acpi/osi.rst
Documentation/i2c/busses/i2c-piix4.rst
Documentation/i2c/dev-interface.rst
Documentation/i2c/i2c-topology.rst
Documentation/i2c/slave-interface.rst
Documentation/i2c/writing-clients.rst
Documentation/index.rst
Documentation/input/joydev/joystick.rst
Documentation/kbuild/gcc-plugins.rst
Documentation/locking/seqlock.rst
Documentation/memory-barriers.txt
Documentation/mm/unevictable-lru.rst
Documentation/networking/devlink/netdevsim.rst
Documentation/networking/driver.rst
Documentation/networking/ip-sysctl.rst
Documentation/networking/ipvlan.rst
Documentation/networking/l2tp.rst
Documentation/networking/mptcp-sysctl.rst
Documentation/networking/nf_conntrack-sysctl.rst
Documentation/networking/rxrpc.rst
Documentation/networking/switchdev.rst
Documentation/process/5.Posting.rst
Documentation/process/code-of-conduct-interpretation.rst
Documentation/process/coding-style.rst
Documentation/process/index.rst
Documentation/process/maintainer-pgp-guide.rst
Documentation/process/stable-kernel-rules.rst
Documentation/process/submitting-patches.rst
Documentation/scheduler/sched-design-CFS.rst
Documentation/sphinx/kerneldoc-preamble.sty
Documentation/staging/index.rst
Documentation/subsystem-apis.rst [new file with mode: 0644]
Documentation/trace/histogram.rst
Documentation/trace/kprobes.rst
Documentation/trace/timerlat-tracer.rst
Documentation/translations/ja_JP/SubmittingPatches
Documentation/translations/zh_CN/IRQ.txt [deleted file]
Documentation/translations/zh_CN/PCI/acpi-info.rst [new file with mode: 0644]
Documentation/translations/zh_CN/PCI/index.rst
Documentation/translations/zh_CN/admin-guide/README.rst
Documentation/translations/zh_CN/admin-guide/bootconfig.rst [new file with mode: 0644]
Documentation/translations/zh_CN/admin-guide/index.rst
Documentation/translations/zh_CN/core-api/circular-buffers.rst [new file with mode: 0644]
Documentation/translations/zh_CN/core-api/generic-radix-tree.rst [new file with mode: 0644]
Documentation/translations/zh_CN/core-api/idr.rst [new file with mode: 0644]
Documentation/translations/zh_CN/core-api/index.rst
Documentation/translations/zh_CN/core-api/packing.rst [new file with mode: 0644]
Documentation/translations/zh_CN/devicetree/changesets.rst [new file with mode: 0644]
Documentation/translations/zh_CN/devicetree/dynamic-resolution-notes.rst [new file with mode: 0644]
Documentation/translations/zh_CN/devicetree/index.rst
Documentation/translations/zh_CN/devicetree/kernel-api.rst [new file with mode: 0644]
Documentation/translations/zh_CN/devicetree/overlay-notes.rst [new file with mode: 0644]
Documentation/translations/zh_CN/driver-api/gpio/index.rst [new file with mode: 0644]
Documentation/translations/zh_CN/driver-api/gpio/legacy.rst [moved from Documentation/translations/zh_CN/gpio.txt with 89% similarity]
Documentation/translations/zh_CN/driver-api/index.rst [new file with mode: 0644]
Documentation/translations/zh_CN/driver-api/io_ordering.rst [new file with mode: 0644]
Documentation/translations/zh_CN/index.rst
Documentation/translations/zh_CN/io_ordering.txt [deleted file]
Documentation/translations/zh_CN/oops-tracing.txt [deleted file]
Documentation/translations/zh_CN/process/coding-style.rst
Documentation/translations/zh_CN/process/email-clients.rst
Documentation/translations/zh_CN/process/submit-checklist.rst
Documentation/translations/zh_CN/process/submitting-patches.rst
Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst
Documentation/translations/zh_TW/oops-tracing.txt [deleted file]
Documentation/virt/kvm/x86/mmu.rst
Documentation/w1/masters/ds2490.rst
Documentation/w1/w1-generic.rst
Documentation/x86/entry_64.rst
MAINTAINERS
Makefile
arch/Kconfig
arch/arm/boot/compressed/misc.c
arch/arm/boot/dts/am33xx-l4.dtsi
arch/arm/boot/dts/am5748.dtsi
arch/arm/boot/dts/arm-realview-eb.dtsi
arch/arm/boot/dts/arm-realview-pb1176.dts
arch/arm/boot/dts/arm-realview-pb11mp.dts
arch/arm/boot/dts/arm-realview-pbx.dtsi
arch/arm/boot/dts/at91-sama5d27_wlsom1.dtsi
arch/arm/boot/dts/at91-sama5d2_icp.dts
arch/arm/boot/dts/at91-sama7g5ek.dts
arch/arm/boot/dts/bcm63178.dtsi
arch/arm/boot/dts/bcm6846.dtsi
arch/arm/boot/dts/bcm6878.dtsi
arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi
arch/arm/boot/dts/imx6qdl-vicut1.dtsi
arch/arm/boot/dts/integratorap-im-pd1.dts
arch/arm/boot/dts/integratorap.dts
arch/arm/boot/dts/lan966x.dtsi
arch/arm/boot/dts/moxart-uc7112lx.dts
arch/arm/boot/dts/moxart.dtsi
arch/arm/boot/dts/versatile-ab.dts
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/sama7_defconfig
arch/arm/kernel/irq.c
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm_suspend.S
arch/arm/mach-ixp4xx/ixp4xx-of.c
arch/arm/mach-sunplus/Kconfig
arch/arm/mm/dump.c
arch/arm/mm/mmu.c
arch/arm64/Kconfig
arch/arm64/boot/dts/arm/juno-base.dtsi
arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts
arch/arm64/boot/dts/freescale/imx8mm-mx8menlo.dts
arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml-mba8mx.dts
arch/arm64/boot/dts/freescale/imx8mm-tqma8mqml.dtsi
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
arch/arm64/boot/dts/freescale/imx8ulp.dtsi
arch/arm64/boot/dts/qcom/sc7280.dtsi
arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
arch/arm64/boot/dts/qcom/sm8150.dtsi
arch/arm64/boot/dts/qcom/sm8350.dtsi
arch/arm64/boot/dts/renesas/r8a779g0.dtsi
arch/arm64/boot/dts/rockchip/px30-engicam-px30-core.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
arch/arm64/boot/dts/rockchip/rk3566-quartz64-b.dts
arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
arch/arm64/configs/defconfig
arch/arm64/include/asm/kernel-pgtable.h
arch/arm64/kernel/head.S
arch/arm64/kernel/machine_kexec_file.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/sleep.S
arch/arm64/kernel/topology.c
arch/arm64/kvm/arm.c
arch/arm64/mm/mmu.c
arch/loongarch/Kconfig
arch/loongarch/include/asm/acpi.h
arch/loongarch/include/asm/loongson.h
arch/loongarch/kernel/acpi.c
arch/loongarch/kernel/dma.c
arch/loongarch/kernel/head.S
arch/loongarch/kernel/setup.c
arch/loongarch/kernel/signal.c
arch/loongarch/kernel/traps.c
arch/loongarch/kernel/vmlinux.lds.S
arch/loongarch/lib/dump_tlb.c
arch/loongarch/mm/init.c
arch/m68k/Kconfig
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/include/uapi/asm/bootinfo-virt.h
arch/m68k/include/uapi/asm/bootinfo.h
arch/m68k/kernel/setup_mm.c
arch/m68k/virt/config.c
arch/mips/Kconfig
arch/mips/bcm47xx/prom.c
arch/mips/boot/dts/brcm/bcm63268.dtsi
arch/mips/boot/dts/lantiq/Makefile
arch/mips/boot/dts/lantiq/danube_easy50712.dts [moved from arch/mips/boot/dts/lantiq/easy50712.dts with 100% similarity]
arch/mips/cavium-octeon/executive/cvmx-cmd-queue.c
arch/mips/cavium-octeon/oct_ilm.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/setup.c
arch/mips/configs/ar7_defconfig
arch/mips/configs/ath25_defconfig
arch/mips/configs/ath79_defconfig
arch/mips/configs/bcm63xx_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/bmips_be_defconfig
arch/mips/configs/bmips_stb_defconfig
arch/mips/configs/cavium_octeon_defconfig
arch/mips/configs/db1xxx_defconfig
arch/mips/configs/decstation_64_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/decstation_r4k_defconfig
arch/mips/configs/fuloong2e_defconfig
arch/mips/configs/generic/board-ocelot.config
arch/mips/configs/gpr_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip28_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/jazz_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/loongson1b_defconfig
arch/mips/configs/loongson1c_defconfig
arch/mips/configs/loongson2k_defconfig
arch/mips/configs/loongson3_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/malta_kvm_defconfig
arch/mips/configs/malta_qemu_32r6_defconfig
arch/mips/configs/maltaaprp_defconfig
arch/mips/configs/maltasmvp_defconfig
arch/mips/configs/maltasmvp_eva_defconfig
arch/mips/configs/maltaup_defconfig
arch/mips/configs/maltaup_xpa_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/configs/omega2p_defconfig
arch/mips/configs/pic32mzda_defconfig
arch/mips/configs/rb532_defconfig
arch/mips/configs/rbtx49xx_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/rt305x_defconfig
arch/mips/configs/sb1250_swarm_defconfig
arch/mips/configs/vocore2_defconfig
arch/mips/configs/xway_defconfig
arch/mips/include/asm/irq.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/octeon/cvmx-fpa.h
arch/mips/include/asm/octeon/octeon.h
arch/mips/include/asm/octeon/pci-octeon.h
arch/mips/include/asm/sibyte/sb1250.h
arch/mips/include/asm/sni.h
arch/mips/kernel/prom.c
arch/mips/kernel/relocate.c
arch/mips/kernel/segment.c
arch/mips/kernel/setup.c
arch/mips/lantiq/clk.c
arch/mips/lantiq/prom.c
arch/mips/lantiq/xway/vmmc.c
arch/mips/lib/bswapdi.c
arch/mips/lib/bswapsi.c
arch/mips/loongson2ef/common/pci.c
arch/mips/loongson32/common/platform.c
arch/mips/loongson32/ls1c/board.c
arch/mips/math-emu/cp1emu.c
arch/mips/pci/pci-ar2315.c
arch/mips/pci/pci-lantiq.c
arch/mips/pic32/pic32mzda/init.c
arch/mips/ralink/bootrom.c
arch/mips/sgi-ip27/ip27-xtalk.c
arch/mips/sgi-ip30/ip30-xtalk.c
arch/mips/sibyte/sb1250/irq.c
arch/parisc/Kconfig
arch/parisc/kernel/irq.c
arch/powerpc/include/asm/firmware.h
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/rtas_entry.S
arch/powerpc/kernel/systbl.S
arch/powerpc/mm/book3s64/radix_pgtable.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/platforms/pseries/plpks.c
arch/riscv/Kconfig
arch/riscv/Kconfig.erratas
arch/riscv/boot/dts/microchip/mpfs.dtsi
arch/riscv/errata/thead/errata.c
arch/riscv/include/asm/cacheflush.h
arch/riscv/include/asm/kvm_vcpu_sbi.h
arch/riscv/kernel/setup.c
arch/riscv/kernel/signal.c
arch/riscv/kvm/vcpu_sbi.c
arch/riscv/kvm/vcpu_timer.c
arch/riscv/mm/dma-noncoherent.c
arch/riscv/mm/pageattr.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/softirq_stack.h
arch/s390/kernel/nmi.c
arch/s390/kernel/setup.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/gaccess.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/pci.c
arch/s390/kvm/pci.h
arch/s390/mm/fault.c
arch/s390/pci/Makefile
arch/s390/pci/pci_kvm_hook.c [new file with mode: 0644]
arch/sh/kernel/irq.c
arch/sparc/kernel/irq_64.c
arch/um/Makefile
arch/um/kernel/sysrq.c
arch/um/kernel/um_arch.c
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/events/perf_event.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/irq_stack.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/smp.h
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/sgx/encl.c
arch/x86/kernel/cpu/sgx/main.c
arch/x86/kernel/irq_32.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/emulate.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/spte.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/usercopy.c
arch/x86/mm/Makefile
arch/x86/um/shared/sysdep/syscalls_32.h
arch/x86/um/tls_32.c
arch/x86/um/vdso/Makefile
block/blk-core.c
block/blk-lib.c
block/blk-mq-debugfs.c
block/genhd.c
block/partitions/core.c
certs/Kconfig
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/acpi_amba.c
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_fpdt.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_pcc.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_video.c
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/bert.c
drivers/acpi/apei/erst.c
drivers/acpi/arm64/dma.c
drivers/acpi/bus.c
drivers/acpi/cppc_acpi.c
drivers/acpi/device_pm.c
drivers/acpi/dptf/Kconfig
drivers/acpi/ec.c
drivers/acpi/fan_core.c
drivers/acpi/internal.h
drivers/acpi/irq.c
drivers/acpi/numa/hmat.c
drivers/acpi/osi.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/processor_idle.c
drivers/acpi/property.c
drivers/acpi/resource.c
drivers/acpi/sbs.c
drivers/acpi/sbshc.c
drivers/acpi/scan.c
drivers/acpi/utils.c
drivers/acpi/x86/apple.c
drivers/acpi/x86/s2idle.c
drivers/acpi/x86/utils.c
drivers/amba/bus.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/ata/libata-core.c
drivers/ata/libata-sata.c
drivers/ata/libata-scsi.c
drivers/base/arch_topology.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/driver.c
drivers/base/firmware_loader/sysfs.c
drivers/base/firmware_loader/sysfs.h
drivers/base/firmware_loader/sysfs_upload.c
drivers/base/power/domain.c
drivers/base/power/runtime.c
drivers/base/power/wakeup.c
drivers/base/regmap/regmap-spi.c
drivers/block/virtio_blk.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/bus/mhi/host/main.c
drivers/char/mem.c
drivers/clk/bcm/clk-iproc-pll.c
drivers/clk/bcm/clk-raspberrypi.c
drivers/clk/clk-tps68470.c
drivers/clk/clk.c
drivers/clk/imx/clk-imx6sx.c
drivers/clk/imx/clk-imx93.c
drivers/clk/ingenic/tcu.c
drivers/clk/microchip/clk-mpfs.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.c
drivers/clk/ti/clk.c
drivers/counter/104-quad-8.c
drivers/cpufreq/amd-pstate.c
drivers/cpufreq/bmips-cpufreq.c
drivers/cpufreq/cppc_cpufreq.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/highbank-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/qcom-cpufreq-hw.c
drivers/cpufreq/sti-cpufreq.c
drivers/cpufreq/tegra194-cpufreq.c
drivers/cpufreq/ti-cpufreq.c
drivers/cpuidle/coupled.c
drivers/cpuidle/cpuidle-powernv.c
drivers/cpuidle/governor.c
drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
drivers/dax/hmem/device.c
drivers/devfreq/event/rockchip-dfi.c
drivers/devfreq/mtk-cci-devfreq.c
drivers/dma-buf/dma-resv.c
drivers/dma/ti/k3-udma-private.c
drivers/dma/xilinx/xilinx_dma.c
drivers/dma/xilinx/zynqmp_dma.c
drivers/firmware/arm_scmi/clock.c
drivers/firmware/arm_scmi/optee.c
drivers/firmware/arm_scmi/reset.c
drivers/firmware/arm_scmi/scmi_pm_domain.c
drivers/firmware/arm_scmi/sensors.c
drivers/firmware/efi/capsule-loader.c
drivers/firmware/efi/dev-path-parser.c
drivers/firmware/efi/efibc.c
drivers/firmware/efi/libstub/Makefile
drivers/firmware/efi/libstub/secureboot.c
drivers/firmware/efi/libstub/x86-stub.c
drivers/fpga/intel-m10-bmc-sec-update.c
drivers/gpio/gpio-104-dio-48e.c
drivers/gpio/gpio-104-idi-48.c
drivers/gpio/gpio-104-idio-16.c
drivers/gpio/gpio-ftgpio010.c
drivers/gpio/gpio-ixp4xx.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-mt7621.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-realtek-otto.c
drivers/gpio/gpio-rockchip.c
drivers/gpio/gpio-tqmx86.c
drivers/gpio/gpio-ws16c48.c
drivers/gpio/gpiolib-cdev.c
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdgpu/vega10_ih.c
drivers/gpu/drm/amd/amdgpu/vega20_ih.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.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_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.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/dcn32/dcn32_resource.h
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
drivers/gpu/drm/amd/display/dc/dml/Makefile
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h
drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
drivers/gpu/drm/amd/display/dc/inc/resource.h
drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c
drivers/gpu/drm/amd/display/modules/color/color_gamma.c
drivers/gpu/drm/amd/include/mes_v11_api_def.h
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.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.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/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/lontium-lt8912b.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/gma500/cdv_device.c
drivers/gpu/drm/gma500/gem.c
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/oaktrail_device.c
drivers/gpu/drm/gma500/power.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_irq.c
drivers/gpu/drm/gma500/psb_irq.h
drivers/gpu/drm/hisilicon/hibmc/Kconfig
drivers/gpu/drm/hyperv/hyperv_drm_drv.c
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_backlight.c
drivers/gpu/drm/i915/display/intel_bios.c
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_dp_link_training.c
drivers/gpu/drm/i915/display/intel_quirks.c
drivers/gpu/drm/i915/display/intel_vdsc.c
drivers/gpu/drm/i915/display/vlv_dsi.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_object.c
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/i915/gt/intel_engine_types.h
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
drivers/gpu/drm/i915/gt/intel_llc.c
drivers/gpu/drm/i915/gt/intel_migrate.c
drivers/gpu/drm/i915/gt/intel_rps.c
drivers/gpu/drm/i915/gt/intel_rps.h
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
drivers/gpu/drm/i915/gvt/aperture_gm.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_gvt_mmio_table.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/dp/dp_ctrl.c
drivers/gpu/drm/msm/dsi/dsi_cfg.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_gpu_devfreq.c
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/panel/panel-edp.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/panfrost/panfrost_devfreq.c
drivers/gpu/drm/rockchip/cdn-dp-core.c
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/hid-asus.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-nintendo.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/hid-thrustmaster.c
drivers/hid/hidraw.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/intel-ish-hid/ishtp-hid.h
drivers/hid/intel-ish-hid/ishtp/client.c
drivers/hv/hv_fcopy.c
drivers/hv/vmbus_drv.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/asus-ec-sensors.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/mr75203.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/tps23861.c
drivers/i2c/busses/i2c-amd-mp2-plat.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mlxbf.c
drivers/i2c/i2c-mux.c
drivers/idle/intel_idle.c
drivers/iio/adc/ad7292.c
drivers/iio/adc/mcp3911.c
drivers/iio/light/cm32181.c
drivers/iio/light/cm3605.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/hns/hns_roce_device.h
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
drivers/infiniband/hw/hns/hns_roce_main.c
drivers/infiniband/hw/hns/hns_roce_qp.c
drivers/infiniband/hw/irdma/uk.c
drivers/infiniband/hw/irdma/utils.c
drivers/infiniband/hw/irdma/verbs.c
drivers/infiniband/hw/mlx5/mad.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/umr.c
drivers/infiniband/sw/siw/siw_qp_tx.c
drivers/infiniband/ulp/rtrs/rtrs-clt.c
drivers/infiniband/ulp/rtrs/rtrs-srv.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce.h
drivers/input/keyboard/iqs62x-keys.c
drivers/input/keyboard/snvs_pwrkey.c
drivers/input/misc/rk805-pwrkey.c
drivers/input/mouse/synaptics.c
drivers/input/touchscreen/goodix.c
drivers/input/touchscreen/melfas_mip4.c
drivers/iommu/amd/iommu.c
drivers/iommu/amd/iommu_v2.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/iommu.h
drivers/iommu/iommu.c
drivers/iommu/of_iommu.c
drivers/iommu/virtio-iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-stm32-exti.c
drivers/media/dvb-core/dvb_vb2.c
drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c
drivers/media/rc/mceusb.c
drivers/media/usb/b2c2/flexcop-usb.c
drivers/media/usb/uvc/uvc_driver.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/misc/fastrpc.c
drivers/mmc/core/sd.c
drivers/mmc/host/mmc_hsq.c
drivers/mmc/host/moxart-mmc.c
drivers/mmc/host/sdhci.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/can/c_can/c_can.h
drivers/net/can/c_can/c_can_main.c
drivers/net/can/flexcan/flexcan-core.c
drivers/net/can/usb/gs_usb.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/lan937x_main.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/qca/qca8k-8xxx.c
drivers/net/dsa/xrs700x/xrs700x.c
drivers/net/ethernet/aquantia/atlantic/aq_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
drivers/net/ethernet/cortina/gemini.c
drivers/net/ethernet/freescale/enetc/Makefile
drivers/net/ethernet/freescale/enetc/enetc.c
drivers/net/ethernet/freescale/enetc/enetc.h
drivers/net/ethernet/freescale/enetc/enetc_pf.c
drivers/net/ethernet/freescale/enetc/enetc_qos.c
drivers/net/ethernet/freescale/enetc/enetc_vf.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/fungible/funeth/funeth_txrx.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/google/gve/gve_rx_dqo.c
drivers/net/ethernet/huawei/hinic/hinic_rx.c
drivers/net/ethernet/huawei/hinic/hinic_tx.c
drivers/net/ethernet/intel/i40e/i40e_client.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.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_base.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/intel/ice/ice_xsk.c
drivers/net/ethernet/intel/ice/ice_xsk.h
drivers/net/ethernet/marvell/prestera/prestera_main.c
drivers/net/ethernet/marvell/prestera/prestera_pci.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.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
drivers/net/ethernet/microsoft/mana/gdma_main.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx_channels.c
drivers/net/ethernet/sfc/siena/efx_channels.c
drivers/net/ethernet/sfc/siena/tx.c
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/hippi/rrunner.c
drivers/net/ieee802154/adf7242.c
drivers/net/ieee802154/ca8210.c
drivers/net/ieee802154/cc2520.c
drivers/net/ipa/ipa_qmi.c
drivers/net/ipa/ipa_qmi_msg.c
drivers/net/ipa/ipa_qmi_msg.h
drivers/net/ipa/ipa_table.c
drivers/net/ipa/ipa_table.h
drivers/net/ipvlan/ipvlan_core.c
drivers/net/mdio/fwnode_mdio.c
drivers/net/mdio/of_mdio.c
drivers/net/netdevsim/hwstats.c
drivers/net/netdevsim/netdev.c
drivers/net/phy/aquantia_main.c
drivers/net/phy/meson-gxl.c
drivers/net/phy/micrel.c
drivers/net/phy/microchip_t1.c
drivers/net/phy/phy_device.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/usbnet.c
drivers/net/wireguard/netlink.c
drivers/net/wireguard/selftest/ratelimiter.c
drivers/net/wireless/intel/iwlegacy/4965-rs.c
drivers/net/wireless/intel/iwlwifi/Kconfig
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c
drivers/net/wireless/microchip/wilc1000/netdev.h
drivers/net/wireless/microchip/wilc1000/sdio.c
drivers/net/wireless/microchip/wilc1000/wlan.c
drivers/net/xen-netback/xenbus.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/pmem.c
drivers/nvme/host/core.c
drivers/nvme/host/pci.c
drivers/nvme/host/tcp.c
drivers/nvme/target/auth.c
drivers/nvme/target/core.c
drivers/nvme/target/tcp.c
drivers/nvme/target/zns.c
drivers/of/fdt.c
drivers/opp/core.c
drivers/parisc/ccio-dma.c
drivers/parisc/iosapic.c
drivers/peci/controller/peci-aspeed.c
drivers/peci/cpu.c
drivers/perf/arm-cmn.c
drivers/perf/arm_dsu_pmu.c
drivers/perf/arm_pmu_platform.c
drivers/perf/qcom_l2_pmu.c
drivers/perf/qcom_l3_pmu.c
drivers/perf/riscv_pmu_sbi.c
drivers/phy/marvell/phy-mvebu-a3700-comphy.c
drivers/pinctrl/pinctrl-ocelot.c
drivers/pinctrl/qcom/pinctrl-sc8180x.c
drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
drivers/platform/mellanox/mlxreg-lc.c
drivers/platform/surface/surface_aggregator_registry.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/intel/int3472/common.c
drivers/platform/x86/intel/int3472/tps68470.c
drivers/platform/x86/intel/int3472/tps68470.h
drivers/platform/x86/intel/int3472/tps68470_board_data.c
drivers/platform/x86/p2sb.c
drivers/platform/x86/pmc_atom.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/x86-android-tablets.c
drivers/pnp/pnpbios/pnpbios.h
drivers/powercap/intel_rapl_common.c
drivers/regulator/core.c
drivers/regulator/pfuze100-regulator.c
drivers/reset/reset-imx7.c
drivers/reset/reset-microchip-sparx5.c
drivers/reset/reset-npcm.c
drivers/s390/block/dasd_alias.c
drivers/s390/crypto/vfio_ap_ops.c
drivers/scsi/hosts.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/soc/bcm/brcmstb/biuctrl.c
drivers/soc/bcm/brcmstb/pm/pm-arm.c
drivers/soc/fsl/Kconfig
drivers/soc/imx/gpcv2.c
drivers/soc/imx/imx8m-blk-ctrl.c
drivers/soc/sunxi/sunxi_sram.c
drivers/soundwire/qcom.c
drivers/spi/spi-bitbang-txrx.h
drivers/spi/spi-cadence-quadspi.c
drivers/spi/spi-mux.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi.c
drivers/staging/media/rkvdec/rkvdec-h264.c
drivers/staging/r8188eu/os_dep/os_intfs.c
drivers/staging/r8188eu/os_dep/usb_intf.c
drivers/staging/rtl8712/rtl8712_cmd.c
drivers/tee/tee_shm.c
drivers/thunderbolt/Kconfig
drivers/thunderbolt/acpi.c
drivers/thunderbolt/ctl.c
drivers/thunderbolt/icm.c
drivers/thunderbolt/nhi.h
drivers/thunderbolt/switch.c
drivers/tty/n_gsm.c
drivers/tty/serial/8250/8250_omap.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/serial-tegra.c
drivers/tty/serial/sifive.c
drivers/tty/serial/tegra-tcu.c
drivers/tty/tty_buffer.c
drivers/tty/vt/vt.c
drivers/usb/cdns3/cdns3-gadget.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/dwc3-qcom.c
drivers/usb/dwc3/dwc3-st.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/host.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/storage_common.c
drivers/usb/gadget/udc/core.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mtk-sch.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/musb/Kconfig
drivers/usb/serial/ch341.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_uas.h
drivers/usb/typec/Kconfig
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/class.c
drivers/usb/typec/mux/intel_pmc_mux.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/vdpa/ifcvf/ifcvf_base.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/vdpa_user/vduse_dev.c
drivers/vfio/pci/vfio_pci_zdev.c
drivers/vfio/vfio_iommu_type1.c
drivers/video/fbdev/hyperv_fb.c
drivers/virt/nitro_enclaves/Kconfig
drivers/xen/grant-table.c
drivers/xen/xenbus/xenbus_client.c
fs/afs/flock.c
fs/afs/fsclient.c
fs/afs/internal.h
fs/afs/misc.c
fs/afs/rxrpc.c
fs/afs/yfsclient.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/space-info.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/cachefiles/internal.h
fs/cachefiles/ondemand.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/transport.c
fs/coredump.c
fs/dax.c
fs/debugfs/inode.c
fs/erofs/fscache.c
fs/erofs/internal.h
fs/erofs/zmap.c
fs/exec.c
fs/exfat/fatent.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/mballoc.c
fs/ext4/mballoc.h
fs/internal.h
fs/nfs/internal.h
fs/nfs/nfs42proc.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/vfs.c
fs/ntfs/super.c
fs/open.c
fs/pstore/platform.c
fs/read_write.c
fs/tracefs/inode.c
fs/xfs/xfs_notify_failure.c
include/acpi/acpi_bus.h
include/acpi/cppc_acpi.h
include/asm-generic/softirq_stack.h
include/asm-generic/vmlinux.lds.h
include/drm/drm_connector.h
include/drm/drm_edid.h
include/kunit/test.h
include/linux/acpi.h
include/linux/amba/bus.h
include/linux/buffer_head.h
include/linux/compiler.h
include/linux/cpumask.h
include/linux/debugfs.h
include/linux/device/driver.h
include/linux/dma-mapping.h
include/linux/fscache.h
include/linux/hp_sdc.h
include/linux/ieee80211.h
include/linux/libata.h
include/linux/lsm_hook_defs.h
include/linux/lsm_hooks.h
include/linux/memcontrol.h
include/linux/memremap.h
include/linux/mlx5/driver.h
include/linux/of_device.h
include/linux/overflow.h
include/linux/pci_ids.h
include/linux/platform_data/tps68470.h
include/linux/platform_data/x86/pmc_atom.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/rmap.h
include/linux/scmi_protocol.h
include/linux/security.h
include/linux/serial_core.h
include/linux/skbuff.h
include/linux/spi/spi.h
include/linux/srcutiny.h
include/linux/suspend.h
include/linux/trace_events.h
include/linux/udp.h
include/linux/usb.h
include/linux/usb/typec_dp.h
include/net/af_rxrpc.h
include/net/bluetooth/hci_sock.h
include/net/bond_3ad.h
include/net/bonding.h
include/net/dropreason.h
include/net/ieee802154_netdev.h
include/net/ip_tunnels.h
include/net/netfilter/nf_conntrack.h
include/net/netns/conntrack.h
include/net/netns/ipv4.h
include/net/udp_tunnel.h
include/scsi/scsi_device.h
include/scsi/scsi_host.h
include/soc/at91/sama7-ddr.h
include/trace/events/scmi.h
include/trace/events/skb.h
include/uapi/linux/bpf.h
include/uapi/linux/if_tun.h
include/uapi/linux/io_uring.h
include/uapi/linux/virtio_net.h
io_uring/io_uring.c
io_uring/kbuf.h
io_uring/msg_ring.c
io_uring/net.c
io_uring/net.h
io_uring/notif.c
io_uring/notif.h
io_uring/opdef.c
io_uring/poll.c
io_uring/rsrc.c
io_uring/rsrc.h
io_uring/rw.c
io_uring/uring_cmd.c
kernel/bpf/cgroup.c
kernel/bpf/core.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/dma/debug.c
kernel/dma/mapping.c
kernel/dma/swiotlb.c
kernel/events/core.c
kernel/fork.c
kernel/kprobes.c
kernel/nsproxy.c
kernel/rcu/rcutorture.c
kernel/rcu/srcutiny.c
kernel/rcu/tasks.h
kernel/rcu/tiny.c
kernel/rcu/tree.c
kernel/rcu/tree_exp.h
kernel/rcu/tree_nocb.h
kernel/rcu/tree_plugin.h
kernel/rcu/tree_stall.h
kernel/sched/core.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/debug.c
kernel/smp.c
kernel/trace/rv/monitors/wip/wip.h
kernel/trace/rv/monitors/wwnr/wwnr.h
kernel/trace/rv/reactor_panic.c
kernel/trace/rv/reactor_printk.c
kernel/trace/trace_events_trigger.c
kernel/trace/trace_preemptirq.c
kernel/tracepoint.c
kernel/workqueue.c
lib/Kconfig.debug
lib/crypto/Kconfig
mm/damon/dbgfs.c
mm/damon/sysfs.c
mm/frontswap.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/khugepaged.c
mm/madvise.c
mm/memory-failure.c
mm/memory.c
mm/migrate_device.c
mm/page_alloc.c
mm/page_isolation.c
mm/pagewalk.c
mm/ptdump.c
mm/rmap.c
mm/secretmem.c
mm/slab_common.c
mm/slub.c
mm/swap_state.c
mm/util.c
mm/vmscan.c
net/batman-adv/hard-interface.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/bridge/br_netfilter_hooks.c
net/bridge/br_netfilter_ipv6.c
net/bridge/netfilter/ebtables.c
net/compat.c
net/core/.gitignore [deleted file]
net/core/Makefile
net/core/datagram.c
net/core/flow_dissector.c
net/core/net_namespace.c
net/core/skbuff.c
net/core/skmsg.c
net/dsa/tag_hellcreek.c
net/ieee802154/socket.c
net/ipv4/fib_frontend.c
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel.c
net/ipv4/ipmr.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv4/udp_tunnel_core.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ip6mr.c
net/ipv6/seg6.c
net/ipv6/udp.c
net/kcm/kcmsock.c
net/mac80211/ibss.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wpa.c
net/mac802154/rx.c
net/mpls/af_mpls.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_osf.c
net/netfilter/nft_ct.c
net/openvswitch/datapath.c
net/rxrpc/ar-internal.h
net/rxrpc/call_event.c
net/rxrpc/local_object.c
net/rxrpc/peer_event.c
net/rxrpc/recvmsg.c
net/rxrpc/rxkad.c
net/sched/act_ct.c
net/sched/cls_api.c
net/sched/sch_generic.c
net/sched/sch_sfb.c
net/sched/sch_taprio.c
net/sched/sch_tbf.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_wr.c
net/smc/smc_wr.h
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/tipc/monitor.c
net/wireless/debugfs.c
net/wireless/lib80211_crypt_ccmp.c
net/wireless/util.c
net/xdp/xsk_buff_pool.c
scripts/Makefile.debug
scripts/Makefile.extrawarn
scripts/checkpatch.pl
scripts/clang-tools/run-clang-tools.py
scripts/extract-ikconfig
scripts/gcc-ld [deleted file]
scripts/kconfig/lkc.h
scripts/kconfig/menu.c
scripts/mksysmap
security/landlock/fs.c
security/security.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/smack/smack_lsm.c
sound/core/control.c
sound/core/init.c
sound/core/memalloc.c
sound/core/oss/pcm_oss.c
sound/core/seq/oss/seq_oss_midi.c
sound/core/seq/seq_clientmgr.c
sound/drivers/aloop.c
sound/hda/intel-dsp-config.c
sound/hda/intel-nhlt.c
sound/pci/emu10k1/emupcm.c
sound/pci/hda/hda_bind.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/atmel/mchp-spdiftx.c
sound/soc/codecs/cs42l42.c
sound/soc/codecs/nau8540.c
sound/soc/codecs/nau8821.c
sound/soc/codecs/nau8824.c
sound/soc/codecs/nau8824.h
sound/soc/codecs/nau8825.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5640.h
sound/soc/codecs/tas2770.c
sound/soc/fsl/fsl_aud2htx.c
sound/soc/fsl/fsl_mqs.c
sound/soc/fsl/fsl_sai.c
sound/soc/fsl/imx-card.c
sound/soc/intel/boards/sof_sdw.c
sound/soc/mediatek/mt8186/mt8186-dai-adda.c
sound/soc/qcom/sm8250.c
sound/soc/sof/Kconfig
sound/soc/sof/ipc4-topology.c
sound/usb/card.c
sound/usb/endpoint.c
sound/usb/quirks.c
sound/usb/stream.c
tools/arch/x86/include/asm/cpufeatures.h
tools/debugging/kernel-chktaint
tools/hv/hv_kvp_daemon.c
tools/include/linux/gfp.h
tools/include/linux/gfp_types.h [new file with mode: 0644]
tools/include/nolibc/arch-riscv.h
tools/include/nolibc/sys.h
tools/include/uapi/asm/errno.h
tools/lib/perf/evlist.c
tools/memory-model/Documentation/litmus-tests.txt
tools/perf/Makefile.perf
tools/perf/builtin-c2c.c
tools/perf/builtin-lock.c
tools/perf/builtin-record.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/dlfilters/dlfilter-show-cycles.c
tools/perf/tests/mmap-basic.c
tools/perf/tests/perf-record.c
tools/perf/tests/shell/record.sh
tools/perf/tests/shell/stat_bpf_counters_cgrp.sh [new file with mode: 0755]
tools/perf/tests/shell/test_brstack.sh
tools/perf/tests/vmlinux-kallsyms.c
tools/perf/tests/wp.c
tools/perf/util/Build
tools/perf/util/affinity.c
tools/perf/util/arm-spe.c
tools/perf/util/bpf_counter_cgroup.c
tools/perf/util/bpf_skel/bperf_cgroup.bpf.c
tools/perf/util/bpf_skel/off_cpu.bpf.c
tools/perf/util/genelf.c
tools/perf/util/genelf.h
tools/perf/util/metricgroup.c
tools/perf/util/parse-events-hybrid.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/print-events.c
tools/perf/util/scripting-engines/Build
tools/perf/util/symbol-elf.c
tools/perf/util/synthetic-events.c
tools/power/acpi/tools/pfrut/pfrut.c
tools/testing/nvdimm/test/ndtest.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/DENYLIST.s390x
tools/testing/selftests/bpf/verifier/precise.c
tools/testing/selftests/drivers/net/bonding/Makefile
tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/bonding/config
tools/testing/selftests/drivers/net/bonding/dev_addr_lists.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/bonding/lag_lib.sh [new file with mode: 0644]
tools/testing/selftests/drivers/net/team/Makefile [new file with mode: 0644]
tools/testing/selftests/drivers/net/team/config [new file with mode: 0644]
tools/testing/selftests/drivers/net/team/dev_addr_lists.sh [new file with mode: 0755]
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/access_tracking_perf_test.c
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/include/x86_64/vmx.h
tools/testing/selftests/kvm/lib/assert.c
tools/testing/selftests/kvm/lib/string_override.c [new file with mode: 0644]
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/rseq_test.c
tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c
tools/testing/selftests/landlock/Makefile
tools/testing/selftests/landlock/fs_test.c
tools/testing/selftests/lib.mk
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/forwarding/router_multicast.sh
tools/testing/selftests/net/forwarding/sch_red.sh
tools/testing/selftests/net/io_uring_zerocopy_tx.c
tools/testing/selftests/net/io_uring_zerocopy_tx.sh
tools/testing/selftests/net/reuseport_bpf.c
tools/testing/selftests/netfilter/nft_concat_range.sh
tools/testing/selftests/netfilter/nft_conntrack_helper.sh
tools/testing/selftests/nolibc/.gitignore [new file with mode: 0644]
tools/testing/selftests/nolibc/Makefile [new file with mode: 0644]
tools/testing/selftests/nolibc/nolibc-test.c [new file with mode: 0644]
tools/testing/selftests/timens/Makefile
tools/testing/selftests/timens/vfork_exec.c [deleted file]
tools/testing/selftests/wireguard/qemu/Makefile
tools/virtio/linux/virtio.h
tools/virtio/linux/virtio_config.h

index 8ded2e7..1917781 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -71,6 +71,9 @@ Ben M Cahill <ben.m.cahill@intel.com>
 Ben Widawsky <bwidawsk@kernel.org> <ben@bwidawsk.net>
 Ben Widawsky <bwidawsk@kernel.org> <ben.widawsky@intel.com>
 Ben Widawsky <bwidawsk@kernel.org> <benjamin.widawsky@intel.com>
+Bjorn Andersson <andersson@kernel.org> <bjorn@kryo.se>
+Bjorn Andersson <andersson@kernel.org> <bjorn.andersson@linaro.org>
+Bjorn Andersson <andersson@kernel.org> <bjorn.andersson@sonymobile.com>
 Björn Steinbrink <B.Steinbrink@gmx.de>
 Björn Töpel <bjorn@kernel.org> <bjorn.topel@gmail.com>
 Björn Töpel <bjorn@kernel.org> <bjorn.topel@intel.com>
@@ -315,6 +318,7 @@ Morten Welinder <welinder@troll.com>
 Mythri P K <mythripk@ti.com>
 Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>
 Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>
+Neil Armstrong <neil.armstrong@linaro.org> <narmstrong@baylibre.com>
 Nguyen Anh Quynh <aquynh@gmail.com>
 Nicholas Piggin <npiggin@gmail.com> <npiggen@suse.de>
 Nicholas Piggin <npiggin@gmail.com> <npiggin@kernel.dk>
index 721b4ae..e93d3dd 100644 (file)
@@ -3,7 +3,7 @@ Date:           May 2011
 KernelVersion: 3.0
 Contact:       Rafał Miłecki <zajec5@gmail.com>
 Description:
-               Each BCMA core has it's manufacturer id. See
+               Each BCMA core has its manufacturer id. See
                include/linux/bcma/bcma.h for possible values.
 
 What:          /sys/bus/bcma/devices/.../id
index 8fe787c..5a4f209 100644 (file)
@@ -31,7 +31,7 @@ Description:  'FCoE Controller' instances on the fcoe bus.
                1) Write interface name to ctlr_create 2) Configure the FCoE
                Controller (ctlr_X) 3) Enable the FCoE Controller to begin
                discovery and login. The FCoE Controller is destroyed by
-               writing it's name, i.e. ctlr_X to the ctlr_delete file.
+               writing its name, i.e. ctlr_X to the ctlr_delete file.
 
 Attributes:
 
index 3aac6da..9b9d1cc 100644 (file)
@@ -18,7 +18,7 @@ Description:
                on the signal from which time of flight measurements are
                taken.
                The appropriate values to take is dependent on both the
-               sensor and it's operating environment:
+               sensor and its operating environment:
                * as3935 (0-31 range)
                18 = indoors (default)
                14 = outdoors
index 760c889..f54867c 100644 (file)
@@ -296,7 +296,7 @@ Description:        Processor frequency boosting control
 
                This switch controls the boost setting for the whole system.
                Boosting allows the CPU and the firmware to run at a frequency
-               beyond it's nominal limit.
+               beyond its nominal limit.
 
                More details can be found in
                Documentation/admin-guide/pm/cpufreq.rst
index b0f4684..b9f7d92 100644 (file)
@@ -2,8 +2,8 @@ What:           /sys/bus/platform/devices/ci_hdrc.0/role
 Date:          Mar 2017
 Contact:       Peter Chen <peter.chen@nxp.com>
 Description:
-               It returns string "gadget" or "host" when read it, it indicates
-               current controller role.
+               When read, it returns string "gadget" or "host", indicating
+               the current controller role.
 
-               It will do role switch when write "gadget" or "host" to it.
+               It will do role switch when "gadget" or "host" is written to it.
                Only controller at dual-role configuration supports writing.
index 90ec498..f99d433 100644 (file)
@@ -152,7 +152,7 @@ Description:
                case further investigation is required to determine which
                device is causing the problem.  Note that genuine RTC clock
                values (such as when pm_trace has not been used), can still
-               match a device and output it's name here.
+               match a device and output its name here.
 
 What:          /sys/power/pm_async
 Date:          January 2009
index 42cc5d8..048c5bc 100644 (file)
@@ -66,8 +66,13 @@ over a rather long period of time, but improvements are always welcome!
        As a rough rule of thumb, any dereference of an RCU-protected
        pointer must be covered by rcu_read_lock(), rcu_read_lock_bh(),
        rcu_read_lock_sched(), or by the appropriate update-side lock.
-       Disabling of preemption can serve as rcu_read_lock_sched(), but
-       is less readable and prevents lockdep from detecting locking issues.
+       Explicit disabling of preemption (preempt_disable(), for example)
+       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
+       only in non-preemptible kernels.  Such code can and will break,
+       especially in kernels built with CONFIG_PREEMPT_COUNT=y.
 
        Letting RCU-protected pointers "leak" out of an RCU read-side
        critical section is every bit as bad as letting them leak out
@@ -185,6 +190,9 @@ over a rather long period of time, but improvements are always welcome!
 
 5.     If call_rcu() or call_srcu() is used, the callback function will
        be called from softirq context.  In particular, it cannot block.
+       If you need the callback to block, run that code in a workqueue
+       handler scheduled from the callback.  The queue_rcu_work()
+       function does this for you in the case of call_rcu().
 
 6.     Since synchronize_rcu() can block, it cannot be called
        from any sort of irq context.  The same rule applies
@@ -297,7 +305,8 @@ over a rather long period of time, but improvements are always welcome!
                the machine.
 
        d.      Periodically invoke synchronize_rcu(), permitting a limited
-               number of updates per grace period.
+               number of updates per grace period.  Better yet, periodically
+               invoke rcu_barrier() to wait for all outstanding callbacks.
 
        The same cautions apply to call_srcu() and kfree_rcu().
 
@@ -477,6 +486,6 @@ over a rather long period of time, but improvements are always welcome!
        So if you need to wait for both an RCU grace period and for
        all pre-existing call_rcu() callbacks, you will need to execute
        both rcu_barrier() and synchronize_rcu(), if necessary, using
-       something like workqueues to to execute them concurrently.
+       something like workqueues to execute them concurrently.
 
        See rcubarrier.rst for more information.
index cc860a0..a94f559 100644 (file)
@@ -61,7 +61,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 when testing the
+               or coalescsing.  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 0b418a5..81e828c 100644 (file)
@@ -128,10 +128,16 @@ Follow these rules to keep your RCU code working properly:
                This sort of comparison occurs frequently when scanning
                RCU-protected circular linked lists.
 
-               Note that if checks for being within an RCU read-side
-               critical section are not required and the pointer is never
-               dereferenced, rcu_access_pointer() should be used in place
-               of rcu_dereference().
+               Note that if the pointer comparison is done outside
+               of an RCU read-side critical section, and the pointer
+               is never dereferenced, rcu_access_pointer() should be
+               used in place of rcu_dereference().  In most cases,
+               it is best to avoid accidental dereferences by testing
+               the rcu_access_pointer() return value directly, without
+               assigning it to a variable.
+
+               Within an RCU read-side critical section, there is little
+               reason to use rcu_access_pointer().
 
        -       The comparison is against a pointer that references memory
                that was initialized "a long time ago."  The reason
index 77ea260..1c747ac 100644 (file)
@@ -6,13 +6,15 @@ What is RCU?  --  "Read, Copy, Update"
 Please note that the "What is RCU?" LWN series is an excellent place
 to start learning about RCU:
 
-| 1.   What is RCU, Fundamentally?  http://lwn.net/Articles/262464/
-| 2.   What is RCU? Part 2: Usage   http://lwn.net/Articles/263130/
-| 3.   RCU part 3: the RCU API      http://lwn.net/Articles/264090/
-| 4.   The RCU API, 2010 Edition    http://lwn.net/Articles/418853/
-|      2010 Big API Table           http://lwn.net/Articles/419086/
-| 5.   The RCU API, 2014 Edition    http://lwn.net/Articles/609904/
-|      2014 Big API Table           http://lwn.net/Articles/609973/
+| 1.   What is RCU, Fundamentally?  https://lwn.net/Articles/262464/
+| 2.   What is RCU? Part 2: Usage   https://lwn.net/Articles/263130/
+| 3.   RCU part 3: the RCU API      https://lwn.net/Articles/264090/
+| 4.   The RCU API, 2010 Edition    https://lwn.net/Articles/418853/
+|      2010 Big API Table           https://lwn.net/Articles/419086/
+| 5.   The RCU API, 2014 Edition    https://lwn.net/Articles/609904/
+|      2014 Big API Table           https://lwn.net/Articles/609973/
+| 6.   The RCU API, 2019 Edition    https://lwn.net/Articles/777036/
+|      2019 Big API Table           https://lwn.net/Articles/777165/
 
 
 What is RCU?
@@ -915,13 +917,18 @@ which an RCU reference is held include:
 The understanding that RCU provides a reference that only prevents a
 change of type is particularly visible with objects allocated from a
 slab cache marked ``SLAB_TYPESAFE_BY_RCU``.  RCU operations may yield a
-reference to an object from such a cache that has been concurrently
-freed and the memory reallocated to a completely different object,
-though of the same type.  In this case RCU doesn't even protect the
-identity of the object from changing, only its type.  So the object
-found may not be the one expected, but it will be one where it is safe
-to take a reference or spinlock and then confirm that the identity
-matches the expectations.
+reference to an object from such a cache that has been concurrently freed
+and the memory reallocated to a completely different object, though of
+the same type.  In this case RCU doesn't even protect the identity of the
+object from changing, only its type.  So the object found may not be the
+one expected, but it will be one where it is safe to take a reference
+(and then potentially acquiring a spinlock), allowing subsequent code
+to check whether the identity matches expectations.  It is tempting
+to simply acquire the spinlock without first taking the reference, but
+unfortunately any spinlock in a ``SLAB_TYPESAFE_BY_RCU`` object must be
+initialized after each and every call to kmem_cache_alloc(), which renders
+reference-free spinlock acquisition completely unsafe.  Therefore, when
+using ``SLAB_TYPESAFE_BY_RCU``, make proper use of a reference counter.
 
 With traditional reference counting -- such as that implemented by the
 kref library in Linux -- there is typically code that runs when the last
@@ -1057,14 +1064,20 @@ SRCU: Initialization/cleanup::
        init_srcu_struct
        cleanup_srcu_struct
 
-All: lockdep-checked RCU-protected pointer access::
+All: lockdep-checked RCU utility APIs::
 
-       rcu_access_pointer
-       rcu_dereference_raw
        RCU_LOCKDEP_WARN
        rcu_sleep_check
        RCU_NONIDLE
 
+All: Unchecked RCU-protected pointer access::
+
+       rcu_dereference_raw
+
+All: Unchecked RCU-protected pointer access with dereferencing prohibited::
+
+       rcu_access_pointer
+
 See the comment headers in the source code (or the docbook generated
 from them) for more information.
 
index caa3c09..9a969c0 100644 (file)
@@ -1,9 +1,9 @@
 .. _readme:
 
-Linux kernel release 5.x <http://kernel.org/>
+Linux kernel release 6.x <http://kernel.org/>
 =============================================
 
-These are the release notes for Linux version 5.  Read them carefully,
+These are the release notes for Linux version 6.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong.
 
@@ -63,7 +63,7 @@ Installing the kernel source
    directory where you have permissions (e.g. your home directory) and
    unpack it::
 
-     xz -cd linux-5.x.tar.xz | tar xvf -
+     xz -cd linux-6.x.tar.xz | tar xvf -
 
    Replace "X" with the version number of the latest kernel.
 
@@ -72,12 +72,12 @@ Installing the kernel source
    files.  They should match the library, and not get messed up by
    whatever the kernel-du-jour happens to be.
 
- - You can also upgrade between 5.x releases by patching.  Patches are
+ - You can also upgrade between 6.x releases by patching.  Patches are
    distributed in the xz format.  To install by patching, get all the
    newer patch files, enter the top level directory of the kernel source
-   (linux-5.x) and execute::
+   (linux-6.x) and execute::
 
-     xz -cd ../patch-5.x.xz | patch -p1
+     xz -cd ../patch-6.x.xz | patch -p1
 
    Replace "x" for all versions bigger than the version "x" of your current
    source tree, **in_order**, and you should be ok.  You may want to remove
@@ -85,13 +85,13 @@ Installing the kernel source
    that there are no failed patches (some-file-name# or some-file-name.rej).
    If there are, either you or I have made a mistake.
 
-   Unlike patches for the 5.x kernels, patches for the 5.x.y kernels
+   Unlike patches for the 6.x kernels, patches for the 6.x.y kernels
    (also known as the -stable kernels) are not incremental but instead apply
-   directly to the base 5.x kernel.  For example, if your base kernel is 5.0
-   and you want to apply the 5.0.3 patch, you must not first apply the 5.0.1
-   and 5.0.2 patches. Similarly, if you are running kernel version 5.0.2 and
-   want to jump to 5.0.3, you must first reverse the 5.0.2 patch (that is,
-   patch -R) **before** applying the 5.0.3 patch. You can read more on this in
+   directly to the base 6.x kernel.  For example, if your base kernel is 6.0
+   and you want to apply the 6.0.3 patch, you must not first apply the 6.0.1
+   and 6.0.2 patches. Similarly, if you are running kernel version 6.0.2 and
+   want to jump to 6.0.3, you must first reverse the 6.0.2 patch (that is,
+   patch -R) **before** applying the 6.0.3 patch. You can read more on this in
    :ref:`Documentation/process/applying-patches.rst <applying_patches>`.
 
    Alternatively, the script patch-kernel can be used to automate this
@@ -114,7 +114,7 @@ Installing the kernel source
 Software requirements
 ---------------------
 
-   Compiling and running the 5.x kernels requires up-to-date
+   Compiling and running the 6.x kernels requires up-to-date
    versions of various software packages.  Consult
    :ref:`Documentation/process/changes.rst <changes>` for the minimum version numbers
    required and how to get updates for these packages.  Beware that using
@@ -132,12 +132,12 @@ Build directory for the kernel
    place for the output files (including .config).
    Example::
 
-     kernel source code: /usr/src/linux-5.x
+     kernel source code: /usr/src/linux-6.x
      build directory:    /home/name/build/kernel
 
    To configure and build the kernel, use::
 
-     cd /usr/src/linux-5.x
+     cd /usr/src/linux-6.x
      make O=/home/name/build/kernel menuconfig
      make O=/home/name/build/kernel
      sudo make O=/home/name/build/kernel modules_install install
@@ -262,8 +262,6 @@ Compiling the kernel
  - Make sure you have at least gcc 5.1 available.
    For more information, refer to :ref:`Documentation/process/changes.rst <changes>`.
 
-   Please note that you can still run a.out user programs with this kernel.
-
  - Do a ``make`` to create a compressed kernel image. It is also
    possible to do ``make install`` if you have lilo installed to suit the
    kernel makefiles, but you may want to check your particular lilo setup first.
@@ -332,85 +330,10 @@ Compiling the kernel
 If something goes wrong
 -----------------------
 
- - If you have problems that seem to be due to kernel bugs, please check
-   the file MAINTAINERS to see if there is a particular person associated
-   with the part of the kernel that you are having trouble with. If there
-   isn't anyone listed there, then the second best thing is to mail
-   them to me (torvalds@linux-foundation.org), and possibly to any other
-   relevant mailing-list or to the newsgroup.
-
- - In all bug-reports, *please* tell what kernel you are talking about,
-   how to duplicate the problem, and what your setup is (use your common
-   sense).  If the problem is new, tell me so, and if the problem is
-   old, please try to tell me when you first noticed it.
-
- - If the bug results in a message like::
-
-     unable to handle kernel paging request at address C0000010
-     Oops: 0002
-     EIP:   0010:XXXXXXXX
-     eax: xxxxxxxx   ebx: xxxxxxxx   ecx: xxxxxxxx   edx: xxxxxxxx
-     esi: xxxxxxxx   edi: xxxxxxxx   ebp: xxxxxxxx
-     ds: xxxx  es: xxxx  fs: xxxx  gs: xxxx
-     Pid: xx, process nr: xx
-     xx xx xx xx xx xx xx xx xx xx
-
-   or similar kernel debugging information on your screen or in your
-   system log, please duplicate it *exactly*.  The dump may look
-   incomprehensible to you, but it does contain information that may
-   help debugging the problem.  The text above the dump is also
-   important: it tells something about why the kernel dumped code (in
-   the above example, it's due to a bad kernel pointer). More information
-   on making sense of the dump is in Documentation/admin-guide/bug-hunting.rst
-
- - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
-   as is, otherwise you will have to use the ``ksymoops`` program to make
-   sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
-   This utility can be downloaded from
-   https://www.kernel.org/pub/linux/utils/kernel/ksymoops/ .
-   Alternatively, you can do the dump lookup by hand:
-
- - In debugging dumps like the above, it helps enormously if you can
-   look up what the EIP value means.  The hex value as such doesn't help
-   me or anybody else very much: it will depend on your particular
-   kernel setup.  What you should do is take the hex value from the EIP
-   line (ignore the ``0010:``), and look it up in the kernel namelist to
-   see which kernel function contains the offending address.
-
-   To find out the kernel function name, you'll need to find the system
-   binary associated with the kernel that exhibited the symptom.  This is
-   the file 'linux/vmlinux'.  To extract the namelist and match it against
-   the EIP from the kernel crash, do::
-
-     nm vmlinux | sort | less
-
-   This will give you a list of kernel addresses sorted in ascending
-   order, from which it is simple to find the function that contains the
-   offending address.  Note that the address given by the kernel
-   debugging messages will not necessarily match exactly with the
-   function addresses (in fact, that is very unlikely), so you can't
-   just 'grep' the list: the list will, however, give you the starting
-   point of each kernel function, so by looking for the function that
-   has a starting address lower than the one you are searching for but
-   is followed by a function with a higher address you will find the one
-   you want.  In fact, it may be a good idea to include a bit of
-   "context" in your problem report, giving a few lines around the
-   interesting one.
-
-   If you for some reason cannot do the above (you have a pre-compiled
-   kernel image or similar), telling me as much about your setup as
-   possible will help.  Please read
-   'Documentation/admin-guide/reporting-issues.rst' for details.
-
- - Alternatively, you can use gdb on a running kernel. (read-only; i.e. you
-   cannot change values or set break points.) To do this, first compile the
-   kernel with -g; edit arch/x86/Makefile appropriately, then do a ``make
-   clean``. You'll also need to enable CONFIG_PROC_FS (via ``make config``).
-
-   After you've rebooted with the new kernel, do ``gdb vmlinux /proc/kcore``.
-   You can now use all the usual gdb commands. The command to look up the
-   point where your system crashed is ``l *0xXXXXXXXX``. (Replace the XXXes
-   with the EIP value.)
-
-   gdb'ing a non-running kernel currently fails because ``gdb`` (wrongly)
-   disregards the starting offset for which the kernel is compiled.
+If you have problems that seem to be due to kernel bugs, please follow the
+instructions at 'Documentation/admin-guide/reporting-issues.rst'.
+
+Hints on understanding kernel bug reports are in
+'Documentation/admin-guide/bug-hunting.rst'. More on debugging the kernel
+with gdb is in 'Documentation/dev-tools/gdb-kernel-debugging.rst' and
+'Documentation/dev-tools/kgdb.rst'.
diff --git a/Documentation/admin-guide/acpi/dsdt-override.rst b/Documentation/admin-guide/acpi/dsdt-override.rst
deleted file mode 100644 (file)
index 50bd7f1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===============
-Overriding DSDT
-===============
-
-Linux supports a method of overriding the BIOS DSDT:
-
-CONFIG_ACPI_CUSTOM_DSDT - builds the image into the kernel.
-
-When to use this method is described in detail on the
-Linux/ACPI home page:
-https://01.org/linux-acpi/documentation/overriding-dsdt
index 2ce2a38..c4dcdb3 100644 (file)
@@ -613,6 +613,7 @@ kernel command line.
                 eibrs                   enhanced IBRS
                 eibrs,retpoline         enhanced IBRS + Retpolines
                 eibrs,lfence            enhanced IBRS + LFENCE
+                ibrs                    use IBRS to protect kernel
 
                Not specifying this option is equivalent to
                spectre_v2=auto.
index 8419019..6726f43 100644 (file)
@@ -200,7 +200,7 @@ prb
 
 A pointer to the printk ringbuffer (struct printk_ringbuffer). This
 may be pointing to the static boot ringbuffer or the dynamically
-allocated ringbuffer, depending on when the the core dump occurred.
+allocated ringbuffer, depending on when the core dump occurred.
 Used by user-space tools to read the active kernel log buffer.
 
 printk_rb_static
index d52f572..ca91ecc 100644 (file)
@@ -50,10 +50,10 @@ For a short example, users can monitor the virtual address space of a given
 workload as below. ::
 
     # cd /sys/kernel/mm/damon/admin/
-    # echo 1 > kdamonds/nr && echo 1 > kdamonds/0/contexts/nr
+    # echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
     # echo vaddr > kdamonds/0/contexts/0/operations
-    # echo 1 > kdamonds/0/contexts/0/targets/nr
-    # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid
+    # echo 1 > kdamonds/0/contexts/0/targets/nr_targets
+    # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
     # echo on > kdamonds/0/state
 
 Files Hierarchy
@@ -366,12 +366,12 @@ memory rate becomes larger than 60%, or lower than 30%". ::
     # echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
     # cd kdamonds/0/contexts/0/schemes/0
     # # set the basic access pattern and the action
-    # echo 4096 > access_patterns/sz/min
-    # echo 8192 > access_patterns/sz/max
-    # echo 0 > access_patterns/nr_accesses/min
-    # echo 5 > access_patterns/nr_accesses/max
-    # echo 10 > access_patterns/age/min
-    # echo 20 > access_patterns/age/max
+    # echo 4096 > access_pattern/sz/min
+    # echo 8192 > access_pattern/sz/max
+    # echo 0 > access_pattern/nr_accesses/min
+    # echo 5 > access_pattern/nr_accesses/max
+    # echo 10 > access_pattern/age/min
+    # echo 20 > access_pattern/age/max
     # echo pageout > action
     # # set quotas
     # echo 10 > quotas/ms
index 8e2727d..19f27c0 100644 (file)
@@ -65,7 +65,7 @@ HugePages_Surp
        may be temporarily larger than the maximum number of surplus huge
        pages when the system is under memory pressure.
 Hugepagesize
-       is the default hugepage size (in Kb).
+       is the default hugepage size (in kB).
 Hugetlb
         is the total amount of memory (in kB), consumed by huge
         pages of all sizes.
index 68f115f..c4c73db 100644 (file)
@@ -23,3 +23,4 @@ Block
    stat
    switching-sched
    writeback_cache_control
+   ublk
diff --git a/Documentation/block/ublk.rst b/Documentation/block/ublk.rst
new file mode 100644 (file)
index 0000000..2122d1a
--- /dev/null
@@ -0,0 +1,253 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================================
+Userspace block device driver (ublk driver)
+===========================================
+
+Overview
+========
+
+ublk is a generic framework for implementing block device logic from userspace.
+The motivation behind it is that moving virtual block drivers into userspace,
+such as loop, nbd and similar can be very helpful. It can help to implement
+new virtual block device such as ublk-qcow2 (there are several attempts of
+implementing qcow2 driver in kernel).
+
+Userspace block devices are attractive because:
+
+- They can be written many programming languages.
+- They can use libraries that are not available in the kernel.
+- They can be debugged with tools familiar to application developers.
+- Crashes do not kernel panic the machine.
+- Bugs are likely to have a lower security impact than bugs in kernel
+  code.
+- They can be installed and updated independently of the kernel.
+- They can be used to simulate block device easily with user specified
+  parameters/setting for test/debug purpose
+
+ublk block device (``/dev/ublkb*``) is added by ublk driver. Any IO request
+on the device will be forwarded to ublk userspace program. For convenience,
+in this document, ``ublk server`` refers to generic ublk userspace
+program. ``ublksrv`` [#userspace]_ is one of such implementation. It
+provides ``libublksrv`` [#userspace_lib]_ library for developing specific
+user block device conveniently, while also generic type block device is
+included, such as loop and null. Richard W.M. Jones wrote userspace nbd device
+``nbdublk`` [#userspace_nbdublk]_  based on ``libublksrv`` [#userspace_lib]_.
+
+After the IO is handled by userspace, the result is committed back to the
+driver, thus completing the request cycle. This way, any specific IO handling
+logic is totally done by userspace, such as loop's IO handling, NBD's IO
+communication, or qcow2's IO mapping.
+
+``/dev/ublkb*`` is driven by blk-mq request-based driver. Each request is
+assigned by one queue wide unique tag. ublk server assigns unique tag to each
+IO too, which is 1:1 mapped with IO of ``/dev/ublkb*``.
+
+Both the IO request forward and IO handling result committing are done via
+``io_uring`` passthrough command; that is why ublk is also one io_uring based
+block driver. It has been observed that using io_uring passthrough command can
+give better IOPS than block IO; which is why ublk is one of high performance
+implementation of userspace block device: not only IO request communication is
+done by io_uring, but also the preferred IO handling in ublk server is io_uring
+based approach too.
+
+ublk provides control interface to set/get ublk block device parameters.
+The interface is extendable and kabi compatible: basically any ublk request
+queue's parameter or ublk generic feature parameters can be set/get via the
+interface. Thus, ublk is generic userspace block device framework.
+For example, it is easy to setup a ublk device with specified block
+parameters from userspace.
+
+Using ublk
+==========
+
+ublk requires userspace ublk server to handle real block device logic.
+
+Below is example of using ``ublksrv`` to provide ublk-based loop device.
+
+- add a device::
+
+     ublk add -t loop -f ublk-loop.img
+
+- format with xfs, then use it::
+
+     mkfs.xfs /dev/ublkb0
+     mount /dev/ublkb0 /mnt
+     # do anything. all IOs are handled by io_uring
+     ...
+     umount /mnt
+
+- list the devices with their info::
+
+     ublk list
+
+- delete the device::
+
+     ublk del -a
+     ublk del -n $ublk_dev_id
+
+See usage details in README of ``ublksrv`` [#userspace_readme]_.
+
+Design
+======
+
+Control plane
+-------------
+
+ublk driver provides global misc device node (``/dev/ublk-control``) for
+managing and controlling ublk devices with help of several control commands:
+
+- ``UBLK_CMD_ADD_DEV``
+
+  Add a ublk char device (``/dev/ublkc*``) which is talked with ublk server
+  WRT IO command communication. Basic device info is sent together with this
+  command. It sets UAPI structure of ``ublksrv_ctrl_dev_info``,
+  such as ``nr_hw_queues``, ``queue_depth``, and max IO request buffer size,
+  for which the info is negotiated with the driver and sent back to the server.
+  When this command is completed, the basic device info is immutable.
+
+- ``UBLK_CMD_SET_PARAMS`` / ``UBLK_CMD_GET_PARAMS``
+
+  Set or get parameters of the device, which can be either generic feature
+  related, or request queue limit related, but can't be IO logic specific,
+  because the driver does not handle any IO logic. This command has to be
+  sent before sending ``UBLK_CMD_START_DEV``.
+
+- ``UBLK_CMD_START_DEV``
+
+  After the server prepares userspace resources (such as creating per-queue
+  pthread & io_uring for handling ublk IO), this command is sent to the
+  driver for allocating & exposing ``/dev/ublkb*``. Parameters set via
+  ``UBLK_CMD_SET_PARAMS`` are applied for creating the device.
+
+- ``UBLK_CMD_STOP_DEV``
+
+  Halt IO on ``/dev/ublkb*`` and remove the device. When this command returns,
+  ublk server will release resources (such as destroying per-queue pthread &
+  io_uring).
+
+- ``UBLK_CMD_DEL_DEV``
+
+  Remove ``/dev/ublkc*``. When this command returns, the allocated ublk device
+  number can be reused.
+
+- ``UBLK_CMD_GET_QUEUE_AFFINITY``
+
+  When ``/dev/ublkc`` is added, the driver creates block layer tagset, so
+  that each queue's affinity info is available. The server sends
+  ``UBLK_CMD_GET_QUEUE_AFFINITY`` to retrieve queue affinity info. It can
+  set up the per-queue context efficiently, such as bind affine CPUs with IO
+  pthread and try to allocate buffers in IO thread context.
+
+- ``UBLK_CMD_GET_DEV_INFO``
+
+  For retrieving device info via ``ublksrv_ctrl_dev_info``. It is the server's
+  responsibility to save IO target specific info in userspace.
+
+Data plane
+----------
+
+ublk server needs to create per-queue IO pthread & io_uring for handling IO
+commands via io_uring passthrough. The per-queue IO pthread
+focuses on IO handling and shouldn't handle any control & management
+tasks.
+
+The's IO is assigned by a unique tag, which is 1:1 mapping with IO
+request of ``/dev/ublkb*``.
+
+UAPI structure of ``ublksrv_io_desc`` is defined for describing each IO from
+the driver. A fixed mmaped area (array) on ``/dev/ublkc*`` is provided for
+exporting IO info to the server; such as IO offset, length, OP/flags and
+buffer address. Each ``ublksrv_io_desc`` instance can be indexed via queue id
+and IO tag directly.
+
+The following IO commands are communicated via io_uring passthrough command,
+and each command is only for forwarding the IO and committing the result
+with specified IO tag in the command data:
+
+- ``UBLK_IO_FETCH_REQ``
+
+  Sent from the server IO pthread for fetching future incoming IO requests
+  destined to ``/dev/ublkb*``. This command is sent only once from the server
+  IO pthread for ublk driver to setup IO forward environment.
+
+- ``UBLK_IO_COMMIT_AND_FETCH_REQ``
+
+  When an IO request is destined to ``/dev/ublkb*``, the driver stores
+  the IO's ``ublksrv_io_desc`` to the specified mapped area; then the
+  previous received IO command of this IO tag (either ``UBLK_IO_FETCH_REQ``
+  or ``UBLK_IO_COMMIT_AND_FETCH_REQ)`` is completed, so the server gets
+  the IO notification via io_uring.
+
+  After the server handles the IO, its result is committed back to the
+  driver by sending ``UBLK_IO_COMMIT_AND_FETCH_REQ`` back. Once ublkdrv
+  received this command, it parses the result and complete the request to
+  ``/dev/ublkb*``. In the meantime setup environment for fetching future
+  requests with the same IO tag. That is, ``UBLK_IO_COMMIT_AND_FETCH_REQ``
+  is reused for both fetching request and committing back IO result.
+
+- ``UBLK_IO_NEED_GET_DATA``
+
+  With ``UBLK_F_NEED_GET_DATA`` enabled, the WRITE request will be firstly
+  issued to ublk server without data copy. Then, IO backend of ublk server
+  receives the request and it can allocate data buffer and embed its addr
+  inside this new io command. After the kernel driver gets the command,
+  data copy is done from request pages to this backend's buffer. Finally,
+  backend receives the request again with data to be written and it can
+  truly handle the request.
+
+  ``UBLK_IO_NEED_GET_DATA`` adds one additional round-trip and one
+  io_uring_enter() syscall. Any user thinks that it may lower performance
+  should not enable UBLK_F_NEED_GET_DATA. ublk server pre-allocates IO
+  buffer for each IO by default. Any new project should try to use this
+  buffer to communicate with ublk driver. However, existing project may
+  break or not able to consume the new buffer interface; that's why this
+  command is added for backwards compatibility so that existing projects
+  can still consume existing buffers.
+
+- data copy between ublk server IO buffer and ublk block IO request
+
+  The driver needs to copy the block IO request pages into the server buffer
+  (pages) first for WRITE before notifying the server of the coming IO, so
+  that the server can handle WRITE request.
+
+  When the server handles READ request and sends
+  ``UBLK_IO_COMMIT_AND_FETCH_REQ`` to the server, ublkdrv needs to copy
+  the server buffer (pages) read to the IO request pages.
+
+Future development
+==================
+
+Container-aware ublk deivice
+----------------------------
+
+ublk driver doesn't handle any IO logic. Its function is well defined
+for now and very limited userspace interfaces are needed, which is also
+well defined too. It is possible to make ublk devices container-aware block
+devices in future as Stefan Hajnoczi suggested [#stefan]_, by removing
+ADMIN privilege.
+
+Zero copy
+---------
+
+Zero copy is a generic requirement for nbd, fuse or similar drivers. A
+problem [#xiaoguang]_ Xiaoguang mentioned is that pages mapped to userspace
+can't be remapped any more in kernel with existing mm interfaces. This can
+occurs when destining direct IO to ``/dev/ublkb*``. Also, he reported that
+big requests (IO size >= 256 KB) may benefit a lot from zero copy.
+
+
+References
+==========
+
+.. [#userspace] https://github.com/ming1/ubdsrv
+
+.. [#userspace_lib] https://github.com/ming1/ubdsrv/tree/master/lib
+
+.. [#userspace_nbdublk] https://gitlab.com/rwmjones/libnbd/-/tree/nbdublk
+
+.. [#userspace_readme] https://github.com/ming1/ubdsrv/blob/master/README
+
+.. [#stefan] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
+
+.. [#xiaoguang] https://lore.kernel.org/linux-block/YoOr6jBfgVm8GvWg@stefanha-x1.localdomain/
index 1b0e671..0ac7ae4 100644 (file)
@@ -133,7 +133,7 @@ code field of ``BPF_END``.
 The byte swap instructions operate on the destination register
 only and do not use a separate source register or immediate value.
 
-The 1-bit source operand field in the opcode is used to to select what byte
+The 1-bit source operand field in the opcode is used to select what byte
 order the operation convert from or to:
 
   =========  =====  =================================================
index cab9543..8e5fe53 100644 (file)
@@ -31,7 +31,7 @@ The map uses key of type of either ``__u64 cgroup_inode_id`` or
     };
 
 ``cgroup_inode_id`` is the inode id of the cgroup directory.
-``attach_type`` is the the program's attach type.
+``attach_type`` is the program's attach type.
 
 Linux 5.9 added support for type ``__u64 cgroup_inode_id`` as the key type.
 When this key type is used, then all attach types of the particular cgroup and
@@ -155,7 +155,7 @@ However, the BPF program can still only associate with one map of each type
 ``BPF_MAP_TYPE_CGROUP_STORAGE`` or more than one
 ``BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE``.
 
-In all versions, userspace may use the the attach parameters of cgroup and
+In all versions, userspace may use the attach parameters of cgroup and
 attach type pair in ``struct bpf_cgroup_storage_key`` as the key to the BPF map
 APIs to read or update the storage for a given attachment. For Linux 5.9
 attach type shared storages, only the first value in the struct, cgroup inode
index 934727e..b50c850 100644 (file)
 import sys
 import os
 import sphinx
+import shutil
+
+# helper
+# ------
+
+def have_command(cmd):
+    """Search ``cmd`` in the ``PATH`` environment.
+
+    If found, return True.
+    If not found, return False.
+    """
+    return shutil.which(cmd) is not None
 
 # Get Sphinx version
 major, minor, patch = sphinx.version_info[:3]
@@ -86,6 +98,7 @@ if major >= 3:
             "__used",
             "__weak",
             "noinline",
+            "__fix_address",
 
             # include/linux/memblock.h:
             "__init_memblock",
@@ -106,7 +119,32 @@ else:
 autosectionlabel_prefix_document = True
 autosectionlabel_maxdepth = 2
 
-extensions.append("sphinx.ext.imgmath")
+# Load math renderer:
+# For html builder, load imgmath only when its dependencies are met.
+# mathjax is the default math renderer since Sphinx 1.8.
+have_latex =  have_command('latex')
+have_dvipng = have_command('dvipng')
+load_imgmath = have_latex and have_dvipng
+
+# Respect SPHINX_IMGMATH (for html docs only)
+if 'SPHINX_IMGMATH' in os.environ:
+    env_sphinx_imgmath = os.environ['SPHINX_IMGMATH']
+    if 'yes' in env_sphinx_imgmath:
+        load_imgmath = True
+    elif 'no' in env_sphinx_imgmath:
+        load_imgmath = False
+    else:
+        sys.stderr.write("Unknown env SPHINX_IMGMATH=%s ignored.\n" % env_sphinx_imgmath)
+
+# Always load imgmath for Sphinx <1.8 or for epub docs
+load_imgmath = (load_imgmath or (major == 1 and minor < 8)
+                or 'epub' in sys.argv)
+
+if load_imgmath:
+    extensions.append("sphinx.ext.imgmath")
+    math_renderer = 'imgmath'
+else:
+    math_renderer = 'mathjax'
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -332,7 +370,8 @@ html_static_path = ['sphinx-static']
 html_use_smartypants = False
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# Note that the RTD theme ignores this.
+html_sidebars = { '**': ['searchbox.html', 'localtoc.html', 'sourcelink.html']}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
similarity index 97%
rename from Documentation/asm-annotations.rst
rename to Documentation/core-api/asm-annotations.rst
index a64f2ca..bc514ed 100644 (file)
@@ -43,10 +43,11 @@ annotated objects like this, tools can be run on them to generate more useful
 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 :doc:`ORC unwinder <x86/orc-unwinder>`
+automatically generate annotations for the ORC unwinder
+(Documentation/x86/orc-unwinder.rst)
 for most code. Both of these are especially important to support reliable
-stack traces which are in turn necessary for :doc:`Kernel live patching
-<livepatch/livepatch>`.
+stack traces which are in turn necessary for kernel live patching
+(Documentation/livepatch/livepatch.rst).
 
 Caveat and Discussion
 ---------------------
index c6f4ba2..f75778d 100644 (file)
@@ -560,7 +560,7 @@ available:
   * cpuhp_state_remove_instance(state, node)
   * cpuhp_state_remove_instance_nocalls(state, node)
 
-The arguments are the same as for the the cpuhp_state_add_instance*()
+The arguments are the same as for the cpuhp_state_add_instance*()
 variants above.
 
 The functions differ in the way how the installed callbacks are treated:
index dc95df4..b0e7b47 100644 (file)
@@ -23,6 +23,7 @@ it.
    printk-formats
    printk-index
    symbol-namespaces
+   asm-annotations
 
 Data structures and low-level utilities
 =======================================
@@ -44,6 +45,8 @@ Library functionality that is used throughout the kernel.
    this_cpu_ops
    timekeeping
    errseq
+   wrappers/atomic_t
+   wrappers/atomic_bitops
 
 Low level entry and exit
 ========================
@@ -67,6 +70,7 @@ Documentation/locking/index.rst for more related documentation.
    local_ops
    padata
    ../RCU/index
+   wrappers/memory-barriers.rst
 
 Low-level hardware management
 =============================
index d30b4d0..f88a6ee 100644 (file)
@@ -71,7 +71,7 @@ variety of methods:
 Note that irq domain lookups must happen in contexts that are
 compatible with a RCU read-side critical section.
 
-The irq_create_mapping() function must be called *atleast once*
+The irq_create_mapping() function must be called *at least once*
 before any call to irq_find_mapping(), lest the descriptor will not
 be allocated.
 
diff --git a/Documentation/core-api/wrappers/atomic_bitops.rst b/Documentation/core-api/wrappers/atomic_bitops.rst
new file mode 100644 (file)
index 0000000..bf24e40
--- /dev/null
@@ -0,0 +1,18 @@
+.. SPDX-License-Identifier: GPL-2.0
+   This is a simple wrapper to bring atomic_bitops.txt into the RST world
+   until such a time as that file can be converted directly.
+
+=============
+Atomic bitops
+=============
+
+.. raw:: latex
+
+    \footnotesize
+
+.. include:: ../../atomic_bitops.txt
+   :literal:
+
+.. raw:: latex
+
+    \normalsize
diff --git a/Documentation/core-api/wrappers/atomic_t.rst b/Documentation/core-api/wrappers/atomic_t.rst
new file mode 100644 (file)
index 0000000..ed109a9
--- /dev/null
@@ -0,0 +1,19 @@
+.. SPDX-License-Identifier: GPL-2.0
+   This is a simple wrapper to bring atomic_t.txt into the RST world
+   until such a time as that file can be converted directly.
+
+============
+Atomic types
+============
+
+.. raw:: latex
+
+    \footnotesize
+
+.. include:: ../../atomic_t.txt
+   :literal:
+
+.. raw:: latex
+
+    \normalsize
+
diff --git a/Documentation/core-api/wrappers/memory-barriers.rst b/Documentation/core-api/wrappers/memory-barriers.rst
new file mode 100644 (file)
index 0000000..532460b
--- /dev/null
@@ -0,0 +1,18 @@
+.. SPDX-License-Identifier: GPL-2.0
+   This is a simple wrapper to bring memory-barriers.txt into the RST world
+   until such a time as that file can be converted directly.
+
+============================
+Linux kernel memory barriers
+============================
+
+.. raw:: latex
+
+    \footnotesize
+
+.. include:: ../../memory-barriers.txt
+   :literal:
+
+.. raw:: latex
+
+    \normalsize
index 6cc7452..1748f16 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson Firmware registers Interface
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The Meson SoCs have a register bank with status and data shared with the
index 2e208d2..7cdffdb 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic specific extensions to the Synopsys Designware HDMI Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 allOf:
   - $ref: /schemas/sound/name-prefix.yaml#
index 047fd69..6655a93 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson Display Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The Amlogic Meson Display controller is composed of several components
index bce96b5..4a5e5d9 100644 (file)
@@ -8,7 +8,7 @@ title: Analogix ANX7814 SlimPort (Full-HD Transmitter)
 
 maintainers:
   - Andrzej Hajda <andrzej.hajda@intel.com>
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
   - Robert Foss <robert.foss@linaro.org>
 
 properties:
index c6e81f5..1b2185b 100644 (file)
@@ -8,7 +8,7 @@ title: ITE it66121 HDMI bridge Device Tree Bindings
 
 maintainers:
   - Phong LE <ple@baylibre.com>
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The IT66121 is a high-performance and low-power single channel HDMI
index 44e02de..2e75e37 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Solomon Goldentek Display GKTW70SDAE4SE 7" WVGA LVDS Display Panel
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
   - Thierry Reding <thierry.reding@gmail.com>
 
 allOf:
index 8a9f355..7e14e26 100644 (file)
@@ -34,8 +34,8 @@ Example:
 Use specific request line passing from dma
 For example, MMC request line is 5
 
-       sdhci: sdhci@98e00000 {
-               compatible = "moxa,moxart-sdhci";
+       mmc: mmc@98e00000 {
+               compatible = "moxa,moxart-mmc";
                reg = <0x98e00000 0x5C>;
                interrupts = <5 0>;
                clocks = <&clk_apb>;
index b79f069..8ea97e7 100644 (file)
@@ -48,7 +48,6 @@ required:
   - compatible
   - reg
   - reg-names
-  - intel,vm-map
   - clocks
   - resets
   - "#thermal-sensor-cells"
index 6ecb027..199a354 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson I2C Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
   - Beniamino Galvani <b.galvani@gmail.com>
 
 allOf:
index 2f31548..d3c0d5c 100644 (file)
@@ -60,6 +60,9 @@ properties:
   power-domains:
     maxItems: 1
 
+  resets:
+    maxItems: 1
+
 required:
   - compatible
   - reg
index a415887..bf396e9 100644 (file)
@@ -57,6 +57,11 @@ properties:
       - description: interrupt ID for I2C event
       - description: interrupt ID for I2C error
 
+  interrupt-names:
+    items:
+      - const: event
+      - const: error
+
   resets:
     maxItems: 1
 
@@ -92,6 +97,8 @@ properties:
           - description: register offset within syscfg
           - description: register bitmask for FMP bit
 
+  wakeup-source: true
+
 required:
   - compatible
   - reg
index b6bbc31..1414ba9 100644 (file)
@@ -24,8 +24,10 @@ properties:
 
   interrupts:
     minItems: 1
+    maxItems: 2
     description:
       Should be configured with type IRQ_TYPE_EDGE_RISING.
+      If two interrupts are provided, expected order is INT1 and INT2.
 
 required:
   - compatible
index 93f2ce3..19ac9da 100644 (file)
@@ -16,6 +16,7 @@ properties:
   compatible:
     enum:
       - goodix,gt1151
+      - goodix,gt1158
       - goodix,gt5663
       - goodix,gt5688
       - goodix,gt911
index 09c8948..fa4f768 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Generic i.MX bus frequency device
 
 maintainers:
-  - Leonard Crestez <leonard.crestez@nxp.com>
+  - Peng Fan <peng.fan@nxp.com>
 
 description: |
   The i.MX SoC family has multiple buses for which clock frequency (and
index 85c85b6..e18107e 100644 (file)
@@ -96,7 +96,7 @@ properties:
               Documentation/devicetree/bindings/arm/cpus.yaml).
 
         required:
-          - fiq-index
+          - apple,fiq-index
           - cpus
 
 required:
index ea06976..dfd26b9 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson Message-Handling-Unit Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The Amlogic's Meson SoCs Message-Handling-Unit (MHU) is a mailbox controller
index bee93bd..e551be5 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic GE2D Acceleration Unit
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 properties:
   compatible:
index 5044c4b..b827eda 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Video Decoder
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
   - Maxime Jourdan <mjourdan@baylibre.com>
 
 description: |
index d93aea6..8d844f4 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson AO-CEC Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The Amlogic Meson AO-CEC module is present is Amlogic SoCs and its purpose is
index 445e46f..2b39fce 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: i.MX8M DDR Controller
 
 maintainers:
-  - Leonard Crestez <leonard.crestez@nxp.com>
+  - Peng Fan <peng.fan@nxp.com>
 
 description:
   The DDRC block is integrated in i.MX8M for interfacing with DDR based
index a3b976f..5750cc0 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Khadas on-board Microcontroller Device Tree Bindings
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   Khadas embeds a microcontroller on their VIM and Edge boards adding some
index 608e1d6..ddd5a07 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson DWMAC Ethernet controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
   - Martin Blumenstingl <martin.blumenstingl@googlemail.com>
 
 # We need a select here so we don't match all nodes with 'snps,dwmac'
index 59663e8..a202b6c 100644 (file)
@@ -40,6 +40,7 @@ properties:
 patternProperties:
   '^opp-?[0-9]+$':
     type: object
+    additionalProperties: false
 
     properties:
       opp-hz: true
index 14a7a68..df8442f 100644 (file)
@@ -19,6 +19,7 @@ properties:
 patternProperties:
   '^opp-?[0-9]+$':
     type: object
+    additionalProperties: false
 
     properties:
       opp-level: true
index be485f5..5eddaed 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic AXG MIPI D-PHY
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 properties:
   compatible:
index 399ebde..f3a5fba 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic G12A USB2 PHY
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 properties:
   compatible:
index 453c083..868b4e6 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic G12A USB3 + PCIE Combo PHY
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 properties:
   compatible:
index 33d1d37..624e14f 100644 (file)
@@ -8,7 +8,6 @@ title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS)
   Low Power Island (LPI) TLMM block
 
 maintainers:
-  - Srinivasa Rao Mandadapu <srivasam@codeaurora.org>
   - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
 
 description: |
index 2d22816..2bd60c4 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Qualcomm Technologies, Inc. SC7280 TLMM block
 
 maintainers:
-  - Rajendra Nayak <rnayak@codeaurora.org>
+  - Bjorn Andersson <andersson@kernel.org>
 
 description: |
   This binding describes the Top Level Mode Multiplexer block found in the
index 5390e98..43a9322 100644 (file)
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Amlogic Meson Everything-Else Power Domains
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |+
   The Everything-Else Power Domains node should be the child of a syscon
index 0ccca49..3934a2b 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Qualcomm RPM/RPMh Power domains
 
 maintainers:
-  - Rajendra Nayak <rnayak@codeaurora.org>
+  - Bjorn Andersson <andersson@kernel.org>
 
 description:
   For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
index 8b7c4af..faa4af9 100644 (file)
@@ -35,6 +35,7 @@ patternProperties:
     description: List of regulators and its properties
     type: object
     $ref: regulator.yaml#
+    unevaluatedProperties: false
 
     properties:
       qcom,ocp-max-retries:
@@ -100,8 +101,6 @@ patternProperties:
           SAW controlled gang leader. Will be configured as SAW regulator.
         type: boolean
 
-      unevaluatedProperties: false
-
 required:
   - compatible
 
index 494a454..98db2aa 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson SoC Reset Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 properties:
   compatible:
index 69cdab1..ca3b9be 100644 (file)
@@ -17,9 +17,6 @@ description:
   acts as directory-based coherency manager.
   All the properties in ePAPR/DeviceTree specification applies for this platform.
 
-allOf:
-  - $ref: /schemas/cache-controller.yaml#
-
 select:
   properties:
     compatible:
@@ -33,11 +30,16 @@ select:
 
 properties:
   compatible:
-    items:
-      - enum:
-          - sifive,fu540-c000-ccache
-          - sifive,fu740-c000-ccache
-      - const: cache
+    oneOf:
+      - items:
+          - enum:
+              - sifive,fu540-c000-ccache
+              - sifive,fu740-c000-ccache
+          - const: cache
+      - items:
+          - const: microchip,mpfs-ccache
+          - const: sifive,fu540-c000-ccache
+          - const: cache
 
   cache-block-size:
     const: 64
@@ -72,29 +74,46 @@ properties:
       The reference to the reserved-memory for the L2 Loosely Integrated Memory region.
       The reserved memory node should be defined as per the bindings in reserved-memory.txt.
 
-if:
-  properties:
-    compatible:
-      contains:
-        const: sifive,fu540-c000-ccache
+allOf:
+  - $ref: /schemas/cache-controller.yaml#
 
-then:
-  properties:
-    interrupts:
-      description: |
-        Must contain entries for DirError, DataError and DataFail signals.
-      maxItems: 3
-    cache-sets:
-      const: 1024
-
-else:
-  properties:
-    interrupts:
-      description: |
-        Must contain entries for DirError, DataError, DataFail, DirFail signals.
-      minItems: 4
-    cache-sets:
-      const: 2048
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - sifive,fu740-c000-ccache
+              - microchip,mpfs-ccache
+
+    then:
+      properties:
+        interrupts:
+          description: |
+            Must contain entries for DirError, DataError, DataFail, DirFail signals.
+          minItems: 4
+
+    else:
+      properties:
+        interrupts:
+          description: |
+            Must contain entries for DirError, DataError and DataFail signals.
+          maxItems: 3
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: sifive,fu740-c000-ccache
+
+    then:
+      properties:
+        cache-sets:
+          const: 2048
+
+    else:
+      properties:
+        cache-sets:
+          const: 1024
 
 additionalProperties: false
 
index 444be32..09c6c90 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson Random number generator
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 properties:
   compatible:
index 72e8868..7822705 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson SoC UART Serial Interface
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The Amlogic Meson SoC UART Serial Interface is present on a large range
index 17db87c..c3c5990 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Canvas Video Lookup Table
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
   - Maxime Jourdan <mjourdan@baylibre.com>
 
 description: |
index 50de0da..0c10f76 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson SPI Communication Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 allOf:
   - $ref: "spi-controller.yaml#"
index 8a9d526..ac3b2ec 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson SPI Flash Controller
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 allOf:
   - $ref: "spi-controller.yaml#"
index e349fa5..daf2a85 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Amlogic Meson G12A DWC3 USB SoC Controller Glue
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 description: |
   The Amlogic G12A embeds a DWC3 USB IP Core configured for USB2 and USB3
index e63b665..b019d49 100644 (file)
@@ -24,6 +24,7 @@ properties:
           - mediatek,mt2712-mtu3
           - mediatek,mt8173-mtu3
           - mediatek,mt8183-mtu3
+          - mediatek,mt8188-mtu3
           - mediatek,mt8192-mtu3
           - mediatek,mt8195-mtu3
       - const: mediatek,mtu3
index fea3e70..cd2f7cb 100644 (file)
@@ -33,6 +33,7 @@ properties:
           - qcom,sm6115-dwc3
           - qcom,sm6125-dwc3
           - qcom,sm6350-dwc3
+          - qcom,sm6375-dwc3
           - qcom,sm8150-dwc3
           - qcom,sm8250-dwc3
           - qcom,sm8350-dwc3
@@ -108,12 +109,17 @@ properties:
       HS/FS/LS modes are supported.
     type: boolean
 
+  wakeup-source: true
+
 # Required child node:
 
 patternProperties:
   "^usb@[0-9a-f]+$":
     $ref: snps,dwc3.yaml#
 
+    properties:
+      wakeup-source: false
+
 required:
   - compatible
   - reg
index c7459cf..497d604 100644 (file)
@@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: Meson GXBB SoCs Watchdog timer
 
 maintainers:
-  - Neil Armstrong <narmstrong@baylibre.com>
+  - Neil Armstrong <neil.armstrong@linaro.org>
 
 allOf:
   - $ref: watchdog.yaml#
index 1228b85..c708cec 100644 (file)
@@ -48,10 +48,6 @@ or ``virtualenv``, depending on how your distribution packaged Python 3.
       on the Sphinx version, it should be installed separately,
       with ``pip install sphinx_rtd_theme``.
 
-   #) Some ReST pages contain math expressions. Due to the way Sphinx works,
-      those expressions are written using LaTeX notation. It needs texlive
-      installed with amsfonts and amsmath in order to evaluate them.
-
 In summary, if you want to install Sphinx version 2.4.4, you should do::
 
        $ virtualenv sphinx_2.4.4
@@ -86,6 +82,27 @@ Depending on the distribution, you may also need to install a series of
 ``texlive`` packages that provide the minimal set of functionalities
 required for ``XeLaTeX`` to work.
 
+Math Expressions in HTML
+------------------------
+
+Some ReST pages contain math expressions. Due to the way Sphinx works,
+those expressions are written using LaTeX notation.
+There are two options for Sphinx to render math expressions in html output.
+One is an extension called `imgmath`_ which converts math expressions into
+images and embeds them in html pages.
+The other is an extension called `mathjax`_ which delegates math rendering
+to JavaScript capable web browsers.
+The former was the only option for pre-6.1 kernel documentation and it
+requires quite a few texlive packages including amsfonts and amsmath among
+others.
+
+Since kernel release 6.1, html pages with math expressions can be built
+without installing any texlive packages. See `Choice of Math Renderer`_ for
+further info.
+
+.. _imgmath: https://www.sphinx-doc.org/en/master/usage/extensions/math.html#module-sphinx.ext.imgmath
+.. _mathjax: https://www.sphinx-doc.org/en/master/usage/extensions/math.html#module-sphinx.ext.mathjax
+
 .. _sphinx-pre-install:
 
 Checking for Sphinx dependencies
@@ -164,6 +181,38 @@ To remove the generated documentation, run ``make cleandocs``.
          as well would improve the quality of images embedded in PDF
          documents, especially for kernel releases 5.18 and later.
 
+Choice of Math Renderer
+-----------------------
+
+Since kernel release 6.1, mathjax works as a fallback math renderer for
+html output.\ [#sph1_8]_
+
+Math renderer is chosen depending on available commands as shown below:
+
+.. table:: Math Renderer Choices for HTML
+
+    ============= ================= ============
+    Math renderer Required commands Image format
+    ============= ================= ============
+    imgmath       latex, dvipng     PNG (raster)
+    mathjax
+    ============= ================= ============
+
+The choice can be overridden by setting an environment variable
+``SPHINX_IMGMATH`` as shown below:
+
+.. table:: Effect of Setting ``SPHINX_IMGMATH``
+
+    ====================== ========
+    Setting                Renderer
+    ====================== ========
+    ``SPHINX_IMGMATH=yes`` imgmath
+    ``SPHINX_IMGMATH=no``  mathjax
+    ====================== ========
+
+.. [#sph1_8] Fallback of math renderer requires Sphinx >=1.8.
+
+
 Writing Documentation
 =====================
 
index 5527294..dc1b235 100644 (file)
@@ -301,6 +301,7 @@ IO region
   devm_release_region()
   devm_release_resource()
   devm_request_mem_region()
+  devm_request_free_mem_region()
   devm_request_region()
   devm_request_resource()
 
@@ -334,7 +335,7 @@ IRQ
   devm_irq_alloc_descs_from()
   devm_irq_alloc_generic_chip()
   devm_irq_setup_generic_chip()
-  devm_irq_sim_init()
+  devm_irq_domain_create_sim()
 
 LED
   devm_led_classdev_register()
@@ -392,7 +393,9 @@ PHY
 PINCTRL
   devm_pinctrl_get()
   devm_pinctrl_put()
+  devm_pinctrl_get_select()
   devm_pinctrl_register()
+  devm_pinctrl_register_and_init()
   devm_pinctrl_unregister()
 
 POWER
@@ -427,6 +430,8 @@ SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
 
 SPI
+  devm_spi_alloc_master()
+  devm_spi_alloc_slave()
   devm_spi_register_master()
 
 WATCHDOG
index def4a7b..3df1b16 100644 (file)
@@ -100,7 +100,7 @@ I believe platform_data is available for this, but if rather not, moving
 the isa_driver pointer to the private struct isa_dev is ofcourse fine as
 well.
 
-Then, if the the driver did not provide a .match, it matches. If it did,
+Then, if the driver did not provide a .match, it matches. If it did,
 the driver match() method is called to determine a match.
 
 If it did **not** match, dev->platform_data is reset to indicate this to
index 732b37d..99cfbb7 100644 (file)
@@ -86,17 +86,24 @@ Module Options
 Special configuration for udlfb is usually unnecessary. There are a few
 options, however.
 
-From the command line, pass options to modprobe
-modprobe udlfb fb_defio=0 console=1 shadow=1
+From the command line, pass options to modprobe::
 
-Or modify options on the fly at /sys/module/udlfb/parameters directory via
-sudo nano fb_defio
-change the parameter in place, and save the file.
+  modprobe udlfb fb_defio=0 console=1 shadow=1
 
-Unplug/replug USB device to apply with new settings
+Or change options on the fly by editing
+/sys/module/udlfb/parameters/PARAMETER_NAME ::
 
-Or for permanent option, create file like /etc/modprobe.d/udlfb.conf with text
-options udlfb fb_defio=0 console=1 shadow=1
+  cd /sys/module/udlfb/parameters
+  ls # to see a list of parameter names
+  sudo nano PARAMETER_NAME
+  # change the parameter in place, and save the file.
+
+Unplug/replug USB device to apply with new settings.
+
+Or to apply options permanently, create a modprobe configuration file
+like /etc/modprobe.d/udlfb.conf with text::
+
+  options udlfb fb_defio=0 console=1 shadow=1
 
 Accepted boolean options:
 
index d7507be..3a199fc 100644 (file)
@@ -122,7 +122,7 @@ volumes, calling::
 to tell fscache that a volume has been withdrawn.  This waits for all
 outstanding accesses on the volume to complete before returning.
 
-When the the cache is completely withdrawn, fscache should be notified by
+When the cache is completely withdrawn, fscache should be notified by
 calling::
 
        void fscache_relinquish_cache(struct fscache_cache *cache);
index 2688885..0152888 100644 (file)
@@ -456,15 +456,15 @@ The ext4 superblock is laid out as follows in
    * - 0x277
      - __u8
      - s_lastcheck_hi
-     - Upper 8 bits of the s_lastcheck_hi field.
+     - Upper 8 bits of the s_lastcheck field.
    * - 0x278
      - __u8
      - s_first_error_time_hi
-     - Upper 8 bits of the s_first_error_time_hi field.
+     - Upper 8 bits of the s_first_error_time field.
    * - 0x279
      - __u8
      - s_last_error_time_hi
-     - Upper 8 bits of the s_last_error_time_hi field.
+     - Upper 8 bits of the s_last_error_time field.
    * - 0x27A
      - __u8
      - s_pad[2]
index d0c0966..17df9a0 100644 (file)
@@ -286,9 +286,8 @@ compress_algorithm=%s:%d Control compress algorithm and its compress level, now,
                         algorithm      level range
                         lz4            3 - 16
                         zstd           1 - 22
-compress_log_size=%u    Support configuring compress cluster size, the size will
-                        be 4KB * (1 << %u), 16KB is minimum size, also it's
-                        default size.
+compress_log_size=%u    Support configuring compress cluster size. The size will
+                        be 4KB * (1 << %u). The default and minimum sizes are 16KB.
 compress_extension=%s   Support adding specified extension, so that f2fs can enable
                         compression on those corresponding files, e.g. if all files
                         with '.ext' has high compression rate, we can set the '.ext'
index c1db874..b9b3106 100644 (file)
@@ -661,7 +661,7 @@ idmappings::
  mount idmapping:      u0:k10000:r10000
 
 Assume a file owned by ``u1000`` is read from disk. The filesystem maps this id
-to ``k21000`` according to it's idmapping. This is what is stored in the
+to ``k21000`` according to its idmapping. This is what is stored in the
 inode's ``i_uid`` and ``i_gid`` fields.
 
 When the caller queries the ownership of this file via ``stat()`` the kernel
index fd13433..523b798 100644 (file)
@@ -176,7 +176,7 @@ Then userspace.
 The requirement for a static, fixed preallocated system area comes from how
 qnx6fs deals with writes.
 
-Each superblock got it's own half of the system area. So superblock #1
+Each superblock got its own half of the system area. So superblock #1
 always uses blocks from the lower half while superblock #2 just writes to
 blocks represented by the upper half bitmap system area bits.
 
index 8a42859..ca0441c 100644 (file)
@@ -227,7 +227,7 @@ Files
               from the data buffer, updating the value of the specified signal
               notification register.  The signal  notification  register  will
               either be replaced with the input data or will be updated to the
-              bitwise OR or the old value and the input data, depending on the
+              bitwise OR of the old value and the input data, depending on the
               contents  of  the  signal1_type,  or  signal2_type respectively,
               file.
 
index 4ef419f..6402ab8 100644 (file)
@@ -100,7 +100,7 @@ transactions together::
 
        ntp = xfs_trans_dup(tp);
        xfs_trans_commit(tp);
-       xfs_log_reserve(ntp);
+       xfs_trans_reserve(ntp);
 
 This results in a series of "rolling transactions" where the inode is locked
 across the entire chain of transactions.  Hence while this series of rolling
@@ -191,7 +191,7 @@ transaction rolling mechanism to re-reserve space on every transaction roll. We
 know from the implementation of the permanent transactions how many transaction
 rolls are likely for the common modifications that need to be made.
 
-For example, and inode allocation is typically two transactions - one to
+For example, an inode allocation is typically two transactions - one to
 physically allocate a free inode chunk on disk, and another to allocate an inode
 from an inode chunk that has free inodes in it.  Hence for an inode allocation
 transaction, we might set the reservation log count to a value of 2 to indicate
@@ -200,7 +200,7 @@ chain. Each time a permanent transaction rolls, it consumes an entire unit
 reservation.
 
 Hence when the permanent transaction is first allocated, the log space
-reservation is increases from a single unit reservation to multiple unit
+reservation is increased from a single unit reservation to multiple unit
 reservations. That multiple is defined by the reservation log count, and this
 means we can roll the transaction multiple times before we have to re-reserve
 log space when we roll the transaction. This ensures that the common
@@ -259,7 +259,7 @@ the next transaction in the sequeunce, but we have none remaining. We cannot
 sleep during the transaction commit process waiting for new log space to become
 available, as we may end up on the end of the FIFO queue and the items we have
 locked while we sleep could end up pinning the tail of the log before there is
-enough free space in the log to fulfil all of the pending reservations and
+enough free space in the log to fulfill all of the pending reservations and
 then wake up transaction commit in progress.
 
 To take a new reservation without sleeping requires us to be able to take a
@@ -551,14 +551,14 @@ Essentially, this shows that an item that is in the AIL can still be modified
 and relogged, so any tracking must be separate to the AIL infrastructure. As
 such, we cannot reuse the AIL list pointers for tracking committed items, nor
 can we store state in any field that is protected by the AIL lock. Hence the
-committed item tracking needs it's own locks, lists and state fields in the log
+committed item tracking needs its own locks, lists and state fields in the log
 item.
 
 Similar to the AIL, tracking of committed items is done through a new list
 called the Committed Item List (CIL).  The list tracks log items that have been
 committed and have formatted memory buffers attached to them. It tracks objects
 in transaction commit order, so when an object is relogged it is removed from
-it's place in the list and re-inserted at the tail. This is entirely arbitrary
+its place in the list and re-inserted at the tail. This is entirely arbitrary
 and done to make it easy for debugging - the last items in the list are the
 ones that are most recently modified. Ordering of the CIL is not necessary for
 transactional integrity (as discussed in the next section) so the ordering is
@@ -615,7 +615,7 @@ those changes into the current checkpoint context. We then initialise a new
 context and attach that to the CIL for aggregation of new transactions.
 
 This allows us to unlock the CIL immediately after transfer of all the
-committed items and effectively allow new transactions to be issued while we
+committed items and effectively allows new transactions to be issued while we
 are formatting the checkpoint into the log. It also allows concurrent
 checkpoints to be written into the log buffers in the case of log force heavy
 workloads, just like the existing transaction commit code does. This, however,
@@ -884,9 +884,9 @@ pin the object the first time it is inserted into the CIL - if it is already in
 the CIL during a transaction commit, then we do not pin it again. Because there
 can be multiple outstanding checkpoint contexts, we can still see elevated pin
 counts, but as each checkpoint completes the pin count will retain the correct
-value according to it's context.
+value according to its context.
 
-Just to make matters more slightly more complex, this checkpoint level context
+Just to make matters slightly more complex, this checkpoint level context
 for the pin count means that the pinning of an item must take place under the
 CIL commit/flush lock. If we pin the object outside this lock, we cannot
 guarantee which context the pin count is associated with. This is because of
index dbb0302..b9dc0c6 100644 (file)
@@ -21,7 +21,7 @@ possible we decided to do following:
   - Devices behind real busses where there is a connector resource
     are represented as struct spi_device or struct i2c_device. Note
     that standard UARTs are not busses so there is no struct uart_device,
-    although some of them may be represented by sturct serdev_device.
+    although some of them may be represented by struct serdev_device.
 
 As both ACPI and Device Tree represent a tree of devices (and their
 resources) this implementation follows the Device Tree way as much as
@@ -205,7 +205,7 @@ Here is what the ACPI namespace for a SPI slave might look like::
                }
                ...
 
-The SPI device drivers only need to add ACPI IDs in a similar way than with
+The SPI device drivers only need to add ACPI IDs in a similar way to
 the platform device drivers. Below is an example where we add ACPI support
 to at25 SPI eeprom driver (this is meant for the above ACPI snippet)::
 
@@ -362,7 +362,7 @@ These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
 specifies the path to the controller. In order to use these GPIOs in Linux
 we need to translate them to the corresponding Linux GPIO descriptors.
 
-There is a standard GPIO API for that and is documented in
+There is a standard GPIO API for that and it is documented in
 Documentation/admin-guide/gpio/.
 
 In the above example we can get the corresponding two GPIO descriptors with
@@ -538,8 +538,8 @@ information.
 PCI hierarchy representation
 ============================
 
-Sometimes could be useful to enumerate a PCI device, knowing its position on the
-PCI bus.
+Sometimes it could be useful to enumerate a PCI device, knowing its position on
+the PCI bus.
 
 For example, some systems use PCI devices soldered directly on the mother board,
 in a fixed position (ethernet, Wi-Fi, serial ports, etc.). In this conditions it
@@ -550,7 +550,7 @@ To identify a PCI device, a complete hierarchical description is required, from
 the chipset root port to the final device, through all the intermediate
 bridges/switches of the board.
 
-For example, let us assume to have a system with a PCIe serial port, an
+For example, let's assume we have a system with a PCIe serial port, an
 Exar XR17V3521, soldered on the main board. This UART chip also includes
 16 GPIOs and we want to add the property ``gpio-line-names`` [1] to these pins.
 In this case, the ``lspci`` output for this component is::
@@ -593,8 +593,8 @@ of the chipset bridge (also called "root port") with address::
 
        Bus: 0 - Device: 14 - Function: 1
 
-To find this information is necessary disassemble the BIOS ACPI tables, in
-particular the DSDT (see also [2])::
+To find this information, it is necessary to disassemble the BIOS ACPI tables,
+in particular the DSDT (see also [2])::
 
        mkdir ~/tables/
        cd ~/tables/
index 05869c0..784850a 100644 (file)
@@ -41,26 +41,23 @@ But it is likely that they will all eventually be added.
 What should an OEM do if they want to support Linux and Windows
 using the same BIOS image?  Often they need to do something different
 for Linux to deal with how Linux is different from Windows.
-Here the BIOS should ask exactly what it wants to know:
 
+In this case, the OEM should create custom ASL to be executed by the
+Linux kernel and changes to Linux kernel drivers to execute this custom
+ASL.  The easiest way to accomplish this is to introduce a device specific
+method (_DSM) that is called from the Linux kernel.
+
+In the past the kernel used to support something like:
 _OSI("Linux-OEM-my_interface_name")
 where 'OEM' is needed if this is an OEM-specific hook,
 and 'my_interface_name' describes the hook, which could be a
 quirk, a bug, or a bug-fix.
 
-In addition, the OEM should send a patch to upstream Linux
-via the linux-acpi@vger.kernel.org mailing list.  When that patch
-is checked into Linux, the OS will answer "YES" when the BIOS
-on the OEM's system uses _OSI to ask if the interface is supported
-by the OS.  Linux distributors can back-port that patch for Linux
-pre-installs, and it will be included by all distributions that
-re-base to upstream.  If the distribution can not update the kernel binary,
-they can also add an acpi_osi=Linux-OEM-my_interface_name
-cmdline parameter to the boot loader, as needed.
-
-If the string refers to a feature where the upstream kernel
-eventually grows support, a patch should be sent to remove
-the string when that support is added to the kernel.
+However this was discovered to be abused by other BIOS vendors to change
+completely unrelated code on completely unrelated systems.  This prompted
+an evaluation of all of it's uses. This uncovered that they aren't needed
+for any of the original reasons. As such, the kernel will not respond to
+any custom Linux-* strings by default.
 
 That was easy.  Read on, to find out how to do it wrong.
 
index cc90002..07fe6f6 100644 (file)
@@ -64,7 +64,7 @@ correct address for this module, you could get in big trouble (read:
 crashes, data corruption, etc.). Try this only as a last resort (try BIOS
 updates first, for example), and backup first! An even more dangerous
 option is 'force_addr=<IOPORT>'. This will not only enable the PIIX4 like
-'force' foes, but it will also set a new base I/O port address. The SMBus
+'force' does, but it will also set a new base I/O port address. The SMBus
 parts of the PIIX4 needs a range of 8 of these addresses to function
 correctly. If these addresses are already reserved by some other device,
 you will get into big trouble! DON'T USE THIS IF YOU ARE NOT VERY SURE
@@ -86,15 +86,15 @@ If you own Force CPCI735 motherboard or other OSB4 based systems you may need
 to change the SMBus Interrupt Select register so the SMBus controller uses
 the SMI mode.
 
-1) Use lspci command and locate the PCI device with the SMBus controller:
+1) Use ``lspci`` command and locate the PCI device with the SMBus controller:
    00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 4f)
    The line may vary for different chipsets. Please consult the driver source
-   for all possible PCI ids (and lspci -n to match them). Lets assume the
+   for all possible PCI ids (and ``lspci -n`` to match them). Let's assume the
    device is located at 00:0f.0.
 2) Now you just need to change the value in 0xD2 register. Get it first with
-   command: lspci -xxx -s 00:0f.0
+   command: ``lspci -xxx -s 00:0f.0``
    If the value is 0x3 then you need to change it to 0x1:
-   setpci  -s 00:0f.0 d2.b=1
+   ``setpci  -s 00:0f.0 d2.b=1``
 
 Please note that you don't need to do that in all cases, just when the SMBus is
 not working properly.
@@ -109,6 +109,3 @@ which can easily get corrupted due to a state machine bug. These are mostly
 Thinkpad laptops, but desktop systems may also be affected. We have no list
 of all affected systems, so the only safe solution was to prevent access to
 the SMBus on all IBM systems (detected using DMI data.)
-
-For additional information, read:
-http://www.lm-sensors.org/browser/lm-sensors/trunk/README
index 73ad348..c277a8e 100644 (file)
@@ -148,7 +148,7 @@ You can do plain I2C transactions by using read(2) and write(2) calls.
 You do not need to pass the address byte; instead, set it through
 ioctl I2C_SLAVE before you try to access the device.
 
-You can do SMBus level transactions (see documentation file smbus-protocol
+You can do SMBus level transactions (see documentation file smbus-protocol.rst
 for details) through the following functions::
 
   __s32 i2c_smbus_write_quick(int file, __u8 value);
index 7cb5381..48fce0f 100644 (file)
@@ -5,6 +5,8 @@ I2C muxes and complex topologies
 There are a couple of reasons for building more complex I2C topologies
 than a straight-forward I2C bus with one adapter and one or more devices.
 
+Some example use cases are:
+
 1. A mux may be needed on the bus to prevent address collisions.
 
 2. The bus may be accessible from some external bus master, and arbitration
@@ -14,10 +16,10 @@ than a straight-forward I2C bus with one adapter and one or more devices.
    from the I2C bus, at least most of the time, and sits behind a gate
    that has to be operated before the device can be accessed.
 
-Etc
-===
+Several types of hardware components such as I2C muxes, I2C gates and I2C
+arbitrators allow to handle such needs.
 
-These constructs are represented as I2C adapter trees by Linux, where
+These components are represented as I2C adapter trees by Linux, where
 each adapter has a parent adapter (except the root adapter) and zero or
 more child adapters. The root adapter is the actual adapter that issues
 I2C transfers, and all adapters with a parent are part of an "i2c-mux"
@@ -35,46 +37,7 @@ Locking
 =======
 
 There are two variants of locking available to I2C muxes, they can be
-mux-locked or parent-locked muxes. As is evident from below, it can be
-useful to know if a mux is mux-locked or if it is parent-locked. The
-following list was correct at the time of writing:
-
-In drivers/i2c/muxes/:
-
-======================    =============================================
-i2c-arb-gpio-challenge    Parent-locked
-i2c-mux-gpio              Normally parent-locked, mux-locked iff
-                          all involved gpio pins are controlled by the
-                          same I2C root adapter that they mux.
-i2c-mux-gpmux             Normally parent-locked, mux-locked iff
-                          specified in device-tree.
-i2c-mux-ltc4306           Mux-locked
-i2c-mux-mlxcpld           Parent-locked
-i2c-mux-pca9541           Parent-locked
-i2c-mux-pca954x           Parent-locked
-i2c-mux-pinctrl           Normally parent-locked, mux-locked iff
-                          all involved pinctrl devices are controlled
-                          by the same I2C root adapter that they mux.
-i2c-mux-reg               Parent-locked
-======================    =============================================
-
-In drivers/iio/:
-
-======================    =============================================
-gyro/mpu3050              Mux-locked
-imu/inv_mpu6050/          Mux-locked
-======================    =============================================
-
-In drivers/media/:
-
-=======================   =============================================
-dvb-frontends/lgdt3306a   Mux-locked
-dvb-frontends/m88ds3103   Parent-locked
-dvb-frontends/rtl2830     Parent-locked
-dvb-frontends/rtl2832     Mux-locked
-dvb-frontends/si2168      Mux-locked
-usb/cx231xx/              Parent-locked
-=======================   =============================================
+mux-locked or parent-locked muxes.
 
 
 Mux-locked muxes
@@ -89,40 +52,8 @@ full transaction, unrelated I2C transfers may interleave the different
 stages of the transaction. This has the benefit that the mux driver
 may be easier and cleaner to implement, but it has some caveats.
 
-==== =====================================================================
-ML1. If you build a topology with a mux-locked mux being the parent
-     of a parent-locked mux, this might break the expectation from the
-     parent-locked mux that the root adapter is locked during the
-     transaction.
-
-ML2. It is not safe to build arbitrary topologies with two (or more)
-     mux-locked muxes that are not siblings, when there are address
-     collisions between the devices on the child adapters of these
-     non-sibling muxes.
-
-     I.e. the select-transfer-deselect transaction targeting e.g. device
-     address 0x42 behind mux-one may be interleaved with a similar
-     operation targeting device address 0x42 behind mux-two. The
-     intension with such a topology would in this hypothetical example
-     be that mux-one and mux-two should not be selected simultaneously,
-     but mux-locked muxes do not guarantee that in all topologies.
-
-ML3. A mux-locked mux cannot be used by a driver for auto-closing
-     gates/muxes, i.e. something that closes automatically after a given
-     number (one, in most cases) of I2C transfers. Unrelated I2C transfers
-     may creep in and close prematurely.
-
-ML4. If any non-I2C operation in the mux driver changes the I2C mux state,
-     the driver has to lock the root adapter during that operation.
-     Otherwise garbage may appear on the bus as seen from devices
-     behind the mux, when an unrelated I2C transfer is in flight during
-     the non-I2C mux-changing operation.
-==== =====================================================================
-
-
 Mux-locked Example
-------------------
-
+~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -153,6 +84,43 @@ This means that accesses to D2 are lockout out for the full duration
 of the entire operation. But accesses to D3 are possibly interleaved
 at any point.
 
+Mux-locked caveats
+~~~~~~~~~~~~~~~~~~
+
+When using a mux-locked mux, be aware of the following restrictions:
+
+[ML1]
+  If you build a topology with a mux-locked mux being the parent
+  of a parent-locked mux, this might break the expectation from the
+  parent-locked mux that the root adapter is locked during the
+  transaction.
+
+[ML2]
+  It is not safe to build arbitrary topologies with two (or more)
+  mux-locked muxes that are not siblings, when there are address
+  collisions between the devices on the child adapters of these
+  non-sibling muxes.
+
+  I.e. the select-transfer-deselect transaction targeting e.g. device
+  address 0x42 behind mux-one may be interleaved with a similar
+  operation targeting device address 0x42 behind mux-two. The
+  intent with such a topology would in this hypothetical example
+  be that mux-one and mux-two should not be selected simultaneously,
+  but mux-locked muxes do not guarantee that in all topologies.
+
+[ML3]
+  A mux-locked mux cannot be used by a driver for auto-closing
+  gates/muxes, i.e. something that closes automatically after a given
+  number (one, in most cases) of I2C transfers. Unrelated I2C transfers
+  may creep in and close prematurely.
+
+[ML4]
+  If any non-I2C operation in the mux driver changes the I2C mux state,
+  the driver has to lock the root adapter during that operation.
+  Otherwise garbage may appear on the bus as seen from devices
+  behind the mux, when an unrelated I2C transfer is in flight during
+  the non-I2C mux-changing operation.
+
 
 Parent-locked muxes
 -------------------
@@ -161,28 +129,10 @@ Parent-locked muxes lock the parent adapter during the full select-
 transfer-deselect transaction. The implication is that the mux driver
 has to ensure that any and all I2C transfers through that parent
 adapter during the transaction are unlocked I2C transfers (using e.g.
-__i2c_transfer), or a deadlock will follow. There are a couple of
-caveats.
-
-==== ====================================================================
-PL1. If you build a topology with a parent-locked mux being the child
-     of another mux, this might break a possible assumption from the
-     child mux that the root adapter is unused between its select op
-     and the actual transfer (e.g. if the child mux is auto-closing
-     and the parent mux issues I2C transfers as part of its select).
-     This is especially the case if the parent mux is mux-locked, but
-     it may also happen if the parent mux is parent-locked.
-
-PL2. If select/deselect calls out to other subsystems such as gpio,
-     pinctrl, regmap or iio, it is essential that any I2C transfers
-     caused by these subsystems are unlocked. This can be convoluted to
-     accomplish, maybe even impossible if an acceptably clean solution
-     is sought.
-==== ====================================================================
-
+__i2c_transfer), or a deadlock will follow.
 
 Parent-locked Example
----------------------
+~~~~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -212,10 +162,30 @@ When there is an access to D1, this happens:
  9.  M1 unlocks its parent adapter.
  10. M1 unlocks muxes on its parent.
 
-
 This means that accesses to both D2 and D3 are locked out for the full
 duration of the entire operation.
 
+Parent-locked Caveats
+~~~~~~~~~~~~~~~~~~~~~
+
+When using a parent-locked mux, be aware of the following restrictions:
+
+[PL1]
+  If you build a topology with a parent-locked mux being the child
+  of another mux, this might break a possible assumption from the
+  child mux that the root adapter is unused between its select op
+  and the actual transfer (e.g. if the child mux is auto-closing
+  and the parent mux issues I2C transfers as part of its select).
+  This is especially the case if the parent mux is mux-locked, but
+  it may also happen if the parent mux is parent-locked.
+
+[PL2]
+  If select/deselect calls out to other subsystems such as gpio,
+  pinctrl, regmap or iio, it is essential that any I2C transfers
+  caused by these subsystems are unlocked. This can be convoluted to
+  accomplish, maybe even impossible if an acceptably clean solution
+  is sought.
+
 
 Complex Examples
 ================
@@ -261,8 +231,10 @@ This is a good topology::
 When device D1 is accessed, accesses to D2 are locked out for the
 full duration of the operation (muxes on the top child adapter of M1
 are locked). But accesses to D3 and D4 are possibly interleaved at
-any point. Accesses to D3 locks out D1 and D2, but accesses to D4
-are still possibly interleaved.
+any point.
+
+Accesses to D3 locks out D1 and D2, but accesses to D4 are still possibly
+interleaved.
 
 
 Mux-locked mux as parent of parent-locked mux
@@ -394,3 +366,47 @@ This is a good topology::
 When D1 or D2 are accessed, accesses to D3 and D4 are locked out while
 accesses to D5 may interleave. When D3 or D4 are accessed, accesses to
 all other devices are locked out.
+
+
+Mux type of existing device drivers
+===================================
+
+Whether a device is mux-locked or parent-locked depends on its
+implementation. The following list was correct at the time of writing:
+
+In drivers/i2c/muxes/:
+
+======================    =============================================
+i2c-arb-gpio-challenge    Parent-locked
+i2c-mux-gpio              Normally parent-locked, mux-locked iff
+                          all involved gpio pins are controlled by the
+                          same I2C root adapter that they mux.
+i2c-mux-gpmux             Normally parent-locked, mux-locked iff
+                          specified in device-tree.
+i2c-mux-ltc4306           Mux-locked
+i2c-mux-mlxcpld           Parent-locked
+i2c-mux-pca9541           Parent-locked
+i2c-mux-pca954x           Parent-locked
+i2c-mux-pinctrl           Normally parent-locked, mux-locked iff
+                          all involved pinctrl devices are controlled
+                          by the same I2C root adapter that they mux.
+i2c-mux-reg               Parent-locked
+======================    =============================================
+
+In drivers/iio/:
+
+======================    =============================================
+gyro/mpu3050              Mux-locked
+imu/inv_mpu6050/          Mux-locked
+======================    =============================================
+
+In drivers/media/:
+
+=======================   =============================================
+dvb-frontends/lgdt3306a   Mux-locked
+dvb-frontends/m88ds3103   Parent-locked
+dvb-frontends/rtl2830     Parent-locked
+dvb-frontends/rtl2832     Mux-locked
+dvb-frontends/si2168      Mux-locked
+usb/cx231xx/              Parent-locked
+=======================   =============================================
index 82ea3e1..58fb143 100644 (file)
@@ -32,9 +32,9 @@ User manual
 ===========
 
 I2C slave backends behave like standard I2C clients. So, you can instantiate
-them as described in the document 'instantiating-devices'. The only difference
-is that i2c slave backends have their own address space. So, you have to add
-0x1000 to the address you would originally request. An example for
+them as described in the document instantiating-devices.rst. The only
+difference is that i2c slave backends have their own address space. So, you
+have to add 0x1000 to the address you would originally request. An example for
 instantiating the slave-eeprom driver from userspace at the 7 bit address 0x64
 on bus 1::
 
index e3b126c..47f7cbf 100644 (file)
@@ -364,7 +364,7 @@ stop condition is issued between transaction. The i2c_msg structure
 contains for each message the client address, the number of bytes of the
 message and the message data itself.
 
-You can read the file ``i2c-protocol`` for more information about the
+You can read the file i2c-protocol.rst for more information about the
 actual I2C protocol.
 
 
@@ -414,7 +414,7 @@ transactions return 0 on success; the 'read' transactions return the read
 value, except for block transactions, which return the number of values
 read. The block buffers need not be longer than 32 bytes.
 
-You can read the file ``smbus-protocol`` for more information about the
+You can read the file smbus-protocol.rst for more information about the
 actual SMBus protocol.
 
 
index 4737c18..85eab6e 100644 (file)
@@ -1,11 +1,5 @@
 .. SPDX-License-Identifier: GPL-2.0
 
-
-.. The Linux Kernel documentation master file, created by
-   sphinx-quickstart on Fri Feb 12 13:51:46 2016.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
-
 .. _linux_doc:
 
 The Linux Kernel documentation
@@ -18,133 +12,84 @@ documents into a coherent whole.  Please note that improvements to the
 documentation are welcome; join the linux-doc list at vger.kernel.org if
 you want to help out.
 
-Licensing documentation
------------------------
+Working with the development community
+--------------------------------------
 
-The following describes the license of the Linux kernel source code
-(GPLv2), how to properly mark the license of individual files in the source
-tree, as well as links to the full license text.
-
-* :ref:`kernel_licensing`
-
-User-oriented documentation
----------------------------
-
-The following manuals are written for *users* of the kernel — those who are
-trying to get it to work optimally on a given system.
+The essential guides for interacting with the kernel's development
+community and getting your work upstream.
 
 .. toctree::
-   :maxdepth: 2
-
-   admin-guide/index
-   kbuild/index
-
-Firmware-related documentation
-------------------------------
-The following holds information on the kernel's expectations regarding the
-platform firmwares.
+   :maxdepth: 1
 
-.. toctree::
-   :maxdepth: 2
+   process/development-process
+   process/submitting-patches
+   Code of conduct <process/code-of-conduct>
+   maintainer/index
+   All development-process docs <process/index>
 
-   firmware-guide/index
-   devicetree/index
 
-Application-developer documentation
------------------------------------
+Internal API manuals
+--------------------
 
-The user-space API manual gathers together documents describing aspects of
-the kernel interface as seen by application developers.
+Manuals for use by developers working to interface with the rest of the
+kernel.
 
 .. toctree::
-   :maxdepth: 2
-
-   userspace-api/index
+   :maxdepth: 1
 
+   core-api/index
+   driver-api/index
+   subsystem-apis
+   Locking in the kernel <locking/index>
 
-Introduction to kernel development
-----------------------------------
+Development tools and processes
+-------------------------------
 
-These manuals contain overall information about how to develop the kernel.
-The kernel community is quite large, with thousands of developers
-contributing over the course of a year.  As with any large community,
-knowing how things are done will make the process of getting your changes
-merged much easier.
+Various other manuals with useful information for all kernel developers.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   process/index
-   dev-tools/index
+   process/license-rules
    doc-guide/index
+   dev-tools/index
+   dev-tools/testing-overview
    kernel-hacking/index
    trace/index
-   maintainer/index
    fault-injection/index
    livepatch/index
 
 
-Kernel API documentation
-------------------------
+User-oriented documentation
+---------------------------
 
-These books get into the details of how specific kernel subsystems work
-from the point of view of a kernel developer.  Much of the information here
-is taken directly from the kernel source, with supplemental material added
-as needed (or at least as we managed to add it — probably *not* all that is
-needed).
+The following manuals are written for *users* of the kernel — those who are
+trying to get it to work optimally on a given system and application
+developers seeking information on the kernel's user-space APIs.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   driver-api/index
-   core-api/index
-   locking/index
-   accounting/index
-   block/index
-   cdrom/index
-   cpu-freq/index
-   fb/index
-   fpga/index
-   hid/index
-   i2c/index
-   iio/index
-   isdn/index
-   infiniband/index
-   leds/index
-   netlabel/index
-   networking/index
-   pcmcia/index
-   power/index
-   target/index
-   timers/index
-   spi/index
-   w1/index
-   watchdog/index
-   virt/index
-   input/index
-   hwmon/index
-   gpu/index
-   security/index
-   sound/index
-   crypto/index
-   filesystems/index
-   mm/index
-   bpf/index
-   usb/index
-   PCI/index
-   scsi/index
-   misc-devices/index
-   scheduler/index
-   mhi/index
-   peci/index
-
-Architecture-agnostic documentation
------------------------------------
+   admin-guide/index
+   The kernel build system <kbuild/index>
+   admin-guide/reporting-issues.rst
+   User-space tools <tools/index>
+   userspace-api/index
+
+See also: the `Linux man pages <https://www.kernel.org/doc/man-pages/>`_,
+which are kept separately from the kernel's own documentation.
+
+Firmware-related documentation
+------------------------------
+The following holds information on the kernel's expectations regarding the
+platform firmwares.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
+
+   firmware-guide/index
+   devicetree/index
 
-   asm-annotations
 
 Architecture-specific documentation
 -----------------------------------
@@ -163,9 +108,8 @@ of the documentation body, or may require some adjustments and/or conversion
 to ReStructured Text format, or are simply too old.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
-   tools/index
    staging/index
 
 
index f615906..6d72139 100644 (file)
@@ -517,6 +517,7 @@ All I-Force devices are supported by the iforce module. This includes:
 * AVB Mag Turbo Force
 * AVB Top Shot Pegasus
 * AVB Top Shot Force Feedback Racing Wheel
+* Boeder Force Feedback Wheel
 * Logitech WingMan Force
 * Logitech WingMan Force Wheel
 * Guillemot Race Leader Force Feedback
index 0ba7671..c578c6b 100644 (file)
@@ -90,7 +90,11 @@ e.g., on Ubuntu for gcc-10::
 
 Or on Fedora::
 
-       dnf install gcc-plugin-devel
+       dnf install gcc-plugin-devel libmpc-devel
+
+Or on Fedora when using cross-compilers that include plugins::
+
+       dnf install libmpc-devel
 
 Enable the GCC plugin infrastructure and some plugin(s) you want to use
 in the kernel config::
@@ -99,6 +103,19 @@ in the kernel config::
        CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y
        ...
 
+Run gcc (native or cross-compiler) to ensure plugin headers are detected::
+
+       gcc -print-file-name=plugin
+       CROSS_COMPILE=arm-linux-gnu- ${CROSS_COMPILE}gcc -print-file-name=plugin
+
+The word "plugin" means they are not detected::
+
+       plugin
+
+A full path means they are detected::
+
+       /usr/lib/gcc/x86_64-redhat-linux/12/plugin
+
 To compile the minimum tool set including the plugin(s)::
 
        make scripts
index 64405e5..bfda1a5 100644 (file)
@@ -39,7 +39,7 @@ as the writer can invalidate a pointer that the reader is following.
 Sequence counters (``seqcount_t``)
 ==================================
 
-This is the the raw counting mechanism, which does not protect against
+This is the raw counting mechanism, which does not protect against
 multiple writers.  Write side critical sections must thus be serialized
 by an external lock.
 
index 832b5d3..06f80e3 100644 (file)
@@ -52,7 +52,7 @@ CONTENTS
 
      - Varieties of memory barrier.
      - What may not be assumed about memory barriers?
-     - Data dependency barriers (historical).
+     - Address-dependency barriers (historical).
      - Control dependencies.
      - SMP barrier pairing.
      - Examples of memory barrier sequences.
@@ -187,9 +187,9 @@ As a further example, consider this sequence of events:
        B = 4;          Q = P;
        P = &B;         D = *Q;
 
-There is an obvious data dependency here, as the value loaded into D depends on
-the address retrieved from P by CPU 2.  At the end of the sequence, any of the
-following results are possible:
+There is an obvious address dependency here, as the value loaded into D depends
+on the address retrieved from P by CPU 2.  At the end of the sequence, any of
+the following results are possible:
 
        (Q == &A) and (D == 1)
        (Q == &B) and (D == 2)
@@ -391,58 +391,62 @@ Memory barriers come in four basic varieties:
      memory system as time progresses.  All stores _before_ a write barrier
      will occur _before_ all the stores after the write barrier.
 
-     [!] Note that write barriers should normally be paired with read or data
-     dependency barriers; see the "SMP barrier pairing" subsection.
+     [!] Note that write barriers should normally be paired with read or
+     address-dependency barriers; see the "SMP barrier pairing" subsection.
 
 
- (2) Data dependency barriers.
+ (2) Address-dependency barriers (historical).
 
-     A data dependency barrier is a weaker form of read barrier.  In the case
-     where two loads are performed such that the second depends on the result
-     of the first (eg: the first load retrieves the address to which the second
-     load will be directed), a data dependency barrier would be required to
-     make sure that the target of the second load is updated after the address
-     obtained by the first load is accessed.
+     An address-dependency barrier is a weaker form of read barrier.  In the
+     case where two loads are performed such that the second depends on the
+     result of the first (eg: the first load retrieves the address to which
+     the second load will be directed), an address-dependency barrier would
+     be required to make sure that the target of the second load is updated
+     after the address obtained by the first load is accessed.
 
-     A data dependency barrier is a partial ordering on interdependent loads
-     only; it is not required to have any effect on stores, independent loads
-     or overlapping loads.
+     An address-dependency barrier is a partial ordering on interdependent
+     loads only; it is not required to have any effect on stores, independent
+     loads or overlapping loads.
 
      As mentioned in (1), the other CPUs in the system can be viewed as
      committing sequences of stores to the memory system that the CPU being
-     considered can then perceive.  A data dependency barrier issued by the CPU
-     under consideration guarantees that for any load preceding it, if that
-     load touches one of a sequence of stores from another CPU, then by the
-     time the barrier completes, the effects of all the stores prior to that
-     touched by the load will be perceptible to any loads issued after the data
-     dependency barrier.
+     considered can then perceive.  An address-dependency barrier issued by
+     the CPU under consideration guarantees that for any load preceding it,
+     if that load touches one of a sequence of stores from another CPU, then
+     by the time the barrier completes, the effects of all the stores prior to
+     that touched by the load will be perceptible to any loads issued after
+     the address-dependency barrier.
 
      See the "Examples of memory barrier sequences" subsection for diagrams
      showing the ordering constraints.
 
-     [!] Note that the first load really has to have a _data_ dependency and
+     [!] Note that the first load really has to have an _address_ dependency and
      not a control dependency.  If the address for the second load is dependent
      on the first load, but the dependency is through a conditional rather than
      actually loading the address itself, then it's a _control_ dependency and
      a full read barrier or better is required.  See the "Control dependencies"
      subsection for more information.
 
-     [!] Note that data dependency barriers should normally be paired with
+     [!] Note that address-dependency barriers should normally be paired with
      write barriers; see the "SMP barrier pairing" subsection.
 
+     [!] Kernel release v5.9 removed kernel APIs for explicit address-
+     dependency barriers.  Nowadays, APIs for marking loads from shared
+     variables such as READ_ONCE() and rcu_dereference() provide implicit
+     address-dependency barriers.
 
  (3) Read (or load) memory barriers.
 
-     A read barrier is a data dependency barrier plus a guarantee that all the
-     LOAD operations specified before the barrier will appear to happen before
-     all the LOAD operations specified after the barrier with respect to the
-     other components of the system.
+     A read barrier is an address-dependency barrier plus a guarantee that all
+     the LOAD operations specified before the barrier will appear to happen
+     before all the LOAD operations specified after the barrier with respect to
+     the other components of the system.
 
      A read barrier is a partial ordering on loads only; it is not required to
      have any effect on stores.
 
-     Read memory barriers imply data dependency barriers, and so can substitute
-     for them.
+     Read memory barriers imply address-dependency barriers, and so can
+     substitute for them.
 
      [!] Note that read barriers should normally be paired with write barriers;
      see the "SMP barrier pairing" subsection.
@@ -550,17 +554,21 @@ There are certain things that the Linux kernel memory barriers do not guarantee:
            Documentation/core-api/dma-api.rst
 
 
-DATA DEPENDENCY BARRIERS (HISTORICAL)
--------------------------------------
+ADDRESS-DEPENDENCY BARRIERS (HISTORICAL)
+----------------------------------------
 
 As of v4.15 of the Linux kernel, an smp_mb() was added to READ_ONCE() for
 DEC Alpha, which means that about the only people who need to pay attention
 to this section are those working on DEC Alpha architecture-specific code
 and those working on READ_ONCE() itself.  For those who need it, and for
 those who are interested in the history, here is the story of
-data-dependency barriers.
+address-dependency barriers.
+
+[!] While address dependencies are observed in both load-to-load and
+load-to-store relations, address-dependency barriers are not necessary
+for load-to-store situations.
 
-The usage requirements of data dependency barriers are a little subtle, and
+The requirement of address-dependency barriers is a little subtle, and
 it's not always obvious that they're needed.  To illustrate, consider the
 following sequence of events:
 
@@ -570,11 +578,14 @@ following sequence of events:
        B = 4;
        <write barrier>
        WRITE_ONCE(P, &B);
-                             Q = READ_ONCE(P);
+                             Q = READ_ONCE_OLD(P);
                              D = *Q;
 
-There's a clear data dependency here, and it would seem that by the end of the
-sequence, Q must be either &A or &B, and that:
+[!] READ_ONCE_OLD() corresponds to READ_ONCE() of pre-4.15 kernel, which
+doesn't imply an address-dependency barrier.
+
+There's a clear address dependency here, and it would seem that by the end of
+the sequence, Q must be either &A or &B, and that:
 
        (Q == &A) implies (D == 1)
        (Q == &B) implies (D == 4)
@@ -588,8 +599,8 @@ While this may seem like a failure of coherency or causality maintenance, it
 isn't, and this behaviour can be observed on certain real CPUs (such as the DEC
 Alpha).
 
-To deal with this, a data dependency barrier or better must be inserted
-between the address load and the data load:
+To deal with this, READ_ONCE() provides an implicit address-dependency barrier
+since kernel release v4.15:
 
        CPU 1                 CPU 2
        ===============       ===============
@@ -598,7 +609,7 @@ between the address load and the data load:
        <write barrier>
        WRITE_ONCE(P, &B);
                              Q = READ_ONCE(P);
-                             <data dependency barrier>
+                             <implicit address-dependency barrier>
                              D = *Q;
 
 This enforces the occurrence of one of the two implications, and prevents the
@@ -615,13 +626,13 @@ odd-numbered bank is idle, one can see the new value of the pointer P (&B),
 but the old value of the variable B (2).
 
 
-A data-dependency barrier is not required to order dependent writes
-because the CPUs that the Linux kernel supports don't do writes
-until they are certain (1) that the write will actually happen, (2)
-of the location of the write, and (3) of the value to be written.
+An address-dependency barrier is not required to order dependent writes
+because the CPUs that the Linux kernel supports don't do writes until they
+are certain (1) that the write will actually happen, (2) of the location of
+the write, and (3) of the value to be written.
 But please carefully read the "CONTROL DEPENDENCIES" section and the
-Documentation/RCU/rcu_dereference.rst file:  The compiler can and does
-break dependencies in a great many highly creative ways.
+Documentation/RCU/rcu_dereference.rst file:  The compiler can and does break
+dependencies in a great many highly creative ways.
 
        CPU 1                 CPU 2
        ===============       ===============
@@ -629,12 +640,12 @@ break dependencies in a great many highly creative ways.
        B = 4;
        <write barrier>
        WRITE_ONCE(P, &B);
-                             Q = READ_ONCE(P);
+                             Q = READ_ONCE_OLD(P);
                              WRITE_ONCE(*Q, 5);
 
-Therefore, no data-dependency barrier is required to order the read into
+Therefore, no address-dependency barrier is required to order the read into
 Q with the store into *Q.  In other words, this outcome is prohibited,
-even without a data-dependency barrier:
+even without an implicit address-dependency barrier of modern READ_ONCE():
 
        (Q == &B) && (B == 4)
 
@@ -645,12 +656,12 @@ can be used to record rare error conditions and the like, and the CPUs'
 naturally occurring ordering prevents such records from being lost.
 
 
-Note well that the ordering provided by a data dependency is local to
+Note well that the ordering provided by an address dependency is local to
 the CPU containing it.  See the section on "Multicopy atomicity" for
 more information.
 
 
-The data dependency barrier is very important to the RCU system,
+The address-dependency barrier is very important to the RCU system,
 for example.  See rcu_assign_pointer() and rcu_dereference() in
 include/linux/rcupdate.h.  This permits the current target of an RCU'd
 pointer to be replaced with a new modified target, without the replacement
@@ -667,20 +678,21 @@ not understand them.  The purpose of this section is to help you prevent
 the compiler's ignorance from breaking your code.
 
 A load-load control dependency requires a full read memory barrier, not
-simply a data dependency barrier to make it work correctly.  Consider the
-following bit of code:
+simply an (implicit) address-dependency barrier to make it work correctly.
+Consider the following bit of code:
 
        q = READ_ONCE(a);
+       <implicit address-dependency barrier>
        if (q) {
-               <data dependency barrier>  /* BUG: No data dependency!!! */
+               /* BUG: No address dependency!!! */
                p = READ_ONCE(b);
        }
 
-This will not have the desired effect because there is no actual data
+This will not have the desired effect because there is no actual address
 dependency, but rather a control dependency that the CPU may short-circuit
 by attempting to predict the outcome in advance, so that other CPUs see
-the load from b as having happened before the load from a.  In such a
-case what's actually required is:
+the load from b as having happened before the load from a.  In such a case
+what's actually required is:
 
        q = READ_ONCE(a);
        if (q) {
@@ -927,9 +939,9 @@ General barriers pair with each other, though they also pair with most
 other types of barriers, albeit without multicopy atomicity.  An acquire
 barrier pairs with a release barrier, but both may also pair with other
 barriers, including of course general barriers.  A write barrier pairs
-with a data dependency barrier, a control dependency, an acquire barrier,
+with an address-dependency barrier, a control dependency, an acquire barrier,
 a release barrier, a read barrier, or a general barrier.  Similarly a
-read barrier, control dependency, or a data dependency barrier pairs
+read barrier, control dependency, or an address-dependency barrier pairs
 with a write barrier, an acquire barrier, a release barrier, or a
 general barrier:
 
@@ -948,7 +960,7 @@ Or:
        a = 1;
        <write barrier>
        WRITE_ONCE(b, &a);    x = READ_ONCE(b);
-                             <data dependency barrier>
+                             <implicit address-dependency barrier>
                              y = *x;
 
 Or even:
@@ -968,8 +980,8 @@ Basically, the read barrier always has to be there, even though it can be of
 the "weaker" type.
 
 [!] Note that the stores before the write barrier would normally be expected to
-match the loads after the read barrier or the data dependency barrier, and vice
-versa:
+match the loads after the read barrier or the address-dependency barrier, and
+vice versa:
 
        CPU 1                               CPU 2
        ===================                 ===================
@@ -1021,8 +1033,8 @@ STORE B, STORE C } all occurring before the unordered set of { STORE D, STORE E
                           V
 
 
-Secondly, data dependency barriers act as partial orderings on data-dependent
-loads.  Consider the following sequence of events:
+Secondly, address-dependency barriers act as partial orderings on address-
+dependent loads.  Consider the following sequence of events:
 
        CPU 1                   CPU 2
        ======================= =======================
@@ -1067,8 +1079,8 @@ effectively random order, despite the write barrier issued by CPU 1:
 In the above example, CPU 2 perceives that B is 7, despite the load of *C
 (which would be B) coming after the LOAD of C.
 
-If, however, a data dependency barrier were to be placed between the load of C
-and the load of *C (ie: B) on CPU 2:
+If, however, an address-dependency barrier were to be placed between the load
+of C and the load of *C (ie: B) on CPU 2:
 
        CPU 1                   CPU 2
        ======================= =======================
@@ -1078,7 +1090,7 @@ and the load of *C (ie: B) on CPU 2:
        <write barrier>
        STORE C = &B            LOAD X
        STORE D = 4             LOAD C (gets &B)
-                               <data dependency barrier>
+                               <address-dependency barrier>
                                LOAD *C (reads B)
 
 then the following will occur:
@@ -1101,7 +1113,7 @@ then the following will occur:
                                       |        +-------+       |       |
                                       |        | X->9  |------>|       |
                                       |        +-------+       |       |
-         Makes sure all effects --->   \   ddddddddddddddddd   |       |
+         Makes sure all effects --->   \   aaaaaaaaaaaaaaaaa   |       |
          prior to the store of C        \      +-------+       |       |
          are perceptible to              ----->| B->2  |------>|       |
          subsequent loads                      +-------+       |       |
@@ -1292,7 +1304,7 @@ Which might appear as this:
        LOAD with immediate effect              :       :       +-------+
 
 
-Placing a read barrier or a data dependency barrier just before the second
+Placing a read barrier or an address-dependency barrier just before the second
 load:
 
        CPU 1                   CPU 2
@@ -1816,20 +1828,20 @@ which may then reorder things however it wishes.
 CPU MEMORY BARRIERS
 -------------------
 
-The Linux kernel has eight basic CPU memory barriers:
+The Linux kernel has seven basic CPU memory barriers:
 
-       TYPE            MANDATORY               SMP CONDITIONAL
-       =============== ======================= ===========================
-       GENERAL         mb()                    smp_mb()
-       WRITE           wmb()                   smp_wmb()
-       READ            rmb()                   smp_rmb()
-       DATA DEPENDENCY                         READ_ONCE()
+       TYPE                    MANDATORY       SMP CONDITIONAL
+       ======================= =============== ===============
+       GENERAL                 mb()            smp_mb()
+       WRITE                   wmb()           smp_wmb()
+       READ                    rmb()           smp_rmb()
+       ADDRESS DEPENDENCY                      READ_ONCE()
 
 
-All memory barriers except the data dependency barriers imply a compiler
-barrier.  Data dependencies do not impose any additional compiler ordering.
+All memory barriers except the address-dependency barriers imply a compiler
+barrier.  Address dependencies do not impose any additional compiler ordering.
 
-Aside: In the case of data dependencies, the compiler would be expected
+Aside: In the case of address dependencies, the compiler would be expected
 to issue the loads in the correct order (eg. `a[b]` would have to load
 the value of b before loading a[b]), however there is no guarantee in
 the C specification that the compiler may not speculate the value of b
@@ -2749,7 +2761,8 @@ is discarded from the CPU's cache and reloaded.  To deal with this, the
 appropriate part of the kernel must invalidate the overlapping bits of the
 cache on each CPU.
 
-See Documentation/core-api/cachetlb.rst for more information on cache management.
+See Documentation/core-api/cachetlb.rst for more information on cache
+management.
 
 
 CACHE COHERENCY VS MMIO
@@ -2889,8 +2902,8 @@ AND THEN THERE'S THE ALPHA
 The DEC Alpha CPU is one of the most relaxed CPUs there is.  Not only that,
 some versions of the Alpha CPU have a split data cache, permitting them to have
 two semantically-related cache lines updated at separate times.  This is where
-the data dependency barrier really becomes necessary as this synchronises both
-caches with the memory coherence system, thus making it seem like pointer
+the address-dependency barrier really becomes necessary as this synchronises
+both caches with the memory coherence system, thus making it seem like pointer
 changes vs new data occur in the right order.
 
 The Alpha defines the Linux kernel's memory model, although as of v4.15
index b280367..4a0e158 100644 (file)
@@ -197,7 +197,7 @@ unevictable list for the memory cgroup and node being scanned.
 There may be situations where a page is mapped into a VM_LOCKED VMA, but the
 page is not marked as PG_mlocked.  Such pages will make it all the way to
 shrink_active_list() or shrink_page_list() where they will be detected when
-vmscan walks the reverse map in page_referenced() or try_to_unmap().  The page
+vmscan walks the reverse map in folio_referenced() or try_to_unmap().  The page
 is culled to the unevictable list when it is released by the shrinker.
 
 To "cull" an unevictable page, vmscan simply puts the page back on the LRU list
@@ -267,7 +267,7 @@ the LRU.  Such pages can be "noticed" by memory management in several places:
  (4) in the fault path and when a VM_LOCKED stack segment is expanded; or
 
  (5) as mentioned above, in vmscan:shrink_page_list() when attempting to
-     reclaim a page in a VM_LOCKED VMA by page_referenced() or try_to_unmap().
+     reclaim a page in a VM_LOCKED VMA by folio_referenced() or try_to_unmap().
 
 mlocked pages become unlocked and rescued from the unevictable list when:
 
@@ -547,7 +547,7 @@ vmscan's shrink_inactive_list() and shrink_page_list() also divert obviously
 unevictable pages found on the inactive lists to the appropriate memory cgroup
 and node unevictable list.
 
-rmap's page_referenced_one(), called via vmscan's shrink_active_list() or
+rmap's folio_referenced_one(), called via vmscan's shrink_active_list() or
 shrink_page_list(), and rmap's try_to_unmap_one() called via shrink_page_list(),
 check for (3) pages still mapped into VM_LOCKED VMAs, and call mlock_vma_page()
 to correct them.  Such pages are culled to the unevictable list when released
index 8a292fb..ec5e6d7 100644 (file)
@@ -67,7 +67,7 @@ The ``netdevsim`` driver supports rate objects management, which includes:
 - setting tx_share and tx_max rate values for any rate object type;
 - setting parent node for any rate object type.
 
-Rate nodes and it's parameters are exposed in ``netdevsim`` debugfs in RO mode.
+Rate nodes and their parameters are exposed in ``netdevsim`` debugfs in RO mode.
 For example created rate node with name ``some_group``:
 
 .. code:: shell
index c8f59db..64f7236 100644 (file)
@@ -8,7 +8,7 @@ Transmit path guidelines:
 
 1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under
    any normal circumstances.  It is considered a hard error unless
-   there is no way your device can tell ahead of time when it's
+   there is no way your device can tell ahead of time when its
    transmit function will become busy.
 
    Instead it must maintain the queue properly.  For example,
index 56cd4ea..a759872 100644 (file)
@@ -1035,7 +1035,10 @@ tcp_limit_output_bytes - INTEGER
 tcp_challenge_ack_limit - INTEGER
        Limits number of Challenge ACK sent per second, as recommended
        in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
-       Default: 1000
+       Note that this per netns rate limit can allow some side channel
+       attacks and probably should not be enabled.
+       TCP stack implements per TCP socket limits anyway.
+       Default: INT_MAX (unlimited)
 
 UDP variables
 =============
index 694adcb..0000c1d 100644 (file)
@@ -11,7 +11,7 @@ Initial Release:
 ================
 This is conceptually very similar to the macvlan driver with one major
 exception of using L3 for mux-ing /demux-ing among slaves. This property makes
-the master device share the L2 with it's slave devices. I have developed this
+the master device share the L2 with its slave devices. I have developed this
 driver in conjunction with network namespaces and not sure if there is use case
 outside of it.
 
index 498b382..7f383e9 100644 (file)
@@ -530,7 +530,7 @@ its tunnel close actions. For L2TPIP sockets, the socket's close
 handler initiates the same tunnel close actions. All sessions are
 first closed. Each session drops its tunnel ref. When the tunnel ref
 reaches zero, the tunnel puts its socket ref. When the socket is
-eventually destroyed, it's sk_destruct finally frees the L2TP tunnel
+eventually destroyed, its sk_destruct finally frees the L2TP tunnel
 context.
 
 Sessions
index e263dfc..2135106 100644 (file)
@@ -47,7 +47,6 @@ allow_join_initial_addr_port - BOOLEAN
        Default: 1
 
 pm_type - INTEGER
-
        Set the default path manager type to use for each new MPTCP
        socket. In-kernel path management will control subflow
        connections and address advertisements according to
index 834945e..1120d71 100644 (file)
@@ -70,15 +70,6 @@ nf_conntrack_generic_timeout - INTEGER (seconds)
        Default for generic timeout.  This refers to layer 4 unknown/unsupported
        protocols.
 
-nf_conntrack_helper - BOOLEAN
-       - 0 - disabled (default)
-       - not 0 - enabled
-
-       Enable automatic conntrack helper assignment.
-       If disabled it is required to set up iptables rules to assign
-       helpers to connections.  See the CT target description in the
-       iptables-extensions(8) man page for further information.
-
 nf_conntrack_icmp_timeout - INTEGER (seconds)
        default 30
 
index 39c2249..39494a6 100644 (file)
@@ -1055,17 +1055,6 @@ The kernel interface functions are as follows:
      first function to change.  Note that this must be called in TASK_RUNNING
      state.
 
- (#) Get reply timestamp::
-
-       bool rxrpc_kernel_get_reply_time(struct socket *sock,
-                                        struct rxrpc_call *call,
-                                        ktime_t *_ts)
-
-     This allows the timestamp on the first DATA packet of the reply of a
-     client call to be queried, provided that it is still in the Rx ring.  If
-     successful, the timestamp will be stored into ``*_ts`` and true will be
-     returned; false will be returned otherwise.
-
  (#) Get remote client epoch::
 
        u32 rxrpc_kernel_get_epoch(struct socket *sock,
index f1f4e6a..bbf272e 100644 (file)
@@ -159,7 +159,7 @@ tools such as iproute2.
 
 The switchdev driver can know a particular port's position in the topology by
 monitoring NETDEV_CHANGEUPPER notifications.  For example, a port moved into a
-bond will see it's upper master change.  If that bond is moved into a bridge,
+bond will see its upper master change.  If that bond is moved into a bridge,
 the bond's upper master will change.  And so on.  The driver will track such
 movements to know what position a port is in in the overall topology by
 registering for netdevice events and acting on NETDEV_CHANGEUPPER.
index 906235c..d87f1fe 100644 (file)
@@ -256,8 +256,10 @@ The tags in common use are:
  - Cc: the named person received a copy of the patch and had the
    opportunity to comment on it.
 
-Be careful in the addition of tags to your patches: only Cc: is appropriate
-for addition without the explicit permission of the person named.
+Be careful in the addition of tags to your patches, as only Cc: is appropriate
+for addition without the explicit permission of the person named; using
+Reported-by: is fine most of the time as well, but ask for permission if
+the bug was reported in private.
 
 
 Sending the patch
index e899f14..922e0b5 100644 (file)
@@ -51,7 +51,7 @@ the Technical Advisory Board (TAB) or other maintainers if you're
 uncertain how to handle situations that come up.  It will not be
 considered a violation report unless you want it to be.  If you are
 uncertain about approaching the TAB or any other maintainers, please
-reach out to our conflict mediator, Mishi Choudhary <mishi@linux.com>.
+reach out to our conflict mediator, Joanna Lee <joanna.lee@gesmer.com>.
 
 In the end, "be kind to each other" is really what the end goal is for
 everybody.  We know everyone is human and we all fail at times, but the
@@ -127,10 +127,12 @@ are listed at https://kernel.org/code-of-conduct.html.  Members can not
 access reports made before they joined or after they have left the
 committee.
 
-The initial Code of Conduct Committee consists of volunteer members of
-the TAB, as well as a professional mediator acting as a neutral third
-party.  The first task of the committee is to establish documented
-processes, which will be made public.
+The Code of Conduct Committee consists of volunteer community members
+appointed by the TAB, as well as a professional mediator acting as a
+neutral third party.  The processes the Code of Conduct committee will
+use to address reports is varied and will depend on the individual
+circumstance, however, this file serves as documentation for the
+general process used.
 
 Any member of the committee, including the mediator, can be contacted
 directly if a reporter does not wish to include the full committee in a
@@ -141,16 +143,16 @@ processes (see above) and consults with the TAB as needed and
 appropriate, for instance to request and receive information about the
 kernel community.
 
-Any decisions by the committee will be brought to the TAB, for
-implementation of enforcement with the relevant maintainers if needed.
-A decision by the Code of Conduct Committee can be overturned by the TAB
-by a two-thirds vote.
+Any decisions regarding enforcement recommendations will be brought to
+the TAB for implementation of enforcement with the relevant maintainers
+if needed.  A decision by the Code of Conduct Committee can be overturned
+by the TAB by a two-thirds vote.
 
 At quarterly intervals, the Code of Conduct Committee and TAB will
 provide a report summarizing the anonymised reports that the Code of
 Conduct committee has received and their status, as well details of any
 overridden decisions including complete and identifiable voting details.
 
-We expect to establish a different process for Code of Conduct Committee
-staffing beyond the bootstrap period.  This document will be updated
-with that information when this occurs.
+Because how we interpret and enforce the Code of Conduct will evolve over
+time, this document will be updated when necessary to reflect any
+changes.
index 03eb53f..007e49e 100644 (file)
@@ -1186,6 +1186,68 @@ expression used.  For instance:
        #endif /* CONFIG_SOMETHING */
 
 
+22) Do not crash the kernel
+---------------------------
+
+In general, the decision to crash the kernel belongs to the user, rather
+than to the kernel developer.
+
+Avoid panic()
+*************
+
+panic() should be used with care and primarily only during system boot.
+panic() is, for example, acceptable when running out of memory during boot and
+not being able to continue.
+
+Use WARN() rather than BUG()
+****************************
+
+Do not add new code that uses any of the BUG() variants, such as BUG(),
+BUG_ON(), or VM_BUG_ON(). Instead, use a WARN*() variant, preferably
+WARN_ON_ONCE(), and possibly with recovery code. Recovery code is not
+required if there is no reasonable way to at least partially recover.
+
+"I'm too lazy to do error handling" is not an excuse for using BUG(). Major
+internal corruptions with no way of continuing may still use BUG(), but need
+good justification.
+
+Use WARN_ON_ONCE() rather than WARN() or WARN_ON()
+**************************************************
+
+WARN_ON_ONCE() is generally preferred over WARN() or WARN_ON(), because it
+is common for a given warning condition, if it occurs at all, to occur
+multiple times. This can fill up and wrap the kernel log, and can even slow
+the system enough that the excessive logging turns into its own, additional
+problem.
+
+Do not WARN lightly
+*******************
+
+WARN*() is intended for unexpected, this-should-never-happen situations.
+WARN*() macros are not to be used for anything that is expected to happen
+during normal operation. These are not pre- or post-condition asserts, for
+example. Again: WARN*() must not be used for a condition that is expected
+to trigger easily, for example, by user space actions. pr_warn_once() is a
+possible alternative, if you need to notify the user of a problem.
+
+Do not worry about panic_on_warn users
+**************************************
+
+A few more words about panic_on_warn: Remember that ``panic_on_warn`` is an
+available kernel option, and that many users set this option. This is why
+there is a "Do not WARN lightly" writeup, above. However, the existence of
+panic_on_warn users is not a valid reason to avoid the judicious use
+WARN*(). That is because, whoever enables panic_on_warn has explicitly
+asked the kernel to crash if a WARN*() fires, and such users must be
+prepared to deal with the consequences of a system that is somewhat more
+likely to crash.
+
+Use BUILD_BUG_ON() for compile-time assertions
+**********************************************
+
+The use of BUILD_BUG_ON() is acceptable and encouraged, because it is a
+compile-time assertion that has no effect at runtime.
+
 Appendix I) References
 ----------------------
 
index 2ba2a15..d4b6217 100644 (file)
@@ -5,6 +5,7 @@
 
 .. _process_index:
 
+=============================================
 Working with the kernel development community
 =============================================
 
index 29e7d7b..40bfbd3 100644 (file)
@@ -121,57 +121,56 @@ edit your ``~/.gnupg/gpg-agent.conf`` file to set your own values::
     to remove anything you had in place for older versions of GnuPG, as
     it may not be doing the right thing any more.
 
-Set up a refresh cronjob
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-You will need to regularly refresh your keyring in order to get the
-latest changes on other people's public keys, which is best done with a
-daily cronjob::
-
-    @daily /usr/bin/gpg2 --refresh >/dev/null 2>&1
-
-Check the full path to your ``gpg`` or ``gpg2`` command and use the
-``gpg2`` command if regular ``gpg`` for you is the legacy GnuPG v.1.
-
-.. _master_key:
+.. _protect_your_key:
 
-Protect your master PGP key
-===========================
+Protect your PGP key
+====================
 
 This guide assumes that you already have a PGP key that you use for Linux
 kernel development purposes. If you do not yet have one, please see the
 "`Protecting Code Integrity`_" document mentioned earlier for guidance
 on how to create a new one.
 
-You should also make a new key if your current one is weaker than 2048 bits
-(RSA).
-
-Master key vs. Subkeys
-----------------------
-
-Subkeys are fully independent PGP keypairs that are tied to the "master"
-key using certifying key signatures (certificates). It is important to
-understand the following:
-
-1. There are no technical differences between the "master key" and "subkeys."
-2. At creation time, we assign functional limitations to each key by
-   giving it specific capabilities.
-3. A PGP key can have 4 capabilities:
-
-   - **[S]** key can be used for signing
-   - **[E]** key can be used for encryption
-   - **[A]** key can be used for authentication
-   - **[C]** key can be used for certifying other keys
-
-4. A single key may have multiple capabilities.
-5. A subkey is fully independent from the master key. A message
-   encrypted to a subkey cannot be decrypted with the master key. If you
-   lose your private subkey, it cannot be recreated from the master key
-   in any way.
-
-The key carrying the **[C]** (certify) capability is considered the
-"master" key because it is the only key that can be used to indicate
-relationship with other keys. Only the **[C]** key can be used to:
+You should also make a new key if your current one is weaker than 2048
+bits (RSA).
+
+Understanding PGP Subkeys
+-------------------------
+
+A PGP key rarely consists of a single keypair -- usually it is a
+collection of independent subkeys that can be used for different
+purposes based on their capabilities, assigned at their creation time.
+PGP defines four capabilities that a key can have:
+
+- **[S]** keys can be used for signing
+- **[E]** keys can be used for encryption
+- **[A]** keys can be used for authentication
+- **[C]** keys can be used for certifying other keys
+
+The key with the **[C]** capability is often called the "master" key,
+but this terminology is misleading because it implies that the Certify
+key can be used in place of any of other subkey on the same chain (like
+a physical "master key" can be used to open the locks made for other
+keys). Since this is not the case, this guide will refer to it as "the
+Certify key" to avoid any ambiguity.
+
+It is critical to fully understand the following:
+
+1. All subkeys are fully independent from each other. If you lose a
+   private subkey, it cannot be restored or recreated from any other
+   private key on your chain.
+2. With the exception of the Certify key, there can be multiple subkeys
+   with identical capabilities (e.g. you can have 2 valid encryption
+   subkeys, 3 valid signing subkeys, but only one valid certification
+   subkey). All subkeys are fully independent -- a message encrypted to
+   one **[E]** subkey cannot be decrypted with any other **[E]** subkey
+   you may also have.
+3. A single subkey may have multiple capabilities (e.g. your **[C]** key
+   can also be your **[S]** key).
+
+The key carrying the **[C]** (certify) capability is the only key that
+can be used to indicate relationship with other keys. Only the **[C]**
+key can be used to:
 
 - add or revoke other keys (subkeys) with S/E/A capabilities
 - add, change or revoke identities (uids) associated with the key
@@ -180,7 +179,7 @@ relationship with other keys. Only the **[C]** key can be used to:
 
 By default, GnuPG creates the following when generating new keys:
 
-- A master key carrying both Certify and Sign capabilities (**[SC]**)
+- One subkey carrying both Certify and Sign capabilities (**[SC]**)
 - A separate subkey with the Encryption capability (**[E]**)
 
 If you used the default parameters when generating your key, then that
@@ -192,9 +191,6 @@ for example::
     uid           [ultimate] Alice Dev <adev@kernel.org>
     ssb   rsa2048 2018-01-23 [E] [expires: 2020-01-23]
 
-Any key carrying the **[C]** capability is your master key, regardless
-of any other capabilities it may have assigned to it.
-
 The long line under the ``sec`` entry is your key fingerprint --
 whenever you see ``[fpr]`` in the examples below, that 40-character
 string is what it refers to.
@@ -215,37 +211,30 @@ strong passphrase. To set it or change it, use::
 Create a separate Signing subkey
 --------------------------------
 
-Our goal is to protect your master key by moving it to offline media, so
-if you only have a combined **[SC]** key, then you should create a separate
-signing subkey::
+Our goal is to protect your Certify key by moving it to offline media,
+so if you only have a combined **[SC]** key, then you should create a
+separate signing subkey::
 
     $ gpg --quick-addkey [fpr] ed25519 sign
 
-Remember to tell the keyservers about this change, so others can pull down
-your new subkey::
-
-    $ gpg --send-key [fpr]
-
 .. note:: ECC support in GnuPG
 
     GnuPG 2.1 and later has full support for Elliptic Curve
     Cryptography, with ability to combine ECC subkeys with traditional
-    RSA master keys. The main upside of ECC cryptography is that it is
-    much faster computationally and creates much smaller signatures when
+    RSA keys. The main upside of ECC cryptography is that it is much
+    faster computationally and creates much smaller signatures when
     compared byte for byte with 2048+ bit RSA keys. Unless you plan on
     using a smartcard device that does not support ECC operations, we
     recommend that you create an ECC signing subkey for your kernel
     work.
 
-    If for some reason you prefer to stay with RSA subkeys, just replace
-    "ed25519" with "rsa2048" in the above command. Additionally, if you
-    plan to use a hardware device that does not support ED25519 ECC
-    keys, like Nitrokey Pro or a Yubikey, then you should use
-    "nistp256" instead or "ed25519."
+    Note, that if you plan to use a hardware device that does not
+    support ED25519 ECC keys, you should choose "nistp256" instead or
+    "ed25519."
 
 
-Back up your master key for disaster recovery
----------------------------------------------
+Back up your Certify key for disaster recovery
+----------------------------------------------
 
 The more signatures you have on your PGP key from other developers, the
 more reasons you have to create a backup version that lives on something
@@ -277,9 +266,7 @@ home, such as your bank vault.
     Your printer is probably no longer a simple dumb device connected to
     your parallel port, but since the output is still encrypted with
     your passphrase, printing out even to "cloud-integrated" modern
-    printers should remain a relatively safe operation. One option is to
-    change the passphrase on your master key immediately after you are
-    done with paperkey.
+    printers should remain a relatively safe operation.
 
 Back up your whole GnuPG directory
 ----------------------------------
@@ -300,7 +287,7 @@ will use for backup purposes. You will need to encrypt them using LUKS
 -- refer to your distro's documentation on how to accomplish this.
 
 For the encryption passphrase, you can use the same one as on your
-master key.
+PGP key.
 
 Once the encryption process is over, re-insert the USB drive and make
 sure it gets properly mounted. Copy your entire ``.gnupg`` directory
@@ -319,7 +306,7 @@ far away, because you'll need to use it every now and again for things
 like editing identities, adding or revoking subkeys, or signing other
 people's keys.
 
-Remove the master key from  your homedir
+Remove the Certify key from your homedir
 ----------------------------------------
 
 The files in our home directory are not as well protected as we like to
@@ -334,7 +321,7 @@ think.  They can be leaked or stolen via many different means:
 Protecting your key with a good passphrase greatly helps reduce the risk
 of any of the above, but passphrases can be discovered via keyloggers,
 shoulder-surfing, or any number of other means. For this reason, the
-recommended setup is to remove your master key from your home directory
+recommended setup is to remove your Certify key from your home directory
 and store it on offline storage.
 
 .. warning::
@@ -343,7 +330,7 @@ and store it on offline storage.
     your GnuPG directory in its entirety. What we are about to do will
     render your key useless if you do not have a usable backup!
 
-First, identify the keygrip of your master key::
+First, identify the keygrip of your Certify key::
 
     $ gpg --with-keygrip --list-key [fpr]
 
@@ -359,7 +346,7 @@ The output will be something like this::
           Keygrip = 3333000000000000000000000000000000000000
 
 Find the keygrip entry that is beneath the ``pub`` line (right under the
-master key fingerprint). This will correspond directly to a file in your
+Certify key fingerprint). This will correspond directly to a file in your
 ``~/.gnupg`` directory::
 
     $ cd ~/.gnupg/private-keys-v1.d
@@ -369,13 +356,13 @@ master key fingerprint). This will correspond directly to a file in your
     3333000000000000000000000000000000000000.key
 
 All you have to do is simply remove the .key file that corresponds to
-the master keygrip::
+the Certify key keygrip::
 
     $ cd ~/.gnupg/private-keys-v1.d
     $ rm 1111000000000000000000000000000000000000.key
 
 Now, if you issue the ``--list-secret-keys`` command, it will show that
-the master key is missing (the ``#`` indicates it is not available)::
+the Certify key is missing (the ``#`` indicates it is not available)::
 
     $ gpg --list-secret-keys
     sec#  rsa2048 2018-01-24 [SC] [expires: 2020-01-24]
@@ -404,7 +391,7 @@ file, which still contains your private keys.
 Move the subkeys to a dedicated crypto device
 =============================================
 
-Even though the master key is now safe from being leaked or stolen, the
+Even though the Certify key is now safe from being leaked or stolen, the
 subkeys are still in your home directory. Anyone who manages to get
 their hands on those will be able to decrypt your communication or fake
 your signatures (if they know the passphrase). Furthermore, each time a
@@ -447,7 +434,8 @@ functionality. There are several options available:
 - `Yubikey 5`_: proprietary hardware and software, but cheaper than
   Nitrokey Pro and comes available in the USB-C form that is more useful
   with newer laptops. Offers additional security features such as FIDO
-  U2F, among others, and now finally supports ECC keys (NISTP).
+  U2F, among others, and now finally supports NISTP and ED25519 ECC
+  keys.
 
 `LWN has a good review`_ of some of the above models, as well as several
 others. Your choice will depend on cost, shipping availability in your
@@ -460,7 +448,7 @@ geographical region, and open/proprietary hardware considerations.
     Foundation.
 
 .. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6
-.. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nitrokey-pro-2-3
+.. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nkpr2-nitrokey-pro-2-3
 .. _`Yubikey 5`: https://www.yubico.com/products/yubikey-5-overview/
 .. _Gnuk: https://www.fsij.org/doc-gnuk/
 .. _`LWN has a good review`: https://lwn.net/Articles/736231/
@@ -627,10 +615,10 @@ Other common GnuPG operations
 Here is a quick reference for some common operations you'll need to do
 with your PGP key.
 
-Mounting your master key offline storage
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Mounting your safe offline storage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-You will need your master key for any of the operations below, so you
+You will need your Certify key for any of the operations below, so you
 will first need to mount your backup offline storage and tell GnuPG to
 use it::
 
@@ -644,7 +632,7 @@ your regular home directory location).
 Extending key expiration date
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The master key has the default expiration date of 2 years from the date
+The Certify key has the default expiration date of 2 years from the date
 of creation. This is done both for security reasons and to make obsolete
 keys eventually disappear from keyservers.
 
@@ -685,6 +673,7 @@ remote end.
 
 .. _`Agent Forwarding over SSH`: https://wiki.gnupg.org/AgentForwarding
 
+.. _pgp_with_git:
 
 Using PGP with Git
 ==================
@@ -828,6 +817,63 @@ You can tell git to always sign commits::
 
 .. _verify_identities:
 
+
+How to work with signed patches
+-------------------------------
+
+It is possible to use your PGP key to sign patches sent to kernel
+developer mailing lists. Since existing email signature mechanisms
+(PGP-Mime or PGP-inline) tend to cause problems with regular code
+review tasks, you should use the tool kernel.org created for this
+purpose that puts cryptographic attestation signatures into message
+headers (a-la DKIM):
+
+- `Patatt Patch Attestation`_
+
+.. _`Patatt Patch Attestation`: https://pypi.org/project/patatt/
+
+Installing and configuring patatt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Patatt is packaged for many distributions already, so please check there
+first. You can also install it from pypi using "``pip install patatt``".
+
+If you already have your PGP key configured with git (via the
+``user.signingKey`` configuration parameter), then patatt requires no
+further configuration. You can start signing your patches by installing
+the git-send-email hook in the repository you want::
+
+    patatt install-hook
+
+Now any patches you send with ``git send-email`` will be automatically
+signed with your cryptographic signature.
+
+Checking patatt signatures
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are using ``b4`` to retrieve and apply patches, then it will
+automatically attempt to verify all DKIM and patatt signatures it
+encounters, for example::
+
+    $ 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::
+
+    Patatt and b4 are still in active development and you should check
+    the latest documentation for these projects for any new or updated
+    features.
+
+.. _kernel_identities:
+
 How to verify kernel developer identities
 =========================================
 
@@ -899,65 +945,17 @@ the new default in GnuPG v2). To set it, add (or modify) the
 
     trust-model tofu+pgp
 
-How to use keyservers (more) safely
------------------------------------
-
-If you get a "No public key" error when trying to validate someone's
-tag, then you should attempt to lookup that key using a keyserver. It is
-important to keep in mind that there is absolutely no guarantee that the
-key you retrieve from PGP keyservers belongs to the actual person --
-that much is by design. You are supposed to use the Web of Trust to
-establish key validity.
-
-How to properly maintain the Web of Trust is beyond the scope of this
-document, simply because doing it properly requires both effort and
-dedication that tends to be beyond the caring threshold of most human
-beings. Here are some shortcuts that will help you reduce the risk of
-importing a malicious key.
-
-First, let's say you've tried to run ``git verify-tag`` but it returned
-an error saying the key is not found::
-
-    $ 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
-
-Let's query the keyserver for more info about that key fingerprint (the
-fingerprint probably belongs to a subkey, so we can't use it directly
-without finding out the ID of the master key it is associated with)::
-
-    $ 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
-
-Locate the ID of the master key in the output, in our example
-``C94035C21B4F2AEB``. Now display the key of Linus Torvalds that you
-have on your keyring::
-
-    $ 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]
-
-Next, find a trust path from Linus Torvalds to the key-id you found via ``gpg
---search`` of the unknown key.  For this, you can use several tools including
-https://github.com/mricon/wotmate,
-https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/tree/graphs, and
-https://the.earth.li/~noodles/pathfind.html.
-
-If you get a few decent trust paths, then it's a pretty good indication
-that it is a valid key. You can add it to your keyring from the
-keyserver now::
-
-    $ gpg --recv-key C94035C21B4F2AEB
-
-This process is not perfect, and you are obviously trusting the
-administrators of the PGP Pathfinder service to not be malicious (in
-fact, this goes against :ref:`devs_not_infra`). However, if you
-do not carefully maintain your own web of trust, then it is a marked
-improvement over blindly trusting keyservers.
+Using the kernel.org web of trust repository
+--------------------------------------------
+
+Kernel.org maintains a git repository with developers' public keys as a
+replacement for replicating keyserver networks that have gone mostly
+dark in the past few years. The full documentation for how to set up
+that repository as your source of public keys can be found here:
+
+- `Kernel developer PGP Keyring`_
+
+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 c61865e..2fd8aa5 100644 (file)
@@ -97,6 +97,12 @@ text, like this:
 
     commit <sha1> upstream.
 
+or alternatively:
+
+.. code-block:: none
+
+    [ Upstream commit <sha1> ]
+
 Additionally, some patches submitted via :ref:`option_1` may have additional
 patch prerequisites which can be cherry-picked. This can be specified in the
 following format in the sign-off area:
index be49d8f..7dc9455 100644 (file)
@@ -715,8 +715,8 @@ references.
 
 .. _backtraces:
 
-Backtraces in commit mesages
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Backtraces in commit messages
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Backtraces help document the call chain leading to a problem. However,
 not all backtraces are helpful. For example, early boot call chains are
index 59b2d1f..03db555 100644 (file)
@@ -94,7 +94,7 @@ other HZ detail.  Thus the CFS scheduler has no notion of "timeslices" in the
 way the previous scheduler had, and has no heuristics whatsoever.  There is
 only one central tunable (you have to switch on CONFIG_SCHED_DEBUG):
 
-   /proc/sys/kernel/sched_min_granularity_ns
+   /sys/kernel/debug/sched/min_granularity_ns
 
 which can be used to tune the scheduler from "desktop" (i.e., low latencies) to
 "server" (i.e., good batching) workloads.  It defaults to a setting suitable
index 2a29cbe..9707e03 100644 (file)
 
 % Translations have Asian (CJK) characters which are only displayed if
 % xeCJK is used
+\usepackage{ifthen}
+\newboolean{enablecjk}
+\setboolean{enablecjk}{false}
 \IfFontExistsTF{Noto Sans CJK SC}{
-    % Load xeCJK when CJK font is available
+    \IfFileExists{xeCJK.sty}{
+       \setboolean{enablecjk}{true}
+    }{}
+}{}
+\ifthenelse{\boolean{enablecjk}}{
+    % Load xeCJK when both the Noto Sans CJK font and xeCJK.sty are available.
     \usepackage{xeCJK}
     % Noto CJK fonts don't provide slant shape. [AutoFakeSlant] permits
     % its emulation.
     % Inactivate CJK after tableofcontents
     \apptocmd{\sphinxtableofcontents}{\kerneldocCJKoff}{}{}
     \xeCJKsetup{CJKspace = true}% For inter-phrase space of Korean TOC
-}{ % No CJK font found
+}{ % Don't enable CJK
     % Custom macros to on/off CJK and switch CJK fonts (Dummy)
     \newcommand{\kerneldocCJKon}{}
     \newcommand{\kerneldocCJKoff}{}
     %% and ignore the argument (#1) in their definitions, whole contents of
     %% CJK chapters can be ignored.
     \newcommand{\kerneldocBeginSC}[1]{%
-       %% Put a note on missing CJK fonts in place of zh_CN translation.
-       \begin{sphinxadmonition}{note}{Note on missing fonts:}
+       %% Put a note on missing CJK fonts or the xecjk package in place of
+       %% zh_CN translation.
+       \begin{sphinxadmonition}{note}{Note on missing fonts and a package:}
            Translations of Simplified Chinese (zh\_CN), Traditional Chinese
            (zh\_TW), Korean (ko\_KR), and Japanese (ja\_JP) were skipped
-           due to the lack of suitable font families.
+           due to the lack of suitable font families and/or the texlive-xecjk
+           package.
 
            If you want them, please install ``Noto Sans CJK'' font families
-           by following instructions from
+           along with the texlive-xecjk package by following instructions from
            \sphinxcode{./scripts/sphinx-pre-install}.
            Having optional ``Noto Serif CJK'' font families will improve
            the looks of those translations.
index abd0d18..ded8254 100644 (file)
@@ -14,45 +14,3 @@ Unsorted Documentation
    static-keys
    tee
    xz
-
-Atomic Types
-============
-
-.. raw:: latex
-
-    \footnotesize
-
-.. include:: ../atomic_t.txt
-   :literal:
-
-.. raw:: latex
-
-    \normalsize
-
-Atomic bitops
-=============
-
-.. raw:: latex
-
-    \footnotesize
-
-.. include:: ../atomic_bitops.txt
-   :literal:
-
-.. raw:: latex
-
-    \normalsize
-
-Memory Barriers
-===============
-
-.. raw:: latex
-
-    \footnotesize
-
-.. include:: ../memory-barriers.txt
-   :literal:
-
-.. raw:: latex
-
-    \normalsize
diff --git a/Documentation/subsystem-apis.rst b/Documentation/subsystem-apis.rst
new file mode 100644 (file)
index 0000000..af65004
--- /dev/null
@@ -0,0 +1,58 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================
+Kernel subsystem documentation
+==============================
+
+These books get into the details of how specific kernel subsystems work
+from the point of view of a kernel developer.  Much of the information here
+is taken directly from the kernel source, with supplemental material added
+as needed (or at least as we managed to add it — probably *not* all that is
+needed).
+
+**Fixme**: much more organizational work is needed here.
+
+.. toctree::
+   :maxdepth: 1
+
+   driver-api/index
+   core-api/index
+   locking/index
+   accounting/index
+   block/index
+   cdrom/index
+   cpu-freq/index
+   fb/index
+   fpga/index
+   hid/index
+   i2c/index
+   iio/index
+   isdn/index
+   infiniband/index
+   leds/index
+   netlabel/index
+   networking/index
+   pcmcia/index
+   power/index
+   target/index
+   timers/index
+   spi/index
+   w1/index
+   watchdog/index
+   virt/index
+   input/index
+   hwmon/index
+   gpu/index
+   security/index
+   sound/index
+   crypto/index
+   filesystems/index
+   mm/index
+   bpf/index
+   usb/index
+   PCI/index
+   scsi/index
+   misc-devices/index
+   scheduler/index
+   mhi/index
+   peci/index
index 859fd1b..c1b685a 100644 (file)
@@ -412,7 +412,7 @@ Extended error information
   Because the default sort key above is 'hitcount', the above shows a
   the list of call_sites by increasing hitcount, so that at the bottom
   we see the functions that made the most kmalloc calls during the
-  run.  If instead we we wanted to see the top kmalloc callers in
+  run.  If instead we wanted to see the top kmalloc callers in
   terms of the number of bytes requested rather than the number of
   calls, and we wanted the top caller to appear at the top, we can use
   the 'sort' parameter, along with the 'descending' modifier::
index f318bce..48cf778 100644 (file)
@@ -328,8 +328,8 @@ Configuring Kprobes
 ===================
 
 When configuring the kernel using make menuconfig/xconfig/oldconfig,
-ensure that CONFIG_KPROBES is set to "y". Under "General setup", look
-for "Kprobes".
+ensure that CONFIG_KPROBES is set to "y", look for "Kprobes" under
+"General architecture-dependent options".
 
 So that you can load and unload Kprobes-based instrumentation modules,
 make sure "Loadable module support" (CONFIG_MODULES) and "Module
index d643c95..db17df3 100644 (file)
@@ -20,7 +20,7 @@ For example::
         [root@f32 ~]# cd /sys/kernel/tracing/
         [root@f32 tracing]# echo timerlat > current_tracer
 
-It is possible to follow the trace by reading the trace trace file::
+It is possible to follow the trace by reading the trace file::
 
   [root@f32 tracing]# cat trace
   # tracer: timerlat
index 66ce0d8..04deb77 100644 (file)
@@ -35,8 +35,7 @@ Linux カーネルに変更を加えたいと思っている個人又は会社
 てもらえやすくする提案を集めたものです。
 
 コードを投稿する前に、Documentation/process/submit-checklist.rst の項目リストに目
-を通してチェックしてください。もしあなたがドライバーを投稿しようとし
-ているなら、Documentation/process/submitting-drivers.rst にも目を通してください。
+を通してチェックしてください。
 
 --------------------------------------------
 セクション1 パッチの作り方と送り方
diff --git a/Documentation/translations/zh_CN/IRQ.txt b/Documentation/translations/zh_CN/IRQ.txt
deleted file mode 100644 (file)
index 9aec8dc..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-Chinese translated version of Documentation/core-api/irq/index.rst
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Maintainer: Eric W. Biederman <ebiederman@xmission.com>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/core-api/irq/index.rst 的中文翻译
-
-如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
-交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题,请联系中文版维护者。
-英文版维护者: Eric W. Biederman <ebiederman@xmission.com>
-中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-何为 IRQ?
-
-一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚,
-或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。
-
-一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个
-全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现,
-具体的细节是体系结构特定的。
-
-一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是
-该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况,
-枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
-
-架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下,
-是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff --git a/Documentation/translations/zh_CN/PCI/acpi-info.rst b/Documentation/translations/zh_CN/PCI/acpi-info.rst
new file mode 100644 (file)
index 0000000..a35f39d
--- /dev/null
@@ -0,0 +1,139 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/PCI/acpi-info.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+
+=====================
+PCI主桥的ACPI注意事项
+=====================
+
+一般的规则是,ACPI命名空间应该描述操作系统可能使用的所有东西,除非有其他方法让操作系
+统找到它[1, 2]。
+
+例如,没有标准的硬件机制来枚举PCI主桥,所以ACPI命名空间必须描述每个主桥、访问它
+下面的PCI配置空间的方法、主桥转发到PCI的地址空间窗口(使用_CRS)以及传统的INTx
+中断的路由(使用_PRT)。
+
+在主桥下面的PCI设备,通常不需要通过ACPI描述。操作系统可以通过标准的PCI枚举机制来
+发现它们,使用配置访问来发现和识别设备,并读取和测量它们的BAR。然而,如果ACPI为它们
+提供电源管理或热插拔功能,或者如果设备有由平台中断控制器连接的INTx中断,需要一个_PRT
+来描述这些连接,这种情况下ACPI可以描述PCI设备。
+
+ACPI资源描述是通过ACPI命名空间中设备的_CRS对象完成的[2]。_CRS就像一个通用的PCI BAR:
+操作系统可以读取_CRS并找出正在消耗的资源,即使它没有该设备的驱动程序[3]。这一点很重要,
+因为它意味着一个旧的操作系统可以正确地工作,即使是在操作系统不知道的新设备的系统上。新设
+备可能什么都不做,但操作系统至少可以确保没有资源与它们冲突。
+
+像MCFG、HPET、ECDT等静态表,不是保留地址空间的机制。静态表是在操作系统在启动初期且在它
+能够解析ACPI命名空间之前需要知道的东西。如果定义了一个新的表,即使旧的操作系统忽略了这
+个表,它也需要正常运行。_CRS允许这样做,因为它是通用的,可以被旧的操作系统解析;而静态表
+则不允许。
+
+如果操作系统要管理一个通过ACPI描述的不可发现的设备,该设备将有一个特定的_HID/_CID,以
+告诉操作系统与之绑定的驱动程序,并且_CRS告诉操作系统和驱动程序该设备的寄存器在哪里。
+
+PCI主桥是PNP0A03或PNP0A08设备。它们的_CRS应该描述它们所消耗的所有地址空间。这包括它
+们转发到PCI总线上的所有窗口,以及不转发到PCI的主桥本身的寄存器。主桥的寄存器包括次要/下
+级总线寄存器,决定了桥下面的总线范围,窗口寄存器描述了桥洞,等等。这些都是设备相关的,非
+架构相关的东西,所以PNP0A03/PNP0A08驱动可以管理它们的唯一方法是通过_PRS/_CRS/_SRS,
+它包含了特定于设备的细节。主桥寄存器也包括ECAM空间,因为它是由主桥消耗的。
+
+ACPI定义了一个Consumer/Producer位来区分桥寄存器(“Consumer”下文译作消费者)和
+桥洞(“Producer”下文译作生产者)[4, 5],但是早期的BIOS没有正确使用这个位。其结果
+是,目前的ACPI规范只为扩展地址空间描述符定义了消费者/生产者;在旧的QWord/Word/Word地
+址空间描述符中,该位应该被忽略。因此,操作系统必须假定所有的QWord/Word/Word描述符都是
+窗口。
+
+在增加扩展地址空间描述符之前,消费者/生产者的失败意味着没有办法描述PNP0A03/PNP0A08设
+备本身的桥寄存器。解决办法是在PNP0C02捕捉器中描述桥寄存器(包括ECAM空间)[6]。
+除了ECAM之外,桥寄存器空间反正是特定于设备的,所以通用的PNP0A03/PNP0A08驱动程
+序(pci_root.c)没有必要了解它。
+
+新的架构应该能够在PNP0A03设备中使用“消费者”扩展地址空间描述符,用于桥寄存器,包括
+ECAM,尽管对[6]的严格解释可能禁止这样做。旧的x86和ia64内核假定所有的地址空间描述
+符,包括“消费者”扩展地址空间的描述符,都是窗口,所以在这些架构上以这种方式描述桥寄
+存器是不安全的。
+
+PNP0C02“主板”设备基本上是万能的。除了“不要将这些资源用于其他用途”之外,没有其他的编
+程模型。因此,PNP0C02 _CRS应该声明ACPI命名空间中(1)没有被_CRS声明的任何其他设备对
+象的地址空间,(2)不应该被OS分配给其他东西。
+
+除非有一个标准的固件接口用于配置访问,例如ia64 SAL接口[7],否则PCIe规范要求使用增强
+型配置访问方法(ECAM)。主桥消耗ECAM内存地址空间并将内存访问转换为PCI配置访问。该规范
+定义了ECAM地址空间的布局和功能;只有地址空间的基础是特定于设备的。ACPI操作系统从静态
+MCFG表或PNP0A03设备中的_CBA方法中了解基础地址。
+
+MCFG表必须描述非热插拔主桥的ECAM空间[8]。由于MCFG是一个静态表,不能通过热插拔更新,
+PNP0A03设备中的_CBA方法描述了可热插拔主桥的ECAM空间[9]。请注意,对于MCFG和_CBA,
+基址总是对应于总线0,即使桥器下面的总线范围(通过_CRS报告)不从0开始。
+
+
+[1] ACPI 6.2, sec 6.1:
+    对于任何在非枚举类型的总线上的设备(例如,ISA总线),OSPM会枚举设备的标识符,ACPI
+    系统固件必须为每个设备提供一个_HID对象...以使OSPM能够做到这一点。
+
+[2] ACPI 6.2, sec 3.7:
+    操作系统枚举主板设备时,只需通过读取ACPI命名空间来寻找具有硬件ID的设备。
+
+    ACPI枚举的每个设备都包括ACPI命名空间中ACPI定义的对象,该对象报告设备可能占用的硬
+    件资源[_PRS],报告设备当前使用的资源[_CRS]的对象,以及配置这些资源的对象[_SRS]。
+    这些信息被即插即用操作系统(OSPM)用来配置设备。
+
+[3] ACPI 6.2, sec 6.2:
+    OSPM使用设备配置对象来配置通过ACPI列举的设备的硬件资源。设备配置对象提供了关于当前
+    和可能的资源需求的信息,共享资源之间的关系,以及配置硬件资源的方法。
+
+    当OSPM枚举一个设备时,它调用_PRS来确定该设备的资源需求。它也可以调用_CRS来找到该设
+    备的当前资源设置。利用这些信息,即插即用系统决定设备应该消耗什么资源,并通过调用设备
+    的_SRS控制方法来设置这些资源。
+
+    在ACPI中,设备可以消耗资源(例如,传统的键盘),提供资源(例如,一个专有的PCI桥),
+    或者两者都做。除非另有规定,设备的资源被假定为来自设备层次结构中设备上方最近的匹配资
+    源。
+
+[4] ACPI 6.2, sec 6.4.3.5.1, 2, 3, 4:
+    QWord/DWord/Word 地址空间描述符 (.1, .2, .3)
+      常规标志: Bit [0] 被忽略。
+
+    扩展地址空间描述符 (.4)
+      常规标志: Bit [0] 消费者/生产者:
+
+        * 1 – 这个设备消费这个资源
+        * 0 – 该设备生产和消费该资源
+
+[5] ACPI 6.2, sec 19.6.43:
+    ResourceUsage指定内存范围是由这个设备(ResourceConsumer)消费还是传递给子设备
+    (ResourceProducer)。如果没有指定,那么就假定是ResourceConsumer。
+
+[6] PCI Firmware 3.2, sec 4.1.2:
+    如果操作系统不能原生的懂得保留MMCFG区域,MMCFG区域必须由固件保留。在MCFG表中或通
+    过_CBA方法(见第4.1.3节)报告的地址范围必须通过声明主板资源来保留。对于大多数系统,
+    主板资源将出现在ACPI命名空间的根部(在_SB下),在一个节点的_HID为EISAID(PNP0C0
+    2),在这种情况下的资源不应该要求在根PCI总线的_CRS。这些资源可以选择在Int15 E820
+    或EFIGetMemoryMap中作为保留内存返回,但必须始终通过ACPI作为主板资源报告。
+
+[7] PCI Express 4.0, sec 7.2.2:
+    对于PC兼容的系统,或者没有实现允许访问配置空间的处理器架构特定固件接口标准的系统,需
+    要使用本节中定义的ECAM。
+
+[8] PCI Firmware 3.2, sec 4.1.2:
+    MCFG表是一个ACPI表,用于沟通的基础地址对应的非热的可移动的PCI段组范围内的PCI段组在
+    启动时提供给操作系统。这对PC兼容系统来说是必需的。
+
+    MCFG表仅用于沟通在启动时系统可用的PCI段组对应的基址。
+
+[9] PCI Firmware 3.2, sec 4.1.3:
+    _CBA (Memory mapped Configuration Base Address) 控制方法是一个可选的ACPI对
+    象,用于返回热插拔主桥的64位内存映射的配置基址。_CBA 返回的基址是与处理器相关的地址。
+    _CBA 控制方法被评估为一个整数。
+
+    这个控制方法出现在主桥对象下。当_CBA方法出现在一个活动的主桥对象下时,操作系统会评
+    估这个结构,以确定内存映射的配置基址,对应于_CRS方法中指定的总线编号范围的PCI段组。
+    一个包含_CBA方法的ACPI命名空间对象也必须包含一个相应的_SEG方法。
index 16acb2b..cbeb33c 100644 (file)
@@ -10,9 +10,6 @@
 :校译:
 
 
-
-.. _cn_PCI_index.rst:
-
 ===================
 Linux PCI总线子系统
 ===================
@@ -26,12 +23,12 @@ Linux PCI总线子系统
    pci-iov-howto
    msi-howto
    sysfs-pci
+   acpi-info
 
 
 Todolist:
 
-   acpi-info
-   pci-error-recovery
-   pcieaer-howto
-   endpoint/index
-   boot-interrupts
+* pci-error-recovery
+* pcieaer-howto
+* endpoint/index
+* boot-interrupts
index d20949e..e679cbc 100644 (file)
@@ -6,10 +6,10 @@
 
  吴想成 Wu XiangCheng <bobwxc@email.cn>
 
-Linux内核5.x版本 <http://kernel.org/>
+Linux内核6.x版本 <http://kernel.org/>
 =========================================
 
-以下是Linux版本5的发行注记。仔细阅读它们,
+以下是Linux版本6的发行注记。仔细阅读它们,
 它们会告诉你这些都是什么,解释如何安装内核,以及遇到问题时该如何做。
 
 什么是Linux?
@@ -61,27 +61,27 @@ Linux内核5.x版本 <http://kernel.org/>
  - 如果您要安装完整的源代码,请把内核tar档案包放在您有权限的目录中(例如您
    的主目录)并将其解包::
 
-     xz -cd linux-5.x.tar.xz | tar xvf -
+     xz -cd linux-6.x.tar.xz | tar xvf -
 
    将“X”替换成最新内核的版本号。
 
    【不要】使用 /usr/src/linux 目录!这里有一组库头文件使用的内核头文件
    (通常是不完整的)。它们应该与库匹配,而不是被内核的变化搞得一团糟。
 
- - 您还可以通过打补丁在5.x版本之间升级。补丁以xz格式分发。要通过打补丁进行
-   安装,请获取所有较新的补丁文件,进入内核源代码(linux-5.x)的目录并
+ - 您还可以通过打补丁在6.x版本之间升级。补丁以xz格式分发。要通过打补丁进行
+   安装,请获取所有较新的补丁文件,进入内核源代码(linux-6.x)的目录并
    执行::
 
-     xz -cd ../patch-5.x.xz | patch -p1
+     xz -cd ../patch-6.x.xz | patch -p1
 
    请【按顺序】替换所有大于当前源代码树版本的“x”,这样就可以了。您可能想要
    删除备份文件(文件名类似xxx~ 或 xxx.orig),并确保没有失败的补丁(文件名
    类似xxx# 或 xxx.rej)。如果有,不是你就是我犯了错误。
 
-   与5.x内核的补丁不同,5.x.y内核(也称为稳定版内核)的补丁不是增量的,而是
-   直接应用于基本的5.x内核。例如,如果您的基本内核是5.0,并且希望应用5.0.3
-   补丁,则不应先应用5.0.1和5.0.2的补丁。类似地,如果您运行的是5.0.2内核,
-   并且希望跳转到5.0.3,那么在应用5.0.3补丁之前,必须首先撤销5.0.2补丁
+   与6.x内核的补丁不同,6.x.y内核(也称为稳定版内核)的补丁不是增量的,而是
+   直接应用于基本的6.x内核。例如,如果您的基本内核是6.0,并且希望应用6.0.3
+   补丁,则不应先应用6.0.1和6.0.2的补丁。类似地,如果您运行的是6.0.2内核,
+   并且希望跳转到6.0.3,那么在应用6.0.3补丁之前,必须首先撤销6.0.2补丁
    (即patch -R)。更多关于这方面的内容,请阅读
    :ref:`Documentation/process/applying-patches.rst <applying_patches>` 。
 
@@ -103,7 +103,7 @@ Linux内核5.x版本 <http://kernel.org/>
 软件要求
 ---------
 
-   编译和运行5.x内核需要各种软件包的最新版本。请参考
+   编译和运行6.x内核需要各种软件包的最新版本。请参考
    :ref:`Documentation/process/changes.rst <changes>`
    来了解最低版本要求以及如何升级软件包。请注意,使用过旧版本的这些包可能会
    导致很难追踪的间接错误,因此不要以为在生成或操作过程中出现明显问题时可以
@@ -116,12 +116,12 @@ Linux内核5.x版本 <http://kernel.org/>
    ``make O=output/dir`` 选项可以为输出文件(包括 .config)指定备用位置。
    例如::
 
-     kernel source code: /usr/src/linux-5.x
+     kernel source code: /usr/src/linux-6.x
      build directory:    /home/name/build/kernel
 
    要配置和构建内核,请使用::
 
-     cd /usr/src/linux-5.x
+     cd /usr/src/linux-6.x
      make O=/home/name/build/kernel menuconfig
      make O=/home/name/build/kernel
      sudo make O=/home/name/build/kernel modules_install install
@@ -227,8 +227,6 @@ Linux内核5.x版本 <http://kernel.org/>
  - 确保您至少有gcc 5.1可用。
    有关更多信息,请参阅 :ref:`Documentation/process/changes.rst <changes>` 。
 
-   请注意,您仍然可以使用此内核运行a.out用户程序。
-
  - 执行 ``make`` 来创建压缩内核映像。如果您安装了lilo以适配内核makefile,
    那么也可以进行 ``make install`` ,但是您可能需要先检查特定的lilo设置。
 
@@ -282,67 +280,12 @@ Linux内核5.x版本 <http://kernel.org/>
 若遇到问题
 -----------
 
- - 如果您发现了一些可能由于内核缺陷所导致的问题,请检查MAINTAINERS(维护者)
-   文件看看是否有人与令您遇到麻烦的内核部分相关。如果无人在此列出,那么第二
-   个最好的方案就是把它们发给我(torvalds@linux-foundation.org),也可能发送
-   到任何其他相关的邮件列表或新闻组。
-
- - 在所有的缺陷报告中,【请】告诉我们您在说什么内核,如何复现问题,以及您的
-   设置是什么的(使用您的常识)。如果问题是新的,请告诉我;如果问题是旧的,
-   请尝试告诉我您什么时候首次注意到它。
-
- - 如果缺陷导致如下消息::
-
-     unable to handle kernel paging request at address C0000010
-     Oops: 0002
-     EIP:   0010:XXXXXXXX
-     eax: xxxxxxxx   ebx: xxxxxxxx   ecx: xxxxxxxx   edx: xxxxxxxx
-     esi: xxxxxxxx   edi: xxxxxxxx   ebp: xxxxxxxx
-     ds: xxxx  es: xxxx  fs: xxxx  gs: xxxx
-     Pid: xx, process nr: xx
-     xx xx xx xx xx xx xx xx xx xx
-
-   或者类似的内核调试信息显示在屏幕上或在系统日志里,请【如实】复制它。
-   可能对你来说转储(dump)看起来不可理解,但它确实包含可能有助于调试问题的
-   信息。转储上方的文本也很重要:它说明了内核转储代码的原因(在上面的示例中,
-   是由于内核指针错误)。更多关于如何理解转储的信息,请参见
-   Documentation/admin-guide/bug-hunting.rst。
-
- - 如果使用 CONFIG_KALLSYMS 编译内核,则可以按原样发送转储,否则必须使用
-   ``ksymoops`` 程序来理解转储(但通常首选使用CONFIG_KALLSYMS编译)。
-   此实用程序可从
-   https://www.kernel.org/pub/linux/utils/kernel/ksymoops/ 下载。
-   或者,您可以手动执行转储查找:
-
- - 在调试像上面这样的转储时,如果您可以查找EIP值的含义,这将非常有帮助。
-   十六进制值本身对我或其他任何人都没有太大帮助:它会取决于特定的内核设置。
-   您应该做的是从EIP行获取十六进制值(忽略 ``0010:`` ),然后在内核名字列表
-   中查找它,以查看哪个内核函数包含有问题的地址。
-
-   要找到内核函数名,您需要找到与显示症状的内核相关联的系统二进制文件。就是
-   文件“linux/vmlinux”。要提取名字列表并将其与内核崩溃中的EIP进行匹配,
-   请执行::
-
-     nm vmlinux | sort | less
-
-   这将为您提供一个按升序排序的内核地址列表,从中很容易找到包含有问题的地址
-   的函数。请注意,内核调试消息提供的地址不一定与函数地址完全匹配(事实上,
-   这是不可能的),因此您不能只“grep”列表:不过列表将为您提供每个内核函数
-   的起点,因此通过查找起始地址低于你正在搜索的地址,但后一个函数的高于的
-   函数,你会找到您想要的。实际上,在您的问题报告中加入一些“上下文”可能是
-   一个好主意,给出相关的上下几行。
-
-   如果您由于某些原因无法完成上述操作(如您使用预编译的内核映像或类似的映像),
-   请尽可能多地告诉我您的相关设置信息,这会有所帮助。有关详细信息请阅读
-   ‘Documentation/admin-guide/reporting-issues.rst’。
-
- - 或者,您可以在正在运行的内核上使用gdb(只读的;即不能更改值或设置断点)。
-   为此,请首先使用-g编译内核;适当地编辑arch/x86/Makefile,然后执行 ``make
-   clean`` 。您还需要启用CONFIG_PROC_FS(通过 ``make config`` )。
-
-   使用新内核重新启动后,执行 ``gdb vmlinux /proc/kcore`` 。现在可以使用所有
-   普通的gdb命令。查找系统崩溃点的命令是 ``l *0xXXXXXXXX`` (将xxx替换为EIP
-   值)。
-
-   用gdb无法调试一个当前未运行的内核是由于gdb(错误地)忽略了编译内核的起始
-   偏移量。
+如果您发现了一些可能由于内核缺陷所导致的问题,请参阅:
+Documentation/translations/zh_CN/admin-guide/reporting-issues.rst 。
+
+想要理解内核错误报告,请参阅:
+Documentation/translations/zh_CN/admin-guide/bug-hunting.rst 。
+
+更多用GDB调试内核的信息,请参阅:
+Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst
+和 Documentation/dev-tools/kgdb.rst 。
diff --git a/Documentation/translations/zh_CN/admin-guide/bootconfig.rst b/Documentation/translations/zh_CN/admin-guide/bootconfig.rst
new file mode 100644 (file)
index 0000000..072d17f
--- /dev/null
@@ -0,0 +1,293 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/admin-guide/bootconfig.rst
+
+:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
+
+========
+引导配置
+========
+
+:作者: Masami Hiramatsu <mhiramat@kernel.org>
+
+概述
+====
+
+引导配置扩展了现有的内核命令行,以一种更有效率的方式在引导内核时进一步支持
+键值数据。这允许管理员传递一份结构化关键字的配置文件。
+
+配置文件语法
+============
+
+引导配置文件的语法采用非常简单的键值结构。每个关键字由点连接的单词组成,键
+和值由 ``=`` 连接。值以分号( ``;`` )或换行符( ``\n`` )结尾。数组值中每
+个元素由逗号( ``,`` )分隔。::
+
+  KEY[.WORD[...]] = VALUE[, VALUE2[...]][;]
+
+与内核命令行语法不同,逗号和 ``=`` 周围允许有空格。
+
+关键字只允许包含字母、数字、连字符( ``-`` )和下划线( ``_`` )。值可包含
+可打印字符和空格,但分号( ``;`` )、换行符( ``\n`` )、逗号( ``,`` )、
+井号( ``#`` )和右大括号( ``}`` )等分隔符除外。
+
+如果你需要在值中使用这些分隔符,可以用双引号( ``"VALUE"`` )或单引号
+( ``'VALUE'`` )括起来。注意,引号无法转义。
+
+键的值可以为空或不存在。这些键用于检查该键是否存在(类似布尔值)。
+
+键值语法
+--------
+
+引导配置文件语法允许用户通过大括号合并键名部分相同的关键字。例如::
+
+ foo.bar.baz = value1
+ foo.bar.qux.quux = value2
+
+也可以写成::
+
+ foo.bar {
+    baz = value1
+    qux.quux = value2
+ }
+
+或者更紧凑一些,写成::
+
+ foo.bar { baz = value1; qux.quux = value2 }
+
+在这两种样式中,引导解析时相同的关键字都会自动合并。因此可以追加类似的树或
+键值。
+
+相同关键字的值
+--------------
+
+禁止两个或多个值或数组共享同一个关键字。例如::
+
+ foo = bar, baz
+ foo = qux  # !错误! 我们不可以重定义相同的关键字
+
+如果你想要更新值,必须显式使用覆盖操作符 ``:=`` 。例如::
+
+ foo = bar, baz
+ foo := qux
+
+这样 ``foo`` 关键字的值就变成了 ``qux`` 。这对于通过添加(部分)自定义引导
+配置来覆盖默认值非常有用,免于解析默认引导配置。
+
+如果你想对现有关键字追加值作为数组成员,可以使用 ``+=`` 操作符。例如::
+
+ foo = bar, baz
+ foo += qux
+
+这样, ``foo`` 关键字就同时拥有了 ``bar`` , ``baz`` 和 ``qux`` 。
+
+此外,父关键字下可同时存在值和子关键字。
+例如,下列配置是可行的。::
+
+ foo = value1
+ foo.bar = value2
+ foo := value3 # 这会更新foo的值。
+
+注意,裸值不能直接放进结构化关键字中,必须在大括号外定义它。例如::
+
+ foo {
+     bar = value1
+     bar {
+         baz = value2
+         qux = value3
+     }
+ }
+
+同时,关键字下值节点的顺序是固定的。如果值和子关键字同时存在,值永远是该关
+键字的第一个子节点。因此如果用户先指定子关键字,如::
+
+ foo.bar = value1
+ foo = value2
+
+则在程序(和/proc/bootconfig)中,它会按如下显示::
+
+ foo = value2
+ foo.bar = value1
+
+注释
+----
+
+配置语法接受shell脚本风格的注释。注释以井号( ``#`` )开始,到换行符
+( ``\n`` )结束。
+
+::
+
+ # comment line
+ foo = value # value is set to foo.
+ bar = 1, # 1st element
+       2, # 2nd element
+       3  # 3rd element
+
+会被解析为::
+
+ foo = value
+ bar = 1, 2, 3
+
+注意你不能把注释放在值和分隔符( ``,`` 或 ``;`` )之间。如下配置语法是错误的::
+
+ key = 1 # comment
+       ,2
+
+
+/proc/bootconfig
+================
+
+/proc/bootconfig是引导配置的用户空间接口。与/proc/cmdline不同,此文件内容以
+键值列表样式显示。
+每个键值对一行,样式如下::
+
+ KEY[.WORDS...] = "[VALUE]"[,"VALUE2"...]
+
+
+用引导配置引导内核
+==================
+
+用引导配置引导内核有两种方法:将引导配置附加到initrd镜像或直接嵌入内核中。
+
+*initrd: initial RAM disk,初始内存磁盘*
+
+将引导配置附加到initrd
+----------------------
+
+由于默认情况下引导配置文件是用initrd加载的,因此它将被添加到initrd(initramfs)
+镜像文件的末尾,其中包含填充、大小、校验值和12字节幻数,如下所示::
+
+ [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
+
+大小和校验值为小端序存放的32位无符号值。
+
+当引导配置被加到initrd镜像时,整个文件大小会对齐到4字节。空字符( ``\0`` )
+会填补对齐空隙。因此 ``size`` 就是引导配置文件的长度+填充的字节。
+
+Linux内核在内存中解码initrd镜像的最后部分以获取引导配置数据。由于这种“背负式”
+的方法,只要引导加载器传递了正确的initrd文件大小,就无需更改或更新引导加载器
+和内核镜像本身。如果引导加载器意外传递了更长的大小,内核将无法找到引导配置数
+据。
+
+Linux内核在tools/bootconfig下提供了 ``bootconfig`` 命令来完成此操作,管理员
+可以用它从initrd镜像中删除或追加配置文件。你可以用以下命令来构建它::
+
+ # make -C tools/bootconfig
+
+要向initrd镜像添加你的引导配置文件,请按如下命令操作(旧数据会自动移除)::
+
+ # tools/bootconfig/bootconfig -a your-config /boot/initrd.img-X.Y.Z
+
+要从镜像中移除配置,可以使用-d选项::
+
+ # tools/bootconfig/bootconfig -d /boot/initrd.img-X.Y.Z
+
+然后在内核命令行上添加 ``bootconfig`` 告诉内核去initrd文件末尾寻找内核配置。
+
+将引导配置嵌入内核
+------------------
+
+如果你不能使用initrd,也可以通过Kconfig选项将引导配置文件嵌入内核中。在此情
+况下,你需要用以下选项重新编译内核::
+
+ CONFIG_BOOT_CONFIG_EMBED=y
+ CONFIG_BOOT_CONFIG_EMBED_FILE="/引导配置/文件/的/路径"
+
+``CONFIG_BOOT_CONFIG_EMBED_FILE`` 需要从源码树或对象树开始的引导配置文件的
+绝对/相对路径。内核会将其嵌入作为默认引导配置。
+
+与将引导配置附加到initrd一样,你也需要在内核命令行上添加 ``bootconfig`` 告诉
+内核去启用内嵌的引导配置。
+
+注意,即使你已经设置了此选项,仍可用附加到initrd的其他引导配置覆盖内嵌的引导
+配置。
+
+通过引导配置传递内核参数
+========================
+
+除了内核命令行,引导配置也可以用于传递内核参数。所有 ``kernel`` 关键字下的键
+值对都将直接传递给内核命令行。此外, ``init`` 下的键值对将通过命令行传递给
+init进程。参数按以下顺序与用户给定的内核命令行字符串相连,因此命令行参数可以
+覆盖引导配置参数(这取决于子系统如何处理参数,但通常前面的参数将被后面的参数
+覆盖)::
+
+ [bootconfig params][cmdline params] -- [bootconfig init params][cmdline init params]
+
+如果引导配置文件给出的kernel/init参数是::
+
+ kernel {
+   root = 01234567-89ab-cdef-0123-456789abcd
+ }
+ init {
+  splash
+ }
+
+这将被复制到内核命令行字符串中,如下所示::
+
+ root="01234567-89ab-cdef-0123-456789abcd" -- splash
+
+如果用户给出的其他命令行是::
+
+ ro bootconfig -- quiet
+
+则最后的内核命令行如下::
+
+ root="01234567-89ab-cdef-0123-456789abcd" ro bootconfig -- splash quiet
+
+
+配置文件的限制
+==============
+
+当前最大的配置大小是32KB,关键字总数(不是键值条目)必须少于1024个节点。
+注意:这不是条目数而是节点数,条目必须消耗超过2个节点(一个关键字和一个值)。
+所以从理论上讲最多512个键值对。如果关键字平均包含3个单词,则可有256个键值对。
+在大多数情况下,配置项的数量将少于100个条目,小于8KB,因此这应该足够了。如果
+节点数超过1024,解析器将返回错误,即使文件大小小于32KB。(请注意,此最大尺寸
+不包括填充的空字符。)
+无论如何,因为 ``bootconfig`` 命令在附加启动配置到initrd映像时会验证它,用户
+可以在引导之前注意到它。
+
+
+引导配置API
+===========
+
+用户可以查询或遍历键值对,也可以查找(前缀)根关键字节点,并在查找该节点下的
+键值。
+
+如果您有一个关键字字符串,则可以直接使用 xbc_find_value() 查询该键的值。如果
+你想知道引导配置里有哪些关键字,可以使用 xbc_for_each_key_value() 迭代键值对。
+请注意,您需要使用 xbc_array_for_each_value() 访问数组的值,例如::
+
+ vnode = NULL;
+ xbc_find_value("key.word", &vnode);
+ if (vnode && xbc_node_is_array(vnode))
+    xbc_array_for_each_value(vnode, value) {
+      printk("%s ", value);
+    }
+
+如果您想查找具有前缀字符串的键,可以使用 xbc_find_node() 通过前缀字符串查找
+节点,然后用 xbc_node_for_each_key_value() 迭代前缀节点下的键。
+
+但最典型的用法是获取前缀下的命名值或前缀下的命名数组,例如::
+
+ root = xbc_find_node("key.prefix");
+ value = xbc_node_find_value(root, "option", &vnode);
+ ...
+ xbc_node_for_each_array_value(root, "array-option", value, anode) {
+    ...
+ }
+
+这将访问值“key.prefix.option”的值和“key.prefix.array-option”的数组。
+
+锁是不需要的,因为在初始化之后配置只读。如果需要修改,必须复制所有数据和关键字。
+
+
+函数与结构体
+============
+
+相关定义的kernel-doc参见:
+
+ - include/linux/bootconfig.h
+ - lib/bootconfig.c
index 2f6970d..ac2960d 100644 (file)
@@ -63,6 +63,7 @@ Todolist:
 .. toctree::
    :maxdepth: 1
 
+   bootconfig
    clearing-warn-once
    cpu-load
    cputopology
@@ -80,7 +81,6 @@ Todolist:
 *   binderfs
 *   binfmt-misc
 *   blockdev/index
-*   bootconfig
 *   braille-console
 *   btmrvl
 *   cgroup-v1/index
diff --git a/Documentation/translations/zh_CN/core-api/circular-buffers.rst b/Documentation/translations/zh_CN/core-api/circular-buffers.rst
new file mode 100644 (file)
index 0000000..694ad8e
--- /dev/null
@@ -0,0 +1,210 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/circular-buffers.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+ 吴想成 Wu Xiangcheng <bobwxc@email.cn>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+==========
+环形缓冲区
+==========
+
+:作者: David Howells <dhowells@redhat.com>
+:作者: Paul E. McKenney <paulmck@linux.ibm.com>
+
+
+Linux 提供了许多可用于实现循环缓冲的特性。有两组这样的特性:
+
+ (1) 用于确定2次方大小的缓冲区信息的便利函数。
+
+ (2) 可以代替缓冲区中对象的生产者和消费者共享锁的内存屏障。
+
+如下所述,要使用这些设施,只需要一个生产者和一个消费者。可以通过序列化来处理多个
+生产者,并通过序列化来处理多个消费者。
+
+.. Contents:
+
+ (*) 什么是环形缓冲区?
+
+ (*) 测量2次幂缓冲区
+
+ (*) 内存屏障与环形缓冲区的结合使用
+     - 生产者
+     - 消费者
+
+ (*) 延伸阅读
+
+
+
+什么是环形缓冲区?
+==================
+
+首先,什么是环形缓冲区?环形缓冲区是具有固定的有限大小的缓冲区,它有两个索引:
+
+ (1) 'head'索引 - 生产者将元素插入缓冲区的位置。
+
+ (2) 'tail'索引 - 消费者在缓冲区中找到下一个元素的位置。
+
+通常,当tail指针等于head指针时,表明缓冲区是空的;而当head指针比tail指针少一个时,
+表明缓冲区是满的。
+
+添加元素时,递增head索引;删除元素时,递增tail索引。tail索引不应该跳过head索引,
+两个索引在到达缓冲区末端时都应该被赋值为0,从而允许海量的数据流过缓冲区。
+
+通常情况下,元素都有相同的单元大小,但这并不是使用以下技术的严格要求。如果要在缓
+冲区中包含多个元素或可变大小的元素,则索引可以增加超过1,前提是两个索引都没有超过
+另一个。然而,实现者必须小心,因为超过一个单位大小的区域可能会覆盖缓冲区的末端并
+且缓冲区会被分成两段。
+
+测量2次幂缓冲区
+===============
+
+计算任意大小的环形缓冲区的占用或剩余容量通常是一个费时的操作,需要使用模(除法)
+指令。但是如果缓冲区的大小为2次幂,则可以使用更快的按位与指令代替。
+
+Linux提供了一组用于处理2次幂环形缓冲区的宏。可以通过以下方式使用::
+
+       #include <linux/circ_buf.h>
+
+这些宏包括:
+
+ (#) 测量缓冲区的剩余容量::
+
+       CIRC_SPACE(head_index, tail_index, buffer_size);
+
+     返回缓冲区[1]中可插入元素的剩余空间大小。
+
+
+ (#) 测量缓冲区中的最大连续立即可用空间::
+
+       CIRC_SPACE_TO_END(head_index, tail_index, buffer_size);
+
+     返回缓冲区[1]中剩余的连续空间的大小,元素可以立即插入其中,而不必绕回到缓冲
+     区的开头。
+
+
+ (#) 测量缓冲区的使用数::
+
+       CIRC_CNT(head_index, tail_index, buffer_size);
+
+     返回当前占用缓冲区[2]的元素数量。
+
+
+ (#) 测量缓冲区的连续使用数::
+
+       CIRC_CNT_TO_END(head_index, tail_index, buffer_size);
+
+     返回可以从缓冲区中提取的连续元素[2]的数量,而不必绕回到缓冲区的开头。
+
+这里的每一个宏名义上都会返回一个介于0和buffer_size-1之间的值,但是:
+
+ (1) CIRC_SPACE*()是为了在生产者中使用。对生产者来说,它们将返回一个下限,因为生
+     产者控制着head索引,但消费者可能仍然在另一个CPU上耗尽缓冲区并移动tail索引。
+
+     对消费者来说,它将显示一个上限,因为生产者可能正忙于耗尽空间。
+
+ (2) CIRC_CNT*()是为了在消费者中使用。对消费者来说,它们将返回一个下限,因为消费
+     者控制着tail索引,但生产者可能仍然在另一个CPU上填充缓冲区并移动head索引。
+
+     对于生产者,它将显示一个上限,因为消费者可能正忙于清空缓冲区。
+
+ (3) 对于第三方来说,生产者和消费者对索引的写入顺序是无法保证的,因为它们是独立的,
+     而且可能是在不同的CPU上进行的,所以在这种情况下的结果只是一种猜测,甚至可能
+     是错误的。
+
+内存屏障与环形缓冲区的结合使用
+==============================
+
+通过将内存屏障与环形缓冲区结合使用,可以避免以下需求:
+
+ (1) 使用单个锁来控制对缓冲区两端的访问,从而允许同时填充和清空缓冲区;以及
+
+ (2) 使用原子计数器操作。
+
+这有两个方面:填充缓冲区的生产者和清空缓冲区的消费者。在任何时候,只应有一个生产
+者在填充缓冲区,同样的也只应有一个消费者在清空缓冲区,但双方可以同时操作。
+
+
+生产者
+------
+
+生产者看起来像这样::
+
+       spin_lock(&producer_lock);
+
+       unsigned long head = buffer->head;
+       /* spin_unlock()和下一个spin_lock()提供必要的排序。 */
+       unsigned long tail = READ_ONCE(buffer->tail);
+
+       if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
+               /* 添加一个元素到缓冲区 */
+               struct item *item = buffer[head];
+
+               produce_item(item);
+
+               smp_store_release(buffer->head,
+                                 (head + 1) & (buffer->size - 1));
+
+               /* wake_up()将确保在唤醒任何人之前提交head */
+               wake_up(consumer);
+       }
+
+       spin_unlock(&producer_lock);
+
+这将表明CPU必须在head索引使其对消费者可用之前写入新项目的内容,同时CPU必须在唤醒
+消费者之前写入修改后的head索引。
+
+请注意,wake_up()并不保证任何形式的屏障,除非确实唤醒了某些东西。因此我们不能依靠
+它来进行排序。但是数组中始终有一个元素留空,因此生产者必须产生两个元素,然后才可
+能破坏消费者当前正在读取的元素。同时,消费者连续调用之间成对的解锁-加锁提供了索引
+读取(指示消费者已清空给定元素)和生产者对该相同元素的写入之间的必要顺序。
+
+
+消费者
+------
+
+消费者看起来像这样::
+
+       spin_lock(&consumer_lock);
+
+       /* 读取该索引处的内容之前,先读取索引 */
+       unsigned long head = smp_load_acquire(buffer->head);
+       unsigned long tail = buffer->tail;
+
+       if (CIRC_CNT(head, tail, buffer->size) >= 1) {
+
+               /* 从缓冲区中提取一个元素 */
+               struct item *item = buffer[tail];
+
+               consume_item(item);
+
+               /* 在递增tail之前完成对描述符的读取。 */
+               smp_store_release(buffer->tail,
+                                 (tail + 1) & (buffer->size - 1));
+       }
+
+       spin_unlock(&consumer_lock);
+
+这表明CPU在读取新元素之前确保索引是最新的,然后在写入新的尾指针之前应确保CPU已完
+成读取该元素,这将擦除该元素。
+
+请注意,使用READ_ONCE()和smp_load_acquire()来读取反向(head)索引。这可以防止编译
+器丢弃并重新加载其缓存值。如果您能确定反向(head)索引将仅使用一次,则这不是必须
+的。smp_load_acquire()还可以强制CPU对后续的内存引用进行排序。类似地,两种算法都使
+用smp_store_release()来写入线程的索引。这记录了我们正在写入可以并发读取的内容的事
+实,以防止编译器破坏存储,并强制对以前的访问进行排序。
+
+
+延伸阅读
+========
+
+关于Linux的内存屏障设施的描述,请查看Documentation/memory-barriers.txt。
diff --git a/Documentation/translations/zh_CN/core-api/generic-radix-tree.rst b/Documentation/translations/zh_CN/core-api/generic-radix-tree.rst
new file mode 100644 (file)
index 0000000..eacd1d2
--- /dev/null
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/generic-radix-tree.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+===================
+通用基数树/稀疏数组
+===================
+
+通用基数树/稀疏数组的相关内容请见include/linux/generic-radix-tree.h文件中的
+“DOC: Generic radix trees/sparse arrays”。
+
+通用基数树函数
+--------------
+
+该API在以下内核代码中:
+
+include/linux/generic-radix-tree.h
diff --git a/Documentation/translations/zh_CN/core-api/idr.rst b/Documentation/translations/zh_CN/core-api/idr.rst
new file mode 100644 (file)
index 0000000..97a16e7
--- /dev/null
@@ -0,0 +1,80 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/idr.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+ 吴想成 Wu Xiangcheng <bobwxc@email.cn>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+======
+ID分配
+======
+
+:作者: Matthew Wilcox
+
+概述
+====
+
+要解决的一个常见问题是分配标识符(IDs);它通常是标识事物的数字。比如包括文件描述
+符、进程ID、网络协议中的数据包标识符、SCSI标记和设备实例编号。IDR和IDA为这个问题
+提供了一个合理的解决方案,以避免每个人都自创。IDR提供将ID映射到指针的能力,而IDA
+仅提供ID分配,因此内存效率更高。
+
+IDR接口已经被废弃,请使用 ``XArray`` 。
+
+IDR的用法
+=========
+
+首先初始化一个IDR,对于静态分配的IDR使用DEFINE_IDR(),或者对于动态分配的IDR使用
+idr_init()。
+
+您可以调用idr_alloc()来分配一个未使用的ID。通过调用idr_find()查询与该ID相关的指针,
+并通过调用idr_remove()释放该ID。
+
+如果需要更改与一个ID相关联的指针,可以调用idr_replace()。这样做的一个常见原因是通
+过将 ``NULL`` 指针传递给分配函数来保留ID;用保留的ID初始化对象,最后将初始化的对
+象插入IDR。
+
+一些用户需要分配大于 ``INT_MAX`` 的ID。到目前为止,所有这些用户都满足 ``UINT_MAX``
+的限制,他们使用idr_alloc_u32()。如果您需要超出u32的ID,我们将与您合作以满足您的
+需求。
+
+如果需要按顺序分配ID,可以使用idr_alloc_cyclic()。处理较大数量的ID时,IDR的效率会
+降低,所以使用这个函数会有一点代价。
+
+要对IDR使用的所有指针进行操作,您可以使用基于回调的idr_for_each()或迭代器样式的
+idr_for_each_entry()。您可能需要使用idr_for_each_entry_continue()来继续迭代。如果
+迭代器不符合您的需求,您也可以使用idr_get_next()。
+
+当使用完IDR后,您可以调用idr_destroy()来释放IDR占用的内存。这并不会释放IDR指向的
+对象;如果您想这样做,请使用其中一个迭代器来执行此操作。
+
+您可以使用idr_is_empty()来查看当前是否分配了任何ID。
+
+如果在从IDR分配一个新ID时需要带锁,您可能需要传递一组限制性的GFP标志,但这可能导
+致IDR无法分配内存。为了解决该问题,您可以在获取锁之前调用idr_preload(),然后在分
+配之后调用idr_preload_end()。
+
+IDR同步的相关内容请见include/linux/idr.h文件中的“DOC: idr sync”。
+
+IDA的用法
+=========
+
+IDA的用法的相关内容请见lib/idr.c文件中的“DOC: IDA description”。
+
+函数和数据结构
+==============
+
+该API在以下内核代码中:
+
+include/linux/idr.h
+
+lib/idr.c
index 8a94ad8..37756d2 100644 (file)
    assoc_array
    xarray
    rbtree
+   idr
+   circular-buffers
+   generic-radix-tree
+   packing
 
 Todolist:
 
 
 
-   idr
-   circular-buffers
-   generic-radix-tree
-   packing
    this_cpu_ops
    timekeeping
    errseq
diff --git a/Documentation/translations/zh_CN/core-api/packing.rst b/Documentation/translations/zh_CN/core-api/packing.rst
new file mode 100644 (file)
index 0000000..c0aab3a
--- /dev/null
@@ -0,0 +1,160 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/packing.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+ 吴想成 Wu Xiangcheng <bobwxc@email.cn>
+ 时奎亮 Alex Shi <alexs@kernel.org>
+
+========================
+通用的位域打包和解包函数
+========================
+
+问题陈述
+--------
+
+使用硬件时,必须在几种与其交互的方法之间进行选择。
+
+可以将指针映射到在硬件设备的内存区上精心设计的结构体,并将其字段作为结构成员(可
+能声明为位域)访问。但是由于CPU和硬件设备之间潜在的字节顺序不匹配,以这种方式编写
+代码会降低其可移植性。
+
+此外,必须密切注意将硬件文档中的寄存器定义转换为结构的位域索引。此外,一些硬件
+(通常是网络设备)倾向于以违反任何合理字边界(有时甚至是64位)的方式对其寄存器字
+段进行分组。这就造成了不得不在结构中定义寄存器字段的“高”和“低”部分的不便。
+
+结构域定义的更可靠的替代方法是通过移动适当数量的位来提取所需的字段。但这仍然不能
+防止字节顺序不匹配,除非所有内存访问都是逐字节执行的。此外,代码很容易变得杂乱无
+章,同时可能会在所需的许多位移操作中丢失一些高层次的想法。
+
+许多驱动程序采用了位移的方法,然后试图用定制的宏来减少杂乱无章的东西,但更多的时
+候,这些宏所采用的捷径依旧妨碍了代码真正的可移植性。
+
+解决方案
+--------
+
+该API涉及2个基本操作:
+
+  - 将一个CPU可使用的数字打包到内存缓冲区中(具有硬件约束/特殊性)。
+  - 将内存缓冲区(具有硬件约束/特殊性)解压缩为一个CPU可使用的数字。
+
+该API提供了对所述硬件约束和特殊性以及CPU字节序的抽象,因此这两者之间可能不匹配。
+
+这些API函数的基本单元是u64。从CPU的角度来看,位63总是意味着字节7的位偏移量7,尽管
+只是逻辑上的。问题是:我们将这个比特放在内存的什么位置?
+
+以下示例介绍了打包u64字段的内存布局。打包缓冲区中的字节偏移量始终默认为0,1...7。
+示例显示的是逻辑字节和位所在的位置。
+
+1. 通常情况下(无特殊性),我们会这样做:
+
+::
+
+  63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+  7                       6                       5                        4
+  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
+  3                       2                       1                        0
+
+也就是说,CPU可使用的u64的MSByte(7)位于内存偏移量0处,而u64的LSByte(0)位于内存偏移量7处。
+
+这对应于大多数人认为的“大端”,其中位i对应于数字2^i。这在代码注释中也称为“逻辑”符号。
+
+
+2. 如果设置了QUIRK_MSB_ON_THE_RIGHT,我们按如下方式操作:
+
+::
+
+  56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39
+  7                       6                        5                       4
+  24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7
+  3                       2                        1                       0
+
+也就是说,QUIRK_MSB_ON_THE_RIGHT不会影响字节定位,但会反转字节内的位偏移量。
+
+
+3. 如果设置了QUIRK_LITTLE_ENDIAN,我们按如下方式操作:
+
+::
+
+  39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56
+  4                       5                       6                       7
+  7  6  5  4  3  2  1  0  15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
+  0                       1                       2                       3
+
+因此,QUIRK_LITTLE_ENDIAN意味着在内存区域内,每个4字节的字的每个字节都被放置在与
+该字的边界相比的镜像位置。
+
+
+4. 如果设置了QUIRK_MSB_ON_THE_RIGHT和QUIRK_LITTLE_ENDIAN,我们这样做:
+
+::
+
+  32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
+  4                       5                       6                       7
+  0  1  2  3  4  5  6  7  8   9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+  0                       1                       2                       3
+
+
+5. 如果只设置了QUIRK_LSW32_IS_FIRST,我们这样做:
+
+::
+
+  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
+  3                       2                       1                        0
+  63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+  7                       6                       5                        4
+
+在这种情况下,8字节内存区域解释如下:前4字节对应最不重要的4字节的字,后4字节对应
+更重要的4字节的字。
+
+6. 如果设置了QUIRK_LSW32_IS_FIRST和QUIRK_MSB_ON_THE_RIGHT,我们这样做:
+
+::
+
+  24 25 26 27 28 29 30 31 16 17 18 19 20 21 22 23  8  9 10 11 12 13 14 15  0  1  2  3  4  5  6  7
+  3                       2                        1                       0
+  56 57 58 59 60 61 62 63 48 49 50 51 52 53 54 55 40 41 42 43 44 45 46 47 32 33 34 35 36 37 38 39
+  7                       6                        5                       4
+
+
+7. 如果设置了QUIRK_LSW32_IS_FIRST和QUIRK_LITTLE_ENDIAN,则如下所示:
+
+::
+
+  7  6  5  4  3  2  1  0  15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
+  0                       1                       2                       3
+  39 38 37 36 35 34 33 32 47 46 45 44 43 42 41 40 55 54 53 52 51 50 49 48 63 62 61 60 59 58 57 56
+  4                       5                       6                       7
+
+
+8. 如果设置了QUIRK_LSW32_IS_FIRST,QUIRK_LITTLE_ENDIAN和QUIRK_MSB_ON_THE_RIGHT,
+   则如下所示:
+
+::
+
+  0  1  2  3  4  5  6  7  8   9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+  0                       1                       2                       3
+  32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
+  4                       5                       6                       7
+
+
+我们总是认为我们的偏移量好像没有特殊性,然后在访问内存区域之前翻译它们。
+
+预期用途
+--------
+
+选择使用该API的驱动程序首先需要确定上述3种quirk组合(共8种)中的哪一种与硬件文档
+中描述的相匹配。然后,他们应该封装packing()函数,创建一个新的xxx_packing(),使用
+适当的QUIRK_* one-hot 位集合来调用它。
+
+packing()函数返回一个int类型的错误码,以防止程序员使用不正确的API。这些错误预计不
+会在运行时发生,因此xxx_packing()返回void并简单地接受这些错误是合理的。它可以选择
+转储栈或打印错误描述。
diff --git a/Documentation/translations/zh_CN/devicetree/changesets.rst b/Documentation/translations/zh_CN/devicetree/changesets.rst
new file mode 100644 (file)
index 0000000..2ace05f
--- /dev/null
@@ -0,0 +1,37 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/Devicetree/changesets.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+
+============
+设备树变更集
+============
+
+设备树变更集是一种方法,它允许人们以这样一种方式在实时树中使用变化,即要么使用全部的
+变化,要么不使用。如果在使用变更集的过程中发生错误,那么树将被回滚到之前的状态。一个
+变更集也可以在使用后被删除。
+
+当一个变更集被使用时,所有的改变在发出OF_RECONFIG通知器之前被一次性使用到树上。这是
+为了让接收者在收到通知时看到一个完整的、一致的树的状态。
+
+一个变化集的顺序如下。
+
+1. of_changeset_init() - 初始化一个变更集。
+
+2. 一些DT树变化的调用,of_changeset_attach_node(), of_changeset_detach_node(),
+   of_changeset_add_property(), of_changeset_remove_property,
+   of_changeset_update_property()来准备一组变更。此时不会对活动树做任何变更。所有
+   的变更操作都记录在of_changeset的 `entries` 列表中。
+
+3. of_changeset_apply() - 将变更使用到树上。要么整个变更集被使用,要么如果有错误,
+   树会被恢复到之前的状态。核心通过锁确保正确的顺序。如果需要的话,可以使用一个解锁的
+   __of_changeset_apply版本。
+
+如果一个成功使用的变更集需要被删除,可以用of_changeset_revert()来完成。
diff --git a/Documentation/translations/zh_CN/devicetree/dynamic-resolution-notes.rst b/Documentation/translations/zh_CN/devicetree/dynamic-resolution-notes.rst
new file mode 100644 (file)
index 0000000..1151903
--- /dev/null
@@ -0,0 +1,31 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/Devicetree/dynamic-resolution-notes.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+========================
+Devicetree动态解析器说明
+========================
+
+本文描述了内核内DeviceTree解析器的实现,它位于drivers/of/resolver.c中。
+
+解析器如何工作?
+----------------
+
+解析器被赋予一个任意的树作为输入,该树用适当的dtc选项编译,并有一个/plugin/标签。这就产
+生了适当的__fixups__和__local_fixups__节点。
+
+解析器依次通过以下步骤工作:
+
+1. 从实时树中获取最大的设备树phandle值 + 1.
+2. 调整树的所有本地 phandles,以解决这个量。
+3. 使用 __local__fixups__ 节点信息以相同的量调整所有本地引用。
+4. 对于__fixups__节点中的每个属性,找到它在实时树中引用的节点。这是用来标记该节点的标签。
+5. 检索fixup的目标的phandle。
+6. 对于属性中的每个fixup,找到节点:属性:偏移的位置,并用phandle值替换它。
index 3fc355f..7451dbf 100644 (file)
@@ -24,21 +24,16 @@ Open Firmware 和 Devicetree
 
    usage-model
    of_unittest
-
-Todolist:
-
-*   kernel-api
+   kernel-api
 
 Devicetree Overlays
 ===================
 .. toctree::
    :maxdepth: 1
 
-Todolist:
-
-*   changesets
-*   dynamic-resolution-notes
-*   overlay-notes
+   changesets
+   dynamic-resolution-notes
+   overlay-notes
 
 Devicetree Bindings
 ===================
diff --git a/Documentation/translations/zh_CN/devicetree/kernel-api.rst b/Documentation/translations/zh_CN/devicetree/kernel-api.rst
new file mode 100644 (file)
index 0000000..6aa3b68
--- /dev/null
@@ -0,0 +1,58 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/Devicetree/kernel-api.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+
+=================
+内核中的设备树API
+=================
+
+核心函数
+--------
+
+该API在以下内核代码中:
+
+drivers/of/base.c
+
+include/linux/of.h
+
+drivers/of/property.c
+
+include/linux/of_graph.h
+
+drivers/of/address.c
+
+drivers/of/irq.c
+
+drivers/of/fdt.c
+
+驱动模型函数
+------------
+
+该API在以下内核代码中:
+
+include/linux/of_device.h
+
+drivers/of/device.c
+
+include/linux/of_platform.h
+
+drivers/of/platform.c
+
+覆盖和动态DT函数
+----------------
+
+该API在以下内核代码中:
+
+drivers/of/resolver.c
+
+drivers/of/dynamic.c
+
+drivers/of/overlay.c
diff --git a/Documentation/translations/zh_CN/devicetree/overlay-notes.rst b/Documentation/translations/zh_CN/devicetree/overlay-notes.rst
new file mode 100644 (file)
index 0000000..1bd482c
--- /dev/null
@@ -0,0 +1,140 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/Devicetree/overlay-notes.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+==============
+设备树覆盖说明
+==============
+
+本文档描述了drivers/of/overlay.c中的内核内设备树覆盖功能的实现,是
+Documentation/devicetree/dynamic-resolution-notes.rst[1]的配套文档。
+
+覆盖如何工作
+------------
+
+设备树覆盖的目的是修改内核的实时树,并使修改以反映变化的方式影响内核的状态。
+由于内核主要处理的是设备,任何新的设备节点如果导致一个活动的设备,就应该创建它,
+而如果设备节点被禁用或被全部删除,受影响的设备应该被取消注册。
+
+让我们举个例子,我们有一个foo板,它的基本树形图如下::
+
+    ---- foo.dts ---------------------------------------------------------------
+       /* FOO平台 */
+       /dts-v1/;
+       / {
+               compatible = "corp,foo";
+
+               /* 共享的资源 */
+               res: res {
+               };
+
+               /* 芯片上的外围设备 */
+               ocp: ocp {
+                       /* 总是被实例化的外围设备 */
+                       peripheral1 { ... };
+               };
+       };
+    ---- foo.dts ---------------------------------------------------------------
+
+覆盖bar.dts,
+::
+
+    ---- bar.dts - 按标签覆盖目标位置 ----------------------------
+       /dts-v1/;
+       /插件/;
+       &ocp {
+               /* bar外围 */
+               bar {
+                       compatible = "corp,bar";
+                       ... /* 各种属性和子节点 */
+               };
+       };
+    ---- bar.dts ---------------------------------------------------------------
+
+当加载(并按照[1]中描述的方式解决)时,应该产生foo+bar.dts::
+
+    ---- foo+bar.dts -----------------------------------------------------------
+       /* FOO平台 + bar外围 */
+       / {
+               compatible = "corp,foo";
+
+               /* 共享资源 */
+               res: res {
+               };
+
+               /* 芯片上的外围设备 */
+               ocp: ocp {
+                       /* 总是被实例化的外围设备 */
+                       peripheral1 { ... };
+
+                       /* bar外围 */
+                       bar {
+                               compatible = "corp,bar";
+                               ... /* 各种属性和子节点 */
+                       };
+               };
+       };
+    ---- foo+bar.dts -----------------------------------------------------------
+
+作为覆盖的结果,已经创建了一个新的设备节点(bar),因此将注册一个bar平台设备,
+如果加载了匹配的设备驱动程序,将按预期创建设备。
+
+如果基础DT不是用-@选项编译的,那么“&ocp”标签将不能用于将覆盖节点解析到基础
+DT中的适当位置。在这种情况下,可以提供目标路径。通过标签的目标位置的语法是比
+较好的,因为不管标签在DT中出现在哪里,覆盖都可以被应用到任何包含标签的基础DT上。
+
+上面的bar.dts例子被修改为使用目标路径语法,即为::
+
+    ---- bar.dts - 通过明确的路径覆盖目标位置 --------------------
+       /dts-v1/;
+       /插件/;
+       &{/ocp} {
+               /* bar外围 */
+               bar {
+                       compatible = "corp,bar";
+                       ... /* 各种外围设备和子节点 */
+               }
+       };
+    ---- bar.dts ---------------------------------------------------------------
+
+
+内核中关于覆盖的API
+-------------------
+
+该API相当容易使用。
+
+1) 调用of_overlay_fdt_apply()来创建和应用一个覆盖的变更集。返回值是一个
+   错误或一个识别这个覆盖的cookie。
+
+2) 调用of_overlay_remove()来删除和清理先前通过调用of_overlay_fdt_apply()
+   而创建的覆盖变更集。不允许删除一个被另一个覆盖的覆盖变化集。
+
+最后,如果你需要一次性删除所有的覆盖,只需调用of_overlay_remove_all(),
+它将以正确的顺序删除每一个覆盖。
+
+你可以选择注册在覆盖操作中被调用的通知器。详见
+of_overlay_notifier_register/unregister和enum of_overlay_notify_action。
+
+OF_OVERLAY_PRE_APPLY、OF_OVERLAY_POST_APPLY或OF_OVERLAY_PRE_REMOVE
+的通知器回调可以存储指向覆盖层中的设备树节点或其内容的指针,但这些指针不能持
+续到OF_OVERLAY_POST_REMOVE的通知器回调。在OF_OVERLAY_POST_REMOVE通
+知器被调用后,包含覆盖层的内存将被kfree()ed。请注意,即使OF_OVERLAY_POST_REMOVE
+的通知器返回错误,内存也会被kfree()ed。
+
+drivers/of/dynamic.c中的变更集通知器是第二种类型的通知器,可以通过应用或移除
+覆盖层来触发。这些通知器不允许在覆盖层或其内容中存储指向设备树节点的指针。当包含
+覆盖层的内存因移除覆盖层而被释放时,覆盖层代码并不能防止这类指针仍然有效。
+
+任何其他保留指向覆盖层节点或数据的指针的代码都被认为是一个错误,因为在移除覆盖层
+后,该指针将指向已释放的内存。
+
+覆盖层的用户必须特别注意系统上发生的整体操作,以确保其他内核代码不保留任何指向覆
+盖层节点或数据的指针。任何无意中使用这种指针的例子是,如果一个驱动或子系统模块在
+应用了覆盖后被加载,并且该驱动或子系统扫描了整个设备树或其大部分,包括覆盖节点。
diff --git a/Documentation/translations/zh_CN/driver-api/gpio/index.rst b/Documentation/translations/zh_CN/driver-api/gpio/index.rst
new file mode 100644 (file)
index 0000000..9ab64e9
--- /dev/null
@@ -0,0 +1,69 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/driver-api/gpio/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+=======================
+通用型输入/输出(GPIO)
+=======================
+
+目录:
+
+.. toctree::
+   :maxdepth: 2
+
+   legacy
+
+Todolist:
+
+*   intro
+*   using-gpio
+*   driver
+*   consumer
+*   board
+*   drivers-on-gpio
+*   bt8xxgpio
+
+核心
+====
+
+该API在以下内核代码中:
+
+include/linux/gpio/driver.h
+
+drivers/gpio/gpiolib.c
+
+ACPI支持
+========
+
+该API在以下内核代码中:
+
+drivers/gpio/gpiolib-acpi.c
+
+设备树支持
+==========
+
+该API在以下内核代码中:
+
+drivers/gpio/gpiolib-of.c
+
+设备管理支持
+============
+
+该API在以下内核代码中:
+
+drivers/gpio/gpiolib-devres.c
+
+sysfs帮助(函数)
+=================
+
+该API在以下内核代码中:
+
+drivers/gpio/gpiolib-sysfs.c
@@ -1,39 +1,28 @@
-Chinese translated version of Documentation/admin-guide/gpio
+.. SPDX-License-Identifier: GPL-2.0
 
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
+.. include:: ../../disclaimer-zh_CN.rst
 
-Maintainer: Grant Likely <grant.likely@secretlab.ca>
-               Linus Walleij <linus.walleij@linaro.org>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/admin-guide/gpio 的中文翻译
+:Original: Documentation/driver-api/gpio/legacy.rst
 
-如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
-交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题,请联系中文版维护者。
-英文版维护者: Grant Likely <grant.likely@secretlab.ca>
-               Linus Walleij <linus.walleij@linaro.org>
-中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+:翻译:
 
+ 傅炜 Fu Wei <tekkamanninja@gmail.com>
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
 
-以下为正文
----------------------------------------------------------------------
-GPIO 接口
+:校译:
 
-本文档提供了一个在Linux下访问GPIO的公约概述。
+
+传统GPIO接口
+============
+
+本文档概述了Linux下的GPIO访问公约。
 
 这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的
 __gpio_* 前缀。
 
 
-什么是GPIO?
-==========
+什么是GPIO
+============
 "通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可
 由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是
 比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中
@@ -99,6 +88,7 @@ GPIO 公约
 
 标识 GPIO
 ---------
+
 GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数
 用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层
 硬件的代码会忽略这些整数。
@@ -115,7 +105,7 @@ FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中
 
 如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码
 (如"-EINVAL"),那将使其永远不会是有效。来测试这样一个结构体中的编号
-是否关联一个 GPIO,你可使用以下断言:
+是否关联一个 GPIO,你可使用以下断言::
 
        int gpio_is_valid(int number);
 
@@ -128,11 +118,12 @@ FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中
 
 使用 GPIO
 ---------
+
 对于一个 GPIO,系统应该做的第一件事情就是通过 gpio_request()
 函数分配它,见下文。
 
 接下来是设置I/O方向,这通常是在板级启动代码中为所使用的 GPIO 设置
-platform_device 时完成
+platform_device 时完成::
 
        /* 设置为输入或输出, 返回 0 或负的错误代码 */
        int gpio_direction_input(unsigned gpio);
@@ -157,12 +148,13 @@ get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误
 
 
 访问自旋锁安全的 GPIO
--------------------
+---------------------
+
 大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以
 安全地在硬(非线程)中断例程和类似的上下文中完成。
 
 对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文),使用
-以下的函数访问:
+以下的函数访问::
 
        /* GPIO 输入:返回零或非零 */
        int gpio_get_value(unsigned gpio);
@@ -188,17 +180,18 @@ GPIO值是布尔值,零表示低电平,非零表示高电平。当读取一
 
 
 访问可能休眠的 GPIO
------------------
+-------------------
+
 某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些
 GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其反馈。期间需要
 休眠,这不能在 IRQ 例程(中断上下文)中执行。
 
 支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要
-一个之前通过 gpio_request 分配到的有效 GPIO 编号):
+一个之前通过 gpio_request 分配到的有效 GPIO 编号)::
 
        int gpio_cansleep(unsigned gpio);
 
-为了访问这种 GPIO,内核定义了一套不同的函数:
+为了访问这种 GPIO,内核定义了一套不同的函数::
 
        /* GPIO 输入:返回零或非零 ,可能会休眠 */
        int gpio_get_value_cansleep(unsigned gpio);
@@ -214,25 +207,26 @@ GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其
 事实,这些处理例程实际上和自旋锁安全的函数是一样的。
 
 ** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中,
-因为它们可能也需要访问 GPIO 控制器芯片: (这些设置函数通常在板级启动代码或者
-驱动探测/断开代码中,所以这是一个容易满足的约束条件。)
+因为它们可能也需要访问 GPIO 控制器芯片 (这些设置函数通常在板级启动代码或者
+驱动探测/断开代码中,所以这是一个容易满足的约束条件。) ::
 
-       gpio_direction_input()
-       gpio_direction_output()
-       gpio_request()
+                gpio_direction_input()
+                gpio_direction_output()
+                gpio_request()
 
-##     gpio_request_one()
-##     gpio_request_array()
-##     gpio_free_array()
+        ##     gpio_request_one()
+        ##     gpio_request_array()
+        ##     gpio_free_array()
 
-       gpio_free()
-       gpio_set_debounce()
+                gpio_free()
+                gpio_set_debounce()
 
 
 
 声明和释放 GPIO
-----------------------------
-为了有助于捕获系统配置错误,定义了两个函数。
+----------------
+
+为了有助于捕获系统配置错误,定义了两个函数::
 
        /* 申请 GPIO, 返回 0 或负的错误代码.
         * 非空标签可能有助于诊断.
@@ -256,9 +250,9 @@ GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其
 某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和
 简单地关闭未使用时钟)。
 
-对于 GPIO 使用 pinctrl 子系统已知的引脚,子系统应该被告知其使用情况;
+对于 GPIO 使用引脚控制子系统已知的引脚,子系统应该被告知其使用情况;
 一个 gpiolib 驱动的 .request()操作应调用 pinctrl_gpio_request(),
-而 gpiolib 驱动的 .free()操作应调用 pinctrl_gpio_free()。pinctrl
+而 gpiolib 驱动的 .free()操作应调用 pinctrl_gpio_free()。引脚控制
 子系统允许 pinctrl_gpio_request()在某个引脚或引脚组以复用形式“属于”
 一个设备时都成功返回。
 
@@ -270,7 +264,7 @@ GPIO 值的命令需要等待其信息排到队首才发送命令,再获得其
 
 某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的,GPIO 或引脚的
 其他方面也需要配置,如上拉/下拉。平台软件应该在对这些 GPIO 调用
-gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映射表,
+gpio_request()前将这类细节配置好,例如使用引脚控制子系统的映射表,
 使得 GPIO 的用户无须关注这些细节。
 
 还有一个值得注意的是在释放 GPIO 前,你必须停止使用它。
@@ -278,7 +272,7 @@ gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映
 
 注意:申请一个 GPIO 并没有以任何方式配置它,只不过标识那个 GPIO 处于使用
 状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。
-考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数:
+考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数::
 
        /* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置,
         * 其他和 gpio_request()的参数和返回值相同
@@ -326,7 +320,7 @@ gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映
 将来这些标志可能扩展到支持更多的属性。
 
 更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有
-这三个领域:
+这三个领域::
 
        struct gpio {
                unsigned        gpio;
@@ -334,7 +328,7 @@ gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映
                const char      *label;
        };
 
-一个典型的用例:
+一个典型的用例::
 
        static struct gpio leds_gpios[] = {
                { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */
@@ -356,9 +350,10 @@ gpio_request()前将这类细节配置好,例如使用 pinctrl 子系统的映
 
 
 GPIO 映射到 IRQ
---------------------
+----------------
+
 GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间
-(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射:
+(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射::
 
        /* 映射 GPIO 编号到 IRQ 编号 */
        int gpio_to_irq(unsigned gpio);
@@ -384,7 +379,8 @@ irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所
 
 
 模拟开漏信号
-----------------------------
+------------
+
 有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点,逻辑电平
 结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语
 适用于 CMOS 管;而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这
@@ -408,9 +404,44 @@ irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所
 这不一定是错误的。一个常见的例子就是 I2C 时钟的延长:一个需要较慢时钟的
 从设备延迟 SCK 的上升沿,而 I2C 主设备相应地调整其信号传输速率。
 
+GPIO控制器和引脚控制子系统
+--------------------------
+
+SOC上的GPIO控制器可能与引脚控制子系统紧密结合,即引脚可以与可选的gpio功
+能一起被其他功能使用。我们已经涵盖了这样的情况,例如一个GPIO控制器需要保
+留一个引脚或通过调用以下任何一个引脚来设置其方向::
+
+  pinctrl_gpio_request()
+  pinctrl_gpio_free()
+  pinctrl_gpio_direction_input()
+  pinctrl_gpio_direction_output()
+
+但是,引脚控制子系统是如何将GPIO号码(这是一个全局事项)与某个引脚控制器
+上的某个引脚交叉关联的?
+
+这是通过注册引脚的“范围”来实现的,这基本上是交叉参考表。这些描述是在
+Documentation/driver-api/pin-control.rst
+
+虽然引脚分配完全由引脚控制子系统管理,但gpio(在gpiolib下)仍由gpio驱动
+维护。可能发生的情况是,SoC中的不同引脚范围由不同的gpio驱动器管理。
+
+这使得在调用 "pinctrl_gpio_request" 之前,让gpio驱动向pin ctrl子系
+统宣布它们的引脚范围是合理的,以便在使用任何gpio之前要求引脚控制子系统准
+备相应的引脚。
+
+为此,gpio控制器可以用引脚控制子系统注册其引脚范围。目前有两种方法:有或
+无DT。
+
+关于对DT的支持,请参考 Documentation/devicetree/bindings/gpio/gpio.txt.
+
+对于非DT支持,用户可以用适当的参数调用gpiochip_add_pin_range(),将一
+系列的gpio引脚注册到引脚控制驱动上。为此,必须将引脚控制设备的名称字符串
+作为参数之一传给这个程序。
+
+
+这些公约忽略了什么?
+====================
 
-这些公约忽略了什么?
-================
 这些公约忽略的最大一件事就是引脚复用,因为这属于高度芯片特定的属性且
 没有可移植性。某个平台可能不需要明确的复用信息;有的对于任意给定的引脚
 可能只有两个功能选项;有的可能每个引脚有八个功能选项;有的可能可以将
@@ -433,8 +464,9 @@ Linux 的系统。)
 当前,动态定义 GPIO 并不是标准的,例如作为配置一个带有某些 GPIO 扩展器的
 附加电路板的副作用。
 
-GPIO 实现者的框架 (可选)
-=====================
+GPIO 实现者的框架(可选)
+=========================
+
 前面提到了,有一个可选的实现框架,让平台使用相同的编程接口,更加简单地支持
 不同种类的 GPIO 控制器。这个框架称为"gpiolib"。
 
@@ -444,15 +476,16 @@ GPIO 实现者的框架 (可选)
 
 
 控制器驱动: gpio_chip
--------------------
+---------------------
+
 在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip",他包含了
 该类型的每个控制器的常用信息:
 
- - 设置 GPIO 方向的方法
- - 用于访问 GPIO 值的方法
- - 告知调用其方法是否可能休眠的标志
- - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
- - 诊断标签
      - 设置 GPIO 方向的方法
      - 用于访问 GPIO 值的方法
      - 告知调用其方法是否可能休眠的标志
      - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
      - 诊断标签
 
 也包含了来自 device.platform_data 的每个实例的数据:它第一个 GPIO 的
 编号和它可用的 GPIO 的数量。
@@ -471,7 +504,8 @@ GPIO 实现者的框架 (可选)
 
 
 平台支持
--------
+--------
+
 为了支持这个框架,一个平台的 Kconfig 文件将会 "select"(选择)
 ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB,并让它的
 <asm/gpio.h> 包含 <asm-generic/gpio.h>,同时定义三个方法:
@@ -489,7 +523,7 @@ ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以
 如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以
 被用户使能。
 
-以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度:
+以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度::
 
   #define gpio_get_value       __gpio_get_value
   #define gpio_set_value       __gpio_set_value
@@ -508,7 +542,8 @@ arch_initcall()或者更早的地方集成进平台初始化代码,使这些 G
 且他们通常可以作为 IRQ 使用。
 
 板级支持
--------
+--------
+
 对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA
 或 CPLD),大多数常用板级特定代码都可以注册控制器设备,并保证他们的驱动知道
 gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO
@@ -526,8 +561,9 @@ GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是
 设备变成无效时移除它们。
 
 
-用户空间的 Sysfs 接口(可选)
-========================
+用户空间的 Sysfs 接口(可选)
+=============================
+
 使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。
 这不同于 debugfs 接口,因为它提供的是对 GPIO方向和值的控制,而不只显示
 一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。
@@ -548,6 +584,7 @@ GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是
 
 Sysfs 中的路径
 --------------
+
 在/sys/class/gpio 中有 3 类入口:
 
    -   用于在用户空间控制 GPIO 的控制接口;
@@ -625,8 +662,9 @@ GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
 
 
 从内核代码中导出
--------------
-内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出:
+----------------
+
+内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出::
 
        /* 导出 GPIO 到用户空间 */
        int gpio_export(unsigned gpio, bool direction_may_change);
@@ -648,3 +686,9 @@ GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
 在 GPIO 被导出之后,gpio_export_link()允许在 sysfs 文件系统的任何地方
 创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的
 名字,在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。
+
+
+API参考
+=======
+
+本节中列出的函数已被废弃。在新的代码中应该使用基于GPIO描述符的API。
diff --git a/Documentation/translations/zh_CN/driver-api/index.rst b/Documentation/translations/zh_CN/driver-api/index.rst
new file mode 100644 (file)
index 0000000..ba354e1
--- /dev/null
@@ -0,0 +1,132 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/driver-api/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+========================
+Linux驱动实现者的API指南
+========================
+
+内核提供了各种各样的接口来支持设备驱动的开发。这份文档只是对其中一些接口进行了
+一定程度的整理——希望随着时间的推移,它能变得更好!可用的小节可以在下面看到。
+
+.. class:: toc-title
+
+          目录列表:
+
+.. toctree::
+   :maxdepth: 2
+
+   gpio/index
+   io_ordering
+
+Todolist:
+
+*   driver-model/index
+*   basics
+*   infrastructure
+*   ioctl
+*   early-userspace/index
+*   pm/index
+*   clk
+*   device-io
+*   dma-buf
+*   device_link
+*   component
+*   message-based
+*   infiniband
+*   aperture
+*   frame-buffer
+*   regulator
+*   reset
+*   iio/index
+*   input
+*   usb/index
+*   firewire
+*   pci/index
+*   cxl/index
+*   spi
+*   i2c
+*   ipmb
+*   ipmi
+*   i3c/index
+*   interconnect
+*   devfreq
+*   hsi
+*   edac
+*   scsi
+*   libata
+*   target
+*   mailbox
+*   mtdnand
+*   miscellaneous
+*   mei/index
+*   mtd/index
+*   mmc/index
+*   nvdimm/index
+*   w1
+*   rapidio/index
+*   s390-drivers
+*   vme
+*   80211/index
+*   uio-howto
+*   firmware/index
+*   pin-control
+*   md/index
+*   media/index
+*   misc_devices
+*   nfc/index
+*   dmaengine/index
+*   slimbus
+*   soundwire/index
+*   thermal/index
+*   fpga/index
+*   acpi/index
+*   auxiliary_bus
+*   backlight/lp855x-driver.rst
+*   connector
+*   console
+*   dcdbas
+*   eisa
+*   isa
+*   isapnp
+*   io-mapping
+*   generic-counter
+*   memory-devices/index
+*   men-chameleon-bus
+*   ntb
+*   nvmem
+*   parport-lowlevel
+*   pps
+*   ptp
+*   phy/index
+*   pwm
+*   pldmfw/index
+*   rfkill
+*   serial/index
+*   sm501
+*   surface_aggregator/index
+*   switchtec
+*   sync_file
+*   tty/index
+*   vfio-mediated-device
+*   vfio
+*   vfio-pci-device-specific-driver-acceptance
+*   xilinx/index
+*   xillybus
+*   zorro
+*   hte/index
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/driver-api/io_ordering.rst b/Documentation/translations/zh_CN/driver-api/io_ordering.rst
new file mode 100644 (file)
index 0000000..4dbfa4c
--- /dev/null
@@ -0,0 +1,60 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/driver-api/io_ordering.rst
+
+:翻译:
+
+ 林永听 Lin Yongting <linyongting@gmail.com>
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+:校译:
+
+===========================
+对内存映射地址的I/O写入排序
+===========================
+
+在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任
+保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
+设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,
+而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
+这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存
+屏障操作,mb(),不过仅适用于I/O)。
+
+假设一个设备驱动程的具体例子::
+
+                ...
+        CPU A:  spin_lock_irqsave(&dev_lock, flags)
+        CPU A:  val = readl(my_status);
+        CPU A:  ...
+        CPU A:  writel(newval, ring_ptr);
+        CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
+                ...
+        CPU B:  spin_lock_irqsave(&dev_lock, flags)
+        CPU B:  val = readl(my_status);
+        CPU B:  ...
+        CPU B:  writel(newval2, ring_ptr);
+        CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
+                ...
+
+上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就
+发生了。不过很容易通过下面方法来修复::
+
+                ...
+        CPU A:  spin_lock_irqsave(&dev_lock, flags)
+        CPU A:  val = readl(my_status);
+        CPU A:  ...
+        CPU A:  writel(newval, ring_ptr);
+        CPU A:  (void)readl(safe_register); /* 配置寄存器?*/
+        CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
+                ...
+        CPU B:  spin_lock_irqsave(&dev_lock, flags)
+        CPU B:  val = readl(my_status);
+        CPU B:  ...
+        CPU B:  writel(newval2, ring_ptr);
+        CPU B:  (void)readl(safe_register); /* 配置寄存器?*/
+        CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
+
+在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,
+再处理后面的读操作,防止引发数据不一致问题。
index bf85bac..2fc60e6 100644 (file)
@@ -108,6 +108,7 @@ TODOList:
    :maxdepth: 2
 
    core-api/index
+   driver-api/index
    locking/index
    accounting/index
    cpu-freq/index
@@ -120,10 +121,10 @@ TODOList:
    scheduler/index
    mm/index
    peci/index
+   PCI/index
 
 TODOList:
 
-* driver-api/index
 * block/index
 * cdrom/index
 * ide/index
@@ -148,7 +149,6 @@ TODOList:
 * crypto/index
 * bpf/index
 * usb/index
-* PCI/index
 * scsi/index
 * misc-devices/index
 * mhi/index
diff --git a/Documentation/translations/zh_CN/io_ordering.txt b/Documentation/translations/zh_CN/io_ordering.txt
deleted file mode 100644 (file)
index 7bb3086..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-Chinese translated version of Documentation/driver-api/io_ordering.rst
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Chinese maintainer: Lin Yongting <linyongting@gmail.com>
----------------------------------------------------------------------
-Documentation/driver-api/io_ordering.rst 的中文翻译
-
-如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
-交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题,请联系中文版维护者。
-
-中文版维护者: 林永听 Lin Yongting <linyongting@gmail.com>
-中文版翻译者: 林永听 Lin Yongting <linyongting@gmail.com>
-中文版校译者: 林永听 Lin Yongting <linyongting@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-
-在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任
-保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
-设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,
-而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
-这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存
-屏障操作,mb(),不过仅适用于I/O)。
-
-假设一个设备驱动程的具体例子:
-
-        ...
-CPU A:  spin_lock_irqsave(&dev_lock, flags)
-CPU A:  val = readl(my_status);
-CPU A:  ...
-CPU A:  writel(newval, ring_ptr);
-CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
-        ...
-CPU B:  spin_lock_irqsave(&dev_lock, flags)
-CPU B:  val = readl(my_status);
-CPU B:  ...
-CPU B:  writel(newval2, ring_ptr);
-CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
-        ...
-
-上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就
-发生了。不过很容易通过下面方法来修复:
-
-        ...
-CPU A:  spin_lock_irqsave(&dev_lock, flags)
-CPU A:  val = readl(my_status);
-CPU A:  ...
-CPU A:  writel(newval, ring_ptr);
-CPU A:  (void)readl(safe_register); /* 配置寄存器?*/
-CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
-        ...
-CPU B:  spin_lock_irqsave(&dev_lock, flags)
-CPU B:  val = readl(my_status);
-CPU B:  ...
-CPU B:  writel(newval2, ring_ptr);
-CPU B:  (void)readl(safe_register); /* 配置寄存器?*/
-CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
-
-在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,
-再处理后面的读操作,防止引发数据不一致问题。
diff --git a/Documentation/translations/zh_CN/oops-tracing.txt b/Documentation/translations/zh_CN/oops-tracing.txt
deleted file mode 100644 (file)
index c5f3bda..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-Chinese translated version of Documentation/admin-guide/bug-hunting.rst
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Chinese maintainer: Dave Young <hidave.darkstar@gmail.com>
----------------------------------------------------------------------
-Documentation/admin-guide/bug-hunting.rst 的中文翻译
-
-如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
-交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题,请联系中文版维护者。
-
-中文版维护者: 杨瑞 Dave Young <hidave.darkstar@gmail.com>
-中文版翻译者: 杨瑞 Dave Young <hidave.darkstar@gmail.com>
-中文版校译者: 李阳 Li Yang <leoyang.li@nxp.com>
-               王聪 Wang Cong <xiyou.wangcong@gmail.com>
-
-以下为正文
----------------------------------------------------------------------
-
-注意: ksymoops 在2.6中是没有用的。 请以原有格式使用Oops(来自dmesg,等等)。
-忽略任何这样那样关于“解码Oops”或者“通过ksymoops运行”的文档。 如果你贴出运行过
-ksymoops的来自2.6的Oops,人们只会让你重贴一次。
-
-快速总结
--------------
-
-发现Oops并发送给看似相关的内核领域的维护者。别太担心对不上号。如果你不确定就发给
-和你所做的事情相关的代码的负责人。 如果可重现试着描述怎样重构。 那甚至比oops更有
-价值。
-
-如果你对于发送给谁一无所知, 发给linux-kernel@vger.kernel.org。感谢你帮助Linux
-尽可能地稳定。
-
-Oops在哪里?
-----------------------
-
-通常Oops文本由klogd从内核缓冲区里读取并传给syslogd,由syslogd写到syslog文件中,
-典型地是/var/log/messages(依赖于/etc/syslog.conf)。有时klogd崩溃了,这种情况下你
-能够运行dmesg > file来从内核缓冲区中读取数据并保存下来。 否则你可以
-cat /proc/kmsg > file, 然而你必须介入中止传输, kmsg是一个“永不结束的文件”。如
-果机器崩溃坏到你不能输入命令或者磁盘不可用那么你有三种选择:-
-
-(1) 手抄屏幕上的文本待机器重启后再输入计算机。 麻烦但如果没有针对崩溃的准备,
-这是仅有的选择。 另外,你可以用数码相机把屏幕拍下来-不太好,但比没有强。 如果信
-息滚动到了终端的上面,你会发现以高分辩率启动(比如,vga=791)会让你读到更多的文
-本。(注意:这需要vesafb,所以对‘早期’的oops没有帮助)
-
-(2)用串口终端启动(请参看Documentation/admin-guide/serial-console.rst),运行一个null
-modem到另一台机器并用你喜欢的通讯工具获取输出。Minicom工作地很好。
-
-(3)使用Kdump(请参看Documentation/admin-guide/kdump/kdump.rst),
-使用在Documentation/admin-guide/kdump/gdbmacros.txt中定义的dmesg gdb宏,从旧的内存中提取内核
-环形缓冲区。
-
-完整信息
-----------------
-
-注意:以下来自于Linus的邮件适用于2.4内核。 我因为历史原因保留了它,并且因为其中
-一些信息仍然适用。 特别注意的是,请忽略任何ksymoops的引用。
-
-From: Linus Torvalds <torvalds@osdl.org>
-
-怎样跟踪Oops.. [原发到linux-kernel的一封邮件]
-
-主要的窍门是有五年和这些烦人的oops消息打交道的经验;-)
-
-实际上,你有办法使它更简单。我有两个不同的方法:
-
-       gdb /usr/src/linux/vmlinux
-       gdb> disassemble <offending_function>
-
-那是发现问题的简单办法,至少如果bug报告做的好的情况下(象这个一样-运行ksymoops
-得到oops发生的函数及函数内的偏移)。
-
-哦,如果报告发生的内核以相同的编译器和相似的配置编译它会有帮助的。
-
-另一件要做的事是反汇编bug报告的“Code”部分:ksymoops也会用正确的工具来做这件事,
-但如果没有那些工具你可以写一个傻程序:
-
-       char str[] = "\xXX\xXX\xXX...";
-       main(){}
-
-并用gcc -g编译它然后执行“disassemble str”(XX部分是由Oops报告的值-你可以仅剪切
-粘贴并用“\x”替换空格-我就是这么做的,因为我懒得写程序自动做这一切)。
-
-另外,你可以用scripts/decodecode这个shell脚本。它的使用方法是:
-decodecode < oops.txt
-
-“Code”之后的十六进制字节可能(在某些架构上)有一些当前指令之前的指令字节以及
-当前和之后的指令字节
-
-Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
-64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
-7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
-
-最后,如果你想知道代码来自哪里,你可以:
-
-       cd /usr/src/linux
-       make fs/buffer.s        # 或任何产生BUG的文件
-
-然后你会比gdb反汇编更清楚的知道发生了什么。
-
-现在,问题是把你所拥有的所有数据结合起来:C源码(关于它应该怎样的一般知识),
-汇编代码及其反汇编得到的代码(另外还有从“oops”消息得到的寄存器状态-对了解毁坏的
-指针有用,而且当你有了汇编代码你也能拿其它的寄存器和任何它们对应的C表达式做匹配
-)。
-
-实际上,你仅需看看哪里不匹配(这个例子是“Code”反汇编和编译器生成的代码不匹配)。
-然后你须要找出为什么不匹配。通常很简单-你看到代码使用了空指针然后你看代码想知道
-空指针是怎么出现的,还有检查它是否合法..
-
-现在,如果明白这是一项耗时的工作而且需要一丁点儿的专心,没错。这就是我为什么大多
-只是忽略那些没有符号表信息的崩溃报告的原因:简单的说太难查找了(我有一些
-程序用于在内核代码段中搜索特定的模式,而且有时我也已经能找出那些崩溃的地方,但是
-仅仅是找出正确的序列也确实需要相当扎实的内核知识)
-
-_有时_会发生这种情况,我仅看到崩溃中的反汇编代码序列, 然后我马上就明白问题出在
-哪里。这时我才意识到自己干这个工作已经太长时间了;-)
-
-               Linus
-
-
----------------------------------------------------------------------------
-关于Oops跟踪的注解:
-
-为了帮助Linus和其它内核开发者,klogd纳入了大量的支持来处理保护错误。为了拥有对
-地址解析的完整支持至少应该使用1.3-pl3的sysklogd包。
-
-当保护错误发生时,klogd守护进程自动把内核日志信息中的重要地址翻译成它们相应的符
-号。
-
-klogd执行两种类型的地址解析。首先是静态翻译其次是动态翻译。静态翻译和ksymoops
-一样使用System.map文件。为了做静态翻译klogd守护进程必须在初始化时能找到system
-map文件。关于klogd怎样搜索map文件请参看klogd手册页。
-
-动态地址翻译在使用内核可装载模块时很重要。 因为内核模块的内存是从内核动态内存池
-里分配的,所以不管是模块开始位置还是模块中函数和符号的位置都不是固定的。
-
-内核支持允许程序决定装载哪些模块和它们在内存中位置的系统调用。使用这些系统调用
-klogd守护进程生成一张符号表用于调试发生在可装载模块中的保护错误。
-
-至少klogd会提供产生保护错误的模块名。还可有额外的符号信息供可装载模块开发者选择
-以从模块中输出符号信息。
-
-因为内核模块环境可能是动态的,所以必须有一种机制当模块环境发生改变时来通知klogd
-守护进程。 有一些可用的命令行选项允许klogd向当前执行中的守护进程发送信号,告知符
-号信息应该被刷新了。 更多信息请参看klogd手册页。
-
-sysklogd发布时包含一个补丁修改了modules-2.0.0包,无论何时一个模块装载或者卸载都
-会自动向klogd发送信号。打上这个补丁提供了必要的对调试发生于内核可装载模块的保护
-错误的无缝支持。
-
-以下是被klogd处理过的发生在可装载模块中的一个保护错误例子:
----------------------------------------------------------------------------
-Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
-Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
-Aug 29 09:51:01 blizard kernel: *pde = 00000000
-Aug 29 09:51:01 blizard kernel: Oops: 0002
-Aug 29 09:51:01 blizard kernel: CPU:    0
-Aug 29 09:51:01 blizard kernel: EIP:    0010:[oops:_oops+16/3868]
-Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
-Aug 29 09:51:01 blizard kernel: eax: 315e97cc   ebx: 003a6f80   ecx: 001be77b   edx: 00237c0c
-Aug 29 09:51:01 blizard kernel: esi: 00000000   edi: bffffdb3   ebp: 00589f90   esp: 00589f8c
-Aug 29 09:51:01 blizard kernel: ds: 0018   es: 0018   fs: 002b   gs: 002b   ss: 0018
-Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
-Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
-Aug 29 09:51:01 blizard kernel:        00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
-Aug 29 09:51:01 blizard kernel:        bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
-Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
-Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
----------------------------------------------------------------------------
-
-Dr. G.W. Wettstein           Oncology Research Div. Computing Facility
-Roger Maris Cancer Center    INTERNET: greg@wind.rmcc.com
-820 4th St. N.
-Fargo, ND  58122
-Phone: 701-234-7556
-
-
----------------------------------------------------------------------------
-受污染的内核
-
-一些oops报告在程序记数器之后包含字符串'Tainted: '。这表明内核已经被一些东西给污
-染了。 该字符串之后紧跟着一系列的位置敏感的字符,每个代表一个特定的污染值。
-
-  1:'G'如果所有装载的模块都有GPL或相容的许可证,'P'如果装载了任何的专有模块。
-没有模块MODULE_LICENSE或者带有insmod认为是与GPL不相容的的MODULE_LICENSE的模块被
-认定是专有的。
-
-  2:'F'如果有任何通过“insmod -f”被强制装载的模块,' '如果所有模块都被正常装载。
-
-  3:'S'如果oops发生在SMP内核中,运行于没有证明安全运行多处理器的硬件。 当前这种
-情况仅限于几种不支持SMP的速龙处理器。
-
-  4:'R'如果模块通过“insmod -f”被强制装载,' '如果所有模块都被正常装载。
-
-  5:'M'如果任何处理器报告了机器检查异常,' '如果没有发生机器检查异常。
-
-  6:'B'如果页释放函数发现了一个错误的页引用或者一些非预期的页标志。
-
-  7:'U'如果用户或者用户应用程序特别请求设置污染标志,否则' '。
-
-  8:'D'如果内核刚刚死掉,比如有OOPS或者BUG。
-
-使用'Tainted: '字符串的主要原因是要告诉内核调试者,这是否是一个干净的内核亦或发
-生了任何的不正常的事。污染是永久的:即使出错的模块已经被卸载了,污染值仍然存在,
-以表明内核不再值得信任。
index 638d714..fa28ef0 100644 (file)
@@ -1,21 +1,23 @@
 .. include:: ../disclaimer-zh_CN.rst
 
-:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>`
+:Original: Documentation/process/coding-style.rst
 
 .. _cn_codingstyle:
 
-译者::
+:译者:
+ - 张乐 Zhang Le <r0bertz@gentoo.org>
+ - Andy Deng <theandy.deng@gmail.com>
+ - 吴想成 <bobwxc@email.cn>
 
-  中文版维护者: 张乐 Zhang Le <r0bertz@gentoo.org>
-  中文版翻译者: 张乐 Zhang Le <r0bertz@gentoo.org>
-  中文版校译者: 王聪 Wang Cong <xiyou.wangcong@gmail.com>
-                 wheelz <kernel.zeng@gmail.com>
-                 管旭东 Xudong Guan <xudong.guan@gmail.com>
-                 Li Zefan <lizf@cn.fujitsu.com>
-                 Wang Chen <wangchen@cn.fujitsu.com>
+:校译:
+ - 王聪 Wang Cong <xiyou.wangcong@gmail.com>
+ - wheelz <kernel.zeng@gmail.com>
+ - 管旭东 Xudong Guan <xudong.guan@gmail.com>
+ - Li Zefan <lizf@cn.fujitsu.com>
+ - Wang Chen <wangchen@cn.fujitsu.com>
 
 Linux 内核代码风格
-=========================
+==================
 
 这是一个简短的文档,描述了 linux 内核的首选代码风格。代码风格是因人而异的,
 而且我不愿意把自己的观点强加给任何人,但这就像我去做任何事情都必须遵循的原则
@@ -29,7 +31,7 @@ Linux 内核代码风格
 
 
 1) 缩进
---------------
+-------
 
 制表符是 8 个字符,所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4 (甚至
 2!) 字符深,这几乎相当于尝试将圆周率的值定义为 3。
@@ -73,6 +75,22 @@ Linux 内核代码风格
        if (condition) do_this;
          do_something_everytime;
 
+不要使用逗号来避免使用大括号:
+
+.. code-block:: c
+
+       if (condition)
+               do_this(), do_that();
+
+使用大括号包裹多语句:
+
+.. code-block:: c
+
+       if (condition) {
+               do_this();
+               do_that();
+       }
+
 也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读
 的表达式。
 
@@ -83,20 +101,25 @@ Linux 内核代码风格
 
 
 2) 把长的行和字符串打散
-------------------------------
+-----------------------
 
 代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。
 
 每一行的长度的限制是 80 列,我们强烈建议您遵守这个惯例。
 
 长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性,并且不
-会隐藏信息。子片段要明显短于母片段,并明显靠右。这同样适用于有着很长参数列表
-的函数头。然而,绝对不要打散对用户可见的字符串,例如 printk 信息,因为这样就
+会隐藏信息。
+
+子片段要明显短于母片段,并明显靠右。一种非常常用的样式是将子体与函数左括号对齐。
+
+这同样适用于有着很长参数列表的函数头。
+
+然而,绝对不要打散对用户可见的字符串,例如 printk 信息,因为这样就
 很难对它们 grep。
 
 
 3) 大括号和空格的放置
-------------------------------
+---------------------
 
 C 语言风格中另外一个常见问题是大括号的放置。和缩进大小不同,选择或弃用某种放
 置策略并没有多少技术上的原因,不过首选的方式,就像 Kernighan 和 Ritchie 展示
@@ -132,12 +155,12 @@ C 语言风格中另外一个常见问题是大括号的放置。和缩进大小
                body of function
        }
 
-全世界的异端可能会抱怨这个不一致性是... 呃... 不一致的,不过所有思维健全的人
+全世界的异端可能会抱怨这个不一致性是……呃……不一致,不过所有思维健全的人
 都知道 (a) K&R 是 **正确的** 并且 (b) K&R 是正确的。此外,不管怎样函数都是特
 殊的 (C 函数是不能嵌套的)。
 
 注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是 do 语
-句中的 "while" 或者 if 语句中的 "else",像这样:
+句中的 ``while`` 或者 if 语句中的 ``else`` ,像这样:
 
 .. code-block:: c
 
@@ -191,7 +214,7 @@ C 语言风格中另外一个常见问题是大括号的放置。和缩进大小
        }
 
 3.1) 空格
-********************
+*********
 
 Linux 内核的空格使用方式 (主要) 取决于它是用于函数还是关键字。(大多数) 关键字
 后要加一个空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,这
@@ -254,7 +277,7 @@ Linux 内核的空格使用方式 (主要) 取决于它是用于函数还是关
 
 
 4) 命名
-------------------------------
+-------
 
 C 是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同,
 C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会
@@ -275,11 +298,31 @@ C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字
 可能的话。类似的, ``tmp`` 可以用来称呼任意类型的临时变量。
 
 如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综
-合。请看第六章 (函数)。
+合。请看第六章 (函数)。
 
+对于符号名称和文档,避免引入新的“master/slave”(或独立于“master”的“slave”)
+和“blacklist/whitelist”。
+
+“master/slave”推荐替换为:
+    '{primary,main} / {secondary,replica,subordinate}'
+    '{initiator,requester} / {target,responder}'
+    '{controller,host} / {device,worker,proxy}'
+    'leader/follower'
+    'director/performer'
+
+“blacklist/whitelist”推荐替换为:
+    'denylist/allowlist'
+    'blocklist/passlist'
+
+引入新用法的例外情况是:维护用户空间ABI/API,或更新现有(截至2020年)硬件或
+协议规范的代码时要求这些术语。对于新规范,尽可能将术语的规范用法转换为内核
+编码标准。
+
+.. warning::
+       以上主从、黑白名单规则不适用于中文文档,请勿更改中文术语!
 
 5) Typedef
------------
+----------
 
 不要使用类似 ``vps_t`` 之类的东西。
 
@@ -308,7 +351,7 @@ C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字
 
      .. note::
 
-       不透明性和 "访问函数" 本身是不好的。我们使用 pte_t 等类型的原因在于真
+       不透明性和“访问函数”本身是不好的。我们使用 pte_t 等类型的原因在于真
        的是完全没有任何共用的可访问信息。
 
  (b) 清楚的整数类型,如此,这层抽象就可以 **帮助** 消除到底是 ``int`` 还是
@@ -353,7 +396,7 @@ C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字
 
 
 6) 函数
-------------------------------
+-------
 
 函数应该简短而漂亮,并且只完成一件事情。函数应该可以一屏或者两屏显示完 (我们
 都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
@@ -383,12 +426,46 @@ C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字
        }
        EXPORT_SYMBOL(system_is_up);
 
-在函数原型中,包含函数名和它们的数据类型。虽然 C 语言里没有这样的要求,在
+6.1) 函数原型
+*************
+
+在函数原型中包含参数名和它们的数据类型。虽然 C 语言里没有这样的要求,但在
 Linux 里这是提倡的做法,因为这样可以很简单的给读者提供更多的有价值的信息。
 
+不要在函数声明里使用 ``extern`` 关键字,因为这会导致代码行变长,并且不是严格
+必需的。
+
+写函数原型时,请保持 `元素顺序规则 <https://lore.kernel.org/mm-commits/CAHk-=wiOCLRny5aifWNhr621kYrJwhfURsa0vFPeUEm8mF0ufg@mail.gmail.com/>`_ 。
+例如下列函数声明::
+
+ __init void * __must_check action(enum magic value, size_t size, u8 count,
+                                  char *fmt, ...) __printf(4, 5) __malloc;
+
+推荐的函数原型元素顺序是:
+
+- 储存类型(下方的 ``static __always_inline`` ,注意 ``__always_inline``
+  技术上来讲是个属性但被当做 ``inline`` )
+- 储存类型属性(上方的 ``__init`` ——即节声明,但也像 ``__cold`` )
+- 返回类型(上方的 ``void *`` )
+- 返回类型属性(上方的 ``__must_check`` )
+- 函数名(上方的 ``action`` )
+- 函数参数(上方的 ``(enum magic value, size_t size, u8 count, char *fmt, ...)`` ,
+  注意必须写上参数名)
+- 函数参数属性(上方的 ``__printf(4, 5)`` )
+- 函数行为属性(上方的 ``__malloc`` )
+
+请注意,对于函数 **定义** (即实际函数体),编译器不允许在函数参数之后添加函
+数参数属性。在这种情况下,它们应该跟随存储类型属性(例如,与上面的 **声明**
+示例相比,请注意下面的 ``__printf(4, 5)`` 的位置发生了变化)::
+
+ static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value,
+               size_t size, u8 count, char *fmt, ...) __malloc
+ {
+       ...
+ }
 
 7) 集中的函数退出途径
-------------------------------
+---------------------
 
 虽然被某些人声称已经过时,但是 goto 语句的等价物还是经常被编译器所使用,具体
 形式是无条件跳转指令。
@@ -432,7 +509,7 @@ Linux 里这是提倡的做法,因为这样可以很简单的给读者提供
                return result;
        }
 
-一个需要注意的常见错误是 ``一个 err 错误`` ,就像这样:
+一个需要注意的常见错误是 `` err 错误`` ,就像这样:
 
 .. code-block:: c
 
@@ -456,19 +533,19 @@ Linux 里这是提倡的做法,因为这样可以很简单的给读者提供
 
 
 8) 注释
-------------------------------
+-------
 
 注释是好的,不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的:
 更好的做法是让别人一看你的代码就可以明白,解释写的很差的代码是浪费时间。
 
-一般的,你想要你的注释告诉别人你的代码做了什么,而不是怎么做的。也请你不要把
+一般来说你用注释告诉别人你的代码做了什么,而不是怎么做的。也请你不要把
 注释放在一个函数体内部:如果函数复杂到你需要独立的注释其中的一部分,你很可能
 需要回到第六章看一看。你可以做一些小注释来注明或警告某些很聪明 (或者槽糕) 的
 做法,但不要加太多。你应该做的,是把注释放在函数的头部,告诉人们它做了什么,
 也可以加上它做这些事情的原因。
 
-å½\93注é\87\8aå\86\85æ ¸ API å\87½æ\95°æ\97¶ï¼\8c请使ç\94¨ kernel-doc æ ¼å¼\8fã\80\82请ç\9c\8b
-Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息
+å½\93注é\87\8aå\86\85æ ¸ API å\87½æ\95°æ\97¶ï¼\8c请使ç\94¨ kernel-doc æ ¼å¼\8fã\80\82详è§\81
+Documentation/translations/zh_CN/doc-guide/index.rst 和 scripts/kernel-doc 
 
 长 (多行) 注释的首选风格是:
 
@@ -500,17 +577,18 @@ Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。
 
 
 9) 你已经把事情弄糟了
-------------------------------
+---------------------
 
-这没什么,我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你
+这没什么,我们都是这样。可能你长期使用 Unix 的朋友已经告诉你
 ``GNU emacs`` 能自动帮你格式化 C 源代码,而且你也注意到了,确实是这样,不过它
 所使用的默认值和我们想要的相去甚远 (实际上,甚至比随机打的还要差——无数个猴子
-在 GNU emacs 里打字永远不会创造出一个好程序) (译注:Infinite Monkey Theorem)
+在 GNU emacs 里打字永远不会创造出一个好程序)
+*(译注:Infinite Monkey Theorem)*
 
 所以你要么放弃 GNU emacs,要么改变它让它使用更合理的设定。要采用后一个方案,
 你可以把下面这段粘贴到你的 .emacs 文件里。
 
-.. code-block:: none
+.. code-block:: elisp
 
   (defun c-lineup-arglist-tabs-only (ignored)
     "Line up argument lists by tabs, not spaces"
@@ -529,7 +607,7 @@ Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。
           (c-offsets-alist . (
                   (arglist-close         . c-lineup-arglist-tabs-only)
                   (arglist-cont-nonempty .
-                     (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+                      (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
                   (arglist-intro         . +)
                   (brace-list-intro      . +)
                   (c                     . c-lineup-C-comments)
@@ -573,9 +651,14 @@ Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。
 ``indent`` 有很多选项,特别是重新格式化注释的时候,你可能需要看一下它的手册。
 不过记住: ``indent`` 不能修正坏的编程习惯。
 
+请注意,您还可以使用 ``clang-format`` 工具帮助您处理这些规则,快速自动重新格
+式化部分代码,并审阅整个文件以发现代码风格错误、打字错误和可能的改进。它还可
+以方便地排序 ``#include`` ,对齐变量/宏,重排文本和其他类似任务。
+详见 Documentation/process/clang-format.rst 。
+
 
 10) Kconfig 配置文件
-------------------------------
+--------------------
 
 对于遍布源码树的所有 Kconfig* 配置文件来说,它们缩进方式有所不同。紧挨着
 ``config`` 定义的行,用一个制表符缩进,然而 help 信息的缩进则额外增加 2 个空
@@ -598,11 +681,11 @@ Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。
        depends on ADFS_FS
        ...
 
-要查看配置文件的完整文档,请看 Documentation/kbuild/kconfig-language.rst。
+要查看配置文件的完整文档,请看 Documentation/kbuild/kconfig-language.rst 
 
 
 11) 数据结构
-------------------------------
+------------
 
 如果一个数据结构,在创建和销毁它的单线执行环境之外可见,那么它必须要有一个引
 用计数器。内核里没有垃圾收集 (并且内核之外的垃圾收集慢且效率低下),这意味着你
@@ -626,7 +709,7 @@ mm_count),和文件系统 (``struct super_block``: s_count 和 s_active) 中
 
 
 12) 宏,枚举和RTL
-------------------------------
+-----------------
 
 用于定义常量的宏的名字及枚举里的标签需要大写。
 
@@ -638,7 +721,7 @@ mm_count),和文件系统 (``struct super_block``: s_count 和 s_active) 中
 
 宏的名字请用大写字母,不过形如函数的宏的名字可以用小写字母。
 
-一般的,如果能写成内联函数就不要写成像函数的宏。
+通常如果能写成内联函数就不要写成像函数的宏。
 
 含有多个语句的宏应该被包含在一个 do-while 代码块里:
 
@@ -696,18 +779,18 @@ mm_count),和文件系统 (``struct super_block``: s_count 和 s_active) 中
                (ret);                          \
        })
 
-ret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。
+ret 是本地变量的通用名字—— __foo_ret 更不容易与一个已存在的变量冲突。
 
 cpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL,内核里的汇编语
 言经常用到它。
 
 
 13) 打印内核消息
-------------------------------
+----------------
 
-内核开发者应该是受过良好教育的。请一定注意内核信息的拼写,以给人以好的印象。
+内核开发者应该看起来有文化。请一定注意内核信息的拼写,以给人良好的印象。
 不要用不规范的单词比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保证这些信
-息简单明了,无歧义。
+息简单明了无歧义。
 
 内核信息不必以英文句号结束。
 
@@ -724,17 +807,18 @@ dev_info() 等等。对于那些不和某个特定设备相关连的信息,<li
 或设定了 CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg(),一个相关约定是在一
 个已经开启了 DEBUG 时,使用 VERBOSE_DEBUG 来添加 dev_vdbg()。
 
-许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面;在其他
+许多子系统拥有 Kconfig 调试选项来开启对应 Makefile 里面的 -DDEBUG;在其他
 情况下,特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时,例如,
 如果已经包含一个调试相关的 #ifdef 条件,printk(KERN_DEBUG ...) 就可被使用。
 
 
 14) 分配内存
-------------------------------
+------------
 
 内核提供了下面的一般用途的内存分配函数:
 kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
-请参考 API 文档以获取有关它们的详细信息。
+请参考 API 文档以获取有关它们的详细信息:
+Documentation/translations/zh_CN/core-api/memory-allocation.rst 。
 
 传递结构体大小的首选形式是这样的:
 
@@ -761,11 +845,13 @@ kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
 
        p = kcalloc(n, sizeof(...), ...);
 
-两种形式检查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
+两种形式都会检查分配 n * sizeof(...) 大小时内存的溢出,如果溢出返回 NULL。
 
+在没有 __GFP_NOWARN 的情况下使用时,这些通用分配函数都会在失败时发起堆栈转储,
+因此当返回NULL时,没有必要发出额外的失败消息。
 
 15) 内联弊病
-------------------------------
+------------
 
 有一个常见的误解是 ``内联`` 是 gcc 提供的可以让代码运行更快的一个选项。虽然使
 用内联函数有时候是恰当的 (比如作为一种替代宏的方式,请看第十二章),不过很多情
@@ -786,7 +872,7 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
 
 
 16) 函数返回值及命名
-------------------------------
+--------------------
 
 函数可以返回多种不同类型的值,最常见的一种是表明函数执行成功或者失败的值。这样
 的一个值可以表示为一个错误代码整数 (-Exxx=失败,0=成功) 或者一个 ``成功``
@@ -797,7 +883,7 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
 产生这种 bug,请遵循下面的惯例::
 
        如果函数的名字是一个动作或者强制性的命令,那么这个函数应该返回错误代
-       码整数。如果是一个判断,那么函数应该返回一个 "成功" 布尔值。
+       码整数。如果是一个判断,那么函数应该返回一个“成功”布尔值。
 
 比如, ``add work`` 是一个命令,所以 add_work() 在成功时返回 0,在失败时返回
 -EBUSY。类似的,因为 ``PCI device present`` 是一个判断,所以 pci_dev_present()
@@ -806,13 +892,35 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
 所有 EXPORTed 函数都必须遵守这个惯例,所有的公共函数也都应该如此。私有
 (static) 函数不需要如此,但是我们也推荐这样做。
 
-返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的,
+返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。通常
 他们通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数,
 他们使用 NULL 或者 ERR_PTR 机制来报告错误。
 
+17) 使用布尔类型
+----------------
+
+Linux内核布尔(bool)类型是C99 _Bool类型的别名。布尔值只能为0或1,而对布尔的
+隐式或显式转换将自动将值转换为true或false。在使用布尔类型时 **不需要** 构造,
+它会消除一类错误。
+
+使用布尔值时,应使用true和false定义,而不是1和0。
 
-17) 不要重新发明内核宏
-------------------------------
+布尔函数返回类型和堆栈变量总是可以在适当的时候使用。鼓励使用布尔来提高可读性,
+并且布尔值在存储时通常比“int”更好。
+
+如果缓存行布局或值的大小很重要,请不要使用布尔,因为其大小和对齐方式根据编译
+的体系结构而不同。针对对齐和大小进行优化的结构体不应使用布尔。
+
+如果一个结构体有多个true/false值,请考虑将它们合并为具有1比特成员的位域,或使
+用适当的固定宽度类型,如u8。
+
+类似地,对于函数参数,多个true/false值可以合并为单个按位的“标志”参数,如果调
+用点具有裸true/false常量,“标志”参数通常是更具可读性的替代方法。
+
+总之,在结构体和参数中有限地使用布尔可以提高可读性。
+
+18) 不要重新发明内核宏
+----------------------
 
 头文件 include/linux/kernel.h 包含了一些宏,你应该使用它们,而不要自己写一些
 它们的变种。比如,如果你需要计算一个数组的长度,使用这个宏
@@ -832,11 +940,11 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
 在你的代码里自己重新定义。
 
 
-18) 编辑器模式行和其他需要罗嗦的事情
---------------------------------------------------
+19) 编辑器模式行和其他需要罗嗦的事情
+------------------------------------
 
 有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如,emacs
-能够解被标记成这样的行:
+能够解被标记成这样的行:
 
 .. code-block:: c
 
@@ -852,7 +960,7 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
        End:
        */
 
-Vim 能够解这样的标记:
+Vim 能够解这样的标记:
 
 .. code-block:: c
 
@@ -863,8 +971,8 @@ Vim 能够解释这样的标记:
 的模式,或者使用其他可以产生正确的缩进的巧妙方法。
 
 
-19) 内联汇编
-------------------------------
+20) 内联汇编
+------------
 
 在特定架构的代码中,你可能需要内联汇编与 CPU 和平台相关功能连接。需要这么做时
 就不要犹豫。然而,当 C 可以完成工作时,不要平白无故地使用内联汇编。在可能的情
@@ -880,8 +988,8 @@ Vim 能够解释这样的标记:
 移除了。你不必总是这样做,尽管,这不必要的举动会限制优化。
 
 在写一个包含多条指令的单个内联汇编语句时,把每条指令用引号分割而且各占一行,
-除了最后一条指令外,在每个指令结尾加上 \n\t,让汇编输出时可以正确地缩进下一条
-指令:
+除了最后一条指令外,在每个指令结尾加上 ``\n\t`` ,让汇编输出时可以正确地缩进
+下一条指令:
 
 .. code-block:: c
 
@@ -890,10 +998,10 @@ Vim 能够解释这样的标记:
             : /* outputs */ : /* inputs */ : /* clobbers */);
 
 
-20) 条件编译
-------------------------------
+21) 条件编译
+------------
 
-只要可能,就不要在 .c 文件里面使用预处理条件 (#if, #ifdef);这样做让代码更难
+只要可能,就不要在 .c 文件里面使用预处理条件 (#if, #ifdef);这样做让代码更难
 阅读并且更难去跟踪逻辑。替代方案是,在头文件中用预处理条件提供给那些 .c 文件
 使用,再给 #else 提供一个空桩 (no-op stub) 版本,然后在 .c 文件内无条件地调用
 那些 (定义在头文件内的) 函数。这样做,编译器会避免为桩函数 (stub) 的调用生成
@@ -904,8 +1012,8 @@ Vim 能够解释这样的标记:
 条件到这个辅助函数内。
 
 如果你有一个在特定配置中,可能变成未使用的函数或变量,编译器会警告它定义了但
-未使用,把它标记为 __maybe_unused 而不是将它包含在一个预处理条件中。(然而,如
-果一个函数或变量总是未使用,就直接删除它。)
+未使用,请把它标记为 __maybe_unused 而不是将它包含在一个预处理条件中。(然而,
+果一个函数或变量总是未使用,就直接删除它。)
 
 在代码中,尽可能地使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔
 表达式,并在一般的 C 条件中使用它:
@@ -931,23 +1039,45 @@ Vim 能够解释这样的标记:
        #endif /* CONFIG_SOMETHING */
 
 
-附录 I) 参考
--------------------
+附录 I) 参考资料
+----------------
 
-The C Programming Language, 第二版
+The C Programming Language, 2nd Edition
 作者:Brian W. Kernighan 和 Denni M. Ritchie.
 Prentice Hall, Inc., 1988.
-ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮).
+ISBN 0-13-110362-8 (平装), 0-13-110370-9 (精装).
+
+.. note::
+
+    《C程序设计语言(第2版)》
+    作者:[美] Brian W. Kernighan / [美] Dennis M. Ritchie
+    译者:徐宝文 / 李志 / 尤晋元(审校)
+    出版社:机械工业出版社,2019
+    ISBN:9787111617945
 
 The Practice of Programming
 作者:Brian W. Kernighan 和 Rob Pike.
 Addison-Wesley, Inc., 1999.
 ISBN 0-201-61586-X.
 
+.. note::
+
+    《程序设计实践》
+    作者:[美] Brian W. Kernighan / [美] Rob Pike
+    出版社:机械工业出版社,2005
+    ISBN:9787111091578
+
+    《程序设计实践》
+    作者:[美] Brian W. Kernighan / Rob Pike
+    译者:裘宗燕
+    出版社:机械工业出版社,2000
+    ISBN:9787111075738
+
 GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
 都可以从 https://www.gnu.org/manual/ 找到
 
 WG14 是 C 语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/
 
-Kernel process/coding-style.rst,作者 greg@kroah.com 发表于 OLS 2002:
+内核文档 Documentation/process/coding-style.rst,
+作者 greg@kroah.com 发表于 OLS 2002:
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
index 1020236..34d51cd 100644 (file)
@@ -1,17 +1,20 @@
-.. _cn_email_clients:
+.. SPDX-License-Identifier: GPL-2.0-or-later
 
 .. include:: ../disclaimer-zh_CN.rst
 
-:Original: :ref:`Documentation/process/email-clients.rst <email_clients>`
+.. _cn_email_clients:
 
-译者::
+:Original: Documentation/process/email-clients.rst
 
-        中文版维护者: 贾威威  Harry Wei <harryxiyou@gmail.com>
-        中文版翻译者: 贾威威  Harry Wei <harryxiyou@gmail.com>
-                       时奎亮  Alex Shi <alex.shi@linux.alibaba.com>
-        中文版校译者: Yinglin Luan <synmyth@gmail.com>
-                      Xiaochen Wang <wangxiaochen0@gmail.com>
-                       yaxinsn <yaxinsn@163.com>
+:译者:
+ - 贾威威  Harry Wei <harryxiyou@gmail.com>
+ - 时奎亮  Alex Shi <alexs@kernel.org>
+ - 吴想成  Wu XiangCheng <bobwxc@email.cn>
+
+:校译:
+ - Yinglin Luan <synmyth@gmail.com>
+ - Xiaochen Wang <wangxiaochen0@gmail.com>
+ - yaxinsn <yaxinsn@163.com>
 
 Linux邮件客户端配置信息
 =======================
@@ -27,12 +30,17 @@ Git
 改日志。如果工作正常,再将补丁发送到相应的邮件列表。
 
 
-普通配置
+通用配置
 --------
+
 Linux内核补丁是通过邮件被提交的,最好把补丁作为邮件体的内嵌文本。有些维护者
 接收附件,但是附件的内容格式应该是"text/plain"。然而,附件一般是不赞成的,
 因为这会使补丁的引用部分在评论过程中变的很困难。
 
+同时也强烈建议在补丁或其他邮件的正文中使用纯文本格式。https://useplaintext.email
+有助于了解如何配置你喜欢的邮件客户端,并在您还没有首选的情况下列出一些推荐的
+客户端。
+
 用来发送Linux内核补丁的邮件客户端在发送补丁时应该处于文本的原始状态。例如,
 他们不能改变或者删除制表符或者空格,甚至是在每一行的开头或者结尾。
 
@@ -40,17 +48,17 @@ Linux内核补丁是通过邮件被提交的,最好把补丁作为邮件体的
 
 不要让你的邮件客户端进行自动换行。这样也会破坏你的补丁。
 
-邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码方式,
-如果你使用UTF-8编码方式发送邮件,那么你将会避免一些可能发生的字符集问题。
+邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码
+方式,如果你使用UTF-8编码方式发送邮件,那么你将会避免一些可能发生的字符集问题。
 
-邮件客户端应该形成并且保持 References: 或者 In-Reply-To: 标题,那么
-邮件话题就不会中断。
+邮件客户端应该生成并且保持“References:”或者“In-Reply-To:”邮件头,这样邮件会话
+就不会中断。
 
-复制粘帖(或者剪贴粘帖)通常不能用于补丁,因为制表符会转换为空格。使用xclipboard, xclip
-或者xcutsel也许可以,但是最好测试一下或者避免使用复制粘帖。
+复制粘帖(或者剪贴粘帖)通常不能用于补丁,因为制表符会转换为空格。使用xclipboard,
+xclip或者xcutsel也许可以,但是最好测试一下或者避免使用复制粘帖。
 
-ä¸\8dè¦\81å\9c¨ä½¿ç\94¨PGP/GPGç½²å\90\8dç\9a\84é\82®ä»¶ä¸­å\8c\85å\90«è¡¥ä¸\81ã\80\82è¿\99æ ·ä¼\9a使å¾\97å¾\88å¤\9aè\84\9aæ\9c¬ä¸\8dè\83½è¯»å\8f\96å\92\8cé\80\82ç\94¨äº\8eä½ ç\9a\84è¡¥ä¸\81ã\80\82
-(这个问题应该是可以修复的)
+ä¸\8dè¦\81å\9c¨ä½¿ç\94¨PGP/GPGç­¾å\90\8dç\9a\84é\82®ä»¶ä¸­å\8c\85å\90«è¡¥ä¸\81ã\80\82è¿\99æ ·ä¼\9a使å¾\97å¾\88å¤\9aè\84\9aæ\9c¬ä¸\8dè\83½è¯»å\8f\96å\92\8cé\80\82ç\94¨äº\8eä½ ç\9a\84
+补丁。(这个问题应该是可以修复的)
 
 在给内核邮件列表发送补丁之前,给自己发送一个补丁是个不错的主意,保存接收到的
 邮件,将补丁用'patch'命令打上,如果成功了,再给内核邮件列表发送。
@@ -58,98 +66,133 @@ Linux内核补丁是通过邮件被提交的,最好把补丁作为邮件体的
 
 一些邮件客户端提示
 ------------------
+
 这里给出一些详细的MUA配置提示,可以用于给Linux内核发送补丁。这些并不意味是
 所有的软件包配置总结。
 
 说明:
-TUI = 以文本为基础的用户接口
-GUI = 图形界面用户接口
+
+- TUI = 以文本为基础的用户接口
+- GUI = 图形界面用户接口
 
 Alpine (TUI)
-~~~~~~~~~~~~
+************
 
 配置选项:
-在"Sending Preferences"部分:
 
-- "Do Not Send Flowed Text"必须开启
-- "Strip Whitespace Before Sending"必须关闭
+在 :menuselection:`Sending Preferences` 菜单:
+
+- :menuselection:`Do Not Send Flowed Text` 必须开启
+- :menuselection:`Strip Whitespace Before Sending` 必须关闭
+
+当写邮件时,光标应该放在补丁会出现的地方,然后按下 :kbd:`CTRL-R` 组合键,使指
+定的补丁文件嵌入到邮件中。
+
+Claws Mail (GUI)
+****************
+
+可以用,有人用它成功地发过补丁。
 
-当写邮件时,光标应该放在补丁会出现的地方,然后按下CTRL-R组合键,使指定的
-补丁文件嵌入到邮件中。
+用 :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`) 或外置编辑器插入补丁。
+
+若要在Claws编辑窗口重修改插入的补丁,需关闭
+:menuselection:`Configuration-->Preferences-->Compose-->Wrapping`
+的 `Auto wrapping` 。
 
 Evolution (GUI)
-~~~~~~~~~~~~~~~
+***************
 
-一些开发者成功的使用它发送补丁
+一些开发者成功的使用它发送补丁
 
-当选择邮件选项:Preformat
-  从Format->Heading->Preformatted (Ctrl-7)或者工具栏
+撰写邮件时:
+从 :menuselection:`格式-->段落样式-->预格式化` (:kbd:`CTRL-7`)
+或工具栏选择 :menuselection:`预格式化` ;
 
 然后使用:
-  Insert->Text File... (Alt-n x)插入补丁文件。
+:menuselection:`插入-->文本文件...` (:kbd:`ALT-N x`) 插入补丁文件。
 
-你还可以"diff -Nru old.c new.c | xclip",选择Preformat,然后使用中间键进行粘帖。
+你还可以 ``diff -Nru old.c new.c | xclip`` ,选择 :menuselection:`预格式化` ,
+然后使用鼠标中键进行粘帖。
 
 Kmail (GUI)
-~~~~~~~~~~~
+***********
 
 一些开发者成功的使用它发送补丁。
 
-默认设置不为HTML格式是合适的;不要启用它。
+默认撰写设置禁用HTML格式是合适的;不要启用它。
 
-当书写一封邮件的时候,在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输入的任何文本
-都不会被自动换行,因此你必须在发送补丁之前手动换行。最简单的方法就是启用自动换行来书写邮件,
-然后把它保存为草稿。一旦你在草稿中再次打开它,它已经全部自动换行了,那么你的邮件虽然没有
-选择自动换行,但是还不会失去已有的自动换行。
+当书写一封邮件的时候,在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输
+入的任何文本都不会被自动换行,因此你必须在发送补丁之前手动换行。最简单的方法
+就是启用自动换行来书写邮件,然后把它保存为草稿。一旦你在草稿中再次打开它,它
+已经全部自动换行了,那么你的邮件虽然没有选择自动换行,但是还不会失去已有的自
+动换行。
 
-在邮件的底部,插入补丁之前,放上常用的补丁定界符:三个连字号(---)。
+在邮件的底部,插入补丁之前,放上常用的补丁定界符:三个连字符(``---``)。
 
-然后在"Message"菜单条目,选择插入文件,接着选取你的补丁文件。还有一个额外的选项,你可以
-通过它配置你的邮件建立工具栏菜单,还可以带上"insert file"图标。
+然后在 :menuselection:`信件` 菜单,选择 :menuselection:`插入文本文件` ,接
+着选取你的补丁文件。还有一个额外的选项,你可以通过它配置你的创建新邮件工具栏,
+加上 :menuselection:`插入文本文件` 图标。
 
-你可以安全地通过GPG标记附件,但是内嵌补丁最好不要使用GPG标记它们。作为内嵌文本的签发补丁,
-当从GPG中提取7位编码时会使他们变的更加复杂。
+将编辑器窗口拉到足够宽避免折行。对于KMail 1.13.5 (KDE 4.5.4),它会在发送邮件
+时对编辑器窗口中显示折行的地方自动换行。在选项菜单中取消自动换行仍不能解决。
+因此,如果你的补丁中有非常长的行,必须在发送之前把编辑器窗口拉得非常宽。
+参见:https://bugs.kde.org/show_bug.cgi?id=174034
 
-如果你非要以附件的形式发送补丁,那么就右键点击附件,然后选中属性,突出"Suggest automatic
-display",这样内嵌附件更容易让读者看到
+你可以安全地用GPG签名附件,但是内嵌补丁最好不要使用GPG签名它们。作为内嵌文本
+插入的签名补丁将使其难以从7-bit编码中提取
 
-当你要保存将要发送的内嵌文本补丁,你可以从消息列表窗格选择包含补丁的邮件,然后右击选择
-"save as"。你可以使用一个没有更改的包含补丁的邮件,如果它是以正确的形式组成。当你正真在它
-自己的窗口之下察看,那时没有选项可以保存邮件--已经有一个这样的bug被汇报到了kmail的bugzilla
-并且希望这将会被处理。邮件是以只针对某个用户可读写的权限被保存的,所以如果你想把邮件复制到其他地方,
-你不得不把他们的权限改为组或者整体可读。
+如果你非要以附件的形式发送补丁,那么就右键点击附件,然后选择
+:menuselection:`属性` ,打开 :menuselection:`建议自动显示` ,使附件内联更容
+易让读者看到。
+
+当你要保存将要发送的内嵌文本补丁,你可以从消息列表窗格选择包含补丁的邮件,然
+后右键选择 :menuselection:`另存为` 。如果整个电子邮件的组成正确,您可直接将
+其作为补丁使用。电子邮件以当前用户可读写权限保存,因此您必须 ``chmod`` ,以
+使其在复制到别处时用户组和其他人可读。
 
 Lotus Notes (GUI)
-~~~~~~~~~~~~~~~~~
+*****************
 
 不要使用它。
 
+IBM Verse (Web GUI)
+*******************
+
+同上条。
+
 Mutt (TUI)
-~~~~~~~~~~
+**********
+
+很多Linux开发人员使用mutt客户端,这证明它肯定工作得非常漂亮。
 
-很多Linux开发人员使用mutt客户端,所以证明它肯定工作的非常漂亮。
+Mutt不自带编辑器,所以不管你使用什么编辑器,不自动断行就行。大多数编辑器都有
+:menuselection:`插入文件` 选项,它可以在不改变文件内容的情况下插入文件。
 
-Mutt不自带编辑器,所以不管你使用什么编辑器都不应该带有自动断行。大多数编辑器都带有
-一个"insert file"选项,它可以通过不改变文件内容的方式插入文件。
+用 ``vim`` 作为mutt的编辑器::
 
-'vim'作为mutt的编辑器:
   set editor="vi"
 
-  如果使用xclip,敲入以下命令
+如果使用xclip,敲入以下命令::
+
   :set paste
-  按中键之前或者shift-insert或者使用
+
+然后再按中键或者shift-insert或者使用::
+
   :r filename
 
-如果想要把补丁作为内嵌文本。
-(a)ttach工作的很好,不带有"set paste"
+把补丁插入为内嵌文本。
+在未设置  ``set paste`` 时(a)ttach工作的很好
 
 你可以通过 ``git format-patch`` 生成补丁,然后用 Mutt发送它们::
 
-        $ mutt -H 0001-some-bug-fix.patch
+    $ mutt -H 0001-some-bug-fix.patch
 
 配置选项:
+
 它应该以默认设置的形式工作。
-然而,把"send_charset"设置为"us-ascii::utf-8"也是一个不错的主意。
+然而,把 ``send_charset`` 设置一下也是一个不错的主意::
+
+  set send_charset="us-ascii:utf-8"
 
 Mutt 是高度可配置的。 这里是个使用mutt通过 Gmail 发送的补丁的最小配置::
 
@@ -178,71 +221,107 @@ Mutt 是高度可配置的。 这里是个使用mutt通过 Gmail 发送的补丁
   set from = "username@gmail.com"
   set use_from = yes
 
-Mutt文档含有更多信息:
+Mutt文档含有更多信息
 
-    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+    https://gitlab.com/muttmua/mutt/-/wikis/UseCases/Gmail
 
-    http://dev.mutt.org/doc/manual.html
+    http://www.mutt.org/doc/manual/
 
 Pine (TUI)
-~~~~~~~~~~
+**********
 
 Pine过去有一些空格删减问题,但是这些现在应该都被修复了。
 
-如果可以,请使用alpine(pine的继承者)
+如果可以,请使用alpine(pine的继承者)。
 
 配置选项:
-- 最近的版本需要消除流程文本
-- "no-strip-whitespace-before-send"选项也是需要的。
+
+- 最近的版本需要 ``quell-flowed-text``
+- ``no-strip-whitespace-before-send`` 选项也是需要的。
 
 
 Sylpheed (GUI)
-~~~~~~~~~~~~~~
+**************
 
 - 内嵌文本可以很好的工作(或者使用附件)。
 - 允许使用外部的编辑器。
-- 对于目录较多时非常慢。
+- 收件箱较多时非常慢。
 - 如果通过non-SSL连接,无法使用TLS SMTP授权。
-- 在组成窗口中有一个很有用的ruler bar
-- 给地址本中添加地址就不会正确的了解显示名
+- 撰写窗口的标尺很有用
+- 将地址添加到通讯簿时无法正确理解显示的名称
 
 Thunderbird (GUI)
-~~~~~~~~~~~~~~~~~
+*****************
+
+Thunderbird是Outlook的克隆版本,它很容易损坏文本,但也有一些方法强制修正。
+
+在完成修改后(包括安装扩展),您需要重新启动Thunderbird。
+
+- 允许使用外部编辑器:
+
+  使用Thunderbird发补丁最简单的方法是使用扩展来打开您最喜欢的外部编辑器。
+
+  下面是一些能够做到这一点的扩展样例。
+
+  - “External Editor Revived”
+
+    https://github.com/Frederick888/external-editor-revived
+
+    https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+    它需要安装“本地消息主机(native messaging host)”。
+    参见以下文档:
+    https://github.com/Frederick888/external-editor-revived/wiki
+
+  - “External Editor”
+
+    https://github.com/exteditor/exteditor
+
+    下载并安装此扩展,然后打开 :menuselection:`新建消息` 窗口, 用
+    :menuselection:`查看-->工具栏-->自定义...` 给它增加一个按钮,直接点击此
+    按钮即可使用外置编辑器。
+
+    请注意,“External Editor”要求你的编辑器不能fork,换句话说,编辑器必须在
+    关闭前不返回。你可能需要传递额外的参数或修改编辑器设置。最值得注意的是,
+    如果您使用的是gvim,那么您必须将 :menuselection:`external editor` 设置的
+    编辑器字段设置为 ``/usr/bin/gvim --nofork"`` (假设可执行文件在
+    ``/usr/bin`` ),以传递 ``-f`` 参数。如果您正在使用其他编辑器,请阅读其
+    手册了解如何处理。
 
-默认情况下,thunderbird很容易损坏文本,但是还有一些方法可以强制它变得更好。
+若要修正内部编辑器,请执行以下操作:
 
-- 在用户帐号设置里,组成和寻址,不要选择"Compose messages in HTML format"。
+- 修改你的Thunderbird设置,不要使用 ``format=flowed`` !
+  回到主窗口,按照
+  :menuselection:`主菜单-->首选项-->常规-->配置编辑器...`
+  打开Thunderbird的配置编辑器。
 
-- 编辑你的Thunderbird配置设置来使它不要拆行使用:user_pref("mailnews.wraplength", 0);
+  - 将 ``mailnews.send_plaintext_flowed`` 设为 ``false``
 
-- 编辑你的Thunderbird配置设置,使它不要使用"format=flowed"格式:user_pref("mailnews.
-  send_plaintext_flowed", false);
+  - 将 ``mailnews.wraplength`` 从 ``72`` 改为 ``0``
 
-- 你需要使Thunderbird变为预先格式方式:
-  如果默认情况下你书写的是HTML格式,那不是很难。仅仅从标题栏的下拉框中选择"Preformat"格式。
-  如果默认情况下你书写的是文本格式,你不得把它改为HTML格式(仅仅作为一次性的)来书写新的消息,
-  然后强制使它回到文本格式,否则它就会拆行。要实现它,在写信的图标上使用shift键来使它变为HTML
-  格式,然后标题栏的下拉框中选择"Preformat"格式。
+- 不要写HTML邮件!
+  回到主窗口,打开
+  :menuselection:`主菜单-->账户设置-->你的@邮件.地址-->通讯录/编写&地址簿` ,
+  关掉 ``以HTML格式编写消息`` 。
 
-- 允许使用外部的编辑器:
-  针对Thunderbird打补丁最简单的方法就是使用一个"external editor"扩展,然后使用你最喜欢的
-  $EDITOR来读取或者合并补丁到文本中。要实现它,可以下载并且安装这个扩展,然后添加一个使用它的
-  按键View->Toolbars->Customize...最后当你书写信息的时候仅仅点击它就可以了。
+- 只用纯文本格式查看邮件!
+  回到主窗口, :menuselection:`主菜单-->查看-->消息体为-->纯文本` !
 
 TkRat (GUI)
-~~~~~~~~~~~
+***********
 
 可以使用它。使用"Insert file..."或者外部的编辑器。
 
 Gmail (Web GUI)
-~~~~~~~~~~~~~~~
+***************
 
 不要使用它发送补丁。
 
 Gmail网页客户端自动地把制表符转换为空格。
 
-虽然制表符转换为空格问题可以被外部编辑器解决,同时它还会使用回车换行把每行拆分为78个字符。
+虽然制表符转换为空格问题可以被外部编辑器解决,但它同时还会使用回车换行把每行
+拆分为78个字符。
 
-另一个问题是Gmail还会把任何不是ASCII的字符的信息改为base64编码。它把东西变的像欧洲人的名字。
+另一个问题是Gmail还会把任何含有非ASCII的字符的消息改用base64编码,如欧洲人的
+名字。
 
-                                ###
index a64858d..3d6ee21 100644 (file)
 .. include:: ../disclaimer-zh_CN.rst
 
-:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
-:Translator: Alex Shi <alex.shi@linux.alibaba.com>
+:Original: Documentation/process/submit-checklist.rst
+:Translator:
+ - Alex Shi <alexs@kernel.org>
+ - Wu XiangCheng <bobwxc@email.cn>
 
 .. _cn_submitchecklist:
 
-Linuxå\86\85核补ä¸\81æ\8f\90交æ¸\85
-~~~~~~~~~~~~~~~~~~~~~
+Linuxå\86\85核补ä¸\81æ\8f\90交æ£\80æ\9f¥
+~~~~~~~~~~~~~~~~~~~~~~~
 
 如果开发人员希望看到他们的内核补丁提交更快地被接受,那么他们应该做一些基本
 的事情。
 
-这些都是在
-:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>`
+这些都是在 Documentation/translations/zh_CN/process/submitting-patches.rst
 和其他有关提交Linux内核补丁的文档中提供的。
 
-1) 如果使用工具,则包括定义/声明该工具的文件。不要依赖于其他头文件拉入您使用
+1) 如果使用工具,则包括定义/声明该工具的文件。不要依赖其他头文件来引入您使用
    的头文件。
 
 2) 干净的编译:
 
-   a) 使用适用或修改的 ``CONFIG`` 选项 ``=y``、``=m`` 和 ``=n`` 。没有GCC
+   a) 使用合适的 ``CONFIG`` 选项 ``=y``、``=m`` 和 ``=n`` 。没有 ``gcc``
       警告/错误,没有链接器警告/错误。
 
-   b) 通过allnoconfig、allmodconfig
+   b) 通过 ``allnoconfig`` 、 ``allmodconfig``
 
    c) 使用 ``O=builddir`` 时可以成功编译
 
-3) 通过使用本地交叉编译工具或其他一些构建场在多个CPU体系结构上构建。
+   d) 任何 Doucmentation/ 下的变更都能成功构建且不引入新警告/错误。
+      用 ``make htmldocs`` 或 ``make pdfdocs`` 检验构建情况并修复问题。
+
+3) 通过使用本地交叉编译工具或其他一些构建设施在多个CPU体系结构上构建。
 
 4) PPC64是一种很好的交叉编译检查体系结构,因为它倾向于对64位的数使用无符号
    长整型。
 
-5) 如下所述 :ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>`.
-   检查您的补丁是否为常规样式。在提交( ``scripts/check patch.pl`` )之前,
-   使用补丁样式检查器检查是否有轻微的冲突。您应该能够处理您的补丁中存在的所有
+5) 按 Documentation/translations/zh_CN/process/coding-style.rst 所述检查您的
+   补丁是否为常规样式。在提交之前使用补丁样式检查器 ``scripts/checkpatch.pl``
+   检查是否有轻微的冲突。您应该能够处理您的补丁中存在的所有
    违规行为。
 
-6) 任何新的或修改过的 ``CONFIG`` 选项都不会弄脏配置菜单,并默认为关闭,除非
-   它们符合 ``Documentation/kbuild/kconfig-language.rst`` 中记录的异常条件,
-   è\8f\9cå\8d\95å±\9eæ\80§ï¼\9aé»\98认å\80¼.
+6) 任何新的或修改过的 ``CONFIG`` 选项都不应搞乱配置菜单,并默认为关闭,除非
+   它们符合 ``Documentation/kbuild/kconfig-language.rst`` 菜单属性:默认值中
+   è®°å½\95ç\9a\84ä¾\8bå¤\96æ\9d¡ä»¶ã\80\82
 
 7) 所有新的 ``kconfig`` 选项都有帮助文本。
 
 8) 已仔细审查了相关的 ``Kconfig`` 组合。这很难用测试来纠正——脑力在这里是有
    回报的。
 
-9) 用 sparse 检查干净。
+9) 通过 sparse 清查。
+   (参见 Documentation/translations/zh_CN/dev-tools/sparse.rst )
 
 10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 并修复他们发现的任何
     问题。
 
     .. note::
 
-        ``checkstack`` 并没有明确指出问题,但是任何一个在堆栈上使用超过512
+        ``checkstack`` 并不会明确指出问题,但是任何一个在堆栈上使用超过512
         字节的函数都可以进行更改。
 
-11) 包括 :ref:`kernel-doc <kernel_doc>` 内核文档以记录全局内核API。(静态函数
-    不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 检查
-    :ref:`kernel-doc <kernel_doc>` 并修复任何问题。
+11) 包括 :ref:`kernel-doc <kernel_doc_zh>` 内核文档以记录全局内核API。(静态
+    函数不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 检查
+    :ref:`kernel-doc <kernel_doc_zh>` 并修复任何问题。
 
-12) 通过以下选项同时启用的测试 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+12) 通过以下选项同时启用的测试 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
     ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
     ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
-    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD``
-
-13) 已经过构建和运行时测试,包括有或没有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``.
+    ``CONFIG_PROVE_RCU`` 和 ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` 。
 
-14) 如果补丁程序影响IO/磁盘等:使用或不使用 ``CONFIG_LBDAF`` 进行测试。
+13) 在 ``CONFIG_SMP``, ``CONFIG_PREEMPT`` 开启和关闭的情况下都进行构建和运行
+    时测试。
 
-15) 所有代码路径都已在启用所有lockdep功能的情况下运行。
+14) 所有代码路径都已在启用所有死锁检测(lockdep)功能的情况下运行。
 
-16) 所有新的/proc条目都记录在 ``Documentation/``
+15) 所有新的 ``/proc`` 条目都记录在 ``Documentation/``
 
-17) 所有新的内核引导参数都记录在
+16) 所有新的内核引导参数都记录在
     Documentation/admin-guide/kernel-parameters.rst 中。
 
-18) 所有新的模块参数都记录在 ``MODULE_PARM_DESC()``
+17) 所有新的模块参数都记录在 ``MODULE_PARM_DESC()``
 
-19) 所有新的用户空间接口都记录在 ``Documentation/ABI/`` 中。有关详细信息,
+18) 所有新的用户空间接口都记录在 ``Documentation/ABI/`` 中。有关详细信息,
     请参阅 ``Documentation/ABI/README`` 。更改用户空间接口的补丁应该抄送
     linux-api@vger.kernel.org。
 
-20) 已通过至少注入slab和page分配失败进行检查。请参阅 ``Documentation/fault-injection/``
+19) 已通过至少注入slab和page分配失败进行检查。请参阅 ``Documentation/fault-injection/`` 。
     如果新代码是实质性的,那么添加子系统特定的故障注入可能是合适的。
 
-21) 新添加的代码已经用 ``gcc -W`` 编译(使用 ``make EXTRA-CFLAGS=-W`` )。这
+20) 新添加的代码已经用 ``gcc -W`` 编译(使用 ``make EXTRA-CFLAGS=-W`` )。这
     将产生大量噪声,但对于查找诸如“警告:有符号和无符号之间的比较”之类的错误
     很有用。
 
-22) 在它被合并到-mm补丁集中之后进行测试,以确保它仍然与所有其他排队的补丁以
+21) 在它被合并到-mm补丁集中之后进行测试,以确保它仍然与所有其他排队的补丁以
     及VM、VFS和其他子系统中的各种更改一起工作。
 
-23) 所有内存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要源代码中的
+22) 所有内存屏障(例如 ``barrier()``, ``rmb()``, ``wmb()`` )都需要源代码
     释来解释它们正在执行的操作及其原因的逻辑。
 
-24) 如果补丁添加了任何ioctl,那么也要更新 ``Documentation/userspace-api/ioctl/ioctl-number.rst``
+23) 如果补丁添加了任何ioctl,那么也要更新
+    ``Documentation/userspace-api/ioctl/ioctl-number.rst`` 。
 
-25) 如果修改后的源代码依赖或使用与以下 ``Kconfig`` 符号相关的任何内核API或
+24) 如果修改后的源代码依赖或使用与以下 ``Kconfig`` 符号相关的任何内核API或
     功能,则在禁用相关 ``Kconfig`` 符号和/或 ``=m`` (如果该选项可用)的情况
     下测试以下多个构建[并非所有这些都同时存在,只是它们的各种/随机组合]:
 
-    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
-    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是后者伴随 ``CONFIG_NET=y``).
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``,
+    ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (但是最后一个需要 ``CONFIG_NET=y`` )。
index ebb7f37..f8978f0 100644 (file)
-.. _cn_submittingpatches:
+.. SPDX-License-Identifier: GPL-2.0-or-later
 
 .. include:: ../disclaimer-zh_CN.rst
 
-:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+.. _cn_submittingpatches:
+
+:Original: Documentation/process/submitting-patches.rst
 
-译者::
+:译者:
+ - 钟宇 TripleX Chung <xxx.phy@gmail.com>
+ - 时奎亮 Alex Shi <alexs@kernel.org>
+ - 吴想成 Wu XiangCheng <bobwxc@email.cn>
 
-        中文版维护者: 钟宇 TripleX Chung <xxx.phy@gmail.com>
-        中文版翻译者: 钟宇 TripleX Chung <xxx.phy@gmail.com>
-                       时奎亮 Alex Shi <alex.shi@linux.alibaba.com>
-        中文版校译者: 李阳 Li Yang <leoyang.li@nxp.com>
-                       王聪 Wang Cong <xiyou.wangcong@gmail.com>
+:校译:
+ - 李阳 Li Yang <leoyang.li@nxp.com>
+ - 王聪 Wang Cong <xiyou.wangcong@gmail.com>
 
 
-如何让你的改动进入内核
-======================
+提交补丁:如何让你的改动进入内核
+================================
 
 对于想要将改动提交到 Linux 内核的个人或者公司来说,如果不熟悉“规矩”,
-提交的流程会让人畏惧。本文档收集了一系列建议,这些建议可以大大的提高你
+提交的流程会让人畏惧。本文档包含了一系列建议,可以大大提高你
 的改动被接受的机会.
 
-以下文档含有大量简洁的建议, 具体请见:
-:ref:`Documentation/process <development_process_main>`
-同样,:ref:`Documentation/translations/zh_CN/process/submit-checklist.rst <cn_submitchecklist>`
-给出在提交代码前需要检查的项目的列表。
+本文档以较为简洁的行文给出了大量建议。关于内核开发流程如何进行的详细信息,
+参见: Documentation/translations/zh_CN/process/development-process.rst 。
+Documentation/translations/zh_CN/process/submit-checklist.rst 给出了一系列
+提交补丁之前要检查的事项。设备树相关的补丁,请参阅
+Documentation/devicetree/bindings/submitting-patches.rst 。
 
-其中许多步骤描述了Git版本控制系统的默认行为;如果您使用Git来准备补丁,
-您将发现它为您完成的大部分机械工作,尽管您仍然需要准备和记录一组合理的
-补丁。一般来说,使用git将使您作为内核开发人员的生活更轻松。
+本文档假设您正在使用 ``git`` 准备你的补丁。如果您不熟悉 ``git`` ,最好学习
+如何使用它,这将使您作为内核开发人员的生活变得更加轻松。
 
+部分子系统和维护人员的树有一些关于其工作流程和要求的额外信息,请参阅
+Documentation/process/maintainer-handbooks.rst 。
 
-0) 获取当前源码树
------------------
+获取当前源码树
+--------------
 
-å¦\82æ\9e\9cæ\82¨æ²¡æ\9c\89ä¸\80个å\8f¯ä»¥ä½¿ç\94¨å½\93å\89\8då\86\85æ ¸æº\90代ç \81ç\9a\84å­\98å\82¨åº\93ï¼\8c请使ç\94¨gitè\8e·å\8f\96ä¸\80个ã\80\82æ\82¨å°\86è¦\81
»\8e主线å­\98å\82¨åº\93å¼\80å§\8bï¼\8cå®\83å\8f¯ä»¥é\80\9aè¿\87以ä¸\8bæ\96¹å¼\8fè\8e·取::
+å¦\82æ\9e\9cæ\82¨æ\89\8b头没æ\9c\89å½\93å\89\8då\86\85æ ¸æº\90代ç \81ç\9a\84å­\98å\82¨åº\93ï¼\8c请使ç\94¨ ``git`` è\8e·å\8f\96ä¸\80份ã\80\82æ\82¨é\9c\80è¦\81å\85\88è\8e·å\8f\96
¸»çº¿å­\98å\82¨åº\93ï¼\8cå®\83å\8f¯ä»¥é\80\9aè¿\87以ä¸\8bå\91½ä»¤æ\8b\89取::
 
-        git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+    git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
 
-但是,请注意,您可能不希望直接针对主线树进行开发。大多数子系统维护人员运
+但是,请注意,您可能不直接针对主线树进行开发。大多数子系统维护人员运
 行自己的树,并希望看到针对这些树准备的补丁。请参见MAINTAINERS文件中子系
-统的 **T:** 项以查找该树,或者简单地询问维护者该树是否未在其中列出。
-
-仍然可以通过tarballs下载内核版本(如下一节所述),但这是进行内核开发的
-一种困难的方式。
-
-1) "diff -up"
--------------
-
-使用 "diff -up" 或者 "diff -uprN" 来创建补丁。
-
-所有内核的改动,都是以补丁的形式呈现的,补丁由 diff(1) 生成。创建补丁的
-时候,要确认它是以 "unified diff" 格式创建的,这种格式由 diff(1) 的 '-u'
-参数生成。而且,请使用 '-p' 参数,那样会显示每个改动所在的C函数,使得
-产生的补丁容易读得多。补丁应该基于内核源代码树的根目录,而不是里边的任
-何子目录。
-
-为一个单独的文件创建补丁,一般来说这样做就够了::
-
-        SRCTREE=linux
-        MYFILE=drivers/net/mydriver.c
+统的 **T:** 项以查找该树,或者直接询问维护者该树是否未在其中列出。
 
-        cd $SRCTREE
-        cp $MYFILE $MYFILE.orig
-        vi $MYFILE      # make your change
-        cd ..
-        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+.. _zh_describe_changes:
 
-为多个文件创建补丁,你可以解开一个没有修改过的内核源代码树,然后和你自
-己的代码树之间做 diff 。例如::
-
-        MYSRC=/devel/linux
-
-        tar xvfz linux-3.19.tar.gz
-        mv linux-3.19 linux-3.19-vanilla
-        diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
-                linux-3.19-vanilla $MYSRC > /tmp/patch
-
-"dontdiff" 是内核在编译的时候产生的文件的列表,列表中的文件在 diff(1)
-产生的补丁里会被跳过。
-
-确定你的补丁里没有包含任何不属于这次补丁提交的额外文件。记得在用diff(1)
-生成补丁之后,审阅一次补丁,以确保准确。
-
-如果你的改动很散乱,你应该研究一下如何将补丁分割成独立的部分,将改动分
-割成一系列合乎逻辑的步骤。这样更容易让其他内核开发者审核,如果你想你的
-补丁被接受,这是很重要的。请参阅:
-:ref:`cn_split_changes`
-
-如果你用 ``git`` , ``git rebase -i`` 可以帮助你这一点。如果你不用 ``git``,
-``quilt`` <https://savannah.nongnu.org/projects/quilt> 另外一个流行的选择。
-
-.. _cn_describe_changes:
-
-2) 描述你的改动
----------------
+描述你的改动
+------------
 
 描述你的问题。无论您的补丁是一行错误修复还是5000行新功能,都必须有一个潜在
\9a\84é\97®é¢\98æ¿\80å\8a±æ\82¨å®\8cæ\88\90è¿\99项工ä½\9cã\80\82让审稿人相信有一个问题值得解决,让他们读完第一段
-是有意义的
\9a\84é\97®é¢\98æ¿\80å\8a±æ\82¨å®\8cæ\88\90è¿\99项工ä½\9cã\80\82说æ\9c\8d审é\98\85è\80\85相信有一个问题值得解决,让他们读完第一段
+后就能明白这一点
 
 描述用户可见的影响。直接崩溃和锁定是相当有说服力的,但并不是所有的错误都那么
-明目张胆。即使在代码审期间发现了这个问题,也要描述一下您认为它可能对用户产
+明目张胆。即使在代码审期间发现了这个问题,也要描述一下您认为它可能对用户产
 生的影响。请记住,大多数Linux安装运行的内核来自二级稳定树或特定于供应商/产品
 的树,只从上游精选特定的补丁,因此请包含任何可以帮助您将更改定位到下游的内容:
 触发的场景、DMESG的摘录、崩溃描述、性能回归、延迟尖峰、锁定等。
 
-量化优化和权衡。如果您声称在性能、内存消耗、堆栈占用空间或二进制大小方面有所
-改进,请包括支持它们的数字。但也要描述不明显的成本。优化通常不是免费的,而是
-在CPU、内存和可读性之间进行权衡;或者,探索性的工作,在不同的工作负载之间进
+质量优化和权衡。如果您声称在性能、内存消耗、堆栈占用空间或二进制大小方面有所
+改进,请包括支持它们的数据。但也要描述不明显的成本。优化通常不是零成本的,而是
+在CPU、内存和可读性之间进行权衡;或者,探索性的工作,在不同的工作负载之间进
 行权衡。请描述优化的预期缺点,以便审阅者可以权衡成本和收益。
 
-一旦问题建立起来,就要详细地描述一下您实际在做什么。对于审阅者来说,用简单
-英语描述代码的变化是很重要的,以验证代码的行为是否符合您的意
+提出问题之后,就要详细地描述一下您实际在做的技术细节。对于审阅者来说,用简练
+英语描述代码的变化是很重要的,以验证代码的行为是否符合您的意
 
-如果您将补丁描述写在一个表单中,这个表单可以很容易地作为“提交日志”放入Linux
-的源代码管理系统git中,那么维护人员将非常感谢您。见 :ref:`cn_explicit_in_reply_to`.
+如果您将补丁描述写成“标准格式”,可以很容易地作为“提交日志”放入Linux的源代
+码管理系统 ``git`` 中,那么维护人员将非常感谢您。
+参见 :ref:`zh_the_canonical_patch_format` 。
 
 每个补丁只解决一个问题。如果你的描述开始变长,这就表明你可能需要拆分你的补丁。
-请见 :ref:`cn_split_changes`
+请见 :ref:`zh_split_changes` 。
 
-提交或重新提交修补程序或修补程序系列时,请包括完整的修补程序说明和理由。不要
+提交或重新提交补丁或补丁系列时,请包括完整的补丁说明和理由。不要
 只说这是补丁(系列)的第几版。不要期望子系统维护人员引用更早的补丁版本或引用
 URL来查找补丁描述并将其放入补丁中。也就是说,补丁(系列)及其描述应该是独立的。
-这对维护人员和审查人员都有好处。一些评审者可能甚至没有收到补丁的早期版本。
+这对维护人员和审阅者都有好处。一些审阅者可能甚至没有收到补丁的早期版本。
 
-描述你在命令语气中的变化,例如“make xyzzy do frotz”而不是“[This patch]make
+用祈使句描述你的变更,例如“make xyzzy do frotz”而不是“[This patch]make
 xyzzy do frotz”或“[I]changed xyzzy to do frotz”,就好像你在命令代码库改变
 它的行为一样。
 
-如果修补程序修复了一个记录的bug条目,请按编号和URL引用该bug条目。如果补丁来
-自邮件列表讨论,请给出邮件列表存档的URL;使用带有 ``Message-ID`` 的
-https://lore.kernel.org/ 重定向,以确保链接不会过时。
-
-但是,在没有外部资源的情况下,尽量让你的解释可理解。除了提供邮件列表存档或
-bug的URL之外,还要总结需要提交补丁的相关讨论要点。
-
-如果您想要引用一个特定的提交,不要只引用提交的 SHA-1 ID。还请包括提交的一行
+如果您想要引用一个特定的提交,不要只引用提交的SHA-1 ID。还请包括提交的一行
 摘要,以便于审阅者了解它是关于什么的。例如::
 
         Commit e21d2170f36602ae2708 ("video: remove unnecessary
@@ -144,82 +94,104 @@ bug的URL之外,还要总结需要提交补丁的相关讨论要点。
         platform_set_drvdata(), but left the variable "dev" unused,
         delete it.
 
-您还应该确保至少使用前12位 SHA-1 ID. 内核存储库包含*许多*对象,使与较短的ID
+您还应该确保至少使用前12位SHA-1 ID。内核存储库包含 *许多* 对象,使较短的ID
 发生冲突的可能性很大。记住,即使现在不会与您的六个字符ID发生冲突,这种情况
-可能五年后改变。
+也可能在五年后改变。
+
+如果该变更的相关讨论或背景信息可以在网上查阅,请加上“Link:”标签指向它。例如
+你的补丁修复了一个缺陷,需要添加一个带有URL的标签指向邮件列表存档或缺陷跟踪器
+的相关报告;如果该补丁是由一些早先邮件列表讨论或网络上的记录引起的,请指向它。
+
+当链接到邮件列表存档时,请首选lore.kernel.org邮件存档服务。用邮件中的
+``Message-ID`` 头(去掉尖括号)可以创建链接URL。例如::
+
+    Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
+
+请检查该链接以确保可用且指向正确的邮件。
 
-如果修补程序修复了特定提交中的错误,例如,使用 ``git bisct`` ,请使用带有前
-12个字符SHA-1 ID 的"Fixes:"标记和单行摘要。为了简化不要将标记拆分为多个,
-行、标记不受分析脚本“75列换行”规则的限制。例如::
+不过,在没有外部资源的情况下,也要尽量让你的解释可理解。除了提供邮件列表存档或
+缺陷的URL之外,还要需要总结该补丁的相关讨论要点。
 
-        Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+如果补丁修复了特定提交中的错误,例如使用 ``git bisct`` 发现了一个问题,请使用
+带有前12个字符SHA-1 ID的“Fixes:”标签和单行摘要。为了简化解析脚本,不要将该
+标签拆分为多行,标签不受“75列换行”规则的限制。例如::
 
-下列 ``git config`` 设置可以添加让 ``git log``, ``git show`` 漂亮的显示格式::
+  Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
+
+下列 ``git config`` 设置可以让 ``git log``, ``git show`` 增加上述风格的显示格式::
 
        [core]
                abbrev = 12
        [pretty]
                fixes = Fixes: %h (\"%s\")
 
-.. _cn_split_changes:
+使用示例::
+
+       $ git log -1 --pretty=fixes 54a4f0239f2e
+       Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
 
-3) 拆分你的改动
----------------
+.. _zh_split_changes:
 
-将每个逻辑更改分隔成一个单独的补丁。
+拆分你的改动
+------------
+
+将每个 **逻辑更改** 拆分成一个单独的补丁。
 
 例如,如果你的改动里同时有bug修正和性能优化,那么把这些改动拆分到两个或
-者更多的补丁文件中。如果你的改动包含对API的修改,并且修改了驱动程序来适
-应这些新的API,那么把这些修改分成两个补丁。
+者更多的补丁文件中。如果你的改动包含对API的修改,并且增加了一个使用该新API
+的驱动,那么把这些修改分成两个补丁。
 
 另一方面,如果你将一个单独的改动做成多个补丁文件,那么将它们合并成一个
 单独的补丁文件。这样一个逻辑上单独的改动只被包含在一个补丁文件里。
 
-如果有一个补丁依赖另外一个补丁来完成它的改动,那没问题。简单的在你的补
-丁描述里指出“这个补丁依赖某补丁”就好了。
+需要记住的一点是,每个补丁的更改都应易于理解,以便审阅者验证。每个补丁都应该
+对其价值进行阐述。
+
+如果有一个补丁依赖另外一个补丁来完成它的改动,那没问题。直接在你的补
+丁描述里指出 **“这个补丁依赖某补丁”** 就好了。
 
-在将您的更改划分为一系列补丁时,要特别注意确保内核在系列中的每个补丁之后
-都能正常构建和运行。使用 ``git bisect`` 来追踪问题的开发者可能会在任何
\80\99å\88\86å\89²ä½ ç\9a\84è¡¥ä¸\81ç³»å\88\97ï¼\9bå¦\82æ\9e\9cä½ å\9c¨ä¸­é\97´å¼\95å\85¥é\94\99误ï¼\8cä»\96们ä¸\8dä¼\9aæ\84\9f谢你ã\80\82
+在将您的更改划分为一系列补丁时,要特别注意确保内核在应用系列中的每个补丁之后
+都能正常构建和运行。使用 ``git bisect`` 来追踪问题的开发者可能会在任何地方分
+割你的补丁系列;如果你在中间引入错误,他们不会感谢你。
 
-如果你不能将补丁浓缩成更少的文件,那么每次大约发送出15个,然后等待审查
+如果你不能将补丁系列浓缩得更小,那么每次大约发送出15个补丁,然后等待审阅
 和集成。
 
-4) 检查你的更改风格
--------------------
+检查你的更改风格
+----------------
 
-检查您的补丁是否存在基本样式冲突,详细信息可在
-:ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>`
-中找到。如果不这样做,只会浪费审稿人的时间,并且会导致你的补丁被拒绝,甚至
+检查您的补丁是否违反了基本样式规定,详细信息参见
+Documentation/translations/zh_CN/process/coding-style.rst
+中找到。如果不这样做,只会浪费审阅者的时间,并且会导致你的补丁被拒绝,甚至
 可能没有被阅读。
 
 一个重要的例外是在将代码从一个文件移动到另一个文件时——在这种情况下,您不应
 该在移动代码的同一个补丁中修改移动的代码。这清楚地描述了移动代码和您的更改
-的行为。这大大有助于审实际差异,并允许工具更好地跟踪代码本身的历史。
+的行为。这大大有助于审实际差异,并允许工具更好地跟踪代码本身的历史。
 
 在提交之前,使用补丁样式检查程序检查补丁(scripts/check patch.pl)。不过,
 请注意,样式检查程序应该被视为一个指南,而不是作为人类判断的替代品。如果您
-的代码看起来更好,但有违规行为,那么最好不要使用它。
+的代码看起来更好,但有违规行为,那么最好别管它。
 
 检查者报告三个级别:
 
  - ERROR:很可能出错的事情
- - WARNING:需要仔细审的事项
+ - WARNING:需要仔细审的事项
  - CHECK:需要思考的事情
 
 您应该能够判断您的补丁中存在的所有违规行为。
 
-5) 选择补丁收件人
------------------
+选择补丁收件人
+--------------
 
-您应该总是在任何补丁上复制相应的子系统维护人员,以获得他们维护的代码;查看
+您应该总是知会任何补丁相应代码的子系统维护人员;查看
 维护人员文件和源代码修订历史记录,以了解这些维护人员是谁。脚本
-scripts/get_Maintainer.pl在这个步骤中非常有用。如果您找不到正在工作的子系统
+scripts/get_maintainer.pl在这个步骤中非常有用。如果您找不到正在工作的子系统
 的维护人员,那么Andrew Morton(akpm@linux-foundation.org)将充当最后的维护
 人员。
 
-您通常还应该选择至少一个邮件列表来接收补丁集的。linux-kernel@vger.kernel.org
-作为最后一个解决办法的列表,但是这个列表上的体积已经引起了许多开发人员的拒绝
+您通常还应该选择至少一个邮件列表来接收补丁集的副本。linux-kernel@vger.kernel.org
+是所有补丁的默认列表,但是这个列表的流量已经导致了许多开发人员不再看它
 在MAINTAINERS文件中查找子系统特定的列表;您的补丁可能会在那里得到更多的关注。
 不过,请不要发送垃圾邮件到无关的列表。
 
@@ -229,189 +201,170 @@ http://vger.kernel.org/vger-lists.html 上找到它们的列表。不过,也
 
 不要一次发送超过15个补丁到vger邮件列表!!!!
 
-Linus Torvalds 是决定改动能否进入 Linux 内核的最终裁决者。他的 e-mail
-地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般
-的说,最好别给他发 e-mail。
-
-如果您有修复可利用安全漏洞的补丁,请将该补丁发送到 security@kernel.org。对于
-严重的bug,可以考虑短期暂停以允许分销商向用户发布补丁;在这种情况下,显然不应
-将补丁发送到任何公共列表。
+Linus Torvalds是决定改动能否进入 Linux 内核的最终裁决者。他的邮件地址是
+torvalds@linux-foundation.org 。他收到的邮件很多,所以一般来说最好 **别**
+给他发邮件。
 
-修复已发布内核中严重错误的补丁程序应该指向稳定版维护人员,方法是放这样的一行::
+如果您有修复可利用安全漏洞的补丁,请将该补丁发送到 security@kernel.org 。对于
+严重的bug,可以考虑短期禁令以允许分销商(有时间)向用户发布补丁;在这种情况下,
+显然不应将补丁发送到任何公共列表。
+参见 Documentation/translations/zh_CN/admin-guide/security-bugs.rst 。
 
-        Cc: stable@vger.kernel.org
+修复已发布内核中严重错误的补丁程序应该抄送给稳定版维护人员,方法是把以下列行
+放进补丁的签准区(注意,不是电子邮件收件人)::
 
-进入补丁的签准区(注意,不是电子邮件收件人)。除了这个文件之外,您还应该阅读
-:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+  Cc: stable@vger.kernel.org
 
-但是,请注意,一些子系统维护人员希望得出他们自己的结论,即哪些补丁应该被放到
-稳定的树上。尤其是网络维护人员,不希望看到单个开发人员在补丁中添加像上面这样
-的行。
+除了本文件之外,您还应该阅读
+Documentation/translations/zh_CN/process/stable-kernel-rules.rst 。
 
-如果更改影响到用户内核接口,请向手册页维护人员(如维护人员文件中所列)发送
+如果更改影响到用户内核接口,请向手册页维护人员(如维护人员文件中所列)发送
 手册页补丁,或至少发送更改通知,以便一些信息进入手册页。还应将用户空间API
-更改复制到 linux-api@vger.kernel.org
+更改抄送到 linux-api@vger.kernel.org 
 
 
-6) 没有 MIME 编码,没有链接,没有压缩,没有附件,只有纯文本
------------------------------------------------------------
+不要MIME编码,不要链接,不要压缩,不要附件,只要纯文本
+------------------------------------------------------
 
 Linus 和其他的内核开发者需要阅读和评论你提交的改动。对于内核开发者来说
-,可以“引用”你的改动很重要,使用一般的 e-mail 工具,他们就可以在你的
+,可以“引用”你的改动很重要,使用一般的邮件工具,他们就可以在你的
 代码的任何位置添加评论。
 
-因为这个原因,所有的提交的补丁都是 e-mail 中“内嵌”的。
+因为这个原因,所有的提交的补丁都是邮件中“内嵌”的。最简单(和推荐)的方法就
+是使用 ``git send-email`` 。https://git-send-email.io 有 ``git send-email``
+的交互式教程。
+
+如果你选择不用 ``git send-email`` :
 
 .. warning::
-   如果你使用剪切-粘贴你的补丁,小心你的编辑器的自动换行功能破坏你的补丁
 
-不要将补丁作为 MIME 编码的附件,不管是否压缩。很多流行的 e-mail 软件不
-是任何时候都将 MIME 编码的附件当作纯文本发送的,这会使得别人无法在你的
-代码中加评论。另外,MIME 编码的附件会让 Linus 多花一点时间来处理,这就
-降低了你的改动被接受的可能性。
+  如果你使用剪切-粘贴你的补丁,小心你的编辑器的自动换行功能破坏你的补丁
 
-例外:如果你的邮递员弄坏了补丁,那么有人可能会要求你使用mime重新发送补丁
+不要将补丁作为MIME编码的附件,不管是否压缩。很多流行的邮件软件不
+是任何时候都将MIME编码的附件当作纯文本发送的,这会使得别人无法在你的
+代码中加评论。另外,MIME编码的附件会让Linus多花一点时间来处理,这就
+降低了你的改动被接受的可能性。
 
-请参阅 :ref:`Documentation/translations/zh_CN/process/email-clients.rst <cn_email_clients>`
-以获取有关配置电子邮件客户端以使其不受影响地发送修补程序的提示。
+例外:如果你的邮路损坏了补丁,那么有人可能会要求你使用MIME重新发送补丁。
 
-7) e-mail 的大小
-----------------
+请参阅 Documentation/translations/zh_CN/process/email-clients.rst
+以获取有关配置电子邮件客户端以使其不受影响地发送补丁的提示。
 
-大的改动对邮件列表不合适,对某些维护者也不合适。如果你的补丁,在不压缩
-的情况下,超过了300kB,那么你最好将补丁放在一个能通过 internet 访问的服
-务器上,然后用指向你的补丁的 URL 替代。但是请注意,如果您的补丁超过了
-300kb,那么它几乎肯定需要被破坏。
+回复审阅意见
+------------
 
-8)回复评审意见
----------------
+你的补丁几乎肯定会得到审阅者对补丁改进方法的评论(以回复邮件的形式)。您必须
+对这些评论作出回应;让补丁被忽略的一个好办法就是忽略审阅者的意见。直接回复邮
+件来回应意见即可。不会导致代码更改的意见或问题几乎肯定会带来注释或变更日志的
+改变,以便下一个审阅者更好地了解正在发生的事情。
 
½ ç\9a\84è¡¥ä¸\81å\87 ä¹\8eè\82¯å®\9aä¼\9aå¾\97å\88°è¯\84审è\80\85对补ä¸\81æ\94¹è¿\9bæ\96¹æ³\95ç\9a\84è¯\84论ã\80\82æ\82¨å¿\85须对è¿\99äº\9bè¯\84论ä½\9cå\87º
-回应;让补丁被忽略的一个好办法就是忽略审阅者的意见。不会导致代码更改
-意见或问题几乎肯定会带来注释或变更日志的改变,以便下一个评审者更好地了解
-正在发生的事情
¸\80å®\9aè¦\81å\91\8aè¯\89审é\98\85è\80\85ä½ å\9c¨å\81\9aä»\80ä¹\88æ\94¹å\8f\98ï¼\8c并æ\84\9fè°¢ä»\96们ç\9a\84æ\97¶é\97´ã\80\82代ç \81审é\98\85æ\98¯ä¸\80个累人ä¸\94è\80\97æ\97¶ç\9a\84
+过程,审阅者有时会变得暴躁。即使在这种情况下,也要礼貌地回应并解决他们指出
+问题。当发送下一版时,在封面邮件或独立补丁里加上 ``patch changelog`` 说明与
+前一版本的不同之处(参见 :ref:`zh_the_canonical_patch_format` )
 
-一定要告诉审稿人你在做什么改变,并感谢他们的时间。代码审查是一个累人且
-耗时的过程,审查人员有时会变得暴躁。即使在这种情况下,也要礼貌地回应并
-解决他们指出的问题。
+.. _zh_resend_reminders:
 
-9)不要泄气或不耐烦
--------------------
+不要泄气或不耐烦
+----------------
 
\8f\90交æ\9b´æ\94¹å\90\8eï¼\8c请è\80\90å¿\83ç­\89å¾\85ã\80\82审é\98\85è\80\85æ\98¯å¿\99ç¢\8cç\9a\84人ï¼\8cå\8f¯è\83½æ\97 æ³\95ç«\8bå\8d³è®¿é\97®æ\82¨ç\9a\84修补ç¨\8båº\8f
\8f\90交æ\9b´æ\94¹å\90\8eï¼\8c请è\80\90å¿\83ç­\89å¾\85ã\80\82审é\98\85è\80\85æ\98¯å¤§å¿\99人ï¼\8cå\8f¯è\83½æ\97 æ³\95ç«\8bå\8d³å®¡é\98\85æ\82¨ç\9a\84è¡¥ä¸\81
 
\9b¾å\87 ä½\95æ\97¶ï¼\8cè¡¥ä¸\81æ\9b¾å\9c¨æ²¡æ\9c\89è¯\84论ç\9a\84æ\83\85å\86µä¸\8bæ¶\88失å\9c¨ç©ºç\99½ä¸­ï¼\8cä½\86å¼\80å\8f\91è¿\87ç¨\8bæ¯\94ç\8e°å\9c¨æ\9b´å\8a é¡ºå\88©
\9b¾å\87 ä½\95æ\97¶ï¼\8cè¡¥ä¸\81æ\9b¾å\9c¨æ²¡æ\94¶å\88°è¯\84论ç\9a\84æ\83\85å\86µä¸\8bæ¶\88失å\9c¨è\99\9a空中ï¼\8cä½\86ç\8e°å\9c¨å¼\80å\8f\91è¿\87ç¨\8båº\94该æ\9b´å\8a é¡ºå\88©äº\86
 您应该在一周左右的时间内收到评论;如果没有收到评论,请确保您已将补丁发送
-到正确的位置。在重新提交或联系审阅者之前至少等待一周-在诸如合并窗口之类的
+到正确的位置。在重新提交或联系审阅者之前至少等待一周——在诸如合并窗口之类的
 繁忙时间可能更长。
 
-10)主题中包含 PATCH
---------------------
+在等了几个星期后,用带RESEND的主题重发补丁也是可以的::
 
-由于到linus和linux内核的电子邮件流量很高,通常会在主题行前面加上[PATCH]
-前缀. 这使Linus和其他内核开发人员更容易将补丁与其他电子邮件讨论区分开。
+   [PATCH Vx RESEND] sub/sys: Condensed patch summary
 
-11)签署你的作品-开发者原始认证
--------------------------------
+当你发布补丁(系列)修改版的时候,不要加上“RESEND”——“RESEND”只适用于重
+新提交之前未经修改的补丁(系列)。
 
-为äº\86å\8a å¼ºå¯¹è°\81å\81\9aäº\86ä½\95äº\8bç\9a\84追踪ï¼\8cå°¤å\85¶æ\98¯å¯¹é\82£äº\9bé\80\8fè¿\87好å\87 å±\82ç\9a\84ç»´æ\8a¤è\80\85ç\9a\84è¡¥ä¸\81ï¼\8cæ\88\91们
-建议在发送出去的补丁上加一个 “sign-off” 的过程。
+主é¢\98中å\8c\85å\90« PATCH
+----------------
 
-"sign-off" 是在补丁的注释的最后的简单的一行文字,认证你编写了它或者其他
+由于到Linus和linux-kernel的电子邮件流量很高,通常会在主题行前面加上[PATCH]
+前缀。这使Linus和其他内核开发人员更容易将补丁与其他电子邮件讨论区分开。
+
+``git send-email`` 会自动为你加上。
+
+签署你的作品——开发者来源认证
+------------------------------
+
+为了加强对谁做了何事的追踪,尤其是对那些透过好几层维护者才最终到达的补丁,我
+们在通过邮件发送的补丁上引入了“签署(sign-off)”流程。
+
+“签署”是在补丁注释最后的一行简单文字,认证你编写了它或者其他
 人有权力将它作为开放源代码的补丁传递。规则很简单:如果你能认证如下信息:
 
-å¼\80å\8f\91è\80\85æ\9d¥æº\90è¯\81书 1.1
+å¼\80å\8f\91è\80\85æ\9d¥æº\90认è¯\81 1.1
 ^^^^^^^^^^^^^^^^^^
 
 对于本项目的贡献,我认证如下信息:
 
-      (a)这些贡献是完全或者部分的由我创建,我有权利以文件中指出
+       (a) 这些贡献是完全或者部分的由我创建,我有权利以文件中指出
            的开放源代码许可证提交它;或者
-      (b)这些贡献基于以前的工作,据我所知,这些以前的工作受恰当的开放
-           源代码许可证保护,而且,根据许可证,我有权提交修改后的贡献,
+
+       (b) 这些贡献基于以前的工作,据我所知,这些以前的工作受恰当的开放
+           源代码许可证保护,而且,根据文件中指出的许可证,我有权提交修改后的贡献,
            无论是完全还是部分由我创造,这些贡献都使用同一个开放源代码许可证
-           (除非我被允许用其它的许可证),正如文件中指出的;或者
-      (c)这些贡献由认证(a),(b)或者(c)的人直接提供给我,而
+           (除非我被允许用其它的许可证);或者
+
+       (c) 这些贡献由认证(a),(b)或者(c)的人直接提供给我,而
            且我没有修改它。
-      (d)我理解并同意这个项目和贡献是公开的,贡献的记录(包括我
-           一起提交的个人记录,包括 sign-off )被永久维护并且可以和这个项目
+
+       (d) 我理解并同意这个项目和贡献是公开的,贡献的记录(包括我
+           一起提交的个人记录,包括sign-off)被永久维护并且可以和这个项目
            或者开放源代码的许可证同步地再发行。
 
 那么加入这样一行::
 
-       Signed-off-by: Random J Developer <random@developer.example.org>
-
-使用你的真名(抱歉,不能使用假名或者匿名。)
-
-有人在最后加上标签。现在这些东西会被忽略,但是你可以这样做,来标记公司
-内部的过程,或者只是指出关于 sign-off 的一些特殊细节。
-
-如果您是子系统或分支维护人员,有时需要稍微修改收到的补丁,以便合并它们,
-因为树和提交者中的代码不完全相同。如果你严格遵守规则(c),你应该要求提交者
-重新发布,但这完全是在浪费时间和精力。规则(b)允许您调整代码,但是更改一个
-提交者的代码并让他认可您的错误是非常不礼貌的。要解决此问题,建议在最后一个
-由签名行和您的行之间添加一行,指示更改的性质。虽然这并不是强制性的,但似乎
-在描述前加上您的邮件和/或姓名(全部用方括号括起来),这足以让人注意到您对最
-后一分钟的更改负有责任。例如::
-
-       Signed-off-by: Random J Developer <random@developer.example.org>
-       [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
-       Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
-
-如果您维护一个稳定的分支机构,同时希望对作者进行致谢、跟踪更改、合并修复并
-保护提交者不受投诉,那么这种做法尤其有用。请注意,在任何情况下都不能更改作者
-的ID(From 头),因为它是出现在更改日志中的标识。
-
-对回合(back-porters)的特别说明:在提交消息的顶部(主题行之后)插入一个补丁
-的起源指示似乎是一种常见且有用的实践,以便于跟踪。例如,下面是我们在3.x稳定
-版本中看到的内容::
-
-  Date:   Tue Oct 7 07:26:38 2014 -0400
-
-    libata: Un-break ATA blacklist
-
-    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
-
-还有, 这里是一个旧版内核中的一个回合补丁::
+  Signed-off-by: Random J Developer <random@developer.example.org>
 
-    Date:   Tue May 13 22:12:27 2008 +0200
+使用你的真名(抱歉,不能使用假名或者匿名。)如果使用 ``git commit -s`` 的话
+将会自动完成。撤销也应当包含“Signed-off-by”, ``git revert -s`` 会帮你搞定。
 
-        wireless, airo: waitbusy() won't delay
+有些人会在最后加上额外的标签。现在这些东西会被忽略,但是你可以这样做,来标记
+公司内部的过程,或者只是指出关于签署的一些特殊细节。
 
-        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+作者签署之后的任何其他签署(Signed-off-by:'s)均来自处理和传递补丁的人员,但
+未参与其开发。签署链应当反映补丁传播到维护者并最终传播到Linus所经过的 **真实**
+路径,首个签署指明单个作者的主要作者身份。
 
-12)何时使用Acked-by:,CC:,和Co-Developed by:
-----------------------------------------------
+何时使用Acked-by:,CC:,和Co-Developed by:
+------------------------------------------
 
-Singed-off-by: 标表示签名者参与了补丁的开发,或者他/她在补丁的传递路径中。
+Singed-off-by: 标表示签名者参与了补丁的开发,或者他/她在补丁的传递路径中。
 
-如果一个人没有直接参与补丁的准备或处理,但希望表示并记录他们对补丁的批准,
-那么他们可以要求在补丁的变更日志中添加一个 Acked-by:
+如果一个人没有直接参与补丁的准备或处理,但希望表示并记录他们对补丁的批准/赞成
+那么他们可以要求在补丁的变更日志中添加一个Acked-by:。
 
-Acked-by通常由受影响代码的维护者使用,当该维护者既没有贡献也没有转发补丁时。
+Acked-by通常由受影响代码的维护者使用,当该维护者既没有贡献也没有转发补丁时。
 
-Acked-by: 不像签字人那样正式。这是一个记录,确认人至少审查了补丁,并表示接受。
-因此,补丁合并有时会手动将Acker的“Yep,looks good to me”转换为 Acked-By(但
+Acked-by: 不像签署那样正式。这是一个记录,确认人至少审阅了补丁,并表示接受。
+因此,补丁合并有时会手动将Acker的“Yep,looks good to me”转换为 Acked-By:(但
 请注意,通常最好要求一个明确的Ack)。
 
 Acked-by:不一定表示对整个补丁的确认。例如,如果一个补丁影响多个子系统,并且
-有一个:来自一个子系统维护者,那么这通常表示只确认影响维护者代码的部分。这里
º\94该ä»\94ç»\86å\88¤æ\96­ã\80\82å¦\82æ\9c\89ç\96\91é\97®ï¼\8cåº\94å\8f\82è\80\83é\82®ä»¶å\88\97表档æ¡\88中的原始讨论。
+有一个来自某个子系统维护者的Acked-By:,那么这通常表示只确认影响维护者代码的部
\88\86ã\80\82è¿\99é\87\8cåº\94该ä»\94ç»\86å\88¤æ\96­ã\80\82å¦\82æ\9c\89ç\96\91é\97®ï¼\8cåº\94å\8f\82è\80\83é\82®ä»¶å\88\97表å­\98æ¡£中的原始讨论。
 
-å¦\82æ\9e\9cæ\9f\90人æ\9c\89æ\9cºä¼\9a对补ä¸\81è¿\9bè¡\8cè¯\84论ï¼\8cä½\86没æ\9c\89æ\8f\90ä¾\9b此类è¯\84论ï¼\8cæ\82¨å\8f¯ä»¥é\80\89æ\8b©å\9c¨è¡¥ä¸\81中添å\8a  ``Cc:``
-这是唯一一个标签,它可以在没有被它命名的人显式操作的情况下添加,但它应该表明
-这个人是在补丁上抄送的。讨论中包含了潜在利益相关方。
+å¦\82æ\9e\9cæ\9f\90人æ\9c¬åº\94æ\9c\89æ\9cºä¼\9a对补ä¸\81è¿\9bè¡\8cè¯\84论ï¼\8cä½\86没æ\9c\89æ\8f\90ä¾\9b此类è¯\84论ï¼\8cæ\82¨å\8f¯ä»¥é\80\89æ\8b©å\9c¨è¡¥ä¸\81中添å\8a 
+``Cc:`` 这是唯一可以在没有被该人明确同意的情况下添加的标签——但它应该表明
+这个人是在补丁上抄送的。此标签记录了讨论中包含的潜在利益相关方。
 
 Co-developed-by: 声明补丁是由多个开发人员共同创建的;当几个人在一个补丁上工
-作时,它用于将属性赋予共同作者(除了 From: 所赋予的作者之外)。因为
-Co-developed-by: 表示作者身份,所以每个共同开发人:必须紧跟在相关合作作者的
-签名之后。标准的签核程序要求:标记的签核顺序应尽可能反映补丁的时间历史,而不
-管作者是通过 From :还是由 Co-developed-by: 共同开发的。值得注意的是,最后一
-个签字人:必须始终是提交补丁的开发人员。
+作时,它用于给出共同作者(除了From:所给出的作者之外)。因为Co-developed-by:
+表示作者身份,所以每个Co-developed-by:必须紧跟在相关合作作者的签署之后。标准
+签署程序要求Singed-off-by:标签的顺序应尽可能反映补丁的时间历史,无论作者是通
+过From:还是Co-developed-by:表明。值得注意的是,最后一个Singed-off-by:必须是
+提交补丁的开发人员。
 
-注æ\84\8fï¼\8cå½\93ä½\9cè\80\85ä¹\9fæ\98¯ç\94µå­\90é\82®ä»¶æ \87é¢\98â\80\9cå\8f\91件人ï¼\9aâ\80\9dè¡\8c中å\88\97å\87ºç\9a\84人æ\97¶ï¼\8câ\80\9cFrom: â\80\9d æ \87è®°是可选的。
+注æ\84\8fï¼\8cå¦\82æ\9e\9cFrom:ä½\9cè\80\85ä¹\9fæ\98¯ç\94µå­\90é\82®ä»¶æ \87é¢\98ç\9a\84From:è¡\8c中å\88\97å\87ºç\9a\84人ï¼\8cå\88\99From:æ \87ç­¾是可选的。
 
-作者提交的补丁程序示例::
+被From:作者提交的补丁示例::
 
        <changelog>
 
@@ -421,7 +374,7 @@ Co-developed-by: 表示作者身份,所以每个共同开发人:必须紧跟
        Signed-off-by: Second Co-Author <second@coauthor.example.org>
        Signed-off-by: From Author <from@author.example.org>
 
-合作开发者提交的补丁示例::
+合作开发者提交的补丁示例::
 
        From: From Author <from@author.example.org>
 
@@ -434,76 +387,85 @@ Co-developed-by: 表示作者身份,所以每个共同开发人:必须紧跟
        Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>
 
 
-13)使用报告人:、测试人:、审核人:、建议人:、修复人:
---------------------------------------------------------
+使用Reported-by:、Tested-by:、Reviewed-by:、Suggested-by:和Fixes:
+-----------------------------------------------------------------
 
 Reported-by: 给那些发现错误并报告错误的人致谢,它希望激励他们在将来再次帮助
-我们。请注意,如果bug是以私有方式报告的,那么在使用Reported-by标之前,请
-先请求权限
+我们。请注意,如果bug是以私有方式报告的,那么在使用Reported-by标之前,请
+先请求许可。此标签是为Bug设计的;请不要将其用于感谢功能请求
 
-Tested-by: 标记表示补丁已由指定的人(在某些环境中)成功测试。这个标签通知
-维护人员已经执行了一些测试,为将来的补丁提供了一种定位测试人员的方法,并确
-保测试人员的信誉。
+Tested-by: 标签表示补丁已由指定的人(在某些环境中)成功测试。这个标签通知
+维护人员已经执行了一些测试,为将来的补丁提供了一种定位测试人员的方法,并彰显测试人员的功劳。
 
-Reviewed-by:相反,根据审查人的声明,表明该补丁已被审查并被认为是可接受的:
+Reviewed-by:根据审阅者的监督声明,表明该补丁已被审阅并被认为是可接受的:
 
 
-审查人的监督声明
+审阅者的监督声明
 ^^^^^^^^^^^^^^^^
 
-通过提供我的 Reviewed-by,我声明:
+通过提供我的Reviewed-by:标签,我声明:
 
-        (a) 我已经对这个补丁进行了一次技术审,以评估它是否适合被包含到
+        (a) 我已经对这个补丁进行了一次技术审,以评估它是否适合被包含到
             主线内核中。
 
         (b) 与补丁相关的任何问题、顾虑或问题都已反馈给提交者。我对提交者对
             我的评论的回应感到满意。
 
-        (c) è\99½ç\84¶è¿\99ä¸\80æ\8f\90交å\8f¯è\83½ä¼\9aæ\94¹è¿\9bä¸\80äº\9bä¸\9c西,但我相信,此时,(1)对内核
+        (c) è\99½ç\84¶è¿\99ä¸\80æ\8f\90交å\8f¯è\83½ä»\8då\8f¯è¢«æ\94¹è¿\9b,但我相信,此时,(1)对内核
             进行了有价值的修改,(2)没有包含争论中涉及的已知问题。
 
-        (d) 虽然我已经审了补丁并认为它是健全的,但我不会(除非另有明确
-            说明)作出任何保证或保证它将在任何给定情况下实现其规定的目的
+        (d) 虽然我已经审了补丁并认为它是健全的,但我不会(除非另有明确
+            说明)作出任何保证或担保它会在任何给定情况下实现其规定的目的
             或正常运行。
 
-Reviewed-by 是一种观点声明,即补丁是对内核的适当修改,没有任何遗留的严重技术
-问题。任何感兴趣的审阅者(完成工作的人)都可以为一个补丁提供一个 Review-by
-标签。此标签用于向审阅者提供致谢,并通知维护者已在修补程序上完成的审阅程度。
-Reviewed-by: 当由已知了解主题区域并执行彻底检查的审阅者提供时,通常会增加
+Reviewed-by是一种观点声明,即补丁是对内核的适当修改,没有任何遗留的严重技术
+问题。任何感兴趣的审阅者(完成工作的人)都可以为一个补丁提供一个Reviewed-by
+标签。此标签用于向审阅者提供致谢,并通知维护者补丁的审阅进度。
+当Reviewed-by:标签由已知了解主题区域并执行彻底检查的审阅者提供时,通常会增加
 补丁进入内核的可能性。
 
+一旦从测试人员或审阅者的“Tested-by”和“Reviewed-by”标签出现在邮件列表中,
+作者应在发送下一个版本时将其添加到适用的补丁中。但是,如果补丁在以下版本中发
+生了实质性更改,这些标签可能不再适用,因此应该删除。通常,在补丁更改日志中
+(在 ``---`` 分隔符之后)应该提到删除某人的测试者或审阅者标签。
+
 Suggested-by: 表示补丁的想法是由指定的人提出的,并确保将此想法归功于指定的
 人。请注意,未经许可,不得添加此标签,特别是如果该想法未在公共论坛上发布。
-这就是说,如果我们勤快地致谢我们的创意者,他们很有希望在未来得到鼓舞,再次
+也就是说,如果我们勤快地致谢创意提供者,他们将受到鼓舞,很有希望在未来再次
 帮助我们。
 
-Fixes: 指示补丁在以前的提交中修复了一个问题。它可以很容易地确定错误的来源,
-这有助于检查错误修复。这个标记还帮助稳定内核团队确定应该接收修复的稳定内核
-版本。这是指示补丁修复的错误的首选方法。请参阅 :ref:`cn_describe_changes`
-描述您的更改以了解更多详细信息。
+Fixes: 指示补丁修复了之前提交的一个问题。它可以便于确定错误的来源,这有助于
+检查错误修复。这个标签还帮助稳定内核团队确定应该接收修复的稳定内核版本。这是
+指示补丁修复的错误的首选方法。请参阅 :ref:`zh_describe_changes` 了解更多信息。
 
-.. _cn_the_canonical_patch_format:
+.. note::
 
-12)标准补丁格式
-----------------
+  附加Fixes:标签不会改变稳定内核规则流程,也不改变所有稳定版补丁抄送
+  stable@vger.kernel.org的要求。有关更多信息,请阅读
+  Documentation/translations/zh_CN/process/stable-kernel-rules.rst 。
+
+.. _zh_the_canonical_patch_format:
+
+标准补丁格式
+------------
 
 本节描述如何格式化补丁本身。请注意,如果您的补丁存储在 ``Git`` 存储库中,则
-可以使用 ``git format-patch`` 进行正确的补丁格式设置。但是,这些工具无法创建
+可以使用 ``git format-patch`` 进行正确的补丁格式。但是,这些工具无法创建
 必要的文本,因此请务必阅读下面的说明。
 
-标准的补丁标题行是::
+标准的补丁标题行是::
 
     Subject: [PATCH 001/123] 子系统:一句话概述
 
-æ \87å\87\86è¡¥ä¸\81ç\9a\84ä¿¡ä½\93å­\98å\9c¨如下部分:
+æ \87å\87\86è¡¥ä¸\81ç\9a\84ä¿¡ä½\93å\8c\85å\90«如下部分:
 
-  - 一个 "from" 行指出补丁作者。后跟空行(仅当发送修补程序的人不是作者时才需要)。
+  - 一个 ``from`` 行指出补丁作者。后跟空行(仅当发送补丁的人不是作者时才需要)。
 
-  - è§£é\87\8aç\9a\84æ­£æ\96\87ï¼\8cè¡\8c以75å\88\97å\8c\85è£\85,这将被复制到永久变更日志来描述这个补丁。
+  - è¯´æ\98\8eæ\96\87å­\97ï¼\8cæ¯\8fè¡\8cæ\9c\80é\95¿75å\88\97,这将被复制到永久变更日志来描述这个补丁。
 
   - 一个空行
 
-  - 上面描述的“Signed-off-by” 行,也将出现在更改日志中。
+  - 上述的 ``Signed-off-by:`` 行,也将出现在更改日志中。
 
   - 只包含 ``---`` 的标记线。
 
@@ -511,29 +473,29 @@ Fixes: 指示补丁在以前的提交中修复了一个问题。它可以很容
 
   - 实际补丁( ``diff`` 输出)。
 
-标题行的格式,使得对标题行按字母序排序非常的容易 - 很多 e-mail 客户端都
-可以支持 - 因为序列号是用零填充的,所以按数字排序和按字母排序是一样的。
+标题行的格式,使得对标题行按字母序排序非常的容易——很多邮件客户端都
+可以支持——因为序列号是用零填充的,所以按数字排序和按字母排序是一样的。
 
-e-mail 标题中的“子系统”标识哪个内核子系统将被打补丁。
+邮件标题中的“子系统”标识哪个内核子系统将被打补丁。
 
-e-mail 标题中的“一句话概述”扼要的描述 e-mail 中的补丁。“一句话概述”
+邮件标题中的“一句话概述”扼要的描述邮件中的补丁。“一句话概述”
 不应该是一个文件名。对于一个补丁系列(“补丁系列”指一系列的多个相关补
 丁),不要对每个补丁都使用同样的“一句话概述”。
 
-记住 e-mail 的“一句话概述”会成为该补丁的全局唯一标识。它会蔓延到 git
+记住邮件的“一句话概述”会成为该补丁的全局唯一标识。它会进入 ``git``
 的改动记录里。然后“一句话概述”会被用在开发者的讨论里,用来指代这个补
-丁。用户将希望通过 google 来搜索"一句话概述"来找到那些讨论这个补丁的文
+丁。用户将希望通过搜索引擎搜索“一句话概述”来找到那些讨论这个补丁的文
 章。当人们在两三个月后使用诸如 ``gitk`` 或 ``git log --oneline`` 之类
 的工具查看数千个补丁时,也会很快看到它。
 
 出于这些原因,概述必须不超过70-75个字符,并且必须描述补丁的更改以及为
-什么需要补丁。既要简洁又要描述性很有挑战性,但写得好的概述应该这样
+什么需要补丁。既要简洁又要描述性很有挑战性,但写得好的概述应该这样。
 
 概述的前缀可以用方括号括起来:“Subject: [PATCH <tag>...] <概述>”。标记
 不被视为概述的一部分,而是描述应该如何处理补丁。如果补丁的多个版本已发
-送出来以响应评审(即“v1,v2,v3”)或“rfc”,以指示评审请求,那么通用标记
-可能包括版本描述符。如果一个补丁系列中有四个补丁,那么各个补丁可以这样
-编号:1/4、2/4、3/4、4/4。这可以确保开发人员了解补丁应用的顺序,并且他们
+送出来以响应评审(即“v1,v2,v3”)则必须包含版本号,或包含“RFC”以指示
+评审请求。如果一个补丁系列中有四个补丁,那么各个补丁可以这样编号:1/4、2/4、
+3/4、4/4。这可以确保开发人员了解补丁应用的顺序,且
 已经查看或应用了补丁系列中的所有补丁。
 
 一些标题的例子::
@@ -541,95 +503,134 @@ e-mail 标题中的“一句话概述”扼要的描述 e-mail 中的补丁。
     Subject: [patch 2/5] ext2: improve scalability of bitmap searching
     Subject: [PATCHv2 001/207] x86: fix eflags tracking
 
-"From" 行是信体里的最上面一行,具有如下格式:
+``From`` 行是信体里的最上面一行,具有如下格式::
+
         From: Patch Author <author@example.com>
 
-"From" 行指明在永久改动日志里,谁会被确认为作者。如果没有 "From" 行,那
-么邮件头里的 "From: " 行会被用来决定改动日志中的作者。
+``From`` 行指明在永久改动日志里,谁会被确认为作者。如果没有 ``From`` 行,那
+么邮件头里的 ``From:`` 行会被用来决定改动日志中的作者。
 
-说明的主题将会被提交到永久的源代码改动日志里,因此对那些早已经不记得和
-这个补丁相关的讨论细节的有能力的读者来说,是有意义的。包括补丁程序定位
-错误的(内核日志消息、OOPS消息等)症状,对于搜索提交日志以寻找适用补丁的人
-尤其有用。如果一个补丁修复了一个编译失败,那么可能不需要包含所有编译失败;
+说明文字将会被提交到永久的源代码改动日志里,因此应针对那些早已经不记得和这
+个补丁相关的讨论细节的读者。包括补丁处理的故障症状(内核日志消息、oops消息
+等),这对于可能正在搜索提交日志以查找适用补丁的人特别有用。文本应该写得如
+此详细,以便在数周、数月甚至数年后阅读时,能够为读者提供所需的细节信息,以
+掌握创建补丁的 **原因** 。
+
+如果一个补丁修复了一个编译失败,那么可能不需要包含 *所有* 编译失败;
 只要足够让搜索补丁的人能够找到它就行了。与概述一样,既要简洁又要描述性。
 
-"---" 标记行对于补丁处理工具要找到哪里是改动日志信息的结束,是不可缺少
+``---`` 标记行对于补丁处理工具要找到哪里是改动日志信息的结束,是不可缺少
 的。
 
-对于 "---" 标记之后的额外注解,一个好的用途就是用来写 diffstat,用来显
-示修改了什么文件和每个文件都增加和删除了多少行。diffstat 对于比较大的补
-丁特别有用。其余那些只是和时刻或者开发者相关的注解,不合适放到永久的改
-动日志里的,也应该放这里。
-使用 diffstat的选项 "-p 1 -w 70" 这样文件名就会从内核源代码树的目录开始
+对于 ``---`` 标记之后的额外注解,一个好的用途就是用来写 ``diffstat`` ,用来显
+示修改了什么文件和每个文件都增加和删除了多少行。 ``diffstat`` 对于比较大的补
+丁特别有用。
+使用 ``diffstat`` 的选项 ``-p 1 -w 70`` 这样文件名就会从内核源代码树的目录开始
 ,不会占用太宽的空间(很容易适合80列的宽度,也许会有一些缩进。)
+( ``git`` 默认会生成合适的diffstat。)
+
+其余那些只适用于当时或者与维护者相关的注解,不合适放到永久的改动日志里的,也
+应该放这里。较好的例子就是 ``补丁更改记录`` ,记录了v1和v2版本补丁之间的差异。
+
+请将此信息放在将变更日志与补丁的其余部分分隔开的 ``---`` 行 **之后** 。版本
+信息不是提交到git树的变更日志的一部分。只是供审阅人员使用的附加信息。如果将
+其放置在提交标记上方,则需要手动交互才能将其删除。如果它位于分隔线以下,则在
+应用补丁时会自动剥离::
+
+  <commit message>
+  ...
+  Signed-off-by: Author <author@mail>
+  ---
+  V2 -> V3: Removed redundant helper function
+  V1 -> V2: Cleaned up coding style and addressed review comments
 
-在后面的参考资料中能看到适当的补丁格式的更多细节。
+  path/to/file | 5+++--
+  ...
 
-.. _cn_explicit_in_reply_to:
+在后面的参考资料中能看到正确补丁格式的更多细节。
 
-15) 明确回复邮件头(In-Reply-To)
--------------------------------
+.. _zh_backtraces:
 
-手动添加回复补丁的的标题头(In-Reply_To:) 是有帮助的(例如,使用 ``git send-email`` )
-将补丁与以前的相关讨论关联起来,例如,将bug修复程序链接到电子邮件和bug报告。
+提交消息中的回溯(Backtraces)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+回溯有助于记录导致问题的调用链。然而,并非所有回溯都有帮助。例如,早期引导调
+用链是独特而明显的。而逐字复制完整的dmesg输出则会增加时间戳、模块列表、寄存
+器和堆栈转储等分散注意力的信息。
+
+因此,最有用的回溯应该从转储中提取相关信息,以更容易集中在真实问题上。下面是
+一个剪裁良好的回溯示例::
+
+  unchecked MSR access error: WRMSR to 0xd51 (tried to write 0x0000000000000064)
+  at rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
+  Call Trace:
+  mba_wrmsr
+  update_domains
+  rdtgroup_mkdir
+
+.. _zh_explicit_in_reply_to:
+
+明确回复邮件头(In-Reply-To)
+-----------------------------
+
+手动添加回复补丁的的邮件头(In-Reply_To:)是有用的(例如,使用 ``git send-email`` ),
+可以将补丁与以前的相关讨论关联起来,例如,将bug补丁链接到电子邮件和bug报告。
 但是,对于多补丁系列,最好避免在回复时使用链接到该系列的旧版本。这样,
-补丁的多个版本就不会成为电子邮件客户端中无法管理的引用序列。如果链接有用,
+补丁的多个版本就不会成为电子邮件客户端中无法管理的引用。如果链接有用,
 可以使用 https://lore.kernel.org/ 重定向器(例如,在封面电子邮件文本中)
 链接到补丁系列的早期版本。
 
-16) 发送git pull请求
---------------------
-
-如果您有一系列补丁,那么让维护人员通过git pull操作将它们直接拉入子系统存储
-库可能是最方便的。但是,请注意,从开发人员那里获取补丁比从邮件列表中获取补
-丁需要更高的信任度。因此,许多子系统维护人员不愿意接受请求,特别是来自新的
-未知开发人员的请求。如果有疑问,您可以在封面邮件中使用pull 请求作为补丁系列
-正常发布的一个选项,让维护人员可以选择使用其中之一。
-
-pull 请求的主题行中应该有[Git Pull]。请求本身应该在一行中包含存储库名称和
-感兴趣的分支;它应该看起来像::
+给出基础树信息
+--------------
 
-  Please pull from
+当其他开发人员收到您的补丁并开始审阅时,知道应该将您的工作放到代码树历史记录
+中的什么位置通常很有用。这对于自动化持续集成流水(CI)特别有用,这些流水线试
+图运行一系列测试,以便在维护人员开始审阅之前确定提交的质量。
 
-      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+如果您使用 ``git format-patch`` 生成补丁,则可以通过 ``--base`` 标志在提交中
+自动包含基础树信息。使用此选项最简单、最方便的方法是配合主题分支::
 
-  to get these changes:
+    $ git checkout -t -b my-topical-branch master
+    Branch 'my-topical-branch' set up to track local branch 'master'.
+    Switched to a new branch 'my-topical-branch'
 
+    [perform your edits and commits]
 
-pull 请求还应该包含一条整体消息,说明请求中将包含什么,一个补丁本身的 ``Git shortlog``
-以及一个显示补丁系列整体效果的 ``diffstat`` 。当然,将所有这些信息收集在一起
-的最简单方法是让 ``git`` 使用 ``git request-pull`` 命令为您完成这些工作。
+    $ git format-patch --base=auto --cover-letter -o outgoing/ master
+    outgoing/0000-cover-letter.patch
+    outgoing/0001-First-Commit.patch
+    outgoing/...
 
-一些维护人员(包括Linus)希望看到来自已签名提交的请求;这增加了他们对你的
¯·æ±\82ä¿¡å¿\83ã\80\82ç\89¹å\88«æ\98¯ï¼\8cå\9c¨æ²¡æ\9c\89ç­¾å\90\8dæ \87ç­¾ç\9a\84æ\83\85å\86µä¸\8bï¼\8cLinus ä¸\8dä¼\9aä»\8eå\83\8f Github è¿\99æ ·ç\9a\84å\85¬å\85±
-托管站点拉请求。
+当你编辑 ``outgoing/0000-cover-letter.patch`` 时,您会注意到在它的最底部有一
¡\8c ``base-commit:`` å°¾æ³¨ï¼\8cå®\83为审é\98\85è\80\85å\92\8cCIå·¥å\85·æ\8f\90ä¾\9bäº\86足å¤\9fç\9a\84ä¿¡æ\81¯ä»¥æ­£ç¡®æ\89§è¡\8c
+``git am`` 而不必担心冲突::
 
-创建此类签名的第一步是生成一个 GNRPG 密钥,并由一个或多个核心内核开发人员对
-其进行签名。这一步对新开发人员来说可能很困难,但没有办法绕过它。参加会议是
-找到可以签署您的密钥的开发人员的好方法。
+    $ git checkout -b patch-review [base-commit-id]
+    Switched to a new branch 'patch-review'
+    $ git am patches.mbox
+    Applying: First Commit
+    Applying: ...
 
-一旦您在Git 中准备了一个您希望有人拉的补丁系列,就用 ``git tag -s`` 创建一
-个签名标记。这将创建一个新标记,标识该系列中的最后一次提交,并包含用您的私
-钥创建的签名。您还可以将changelog样式的消息添加到标记中;这是一个描述拉请求
-整体效果的理想位置。
+有关此选项的更多信息,请参阅 ``man git-format-patch`` 。
 
-如果维护人员将要从中提取的树不是您正在使用的存储库,请不要忘记将已签名的标记
-显式推送到公共树。
+.. note::
 
-生成拉请求时,请使用已签名的标记作为目标。这样的命令可以实现::
+    ``--base`` 功能是在2.9.0版git中引入的。
 
-  git request-pull master git://my.public.tree/linux.git my-signed-tag
+如果您不使用git格式化补丁,仍然可以包含相同的 ``base-commit`` 尾注,以指示您
+的工作所基于的树的提交哈希。你应该在封面邮件或系列的第一个补丁中添加它,它应
+该放在 ``---`` 行的下面或所有其他内容之后,即只在你的电子邮件签名之前。
 
 参考文献
 --------
 
-Andrew Morton, "The perfect patch" (tpp).
+Andrew Morton,“完美的补丁”(tpp)
   <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
 
-Jeff Garzik, "Linux kernel patch submission format".
+Jeff Garzik,“Linux内核补丁提交格式”
   <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
 
-Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+Greg Kroah-Hartman,“如何惹恼内核子系统维护人员”
   <http://www.kroah.com/log/linux/maintainer.html>
 
   <http://www.kroah.com/log/linux/maintainer-02.html>
@@ -642,16 +643,15 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
 
   <http://www.kroah.com/log/linux/maintainer-06.html>
 
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+不!!!别再发巨型补丁炸弹给linux-kernel@vger.kernel.org的人们了!
   <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
 
-Kernel Documentation/process/coding-style.rst:
-  :ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>`
+内核 Documentation/translations/zh_CN/process/coding-style.rst
 
-Linus Torvalds's mail on the canonical patch format:
+Linus Torvalds关于标准补丁格式的邮件
   <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
 
-Andi Kleen, "On submitting kernel patches"
-  Some strategies to get difficult or controversial changes in.
+Andi Kleen,“提交补丁之路”
+  一些帮助合入困难或有争议的变更的策略。
 
   http://halobates.de/on-submitting-patches.pdf
index 26b0f36..3076402 100644 (file)
@@ -80,7 +80,7 @@ p->se.vruntime。一旦p->se.vruntime变得足够大,其它的任务将成为
 CFS使用纳秒粒度的计时,不依赖于任何jiffies或HZ的细节。因此CFS并不像之前的调度器那样
 有“时间片”的概念,也没有任何启发式的设计。唯一可调的参数(你需要打开CONFIG_SCHED_DEBUG)是:
 
-   /proc/sys/kernel/sched_min_granularity_ns
+   /sys/kernel/debug/sched/min_granularity_ns
 
 它可以用来将调度器从“桌面”模式(也就是低时延)调节为“服务器”(也就是高批处理)模式。
 它的默认设置是适合桌面的工作负载。SCHED_BATCH也被CFS调度器模块处理。
diff --git a/Documentation/translations/zh_TW/oops-tracing.txt b/Documentation/translations/zh_TW/oops-tracing.txt
deleted file mode 100644 (file)
index be8e59f..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-Chinese translated version of Documentation/admin-guide/bug-hunting.rst
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Traditional Chinese maintainer:  Hu Haowen <src.res@email.cn>
----------------------------------------------------------------------
-Documentation/admin-guide/bug-hunting.rst 的繁體中文版翻譯
-
-如果想評論或更新本文的內容,請直接聯繫原文檔的維護者。如果你使用英文
-交流有困難的話,也可以向繁體中文版維護者求助。如果本翻譯更新不及時或
-者翻譯存在問題,請聯繫繁體中文版維護者。
-
-繁體中文版維護者: 胡皓文 Hu Haowen <src.res@email.cn>
-繁體中文版翻譯者: 胡皓文 Hu Haowen <src.res@email.cn>
-繁體中文版校譯者: 胡皓文 Hu Haowen <src.res@email.cn>
-
-以下爲正文
----------------------------------------------------------------------
-
-注意: ksymoops 在2.6中是沒有用的。 請以原有格式使用Oops(來自dmesg,等等)。
-忽略任何這樣那樣關於「解碼Oops」或者「通過ksymoops運行」的文檔。 如果你貼出運行過
-ksymoops的來自2.6的Oops,人們只會讓你重貼一次。
-
-快速總結
--------------
-
-發現Oops並發送給看似相關的內核領域的維護者。別太擔心對不上號。如果你不確定就發給
-和你所做的事情相關的代碼的負責人。 如果可重現試著描述怎樣重構。 那甚至比oops更有
-價值。
-
-如果你對於發送給誰一無所知, 發給linux-kernel@vger.kernel.org。感謝你幫助Linux
-儘可能地穩定。
-
-Oops在哪裡?
-----------------------
-
-通常Oops文本由klogd從內核緩衝區里讀取並傳給syslogd,由syslogd寫到syslog文件中,
-典型地是/var/log/messages(依賴於/etc/syslog.conf)。有時klogd崩潰了,這種情況下你
-能夠運行dmesg > file來從內核緩衝區中讀取數據並保存下來。 否則你可以
-cat /proc/kmsg > file, 然而你必須介入中止傳輸, kmsg是一個「永不結束的文件」。如
-果機器崩潰壞到你不能輸入命令或者磁碟不可用那麼你有三種選擇:-
-
-(1) 手抄屏幕上的文本待機器重啓後再輸入計算機。 麻煩但如果沒有針對崩潰的準備,
-這是僅有的選擇。 另外,你可以用數位相機把屏幕拍下來-不太好,但比沒有強。 如果信
-息滾動到了終端的上面,你會發現以高分辯率啓動(比如,vga=791)會讓你讀到更多的文
-本。(注意:這需要vesafb,所以對『早期』的oops沒有幫助)
-
-(2)用串口終端啓動(請參看Documentation/admin-guide/serial-console.rst),運行一個null
-modem到另一台機器並用你喜歡的通訊工具獲取輸出。Minicom工作地很好。
-
-(3)使用Kdump(請參看Documentation/admin-guide/kdump/kdump.rst),
-使用在Documentation/admin-guide/kdump/gdbmacros.txt中定義的dmesg gdb宏,從舊的內存中提取內核
-環形緩衝區。
-
-完整信息
-----------------
-
-注意:以下來自於Linus的郵件適用於2.4內核。 我因爲歷史原因保留了它,並且因爲其中
-一些信息仍然適用。 特別注意的是,請忽略任何ksymoops的引用。
-
-From: Linus Torvalds <torvalds@osdl.org>
-
-怎樣跟蹤Oops.. [原發到linux-kernel的一封郵件]
-
-主要的竅門是有五年和這些煩人的oops消息打交道的經驗;-)
-
-實際上,你有辦法使它更簡單。我有兩個不同的方法:
-
-       gdb /usr/src/linux/vmlinux
-       gdb> disassemble <offending_function>
-
-那是發現問題的簡單辦法,至少如果bug報告做的好的情況下(象這個一樣-運行ksymoops
-得到oops發生的函數及函數內的偏移)。
-
-哦,如果報告發生的內核以相同的編譯器和相似的配置編譯它會有幫助的。
-
-另一件要做的事是反彙編bug報告的「Code」部分:ksymoops也會用正確的工具來做這件事,
-但如果沒有那些工具你可以寫一個傻程序:
-
-       char str[] = "\xXX\xXX\xXX...";
-       main(){}
-
-並用gcc -g編譯它然後執行「disassemble str」(XX部分是由Oops報告的值-你可以僅剪切
-粘貼並用「\x」替換空格-我就是這麼做的,因爲我懶得寫程序自動做這一切)。
-
-另外,你可以用scripts/decodecode這個shell腳本。它的使用方法是:
-decodecode < oops.txt
-
-「Code」之後的十六進位字節可能(在某些架構上)有一些當前指令之前的指令字節以及
-當前和之後的指令字節
-
-Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
-64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
-7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
-
-最後,如果你想知道代碼來自哪裡,你可以:
-
-       cd /usr/src/linux
-       make fs/buffer.s        # 或任何產生BUG的文件
-
-然後你會比gdb反彙編更清楚的知道發生了什麼。
-
-現在,問題是把你所擁有的所有數據結合起來:C源碼(關於它應該怎樣的一般知識),
-彙編代碼及其反彙編得到的代碼(另外還有從「oops」消息得到的寄存器狀態-對了解毀壞的
-指針有用,而且當你有了彙編代碼你也能拿其它的寄存器和任何它們對應的C表達式做匹配
-)。
-
-實際上,你僅需看看哪裡不匹配(這個例子是「Code」反彙編和編譯器生成的代碼不匹配)。
-然後你須要找出爲什麼不匹配。通常很簡單-你看到代碼使用了空指針然後你看代碼想知道
-空指針是怎麼出現的,還有檢查它是否合法..
-
-現在,如果明白這是一項耗時的工作而且需要一丁點兒的專心,沒錯。這就是我爲什麼大多
-只是忽略那些沒有符號表信息的崩潰報告的原因:簡單的說太難查找了(我有一些
-程序用於在內核代碼段中搜索特定的模式,而且有時我也已經能找出那些崩潰的地方,但是
-僅僅是找出正確的序列也確實需要相當紮實的內核知識)
-
-_有時_會發生這種情況,我僅看到崩潰中的反彙編代碼序列, 然後我馬上就明白問題出在
-哪裡。這時我才意識到自己幹這個工作已經太長時間了;-)
-
-               Linus
-
-
----------------------------------------------------------------------------
-關於Oops跟蹤的註解:
-
-爲了幫助Linus和其它內核開發者,klogd納入了大量的支持來處理保護錯誤。爲了擁有對
-地址解析的完整支持至少應該使用1.3-pl3的sysklogd包。
-
-當保護錯誤發生時,klogd守護進程自動把內核日誌信息中的重要地址翻譯成它們相應的符
-號。
-
-klogd執行兩種類型的地址解析。首先是靜態翻譯其次是動態翻譯。靜態翻譯和ksymoops
-一樣使用System.map文件。爲了做靜態翻譯klogd守護進程必須在初始化時能找到system
-map文件。關於klogd怎樣搜索map文件請參看klogd手冊頁。
-
-動態地址翻譯在使用內核可裝載模塊時很重要。 因爲內核模塊的內存是從內核動態內存池
-里分配的,所以不管是模塊開始位置還是模塊中函數和符號的位置都不是固定的。
-
-內核支持允許程序決定裝載哪些模塊和它們在內存中位置的系統調用。使用這些系統調用
-klogd守護進程生成一張符號表用於調試發生在可裝載模塊中的保護錯誤。
-
-至少klogd會提供產生保護錯誤的模塊名。還可有額外的符號信息供可裝載模塊開發者選擇
-以從模塊中輸出符號信息。
-
-因爲內核模塊環境可能是動態的,所以必須有一種機制當模塊環境發生改變時來通知klogd
-守護進程。 有一些可用的命令行選項允許klogd向當前執行中的守護進程發送信號,告知符
-號信息應該被刷新了。 更多信息請參看klogd手冊頁。
-
-sysklogd發布時包含一個補丁修改了modules-2.0.0包,無論何時一個模塊裝載或者卸載都
-會自動向klogd發送信號。打上這個補丁提供了必要的對調試發生於內核可裝載模塊的保護
-錯誤的無縫支持。
-
-以下是被klogd處理過的發生在可裝載模塊中的一個保護錯誤例子:
----------------------------------------------------------------------------
-Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
-Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
-Aug 29 09:51:01 blizard kernel: *pde = 00000000
-Aug 29 09:51:01 blizard kernel: Oops: 0002
-Aug 29 09:51:01 blizard kernel: CPU:    0
-Aug 29 09:51:01 blizard kernel: EIP:    0010:[oops:_oops+16/3868]
-Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
-Aug 29 09:51:01 blizard kernel: eax: 315e97cc   ebx: 003a6f80   ecx: 001be77b   edx: 00237c0c
-Aug 29 09:51:01 blizard kernel: esi: 00000000   edi: bffffdb3   ebp: 00589f90   esp: 00589f8c
-Aug 29 09:51:01 blizard kernel: ds: 0018   es: 0018   fs: 002b   gs: 002b   ss: 0018
-Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
-Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
-Aug 29 09:51:01 blizard kernel:        00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
-Aug 29 09:51:01 blizard kernel:        bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
-Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
-Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
----------------------------------------------------------------------------
-
-Dr. G.W. Wettstein           Oncology Research Div. Computing Facility
-Roger Maris Cancer Center    INTERNET: greg@wind.rmcc.com
-820 4th St. N.
-Fargo, ND  58122
-Phone: 701-234-7556
-
-
----------------------------------------------------------------------------
-受汙染的內核
-
-一些oops報告在程序記數器之後包含字符串'Tainted: '。這表明內核已經被一些東西給汙
-染了。 該字符串之後緊跟著一系列的位置敏感的字符,每個代表一個特定的汙染值。
-
-  1:'G'如果所有裝載的模塊都有GPL或相容的許可證,'P'如果裝載了任何的專有模塊。
-沒有模塊MODULE_LICENSE或者帶有insmod認爲是與GPL不相容的的MODULE_LICENSE的模塊被
-認定是專有的。
-
-  2:'F'如果有任何通過「insmod -f」被強制裝載的模塊,' '如果所有模塊都被正常裝載。
-
-  3:'S'如果oops發生在SMP內核中,運行於沒有證明安全運行多處理器的硬體。 當前這種
-情況僅限於幾種不支持SMP的速龍處理器。
-
-  4:'R'如果模塊通過「insmod -f」被強制裝載,' '如果所有模塊都被正常裝載。
-
-  5:'M'如果任何處理器報告了機器檢查異常,' '如果沒有發生機器檢查異常。
-
-  6:'B'如果頁釋放函數發現了一個錯誤的頁引用或者一些非預期的頁標誌。
-
-  7:'U'如果用戶或者用戶應用程式特別請求設置汙染標誌,否則' '。
-
-  8:'D'如果內核剛剛死掉,比如有OOPS或者BUG。
-
-使用'Tainted: '字符串的主要原因是要告訴內核調試者,這是否是一個乾淨的內核亦或發
-生了任何的不正常的事。汙染是永久的:即使出錯的模塊已經被卸載了,汙染值仍然存在,
-以表明內核不再值得信任。
-
index 8739120..8364afa 100644 (file)
@@ -377,7 +377,7 @@ Emulating cr0.wp
 ================
 
 If tdp is not enabled, the host must keep cr0.wp=1 so page write protection
-works for the guest kernel, not guest guest userspace.  When the guest
+works for the guest kernel, not guest userspace.  When the guest
 cr0.wp=1, this does not present a problem.  However when the guest cr0.wp=0,
 we cannot map the permissions for gpte.u=1, gpte.w=0 to any spte (the
 semantics require allowing any guest kernel access plus user read access).
index 7e5b50f..842e7ae 100644 (file)
@@ -52,7 +52,7 @@ Notes and limitations.
   clear the entire bulk in buffer.  It would be possible to read the
   maximum buffer size to not run into this error condition, only extra
   bytes in the buffer is a logic error in the driver.  The code should
-  should match reads and writes as well as data sizes.  Reads and
+  match reads and writes as well as data sizes.  Reads and
   writes are serialized and the status verifies that the chip is idle
   (and data is available) before the read is executed, so it should
   not happen.
index da4e8b4..99255b6 100644 (file)
@@ -113,7 +113,7 @@ generally only make sense when searching is disabled, as a search will
 redetect manually removed devices that are present and timeout manually
 added devices that aren't on the bus.
 
-Bus searches occur at an interval, specified as a summ of timeout and
+Bus searches occur at an interval, specified as a sum of timeout and
 timeout_us module parameters (either of which may be 0) for as long as
 w1_master_search remains greater than 0 or is -1.  Each search attempt
 decrements w1_master_search by 1 (down to 0) and increments
index e433e08..0afdce3 100644 (file)
@@ -33,8 +33,8 @@ Some of these entries are:
  - 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 do_IRQ with
-   the interrupt number as a parameter.
+   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.
index 5895173..dcf675b 100644 (file)
@@ -348,7 +348,6 @@ M:  "Rafael J. Wysocki" <rafael@kernel.org>
 R:     Len Brown <lenb@kernel.org>
 L:     linux-acpi@vger.kernel.org
 S:     Supported
-W:     https://01.org/linux-acpi
 Q:     https://patchwork.kernel.org/project/linux-acpi/list/
 B:     https://bugzilla.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
@@ -427,7 +426,6 @@ M:  Rafael J. Wysocki <rafael@kernel.org>
 R:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
 S:     Supported
-W:     https://01.org/linux-acpi
 B:     https://bugzilla.kernel.org
 F:     drivers/acpi/*thermal*
 
@@ -671,7 +669,8 @@ F:  fs/afs/
 F:     include/trace/events/afs.h
 
 AGPGART DRIVER
-M:     David Airlie <airlied@linux.ie>
+M:     David Airlie <airlied@redhat.com>
+L:     dri-devel@lists.freedesktop.org
 S:     Maintained
 T:     git git://anongit.freedesktop.org/drm/drm
 F:     drivers/char/agp/
@@ -1010,7 +1009,6 @@ F:        drivers/spi/spi-amd.c
 
 AMD MP2 I2C DRIVER
 M:     Elie Morisse <syniurge@gmail.com>
-M:     Nehal Shah <nehal-bakulchandra.shah@amd.com>
 M:     Shyam Sundar S K <shyam-sundar.s-k@amd.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
@@ -1803,7 +1801,7 @@ N:        sun[x456789]i
 N:     sun50i
 
 ARM/Amlogic Meson SoC CLOCK FRAMEWORK
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 M:     Jerome Brunet <jbrunet@baylibre.com>
 L:     linux-amlogic@lists.infradead.org
 S:     Maintained
@@ -1828,7 +1826,7 @@ F:        Documentation/devicetree/bindings/sound/amlogic*
 F:     sound/soc/meson/
 
 ARM/Amlogic Meson SoC support
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 M:     Kevin Hilman <khilman@baylibre.com>
 R:     Jerome Brunet <jbrunet@baylibre.com>
 R:     Martin Blumenstingl <martin.blumenstingl@googlemail.com>
@@ -2531,7 +2529,7 @@ W:        http://www.digriz.org.uk/ts78xx/kernel
 F:     arch/arm/mach-orion5x/ts78xx-*
 
 ARM/OXNAS platform support
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-oxnas@groups.io (moderated for non-subscribers)
 S:     Maintained
@@ -2579,7 +2577,7 @@ W:        http://www.armlinux.org.uk/
 
 ARM/QUALCOMM SUPPORT
 M:     Andy Gross <agross@kernel.org>
-M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+M:     Bjorn Andersson <andersson@kernel.org>
 R:     Konrad Dybcio <konrad.dybcio@somainline.org>
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
@@ -2670,7 +2668,6 @@ M:        Russell King <linux@armlinux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 W:     http://www.armlinux.org.uk/
-F:     arch/arm/include/asm/hardware/entry-macro-iomd.S
 F:     arch/arm/include/asm/hardware/ioc.h
 F:     arch/arm/include/asm/hardware/iomd.h
 F:     arch/arm/include/asm/hardware/memc.h
@@ -5245,6 +5242,7 @@ F:        block/blk-throttle.c
 F:     include/linux/blk-cgroup.h
 
 CONTROL GROUP - CPUSET
+M:     Waiman Long <longman@redhat.com>
 M:     Zefan Li <lizefan.x@bytedance.com>
 L:     cgroups@vger.kernel.org
 S:     Maintained
@@ -6753,7 +6751,7 @@ F:        Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
 F:     drivers/gpu/drm/panel/panel-widechips-ws2401.c
 
 DRM DRIVERS
-M:     David Airlie <airlied@linux.ie>
+M:     David Airlie <airlied@gmail.com>
 M:     Daniel Vetter <daniel@ffwll.ch>
 L:     dri-devel@lists.freedesktop.org
 S:     Maintained
@@ -6792,7 +6790,7 @@ F:        Documentation/devicetree/bindings/display/allwinner*
 F:     drivers/gpu/drm/sun4i/
 
 DRM DRIVERS FOR AMLOGIC SOCS
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 L:     dri-devel@lists.freedesktop.org
 L:     linux-amlogic@lists.infradead.org
 S:     Supported
@@ -6814,7 +6812,7 @@ F:        drivers/gpu/drm/atmel-hlcdc/
 
 DRM DRIVERS FOR BRIDGE CHIPS
 M:     Andrzej Hajda <andrzej.hajda@intel.com>
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 M:     Robert Foss <robert.foss@linaro.org>
 R:     Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
 R:     Jonas Karlman <jonas@kwiboo.se>
@@ -8652,8 +8650,8 @@ F:        drivers/input/touchscreen/goodix*
 
 GOOGLE ETHERNET DRIVERS
 M:     Jeroen de Borst <jeroendb@google.com>
-R:     Catherine Sullivan <csully@google.com>
-R:     David Awogbemila <awogbemila@google.com>
+M:     Catherine Sullivan <csully@google.com>
+R:     Shailend Chand <shailend@google.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/device_drivers/ethernet/google/gve.rst
@@ -8943,7 +8941,7 @@ F:        include/linux/hw_random.h
 
 HARDWARE SPINLOCK CORE
 M:     Ohad Ben-Cohen <ohad@wizery.com>
-M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+M:     Bjorn Andersson <andersson@kernel.org>
 R:     Baolin Wang <baolin.wang7@gmail.com>
 L:     linux-remoteproc@vger.kernel.org
 S:     Maintained
@@ -9122,7 +9120,7 @@ S:        Maintained
 F:     drivers/dma/hisi_dma.c
 
 HISILICON GPIO DRIVER
-M:     Luo Jiaxing <luojiaxing@huawei.com>
+M:     Jay Fang <f.fangjian@huawei.com>
 L:     linux-gpio@vger.kernel.org
 S:     Maintained
 F:     drivers/gpio/gpio-hisi.c
@@ -9208,8 +9206,8 @@ F:        Documentation/ABI/testing/debugfs-hisi-zip
 F:     drivers/crypto/hisilicon/zip/
 
 HISILICON ROCE DRIVER
+M:     Haoyue Xu <xuhaoyue1@hisilicon.com>
 M:     Wenpeng Liang <liangwenpeng@huawei.com>
-M:     Weihang Li <liweihang@huawei.com>
 L:     linux-rdma@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt
@@ -10032,6 +10030,7 @@ F:      Documentation/devicetree/bindings/input/
 F:     Documentation/devicetree/bindings/serio/
 F:     Documentation/input/
 F:     drivers/input/
+F:     include/dt-bindings/input/
 F:     include/linux/input.h
 F:     include/linux/input/
 F:     include/uapi/linux/input-event-codes.h
@@ -10377,7 +10376,6 @@ INTEL MENLOW THERMAL DRIVER
 M:     Sujith Thomas <sujith.thomas@intel.com>
 L:     linux-pm@vger.kernel.org
 S:     Supported
-W:     https://01.org/linux-acpi
 F:     drivers/thermal/intel/intel_menlow.c
 
 INTEL P-Unit IPC DRIVER
@@ -10827,7 +10825,7 @@ F:      drivers/media/tuners/it913x*
 
 ITE IT66121 HDMI BRIDGE DRIVER
 M:     Phong LE <ple@baylibre.com>
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 S:     Maintained
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 F:     Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml
@@ -11346,7 +11344,7 @@ F:      kernel/debug/
 F:     kernel/module/kdb.c
 
 KHADAS MCU MFD DRIVER
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 L:     linux-amlogic@lists.infradead.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
@@ -13217,7 +13215,7 @@ S:      Maintained
 F:     drivers/watchdog/menz69_wdt.c
 
 MESON AO CEC DRIVER FOR AMLOGIC SOCS
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 L:     linux-media@vger.kernel.org
 L:     linux-amlogic@lists.infradead.org
 S:     Supported
@@ -13228,7 +13226,7 @@ F:      drivers/media/cec/platform/meson/ao-cec-g12a.c
 F:     drivers/media/cec/platform/meson/ao-cec.c
 
 MESON GE2D DRIVER FOR AMLOGIC SOCS
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 L:     linux-media@vger.kernel.org
 L:     linux-amlogic@lists.infradead.org
 S:     Supported
@@ -13244,7 +13242,7 @@ F:      Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
 F:     drivers/mtd/nand/raw/meson_*
 
 MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
-M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Neil Armstrong <neil.armstrong@linaro.org>
 L:     linux-media@vger.kernel.org
 L:     linux-amlogic@lists.infradead.org
 S:     Supported
@@ -14448,6 +14446,7 @@ M:      Willy Tarreau <w@1wt.eu>
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
 F:     tools/include/nolibc/
+F:     tools/testing/selftests/nolibc/
 
 NSDEPS
 M:     Matthias Maennich <maennich@google.com>
@@ -16124,7 +16123,7 @@ F:      drivers/gpio/gpio-sama5d2-piobu.c
 F:     drivers/pinctrl/pinctrl-at91*
 
 PIN CONTROLLER - QUALCOMM
-M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+M:     Bjorn Andersson <andersson@kernel.org>
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pinctrl/qcom,*.txt
@@ -16817,7 +16816,7 @@ F:      Documentation/devicetree/bindings/media/*camss*
 F:     drivers/media/platform/qcom/camss/
 
 QUALCOMM CLOCK DRIVERS
-M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+M:     Bjorn Andersson <andersson@kernel.org>
 L:     linux-arm-msm@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
@@ -16856,6 +16855,7 @@ F:      drivers/net/ethernet/qualcomm/emac/
 
 QUALCOMM ETHQOS ETHERNET DRIVER
 M:     Vinod Koul <vkoul@kernel.org>
+R:     Bhupesh Sharma <bhupesh.sharma@linaro.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/net/qcom,ethqos.txt
@@ -17306,7 +17306,7 @@ S:      Supported
 F:     fs/reiserfs/
 
 REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
-M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+M:     Bjorn Andersson <andersson@kernel.org>
 M:     Mathieu Poirier <mathieu.poirier@linaro.org>
 L:     linux-remoteproc@vger.kernel.org
 S:     Maintained
@@ -17319,7 +17319,7 @@ F:      include/linux/remoteproc.h
 F:     include/linux/remoteproc/
 
 REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM
-M:     Bjorn Andersson <bjorn.andersson@linaro.org>
+M:     Bjorn Andersson <andersson@kernel.org>
 M:     Mathieu Poirier <mathieu.poirier@linaro.org>
 L:     linux-remoteproc@vger.kernel.org
 S:     Maintained
@@ -17531,9 +17531,19 @@ M:     Conor Dooley <conor.dooley@microchip.com>
 M:     Daire McNamara <daire.mcnamara@microchip.com>
 L:     linux-riscv@lists.infradead.org
 S:     Supported
+F:     Documentation/devicetree/bindings/clock/microchip,mpfs.yaml
+F:     Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml
+F:     Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml
+F:     Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
+F:     Documentation/devicetree/bindings/net/can/microchip,mpfs-can.yaml
+F:     Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
+F:     Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml
+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/i2c/busses/i2c-microchip-core.c
 F:     drivers/mailbox/mailbox-mpfs.c
 F:     drivers/pci/controller/pcie-microchip-host.c
 F:     drivers/rtc/rtc-mpfs.c
@@ -17734,6 +17744,17 @@ L:     linux-rdma@vger.kernel.org
 S:     Maintained
 F:     drivers/infiniband/ulp/rtrs/
 
+RUNTIME VERIFICATION (RV)
+M:     Daniel Bristot de Oliveira <bristot@kernel.org>
+M:     Steven Rostedt <rostedt@goodmis.org>
+L:     linux-trace-devel@vger.kernel.org
+S:     Maintained
+F:     Documentation/trace/rv/
+F:     include/linux/rv.h
+F:     include/rv/
+F:     kernel/trace/rv/
+F:     tools/verification/
+
 RXRPC SOCKETS (AF_RXRPC)
 M:     David Howells <dhowells@redhat.com>
 M:     Marc Dionne <marc.dionne@auristor.com>
@@ -19937,6 +19958,7 @@ S:      Supported
 F:     drivers/net/team/
 F:     include/linux/if_team.h
 F:     include/uapi/linux/if_team.h
+F:     tools/testing/selftests/drivers/net/team/
 
 TECHNOLOGIC SYSTEMS TS-5500 PLATFORM SUPPORT
 M:     "Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
@@ -20600,6 +20622,7 @@ F:      include/*/ftrace.h
 F:     include/linux/trace*.h
 F:     include/trace/
 F:     kernel/trace/
+F:     scripts/tracing/
 F:     tools/testing/selftests/ftrace/
 
 TRACING MMIO ACCESSES (MMIOTRACE)
@@ -20764,6 +20787,7 @@ UBLK USERSPACE BLOCK DRIVER
 M:     Ming Lei <ming.lei@redhat.com>
 L:     linux-block@vger.kernel.org
 S:     Maintained
+F:     Documentation/block/ublk.rst
 F:     drivers/block/ublk_drv.c
 F:     include/uapi/linux/ublk_cmd.h
 
@@ -21541,7 +21565,7 @@ F:      drivers/gpio/gpio-virtio.c
 F:     include/uapi/linux/virtio_gpio.h
 
 VIRTIO GPU DRIVER
-M:     David Airlie <airlied@linux.ie>
+M:     David Airlie <airlied@redhat.com>
 M:     Gerd Hoffmann <kraxel@redhat.com>
 R:     Gurchetan Singh <gurchetansingh@chromium.org>
 R:     Chia-I Wu <olvaffe@gmail.com>
@@ -22305,7 +22329,7 @@ M:      Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
 R:     Srinivas Neeli <srinivas.neeli@xilinx.com>
 R:     Michal Simek <michal.simek@xilinx.com>
 S:     Maintained
-F:     Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
+F:     Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
 F:     Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
 F:     drivers/gpio/gpio-xilinx.c
 F:     drivers/gpio/gpio-zynq.c
index 952d354..8478e13 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION =
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
@@ -1287,8 +1287,7 @@ hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
 
 PHONY += headers
 headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts
-       $(if $(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/Kbuild),, \
-         $(error Headers not exportable for the $(SRCARCH) architecture))
+       $(if $(filter um, $(SRCARCH)), $(error Headers not exportable for UML))
        $(Q)$(MAKE) $(hdr-inst)=include/uapi
        $(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi
 
index 5dbf11a..8b311e4 100644 (file)
@@ -923,6 +923,9 @@ config HAVE_SOFTIRQ_ON_OWN_STACK
          Architecture provides a function to run __do_softirq() on a
          separate stack.
 
+config SOFTIRQ_ON_OWN_STACK
+       def_bool HAVE_SOFTIRQ_ON_OWN_STACK && !PREEMPT_RT
+
 config ALTERNATE_USER_ADDRESS_SPACE
        bool
        help
index cb2e069..abfed1a 100644 (file)
@@ -23,7 +23,9 @@ unsigned int __machine_arch_type;
 #include <linux/types.h>
 #include <linux/linkage.h>
 #include "misc.h"
+#ifdef CONFIG_ARCH_EP93XX
 #include "misc-ep93xx.h"
+#endif
 
 static void putstr(const char *ptr);
 
index 7da42a5..7e50fe6 100644 (file)
                        mmc1: mmc@0 {
                                compatible = "ti,am335-sdhci";
                                ti,needs-special-reset;
-                               dmas = <&edma_xbar 24 0 0
-                                       &edma_xbar 25 0 0>;
+                               dmas = <&edma 24 0>, <&edma 25 0>;
                                dma-names = "tx", "rx";
                                interrupts = <64>;
                                reg = <0x0 0x1000>;
index c260aa1..a1f029e 100644 (file)
        status = "disabled";
 };
 
+&usb4_tm {
+       status = "disabled";
+};
+
 &atl_tm {
        status = "disabled";
 };
index 2dfb32b..fbb2258 100644 (file)
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0x1000d000 0x1000>;
                        clocks = <&sspclk>, <&pclk>;
-                       clock-names = "SSPCLK", "apb_pclk";
+                       clock-names = "sspclk", "apb_pclk";
                };
 
                wdog: watchdog@10010000 {
index 06b8723..efed325 100644 (file)
                        interrupt-parent = <&intc_dc1176>;
                        interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&sspclk>, <&pclk>;
-                       clock-names = "SSPCLK", "apb_pclk";
+                       clock-names = "sspclk", "apb_pclk";
                };
 
                pb1176_serial0: serial@1010c000 {
index 295aef4..89103d5 100644 (file)
                        interrupt-parent = <&intc_pb11mp>;
                        interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&sspclk>, <&pclk>;
-                       clock-names = "SSPCLK", "apb_pclk";
+                       clock-names = "sspclk", "apb_pclk";
                };
 
                watchdog@1000f000 {
index 6f61f96..ec1507c 100644 (file)
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0x1000d000 0x1000>;
                        clocks = <&sspclk>, <&pclk>;
-                       clock-names = "SSPCLK", "apb_pclk";
+                       clock-names = "sspclk", "apb_pclk";
                };
 
                wdog0: watchdog@1000f000 {
index 76b2025..83bcf9f 100644 (file)
@@ -76,8 +76,8 @@
                regulators {
                        vdd_3v3: VDD_IO {
                                regulator-name = "VDD_IO";
-                               regulator-min-microvolt = <1200000>;
-                               regulator-max-microvolt = <3700000>;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
                                regulator-initial-mode = <2>;
                                regulator-allowed-modes = <2>, <4>;
                                regulator-always-on;
@@ -95,8 +95,8 @@
 
                        vddio_ddr: VDD_DDR {
                                regulator-name = "VDD_DDR";
-                               regulator-min-microvolt = <600000>;
-                               regulator-max-microvolt = <1850000>;
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
                                regulator-initial-mode = <2>;
                                regulator-allowed-modes = <2>, <4>;
                                regulator-always-on;
 
                        vdd_core: VDD_CORE {
                                regulator-name = "VDD_CORE";
-                               regulator-min-microvolt = <600000>;
-                               regulator-max-microvolt = <1850000>;
+                               regulator-min-microvolt = <1250000>;
+                               regulator-max-microvolt = <1250000>;
                                regulator-initial-mode = <2>;
                                regulator-allowed-modes = <2>, <4>;
                                regulator-always-on;
 
                        LDO1 {
                                regulator-name = "LDO1";
-                               regulator-min-microvolt = <1200000>;
-                               regulator-max-microvolt = <3700000>;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
                                regulator-always-on;
 
                                regulator-state-standby {
 
                        LDO2 {
                                regulator-name = "LDO2";
-                               regulator-min-microvolt = <1200000>;
-                               regulator-max-microvolt = <3700000>;
-                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
 
                                regulator-state-standby {
                                        regulator-on-in-suspend;
index 6865be8..dd1dec9 100644 (file)
                        regulators {
                                vdd_io_reg: VDD_IO {
                                        regulator-name = "VDD_IO";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <3700000>;
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-always-on;
 
                                VDD_DDR {
                                        regulator-name = "VDD_DDR";
-                                       regulator-min-microvolt = <600000>;
-                                       regulator-max-microvolt = <1850000>;
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-always-on;
 
                                VDD_CORE {
                                        regulator-name = "VDD_CORE";
-                                       regulator-min-microvolt = <600000>;
-                                       regulator-max-microvolt = <1850000>;
+                                       regulator-min-microvolt = <1250000>;
+                                       regulator-max-microvolt = <1250000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-always-on;
                                        regulator-max-microvolt = <1850000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
-                                       regulator-always-on;
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
 
                                LDO1 {
                                        regulator-name = "LDO1";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <3700000>;
+                                       regulator-min-microvolt = <2500000>;
+                                       regulator-max-microvolt = <2500000>;
                                        regulator-always-on;
 
                                        regulator-state-standby {
 
                                LDO2 {
                                        regulator-name = "LDO2";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <3700000>;
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
                                        regulator-always-on;
 
                                        regulator-state-standby {
index de44da2..3b25c67 100644 (file)
                        regulators {
                                vdd_3v3: VDD_IO {
                                        regulator-name = "VDD_IO";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <3700000>;
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-always-on;
 
                                vddioddr: VDD_DDR {
                                        regulator-name = "VDD_DDR";
-                                       regulator-min-microvolt = <1300000>;
-                                       regulator-max-microvolt = <1450000>;
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-always-on;
 
                                vddcore: VDD_CORE {
                                        regulator-name = "VDD_CORE";
-                                       regulator-min-microvolt = <1100000>;
-                                       regulator-max-microvolt = <1850000>;
+                                       regulator-min-microvolt = <1150000>;
+                                       regulator-max-microvolt = <1150000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-always-on;
                                vddcpu: VDD_OTHER {
                                        regulator-name = "VDD_OTHER";
                                        regulator-min-microvolt = <1050000>;
-                                       regulator-max-microvolt = <1850000>;
+                                       regulator-max-microvolt = <1250000>;
                                        regulator-initial-mode = <2>;
                                        regulator-allowed-modes = <2>, <4>;
                                        regulator-ramp-delay = <3125>;
 
                                vldo1: LDO1 {
                                        regulator-name = "LDO1";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <3700000>;
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
 
                                        regulator-state-standby {
index 5463443..cbd094d 100644 (file)
@@ -32,6 +32,7 @@
                        next-level-cache = <&L2_0>;
                        enable-method = "psci";
                };
+
                CA7_2: cpu@2 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
@@ -39,6 +40,7 @@
                        next-level-cache = <&L2_0>;
                        enable-method = "psci";
                };
+
                L2_0: l2-cache0 {
                        compatible = "cache";
                };
 
        timer {
                compatible = "arm,armv7-timer";
-               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_LOW)>;
                arm,cpu-registers-not-fw-configured;
        };
 
        psci {
                compatible = "arm,psci-0.2";
                method = "smc";
-               cpu_off = <1>;
-               cpu_on = <2>;
        };
 
        axi@81000000 {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
-               ranges = <0 0x81000000 0x4000>;
+               ranges = <0 0x81000000 0x8000>;
 
                gic: interrupt-controller@1000 {
                        compatible = "arm,cortex-a7-gic";
                        #interrupt-cells = <3>;
-                       #address-cells = <0>;
                        interrupt-controller;
+                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(3) | IRQ_TYPE_LEVEL_HIGH)>;
                        reg = <0x1000 0x1000>,
-                               <0x2000 0x2000>;
+                               <0x2000 0x2000>,
+                               <0x4000 0x2000>,
+                               <0x6000 0x2000>;
                };
        };
 
index e610c10..8aa47a2 100644 (file)
 
        timer {
                compatible = "arm,armv7-timer";
-               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
                arm,cpu-registers-not-fw-configured;
        };
 
        psci {
                compatible = "arm,psci-0.2";
                method = "smc";
-               cpu_off = <1>;
-               cpu_on = <2>;
        };
 
        axi@81000000 {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
-               ranges = <0 0x81000000 0x4000>;
+               ranges = <0 0x81000000 0x8000>;
 
                gic: interrupt-controller@1000 {
                        compatible = "arm,cortex-a7-gic";
                        #interrupt-cells = <3>;
-                       #address-cells = <0>;
                        interrupt-controller;
+                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
                        reg = <0x1000 0x1000>,
-                               <0x2000 0x2000>;
+                               <0x2000 0x2000>,
+                               <0x4000 0x2000>,
+                               <0x6000 0x2000>;
                };
        };
 
index a7dff59..1e8b5fa 100644 (file)
@@ -32,6 +32,7 @@
                        next-level-cache = <&L2_0>;
                        enable-method = "psci";
                };
+
                L2_0: l2-cache0 {
                        compatible = "cache";
                };
 
        timer {
                compatible = "arm,armv7-timer";
-               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
                arm,cpu-registers-not-fw-configured;
        };
 
index 095c914..6b791d5 100644 (file)
                vin-supply = <&reg_3p3v_s5>;
        };
 
-       reg_3p3v_s0: regulator-3p3v-s0 {
-               compatible = "regulator-fixed";
-               regulator-name = "V_3V3_S0";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               regulator-always-on;
-               regulator-boot-on;
-               vin-supply = <&reg_3p3v_s5>;
-       };
-
        reg_3p3v_s5: regulator-3p3v-s5 {
                compatible = "regulator-fixed";
                regulator-name = "V_3V3_S5";
 
        /* default boot source: workaround #1 for errata ERR006282 */
        smarc_flash: flash@0 {
-               compatible = "winbond,w25q16dw", "jedec,spi-nor";
+               compatible = "jedec,spi-nor";
                reg = <0>;
                spi-max-frequency = <20000000>;
        };
index a1676b5..c5a98b0 100644 (file)
@@ -28,7 +28,7 @@
                enable-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
        };
 
-       backlight_led: backlight_led {
+       backlight_led: backlight-led {
                compatible = "pwm-backlight";
                pwms = <&pwm3 0 5000000 0>;
                brightness-levels = <0 16 64 255>;
index d47bfb6..cc514cf 100644 (file)
                clock-names = "uartclk", "apb_pclk";
        };
 
-       ssp@300000 {
+       spi@300000 {
                compatible = "arm,pl022", "arm,primecell";
                reg = <0x00300000 0x1000>;
                interrupts-extended = <&impd1_vic 3>;
                clocks = <&impd1_sspclk>, <&sysclk>;
-               clock-names = "spiclk", "apb_pclk";
+               clock-names = "sspclk", "apb_pclk";
        };
 
        impd1_gpio0: gpio@400000 {
                /* 640x480 16bpp @ 25.175MHz is 36827428 bytes/s */
                max-memory-bandwidth = <40000000>;
                memory-region = <&impd1_ram>;
+               dma-ranges;
 
                port@0 {
                        #address-cells = <1>;
index 9b652cc..9148287 100644 (file)
 
        pci: pciv3@62000000 {
                compatible = "arm,integrator-ap-pci", "v3,v360epc-pci";
+               device_type = "pci";
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
                lm0: bus@c0000000 {
                        compatible = "simple-bus";
                        ranges = <0x00000000 0xc0000000 0x10000000>;
-                       dma-ranges = <0x00000000 0x80000000 0x10000000>;
+                       dma-ranges = <0x00000000 0xc0000000 0x10000000>;
                        reg = <0xc0000000 0x10000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                lm1: bus@d0000000 {
                        compatible = "simple-bus";
                        ranges = <0x00000000 0xd0000000 0x10000000>;
-                       dma-ranges = <0x00000000 0x80000000 0x10000000>;
+                       dma-ranges = <0x00000000 0xd0000000 0x10000000>;
                        reg = <0xd0000000 0x10000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                lm2: bus@e0000000 {
                        compatible = "simple-bus";
                        ranges = <0x00000000 0xe0000000 0x10000000>;
-                       dma-ranges = <0x00000000 0x80000000 0x10000000>;
+                       dma-ranges = <0x00000000 0xe0000000 0x10000000>;
                        reg = <0xe0000000 0x10000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                lm3: bus@f0000000 {
                        compatible = "simple-bus";
                        ranges = <0x00000000 0xf0000000 0x10000000>;
-                       dma-ranges = <0x00000000 0x80000000 0x10000000>;
+                       dma-ranges = <0x00000000 0xf0000000 0x10000000>;
                        reg = <0xf0000000 0x10000000>;
                        #address-cells = <1>;
                        #size-cells = <1>;
index 894bf9d..0bf8187 100644 (file)
 
                        phy0: ethernet-phy@1 {
                                reg = <1>;
-                               interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        };
 
                        phy1: ethernet-phy@2 {
                                reg = <2>;
-                               interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        };
                };
index eb5291b..e07b807 100644 (file)
@@ -79,7 +79,7 @@
        clocks = <&ref12>;
 };
 
-&sdhci {
+&mmc {
        status = "okay";
 };
 
index f5f070a..764832d 100644 (file)
@@ -93,8 +93,8 @@
                        clock-names = "PCLK";
                };
 
-               sdhci: sdhci@98e00000 {
-                       compatible = "moxa,moxart-sdhci";
+               mmc: mmc@98e00000 {
+                       compatible = "moxa,moxart-mmc";
                        reg = <0x98e00000 0x5C>;
                        interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clk_apb>;
index 79f7cc2..a520615 100644 (file)
                        reg = <0x101f4000 0x1000>;
                        interrupts = <11>;
                        clocks = <&xtal24mhz>, <&pclk>;
-                       clock-names = "SSPCLK", "apb_pclk";
+                       clock-names = "sspclk", "apb_pclk";
                };
 
                fpga {
index da90ce9..e185eee 100644 (file)
@@ -196,7 +196,6 @@ CONFIG_RTC_DRV_AT91SAM9=y
 CONFIG_DMADEVICES=y
 CONFIG_AT_HDMAC=y
 CONFIG_AT_XDMAC=y
-CONFIG_MICROCHIP_PIT64B=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_AT91_ADC=y
index 0384030..b2311f0 100644 (file)
@@ -188,7 +188,6 @@ CONFIG_RTC_DRV_AT91SAM9=y
 CONFIG_DMADEVICES=y
 CONFIG_AT_XDMAC=y
 CONFIG_STAGING=y
-CONFIG_MICROCHIP_PIT64B=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_IIO_SW_TRIGGER=y
index 034cb48..fe28fc1 100644 (file)
@@ -70,7 +70,7 @@ static void __init init_irq_stacks(void)
        }
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 static void ____do_softirq(void *arg)
 {
        __do_softirq();
index df6d673..f4501de 100644 (file)
@@ -541,10 +541,42 @@ extern u32 at91_pm_suspend_in_sram_sz;
 
 static int at91_suspend_finish(unsigned long val)
 {
+       unsigned char modified_gray_code[] = {
+               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d,
+               0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b,
+               0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13,
+               0x10, 0x11,
+       };
+       unsigned int tmp, index;
        int i;
 
        if (soc_pm.data.mode == AT91_PM_BACKUP && soc_pm.data.ramc_phy) {
                /*
+                * Bootloader will perform DDR recalibration and will try to
+                * restore the ZQ0SR0 with the value saved here. But the
+                * calibration is buggy and restoring some values from ZQ0SR0
+                * is forbidden and risky thus we need to provide processed
+                * values for these (modified gray code values).
+                */
+               tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0);
+
+               /* Store pull-down output impedance select. */
+               index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f;
+               soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index];
+
+               /* Store pull-up output impedance select. */
+               index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f;
+               soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
+
+               /* Store pull-down on-die termination impedance select. */
+               index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f;
+               soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
+
+               /* Store pull-up on-die termination impedance select. */
+               index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f;
+               soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
+
+               /*
                 * The 1st 8 words of memory might get corrupted in the process
                 * of DDR PHY recalibration; it is saved here in securam and it
                 * will be restored later, after recalibration, by bootloader
@@ -1066,10 +1098,6 @@ static int __init at91_pm_backup_init(void)
                of_scan_flat_dt(at91_pm_backup_scan_memcs, &located);
                if (!located)
                        goto securam_fail;
-
-               /* DDR3PHY_ZQ0SR0 */
-               soc_pm.bu->ddr_phy_calibration[0] = readl(soc_pm.data.ramc_phy +
-                                                         0x188);
        }
 
        return 0;
index abe4ced..ffed4d9 100644 (file)
@@ -172,9 +172,15 @@ sr_ena_2:
        /* Put DDR PHY's DLL in bypass mode for non-backup modes. */
        cmp     r7, #AT91_PM_BACKUP
        beq     sr_ena_3
-       ldr     tmp1, [r3, #DDR3PHY_PIR]
-       orr     tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
-       str     tmp1, [r3, #DDR3PHY_PIR]
+
+       /* Disable DX DLLs. */
+       ldr     tmp1, [r3, #DDR3PHY_DX0DLLCR]
+       orr     tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+       str     tmp1, [r3, #DDR3PHY_DX0DLLCR]
+
+       ldr     tmp1, [r3, #DDR3PHY_DX1DLLCR]
+       orr     tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+       str     tmp1, [r3, #DDR3PHY_DX1DLLCR]
 
 sr_ena_3:
        /* Power down DDR PHY data receivers. */
@@ -221,10 +227,14 @@ sr_ena_3:
        bic     tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
        str     tmp1, [r3, #DDR3PHY_DSGCR]
 
-       /* Take DDR PHY's DLL out of bypass mode. */
-       ldr     tmp1, [r3, #DDR3PHY_PIR]
-       bic     tmp1, tmp1, #DDR3PHY_PIR_DLLBYP
-       str     tmp1, [r3, #DDR3PHY_PIR]
+       /* Enable DX DLLs. */
+       ldr     tmp1, [r3, #DDR3PHY_DX0DLLCR]
+       bic     tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+       str     tmp1, [r3, #DDR3PHY_DX0DLLCR]
+
+       ldr     tmp1, [r3, #DDR3PHY_DX1DLLCR]
+       bic     tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+       str     tmp1, [r3, #DDR3PHY_DX1DLLCR]
 
        /* Enable quasi-dynamic programming. */
        mov     tmp1, #0
index f990471..f543e2a 100644 (file)
@@ -46,7 +46,7 @@ static void __init ixp4xx_of_map_io(void)
 }
 
 /*
- * We handle 4 differen SoC families. These compatible strings are enough
+ * We handle 4 different SoC families. These compatible strings are enough
  * to provide the core so that different boards can add their more detailed
  * specifics.
  */
index 926cde5..d0c2416 100644 (file)
@@ -18,8 +18,8 @@ config SOC_SP7021
        select ARM_PSCI
        select PINCTRL
        select PINCTRL_SPPCTL
-       select SERIAL_SUNPLUS
-       select SERIAL_SUNPLUS_CONSOLE
+       select SERIAL_SUNPLUS if TTY
+       select SERIAL_SUNPLUS_CONSOLE if TTY
        help
          Support for Sunplus SP7021 SoC. It is based on ARM 4-core
          Cortex-A7 with various peripherals (e.g.: I2C, SPI, SDIO,
index fb68800..712da6a 100644 (file)
@@ -346,7 +346,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
                addr = start + i * PMD_SIZE;
                domain = get_domain_name(pmd);
                if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd))
-                       note_page(st, addr, 3, pmd_val(*pmd), domain);
+                       note_page(st, addr, 4, pmd_val(*pmd), domain);
                else
                        walk_pte(st, pmd, addr, domain);
 
index a49f0b9..463fc2a 100644 (file)
@@ -300,7 +300,11 @@ static struct mem_type mem_types[] __ro_after_init = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
                             L_PTE_XN | L_PTE_RDONLY,
                .prot_l1   = PMD_TYPE_TABLE,
+#ifdef CONFIG_ARM_LPAE
+               .prot_sect = PMD_TYPE_SECT | L_PMD_SECT_RDONLY | PMD_SECT_AP2,
+#else
                .prot_sect = PMD_TYPE_SECT,
+#endif
                .domain    = DOMAIN_KERNEL,
        },
        [MT_ROM] = {
index 9fb9fff..1ce7685 100644 (file)
@@ -1887,6 +1887,8 @@ config ARM64_BTI_KERNEL
        depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
        depends on !CC_IS_GCC || GCC_VERSION >= 100100
+       # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106671
+       depends on !CC_IS_GCC
        # https://github.com/llvm/llvm-project/commit/a88c722e687e6780dcd6a58718350dc76fcc4cc9
        depends on !CC_IS_CLANG || CLANG_VERSION >= 120000
        depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
index 8d0d45d..2f27619 100644 (file)
@@ -26,7 +26,8 @@
                compatible = "arm,mhu", "arm,primecell";
                reg = <0x0 0x2b1f0000 0x0 0x1000>;
                interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                            <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
                #mbox-cells = <1>;
                clocks = <&soc_refclk100mhz>;
                clock-names = "apb_pclk";
index ba88d15..09d2b69 100644 (file)
@@ -67,7 +67,6 @@
                        port@0 {
                                reg = <0>;
                                csys2_funnel_in_port0: endpoint {
-                                       slave-mode;
                                        remote-endpoint = <&etf0_out_port>;
                                };
                        };
@@ -75,7 +74,6 @@
                        port@1 {
                                reg = <1>;
                                csys2_funnel_in_port1: endpoint {
-                                       slave-mode;
                                        remote-endpoint = <&etf1_out_port>;
                                };
                        };
index 40d34c8..b949cac 100644 (file)
@@ -25,7 +25,6 @@
 &enetc_port0 {
        phy-handle = <&slot1_sgmii>;
        phy-mode = "2500base-x";
-       managed = "in-band-status";
        status = "okay";
 };
 
index c97f4e0..32f6f2f 100644 (file)
         * CPLD_reset is RESET_SOFT in schematic
         */
        gpio-line-names =
-               "CPLD_D[1]", "CPLD_int", "CPLD_reset", "",
-               "", "CPLD_D[0]", "", "",
-               "", "", "", "CPLD_D[2]",
-               "CPLD_D[3]", "CPLD_D[4]", "CPLD_D[5]", "CPLD_D[6]",
-               "CPLD_D[7]", "", "", "",
+               "CPLD_D[6]", "CPLD_int", "CPLD_reset", "",
+               "", "CPLD_D[7]", "", "",
+               "", "", "", "CPLD_D[5]",
+               "CPLD_D[4]", "CPLD_D[3]", "CPLD_D[2]", "CPLD_D[1]",
+               "CPLD_D[0]", "", "", "",
                "", "", "", "",
                "", "", "", "KBD_intK",
                "", "", "", "";
index 286d2df..7e0aeb2 100644 (file)
@@ -5,7 +5,6 @@
 
 /dts-v1/;
 
-#include <dt-bindings/phy/phy-imx8-pcie.h>
 #include "imx8mm-tqma8mqml.dtsi"
 #include "mba8mx.dtsi"
 
index 16ee9b5..f649dfa 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright 2020-2021 TQ-Systems GmbH
  */
 
+#include <dt-bindings/phy/phy-imx8-pcie.h>
 #include "imx8mm.dtsi"
 
 / {
index 35fb929..d3ee6fc 100644 (file)
                        lan1: port@0 {
                                reg = <0>;
                                label = "lan1";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan2: port@1 {
                                reg = <1>;
                                label = "lan2";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan3: port@2 {
                                reg = <2>;
                                label = "lan3";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan4: port@3 {
                                reg = <3>;
                                label = "lan4";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
index d1b4582..3ec0c9a 100644 (file)
        };
 
        /* Fixed clock dedicated to SPI CAN controller */
-       clk20m: oscillator {
+       clk40m: oscillator {
                compatible = "fixed-clock";
                #clock-cells = <0>;
-               clock-frequency = <20000000>;
+               clock-frequency = <40000000>;
        };
 
        gpio-keys {
 
        can1: can@0 {
                compatible = "microchip,mcp251xfd";
-               clocks = <&clk20m>;
-               interrupts-extended = <&gpio1 6 IRQ_TYPE_EDGE_FALLING>;
+               clocks = <&clk40m>;
+               interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_LOW>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_can1_int>;
                reg = <0>;
                                nxp,dvs-standby-voltage = <850000>;
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-max-microvolt = <950000>;
-                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1050000>;
+                               regulator-min-microvolt = <805000>;
                                regulator-name = "On-module +VDD_ARM (BUCK2)";
                                regulator-ramp-delay = <3125>;
                        };
                        reg_vdd_dram: BUCK3 {
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-max-microvolt = <950000>;
-                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-min-microvolt = <805000>;
                                regulator-name = "On-module +VDD_GPU_VPU_DDR (BUCK3)";
                        };
 
                        reg_vdd_snvs: LDO2 {
                                regulator-always-on;
                                regulator-boot-on;
-                               regulator-max-microvolt = <900000>;
+                               regulator-max-microvolt = <800000>;
                                regulator-min-microvolt = <800000>;
                                regulator-name = "On-module +V0.8_SNVS (LDO2)";
                        };
                pinctrl-0 = <&pinctrl_gpio_9_dsi>, <&pinctrl_i2s_2_bclk_touch_reset>;
                reg = <0x4a>;
                /* Verdin I2S_2_BCLK (TOUCH_RESET#, SODIMM 42) */
-               reset-gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
                status = "disabled";
        };
 
 };
 
 &usbphynop2 {
+       power-domains = <&pgc_otg2>;
        vcc-supply = <&reg_vdd_3v3>;
 };
 
index 0c71b74..cb2836b 100644 (file)
                                                         <&clk IMX8MN_CLK_GPU_SHADER>,
                                                         <&clk IMX8MN_CLK_GPU_BUS_ROOT>,
                                                         <&clk IMX8MN_CLK_GPU_AHB>;
-                                               resets = <&src IMX8MQ_RESET_GPU_RESET>;
                                        };
 
                                        pgc_dispmix: power-domain@3 {
index a616eb3..0f13ee3 100644 (file)
@@ -70,7 +70,7 @@
 &ecspi1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ecspi1>;
-       cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+       cs-gpios = <&gpio5 17 GPIO_ACTIVE_LOW>;
        status = "disabled";
 };
 
        pinctrl-names = "default", "gpio";
        pinctrl-0 = <&pinctrl_i2c5>;
        pinctrl-1 = <&pinctrl_i2c5_gpio>;
-       scl-gpios = <&gpio5 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
-       sda-gpios = <&gpio5 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+       scl-gpios = <&gpio3 26 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+       sda-gpios = <&gpio3 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
        status = "okay";
 };
 
 
        pinctrl_ecspi1: dhcom-ecspi1-grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_ECSPI1_SCLK__ECSPI1_SCLK           0x44
-                       MX8MP_IOMUXC_ECSPI1_MOSI__ECSPI1_MOSI           0x44
-                       MX8MP_IOMUXC_ECSPI1_MISO__ECSPI1_MISO           0x44
-                       MX8MP_IOMUXC_ECSPI1_SS0__GPIO5_IO09             0x40
+                       MX8MP_IOMUXC_I2C1_SCL__ECSPI1_SCLK              0x44
+                       MX8MP_IOMUXC_I2C1_SDA__ECSPI1_MOSI              0x44
+                       MX8MP_IOMUXC_I2C2_SCL__ECSPI1_MISO              0x44
+                       MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17               0x40
                >;
        };
 
index d8ca529..0e237b2 100644 (file)
                switch-1 {
                        label = "S12";
                        linux,code = <BTN_0>;
-                       gpios = <&gpio5 26 GPIO_ACTIVE_LOW>;
+                       gpios = <&gpio5 27 GPIO_ACTIVE_LOW>;
                };
 
                switch-2 {
                        label = "S13";
                        linux,code = <BTN_1>;
-                       gpios = <&gpio5 27 GPIO_ACTIVE_LOW>;
+                       gpios = <&gpio5 26 GPIO_ACTIVE_LOW>;
                };
        };
 
 
 &pcf85063 {
        /* RTC_EVENT# is connected on MBa8MPxL */
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcf85063>;
        interrupt-parent = <&gpio4>;
        interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
 };
                fsl,pins = <MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20           0x10>; /* Power enable */
        };
 
+       pinctrl_pcf85063: pcf85063grp {
+               fsl,pins = <MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28          0x80>;
+       };
+
        /* LVDS Backlight */
        pinctrl_pwm2: pwm2grp {
                fsl,pins = <MX8MP_IOMUXC_SAI5_RXD0__PWM2_OUT            0x14>;
index 5212155..211e6a1 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_reg_can>;
                regulator-name = "can2_stby";
-               gpio = <&gpio3 19 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
+               gpio = <&gpio3 19 GPIO_ACTIVE_LOW>;
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
        };
                        lan1: port@0 {
                                reg = <0>;
                                label = "lan1";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan2: port@1 {
                                reg = <1>;
                                label = "lan2";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan3: port@2 {
                                reg = <2>;
                                label = "lan3";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan4: port@3 {
                                reg = <3>;
                                label = "lan4";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
                        lan5: port@4 {
                                reg = <4>;
                                label = "lan5";
+                               phy-mode = "internal";
                                local-mac-address = [00 00 00 00 00 00];
                        };
 
-                       port@6 {
-                               reg = <6>;
+                       port@5 {
+                               reg = <5>;
                                label = "cpu";
                                ethernet = <&fec>;
                                phy-mode = "rgmii-id";
 
        pinctrl_sai2: sai2grp {
                fsl,pins = <
-                       MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC
-                       MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00
-                       MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK
-                       MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI2_MCLK
+                       MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC   0xd6
+                       MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0xd6
+                       MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK    0xd6
+                       MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI2_MCLK      0xd6
                >;
        };
 
index c5987bd..1c74c6a 100644 (file)
                interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
                reg = <0x4a>;
                /* Verdin GPIO_2 (SODIMM 208) */
-               reset-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
                status = "disabled";
        };
 };
                pinctrl-0 = <&pinctrl_gpio_9_dsi>, <&pinctrl_i2s_2_bclk_touch_reset>;
                reg = <0x4a>;
                /* Verdin I2S_2_BCLK (TOUCH_RESET#, SODIMM 42) */
-               reset-gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
                status = "disabled";
        };
 
index 899e8e7..802ad6e 100644 (file)
                reg = <0x51>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_rtc>;
-               interrupt-names = "irq";
                interrupt-parent = <&gpio1>;
                interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
                quartz-load-femtofarads = <7000>;
index 60c1b01..bb56390 100644 (file)
                                compatible = "fsl,imx8ulp-pcc3";
                                reg = <0x292d0000 0x10000>;
                                #clock-cells = <1>;
+                               #reset-cells = <1>;
                        };
 
                        tpm5: tpm@29340000 {
                                compatible = "fsl,imx8ulp-pcc4";
                                reg = <0x29800000 0x10000>;
                                #clock-cells = <1>;
+                               #reset-cells = <1>;
                        };
 
                        lpi2c6: i2c@29840000 {
                                compatible = "fsl,imx8ulp-pcc5";
                                reg = <0x2da70000 0x10000>;
                                #clock-cells = <1>;
+                               #reset-cells = <1>;
                        };
                };
 
index 13d7f26..dac3b69 100644 (file)
                                        <&gem_noc MASTER_APPSS_PROC 0 &cnoc2 SLAVE_USB3_0 0>;
                        interconnect-names = "usb-ddr", "apps-usb";
 
+                       wakeup-source;
+
                        usb_1_dwc3: usb@a600000 {
                                compatible = "snps,dwc3";
                                reg = <0 0x0a600000 0 0xe000>;
                                phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
                                phy-names = "usb2-phy", "usb3-phy";
                                maximum-speed = "super-speed";
-                               wakeup-source;
                        };
                };
 
index 84dc92d..4c404e2 100644 (file)
 };
 
 &remoteproc_adsp {
-       firmware-name = "qcom/sc8280xp/qcadsp8280.mbn";
+       firmware-name = "qcom/sc8280xp/LENOVO/21BX/qcadsp8280.mbn";
 
        status = "okay";
 };
 
 &remoteproc_nsp0 {
-       firmware-name = "qcom/sc8280xp/qccdsp8280.mbn";
+       firmware-name = "qcom/sc8280xp/LENOVO/21BX/qccdsp8280.mbn";
 
        status = "okay";
 };
index 7d509ec..916f12b 100644 (file)
                                        compute-cb@1 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <1>;
-                                               iommus = <&apps_smmu 0x1401 0x2040>,
-                                                        <&apps_smmu 0x1421 0x0>,
-                                                        <&apps_smmu 0x2001 0x420>,
-                                                        <&apps_smmu 0x2041 0x0>;
+                                               iommus = <&apps_smmu 0x1001 0x0460>;
                                        };
 
                                        compute-cb@2 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <2>;
-                                               iommus = <&apps_smmu 0x2 0x3440>,
-                                                        <&apps_smmu 0x22 0x3400>;
+                                               iommus = <&apps_smmu 0x1002 0x0460>;
                                        };
 
                                        compute-cb@3 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <3>;
-                                               iommus = <&apps_smmu 0x3 0x3440>,
-                                                        <&apps_smmu 0x1423 0x0>,
-                                                        <&apps_smmu 0x2023 0x0>;
+                                               iommus = <&apps_smmu 0x1003 0x0460>;
                                        };
 
                                        compute-cb@4 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <4>;
-                                               iommus = <&apps_smmu 0x4 0x3440>,
-                                                        <&apps_smmu 0x24 0x3400>;
+                                               iommus = <&apps_smmu 0x1004 0x0460>;
                                        };
 
                                        compute-cb@5 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <5>;
-                                               iommus = <&apps_smmu 0x5 0x3440>,
-                                                        <&apps_smmu 0x25 0x3400>;
+                                               iommus = <&apps_smmu 0x1005 0x0460>;
                                        };
 
                                        compute-cb@6 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <6>;
-                                               iommus = <&apps_smmu 0x6 0x3460>;
+                                               iommus = <&apps_smmu 0x1006 0x0460>;
                                        };
 
                                        compute-cb@7 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <7>;
-                                               iommus = <&apps_smmu 0x7 0x3460>;
+                                               iommus = <&apps_smmu 0x1007 0x0460>;
                                        };
 
                                        compute-cb@8 {
                                                compatible = "qcom,fastrpc-compute-cb";
                                                reg = <8>;
-                                               iommus = <&apps_smmu 0x8 0x3460>;
+                                               iommus = <&apps_smmu 0x1008 0x0460>;
                                        };
 
                                        /* note: secure cb9 in downstream */
index e72a044..d9b08df 100644 (file)
 
                ufs_mem_phy: phy@1d87000 {
                        compatible = "qcom,sm8350-qmp-ufs-phy";
-                       reg = <0 0x01d87000 0 0xe10>;
+                       reg = <0 0x01d87000 0 0x1c4>;
                        #address-cells = <2>;
                        #size-cells = <2>;
                        ranges;
index 7cbb0de..1c15726 100644 (file)
@@ -85,7 +85,7 @@
                                     "renesas,rcar-gen4-hscif",
                                     "renesas,hscif";
                        reg = <0 0xe6540000 0 96>;
-                       interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 514>,
                                 <&cpg CPG_CORE R8A779G0_CLK_S0D3_PER>,
                                 <&scif_clk>;
index 7249871..5eecbef 100644 (file)
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
  * Copyright (c) 2020 Engicam srl
- * Copyright (c) 2020 Amarula Solutons
- * Copyright (c) 2020 Amarula Solutons(India)
+ * Copyright (c) 2020 Amarula Solutions
+ * Copyright (c) 2020 Amarula Solutions(India)
  */
 
 #include <dt-bindings/gpio/gpio.h>
index 31ebb4e..0f9cc04 100644 (file)
@@ -88,3 +88,8 @@
                };
        };
 };
+
+&wlan_host_wake_l {
+       /* Kevin has an external pull up, but Bob does not. */
+       rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+};
index cd07464..ee6095b 100644 (file)
 &edp {
        status = "okay";
 
+       /*
+        * eDP PHY/clk don't sync reliably at anything other than 24 MHz. Only
+        * set this here, because rk3399-gru.dtsi ensures we can generate this
+        * off GPLL=600MHz, whereas some other RK3399 boards may not.
+        */
+       assigned-clocks = <&cru PCLK_EDP>;
+       assigned-clock-rates = <24000000>;
+
        ports {
                edp_out: port@1 {
                        reg = <1>;
@@ -578,6 +586,7 @@ ap_i2c_tp: &i2c5 {
        };
 
        wlan_host_wake_l: wlan-host-wake-l {
+               /* Kevin has an external pull up, but Bob does not */
                rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
        };
 };
index b1ac3a8..aa3e21b 100644 (file)
@@ -62,7 +62,6 @@
        vcc5v0_host: vcc5v0-host-regulator {
                compatible = "regulator-fixed";
                gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_LOW>;
-               enable-active-low;
                pinctrl-names = "default";
                pinctrl-0 = <&vcc5v0_host_en>;
                regulator-name = "vcc5v0_host";
index d943559..a05460b 100644 (file)
 
        vcc3v3_sd: vcc3v3_sd {
                compatible = "regulator-fixed";
-               enable-active-low;
                gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
                pinctrl-names = "default";
                pinctrl-0 = <&vcc_sd_h>;
index 02d5f5a..528bb4e 100644 (file)
        disable-wp;
        pinctrl-names = "default";
        pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
-       sd-uhs-sdr104;
+       sd-uhs-sdr50;
        vmmc-supply = <&vcc3v3_sd>;
        vqmmc-supply = <&vccio_sd>;
        status = "okay";
index 5e34bd0..93d383b 100644 (file)
 };
 
 &usb_host0_xhci {
-       extcon = <&usb2phy0>;
+       dr_mode = "host";
        status = "okay";
 };
 
index 6ff89ff..6747925 100644 (file)
 };
 
 &usb2phy0_otg {
-       vbus-supply = <&vcc5v0_usb_otg>;
+       phy-supply = <&vcc5v0_usb_otg>;
        status = "okay";
 };
 
index 6b5093a..b2e040d 100644 (file)
 };
 
 &usb2phy0_otg {
-       vbus-supply = <&vcc5v0_usb_otg>;
+       phy-supply = <&vcc5v0_usb_otg>;
        status = "okay";
 };
 
index d5b2d2d..5b16764 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_ARCH_KEEMBAY=y
 CONFIG_ARCH_MEDIATEK=y
 CONFIG_ARCH_MESON=y
 CONFIG_ARCH_MVEBU=y
+CONFIG_ARCH_NXP=y
 CONFIG_ARCH_MXC=y
 CONFIG_ARCH_NPCM=y
 CONFIG_ARCH_QCOM=y
index 02e59fa..32d14f4 100644 (file)
 #define EARLY_KASLR    (0)
 #endif
 
-#define EARLY_ENTRIES(vstart, vend, shift) \
-       ((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
+#define EARLY_ENTRIES(vstart, vend, shift, add) \
+       ((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + add)
 
-#define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
+#define EARLY_PGDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT, add))
 
 #if SWAPPER_PGTABLE_LEVELS > 3
-#define EARLY_PUDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT))
+#define EARLY_PUDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT, add))
 #else
-#define EARLY_PUDS(vstart, vend) (0)
+#define EARLY_PUDS(vstart, vend, add) (0)
 #endif
 
 #if SWAPPER_PGTABLE_LEVELS > 2
-#define EARLY_PMDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT))
+#define EARLY_PMDS(vstart, vend, add) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT, add))
 #else
-#define EARLY_PMDS(vstart, vend) (0)
+#define EARLY_PMDS(vstart, vend, add) (0)
 #endif
 
-#define EARLY_PAGES(vstart, vend) ( 1                  /* PGDIR page */                                \
-                       + EARLY_PGDS((vstart), (vend))  /* each PGDIR needs a next level page table */  \
-                       + EARLY_PUDS((vstart), (vend))  /* each PUD needs a next level page table */    \
-                       + EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */
-#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))
+#define EARLY_PAGES(vstart, vend, add) ( 1                     /* PGDIR page */                                \
+                       + EARLY_PGDS((vstart), (vend), add)     /* each PGDIR needs a next level page table */  \
+                       + EARLY_PUDS((vstart), (vend), add)     /* each PUD needs a next level page table */    \
+                       + EARLY_PMDS((vstart), (vend), add))    /* each PMD needs a next level page table */
+#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end, EARLY_KASLR))
 
 /* the initial ID map may need two extra pages if it needs to be extended */
 #if VA_BITS < 48
@@ -93,7 +93,7 @@
 #else
 #define INIT_IDMAP_DIR_SIZE    (INIT_IDMAP_DIR_PAGES * PAGE_SIZE)
 #endif
-#define INIT_IDMAP_DIR_PAGES   EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE)
+#define INIT_IDMAP_DIR_PAGES   EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE, 1)
 
 /* Initial memory map size */
 #if ARM64_KERNEL_USES_PMD_MAPS
index cefe6a7..814b658 100644 (file)
@@ -371,7 +371,9 @@ SYM_FUNC_END(create_idmap)
 SYM_FUNC_START_LOCAL(create_kernel_mapping)
        adrp    x0, init_pg_dir
        mov_q   x5, KIMAGE_VADDR                // compile time __va(_text)
+#ifdef CONFIG_RELOCATABLE
        add     x5, x5, x23                     // add KASLR displacement
+#endif
        adrp    x6, _end                        // runtime __pa(_end)
        adrp    x3, _text                       // runtime __pa(_text)
        sub     x6, x6, x3                      // _end - _text
index 8899512..a11a6e1 100644 (file)
@@ -47,7 +47,7 @@ static int prepare_elf_headers(void **addr, unsigned long *sz)
        u64 i;
        phys_addr_t start, end;
 
-       nr_ranges = 1; /* for exclusion of crashkernel region */
+       nr_ranges = 2; /* for exclusion of crashkernel region */
        for_each_mem_range(i, &start, &end)
                nr_ranges++;
 
index eb7c08d..041d2ae 100644 (file)
@@ -1084,7 +1084,6 @@ static int za_set(struct task_struct *target,
        if (!target->thread.sve_state) {
                sve_alloc(target, false);
                if (!target->thread.sve_state) {
-                       clear_thread_flag(TIF_SME);
                        ret = -ENOMEM;
                        goto out;
                }
@@ -1094,7 +1093,6 @@ static int za_set(struct task_struct *target,
        sme_alloc(target);
        if (!target->thread.za_state) {
                ret = -ENOMEM;
-               clear_tsk_thread_flag(target, TIF_SME);
                goto out;
        }
 
index 617f78a..97c9de5 100644 (file)
@@ -101,6 +101,9 @@ SYM_FUNC_END(__cpu_suspend_enter)
 SYM_CODE_START(cpu_resume)
        bl      init_kernel_el
        bl      finalise_el2
+#if VA_BITS > 48
+       ldr_l   x0, vabits_actual
+#endif
        bl      __cpu_setup
        /* enable the MMU early - so we can access sleep_save_stash by va */
        adrp    x1, swapper_pg_dir
index ad2bfc7..44ebf5b 100644 (file)
@@ -237,7 +237,7 @@ static void amu_fie_setup(const struct cpumask *cpus)
        for_each_cpu(cpu, cpus) {
                if (!freq_counters_valid(cpu) ||
                    freq_inv_set_max_ratio(cpu,
-                                          cpufreq_get_hw_max_freq(cpu) * 1000,
+                                          cpufreq_get_hw_max_freq(cpu) * 1000ULL,
                                           arch_timer_get_rate()))
                        return;
        }
index 2ff0ef6..917086b 100644 (file)
@@ -2114,7 +2114,7 @@ static int finalize_hyp_mode(void)
         * at, which would end badly once inaccessible.
         */
        kmemleak_free_part(__hyp_bss_start, __hyp_bss_end - __hyp_bss_start);
-       kmemleak_free_part(__va(hyp_mem_base), hyp_mem_size);
+       kmemleak_free_part_phys(hyp_mem_base, hyp_mem_size);
        return pkvm_drop_host_privileges();
 }
 
index e7ad445..eb48930 100644 (file)
@@ -331,12 +331,6 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
        }
        BUG_ON(p4d_bad(p4d));
 
-       /*
-        * No need for locking during early boot. And it doesn't work as
-        * expected with KASLR enabled.
-        */
-       if (system_state != SYSTEM_BOOTING)
-               mutex_lock(&fixmap_lock);
        pudp = pud_set_fixmap_offset(p4dp, addr);
        do {
                pud_t old_pud = READ_ONCE(*pudp);
@@ -368,15 +362,13 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
        } while (pudp++, addr = next, addr != end);
 
        pud_clear_fixmap();
-       if (system_state != SYSTEM_BOOTING)
-               mutex_unlock(&fixmap_lock);
 }
 
-static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
-                                unsigned long virt, phys_addr_t size,
-                                pgprot_t prot,
-                                phys_addr_t (*pgtable_alloc)(int),
-                                int flags)
+static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
+                                       unsigned long virt, phys_addr_t size,
+                                       pgprot_t prot,
+                                       phys_addr_t (*pgtable_alloc)(int),
+                                       int flags)
 {
        unsigned long addr, end, next;
        pgd_t *pgdp = pgd_offset_pgd(pgdir, virt);
@@ -400,8 +392,20 @@ static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
        } while (pgdp++, addr = next, addr != end);
 }
 
+static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
+                                unsigned long virt, phys_addr_t size,
+                                pgprot_t prot,
+                                phys_addr_t (*pgtable_alloc)(int),
+                                int flags)
+{
+       mutex_lock(&fixmap_lock);
+       __create_pgd_mapping_locked(pgdir, phys, virt, size, prot,
+                                   pgtable_alloc, flags);
+       mutex_unlock(&fixmap_lock);
+}
+
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-extern __alias(__create_pgd_mapping)
+extern __alias(__create_pgd_mapping_locked)
 void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt,
                             phys_addr_t size, pgprot_t prot,
                             phys_addr_t (*pgtable_alloc)(int), int flags);
index 26aeb14..551dd99 100644 (file)
@@ -10,7 +10,6 @@ config LOONGARCH
        select ARCH_ENABLE_MEMORY_HOTPLUG
        select ARCH_ENABLE_MEMORY_HOTREMOVE
        select ARCH_HAS_ACPI_TABLE_UPGRADE      if ACPI
-       select ARCH_HAS_PHYS_TO_DMA
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_INLINE_READ_LOCK if !PREEMPTION
@@ -39,6 +38,7 @@ config LOONGARCH
        select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPTION
        select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
        select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
+       select ARCH_KEEP_MEMBLOCK
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select ARCH_SPARSEMEM_ENABLE
@@ -51,6 +51,7 @@ config LOONGARCH
        select ARCH_USE_CMPXCHG_LOCKREF
        select ARCH_USE_QUEUED_RWLOCKS
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
+       select ARCH_WANT_LD_ORPHAN_WARN
        select ARCH_WANTS_NO_INSTR
        select BUILDTIME_TABLE_SORT
        select COMMON_CLK
index c510821..17162f4 100644 (file)
@@ -15,7 +15,7 @@ extern int acpi_pci_disabled;
 extern int acpi_noirq;
 
 #define acpi_os_ioremap acpi_os_ioremap
-void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
+void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
 
 static inline void disable_acpi(void)
 {
index 6e8f697..00db93e 100644 (file)
@@ -14,8 +14,6 @@
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 
-extern const struct plat_smp_ops loongson3_smp_ops;
-
 #define LOONGSON_REG(x) \
        (*(volatile u32 *)((char *)TO_UNCACHE(LOONGSON_REG_BASE) + (x)))
 
index f1c9286..3353984 100644 (file)
@@ -48,7 +48,7 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
        early_memunmap(map, size);
 }
 
-void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
+void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
 {
        if (!memblock_is_memory(phys))
                return ioremap(phys, size);
index 8c9b531..7a9c6a9 100644 (file)
@@ -2,39 +2,29 @@
 /*
  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  */
-#include <linux/init.h>
+#include <linux/acpi.h>
 #include <linux/dma-direct.h>
-#include <linux/dma-mapping.h>
-#include <linux/dma-map-ops.h>
-#include <linux/swiotlb.h>
 
-#include <asm/bootinfo.h>
-#include <asm/dma.h>
-#include <asm/loongson.h>
-
-/*
- * We extract 4bit node id (bit 44~47) from Loongson-3's
- * 48bit physical address space and embed it into 40bit.
- */
-
-static int node_id_offset;
-
-dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
-{
-       long nid = (paddr >> 44) & 0xf;
-
-       return ((nid << 44) ^ paddr) | (nid << node_id_offset);
-}
-
-phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+void acpi_arch_dma_setup(struct device *dev)
 {
-       long nid = (daddr >> node_id_offset) & 0xf;
+       int ret;
+       u64 mask, end = 0;
+       const struct bus_dma_region *map = NULL;
+
+       ret = acpi_dma_get_range(dev, &map);
+       if (!ret && map) {
+               const struct bus_dma_region *r = map;
+
+               for (end = 0; r->size; r++) {
+                       if (r->dma_start + r->size - 1 > end)
+                               end = r->dma_start + r->size - 1;
+               }
+
+               mask = DMA_BIT_MASK(ilog2(end) + 1);
+               dev->bus_dma_limit = end;
+               dev->dma_range_map = map;
+               dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
+               *dev->dma_mask = min(*dev->dma_mask, mask);
+       }
 
-       return ((nid << node_id_offset) ^ daddr) | (nid << 44);
-}
-
-void __init plat_swiotlb_setup(void)
-{
-       swiotlb_init(true, SWIOTLB_VERBOSE);
-       node_id_offset = ((readl(LS7A_DMA_CFG) & LS7A_DMA_NODE_MASK) >> LS7A_DMA_NODE_SHF) + 36;
 }
index c60eb66..3318643 100644 (file)
@@ -14,6 +14,8 @@
 
        __REF
 
+       .align 12
+
 SYM_CODE_START(kernel_entry)                   # kernel entry point
 
        /* Config direct window and set PG */
index 8f5c2f9..d97c69d 100644 (file)
@@ -247,7 +247,7 @@ static void __init arch_mem_init(char **cmdline_p)
        sparse_init();
        memblock_set_bottom_up(true);
 
-       plat_swiotlb_setup();
+       swiotlb_init(true, SWIOTLB_VERBOSE);
 
        dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
 
index 7f4889d..8f5b798 100644 (file)
@@ -529,11 +529,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
        signal_setup_done(ret, ksig, 0);
 }
 
-void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
+void arch_do_signal_or_restart(struct pt_regs *regs)
 {
        struct ksignal ksig;
 
-       if (has_signal && get_signal(&ksig)) {
+       if (get_signal(&ksig)) {
                /* Whee!  Actually deliver the signal.  */
                handle_signal(&ksig, regs);
                return;
index aa1c95a..5010e95 100644 (file)
@@ -461,11 +461,9 @@ asmlinkage void noinstr do_watch(struct pt_regs *regs)
 
 asmlinkage void noinstr do_ri(struct pt_regs *regs)
 {
-       int status = -1;
+       int status = SIGILL;
        unsigned int opcode = 0;
        unsigned int __user *era = (unsigned int __user *)exception_era(regs);
-       unsigned long old_era = regs->csr_era;
-       unsigned long old_ra = regs->regs[1];
        irqentry_state_t state = irqentry_enter(regs);
 
        local_irq_enable();
@@ -477,21 +475,12 @@ asmlinkage void noinstr do_ri(struct pt_regs *regs)
 
        die_if_kernel("Reserved instruction in kernel code", regs);
 
-       compute_return_era(regs);
-
        if (unlikely(get_user(opcode, era) < 0)) {
                status = SIGSEGV;
                current->thread.error_code = 1;
        }
 
-       if (status < 0)
-               status = SIGILL;
-
-       if (unlikely(status > 0)) {
-               regs->csr_era = old_era;                /* Undo skip-over.  */
-               regs->regs[1] = old_ra;
-               force_sig(status);
-       }
+       force_sig(status);
 
 out:
        local_irq_disable();
index 69c76f2..f4831df 100644 (file)
@@ -77,6 +77,8 @@ SECTIONS
        PERCPU_SECTION(1 << CONFIG_L1_CACHE_SHIFT)
 #endif
 
+       .rela.dyn : ALIGN(8) { *(.rela.dyn) *(.rela*) }
+
        .init.bss : {
                *(.init.bss)
        }
index cda2c6b..c2cc7ce 100644 (file)
@@ -18,11 +18,11 @@ void dump_tlb_regs(void)
 {
        const int field = 2 * sizeof(unsigned long);
 
-       pr_info("Index    : %0x\n", read_csr_tlbidx());
-       pr_info("PageSize : %0x\n", read_csr_pagesize());
-       pr_info("EntryHi  : %0*llx\n", field, read_csr_entryhi());
-       pr_info("EntryLo0 : %0*llx\n", field, read_csr_entrylo0());
-       pr_info("EntryLo1 : %0*llx\n", field, read_csr_entrylo1());
+       pr_info("Index    : 0x%0x\n", read_csr_tlbidx());
+       pr_info("PageSize : 0x%0x\n", read_csr_pagesize());
+       pr_info("EntryHi  : 0x%0*llx\n", field, read_csr_entryhi());
+       pr_info("EntryLo0 : 0x%0*llx\n", field, read_csr_entrylo0());
+       pr_info("EntryLo1 : 0x%0*llx\n", field, read_csr_entrylo1());
 }
 
 static void dump_tlb(int first, int last)
@@ -33,8 +33,8 @@ static void dump_tlb(int first, int last)
        unsigned int s_index, s_asid;
        unsigned int pagesize, c0, c1, i;
        unsigned long asidmask = cpu_asid_mask(&current_cpu_data);
-       int pwidth = 11;
-       int vwidth = 11;
+       int pwidth = 16;
+       int vwidth = 16;
        int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
 
        s_entryhi = read_csr_entryhi();
@@ -64,22 +64,22 @@ static void dump_tlb(int first, int last)
                /*
                 * Only print entries in use
                 */
-               pr_info("Index: %2d pgsize=%x ", i, (1 << pagesize));
+               pr_info("Index: %4d pgsize=0x%x ", i, (1 << pagesize));
 
                c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
                c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
 
-               pr_cont("va=%0*lx asid=%0*lx",
+               pr_cont("va=0x%0*lx asid=0x%0*lx",
                        vwidth, (entryhi & ~0x1fffUL), asidwidth, asid & asidmask);
 
                /* NR/NX are in awkward places, so mask them off separately */
                pa = entrylo0 & ~(ENTRYLO_NR | ENTRYLO_NX);
                pa = pa & PAGE_MASK;
                pr_cont("\n\t[");
-               pr_cont("ri=%d xi=%d ",
+               pr_cont("nr=%d nx=%d ",
                        (entrylo0 & ENTRYLO_NR) ? 1 : 0,
                        (entrylo0 & ENTRYLO_NX) ? 1 : 0);
-               pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d plv=%lld] [",
+               pr_cont("pa=0x%0*llx c=%d d=%d v=%d g=%d plv=%lld] [",
                        pwidth, pa, c0,
                        (entrylo0 & ENTRYLO_D) ? 1 : 0,
                        (entrylo0 & ENTRYLO_V) ? 1 : 0,
@@ -88,10 +88,10 @@ static void dump_tlb(int first, int last)
                /* NR/NX are in awkward places, so mask them off separately */
                pa = entrylo1 & ~(ENTRYLO_NR | ENTRYLO_NX);
                pa = pa & PAGE_MASK;
-               pr_cont("ri=%d xi=%d ",
+               pr_cont("nr=%d nx=%d ",
                        (entrylo1 & ENTRYLO_NR) ? 1 : 0,
                        (entrylo1 & ENTRYLO_NX) ? 1 : 0);
-               pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d plv=%lld]\n",
+               pr_cont("pa=0x%0*llx c=%d d=%d v=%d g=%d plv=%lld]\n",
                        pwidth, pa, c1,
                        (entrylo1 & ENTRYLO_D) ? 1 : 0,
                        (entrylo1 & ENTRYLO_V) ? 1 : 0,
index 7094a68..0532ed5 100644 (file)
@@ -131,18 +131,6 @@ int arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params)
        return ret;
 }
 
-#ifdef CONFIG_NUMA
-int memory_add_physaddr_to_nid(u64 start)
-{
-       int nid;
-
-       nid = pa_to_nid(start);
-       return nid;
-}
-EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
-#endif
-
-#ifdef CONFIG_MEMORY_HOTREMOVE
 void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
@@ -154,6 +142,13 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
                page += vmem_altmap_offset(altmap);
        __remove_pages(start_pfn, nr_pages, altmap);
 }
+
+#ifdef CONFIG_NUMA
+int memory_add_physaddr_to_nid(u64 start)
+{
+       return pa_to_nid(start);
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
 #endif
 #endif
 
index b06faf6..7bff881 100644 (file)
@@ -87,7 +87,7 @@ config MMU_SUN3
 
 config KEXEC
        bool "kexec system call"
-       depends on M68KCLASSIC
+       depends on M68KCLASSIC && MMU
        select KEXEC_CORE
        help
          kexec is a system call that implements the ability to shutdown your
index a6a886a..e2038d9 100644 (file)
@@ -84,7 +84,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -573,9 +572,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -594,6 +593,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index bffd24c..ddd2012 100644 (file)
@@ -80,7 +80,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -530,9 +529,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -551,6 +550,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 0013425..d9f7837 100644 (file)
@@ -87,7 +87,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -550,9 +549,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -571,6 +570,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 42d9696..68957c6 100644 (file)
@@ -77,7 +77,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -522,9 +521,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -543,6 +542,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 97d6d9a..825c6a0 100644 (file)
@@ -79,7 +79,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -532,9 +531,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -553,6 +552,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 8cbfc1c..17f64c5 100644 (file)
@@ -78,7 +78,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -552,9 +551,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -573,6 +572,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 9f45fe6..f5f4c57 100644 (file)
@@ -98,7 +98,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -638,9 +637,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -659,6 +658,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 4736cfa..b4a0bbe 100644 (file)
@@ -76,7 +76,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -521,9 +520,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -542,6 +541,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 638cd38..c6a6d59 100644 (file)
@@ -77,7 +77,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -522,9 +521,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -543,6 +542,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index ec8b6bb..49c9c89 100644 (file)
@@ -78,7 +78,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -539,9 +538,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -560,6 +559,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 7d8dc57..9b44eeb 100644 (file)
@@ -74,7 +74,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -521,9 +520,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -542,6 +541,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index 96290ae..d2ffb0a 100644 (file)
@@ -74,7 +74,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_ZONES=y
-# CONFIG_NF_CONNTRACK_PROCFS is not set
 # CONFIG_NF_CT_PROTO_DCCP is not set
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -520,9 +519,9 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_BLAKE2S=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
@@ -541,6 +540,7 @@ CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
index b091ee9..7dbcd7b 100644 (file)
 #define BI_VIRT_VIRTIO_BASE    0x8004
 #define BI_VIRT_CTRL_BASE      0x8005
 
-/*
- * A random seed used to initialize the RNG. Record format:
- *
- *   - length       [ 2 bytes, 16-bit big endian ]
- *   - seed data    [ `length` bytes, padded to preserve 2-byte alignment ]
- */
-#define BI_VIRT_RNG_SEED       0x8006
+/* No longer used -- replaced with BI_RNG_SEED -- but don't reuse this index:
+ * #define BI_VIRT_RNG_SEED    0x8006 */
 
 #define VIRT_BOOTI_VERSION     MK_BI_VERSION(2, 0)
 
index 95ecf3a..024e87d 100644 (file)
@@ -64,6 +64,13 @@ struct mem_info {
                                        /* (struct mem_info) */
 #define BI_COMMAND_LINE                0x0007  /* kernel command line parameters */
                                        /* (string) */
+/*
+ * A random seed used to initialize the RNG. Record format:
+ *
+ *   - length       [ 2 bytes, 16-bit big endian ]
+ *   - seed data    [ `length` bytes, padded to preserve 4-byte struct alignment ]
+ */
+#define BI_RNG_SEED            0x0008
 
 
     /*
index e62fa8f..3a2bb2e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/nvram.h>
 #include <linux/initrd.h>
+#include <linux/random.h>
 
 #include <asm/bootinfo.h>
 #include <asm/byteorder.h>
@@ -109,10 +110,9 @@ extern void paging_init(void);
 
 static void __init m68k_parse_bootinfo(const struct bi_record *record)
 {
+       const struct bi_record *first_record = record;
        uint16_t tag;
 
-       save_bootinfo(record);
-
        while ((tag = be16_to_cpu(record->tag)) != BI_LAST) {
                int unknown = 0;
                const void *data = record->data;
@@ -148,10 +148,21 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
                        break;
 
                case BI_COMMAND_LINE:
-                       strlcpy(m68k_command_line, data,
+                       strscpy(m68k_command_line, data,
                                sizeof(m68k_command_line));
                        break;
 
+               case BI_RNG_SEED: {
+                       u16 len = be16_to_cpup(data);
+                       add_bootloader_randomness(data + 2, len);
+                       /*
+                        * Zero the data to preserve forward secrecy, and zero the
+                        * length to prevent kexec from using it.
+                        */
+                       memzero_explicit((void *)data, len + 2);
+                       break;
+               }
+
                default:
                        if (MACH_IS_AMIGA)
                                unknown = amiga_parse_bootinfo(record);
@@ -182,6 +193,8 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
                record = (struct bi_record *)((unsigned long)record + size);
        }
 
+       save_bootinfo(first_record);
+
        m68k_realnum_memory = m68k_num_memory;
 #ifdef CONFIG_SINGLE_MEMORY_CHUNK
        if (m68k_num_memory > 1) {
index 4ab2294..632ba20 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <linux/reboot.h>
 #include <linux/serial_core.h>
-#include <linux/random.h>
 #include <clocksource/timer-goldfish.h>
 
 #include <asm/bootinfo.h>
@@ -93,16 +92,6 @@ int __init virt_parse_bootinfo(const struct bi_record *record)
                data += 4;
                virt_bi_data.virtio.irq = be32_to_cpup(data);
                break;
-       case BI_VIRT_RNG_SEED: {
-               u16 len = be16_to_cpup(data);
-               add_bootloader_randomness(data + 2, len);
-               /*
-                * Zero the data to preserve forward secrecy, and zero the
-                * length to prevent kexec from using it.
-                */
-               memzero_explicit((void *)data, len + 2);
-               break;
-       }
        default:
                unknown = 1;
                break;
index ec21f89..25dd4c5 100644 (file)
@@ -2669,7 +2669,6 @@ config ARCH_FLATMEM_ENABLE
 
 config ARCH_SPARSEMEM_ENABLE
        bool
-       select SPARSEMEM_STATIC if !SGI_IP27
 
 config NUMA
        bool "NUMA Support"
index ab203e6..a9bea41 100644 (file)
@@ -86,7 +86,7 @@ static __init void prom_init_mem(void)
                        pr_debug("Assume 128MB RAM\n");
                        break;
                }
-               if (!memcmp(prom_init, prom_init + mem, 32))
+               if (!memcmp((void *)prom_init, (void *)prom_init + mem, 32))
                        break;
        }
        lowmem = mem;
@@ -159,7 +159,7 @@ void __init bcm47xx_prom_highmem_init(void)
 
        off = EXTVBASE + __pa(off);
        for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
-               if (!memcmp(prom_init, (void *)(off + extmem), 16))
+               if (!memcmp((void *)prom_init, (void *)(off + extmem), 16))
                        break;
        }
        extmem -= lowmem;
index c3ce49e..8926417 100644 (file)
                        interrupts = <2>, <3>;
                };
 
-               wdt: watchdog@1000009c {
-                       compatible = "brcm,bcm7038-wdt";
-                       reg = <0x1000009c 0xc>;
+               timer-mfd@10000080 {
+                       compatible = "brcm,bcm7038-twd", "simple-mfd", "syscon";
+                       reg = <0x10000080 0x30>;
+                       ranges = <0x0 0x10000080 0x30>;
 
-                       clocks = <&periph_osc>;
-                       clock-names = "refclk";
+                       wdt: watchdog@1c {
+                               compatible = "brcm,bcm7038-wdt";
+                               reg = <0x1c 0xc>;
 
-                       timeout-sec = <30>;
+                               clocks = <&periph_osc>;
+                               clock-names = "refclk";
+
+                               timeout-sec = <30>;
+                       };
                };
 
                uart0: serial@10000180 {
index f5dfc06..ae6e3e2 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_DT_EASY50712)     += easy50712.dtb
+dtb-$(CONFIG_DT_EASY50712)     += danube_easy50712.dtb
 
 obj-$(CONFIG_BUILTIN_DTB)      += $(addsuffix .o, $(dtb-y))
index bf13e35..aa7bbf8 100644 (file)
@@ -57,14 +57,11 @@ EXPORT_SYMBOL_GPL(__cvmx_cmd_queue_state_ptr);
 static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
 {
        char *alloc_name = "cvmx_cmd_queues";
-#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
        extern uint64_t octeon_reserve32_memory;
-#endif
 
        if (likely(__cvmx_cmd_queue_state_ptr))
                return CVMX_CMD_QUEUE_SUCCESS;
 
-#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
        if (octeon_reserve32_memory)
                __cvmx_cmd_queue_state_ptr =
                    cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr),
@@ -73,7 +70,6 @@ static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
                                                   (CONFIG_CAVIUM_RESERVE32 <<
                                                    20) - 1, 128, alloc_name);
        else
-#endif
                __cvmx_cmd_queue_state_ptr =
                    cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr),
                                            128,
index 6a46945..dc05262 100644 (file)
@@ -28,7 +28,7 @@ struct latency_info {
 static struct latency_info li;
 static struct dentry *dir;
 
-static int show_latency(struct seq_file *m, void *v)
+static int oct_ilm_show(struct seq_file *m, void *v)
 {
        u64 cpuclk, avg, max, min;
        struct latency_info curr_li = li;
@@ -43,18 +43,7 @@ static int show_latency(struct seq_file *m, void *v)
                   curr_li.interrupt_cnt, avg, max, min);
        return 0;
 }
-
-static int oct_ilm_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, show_latency, NULL);
-}
-
-static const struct file_operations oct_ilm_ops = {
-       .open = oct_ilm_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(oct_ilm);
 
 static int reset_statistics(void *data, u64 value)
 {
@@ -67,7 +56,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(reset_statistics_ops, NULL, reset_statistics, "%llu\n")
 static void init_debugfs(void)
 {
        dir = debugfs_create_dir("oct_ilm", 0);
-       debugfs_create_file("statistics", 0222, dir, NULL, &oct_ilm_ops);
+       debugfs_create_file("statistics", 0222, dir, NULL, &oct_ilm_fops);
        debugfs_create_file("reset", 0222, dir, NULL, &reset_statistics_ops);
 }
 
index 9cb9ed4..fd8043f 100644 (file)
@@ -127,6 +127,16 @@ static void octeon_irq_free_cd(struct irq_domain *d, unsigned int irq)
 static int octeon_irq_force_ciu_mapping(struct irq_domain *domain,
                                        int irq, int line, int bit)
 {
+       struct device_node *of_node;
+       int ret;
+
+       of_node = irq_domain_get_of_node(domain);
+       if (!of_node)
+               return -EINVAL;
+       ret = irq_alloc_desc_at(irq, of_node_to_nid(of_node));
+       if (ret < 0)
+               return ret;
+
        return irq_domain_associate(domain, irq, line << 6 | bit);
 }
 
index cbd8320..a71727f 100644 (file)
@@ -284,10 +284,8 @@ void octeon_crash_smp_send_stop(void)
 
 #endif /* CONFIG_KEXEC */
 
-#ifdef CONFIG_CAVIUM_RESERVE32
 uint64_t octeon_reserve32_memory;
 EXPORT_SYMBOL(octeon_reserve32_memory);
-#endif
 
 #ifdef CONFIG_KEXEC
 /* crashkernel cmdline parameter is parsed _after_ memory setup
@@ -532,7 +530,7 @@ void octeon_user_io_init(void)
        /* Get the current settings for CP0_CVMMEMCTL_REG */
        cvmmemctl.u64 = read_c0_cvmmemctl();
        /* R/W If set, marked write-buffer entries time out the same
-        * as as other entries; if clear, marked write-buffer entries
+        * as other entries; if clear, marked write-buffer entries
         * use the maximum timeout. */
        cvmmemctl.s.dismarkwblongto = 1;
        /* R/W If set, a merged store does not clear the write-buffer
@@ -666,9 +664,6 @@ void __init prom_init(void)
        int i;
        u64 t;
        int argc;
-#ifdef CONFIG_CAVIUM_RESERVE32
-       int64_t addr = -1;
-#endif
        /*
         * The bootloader passes a pointer to the boot descriptor in
         * $a3, this is available as fw_arg3.
@@ -783,7 +778,7 @@ void __init prom_init(void)
                cvmx_write_csr(CVMX_LED_UDD_DATX(1), 0);
                cvmx_write_csr(CVMX_LED_EN, 1);
        }
-#ifdef CONFIG_CAVIUM_RESERVE32
+
        /*
         * We need to temporarily allocate all memory in the reserve32
         * region. This makes sure the kernel doesn't allocate this
@@ -794,14 +789,16 @@ void __init prom_init(void)
         * Allocate memory for RESERVED32 aligned on 2MB boundary. This
         * is in case we later use hugetlb entries with it.
         */
-       addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
-                                               0, 0, 2 << 20,
-                                               "CAVIUM_RESERVE32", 0);
-       if (addr < 0)
-               pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
-       else
-               octeon_reserve32_memory = addr;
-#endif
+       if (CONFIG_CAVIUM_RESERVE32) {
+               int64_t addr =
+                       cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
+                                                          0, 0, 2 << 20,
+                                                          "CAVIUM_RESERVE32", 0);
+               if (addr < 0)
+                       pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
+               else
+                       octeon_reserve32_memory = addr;
+       }
 
 #ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2
        if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) {
@@ -1079,7 +1076,6 @@ void __init plat_mem_setup(void)
        cvmx_bootmem_unlock();
 #endif /* CONFIG_CRASH_DUMP */
 
-#ifdef CONFIG_CAVIUM_RESERVE32
        /*
         * Now that we've allocated the kernel memory it is safe to
         * free the reserved region. We free it here so that builtin
@@ -1087,7 +1083,6 @@ void __init plat_mem_setup(void)
         */
        if (octeon_reserve32_memory)
                cvmx_bootmem_free_named("CAVIUM_RESERVE32");
-#endif /* CONFIG_CAVIUM_RESERVE32 */
 
        if (total == 0)
                panic("Unable to allocate memory from "
index cf9c632..ed4a638 100644 (file)
@@ -32,9 +32,6 @@ CONFIG_IP_ROUTE_MULTIPATH=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_MROUTE=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 CONFIG_TCP_CONG_ADVANCED=y
 # CONFIG_TCP_CONG_BIC is not set
@@ -117,7 +114,6 @@ CONFIG_JFFS2_SUMMARY=y
 CONFIG_JFFS2_COMPRESSION_OPTIONS=y
 CONFIG_SQUASHFS=y
 # CONFIG_CRYPTO_HW is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 CONFIG_CMDLINE_BOOL=y
index 7143441..afd1c16 100644 (file)
@@ -29,9 +29,6 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
 CONFIG_CFG80211=m
 CONFIG_MAC80211=m
@@ -108,7 +105,6 @@ CONFIG_SQUASHFS_XZ=y
 # CONFIG_XZ_DEC_ARMTHUMB is not set
 # CONFIG_XZ_DEC_SPARC is not set
 CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
index 96622a2..0b74171 100644 (file)
@@ -10,12 +10,6 @@ CONFIG_EMBEDDED=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_ATH79=y
-CONFIG_ATH79_MACH_AP121=y
-CONFIG_ATH79_MACH_AP136=y
-CONFIG_ATH79_MACH_AP81=y
-CONFIG_ATH79_MACH_DB120=y
-CONFIG_ATH79_MACH_PB44=y
-CONFIG_ATH79_MACH_UBNT_XM=y
 CONFIG_HZ_100=y
 # CONFIG_SECCOMP is not set
 CONFIG_PCI=y
@@ -29,9 +23,6 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
 CONFIG_CFG80211=m
 CONFIG_MAC80211=m
@@ -92,7 +83,6 @@ CONFIG_LEDS_GPIO=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_CRC_ITU_T=m
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
index 861f680..34d0ca6 100644 (file)
@@ -24,9 +24,6 @@ CONFIG_PCMCIA_BCM63XX=y
 CONFIG_NET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_CFG80211=y
index d83e7d6..d15961f 100644 (file)
@@ -49,8 +49,6 @@ CONFIG_IP_PIMSM_V2=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -59,7 +57,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_SIT_6RD=y
 CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
@@ -101,7 +98,6 @@ CONFIG_BAYCOM_SER_HDX=m
 CONFIG_YAM=m
 CONFIG_FW_LOADER=m
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_EEPROM_LEGACY=y
 CONFIG_EEPROM_MAX6875=y
@@ -230,12 +226,8 @@ CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -243,7 +235,6 @@ CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index 032bb51..daef132 100644 (file)
@@ -17,9 +17,6 @@ CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=y
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
index 5956fb9..cd0dc37 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_HIGHMEM=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
-CONFIG_CC_STACKPROTECTOR_STRONG=y
 # CONFIG_SECCOMP is not set
 CONFIG_MIPS_O32_FP64_SUPPORT=y
 # CONFIG_RD_GZIP is not set
@@ -21,8 +20,6 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
 CONFIG_RD_XZ=y
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCIEASPM_POWERSAVE=y
@@ -30,7 +27,6 @@ CONFIG_PCIEPORTBUS=y
 CONFIG_PCIE_BRCMSTB=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -44,15 +40,11 @@ CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=y
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
 CONFIG_WIRELESS=y
 CONFIG_MAC80211=y
-CONFIG_NL80211=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
@@ -70,10 +62,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_IP_MROUTE=y
 CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
 CONFIG_INET_UDP_DIAG=y
 CONFIG_TCP_CONG_ADVANCED=y
 CONFIG_TCP_CONG_BIC=y
@@ -93,7 +81,6 @@ CONFIG_NET_SWITCHDEV=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_ALIGNMENT=12
 CONFIG_SPI=y
-CONFIG_SPI_BRCMSTB=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
@@ -105,14 +92,11 @@ CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_ABSENT=y
 CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_BRCMNAND=y
 CONFIG_MTD_SPI_NOR=y
 # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -120,7 +104,6 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_VLAN_8021Q=y
@@ -135,7 +118,6 @@ CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO is not set
 CONFIG_VT=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -203,17 +185,14 @@ CONFIG_CMDLINE="earlycon"
 CONFIG_MIPS_CMDLINE_DTB_EXTEND=y
 # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
 # CONFIG_CRYPTO_HW is not set
-CONFIG_DT_BCM974XX=y
 CONFIG_FW_CFE=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI_PLATFORM=y
-CONFIG_AHCI_BRCMSTB=y
 CONFIG_GENERIC_PHY=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_PHY_BRCM_USB=y
 CONFIG_PHY_BRCM_SATA=y
-CONFIG_PM_RUNTIME=y
 CONFIG_PM_DEBUG=y
 CONFIG_SYSVIPC=y
 CONFIG_FUNCTION_GRAPH_TRACER=y
@@ -227,3 +206,5 @@ CONFIG_FTRACE_SYSCALLS=y
 CONFIG_TRACER_SNAPSHOT=y
 CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
 CONFIG_STACK_TRACER=y
+CONFIG_AHCI_BRCM=y
+CONFIG_MTD_RAW_NAND=y
index 97ceaf0..a231149 100644 (file)
@@ -71,7 +71,6 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_DEC is not set
 # CONFIG_NET_VENDOR_DLINK is not set
 # CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MELLANOX is not set
index b8bd663..a8b62df 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_INET6_AH=y
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
 CONFIG_IPV6_VTI=y
 CONFIG_IPV6_SIT_6RD=y
 CONFIG_IPV6_GRE=y
index 0021427..4f74c4b 100644 (file)
@@ -37,9 +37,6 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -47,7 +44,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
@@ -79,7 +75,6 @@ CONFIG_NETDEVICES=y
 CONFIG_DECLANCE=y
 # CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_AURORA is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CADENCE is not set
 # CONFIG_NET_VENDOR_CAVIUM is not set
@@ -193,12 +188,8 @@ CONFIG_CRYPTO_CRC32=m
 CONFIG_CRYPTO_CRCT10DIF=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_ARC4=m
@@ -208,7 +199,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index 7a97a08..f0d0546 100644 (file)
@@ -33,9 +33,6 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -43,7 +40,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
@@ -75,7 +71,6 @@ CONFIG_NETDEVICES=y
 CONFIG_DECLANCE=y
 # CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_AURORA is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CADENCE is not set
 # CONFIG_NET_VENDOR_CAVIUM is not set
@@ -188,12 +183,8 @@ CONFIG_CRYPTO_CRC32=m
 CONFIG_CRYPTO_CRCT10DIF=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_ARC4=m
@@ -203,7 +194,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index a064336..df5ff9d 100644 (file)
@@ -32,9 +32,6 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -42,7 +39,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
@@ -74,7 +70,6 @@ CONFIG_NETDEVICES=y
 CONFIG_DECLANCE=y
 # CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_AURORA is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CADENCE is not set
 # CONFIG_NET_VENDOR_CAVIUM is not set
@@ -188,12 +183,8 @@ CONFIG_CRYPTO_CRC32=m
 CONFIG_CRYPTO_CRCT10DIF=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_ARC4=m
@@ -203,7 +194,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index ba47c5e..843d6a5 100644 (file)
@@ -35,8 +35,6 @@ CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_IPIP=m
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
@@ -92,7 +90,6 @@ CONFIG_MTD_CFI_AMDSTD=m
 CONFIG_MTD_CFI_STAA=m
 CONFIG_MTD_PHYSMAP=m
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
@@ -159,7 +156,6 @@ CONFIG_USB_MOUSE=y
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_OTG_PRODUCTLIST=y
-CONFIG_USB_WUSB_CBAF=m
 CONFIG_USB_C67X00_HCD=m
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
@@ -219,15 +215,10 @@ CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
 CONFIG_CRC7=m
-# CONFIG_ENABLE_MUST_CHECK is not set
index 5107095..8cfbafa 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_SWITCHDEV=y
 CONFIG_NET_DSA=y
 CONFIG_MSCC_OCELOT_SWITCH=y
-CONFIG_MSCC_OCELOT_SWITCH_OCELOT=y
 CONFIG_MDIO_MSCC_MIIM=y
 CONFIG_MICROSEMI_PHY=y
 
index d82f4eb..7cd321b 100644 (file)
@@ -29,9 +29,6 @@ CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
@@ -220,9 +217,6 @@ CONFIG_HDLC_X25=m
 CONFIG_PCI200SYN=m
 CONFIG_WANXL=m
 CONFIG_FARSYNC=m
-CONFIG_DSCC4=m
-CONFIG_DSCC4_PCISYNC=y
-CONFIG_DSCC4_PCI_RST=y
 CONFIG_LAPBETHER=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
@@ -288,7 +282,6 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -299,7 +292,6 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw ip=auto"
index 70a4ba9..13df299 100644 (file)
@@ -36,9 +36,6 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -47,7 +44,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
@@ -226,7 +222,6 @@ CONFIG_SERIO_RAW=m
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_IP22_ZILOG=m
 # CONFIG_HW_RANDOM is not set
-CONFIG_RAW_DRIVER=m
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_WATCHDOG=y
@@ -320,11 +315,7 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -333,7 +324,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index 821630a..3e86f81 100644 (file)
@@ -33,9 +33,6 @@ CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -44,10 +41,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_SIT_6RD=y
 CONFIG_IPV6_TUNNEL=m
@@ -92,7 +85,6 @@ CONFIG_CFG80211=m
 CONFIG_MAC80211=m
 CONFIG_RFKILL=m
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_SCSI=y
@@ -115,7 +107,6 @@ CONFIG_SCSI_AIC94XX=m
 # CONFIG_AIC94XX_DEBUG is not set
 CONFIG_SCSI_MVSAS=m
 # CONFIG_SCSI_MVSAS_DEBUG is not set
-CONFIG_SCSI_DPT_I2O=m
 CONFIG_SCSI_MPT2SAS=m
 CONFIG_LIBFC=m
 CONFIG_SCSI_QLOGIC_1280=y
@@ -126,8 +117,6 @@ CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
 CONFIG_SCSI_DH_ALUA=m
-CONFIG_SCSI_OSD_INITIATOR=m
-CONFIG_SCSI_OSD_ULD=m
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
@@ -166,7 +155,6 @@ CONFIG_JME=m
 CONFIG_MLX4_EN=m
 # CONFIG_MLX4_DEBUG is not set
 CONFIG_KS8851_MLL=m
-CONFIG_VXGE=m
 CONFIG_AX88796=m
 CONFIG_AX88796_93CX6=y
 CONFIG_ETHOC=m
@@ -264,7 +252,6 @@ CONFIG_I2C_VIAPRO=m
 CONFIG_I2C_OCORES=m
 CONFIG_I2C_PCA_PLATFORM=m
 CONFIG_I2C_SIMTEC=m
-CONFIG_I2C_PARPORT_LIGHT=m
 CONFIG_I2C_TAOS_EVM=m
 CONFIG_I2C_STUB=m
 # CONFIG_HWMON is not set
@@ -309,7 +296,6 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_SQUASHFS=m
 CONFIG_OMFS_FS=m
-CONFIG_EXOFS_FS=m
 CONFIG_NFS_FS=y
 CONFIG_SECURITYFS=y
 CONFIG_CRYPTO_CRYPTD=m
@@ -321,12 +307,8 @@ CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -335,7 +317,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index 0921ef3..ba13eea 100644 (file)
@@ -29,9 +29,6 @@ CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_TCP_MD5SIG=y
 # CONFIG_IPV6 is not set
 CONFIG_SCSI=y
index 74020aa..8ced222 100644 (file)
@@ -43,7 +43,6 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_NETWORK_SECMARK=y
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_RAID_ATTRS=y
 CONFIG_SCSI=y
@@ -165,7 +164,6 @@ CONFIG_CRYPTO_MICHAEL_MIC=y
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_TGR192=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_ANUBIS=y
 CONFIG_CRYPTO_ARC4=y
index 843f360..106b21c 100644 (file)
@@ -32,7 +32,6 @@ CONFIG_PARPORT_1284=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_FD=m
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_CDROM_PKTCDVD=m
index 791894c..7e598d3 100644 (file)
@@ -43,9 +43,6 @@ CONFIG_IP_MROUTE=y
 CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
 CONFIG_SYN_COOKIES=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_CONG_ADVANCED=y
 CONFIG_TCP_CONG_BIC=y
 CONFIG_DEFAULT_BIC=y
@@ -77,7 +74,6 @@ CONFIG_MAC80211_LEDS=y
 CONFIG_RFKILL=m
 CONFIG_RFKILL_INPUT=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_SD=y
@@ -312,12 +308,8 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_RMD256=m
-CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -326,7 +318,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
index 25e7042..68207b3 100644 (file)
@@ -28,9 +28,6 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
@@ -115,7 +112,6 @@ CONFIG_NLS_ISO8859_1=m
 # CONFIG_CRYPTO_ECHAINIV is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_DYNAMIC_DEBUG=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
index 3a158d4..c3910a9 100644 (file)
@@ -29,9 +29,6 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
@@ -116,7 +113,6 @@ CONFIG_NLS_ISO8859_1=m
 # CONFIG_CRYPTO_ECHAINIV is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_DYNAMIC_DEBUG=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
index e948ca4..728bef6 100644 (file)
@@ -95,7 +95,6 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=m
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_RAID_ATTRS=m
@@ -229,7 +228,6 @@ CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_HW_RANDOM=y
-CONFIG_RAW_DRIVER=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_PIIX4=y
 CONFIG_GPIO_LOONGSON=y
@@ -336,7 +334,6 @@ CONFIG_DEFAULT_SECURITY_DAC=y
 CONFIG_CRYPTO_SEQIV=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST5=m
index 25ecd15..aca66a5 100644 (file)
@@ -143,7 +143,6 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=m
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_VIRTIO_BLK=y
@@ -268,7 +267,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_HW_RANDOM=y
-CONFIG_RAW_DRIVER=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_PIIX4=y
 CONFIG_GPIO_LOONGSON=y
index 7a5bdd2..265d38d 100644 (file)
@@ -42,8 +42,6 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -229,7 +227,6 @@ CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_BLK_DEV_FD=m
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -237,7 +234,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_RAID_ATTRS=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -408,7 +404,6 @@ CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index b5ba08d..1d2b248 100644 (file)
@@ -46,8 +46,6 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -233,7 +231,6 @@ CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_BLK_DEV_FD=m
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -241,7 +238,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_RAID_ATTRS=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -415,7 +411,6 @@ CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index 6fb9bc2..fd63a2b 100644 (file)
@@ -76,7 +76,6 @@ CONFIG_NET_ACT_POLICE=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
@@ -98,7 +97,6 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_DEC is not set
 # CONFIG_NET_VENDOR_DLINK is not set
 # CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MELLANOX is not set
@@ -172,7 +170,6 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index eb72df5..1f07e35 100644 (file)
@@ -78,7 +78,6 @@ CONFIG_NET_ACT_POLICE=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
@@ -100,7 +99,6 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_DEC is not set
 # CONFIG_NET_VENDOR_DLINK is not set
 # CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MELLANOX is not set
@@ -173,7 +171,6 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index 1fb40d3..5cd3eca 100644 (file)
@@ -79,7 +79,6 @@ CONFIG_NET_ACT_POLICE=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
@@ -99,7 +98,6 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_DEC is not set
 # CONFIG_NET_VENDOR_DLINK is not set
 # CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MELLANOX is not set
@@ -174,7 +172,6 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index 75cb778..45688e7 100644 (file)
@@ -80,7 +80,6 @@ CONFIG_NET_ACT_POLICE=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
@@ -102,7 +101,6 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_DEC is not set
 # CONFIG_NET_VENDOR_DLINK is not set
 # CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MELLANOX is not set
@@ -176,7 +174,6 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index 7b4f247..136f965 100644 (file)
@@ -77,7 +77,6 @@ CONFIG_NET_ACT_POLICE=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
@@ -99,7 +98,6 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_DEC is not set
 # CONFIG_NET_VENDOR_DLINK is not set
 # CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MELLANOX is not set
@@ -172,7 +170,6 @@ CONFIG_NLS_ISO8859_1=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index 8d58653..75b8da8 100644 (file)
@@ -45,8 +45,6 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -231,7 +229,6 @@ CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_BLK_DEV_FD=m
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
@@ -239,7 +236,6 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_RAID_ATTRS=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -414,7 +410,6 @@ CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index 4194e79..efbfaa5 100644 (file)
@@ -58,13 +58,9 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
@@ -284,7 +280,6 @@ CONFIG_PCMCIA_XIRCOM=m
 CONFIG_DL2K=m
 CONFIG_SUNDANCE=m
 CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_HP100=m
 CONFIG_E100=m
 CONFIG_E1000=m
 CONFIG_IXGB=m
@@ -368,9 +363,6 @@ CONFIG_HDLC_X25=m
 CONFIG_PCI200SYN=m
 CONFIG_WANXL=m
 CONFIG_FARSYNC=m
-CONFIG_DSCC4=m
-CONFIG_DSCC4_PCISYNC=y
-CONFIG_DSCC4_PCI_RST=y
 CONFIG_LAPBETHER=m
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_GPIO=y
@@ -683,7 +675,6 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -692,5 +683,4 @@ CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_MAGIC_SYSRQ=y
index fc39ddf..9c34daf 100644 (file)
@@ -35,9 +35,6 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
index fd56724..48dd02d 100644 (file)
@@ -45,7 +45,6 @@ CONFIG_KEYBOARD_GPIO_POLLED=m
 CONFIG_SERIAL_PIC32=y
 CONFIG_SERIAL_PIC32_CONSOLE=y
 CONFIG_HW_RANDOM=y
-CONFIG_RAW_DRIVER=m
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_HIDRAW=y
index 252d472..93306f5 100644 (file)
@@ -33,9 +33,6 @@ CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_MULTIPATH=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_INET_DIAG=m
 CONFIG_TCP_CONG_ADVANCED=y
 CONFIG_TCP_CONG_CUBIC=m
@@ -162,5 +159,4 @@ CONFIG_SQUASHFS=y
 CONFIG_CRYPTO_TEST=m
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC16=m
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
index f8212a8..30c195f 100644 (file)
@@ -21,9 +21,6 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_MTD=y
@@ -51,7 +48,6 @@ CONFIG_TC35815=y
 CONFIG_SERIAL_TXX9_CONSOLE=y
 CONFIG_SERIAL_TXX9_STDSERIAL=y
 CONFIG_SPI=y
-CONFIG_SPI_TXX9=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_TXX9_WDT=m
@@ -65,8 +61,6 @@ CONFIG_SND=m
 # CONFIG_SND_SPI is not set
 # CONFIG_SND_MIPS is not set
 CONFIG_SND_SOC=m
-CONFIG_SND_SOC_TXX9ACLC=m
-CONFIG_SND_SOC_TXX9ACLC_GENERIC=m
 # CONFIG_USB_SUPPORT is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -78,7 +72,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_RS5C348=y
 CONFIG_RTC_DRV_DS1742=y
-CONFIG_RTC_DRV_TX4939=y
 CONFIG_DMADEVICES=y
 CONFIG_TXX9_DMAC=m
 # CONFIG_DNOTIFY is not set
index 7d6f235..d698185 100644 (file)
@@ -29,9 +29,6 @@ CONFIG_NET_IPIP=m
 CONFIG_IP_MROUTE=y
 CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
@@ -39,7 +36,6 @@ CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
@@ -192,9 +188,7 @@ CONFIG_PARIDE_KTTI=m
 CONFIG_PARIDE_ON20=m
 CONFIG_PARIDE_ON26=m
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_SX8=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
@@ -400,7 +394,6 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
index eb359db..bf017d4 100644 (file)
@@ -35,9 +35,6 @@ CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_MROUTE=y
 CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 CONFIG_TCP_CONG_ADVANCED=y
 # CONFIG_TCP_CONG_BIC is not set
@@ -140,7 +137,6 @@ CONFIG_CRC32_SARWATE=y
 # CONFIG_XZ_DEC_ARMTHUMB is not set
 # CONFIG_XZ_DEC_SPARC is not set
 CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
index de94bf7..030186f 100644 (file)
@@ -88,7 +88,6 @@ CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -96,7 +95,6 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_DES=m
 CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_SALSA20=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_DEFLATE=m
index a14f8ea..0722a3b 100644 (file)
@@ -35,9 +35,6 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
index eeb689f..eb5acf1 100644 (file)
@@ -37,9 +37,6 @@ CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_MROUTE=y
 CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 CONFIG_TCP_CONG_ADVANCED=y
 # CONFIG_TCP_CONG_BIC is not set
@@ -146,7 +143,6 @@ CONFIG_CRYPTO_ARC4=m
 CONFIG_CRC_ITU_T=m
 CONFIG_CRC32_SARWATE=y
 CONFIG_PRINTK_TIME=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
index 57561e0..44f9824 100644 (file)
@@ -63,10 +63,6 @@ extern void do_domain_IRQ(struct irq_domain *domain, unsigned int irq);
 extern void arch_init_irq(void);
 extern void spurious_interrupt(void);
 
-extern int allocate_irqno(void);
-extern void alloc_legacy_irqno(void);
-extern void free_irqno(unsigned int irq);
-
 /*
  * Before R2 the timer and performance counter interrupts were both fixed to
  * IE7.         Since R2 their number has to be read from the c0_intctl register.
index cbe75ad..1e8621a 100644 (file)
@@ -104,8 +104,6 @@ struct plat_dsl_data {
        int reset_bit_sar;
 };
 
-extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
-
 static inline int ar7_is_titan(void)
 {
        return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x24)) & 0xffff) ==
index 29ae636..f6dfcca 100644 (file)
@@ -264,26 +264,6 @@ static inline void cvmx_fpa_free(void *ptr, uint64_t pool,
 }
 
 /**
- * Setup a FPA pool to control a new block of memory.
- * This can only be called once per pool. Make sure proper
- * locking enforces this.
- *
- * @pool:      Pool to initialize
- *                  0 <= pool < 8
- * @name:      Constant character string to name this pool.
- *                  String is not copied.
- * @buffer:    Pointer to the block of memory to use. This must be
- *                  accessible by all processors and external hardware.
- * @block_size: Size for each block controlled by the FPA
- * @num_blocks: Number of blocks
- *
- * Returns 0 on Success,
- *        -1 on failure
- */
-extern int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer,
-                              uint64_t block_size, uint64_t num_blocks);
-
-/**
  * Shutdown a Memory pool and validate that it had all of
  * the buffers originally placed in it. This should only be
  * called by one processor after all hardware has finished
index 7e714ae..5c1d726 100644 (file)
@@ -43,7 +43,6 @@ extern int octeon_get_southbridge_interrupt(void);
 extern int octeon_get_boot_coremask(void);
 extern int octeon_get_boot_num_arguments(void);
 extern const char *octeon_get_boot_argument(int arg);
-extern void octeon_hal_setup_reserved32(void);
 extern void octeon_user_io_init(void);
 
 extern void octeon_init_cvmcount(void);
index b12d9a3..2f46f6c 100644 (file)
@@ -64,6 +64,4 @@ enum octeon_dma_bar_type {
 extern enum octeon_dma_bar_type octeon_dma_bar_type;
 
 void octeon_pci_dma_init(void);
-extern char *octeon_swiotlb;
-
 #endif
index dbde5f9..495b319 100644 (file)
@@ -32,7 +32,6 @@ extern unsigned int soc_type;
 extern unsigned int periph_rev;
 extern unsigned int zbbus_mhz;
 
-extern void sb1250_time_init(void);
 extern void sb1250_mask_irq(int cpu, int irq);
 extern void sb1250_unmask_irq(int cpu, int irq);
 
index 7dfa297..7fb6656 100644 (file)
@@ -226,9 +226,6 @@ extern void sni_pcit_cplus_irq_init(void);
 extern void sni_rm200_irq_init(void);
 extern void sni_pcimt_irq_init(void);
 
-/* timer inits */
-extern void sni_cpu_time_init(void);
-
 /* eisa init for RM200/400 */
 #ifdef CONFIG_EISA
 extern int sni_eisa_root_init(void);
index 7db6ff9..f88ce78 100644 (file)
@@ -26,7 +26,7 @@ __init void mips_set_machine_name(const char *name)
        if (name == NULL)
                return;
 
-       strlcpy(mips_machine_name, name, sizeof(mips_machine_name));
+       strscpy(mips_machine_name, name, sizeof(mips_machine_name));
        pr_info("MIPS: machine is %s\n", mips_get_machine_name());
 }
 
@@ -52,9 +52,9 @@ int __init __dt_register_buses(const char *bus0, const char *bus1)
        if (!of_have_populated_dt())
                panic("device tree not present");
 
-       strlcpy(of_ids[0].compatible, bus0, sizeof(of_ids[0].compatible));
+       strscpy(of_ids[0].compatible, bus0, sizeof(of_ids[0].compatible));
        if (bus1) {
-               strlcpy(of_ids[1].compatible, bus1,
+               strscpy(of_ids[1].compatible, bus1,
                        sizeof(of_ids[1].compatible));
        }
 
index 56b51de..58fc8d0 100644 (file)
@@ -340,7 +340,7 @@ void *__init relocate_kernel(void)
        early_init_dt_scan(fdt);
        if (boot_command_line[0]) {
                /* Boot command line was passed in device tree */
-               strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+               strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
        }
 #endif /* CONFIG_USE_OF */
 
index 0a9bd7b..2456050 100644 (file)
@@ -46,7 +46,7 @@ static void build_segment_config(char *str, unsigned int cfg)
                ((cfg & MIPS_SEGCFG_EU) >> MIPS_SEGCFG_EU_SHIFT));
 }
 
-static int show_segments(struct seq_file *m, void *v)
+static int segments_show(struct seq_file *m, void *v)
 {
        unsigned int segcfg;
        char str[42];
@@ -80,18 +80,7 @@ static int show_segments(struct seq_file *m, void *v)
 
        return 0;
 }
-
-static int segments_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, show_segments, NULL);
-}
-
-static const struct file_operations segments_fops = {
-       .open           = segments_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(segments);
 
 static int __init segments_info(void)
 {
index 2ca156a..39c79f6 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
 #include <asm/prom.h>
+#include <asm/fw/fw.h>
 
 #ifdef CONFIG_MIPS_ELF_APPENDED_DTB
 char __section(".appended_dtb") __appended_dtb[0x100000];
@@ -756,6 +757,24 @@ static void __init prefill_possible_map(void)
 static inline void prefill_possible_map(void) {}
 #endif
 
+static void __init setup_rng_seed(void)
+{
+       char *rng_seed_hex = fw_getenv("rngseed");
+       u8 rng_seed[512];
+       size_t len;
+
+       if (!rng_seed_hex)
+               return;
+
+       len = min(sizeof(rng_seed), strlen(rng_seed_hex) / 2);
+       if (hex2bin(rng_seed, rng_seed_hex, len))
+               return;
+
+       add_bootloader_randomness(rng_seed, len);
+       memzero_explicit(rng_seed, len);
+       memzero_explicit(rng_seed_hex, len * 2);
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
@@ -786,6 +805,8 @@ void __init setup_arch(char **cmdline_p)
        paging_init();
 
        memblock_dump_all();
+
+       setup_rng_seed();
 }
 
 unsigned long kernelsp[NR_CPUS];
index 7a62368..2d5a0bc 100644 (file)
@@ -50,6 +50,7 @@ struct clk *clk_get_io(void)
 {
        return &cpu_clk_generic[2];
 }
+EXPORT_SYMBOL_GPL(clk_get_io);
 
 struct clk *clk_get_ppe(void)
 {
index c731082..be4829c 100644 (file)
@@ -34,6 +34,14 @@ unsigned long physical_memsize = 0L;
  */
 static struct ltq_soc_info soc_info;
 
+/*
+ * These structs are used to override vsmp_init_secondary()
+ */
+#if defined(CONFIG_MIPS_MT_SMP)
+extern const struct plat_smp_ops vsmp_smp_ops;
+static struct plat_smp_ops lantiq_smp_ops;
+#endif
+
 const char *get_system_type(void)
 {
        return soc_info.sys_type;
@@ -84,6 +92,17 @@ void __init plat_mem_setup(void)
        __dt_setup_arch(dtb);
 }
 
+#if defined(CONFIG_MIPS_MT_SMP)
+static void lantiq_init_secondary(void)
+{
+       /*
+        * MIPS CPU startup function vsmp_init_secondary() will only
+        * enable some of the interrupts for the second CPU/VPE.
+        */
+       set_c0_status(ST0_IM);
+}
+#endif
+
 void __init prom_init(void)
 {
        /* call the soc specific detetcion code and get it to fill soc_info */
@@ -95,7 +114,10 @@ void __init prom_init(void)
        prom_init_cmdline();
 
 #if defined(CONFIG_MIPS_MT_SMP)
-       if (register_vsmp_smp_ops())
-               panic("failed to register_vsmp_smp_ops()");
+       if (cpu_has_mipsmt) {
+               lantiq_smp_ops = vsmp_smp_ops;
+               lantiq_smp_ops.init_secondary = lantiq_init_secondary;
+               register_smp_ops(&lantiq_smp_ops);
+       }
 #endif
 }
index 7a14da8..2796e87 100644 (file)
@@ -4,9 +4,10 @@
  *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
+#include <linux/err.h>
 #include <linux/export.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/dma-mapping.h>
 
 #include <lantiq_soc.h>
@@ -25,23 +26,28 @@ EXPORT_SYMBOL(ltq_get_cp1_base);
 static int vmmc_probe(struct platform_device *pdev)
 {
 #define CP1_SIZE       (1 << 20)
+       struct gpio_desc *gpio;
        int gpio_count;
        dma_addr_t dma;
+       int error;
 
        cp1_base =
                (void *) CPHYSADDR(dma_alloc_coherent(&pdev->dev, CP1_SIZE,
                                                    &dma, GFP_KERNEL));
 
-       gpio_count = of_gpio_count(pdev->dev.of_node);
+       gpio_count = gpiod_count(&pdev->dev, NULL);
        while (gpio_count > 0) {
-               enum of_gpio_flags flags;
-               int gpio = of_get_gpio_flags(pdev->dev.of_node,
-                                            --gpio_count, &flags);
-               if (gpio_request(gpio, "vmmc-relay"))
+               gpio = devm_gpiod_get_index(&pdev->dev,
+                                           NULL, --gpio_count, GPIOD_OUT_HIGH);
+               error = PTR_ERR_OR_ZERO(gpio);
+               if (error) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO idx %d: %d\n",
+                               gpio_count, error);
                        continue;
-               dev_info(&pdev->dev, "requested GPIO %d\n", gpio);
-               gpio_direction_output(gpio,
-                                     (flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1));
+               }
+
+               gpiod_set_consumer_name(gpio, "vmmc-relay");
        }
 
        dev_info(&pdev->dev, "reserved %dMB at 0x%p", CP1_SIZE >> 20, cp1_base);
index fcef740..88242dc 100644 (file)
@@ -1,17 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/export.h>
 #include <linux/compiler.h>
+#include <uapi/linux/swab.h>
+
+/* To silence -Wmissing-prototypes. */
+unsigned long long __bswapdi2(unsigned long long u);
 
 unsigned long long notrace __bswapdi2(unsigned long long u)
 {
-       return (((u) & 0xff00000000000000ull) >> 56) |
-              (((u) & 0x00ff000000000000ull) >> 40) |
-              (((u) & 0x0000ff0000000000ull) >> 24) |
-              (((u) & 0x000000ff00000000ull) >>  8) |
-              (((u) & 0x00000000ff000000ull) <<  8) |
-              (((u) & 0x0000000000ff0000ull) << 24) |
-              (((u) & 0x000000000000ff00ull) << 40) |
-              (((u) & 0x00000000000000ffull) << 56);
+       return ___constant_swab64(u);
 }
-
 EXPORT_SYMBOL(__bswapdi2);
index 22d8e4f..2ed6554 100644 (file)
@@ -1,13 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/export.h>
 #include <linux/compiler.h>
+#include <uapi/linux/swab.h>
+
+/* To silence -Wmissing-prototypes. */
+unsigned int __bswapsi2(unsigned int u);
 
 unsigned int notrace __bswapsi2(unsigned int u)
 {
-       return (((u) & 0xff000000) >> 24) |
-              (((u) & 0x00ff0000) >>  8) |
-              (((u) & 0x0000ff00) <<  8) |
-              (((u) & 0x000000ff) << 24);
+       return ___constant_swab32(u);
 }
-
 EXPORT_SYMBOL(__bswapsi2);
index 2009169..7d9ea51 100644 (file)
@@ -73,8 +73,6 @@ static void __init setup_pcimap(void)
 #endif
 }
 
-extern int sbx00_acpi_init(void);
-
 static int __init pcibios_init(void)
 {
        setup_pcimap();
index 794c96c..311dc15 100644 (file)
@@ -98,7 +98,7 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
        if (plat_dat->bus_id) {
                __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
                             GMAC1_USE_UART0, LS1X_MUX_CTRL0);
-               switch (plat_dat->interface) {
+               switch (plat_dat->phy_interface) {
                case PHY_INTERFACE_MODE_RGMII:
                        val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
                        break;
@@ -107,12 +107,12 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
                        break;
                default:
                        pr_err("unsupported mii mode %d\n",
-                              plat_dat->interface);
+                              plat_dat->phy_interface);
                        return -ENOTSUPP;
                }
                val &= ~GMAC1_SHUT;
        } else {
-               switch (plat_dat->interface) {
+               switch (plat_dat->phy_interface) {
                case PHY_INTERFACE_MODE_RGMII:
                        val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
                        break;
@@ -121,7 +121,7 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
                        break;
                default:
                        pr_err("unsupported mii mode %d\n",
-                              plat_dat->interface);
+                              plat_dat->phy_interface);
                        return -ENOTSUPP;
                }
                val &= ~GMAC0_SHUT;
@@ -131,7 +131,7 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
        plat_dat = dev_get_platdata(&pdev->dev);
 
        val &= ~PHY_INTF_SELI;
-       if (plat_dat->interface == PHY_INTERFACE_MODE_RMII)
+       if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII)
                val |= 0x4 << PHY_INTF_SELI_SHIFT;
        __raw_writel(val, LS1X_MUX_CTRL1);
 
@@ -146,9 +146,9 @@ static struct plat_stmmacenet_data ls1x_eth0_pdata = {
        .bus_id                 = 0,
        .phy_addr               = -1,
 #if defined(CONFIG_LOONGSON1_LS1B)
-       .interface              = PHY_INTERFACE_MODE_MII,
+       .phy_interface          = PHY_INTERFACE_MODE_MII,
 #elif defined(CONFIG_LOONGSON1_LS1C)
-       .interface              = PHY_INTERFACE_MODE_RMII,
+       .phy_interface          = PHY_INTERFACE_MODE_RMII,
 #endif
        .mdio_bus_data          = &ls1x_mdio_bus_data,
        .dma_cfg                = &ls1x_eth_dma_cfg,
@@ -186,7 +186,7 @@ struct platform_device ls1x_eth0_pdev = {
 static struct plat_stmmacenet_data ls1x_eth1_pdata = {
        .bus_id                 = 1,
        .phy_addr               = -1,
-       .interface              = PHY_INTERFACE_MODE_MII,
+       .phy_interface          = PHY_INTERFACE_MODE_MII,
        .mdio_bus_data          = &ls1x_mdio_bus_data,
        .dma_cfg                = &ls1x_eth_dma_cfg,
        .has_gmac               = 1,
index e9de6da..9dcfe9d 100644 (file)
@@ -15,7 +15,6 @@ static struct platform_device *ls1c_platform_devices[] __initdata = {
 static int __init ls1c_platform_init(void)
 {
        ls1x_serial_set_uartclk(&ls1x_uart_pdev);
-       ls1x_rtc_set_extclk(&ls1x_rtc_pdev);
 
        return platform_add_devices(ls1c_platform_devices,
                                   ARRAY_SIZE(ls1c_platform_devices));
index 587cf1d..265bc57 100644 (file)
@@ -1032,7 +1032,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
         */
        if (dec_insn.micro_mips_mode) {
                /*
-                * If next instruction is a 16-bit instruction, then it
+                * If next instruction is a 16-bit instruction, then
                 * it cannot be a FPU instruction. This could happen
                 * since we can be called for non-FPU instructions.
                 */
index 30e0922..e17d862 100644 (file)
@@ -2,7 +2,7 @@
 /*
  */
 
-/**
+/*
  * Both AR2315 and AR2316 chips have PCI interface unit, which supports DMA
  * and interrupt. PCI interface supports MMIO access method, but does not
  * seem to support I/O ports.
index 1ca42f4..8d16cd0 100644 (file)
@@ -9,11 +9,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/clk.h>
 #include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/of_pci.h>
 
@@ -62,7 +62,7 @@
 __iomem void *ltq_pci_mapped_cfg;
 static __iomem void *ltq_pci_membase;
 
-static int reset_gpio;
+static struct gpio_desc *reset_gpio;
 static struct clk *clk_pci, *clk_external;
 static struct resource pci_io_resource;
 static struct resource pci_mem_resource;
@@ -95,6 +95,7 @@ static int ltq_pci_startup(struct platform_device *pdev)
        struct device_node *node = pdev->dev.of_node;
        const __be32 *req_mask, *bus_clk;
        u32 temp_buffer;
+       int error;
 
        /* get our clocks */
        clk_pci = clk_get(&pdev->dev, NULL);
@@ -123,17 +124,14 @@ static int ltq_pci_startup(struct platform_device *pdev)
                clk_disable(clk_external);
 
        /* setup reset gpio used by pci */
-       reset_gpio = of_get_named_gpio(node, "gpio-reset", 0);
-       if (gpio_is_valid(reset_gpio)) {
-               int ret = devm_gpio_request(&pdev->dev,
-                                               reset_gpio, "pci-reset");
-               if (ret) {
-                       dev_err(&pdev->dev,
-                               "failed to request gpio %d\n", reset_gpio);
-                       return ret;
-               }
-               gpio_direction_output(reset_gpio, 1);
+       reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
+                                            GPIOD_OUT_LOW);
+       error = PTR_ERR_OR_ZERO(reset_gpio);
+       if (error) {
+               dev_err(&pdev->dev, "failed to request gpio: %d\n", error);
+               return error;
        }
+       gpiod_set_consumer_name(reset_gpio, "pci_reset");
 
        /* enable auto-switching between PCI and EBU */
        ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
@@ -195,11 +193,11 @@ static int ltq_pci_startup(struct platform_device *pdev)
        ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
 
        /* toggle reset pin */
-       if (gpio_is_valid(reset_gpio)) {
-               __gpio_set_value(reset_gpio, 0);
+       if (reset_gpio) {
+               gpiod_set_value_cansleep(reset_gpio, 1);
                wmb();
                mdelay(1);
-               __gpio_set_value(reset_gpio, 1);
+               gpiod_set_value_cansleep(reset_gpio, 0);
        }
        return 0;
 }
index d9c8c4e..08c46cf 100644 (file)
@@ -44,7 +44,7 @@ void __init plat_mem_setup(void)
        pr_info(" builtin_cmdline  : %s\n", CONFIG_CMDLINE);
 #endif
        if (dtb != __dtb_start)
-               strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+               strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 
 #ifdef CONFIG_EARLY_PRINTK
        fw_init_early_console(-1);
index 94ca837..8c8cc0a 100644 (file)
@@ -18,22 +18,11 @@ static int bootrom_show(struct seq_file *s, void *unused)
 
        return 0;
 }
-
-static int bootrom_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, bootrom_show, NULL);
-}
-
-static const struct file_operations bootrom_file_ops = {
-       .open           = bootrom_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(bootrom);
 
 static int __init bootrom_setup(void)
 {
-       debugfs_create_file("bootrom", 0444, NULL, NULL, &bootrom_file_ops);
+       debugfs_create_file("bootrom", 0444, NULL, NULL, &bootrom_fops);
        return 0;
 }
 
index e762886..5143d1c 100644 (file)
@@ -27,15 +27,18 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
 {
        struct xtalk_bridge_platform_data *bd;
        struct sgi_w1_platform_data *wd;
-       struct platform_device *pdev;
+       struct platform_device *pdev_wd;
+       struct platform_device *pdev_bd;
        struct resource w1_res;
        unsigned long offset;
 
        offset = NODE_OFFSET(nasid);
 
        wd = kzalloc(sizeof(*wd), GFP_KERNEL);
-       if (!wd)
-               goto no_mem;
+       if (!wd) {
+               pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
+               return;
+       }
 
        snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
                 offset + (widget << SWIN_SIZE_BITS));
@@ -46,24 +49,35 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
        w1_res.end = w1_res.start + 3;
        w1_res.flags = IORESOURCE_MEM;
 
-       pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
-       if (!pdev) {
-               kfree(wd);
-               goto no_mem;
+       pdev_wd = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
+       if (!pdev_wd) {
+               pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
+               goto err_kfree_wd;
+       }
+       if (platform_device_add_resources(pdev_wd, &w1_res, 1)) {
+               pr_warn("xtalk:n%d/%x bridge failed to add platform resources.\n", nasid, widget);
+               goto err_put_pdev_wd;
+       }
+       if (platform_device_add_data(pdev_wd, wd, sizeof(*wd))) {
+               pr_warn("xtalk:n%d/%x bridge failed to add platform data.\n", nasid, widget);
+               goto err_put_pdev_wd;
+       }
+       if (platform_device_add(pdev_wd)) {
+               pr_warn("xtalk:n%d/%x bridge failed to add platform device.\n", nasid, widget);
+               goto err_put_pdev_wd;
        }
-       platform_device_add_resources(pdev, &w1_res, 1);
-       platform_device_add_data(pdev, wd, sizeof(*wd));
        /* platform_device_add_data() duplicates the data */
        kfree(wd);
-       platform_device_add(pdev);
 
        bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-       if (!bd)
-               goto no_mem;
-       pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
-       if (!pdev) {
-               kfree(bd);
-               goto no_mem;
+       if (!bd) {
+               pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
+               goto err_unregister_pdev_wd;
+       }
+       pdev_bd = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
+       if (!pdev_bd) {
+               pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
+               goto err_kfree_bd;
        }
 
 
@@ -84,15 +98,31 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
        bd->io.flags    = IORESOURCE_IO;
        bd->io_offset   = offset;
 
-       platform_device_add_data(pdev, bd, sizeof(*bd));
+       if (platform_device_add_data(pdev_bd, bd, sizeof(*bd))) {
+               pr_warn("xtalk:n%d/%x bridge failed to add platform data.\n", nasid, widget);
+               goto err_put_pdev_bd;
+       }
+       if (platform_device_add(pdev_bd)) {
+               pr_warn("xtalk:n%d/%x bridge failed to add platform device.\n", nasid, widget);
+               goto err_put_pdev_bd;
+       }
        /* platform_device_add_data() duplicates the data */
        kfree(bd);
-       platform_device_add(pdev);
        pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget);
        return;
 
-no_mem:
-       pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
+err_put_pdev_bd:
+       platform_device_put(pdev_bd);
+err_kfree_bd:
+       kfree(bd);
+err_unregister_pdev_wd:
+       platform_device_unregister(pdev_wd);
+       return;
+err_put_pdev_wd:
+       platform_device_put(pdev_wd);
+err_kfree_wd:
+       kfree(wd);
+       return;
 }
 
 static int probe_one_port(nasid_t nasid, int widget, int masterwid)
index 8129524..7ceb2b2 100644 (file)
@@ -40,12 +40,15 @@ static void bridge_platform_create(int widget, int masterwid)
 {
        struct xtalk_bridge_platform_data *bd;
        struct sgi_w1_platform_data *wd;
-       struct platform_device *pdev;
+       struct platform_device *pdev_wd;
+       struct platform_device *pdev_bd;
        struct resource w1_res;
 
        wd = kzalloc(sizeof(*wd), GFP_KERNEL);
-       if (!wd)
-               goto no_mem;
+       if (!wd) {
+               pr_warn("xtalk:%x bridge create out of memory\n", widget);
+               return;
+       }
 
        snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
                 IP30_SWIN_BASE(widget));
@@ -56,24 +59,35 @@ static void bridge_platform_create(int widget, int masterwid)
        w1_res.end = w1_res.start + 3;
        w1_res.flags = IORESOURCE_MEM;
 
-       pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
-       if (!pdev) {
-               kfree(wd);
-               goto no_mem;
+       pdev_wd = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
+       if (!pdev_wd) {
+               pr_warn("xtalk:%x bridge create out of memory\n", widget);
+               goto err_kfree_wd;
+       }
+       if (platform_device_add_resources(pdev_wd, &w1_res, 1)) {
+               pr_warn("xtalk:%x bridge failed to add platform resources.\n", widget);
+               goto err_put_pdev_wd;
+       }
+       if (platform_device_add_data(pdev_wd, wd, sizeof(*wd))) {
+               pr_warn("xtalk:%x bridge failed to add platform data.\n", widget);
+               goto err_put_pdev_wd;
+       }
+       if (platform_device_add(pdev_wd)) {
+               pr_warn("xtalk:%x bridge failed to add platform device.\n", widget);
+               goto err_put_pdev_wd;
        }
-       platform_device_add_resources(pdev, &w1_res, 1);
-       platform_device_add_data(pdev, wd, sizeof(*wd));
        /* platform_device_add_data() duplicates the data */
        kfree(wd);
-       platform_device_add(pdev);
 
        bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-       if (!bd)
-               goto no_mem;
-       pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
-       if (!pdev) {
-               kfree(bd);
-               goto no_mem;
+       if (!bd) {
+               pr_warn("xtalk:%x bridge create out of memory\n", widget);
+               goto err_unregister_pdev_wd;
+       }
+       pdev_bd = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
+       if (!pdev_bd) {
+               pr_warn("xtalk:%x bridge create out of memory\n", widget);
+               goto err_kfree_bd;
        }
 
        bd->bridge_addr = IP30_RAW_SWIN_BASE(widget);
@@ -93,15 +107,31 @@ static void bridge_platform_create(int widget, int masterwid)
        bd->io.flags    = IORESOURCE_IO;
        bd->io_offset   = IP30_SWIN_BASE(widget);
 
-       platform_device_add_data(pdev, bd, sizeof(*bd));
+       if (platform_device_add_data(pdev_bd, bd, sizeof(*bd))) {
+               pr_warn("xtalk:%x bridge failed to add platform data.\n", widget);
+               goto err_put_pdev_bd;
+       }
+       if (platform_device_add(pdev_bd)) {
+               pr_warn("xtalk:%x bridge failed to add platform device.\n", widget);
+               goto err_put_pdev_bd;
+       }
        /* platform_device_add_data() duplicates the data */
        kfree(bd);
-       platform_device_add(pdev);
        pr_info("xtalk:%x bridge widget\n", widget);
        return;
 
-no_mem:
-       pr_warn("xtalk:%x bridge create out of memory\n", widget);
+err_put_pdev_bd:
+       platform_device_put(pdev_bd);
+err_kfree_bd:
+       kfree(bd);
+err_unregister_pdev_wd:
+       platform_device_unregister(pdev_wd);
+       return;
+err_put_pdev_wd:
+       platform_device_put(pdev_wd);
+err_kfree_wd:
+       kfree(wd);
+       return;
 }
 
 static unsigned int __init xbow_widget_active(s8 wid)
index 86f49c4..2f08ad2 100644 (file)
@@ -262,12 +262,6 @@ void __init arch_init_irq(void)
        __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
        __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
 
-       /*
-        * Note that the timer interrupts are also mapped, but this is
-        * done in sb1250_time_init().  Also, the profiling driver
-        * does its own management of IP7.
-        */
-
        /* Enable necessary IPs, disable the rest */
        change_c0_status(ST0_IM, imask);
 }
index 9aede24..a98940e 100644 (file)
@@ -224,8 +224,18 @@ config MLONGCALLS
          Enabling this option will probably slow down your kernel.
 
 config 64BIT
-       def_bool "$(ARCH)" = "parisc64"
+       def_bool y if "$(ARCH)" = "parisc64"
+       bool "64-bit kernel" if "$(ARCH)" = "parisc"
        depends on PA8X00
+       help
+         Enable this if you want to support 64bit kernel on PA-RISC platform.
+
+         At the moment, only people willing to use more than 2GB of RAM,
+         or having a 64bit-only capable PA-RISC machine should say Y here.
+
+         Since there is no 64bit userland on PA-RISC, there is no point to
+         enable this option otherwise. The 64bit kernel is significantly bigger
+         and slower than the 32bit one.
 
 choice
        prompt "Kernel page size"
index fbb882c..b05055f 100644 (file)
@@ -480,7 +480,7 @@ static void execute_on_irq_stack(void *func, unsigned long param1)
        *irq_stack_in_use = 1;
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 void do_softirq_own_stack(void)
 {
        execute_on_irq_stack(__do_softirq, 0);
index 398e0b5..ed6db13 100644 (file)
@@ -83,6 +83,8 @@ enum {
        FW_FEATURE_POWERNV_ALWAYS = 0,
        FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
        FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
+       FW_FEATURE_NATIVE_POSSIBLE = 0,
+       FW_FEATURE_NATIVE_ALWAYS = 0,
        FW_FEATURE_POSSIBLE =
 #ifdef CONFIG_PPC_PSERIES
                FW_FEATURE_PSERIES_POSSIBLE |
@@ -93,6 +95,9 @@ enum {
 #ifdef CONFIG_PPC_PS3
                FW_FEATURE_PS3_POSSIBLE |
 #endif
+#ifdef CONFIG_PPC_HASH_MMU_NATIVE
+               FW_FEATURE_NATIVE_ALWAYS |
+#endif
                0,
        FW_FEATURE_ALWAYS =
 #ifdef CONFIG_PPC_PSERIES
@@ -104,6 +109,9 @@ enum {
 #ifdef CONFIG_PPC_PS3
                FW_FEATURE_PS3_ALWAYS &
 #endif
+#ifdef CONFIG_PPC_HASH_MMU_NATIVE
+               FW_FEATURE_NATIVE_ALWAYS &
+#endif
                FW_FEATURE_POSSIBLE,
 
 #else /* CONFIG_PPC64 */
index 26ede09..9835518 100644 (file)
@@ -113,7 +113,14 @@ static inline void __hard_RI_enable(void)
 
 static inline notrace unsigned long irq_soft_mask_return(void)
 {
-       return READ_ONCE(local_paca->irq_soft_mask);
+       unsigned long flags;
+
+       asm volatile(
+               "lbz %0,%1(13)"
+               : "=r" (flags)
+               : "i" (offsetof(struct paca_struct, irq_soft_mask)));
+
+       return flags;
 }
 
 /*
@@ -140,24 +147,46 @@ static inline notrace void irq_soft_mask_set(unsigned long mask)
        if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
                WARN_ON(mask && !(mask & IRQS_DISABLED));
 
-       WRITE_ONCE(local_paca->irq_soft_mask, mask);
-       barrier();
+       asm volatile(
+               "stb %0,%1(13)"
+               :
+               : "r" (mask),
+                 "i" (offsetof(struct paca_struct, irq_soft_mask))
+               : "memory");
 }
 
 static inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask)
 {
-       unsigned long flags = irq_soft_mask_return();
+       unsigned long flags;
 
-       irq_soft_mask_set(mask);
+#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
+       WARN_ON(mask && !(mask & IRQS_DISABLED));
+#endif
+
+       asm volatile(
+               "lbz %0,%1(13); stb %2,%1(13)"
+               : "=&r" (flags)
+               : "i" (offsetof(struct paca_struct, irq_soft_mask)),
+                 "r" (mask)
+               : "memory");
 
        return flags;
 }
 
 static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
 {
-       unsigned long flags = irq_soft_mask_return();
+       unsigned long flags, tmp;
+
+       asm volatile(
+               "lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)"
+               : "=&r" (flags), "=r" (tmp)
+               : "i" (offsetof(struct paca_struct, irq_soft_mask)),
+                 "r" (mask)
+               : "memory");
 
-       irq_soft_mask_set(flags | mask);
+#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
+       WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED));
+#endif
 
        return flags;
 }
@@ -282,7 +311,8 @@ static inline bool pmi_irq_pending(void)
        flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED);            \
        local_paca->irq_happened |= PACA_IRQ_HARD_DIS;                  \
        if (!arch_irqs_disabled_flags(flags)) {                         \
-               WRITE_ONCE(local_paca->saved_r1, current_stack_pointer);\
+               asm volatile("std%X0 %1,%0" : "=m" (local_paca->saved_r1) \
+                                           : "r" (current_stack_pointer)); \
                trace_hardirqs_off();                                   \
        }                                                               \
 } while(0)
index 0f17268..9ede61a 100644 (file)
@@ -199,7 +199,7 @@ static inline void check_stack_overflow(unsigned long sp)
        }
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 static __always_inline void call_do_softirq(const void *sp)
 {
        /* Temporarily switch r1 to sp, call __do_softirq() then restore r1. */
@@ -335,7 +335,7 @@ void *mcheckirq_ctx[NR_CPUS] __read_mostly;
 void *softirq_ctx[NR_CPUS] __read_mostly;
 void *hardirq_ctx[NR_CPUS] __read_mostly;
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 void do_softirq_own_stack(void)
 {
        call_do_softirq(softirq_ctx[smp_processor_id()]);
index 433965b..855b598 100644 (file)
@@ -245,6 +245,15 @@ static int __init pcibios_init(void)
 
        printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
+#ifdef CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
+       /*
+        * Enable PCI domains in /proc when PCI bus numbers are not unique
+        * across all PCI domains to prevent conflicts. And keep PCI domain 0
+        * backward compatible in /proc for video cards.
+        */
+       pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);
+#endif
+
        if (pci_has_flag(PCI_REASSIGN_ALL_BUS))
                pci_assign_all_buses = 1;
 
index 9a434d4..6ce95dd 100644 (file)
@@ -109,8 +109,12 @@ __enter_rtas:
         * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
         * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
         * MSR[S] is set, it will remain when entering RTAS.
+        * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
+        * from the saved MSR value and insert into the value RTAS will use.
         */
+       extrdi  r0, r6, 1, 63 - MSR_HV_LG
        LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
+       insrdi  r6, r0, 1, 63 - MSR_HV_LG
 
        li      r0,0
        mtmsrd  r0,1                    /* disable RI before using SRR0/1 */
index cb33588..6c1db3b 100644 (file)
@@ -18,6 +18,7 @@
        .p2align        3
 #define __SYSCALL(nr, entry)   .8byte entry
 #else
+       .p2align        2
 #define __SYSCALL(nr, entry)   .long entry
 #endif
 
index 6982741..e712f80 100644 (file)
@@ -937,15 +937,6 @@ pmd_t radix__pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long addre
        pmd = *pmdp;
        pmd_clear(pmdp);
 
-       /*
-        * pmdp collapse_flush need to ensure that there are no parallel gup
-        * walk after this call. This is needed so that we can have stable
-        * page ref count when collapsing a page. We don't allow a collapse page
-        * if we have gup taken on the page. We can ensure that by sending IPI
-        * because gup walk happens with IRQ disabled.
-        */
-       serialize_against_pte_lookup(vma->vm_mm);
-
        radix__flush_tlb_collapsed_pmd(vma->vm_mm, address);
 
        return pmd;
index 20f6ed8..2f83855 100644 (file)
@@ -124,9 +124,6 @@ struct papr_scm_priv {
 
        /* The bits which needs to be overridden */
        u64 health_bitmap_inject_mask;
-
-       /* array to have event_code and stat_id mappings */
-       u8 *nvdimm_events_map;
 };
 
 static int papr_scm_pmem_flush(struct nd_region *nd_region,
@@ -350,6 +347,25 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p,
 #ifdef CONFIG_PERF_EVENTS
 #define to_nvdimm_pmu(_pmu)    container_of(_pmu, struct nvdimm_pmu, pmu)
 
+static const char * const nvdimm_events_map[] = {
+       [1] = "CtlResCt",
+       [2] = "CtlResTm",
+       [3] = "PonSecs ",
+       [4] = "MemLife ",
+       [5] = "CritRscU",
+       [6] = "HostLCnt",
+       [7] = "HostSCnt",
+       [8] = "HostSDur",
+       [9] = "HostLDur",
+       [10] = "MedRCnt ",
+       [11] = "MedWCnt ",
+       [12] = "MedRDur ",
+       [13] = "MedWDur ",
+       [14] = "CchRHCnt",
+       [15] = "CchWHCnt",
+       [16] = "FastWCnt",
+};
+
 static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count)
 {
        struct papr_scm_perf_stat *stat;
@@ -357,11 +373,15 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev,
        struct papr_scm_priv *p = dev_get_drvdata(dev);
        int rc, size;
 
+       /* Invalid eventcode */
+       if (event->attr.config == 0 || event->attr.config >= ARRAY_SIZE(nvdimm_events_map))
+               return -EINVAL;
+
        /* Allocate request buffer enough to hold single performance stat */
        size = sizeof(struct papr_scm_perf_stats) +
                sizeof(struct papr_scm_perf_stat);
 
-       if (!p || !p->nvdimm_events_map)
+       if (!p)
                return -EINVAL;
 
        stats = kzalloc(size, GFP_KERNEL);
@@ -370,7 +390,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev,
 
        stat = &stats->scm_statistic[0];
        memcpy(&stat->stat_id,
-              &p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)],
+              nvdimm_events_map[event->attr.config],
                sizeof(stat->stat_id));
        stat->stat_val = 0;
 
@@ -458,56 +478,6 @@ static void papr_scm_pmu_del(struct perf_event *event, int flags)
        papr_scm_pmu_read(event);
 }
 
-static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu *nd_pmu)
-{
-       struct papr_scm_perf_stat *stat;
-       struct papr_scm_perf_stats *stats;
-       u32 available_events;
-       int index, rc = 0;
-
-       if (!p->stat_buffer_len)
-               return -ENOENT;
-
-       available_events = (p->stat_buffer_len  - sizeof(struct papr_scm_perf_stats))
-                       / sizeof(struct papr_scm_perf_stat);
-       if (available_events == 0)
-               return -EOPNOTSUPP;
-
-       /* Allocate the buffer for phyp where stats are written */
-       stats = kzalloc(p->stat_buffer_len, GFP_KERNEL);
-       if (!stats) {
-               rc = -ENOMEM;
-               return rc;
-       }
-
-       /* Called to get list of events supported */
-       rc = drc_pmem_query_stats(p, stats, 0);
-       if (rc)
-               goto out;
-
-       /*
-        * Allocate memory and populate nvdimm_event_map.
-        * Allocate an extra element for NULL entry
-        */
-       p->nvdimm_events_map = kcalloc(available_events + 1,
-                                      sizeof(stat->stat_id),
-                                      GFP_KERNEL);
-       if (!p->nvdimm_events_map) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       /* Copy all stat_ids to event map */
-       for (index = 0, stat = stats->scm_statistic;
-            index < available_events; index++, ++stat) {
-               memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)],
-                      &stat->stat_id, sizeof(stat->stat_id));
-       }
-out:
-       kfree(stats);
-       return rc;
-}
-
 static void papr_scm_pmu_register(struct papr_scm_priv *p)
 {
        struct nvdimm_pmu *nd_pmu;
@@ -519,9 +489,10 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
                goto pmu_err_print;
        }
 
-       rc = papr_scm_pmu_check_events(p, nd_pmu);
-       if (rc)
+       if (!p->stat_buffer_len) {
+               rc = -ENOENT;
                goto pmu_check_events_err;
+       }
 
        nd_pmu->pmu.task_ctx_nr = perf_invalid_context;
        nd_pmu->pmu.name = nvdimm_name(p->nvdimm);
@@ -539,7 +510,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
 
        rc = register_nvdimm_pmu(nd_pmu, p->pdev);
        if (rc)
-               goto pmu_register_err;
+               goto pmu_check_events_err;
 
        /*
         * Set archdata.priv value to nvdimm_pmu structure, to handle the
@@ -548,8 +519,6 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
        p->pdev->archdata.priv = nd_pmu;
        return;
 
-pmu_register_err:
-       kfree(p->nvdimm_events_map);
 pmu_check_events_err:
        kfree(nd_pmu);
 pmu_err_print:
@@ -1560,7 +1529,6 @@ static int papr_scm_remove(struct platform_device *pdev)
                unregister_nvdimm_pmu(pdev->archdata.priv);
 
        pdev->archdata.priv = NULL;
-       kfree(p->nvdimm_events_map);
        kfree(p->bus_desc.provider_name);
        kfree(p);
 
index 52aaa28..f4b5b5a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <asm/hvcall.h>
+#include <asm/machdep.h>
 
 #include "plpks.h"
 
@@ -457,4 +458,4 @@ static __init int pseries_plpks_init(void)
 
        return rc;
 }
-arch_initcall(pseries_plpks_init);
+machine_arch_initcall(pseries, pseries_plpks_init);
index ed66c31..59d1888 100644 (file)
@@ -386,6 +386,7 @@ config RISCV_ISA_C
 config RISCV_ISA_SVPBMT
        bool "SVPBMT extension support"
        depends on 64BIT && MMU
+       depends on !XIP_KERNEL
        select RISCV_ALTERNATIVE
        default y
        help
index 6850e93..f3623df 100644 (file)
@@ -46,7 +46,7 @@ config ERRATA_THEAD
 
 config ERRATA_THEAD_PBMT
        bool "Apply T-Head memory type errata"
-       depends on ERRATA_THEAD && 64BIT
+       depends on ERRATA_THEAD && 64BIT && MMU
        select RISCV_ALTERNATIVE_EARLY
        default y
        help
@@ -57,7 +57,7 @@ config ERRATA_THEAD_PBMT
 
 config ERRATA_THEAD_CMO
        bool "Apply T-Head cache management errata"
-       depends on ERRATA_THEAD
+       depends on ERRATA_THEAD && MMU
        select RISCV_DMA_NONCOHERENT
        default y
        help
index 7449334..6d9d455 100644 (file)
                ranges;
 
                cctrllr: cache-controller@2010000 {
-                       compatible = "sifive,fu540-c000-ccache", "cache";
+                       compatible = "microchip,mpfs-ccache", "sifive,fu540-c000-ccache", "cache";
                        reg = <0x0 0x2010000 0x0 0x1000>;
                        cache-block-size = <64>;
                        cache-level = <2>;
index 202c83f..96648c1 100644 (file)
@@ -37,6 +37,7 @@ static bool errata_probe_cmo(unsigned int stage,
        if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
                return false;
 
+       riscv_cbom_block_size = L1_CACHE_BYTES;
        riscv_noncoherent_supported();
        return true;
 #else
index a60acae..273ece6 100644 (file)
@@ -42,6 +42,11 @@ void flush_icache_mm(struct mm_struct *mm, bool local);
 
 #endif /* CONFIG_SMP */
 
+/*
+ * The T-Head CMO errata internally probe the CBOM block size, but otherwise
+ * don't depend on Zicbom.
+ */
+extern unsigned int riscv_cbom_block_size;
 #ifdef CONFIG_RISCV_ISA_ZICBOM
 void riscv_init_cbom_blocksize(void);
 #else
index 83d6d4d..26a446a 100644 (file)
@@ -33,4 +33,16 @@ void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
                                     u32 type, u64 flags);
 const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(unsigned long extid);
 
+#ifdef CONFIG_RISCV_SBI_V01
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01;
+#endif
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_base;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_time;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
+
 #endif /* __RISCV_KVM_VCPU_SBI_H__ */
index 95ef6e2..2dfc463 100644 (file)
@@ -296,8 +296,8 @@ void __init setup_arch(char **cmdline_p)
        setup_smp();
 #endif
 
-       riscv_fill_hwcap();
        riscv_init_cbom_blocksize();
+       riscv_fill_hwcap();
        apply_boot_alternatives();
 }
 
index 5a2de6b..5c59112 100644 (file)
@@ -124,6 +124,8 @@ SYSCALL_DEFINE0(rt_sigreturn)
        if (restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
+       regs->cause = -1UL;
+
        return regs->a0;
 
 badframe:
index d45e7da..f96991d 100644 (file)
@@ -32,23 +32,13 @@ static int kvm_linux_err_map_sbi(int err)
        };
 }
 
-#ifdef CONFIG_RISCV_SBI_V01
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01;
-#else
+#ifndef CONFIG_RISCV_SBI_V01
 static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = {
        .extid_start = -1UL,
        .extid_end = -1UL,
        .handler = NULL,
 };
 #endif
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_base;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_time;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
-extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
 
 static const struct kvm_vcpu_sbi_extension *sbi_ext[] = {
        &vcpu_sbi_ext_v01,
index 16f50c4..185f238 100644 (file)
@@ -299,7 +299,6 @@ static void kvm_riscv_vcpu_update_timedelta(struct kvm_vcpu *vcpu)
 
 void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu_csr *csr;
        struct kvm_vcpu_timer *t = &vcpu->arch.timer;
 
        kvm_riscv_vcpu_update_timedelta(vcpu);
@@ -307,7 +306,6 @@ void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
        if (!t->sstc_enabled)
                return;
 
-       csr = &vcpu->arch.guest_csr;
 #if defined(CONFIG_32BIT)
        csr_write(CSR_VSTIMECMP, (u32)t->next_cycles);
        csr_write(CSR_VSTIMECMPH, (u32)(t->next_cycles >> 32));
@@ -324,13 +322,11 @@ void kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
 
 void kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu_csr *csr;
        struct kvm_vcpu_timer *t = &vcpu->arch.timer;
 
        if (!t->sstc_enabled)
                return;
 
-       csr = &vcpu->arch.guest_csr;
        t = &vcpu->arch.timer;
 #if defined(CONFIG_32BIT)
        t->next_cycles = csr_read(CSR_VSTIMECMP);
index cd22253..e3f9bdf 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/of_device.h>
 #include <asm/cacheflush.h>
 
-static unsigned int riscv_cbom_block_size = L1_CACHE_BYTES;
+unsigned int riscv_cbom_block_size;
 static bool noncoherent_supported;
 
 void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
@@ -79,38 +79,41 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
 void riscv_init_cbom_blocksize(void)
 {
        struct device_node *node;
+       unsigned long cbom_hartid;
+       u32 val, probed_block_size;
        int ret;
-       u32 val;
 
+       probed_block_size = 0;
        for_each_of_cpu_node(node) {
                unsigned long hartid;
-               int cbom_hartid;
 
                ret = riscv_of_processor_hartid(node, &hartid);
                if (ret)
                        continue;
 
-               if (hartid < 0)
-                       continue;
-
                /* set block-size for cbom extension if available */
                ret = of_property_read_u32(node, "riscv,cbom-block-size", &val);
                if (ret)
                        continue;
 
-               if (!riscv_cbom_block_size) {
-                       riscv_cbom_block_size = val;
+               if (!probed_block_size) {
+                       probed_block_size = val;
                        cbom_hartid = hartid;
                } else {
-                       if (riscv_cbom_block_size != val)
-                               pr_warn("cbom-block-size mismatched between harts %d and %lu\n",
+                       if (probed_block_size != val)
+                               pr_warn("cbom-block-size mismatched between harts %lu and %lu\n",
                                        cbom_hartid, hartid);
                }
        }
+
+       if (probed_block_size)
+               riscv_cbom_block_size = probed_block_size;
 }
 #endif
 
 void riscv_noncoherent_supported(void)
 {
+       WARN(!riscv_cbom_block_size,
+            "Non-coherent DMA support enabled without a block size\n");
        noncoherent_supported = true;
 }
index 5e49e4b..86c5661 100644 (file)
@@ -118,10 +118,10 @@ static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask,
        if (!numpages)
                return 0;
 
-       mmap_read_lock(&init_mm);
+       mmap_write_lock(&init_mm);
        ret =  walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL,
                                     &masks);
-       mmap_read_unlock(&init_mm);
+       mmap_write_unlock(&init_mm);
 
        flush_tlb_kernel_range(start, end);
 
index f6dfde5..2a82700 100644 (file)
@@ -40,8 +40,6 @@ CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
-CONFIG_USERFAULTFD=y
-# CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_LIVEPATCH=y
 CONFIG_MARCH_ZEC12=y
@@ -74,6 +72,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODULE_UNLOAD_TAINT_TRACKING=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_MODULE_SIG_SHA256=y
@@ -93,6 +92,10 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_IOSCHED_BFQ=y
 CONFIG_BFQ_GROUP_IOSCHED=y
 CONFIG_BINFMT_MISC=m
+CONFIG_ZSWAP=y
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_SLUB_STATS=y
+# CONFIG_COMPAT_BRK is not set
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
@@ -102,14 +105,12 @@ CONFIG_CMA_DEBUGFS=y
 CONFIG_CMA_SYSFS=y
 CONFIG_CMA_AREAS=7
 CONFIG_MEM_SOFT_DIRTY=y
-CONFIG_ZSWAP=y
-CONFIG_ZSMALLOC=y
-CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
 CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PERCPU_STATS=y
 CONFIG_GUP_TEST=y
 CONFIG_ANON_VMA_NAME=y
+CONFIG_USERFAULTFD=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
@@ -167,6 +168,7 @@ CONFIG_BRIDGE_NETFILTER=m
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
@@ -493,7 +495,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_ASIX is not set
 # CONFIG_NET_VENDOR_ATHEROS is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_BROCADE is not set
 # CONFIG_NET_VENDOR_CADENCE is not set
 # CONFIG_NET_VENDOR_CAVIUM is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
@@ -509,7 +510,7 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_GOOGLE is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MICROSOFT is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_LITEX is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
@@ -518,16 +519,18 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MICROSOFT is not set
 # CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NI is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_NETERION is not set
 # CONFIG_NET_VENDOR_NETRONOME is not set
-# CONFIG_NET_VENDOR_NI is not set
 # CONFIG_NET_VENDOR_NVIDIA is not set
 # CONFIG_NET_VENDOR_OKI is not set
 # CONFIG_NET_VENDOR_PACKET_ENGINES is not set
 # CONFIG_NET_VENDOR_PENSANDO is not set
 # CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RDC is not set
 # CONFIG_NET_VENDOR_REALTEK is not set
@@ -535,9 +538,9 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SILAN is not set
 # CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_SOCIONEXT is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
@@ -570,6 +573,8 @@ CONFIG_VIRTIO_CONSOLE=m
 CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_RANDOM_TRUST_CPU is not set
+# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
 CONFIG_PPS=m
 # CONFIG_PTP_1588_CLOCK is not set
 # CONFIG_HWMON is not set
@@ -727,18 +732,26 @@ CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_BLAKE2S=m
+CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3=m
+CONFIG_CRYPTO_SHA3_256_S390=m
+CONFIG_CRYPTO_SHA3_512_S390=m
+CONFIG_CRYPTO_SM3_GENERIC=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -746,11 +759,14 @@ CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_CHACHA_S390=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_SM4=m
+CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_842=m
@@ -766,16 +782,6 @@ CONFIG_CRYPTO_STATS=y
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
-CONFIG_CRYPTO_SHA1_S390=m
-CONFIG_CRYPTO_SHA256_S390=m
-CONFIG_CRYPTO_SHA512_S390=m
-CONFIG_CRYPTO_SHA3_256_S390=m
-CONFIG_CRYPTO_SHA3_512_S390=m
-CONFIG_CRYPTO_DES_S390=m
-CONFIG_CRYPTO_AES_S390=m
-CONFIG_CRYPTO_CHACHA_S390=m
-CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CRYPTO_DEV_VIRTIO=m
 CONFIG_CORDIC=m
 CONFIG_CRYPTO_LIB_CURVE25519=m
@@ -797,6 +803,7 @@ CONFIG_HEADERS_INSTALL=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_ON=y
 CONFIG_PAGE_OWNER=y
 CONFIG_DEBUG_RODATA_TEST=y
 CONFIG_DEBUG_WX=y
@@ -808,8 +815,6 @@ CONFIG_DEBUG_OBJECTS_TIMERS=y
 CONFIG_DEBUG_OBJECTS_WORK=y
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
 CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
-CONFIG_SLUB_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_VM_PGFLAGS=y
index 706df3a..fb780e8 100644 (file)
@@ -38,8 +38,6 @@ CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_EXPERT=y
 # CONFIG_SYSFS_SYSCALL is not set
-CONFIG_USERFAULTFD=y
-# CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_LIVEPATCH=y
 CONFIG_MARCH_ZEC12=y
@@ -69,6 +67,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODULE_UNLOAD_TAINT_TRACKING=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_MODULE_SIG_SHA256=y
@@ -88,6 +87,9 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_IOSCHED_BFQ=y
 CONFIG_BFQ_GROUP_IOSCHED=y
 CONFIG_BINFMT_MISC=m
+CONFIG_ZSWAP=y
+CONFIG_ZSMALLOC_STAT=y
+# CONFIG_COMPAT_BRK is not set
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
@@ -95,13 +97,11 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CMA_SYSFS=y
 CONFIG_CMA_AREAS=7
 CONFIG_MEM_SOFT_DIRTY=y
-CONFIG_ZSWAP=y
-CONFIG_ZSMALLOC=y
-CONFIG_ZSMALLOC_STAT=y
 CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
 CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PERCPU_STATS=y
 CONFIG_ANON_VMA_NAME=y
+CONFIG_USERFAULTFD=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=m
@@ -159,6 +159,7 @@ CONFIG_BRIDGE_NETFILTER=m
 CONFIG_NETFILTER_NETLINK_HOOK=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
@@ -484,7 +485,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_ASIX is not set
 # CONFIG_NET_VENDOR_ATHEROS is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_BROCADE is not set
 # CONFIG_NET_VENDOR_CADENCE is not set
 # CONFIG_NET_VENDOR_CAVIUM is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
@@ -500,7 +500,7 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_GOOGLE is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MICROSOFT is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_LITEX is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
@@ -509,16 +509,18 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MICROSOFT is not set
 # CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NI is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_NETERION is not set
 # CONFIG_NET_VENDOR_NETRONOME is not set
-# CONFIG_NET_VENDOR_NI is not set
 # CONFIG_NET_VENDOR_NVIDIA is not set
 # CONFIG_NET_VENDOR_OKI is not set
 # CONFIG_NET_VENDOR_PACKET_ENGINES is not set
 # CONFIG_NET_VENDOR_PENSANDO is not set
 # CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RDC is not set
 # CONFIG_NET_VENDOR_REALTEK is not set
@@ -526,9 +528,9 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_ROCKER is not set
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SILAN is not set
 # CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_SOCIONEXT is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
@@ -561,6 +563,8 @@ CONFIG_VIRTIO_CONSOLE=m
 CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_RANDOM_TRUST_CPU is not set
+# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
 # CONFIG_PTP_1588_CLOCK is not set
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -713,18 +717,26 @@ CONFIG_CRYPTO_OFB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_HCTR2=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_BLAKE2S=m
+CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3=m
+CONFIG_CRYPTO_SHA3_256_S390=m
+CONFIG_CRYPTO_SHA3_512_S390=m
+CONFIG_CRYPTO_SM3_GENERIC=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_BLOWFISH=m
@@ -732,11 +744,14 @@ CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_CHACHA_S390=m
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_ARIA=m
 CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_SM4=m
+CONFIG_CRYPTO_SM4_GENERIC=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_842=m
@@ -752,16 +767,6 @@ CONFIG_CRYPTO_STATS=y
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
-CONFIG_CRYPTO_SHA1_S390=m
-CONFIG_CRYPTO_SHA256_S390=m
-CONFIG_CRYPTO_SHA512_S390=m
-CONFIG_CRYPTO_SHA3_256_S390=m
-CONFIG_CRYPTO_SHA3_512_S390=m
-CONFIG_CRYPTO_DES_S390=m
-CONFIG_CRYPTO_AES_S390=m
-CONFIG_CRYPTO_CHACHA_S390=m
-CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CRYPTO_DEV_VIRTIO=m
 CONFIG_CORDIC=m
 CONFIG_PRIME_NUMBERS=m
index f4976f6..a5576b8 100644 (file)
@@ -1,4 +1,3 @@
-# CONFIG_SWAP is not set
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BPF_SYSCALL=y
@@ -9,7 +8,6 @@ CONFIG_BPF_SYSCALL=y
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-# CONFIG_COMPAT_BRK is not set
 CONFIG_MARCH_ZEC12=y
 CONFIG_TUNE_ZEC12=y
 # CONFIG_COMPAT is not set
@@ -28,6 +26,8 @@ CONFIG_CRASH_DUMP=y
 # CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
 CONFIG_PARTITION_ADVANCED=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SWAP is not set
+# CONFIG_COMPAT_BRK is not set
 # CONFIG_COMPACTION is not set
 # CONFIG_MIGRATION is not set
 CONFIG_NET=y
@@ -53,10 +53,12 @@ CONFIG_ZFCP=y
 # CONFIG_HVC_IUCV is not set
 # CONFIG_HW_RANDOM_S390 is not set
 # CONFIG_HMC_DRV is not set
+# CONFIG_S390_UV_UAPI is not set
 # CONFIG_S390_TAPE is not set
 # CONFIG_VMCP is not set
 # CONFIG_MONWRITER is not set
 # CONFIG_S390_VMUR is not set
+# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
 # CONFIG_HID is not set
 # CONFIG_VIRTIO_MENU is not set
 # CONFIG_VHOST_MENU is not set
index f22beda..ccdbccf 100644 (file)
@@ -28,9 +28,11 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 static inline int prepare_hugepage_range(struct file *file,
                        unsigned long addr, unsigned long len)
 {
-       if (len & ~HPAGE_MASK)
+       struct hstate *h = hstate_file(file);
+
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
-       if (addr & ~HPAGE_MASK)
+       if (addr & ~huge_page_mask(h))
                return -EINVAL;
        return 0;
 }
index f39092e..b1e98a9 100644 (file)
@@ -1038,16 +1038,11 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
 #define __KVM_HAVE_ARCH_VM_FREE
 void kvm_arch_free_vm(struct kvm *kvm);
 
-#ifdef CONFIG_VFIO_PCI_ZDEV_KVM
-int kvm_s390_pci_register_kvm(struct zpci_dev *zdev, struct kvm *kvm);
-void kvm_s390_pci_unregister_kvm(struct zpci_dev *zdev);
-#else
-static inline int kvm_s390_pci_register_kvm(struct zpci_dev *dev,
-                                           struct kvm *kvm)
-{
-       return -EPERM;
-}
-static inline void kvm_s390_pci_unregister_kvm(struct zpci_dev *dev) {}
-#endif
+struct zpci_kvm_hook {
+       int (*kvm_register)(void *opaque, struct kvm *kvm);
+       void (*kvm_unregister)(void *opaque);
+};
+
+extern struct zpci_kvm_hook zpci_kvm_hook;
 
 #endif
index af68d6c..1ac5115 100644 (file)
@@ -5,7 +5,7 @@
 #include <asm/lowcore.h>
 #include <asm/stacktrace.h>
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 static inline void do_softirq_own_stack(void)
 {
        call_on_stack(0, S390_lowcore.async_stack, void, __do_softirq);
index 60ac66a..31cb9b0 100644 (file)
@@ -64,7 +64,7 @@ static inline unsigned long nmi_get_mcesa_size(void)
  * structure. The structure is required for machine check happening
  * early in the boot process.
  */
-static struct mcesa boot_mcesa __initdata __aligned(MCESA_MAX_SIZE);
+static struct mcesa boot_mcesa __aligned(MCESA_MAX_SIZE);
 
 void __init nmi_alloc_mcesa_early(u64 *mcesad)
 {
index ed4fbbb..bbd4bde 100644 (file)
@@ -479,6 +479,7 @@ static void __init setup_lowcore_dat_off(void)
        put_abs_lowcore(restart_data, lc->restart_data);
        put_abs_lowcore(restart_source, lc->restart_source);
        put_abs_lowcore(restart_psw, lc->restart_psw);
+       put_abs_lowcore(mcesad, lc->mcesad);
 
        mcck_stack = (unsigned long)memblock_alloc(THREAD_SIZE, THREAD_SIZE);
        if (!mcck_stack)
@@ -507,8 +508,8 @@ static void __init setup_lowcore_dat_on(void)
        S390_lowcore.svc_new_psw.mask |= PSW_MASK_DAT;
        S390_lowcore.program_new_psw.mask |= PSW_MASK_DAT;
        S390_lowcore.io_new_psw.mask |= PSW_MASK_DAT;
-       __ctl_store(S390_lowcore.cregs_save_area, 0, 15);
        __ctl_set_bit(0, 28);
+       __ctl_store(S390_lowcore.cregs_save_area, 0, 15);
        put_abs_lowcore(restart_flags, RESTART_FLAG_CTLREGS);
        put_abs_lowcore(program_new_psw, lc->program_new_psw);
        for (cr = 0; cr < ARRAY_SIZE(lc->cregs_save_area); cr++)
index 2e526f1..5ea3830 100644 (file)
@@ -131,6 +131,7 @@ SECTIONS
        /*
         * Table with the patch locations to undo expolines
        */
+       . = ALIGN(4);
        .nospec_call_table : {
                __nospec_call_start = . ;
                *(.s390_indirect*)
index 082ec5f..0243b6e 100644 (file)
@@ -489,6 +489,8 @@ enum prot_type {
        PROT_TYPE_ALC  = 2,
        PROT_TYPE_DAT  = 3,
        PROT_TYPE_IEP  = 4,
+       /* Dummy value for passing an initialized value when code != PGM_PROTECTION */
+       PROT_NONE,
 };
 
 static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, u8 ar,
@@ -504,6 +506,10 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva,
        switch (code) {
        case PGM_PROTECTION:
                switch (prot) {
+               case PROT_NONE:
+                       /* We should never get here, acts like termination */
+                       WARN_ON_ONCE(1);
+                       break;
                case PROT_TYPE_IEP:
                        tec->b61 = 1;
                        fallthrough;
@@ -968,8 +974,10 @@ static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
                                return rc;
                } else {
                        gpa = kvm_s390_real_to_abs(vcpu, ga);
-                       if (kvm_is_error_gpa(vcpu->kvm, gpa))
+                       if (kvm_is_error_gpa(vcpu->kvm, gpa)) {
                                rc = PGM_ADDRESSING;
+                               prot = PROT_NONE;
+                       }
                }
                if (rc)
                        return trans_exc(vcpu, rc, ga, ar, mode, prot);
@@ -1112,8 +1120,6 @@ int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
                if (rc == PGM_PROTECTION && try_storage_prot_override)
                        rc = access_guest_page_with_key(vcpu->kvm, mode, gpas[idx],
                                                        data, fragment_len, PAGE_SPO_ACC);
-               if (rc == PGM_PROTECTION)
-                       prot = PROT_TYPE_KEYC;
                if (rc)
                        break;
                len -= fragment_len;
@@ -1123,6 +1129,10 @@ int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
        if (rc > 0) {
                bool terminate = (mode == GACC_STORE) && (idx > 0);
 
+               if (rc == PGM_PROTECTION)
+                       prot = PROT_TYPE_KEYC;
+               else
+                       prot = PROT_NONE;
                rc = trans_exc_ending(vcpu, rc, ga, ar, mode, prot, terminate);
        }
 out_unlock:
index b9c944b..ab569fa 100644 (file)
@@ -3324,7 +3324,7 @@ static void aen_host_forward(unsigned long si)
        if (gaite->count == 0)
                return;
        if (gaite->aisb != 0)
-               set_bit_inv(gaite->aisbo, (unsigned long *)gaite->aisb);
+               set_bit_inv(gaite->aisbo, phys_to_virt(gaite->aisb));
 
        kvm = kvm_s390_pci_si_to_kvm(aift, si);
        if (!kvm)
index edfd4bb..b7ef0b7 100644 (file)
@@ -505,7 +505,7 @@ int kvm_arch_init(void *opaque)
                goto out;
        }
 
-       if (kvm_s390_pci_interp_allowed()) {
+       if (IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM)) {
                rc = kvm_s390_pci_init();
                if (rc) {
                        pr_err("Unable to allocate AIFT for PCI\n");
@@ -527,7 +527,7 @@ out:
 void kvm_arch_exit(void)
 {
        kvm_s390_gib_destroy();
-       if (kvm_s390_pci_interp_allowed())
+       if (IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM))
                kvm_s390_pci_exit();
        debug_unregister(kvm_s390_dbf);
        debug_unregister(kvm_s390_dbf_uv);
index 4946fb7..c50c164 100644 (file)
@@ -58,7 +58,7 @@ static int zpci_setup_aipb(u8 nisc)
        if (!zpci_aipb)
                return -ENOMEM;
 
-       aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, 0);
+       aift->sbv = airq_iv_create(ZPCI_NR_DEVICES, AIRQ_IV_ALLOC, NULL);
        if (!aift->sbv) {
                rc = -ENOMEM;
                goto free_aipb;
@@ -71,7 +71,7 @@ static int zpci_setup_aipb(u8 nisc)
                rc = -ENOMEM;
                goto free_sbv;
        }
-       aift->gait = (struct zpci_gaite *)page_to_phys(page);
+       aift->gait = (struct zpci_gaite *)page_to_virt(page);
 
        zpci_aipb->aipb.faisb = virt_to_phys(aift->sbv->vector);
        zpci_aipb->aipb.gait = virt_to_phys(aift->gait);
@@ -373,7 +373,7 @@ static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force)
                gaite->gisc = 0;
                gaite->aisbo = 0;
                gaite->gisa = 0;
-               aift->kzdev[zdev->aisb] = 0;
+               aift->kzdev[zdev->aisb] = NULL;
                /* Clear zdev info */
                airq_iv_free_bit(aift->sbv, zdev->aisb);
                airq_iv_release(zdev->aibv);
@@ -431,8 +431,9 @@ static void kvm_s390_pci_dev_release(struct zpci_dev *zdev)
  * available, enable them and let userspace indicate whether or not they will
  * be used (specify SHM bit to disable).
  */
-int kvm_s390_pci_register_kvm(struct zpci_dev *zdev, struct kvm *kvm)
+static int kvm_s390_pci_register_kvm(void *opaque, struct kvm *kvm)
 {
+       struct zpci_dev *zdev = opaque;
        int rc;
 
        if (!zdev)
@@ -510,10 +511,10 @@ err:
        kvm_put_kvm(kvm);
        return rc;
 }
-EXPORT_SYMBOL_GPL(kvm_s390_pci_register_kvm);
 
-void kvm_s390_pci_unregister_kvm(struct zpci_dev *zdev)
+static void kvm_s390_pci_unregister_kvm(void *opaque)
 {
+       struct zpci_dev *zdev = opaque;
        struct kvm *kvm;
 
        if (!zdev)
@@ -566,7 +567,6 @@ out:
 
        kvm_put_kvm(kvm);
 }
-EXPORT_SYMBOL_GPL(kvm_s390_pci_unregister_kvm);
 
 void kvm_s390_pci_init_list(struct kvm *kvm)
 {
@@ -672,6 +672,12 @@ out:
 
 int kvm_s390_pci_init(void)
 {
+       zpci_kvm_hook.kvm_register = kvm_s390_pci_register_kvm;
+       zpci_kvm_hook.kvm_unregister = kvm_s390_pci_unregister_kvm;
+
+       if (!kvm_s390_pci_interp_allowed())
+               return 0;
+
        aift = kzalloc(sizeof(struct zpci_aift), GFP_KERNEL);
        if (!aift)
                return -ENOMEM;
@@ -684,6 +690,12 @@ int kvm_s390_pci_init(void)
 
 void kvm_s390_pci_exit(void)
 {
+       zpci_kvm_hook.kvm_register = NULL;
+       zpci_kvm_hook.kvm_unregister = NULL;
+
+       if (!kvm_s390_pci_interp_allowed())
+               return;
+
        mutex_destroy(&aift->aift_lock);
 
        kfree(aift);
index 3a3606c..486d06e 100644 (file)
@@ -46,9 +46,9 @@ extern struct zpci_aift *aift;
 static inline struct kvm *kvm_s390_pci_si_to_kvm(struct zpci_aift *aift,
                                                 unsigned long si)
 {
-       if (!IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) || aift->kzdev == 0 ||
-           aift->kzdev[si] == 0)
-               return 0;
+       if (!IS_ENABLED(CONFIG_VFIO_PCI_ZDEV_KVM) || !aift->kzdev ||
+           !aift->kzdev[si])
+               return NULL;
        return aift->kzdev[si]->kvm;
 };
 
index 09b6e75..9ab6ca6 100644 (file)
@@ -421,8 +421,6 @@ retry:
        if (unlikely(!(vma->vm_flags & access)))
                goto out_up;
 
-       if (is_vm_hugetlb_page(vma))
-               address &= HPAGE_MASK;
        /*
         * If for any reason at all we couldn't handle the fault,
         * make sure we exit gracefully rather than endlessly redo
index bf557a1..5ae31ca 100644 (file)
@@ -5,5 +5,5 @@
 
 obj-$(CONFIG_PCI)      += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
                           pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
-                          pci_bus.o
+                          pci_bus.o pci_kvm_hook.o
 obj-$(CONFIG_PCI_IOV)  += pci_iov.o
diff --git a/arch/s390/pci/pci_kvm_hook.c b/arch/s390/pci/pci_kvm_hook.c
new file mode 100644 (file)
index 0000000..ff34baf
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * VFIO ZPCI devices support
+ *
+ * Copyright (C) IBM Corp. 2022.  All rights reserved.
+ *     Author(s): Pierre Morel <pmorel@linux.ibm.com>
+ */
+#include <linux/kvm_host.h>
+
+struct zpci_kvm_hook zpci_kvm_hook;
+EXPORT_SYMBOL_GPL(zpci_kvm_hook);
index 9092767..4e6835d 100644 (file)
@@ -149,7 +149,7 @@ void irq_ctx_exit(int cpu)
        hardirq_ctx[cpu] = NULL;
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 void do_softirq_own_stack(void)
 {
        struct thread_info *curctx;
index 41fa1be..72da2e1 100644 (file)
@@ -855,7 +855,7 @@ void __irq_entry handler_irq(int pil, struct pt_regs *regs)
        set_irq_regs(old_regs);
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 void do_softirq_own_stack(void)
 {
        void *orig_sp, *sp = softirq_stack[smp_processor_id()];
index f2fe63b..f1d4d67 100644 (file)
@@ -132,10 +132,18 @@ export LDS_ELF_FORMAT := $(ELF_FORMAT)
 # The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
+# Avoid binutils 2.39+ warnings by marking the stack non-executable and
+# ignorning warnings for the kallsyms sections.
+LDFLAGS_EXECSTACK = -z noexecstack
+ifeq ($(CONFIG_LD_IS_BFD),y)
+LDFLAGS_EXECSTACK += $(call ld-option,--no-warn-rwx-segments)
+endif
+
 LD_FLAGS_CMDLINE = $(foreach opt,$(KBUILD_LDFLAGS),-Wl,$(opt))
 
 # Used by link-vmlinux.sh which has special support for um link
 export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
+export LDFLAGS_vmlinux := $(LDFLAGS_EXECSTACK)
 
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
index 7452f70..7467153 100644 (file)
@@ -48,7 +48,8 @@ void show_stack(struct task_struct *task, unsigned long *stack,
                        break;
                if (i && ((i % STACKSLOTS_PER_LINE) == 0))
                        pr_cont("\n");
-               pr_cont(" %08lx", *stack++);
+               pr_cont(" %08lx", READ_ONCE_NOCHECK(*stack));
+               stack++;
        }
 
        printk("%sCall Trace:\n", loglvl);
index e0de60e..d9e023c 100644 (file)
@@ -33,7 +33,7 @@
 #include "um_arch.h"
 
 #define DEFAULT_COMMAND_LINE_ROOT "root=98:0"
-#define DEFAULT_COMMAND_LINE_CONSOLE "console=tty"
+#define DEFAULT_COMMAND_LINE_CONSOLE "console=tty0"
 
 /* Changed in add_arg and setup_arch, which run before SMP is started */
 static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
index cb98a05..c20d8cd 100644 (file)
@@ -2102,6 +2102,15 @@ static struct extra_reg intel_tnt_extra_regs[] __read_mostly = {
        EVENT_EXTRA_END
 };
 
+EVENT_ATTR_STR(mem-loads,      mem_ld_grt,     "event=0xd0,umask=0x5,ldlat=3");
+EVENT_ATTR_STR(mem-stores,     mem_st_grt,     "event=0xd0,umask=0x6");
+
+static struct attribute *grt_mem_attrs[] = {
+       EVENT_PTR(mem_ld_grt),
+       EVENT_PTR(mem_st_grt),
+       NULL
+};
+
 static struct extra_reg intel_grt_extra_regs[] __read_mostly = {
        /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
        INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
@@ -4052,8 +4061,9 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
                /* Disable guest PEBS if host PEBS is enabled. */
                arr[pebs_enable].guest = 0;
        } else {
-               /* Disable guest PEBS for cross-mapped PEBS counters. */
+               /* Disable guest PEBS thoroughly for cross-mapped PEBS counters. */
                arr[pebs_enable].guest &= ~kvm_pmu->host_cross_mapped_mask;
+               arr[global_ctrl].guest &= ~kvm_pmu->host_cross_mapped_mask;
                /* Set hw GLOBAL_CTRL bits for PEBS counter when it runs for guest */
                arr[global_ctrl].guest |= arr[pebs_enable].guest;
        }
@@ -5974,6 +5984,36 @@ __init int intel_pmu_init(void)
                name = "Tremont";
                break;
 
+       case INTEL_FAM6_ALDERLAKE_N:
+               x86_pmu.mid_ack = true;
+               memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, tnt_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+               hw_cache_event_ids[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = -1;
+
+               x86_pmu.event_constraints = intel_slm_event_constraints;
+               x86_pmu.pebs_constraints = intel_grt_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_grt_extra_regs;
+
+               x86_pmu.pebs_aliases = NULL;
+               x86_pmu.pebs_prec_dist = true;
+               x86_pmu.pebs_block = true;
+               x86_pmu.lbr_pt_coexist = true;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
+
+               intel_pmu_pebs_data_source_grt();
+               x86_pmu.pebs_latency_data = adl_latency_data_small;
+               x86_pmu.get_event_constraints = tnt_get_event_constraints;
+               x86_pmu.limit_period = spr_limit_period;
+               td_attr = tnt_events_attrs;
+               mem_attr = grt_mem_attrs;
+               extra_attr = nhm_format_attr;
+               pr_cont("Gracemont events, ");
+               name = "gracemont";
+               break;
+
        case INTEL_FAM6_WESTMERE:
        case INTEL_FAM6_WESTMERE_EP:
        case INTEL_FAM6_WESTMERE_EX:
@@ -6316,7 +6356,6 @@ __init int intel_pmu_init(void)
 
        case INTEL_FAM6_ALDERLAKE:
        case INTEL_FAM6_ALDERLAKE_L:
-       case INTEL_FAM6_ALDERLAKE_N:
        case INTEL_FAM6_RAPTORLAKE:
        case INTEL_FAM6_RAPTORLAKE_P:
                /*
index de1f55d..ac973c6 100644 (file)
@@ -110,13 +110,18 @@ void __init intel_pmu_pebs_data_source_skl(bool pmem)
        __intel_pmu_pebs_data_source_skl(pmem, pebs_data_source);
 }
 
-static void __init intel_pmu_pebs_data_source_grt(u64 *data_source)
+static void __init __intel_pmu_pebs_data_source_grt(u64 *data_source)
 {
        data_source[0x05] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HIT);
        data_source[0x06] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM);
        data_source[0x08] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOPX, FWD);
 }
 
+void __init intel_pmu_pebs_data_source_grt(void)
+{
+       __intel_pmu_pebs_data_source_grt(pebs_data_source);
+}
+
 void __init intel_pmu_pebs_data_source_adl(void)
 {
        u64 *data_source;
@@ -127,7 +132,7 @@ void __init intel_pmu_pebs_data_source_adl(void)
 
        data_source = x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX].pebs_data_source;
        memcpy(data_source, pebs_data_source, sizeof(pebs_data_source));
-       intel_pmu_pebs_data_source_grt(data_source);
+       __intel_pmu_pebs_data_source_grt(data_source);
 }
 
 static u64 precise_store_data(u64 status)
index ba3d24a..266143a 100644 (file)
@@ -1516,6 +1516,8 @@ void intel_pmu_pebs_data_source_skl(bool pmem);
 
 void intel_pmu_pebs_data_source_adl(void);
 
+void intel_pmu_pebs_data_source_grt(void);
+
 int intel_pmu_setup_lbr_filter(struct perf_event *event);
 
 void intel_pt_interrupt(void);
index aeb3802..5d75fe2 100644 (file)
 #define INTEL_FAM6_RAPTORLAKE_P                0xBA
 #define INTEL_FAM6_RAPTORLAKE_S                0xBF
 
+#define INTEL_FAM6_METEORLAKE          0xAC
+#define INTEL_FAM6_METEORLAKE_L                0xAA
+
 /* "Small Core" Processors (Atom) */
 
 #define INTEL_FAM6_ATOM_BONNELL                0x1C /* Diamondville, Pineview */
index 63f818a..147cb8f 100644 (file)
                              IRQ_CONSTRAINTS, regs, vector);           \
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 /*
  * Macro to invoke __do_softirq on the irq stack. This is only called from
  * task context when bottom halves are about to be reenabled and soft
index 2c96c43..aa381ab 100644 (file)
@@ -729,6 +729,7 @@ struct kvm_vcpu_arch {
        struct fpu_guest guest_fpu;
 
        u64 xcr0;
+       u64 guest_supported_xcr0;
 
        struct kvm_pio_request pio;
        void *pio_data;
index 81a0211..a73bced 100644 (file)
@@ -21,16 +21,6 @@ DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id);
 DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_l2c_id);
 DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
 
-static inline struct cpumask *cpu_llc_shared_mask(int cpu)
-{
-       return per_cpu(cpu_llc_shared_map, cpu);
-}
-
-static inline struct cpumask *cpu_l2c_shared_mask(int cpu)
-{
-       return per_cpu(cpu_l2c_shared_map, cpu);
-}
-
 DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_cpu_to_apicid);
 DECLARE_EARLY_PER_CPU_READ_MOSTLY(u32, x86_cpu_to_acpiid);
 DECLARE_EARLY_PER_CPU_READ_MOSTLY(u16, x86_bios_cpu_apicid);
@@ -172,6 +162,16 @@ extern int safe_smp_processor_id(void);
 # define safe_smp_processor_id()       smp_processor_id()
 #endif
 
+static inline struct cpumask *cpu_llc_shared_mask(int cpu)
+{
+       return per_cpu(cpu_llc_shared_map, cpu);
+}
+
+static inline struct cpumask *cpu_l2c_shared_mask(int cpu)
+{
+       return per_cpu(cpu_l2c_shared_map, cpu);
+}
+
 #else /* !CONFIG_SMP */
 #define wbinvd_on_cpu(cpu)     wbinvd()
 static inline int wbinvd_on_all_cpus(void)
@@ -179,6 +179,11 @@ static inline int wbinvd_on_all_cpus(void)
        wbinvd();
        return 0;
 }
+
+static inline struct cpumask *cpu_llc_shared_mask(int cpu)
+{
+       return (struct cpumask *)cpumask_of(0);
+}
 #endif /* CONFIG_SMP */
 
 extern unsigned disabled_cpus;
index 62f6b8b..4f32043 100644 (file)
@@ -1319,22 +1319,23 @@ struct bp_patching_desc {
        atomic_t refs;
 };
 
-static struct bp_patching_desc *bp_desc;
+static struct bp_patching_desc bp_desc;
 
 static __always_inline
-struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp)
+struct bp_patching_desc *try_get_desc(void)
 {
-       /* rcu_dereference */
-       struct bp_patching_desc *desc = __READ_ONCE(*descp);
+       struct bp_patching_desc *desc = &bp_desc;
 
-       if (!desc || !arch_atomic_inc_not_zero(&desc->refs))
+       if (!arch_atomic_inc_not_zero(&desc->refs))
                return NULL;
 
        return desc;
 }
 
-static __always_inline void put_desc(struct bp_patching_desc *desc)
+static __always_inline void put_desc(void)
 {
+       struct bp_patching_desc *desc = &bp_desc;
+
        smp_mb__before_atomic();
        arch_atomic_dec(&desc->refs);
 }
@@ -1367,15 +1368,15 @@ noinstr int poke_int3_handler(struct pt_regs *regs)
 
        /*
         * Having observed our INT3 instruction, we now must observe
-        * bp_desc:
+        * bp_desc with non-zero refcount:
         *
-        *      bp_desc = desc                  INT3
+        *      bp_desc.refs = 1                INT3
         *      WMB                             RMB
-        *      write INT3                      if (desc)
+        *      write INT3                      if (bp_desc.refs != 0)
         */
        smp_rmb();
 
-       desc = try_get_desc(&bp_desc);
+       desc = try_get_desc();
        if (!desc)
                return 0;
 
@@ -1429,7 +1430,7 @@ noinstr int poke_int3_handler(struct pt_regs *regs)
        ret = 1;
 
 out_put:
-       put_desc(desc);
+       put_desc();
        return ret;
 }
 
@@ -1460,18 +1461,20 @@ static int tp_vec_nr;
  */
 static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries)
 {
-       struct bp_patching_desc desc = {
-               .vec = tp,
-               .nr_entries = nr_entries,
-               .refs = ATOMIC_INIT(1),
-       };
        unsigned char int3 = INT3_INSN_OPCODE;
        unsigned int i;
        int do_sync;
 
        lockdep_assert_held(&text_mutex);
 
-       smp_store_release(&bp_desc, &desc); /* rcu_assign_pointer */
+       bp_desc.vec = tp;
+       bp_desc.nr_entries = nr_entries;
+
+       /*
+        * Corresponds to the implicit memory barrier in try_get_desc() to
+        * ensure reading a non-zero refcount provides up to date bp_desc data.
+        */
+       atomic_set_release(&bp_desc.refs, 1);
 
        /*
         * Corresponding read barrier in int3 notifier for making sure the
@@ -1559,12 +1562,10 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries
                text_poke_sync();
 
        /*
-        * Remove and synchronize_rcu(), except we have a very primitive
-        * refcount based completion.
+        * Remove and wait for refs to be zero.
         */
-       WRITE_ONCE(bp_desc, NULL); /* RCU_INIT_POINTER */
-       if (!atomic_dec_and_test(&desc.refs))
-               atomic_cond_read_acquire(&desc.refs, !VAL);
+       if (!atomic_dec_and_test(&bp_desc.refs))
+               atomic_cond_read_acquire(&bp_desc.refs, !VAL);
 }
 
 static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
index 24c1bb8..8bdeae2 100644 (file)
@@ -344,8 +344,11 @@ static vm_fault_t sgx_encl_eaug_page(struct vm_area_struct *vma,
        }
 
        va_page = sgx_encl_grow(encl, false);
-       if (IS_ERR(va_page))
+       if (IS_ERR(va_page)) {
+               if (PTR_ERR(va_page) == -EBUSY)
+                       vmret = VM_FAULT_NOPAGE;
                goto err_out_epc;
+       }
 
        if (va_page)
                list_add(&va_page->list, &encl->va_pages);
index 515e2a5..0aad028 100644 (file)
@@ -49,9 +49,13 @@ static LIST_HEAD(sgx_dirty_page_list);
  * Reset post-kexec EPC pages to the uninitialized state. The pages are removed
  * from the input list, and made available for the page allocator. SECS pages
  * prepending their children in the input list are left intact.
+ *
+ * Return 0 when sanitization was successful or kthread was stopped, and the
+ * number of unsanitized pages otherwise.
  */
-static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
+static unsigned long __sgx_sanitize_pages(struct list_head *dirty_page_list)
 {
+       unsigned long left_dirty = 0;
        struct sgx_epc_page *page;
        LIST_HEAD(dirty);
        int ret;
@@ -59,7 +63,7 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
        /* dirty_page_list is thread-local, no need for a lock: */
        while (!list_empty(dirty_page_list)) {
                if (kthread_should_stop())
-                       return;
+                       return 0;
 
                page = list_first_entry(dirty_page_list, struct sgx_epc_page, list);
 
@@ -92,12 +96,14 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list)
                } else {
                        /* The page is not yet clean - move to the dirty list. */
                        list_move_tail(&page->list, &dirty);
+                       left_dirty++;
                }
 
                cond_resched();
        }
 
        list_splice(&dirty, dirty_page_list);
+       return left_dirty;
 }
 
 static bool sgx_reclaimer_age(struct sgx_epc_page *epc_page)
@@ -395,10 +401,7 @@ static int ksgxd(void *p)
         * required for SECS pages, whose child pages blocked EREMOVE.
         */
        __sgx_sanitize_pages(&sgx_dirty_page_list);
-       __sgx_sanitize_pages(&sgx_dirty_page_list);
-
-       /* sanity check: */
-       WARN_ON(!list_empty(&sgx_dirty_page_list));
+       WARN_ON(__sgx_sanitize_pages(&sgx_dirty_page_list));
 
        while (!kthread_should_stop()) {
                if (try_to_freeze())
index e5dd6da..01833eb 100644 (file)
@@ -132,7 +132,7 @@ int irq_init_percpu_irqstack(unsigned int cpu)
        return 0;
 }
 
-#ifndef CONFIG_PREEMPT_RT
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 void do_softirq_own_stack(void)
 {
        struct irq_stack *irqstk;
index 75dcf7a..2796dde 100644 (file)
@@ -315,7 +315,6 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
        struct kvm_cpuid_entry2 *best;
-       u64 guest_supported_xcr0;
 
        best = kvm_find_cpuid_entry(vcpu, 1);
        if (best && apic) {
@@ -327,10 +326,16 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
                kvm_apic_set_version(vcpu);
        }
 
-       guest_supported_xcr0 =
+       vcpu->arch.guest_supported_xcr0 =
                cpuid_get_supported_xcr0(vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent);
 
-       vcpu->arch.guest_fpu.fpstate->user_xfeatures = guest_supported_xcr0;
+       /*
+        * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if
+        * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't
+        * supported by the host.
+        */
+       vcpu->arch.guest_fpu.fpstate->user_xfeatures = vcpu->arch.guest_supported_xcr0 |
+                                                      XFEATURE_MASK_FPSSE;
 
        kvm_update_pv_runtime(vcpu);
 
@@ -897,8 +902,6 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
                        entry->edx = 0;
                }
                break;
-       case 9:
-               break;
        case 0xa: { /* Architectural Performance Monitoring */
                union cpuid10_eax eax;
                union cpuid10_edx edx;
index d5ec3a2..aacb28c 100644 (file)
@@ -4132,6 +4132,9 @@ static int em_xsetbv(struct x86_emulate_ctxt *ctxt)
 {
        u32 eax, ecx, edx;
 
+       if (!(ctxt->ops->get_cr(ctxt, 4) & X86_CR4_OSXSAVE))
+               return emulate_ud(ctxt);
+
        eax = reg_read(ctxt, VCPU_REGS_RAX);
        edx = reg_read(ctxt, VCPU_REGS_RDX);
        ecx = reg_read(ctxt, VCPU_REGS_RCX);
index 126fa9a..3552e6a 100644 (file)
@@ -1596,6 +1596,8 @@ static void __rmap_add(struct kvm *kvm,
        rmap_head = gfn_to_rmap(gfn, sp->role.level, slot);
        rmap_count = pte_list_add(cache, spte, rmap_head);
 
+       if (rmap_count > kvm->stat.max_mmu_rmap_size)
+               kvm->stat.max_mmu_rmap_size = rmap_count;
        if (rmap_count > RMAP_RECYCLE_THRESHOLD) {
                kvm_zap_all_rmap_sptes(kvm, rmap_head);
                kvm_flush_remote_tlbs_with_address(
@@ -5361,19 +5363,6 @@ void kvm_mmu_free_obsolete_roots(struct kvm_vcpu *vcpu)
        __kvm_mmu_free_obsolete_roots(vcpu->kvm, &vcpu->arch.guest_mmu);
 }
 
-static bool need_remote_flush(u64 old, u64 new)
-{
-       if (!is_shadow_present_pte(old))
-               return false;
-       if (!is_shadow_present_pte(new))
-               return true;
-       if ((old ^ new) & SPTE_BASE_ADDR_MASK)
-               return true;
-       old ^= shadow_nx_mask;
-       new ^= shadow_nx_mask;
-       return (old & ~new & SPTE_PERM_MASK) != 0;
-}
-
 static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
                                    int *bytes)
 {
@@ -5519,7 +5508,7 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                        mmu_page_zap_pte(vcpu->kvm, sp, spte, NULL);
                        if (gentry && sp->role.level != PG_LEVEL_4K)
                                ++vcpu->kvm->stat.mmu_pde_zapped;
-                       if (need_remote_flush(entry, *spte))
+                       if (is_shadow_present_pte(entry))
                                flush = true;
                        ++spte;
                }
@@ -6085,47 +6074,18 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
                                      const struct kvm_memory_slot *memslot,
                                      int start_level)
 {
-       bool flush = false;
-
        if (kvm_memslots_have_rmaps(kvm)) {
                write_lock(&kvm->mmu_lock);
-               flush = slot_handle_level(kvm, memslot, slot_rmap_write_protect,
-                                         start_level, KVM_MAX_HUGEPAGE_LEVEL,
-                                         false);
+               slot_handle_level(kvm, memslot, slot_rmap_write_protect,
+                                 start_level, KVM_MAX_HUGEPAGE_LEVEL, false);
                write_unlock(&kvm->mmu_lock);
        }
 
        if (is_tdp_mmu_enabled(kvm)) {
                read_lock(&kvm->mmu_lock);
-               flush |= kvm_tdp_mmu_wrprot_slot(kvm, memslot, start_level);
+               kvm_tdp_mmu_wrprot_slot(kvm, memslot, start_level);
                read_unlock(&kvm->mmu_lock);
        }
-
-       /*
-        * Flush TLBs if any SPTEs had to be write-protected to ensure that
-        * guest writes are reflected in the dirty bitmap before the memslot
-        * update completes, i.e. before enabling dirty logging is visible to
-        * userspace.
-        *
-        * Perform the TLB flush outside the mmu_lock to reduce the amount of
-        * time the lock is held. However, this does mean that another CPU can
-        * now grab mmu_lock and encounter a write-protected SPTE while CPUs
-        * still have a writable mapping for the associated GFN in their TLB.
-        *
-        * This is safe but requires KVM to be careful when making decisions
-        * based on the write-protection status of an SPTE. Specifically, KVM
-        * also write-protects SPTEs to monitor changes to guest page tables
-        * during shadow paging, and must guarantee no CPUs can write to those
-        * page before the lock is dropped. As mentioned in the previous
-        * paragraph, a write-protected SPTE is no guarantee that CPU cannot
-        * perform writes. So to determine if a TLB flush is truly required, KVM
-        * will clear a separate software-only bit (MMU-writable) and skip the
-        * flush if-and-only-if this bit was already clear.
-        *
-        * See is_writable_pte() for more details.
-        */
-       if (flush)
-               kvm_arch_flush_remote_tlbs_memslot(kvm, memslot);
 }
 
 static inline bool need_topup(struct kvm_mmu_memory_cache *cache, int min)
@@ -6493,32 +6453,30 @@ void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
 void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
                                   const struct kvm_memory_slot *memslot)
 {
-       bool flush = false;
-
        if (kvm_memslots_have_rmaps(kvm)) {
                write_lock(&kvm->mmu_lock);
                /*
                 * Clear dirty bits only on 4k SPTEs since the legacy MMU only
                 * support dirty logging at a 4k granularity.
                 */
-               flush = slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false);
+               slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false);
                write_unlock(&kvm->mmu_lock);
        }
 
        if (is_tdp_mmu_enabled(kvm)) {
                read_lock(&kvm->mmu_lock);
-               flush |= kvm_tdp_mmu_clear_dirty_slot(kvm, memslot);
+               kvm_tdp_mmu_clear_dirty_slot(kvm, memslot);
                read_unlock(&kvm->mmu_lock);
        }
 
        /*
+        * The caller will flush the TLBs after this function returns.
+        *
         * It's also safe to flush TLBs out of mmu lock here as currently this
         * function is only used for dirty logging, in which case flushing TLB
         * out of mmu lock also guarantees no dirty pages will be lost in
         * dirty_bitmap.
         */
-       if (flush)
-               kvm_arch_flush_remote_tlbs_memslot(kvm, memslot);
 }
 
 void kvm_mmu_zap_all(struct kvm *kvm)
index f3744ee..7670c13 100644 (file)
@@ -343,7 +343,7 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
 }
 
 /*
- * An shadow-present leaf SPTE may be non-writable for 3 possible reasons:
+ * A shadow-present leaf SPTE may be non-writable for 4 possible reasons:
  *
  *  1. To intercept writes for dirty logging. KVM write-protects huge pages
  *     so that they can be split be split down into the dirty logging
@@ -361,8 +361,13 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
  *     read-only memslot or guest memory backed by a read-only VMA. Writes to
  *     such pages are disallowed entirely.
  *
- * To keep track of why a given SPTE is write-protected, KVM uses 2
- * software-only bits in the SPTE:
+ *  4. To emulate the Accessed bit for SPTEs without A/D bits.  Note, in this
+ *     case, the SPTE is access-protected, not just write-protected!
+ *
+ * For cases #1 and #4, KVM can safely make such SPTEs writable without taking
+ * mmu_lock as capturing the Accessed/Dirty state doesn't require taking it.
+ * To differentiate #1 and #4 from #2 and #3, KVM uses two software-only bits
+ * in the SPTE:
  *
  *  shadow_mmu_writable_mask, aka MMU-writable -
  *    Cleared on SPTEs that KVM is currently write-protecting for shadow paging
@@ -391,7 +396,8 @@ static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check,
  * shadow page tables between vCPUs. Write-protecting an SPTE for dirty logging
  * (which does not clear the MMU-writable bit), does not flush TLBs before
  * dropping the lock, as it only needs to synchronize guest writes with the
- * dirty bitmap.
+ * dirty bitmap. Similarly, making the SPTE inaccessible (and non-writable) for
+ * access-tracking via the clear_young() MMU notifier also does not flush TLBs.
  *
  * So, there is the problem: clearing the MMU-writable bit can encounter a
  * write-protected SPTE while CPUs still have writable mappings for that SPTE
index d7f8331..c9b49a0 100644 (file)
@@ -843,8 +843,7 @@ static bool msr_write_intercepted(struct vcpu_vmx *vmx, u32 msr)
        if (!(exec_controls_get(vmx) & CPU_BASED_USE_MSR_BITMAPS))
                return true;
 
-       return vmx_test_msr_bitmap_write(vmx->loaded_vmcs->msr_bitmap,
-                                        MSR_IA32_SPEC_CTRL);
+       return vmx_test_msr_bitmap_write(vmx->loaded_vmcs->msr_bitmap, msr);
 }
 
 unsigned int __vmx_vcpu_run_flags(struct vcpu_vmx *vmx)
index 205ebdc..b0c47b4 100644 (file)
@@ -1011,15 +1011,10 @@ void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_load_host_xsave_state);
 
-static inline u64 kvm_guest_supported_xcr0(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.guest_fpu.fpstate->user_xfeatures;
-}
-
 #ifdef CONFIG_X86_64
 static inline u64 kvm_guest_supported_xfd(struct kvm_vcpu *vcpu)
 {
-       return kvm_guest_supported_xcr0(vcpu) & XFEATURE_MASK_USER_DYNAMIC;
+       return vcpu->arch.guest_supported_xcr0 & XFEATURE_MASK_USER_DYNAMIC;
 }
 #endif
 
@@ -1042,7 +1037,7 @@ static int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
         * saving.  However, xcr0 bit 0 is always set, even if the
         * emulated CPU does not support XSAVE (see kvm_vcpu_reset()).
         */
-       valid_bits = kvm_guest_supported_xcr0(vcpu) | XFEATURE_MASK_FP;
+       valid_bits = vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FP;
        if (xcr0 & ~valid_bits)
                return 1;
 
@@ -1070,6 +1065,7 @@ static int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr)
 
 int kvm_emulate_xsetbv(struct kvm_vcpu *vcpu)
 {
+       /* Note, #UD due to CR4.OSXSAVE=0 has priority over the intercept. */
        if (static_call(kvm_x86_get_cpl)(vcpu) != 0 ||
            __kvm_set_xcr(vcpu, kvm_rcx_read(vcpu), kvm_read_edx_eax(vcpu))) {
                kvm_inject_gp(vcpu, 0);
@@ -1557,12 +1553,32 @@ static const u32 msr_based_features_all[] = {
 static u32 msr_based_features[ARRAY_SIZE(msr_based_features_all)];
 static unsigned int num_msr_based_features;
 
+/*
+ * Some IA32_ARCH_CAPABILITIES bits have dependencies on MSRs that KVM
+ * does not yet virtualize. These include:
+ *   10 - MISC_PACKAGE_CTRLS
+ *   11 - ENERGY_FILTERING_CTL
+ *   12 - DOITM
+ *   18 - FB_CLEAR_CTRL
+ *   21 - XAPIC_DISABLE_STATUS
+ *   23 - OVERCLOCKING_STATUS
+ */
+
+#define KVM_SUPPORTED_ARCH_CAP \
+       (ARCH_CAP_RDCL_NO | ARCH_CAP_IBRS_ALL | ARCH_CAP_RSBA | \
+        ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \
+        ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
+        ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
+        ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO)
+
 static u64 kvm_get_arch_capabilities(void)
 {
        u64 data = 0;
 
-       if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
+       if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) {
                rdmsrl(MSR_IA32_ARCH_CAPABILITIES, data);
+               data &= KVM_SUPPORTED_ARCH_CAP;
+       }
 
        /*
         * If nx_huge_pages is enabled, KVM's shadow paging will ensure that
@@ -1610,9 +1626,6 @@ static u64 kvm_get_arch_capabilities(void)
                 */
        }
 
-       /* Guests don't need to know "Fill buffer clear control" exists */
-       data &= ~ARCH_CAP_FB_CLEAR_CTRL;
-
        return data;
 }
 
@@ -10652,7 +10665,8 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu)
        case KVM_MP_STATE_INIT_RECEIVED:
                break;
        default:
-               return -EINTR;
+               WARN_ON_ONCE(1);
+               break;
        }
        return 1;
 }
@@ -11093,9 +11107,22 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 
        vcpu_load(vcpu);
 
-       if (!lapic_in_kernel(vcpu) &&
-           mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
+       switch (mp_state->mp_state) {
+       case KVM_MP_STATE_UNINITIALIZED:
+       case KVM_MP_STATE_HALTED:
+       case KVM_MP_STATE_AP_RESET_HOLD:
+       case KVM_MP_STATE_INIT_RECEIVED:
+       case KVM_MP_STATE_SIPI_RECEIVED:
+               if (!lapic_in_kernel(vcpu))
+                       goto out;
+               break;
+
+       case KVM_MP_STATE_RUNNABLE:
+               break;
+
+       default:
                goto out;
+       }
 
        /*
         * KVM_MP_STATE_INIT_RECEIVED means the processor is in
@@ -11563,7 +11590,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
        vcpu->arch.mci_ctl2_banks = kcalloc(KVM_MAX_MCE_BANKS, sizeof(u64),
                                            GFP_KERNEL_ACCOUNT);
        if (!vcpu->arch.mce_banks || !vcpu->arch.mci_ctl2_banks)
-               goto fail_free_pio_data;
+               goto fail_free_mce_banks;
        vcpu->arch.mcg_cap = KVM_MAX_MCE_BANKS;
 
        if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask,
@@ -11617,7 +11644,6 @@ free_wbinvd_dirty_mask:
 fail_free_mce_banks:
        kfree(vcpu->arch.mce_banks);
        kfree(vcpu->arch.mci_ctl2_banks);
-fail_free_pio_data:
        free_page((unsigned long)vcpu->arch.pio_data);
 fail_free_lapic:
        kvm_free_lapic(vcpu);
@@ -12473,6 +12499,50 @@ static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
                } else {
                        kvm_mmu_slot_remove_write_access(kvm, new, PG_LEVEL_4K);
                }
+
+               /*
+                * Unconditionally flush the TLBs after enabling dirty logging.
+                * A flush is almost always going to be necessary (see below),
+                * and unconditionally flushing allows the helpers to omit
+                * the subtly complex checks when removing write access.
+                *
+                * Do the flush outside of mmu_lock to reduce the amount of
+                * time mmu_lock is held.  Flushing after dropping mmu_lock is
+                * safe as KVM only needs to guarantee the slot is fully
+                * write-protected before returning to userspace, i.e. before
+                * userspace can consume the dirty status.
+                *
+                * Flushing outside of mmu_lock requires KVM to be careful when
+                * making decisions based on writable status of an SPTE, e.g. a
+                * !writable SPTE doesn't guarantee a CPU can't perform writes.
+                *
+                * Specifically, KVM also write-protects guest page tables to
+                * monitor changes when using shadow paging, and must guarantee
+                * no CPUs can write to those page before mmu_lock is dropped.
+                * Because CPUs may have stale TLB entries at this point, a
+                * !writable SPTE doesn't guarantee CPUs can't perform writes.
+                *
+                * KVM also allows making SPTES writable outside of mmu_lock,
+                * e.g. to allow dirty logging without taking mmu_lock.
+                *
+                * To handle these scenarios, KVM uses a separate software-only
+                * bit (MMU-writable) to track if a SPTE is !writable due to
+                * a guest page table being write-protected (KVM clears the
+                * MMU-writable flag when write-protecting for shadow paging).
+                *
+                * The use of MMU-writable is also the primary motivation for
+                * the unconditional flush.  Because KVM must guarantee that a
+                * CPU doesn't contain stale, writable TLB entries for a
+                * !MMU-writable SPTE, KVM must flush if it encounters any
+                * MMU-writable SPTE regardless of whether the actual hardware
+                * writable bit was set.  I.e. KVM is almost guaranteed to need
+                * to flush, while unconditionally flushing allows the "remove
+                * write access" helpers to ignore MMU-writable entirely.
+                *
+                * See is_writable_pte() for more details (the case involving
+                * access-tracked SPTEs is particularly relevant).
+                */
+               kvm_arch_flush_remote_tlbs_memslot(kvm, new);
        }
 }
 
index ad0139d..f1bb186 100644 (file)
@@ -44,7 +44,7 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
         * called from other contexts.
         */
        pagefault_disable();
-       ret = __copy_from_user_inatomic(to, from, n);
+       ret = raw_copy_from_user(to, from, n);
        pagefault_enable();
 
        return ret;
index f8220fd..829c140 100644 (file)
@@ -4,10 +4,12 @@ KCOV_INSTRUMENT_tlb.o                 := n
 KCOV_INSTRUMENT_mem_encrypt.o          := n
 KCOV_INSTRUMENT_mem_encrypt_amd.o      := n
 KCOV_INSTRUMENT_mem_encrypt_identity.o := n
+KCOV_INSTRUMENT_pgprot.o               := n
 
 KASAN_SANITIZE_mem_encrypt.o           := n
 KASAN_SANITIZE_mem_encrypt_amd.o       := n
 KASAN_SANITIZE_mem_encrypt_identity.o  := n
+KASAN_SANITIZE_pgprot.o                := n
 
 # Disable KCSAN entirely, because otherwise we get warnings that some functions
 # reference __initdata sections.
@@ -17,6 +19,7 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_mem_encrypt.o            = -pg
 CFLAGS_REMOVE_mem_encrypt_amd.o                = -pg
 CFLAGS_REMOVE_mem_encrypt_identity.o   = -pg
+CFLAGS_REMOVE_pgprot.o                 = -pg
 endif
 
 obj-y                          :=  init.o init_$(BITS).o fault.o ioremap.o extable.o mmap.o \
index 68fd2cf..f6e9f84 100644 (file)
@@ -6,10 +6,9 @@
 #include <asm/unistd.h>
 #include <sysdep/ptrace.h>
 
-typedef long syscall_handler_t(struct pt_regs);
+typedef long syscall_handler_t(struct syscall_args);
 
 extern syscall_handler_t *sys_call_table[];
 
 #define EXECUTE_SYSCALL(syscall, regs) \
-       ((long (*)(struct syscall_args)) \
-        (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+       ((*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
index ac8eee0..66162ea 100644 (file)
@@ -65,9 +65,6 @@ static int get_free_idx(struct task_struct* task)
        struct thread_struct *t = &task->thread;
        int idx;
 
-       if (!t->arch.tls_array)
-               return GDT_ENTRY_TLS_MIN;
-
        for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
                if (!t->arch.tls_array[idx].present)
                        return idx + GDT_ENTRY_TLS_MIN;
@@ -240,9 +237,6 @@ static int get_tls_entry(struct task_struct *task, struct user_desc *info,
 {
        struct thread_struct *t = &task->thread;
 
-       if (!t->arch.tls_array)
-               goto clear;
-
        if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
                return -EINVAL;
 
index 8c0396f..6fbe97c 100644 (file)
@@ -65,7 +65,7 @@ quiet_cmd_vdso = VDSO    $@
                       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
                 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
-VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv
+VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack
 GCOV_PROFILE := n
 
 #
index a0d1104..651057c 100644 (file)
@@ -295,7 +295,7 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
 
        while (!blk_try_enter_queue(q, pm)) {
                if (flags & BLK_MQ_REQ_NOWAIT)
-                       return -EBUSY;
+                       return -EAGAIN;
 
                /*
                 * read pair of barrier in blk_freeze_queue_start(), we need to
@@ -325,7 +325,7 @@ int __bio_queue_enter(struct request_queue *q, struct bio *bio)
                        if (test_bit(GD_DEAD, &disk->state))
                                goto dead;
                        bio_wouldblock_error(bio);
-                       return -EBUSY;
+                       return -EAGAIN;
                }
 
                /*
index 67e6dbc..e59c306 100644 (file)
@@ -309,6 +309,11 @@ int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
        struct blk_plug plug;
        int ret = 0;
 
+       /* make sure that "len << SECTOR_SHIFT" doesn't overflow */
+       if (max_sectors > UINT_MAX >> SECTOR_SHIFT)
+               max_sectors = UINT_MAX >> SECTOR_SHIFT;
+       max_sectors &= ~bs_mask;
+
        if (max_sectors == 0)
                return -EOPNOTSUPP;
        if ((sector | nr_sects) & bs_mask)
@@ -322,10 +327,10 @@ int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
 
                bio = blk_next_bio(bio, bdev, 0, REQ_OP_SECURE_ERASE, gfp);
                bio->bi_iter.bi_sector = sector;
-               bio->bi_iter.bi_size = len;
+               bio->bi_iter.bi_size = len << SECTOR_SHIFT;
 
-               sector += len << SECTOR_SHIFT;
-               nr_sects -= len << SECTOR_SHIFT;
+               sector += len;
+               nr_sects -= len;
                if (!nr_sects) {
                        ret = submit_bio_wait(bio);
                        bio_put(bio);
index 8559cea..dee789f 100644 (file)
@@ -283,7 +283,9 @@ static const char *const rqf_name[] = {
        RQF_NAME(SPECIAL_PAYLOAD),
        RQF_NAME(ZONE_WRITE_LOCKED),
        RQF_NAME(MQ_POLL_SLEPT),
+       RQF_NAME(TIMED_OUT),
        RQF_NAME(ELV),
+       RQF_NAME(RESV),
 };
 #undef RQF_NAME
 
index d36fabf..988ba52 100644 (file)
@@ -602,7 +602,6 @@ void del_gendisk(struct gendisk *disk)
         * Prevent new I/O from crossing bio_queue_enter().
         */
        blk_queue_start_drain(q);
-       blk_mq_freeze_queue_wait(q);
 
        if (!(disk->flags & GENHD_FL_HIDDEN)) {
                sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
@@ -626,6 +625,8 @@ void del_gendisk(struct gendisk *disk)
        pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
        device_del(disk_to_dev(disk));
 
+       blk_mq_freeze_queue_wait(q);
+
        blk_throtl_cancel_bios(disk->queue);
 
        blk_sync_queue(q);
index fc1d703..b8112f5 100644 (file)
@@ -596,6 +596,9 @@ static int blk_add_partitions(struct gendisk *disk)
        if (disk->flags & GENHD_FL_NO_PART)
                return 0;
 
+       if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state))
+               return 0;
+
        state = check_partition(disk);
        if (!state)
                return 0;
index bf9b511..1f109b0 100644 (file)
@@ -43,7 +43,7 @@ config SYSTEM_TRUSTED_KEYRING
        bool "Provide system-wide ring of trusted keys"
        depends on KEYS
        depends on ASYMMETRIC_KEY_TYPE
-       depends on X509_CERTIFICATE_PARSER
+       depends on X509_CERTIFICATE_PARSER = y
        help
          Provide a system keyring to which trusted keys can be added.  Keys in
          the keyring are considered to be trusted.  Keys may be added at will
index 7802d88..bc9ddd2 100644 (file)
@@ -27,9 +27,6 @@ menuconfig ACPI
          Management (APM) specification.  If both ACPI and APM support 
          are configured, ACPI is used.
 
-         The project home page for the Linux ACPI subsystem is here:
-         <https://01.org/linux-acpi>
-
          Linux support for ACPI is based on Intel Corporation's ACPI
          Component Architecture (ACPI CA).  For more information on the
          ACPI CA, see:
@@ -347,7 +344,6 @@ config ACPI_CUSTOM_DSDT_FILE
        depends on !STANDALONE
        help
          This option supports a custom DSDT by linking it into the kernel.
-         See Documentation/admin-guide/acpi/dsdt-override.rst
 
          Enter the full path name to the file which includes the AmlCode
          or dsdt_aml_code declaration.
index c29e41b..bb9fe79 100644 (file)
@@ -36,11 +36,6 @@ static int acpi_ac_add(struct acpi_device *device);
 static int acpi_ac_remove(struct acpi_device *device);
 static void acpi_ac_notify(struct acpi_device *device, u32 event);
 
-struct acpi_ac_bl {
-       const char *hid;
-       int hrv;
-};
-
 static const struct acpi_device_id ac_device_ids[] = {
        {"ACPI0003", 0},
        {"", 0},
index ab8a4e0..f5b443a 100644 (file)
@@ -21,6 +21,7 @@
 
 static const struct acpi_device_id amba_id_list[] = {
        {"ARMH0061", 0}, /* PL061 GPIO Device */
+       {"ARMH0330", 0}, /* ARM DMA Controller DMA-330 */
        {"ARMHC500", 0}, /* ARM CoreSight ETM4x */
        {"ARMHC501", 0}, /* ARM CoreSight ETR */
        {"ARMHC502", 0}, /* ARM CoreSight STM */
@@ -48,6 +49,7 @@ static void amba_register_dummy_clk(void)
 static int amba_handler_attach(struct acpi_device *adev,
                                const struct acpi_device_id *id)
 {
+       struct acpi_device *parent = acpi_dev_parent(adev);
        struct amba_device *dev;
        struct resource_entry *rentry;
        struct list_head resource_list;
@@ -97,8 +99,8 @@ static int amba_handler_attach(struct acpi_device *adev,
         * attached to it, that physical device should be the parent of
         * the amba device we are about to create.
         */
-       if (adev->parent)
-               dev->dev.parent = acpi_get_first_physical_node(adev->parent);
+       if (parent)
+               dev->dev.parent = acpi_get_first_physical_node(parent);
 
        ACPI_COMPANION_SET(&dev->dev, adev);
 
index ad245bb..3bbe227 100644 (file)
@@ -60,12 +60,6 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
 }
 
 #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
-static int misc_check_res(struct acpi_resource *ares, void *data)
-{
-       struct resource res;
-
-       return !acpi_dev_resource_memory(ares, &res);
-}
 
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
@@ -82,8 +76,7 @@ static int fch_misc_setup(struct apd_private_data *pdata)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list, misc_check_res,
-                                    NULL);
+       ret = acpi_dev_get_memory_resources(adev, &resource_list);
        if (ret < 0)
                return -ENOENT;
 
index 6922a44..a2056c4 100644 (file)
@@ -143,6 +143,23 @@ static const struct attribute_group boot_attr_group = {
 
 static struct kobject *fpdt_kobj;
 
+#if defined CONFIG_X86 && defined CONFIG_PHYS_ADDR_T_64BIT
+#include <linux/processor.h>
+static bool fpdt_address_valid(u64 address)
+{
+       /*
+        * On some systems the table contains invalid addresses
+        * with unsuppored high address bits set, check for this.
+        */
+       return !(address >> boot_cpu_data.x86_phys_bits);
+}
+#else
+static bool fpdt_address_valid(u64 address)
+{
+       return true;
+}
+#endif
+
 static int fpdt_process_subtable(u64 address, u32 subtable_type)
 {
        struct fpdt_subtable_header *subtable_header;
@@ -151,6 +168,11 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
        u32 length, offset;
        int result;
 
+       if (!fpdt_address_valid(address)) {
+               pr_info(FW_BUG "invalid physical address: 0x%llx!\n", address);
+               return -EINVAL;
+       }
+
        subtable_header = acpi_os_map_memory(address, sizeof(*subtable_header));
        if (!subtable_header)
                return -ENOMEM;
index c4d4d21..f08ffa7 100644 (file)
@@ -167,10 +167,10 @@ static struct pwm_lookup byt_pwm_lookup[] = {
 
 static void byt_pwm_setup(struct lpss_private_data *pdata)
 {
-       struct acpi_device *adev = pdata->adev;
+       u64 uid;
 
        /* Only call pwm_add_table for the first PWM controller */
-       if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1"))
+       if (acpi_dev_uid_to_integer(pdata->adev, &uid) || uid != 1)
                return;
 
        pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup));
@@ -180,14 +180,13 @@ static void byt_pwm_setup(struct lpss_private_data *pdata)
 
 static void byt_i2c_setup(struct lpss_private_data *pdata)
 {
-       const char *uid_str = acpi_device_uid(pdata->adev);
        acpi_handle handle = pdata->adev->handle;
        unsigned long long shared_host = 0;
        acpi_status status;
-       long uid = 0;
+       u64 uid;
 
-       /* Expected to always be true, but better safe then sorry */
-       if (uid_str && !kstrtol(uid_str, 10, &uid) && uid) {
+       /* Expected to always be successfull, but better safe then sorry */
+       if (!acpi_dev_uid_to_integer(pdata->adev, &uid) && uid) {
                /* Detect I2C bus shared with PUNIT and ignore its d3 status */
                status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host);
                if (ACPI_SUCCESS(status) && shared_host)
@@ -211,10 +210,10 @@ static struct pwm_lookup bsw_pwm_lookup[] = {
 
 static void bsw_pwm_setup(struct lpss_private_data *pdata)
 {
-       struct acpi_device *adev = pdata->adev;
+       u64 uid;
 
        /* Only call pwm_add_table for the first PWM controller */
-       if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1"))
+       if (acpi_dev_uid_to_integer(pdata->adev, &uid) || uid != 1)
                return;
 
        pwm_add_table(bsw_pwm_lookup, ARRAY_SIZE(bsw_pwm_lookup));
@@ -392,13 +391,6 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
 
 #ifdef CONFIG_X86_INTEL_LPSS
 
-static int is_memory(struct acpi_resource *res, void *not_used)
-{
-       struct resource r;
-
-       return !acpi_dev_resource_memory(res, &r);
-}
-
 /* LPSS main clock device. */
 static struct platform_device *lpss_clk_dev;
 
@@ -659,29 +651,25 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
                return -ENOMEM;
 
        INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
+       ret = acpi_dev_get_memory_resources(adev, &resource_list);
        if (ret < 0)
                goto err_out;
 
-       list_for_each_entry(rentry, &resource_list, node)
-               if (resource_type(rentry->res) == IORESOURCE_MEM) {
-                       if (dev_desc->prv_size_override)
-                               pdata->mmio_size = dev_desc->prv_size_override;
-                       else
-                               pdata->mmio_size = resource_size(rentry->res);
-                       pdata->mmio_base = ioremap(rentry->res->start,
-                                                  pdata->mmio_size);
-                       break;
-               }
+       rentry = list_first_entry_or_null(&resource_list, struct resource_entry, node);
+       if (rentry) {
+               if (dev_desc->prv_size_override)
+                       pdata->mmio_size = dev_desc->prv_size_override;
+               else
+                       pdata->mmio_size = resource_size(rentry->res);
+               pdata->mmio_base = ioremap(rentry->res->start, pdata->mmio_size);
+       }
 
        acpi_dev_free_resource_list(&resource_list);
 
        if (!pdata->mmio_base) {
                /* Avoid acpi_bus_attach() instantiating a pdev for this dev. */
                adev->pnp.type.platform_id = 0;
-               /* Skip the device, but continue the namespace scan. */
-               ret = 0;
-               goto err_out;
+               goto out_free;
        }
 
        pdata->adev = adev;
@@ -692,11 +680,8 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
 
        if (dev_desc->flags & LPSS_CLK) {
                ret = register_device_clock(adev, pdata);
-               if (ret) {
-                       /* Skip the device, but continue the namespace scan. */
-                       ret = 0;
-                       goto err_out;
-               }
+               if (ret)
+                       goto out_free;
        }
 
        /*
@@ -708,15 +693,19 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
 
        adev->driver_data = pdata;
        pdev = acpi_create_platform_device(adev, dev_desc->properties);
-       if (!IS_ERR_OR_NULL(pdev)) {
-               acpi_lpss_create_device_links(adev, pdev);
-               return 1;
+       if (IS_ERR_OR_NULL(pdev)) {
+               adev->driver_data = NULL;
+               ret = PTR_ERR(pdev);
+               goto err_out;
        }
 
-       ret = PTR_ERR(pdev);
-       adev->driver_data = NULL;
+       acpi_lpss_create_device_links(adev, pdev);
+       return 1;
 
- err_out:
+out_free:
+       /* Skip the device, but continue the namespace scan */
+       ret = 0;
+err_out:
        kfree(pdata);
        return ret;
 }
index a12b55d..ee4ce5b 100644 (file)
 
 #include <acpi/pcc.h>
 
+/*
+ * Arbitrary retries in case the remote processor is slow to respond
+ * to PCC commands
+ */
+#define PCC_CMD_WAIT_RETRIES_NUM       500
+
 struct pcc_data {
        struct pcc_mbox_chan *pcc_chan;
        void __iomem *pcc_comm_addr;
@@ -63,6 +69,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
        if (IS_ERR(data->pcc_chan)) {
                pr_err("Failed to find PCC channel for subspace %d\n",
                       ctx->subspace_id);
+               kfree(data);
                return AE_NOT_FOUND;
        }
 
@@ -72,6 +79,8 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
        if (!data->pcc_comm_addr) {
                pr_err("Failed to ioremap PCC comm region mem for %d\n",
                       ctx->subspace_id);
+               pcc_mbox_free_channel(data->pcc_chan);
+               kfree(data);
                return AE_NO_MEMORY;
        }
 
@@ -86,6 +95,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
 {
        int ret;
        struct pcc_data *data = region_context;
+       u64 usecs_lat;
 
        reinit_completion(&data->done);
 
@@ -96,10 +106,22 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
        if (ret < 0)
                return AE_ERROR;
 
-       if (data->pcc_chan->mchan->mbox->txdone_irq)
-               wait_for_completion(&data->done);
+       if (data->pcc_chan->mchan->mbox->txdone_irq) {
+               /*
+                * pcc_chan->latency is just a Nominal value. In reality the remote
+                * processor could be much slower to reply. So add an arbitrary
+                * amount of wait on top of Nominal.
+                */
+               usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency;
+               ret = wait_for_completion_timeout(&data->done,
+                                                 usecs_to_jiffies(usecs_lat));
+               if (ret == 0) {
+                       pr_err("PCC command executed timeout!\n");
+                       return AE_TIME;
+               }
+       }
 
-       mbox_client_txdone(data->pcc_chan->mchan, ret);
+       mbox_chan_txdone(data->pcc_chan->mchan, ret);
 
        memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
 
index de3cbf1..fe00a57 100644 (file)
 #include "internal.h"
 
 static const struct acpi_device_id forbidden_id_list[] = {
+       {"ACPI0009", 0},        /* IOxAPIC */
+       {"ACPI000A", 0},        /* IOAPIC */
        {"PNP0000",  0},        /* PIC */
        {"PNP0100",  0},        /* Timer */
        {"PNP0200",  0},        /* AT DMA Controller */
-       {"ACPI0009", 0},        /* IOxAPIC */
-       {"ACPI000A", 0},        /* IOAPIC */
        {"SMB0001",  0},        /* ACPI SMBUS virtual device */
-       {"", 0},
+       { }
 };
 
 static struct platform_device *acpi_platform_device_find_by_companion(struct acpi_device *adev)
@@ -78,7 +78,7 @@ static void acpi_platform_fill_resource(struct acpi_device *adev,
         * If the device has parent we need to take its resources into
         * account as well because this device might consume part of those.
         */
-       parent = acpi_get_first_physical_node(adev->parent);
+       parent = acpi_get_first_physical_node(acpi_dev_parent(adev));
        if (parent && dev_is_pci(parent))
                dest->parent = pci_find_resource(to_pci_dev(parent), dest);
 }
@@ -97,6 +97,7 @@ static void acpi_platform_fill_resource(struct acpi_device *adev,
 struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
                                                    const struct property_entry *properties)
 {
+       struct acpi_device *parent = acpi_dev_parent(adev);
        struct platform_device *pdev = NULL;
        struct platform_device_info pdevinfo;
        struct resource_entry *rentry;
@@ -113,13 +114,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
 
        INIT_LIST_HEAD(&resource_list);
        count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
-       if (count < 0) {
+       if (count < 0)
                return NULL;
-       } else if (count > 0) {
-               resources = kcalloc(count, sizeof(struct resource),
-                                   GFP_KERNEL);
+       if (count > 0) {
+               resources = kcalloc(count, sizeof(*resources), GFP_KERNEL);
                if (!resources) {
-                       dev_err(&adev->dev, "No memory for resources\n");
                        acpi_dev_free_resource_list(&resource_list);
                        return ERR_PTR(-ENOMEM);
                }
@@ -137,10 +136,9 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
         * attached to it, that physical device should be the parent of the
         * platform device we are about to create.
         */
-       pdevinfo.parent = adev->parent ?
-               acpi_get_first_physical_node(adev->parent) : NULL;
+       pdevinfo.parent = parent ? acpi_get_first_physical_node(parent) : NULL;
        pdevinfo.name = dev_name(&adev->dev);
-       pdevinfo.id = -1;
+       pdevinfo.id = PLATFORM_DEVID_NONE;
        pdevinfo.res = resources;
        pdevinfo.num_res = count;
        pdevinfo.fwnode = acpi_fwnode_handle(adev);
index 5cbe219..6d209ea 100644 (file)
@@ -496,6 +496,22 @@ static const struct dmi_system_id video_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"),
                },
        },
+       {
+        .callback = video_disable_backlight_sysfs_if,
+        .ident = "Toshiba Satellite Z830",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Z830"),
+               },
+       },
+       {
+        .callback = video_disable_backlight_sysfs_if,
+        .ident = "Toshiba Portege Z830",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE Z830"),
+               },
+       },
        /*
         * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
         * but the IDs actually follow the Device ID Scheme.
@@ -2030,7 +2046,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
        acpi_status status;
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
-                               device->parent->handle, 1,
+                               acpi_dev_parent(device)->handle, 1,
                                acpi_video_bus_match, NULL,
                                device, NULL);
        if (status == AE_ALREADY_EXISTS) {
index 9f49272..9b52482 100644 (file)
@@ -125,12 +125,9 @@ EXPORT_SYMBOL_GPL(apei_exec_write_register);
 int apei_exec_write_register_value(struct apei_exec_context *ctx,
                                   struct acpi_whea_header *entry)
 {
-       int rc;
-
        ctx->value = entry->value;
-       rc = apei_exec_write_register(ctx, entry);
 
-       return rc;
+       return apei_exec_write_register(ctx, entry);
 }
 EXPORT_SYMBOL_GPL(apei_exec_write_register_value);
 
index 45973aa..c23eb75 100644 (file)
@@ -90,6 +90,9 @@ static void __init bert_print_all(struct acpi_bert_region *region,
 
        if (skipped)
                pr_info(HW_ERR "Skipped %d error records\n", skipped);
+
+       if (printed + skipped)
+               pr_info("Total records found: %d\n", printed + skipped);
 }
 
 static int __init setup_bert_disable(char *str)
index 31b077e..2479890 100644 (file)
@@ -1020,14 +1020,10 @@ static int reader_pos;
 
 static int erst_open_pstore(struct pstore_info *psi)
 {
-       int rc;
-
        if (erst_disable)
                return -ENODEV;
 
-       rc = erst_get_record_id_begin(&reader_pos);
-
-       return rc;
+       return erst_get_record_id_begin(&reader_pos);
 }
 
 static int erst_close_pstore(struct pstore_info *psi)
index f16739a..93d7965 100644 (file)
@@ -4,11 +4,12 @@
 #include <linux/device.h>
 #include <linux/dma-direct.h>
 
-void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
+void acpi_arch_dma_setup(struct device *dev)
 {
        int ret;
        u64 end, mask;
-       u64 dmaaddr = 0, size = 0, offset = 0;
+       u64 size = 0;
+       const struct bus_dma_region *map = NULL;
 
        /*
         * If @dev is expected to be DMA-capable then the bus code that created
@@ -26,7 +27,19 @@ void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
        else
                size = 1ULL << 32;
 
-       ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
+       ret = acpi_dma_get_range(dev, &map);
+       if (!ret && map) {
+               const struct bus_dma_region *r = map;
+
+               for (end = 0; r->size; r++) {
+                       if (r->dma_start + r->size - 1 > end)
+                               end = r->dma_start + r->size - 1;
+               }
+
+               size = end + 1;
+               dev->dma_range_map = map;
+       }
+
        if (ret == -ENODEV)
                ret = iort_dma_get_ranges(dev, &size);
        if (!ret) {
@@ -34,17 +47,10 @@ void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
                 * Limit coherent and dma mask based on size retrieved from
                 * firmware.
                 */
-               end = dmaaddr + size - 1;
+               end = size - 1;
                mask = DMA_BIT_MASK(ilog2(end) + 1);
                dev->bus_dma_limit = end;
                dev->coherent_dma_mask = min(dev->coherent_dma_mask, mask);
                *dev->dma_mask = min(*dev->dma_mask, mask);
        }
-
-       *dma_addr = dmaaddr;
-       *dma_size = size;
-
-       ret = dma_direct_set_offset(dev, dmaaddr + offset, dmaaddr, size);
-
-       dev_dbg(dev, "dma_offset(%#08llx)%s\n", offset, ret ? " failed!" : "");
 }
index c0d20d9..d466c81 100644 (file)
@@ -456,7 +456,7 @@ out_free:
                              Notification Handling
    -------------------------------------------------------------------------- */
 
-/**
+/*
  * acpi_bus_notify
  * ---------------
  * Callback for all 'system-level' device notifications (values 0x00-0x7F).
@@ -511,7 +511,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
                break;
        }
 
-       adev = acpi_bus_get_acpi_device(handle);
+       adev = acpi_get_acpi_dev(handle);
        if (!adev)
                goto err;
 
@@ -524,14 +524,14 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
        }
 
        if (!hotplug_event) {
-               acpi_bus_put_acpi_device(adev);
+               acpi_put_acpi_dev(adev);
                return;
        }
 
        if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
                return;
 
-       acpi_bus_put_acpi_device(adev);
+       acpi_put_acpi_dev(adev);
 
  err:
        acpi_evaluate_ost(handle, type, ost_code, NULL);
@@ -802,7 +802,7 @@ static bool acpi_of_modalias(struct acpi_device *adev,
 
        str = obj->string.pointer;
        chr = strchr(str, ',');
-       strlcpy(modalias, chr ? chr + 1 : str, len);
+       strscpy(modalias, chr ? chr + 1 : str, len);
 
        return true;
 }
@@ -822,7 +822,7 @@ void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
                       char *modalias, size_t len)
 {
        if (!acpi_of_modalias(adev, modalias, len))
-               strlcpy(modalias, default_id, len);
+               strscpy(modalias, default_id, len);
 }
 EXPORT_SYMBOL_GPL(acpi_set_modalias);
 
@@ -925,12 +925,13 @@ static const void *acpi_of_device_get_match_data(const struct device *dev)
 
 const void *acpi_device_get_match_data(const struct device *dev)
 {
+       const struct acpi_device_id *acpi_ids = dev->driver->acpi_match_table;
        const struct acpi_device_id *match;
 
-       if (!dev->driver->acpi_match_table)
+       if (!acpi_ids)
                return acpi_of_device_get_match_data(dev);
 
-       match = acpi_match_device(dev->driver->acpi_match_table, dev);
+       match = acpi_match_device(acpi_ids, dev);
        if (!match)
                return NULL;
 
@@ -948,14 +949,13 @@ EXPORT_SYMBOL(acpi_match_device_ids);
 bool acpi_driver_match_device(struct device *dev,
                              const struct device_driver *drv)
 {
-       if (!drv->acpi_match_table)
-               return acpi_of_match_device(ACPI_COMPANION(dev),
-                                           drv->of_match_table,
-                                           NULL);
-
-       return __acpi_match_device(acpi_companion_match(dev),
-                                  drv->acpi_match_table, drv->of_match_table,
-                                  NULL, NULL);
+       const struct acpi_device_id *acpi_ids = drv->acpi_match_table;
+       const struct of_device_id *of_ids = drv->of_match_table;
+
+       if (!acpi_ids)
+               return acpi_of_match_device(ACPI_COMPANION(dev), of_ids, NULL);
+
+       return __acpi_match_device(acpi_companion_match(dev), acpi_ids, of_ids, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(acpi_driver_match_device);
 
@@ -973,16 +973,13 @@ EXPORT_SYMBOL_GPL(acpi_driver_match_device);
  */
 int acpi_bus_register_driver(struct acpi_driver *driver)
 {
-       int ret;
-
        if (acpi_disabled)
                return -ENODEV;
        driver->drv.name = driver->name;
        driver->drv.bus = &acpi_bus_type;
        driver->drv.owner = driver->owner;
 
-       ret = driver_register(&driver->drv);
-       return ret;
+       return driver_register(&driver->drv);
 }
 
 EXPORT_SYMBOL(acpi_bus_register_driver);
index 1e15a9f..093675b 100644 (file)
@@ -424,6 +424,9 @@ bool acpi_cpc_valid(void)
        struct cpc_desc *cpc_ptr;
        int cpu;
 
+       if (acpi_disabled)
+               return false;
+
        for_each_present_cpu(cpu) {
                cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
                if (!cpc_ptr)
@@ -1241,6 +1244,48 @@ out_err:
 EXPORT_SYMBOL_GPL(cppc_get_perf_caps);
 
 /**
+ * cppc_perf_ctrs_in_pcc - Check if any perf counters are in a PCC region.
+ *
+ * CPPC has flexibility about how CPU performance counters are accessed.
+ * One of the choices is PCC regions, which can have a high access latency. This
+ * routine allows callers of cppc_get_perf_ctrs() to know this ahead of time.
+ *
+ * Return: true if any of the counters are in PCC regions, false otherwise
+ */
+bool cppc_perf_ctrs_in_pcc(void)
+{
+       int cpu;
+
+       for_each_present_cpu(cpu) {
+               struct cpc_register_resource *ref_perf_reg;
+               struct cpc_desc *cpc_desc;
+
+               cpc_desc = per_cpu(cpc_desc_ptr, cpu);
+
+               if (CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) ||
+                   CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) ||
+                   CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME]))
+                       return true;
+
+
+               ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
+
+               /*
+                * If reference perf register is not supported then we should
+                * use the nominal perf value
+                */
+               if (!CPC_SUPPORTED(ref_perf_reg))
+                       ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
+
+               if (CPC_IN_PCC(ref_perf_reg))
+                       return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(cppc_perf_ctrs_in_pcc);
+
+/**
  * cppc_get_perf_ctrs - Read a CPU's performance feedback counters.
  * @cpunum: CPU from which to read counters.
  * @perf_fb_ctrs: ptr to cppc_perf_fb_ctrs. See cppc_acpi.h
index 9dce124..d594eff 100644 (file)
@@ -75,15 +75,17 @@ static int acpi_dev_pm_explicit_get(struct acpi_device *device, int *state)
 int acpi_device_get_power(struct acpi_device *device, int *state)
 {
        int result = ACPI_STATE_UNKNOWN;
+       struct acpi_device *parent;
        int error;
 
        if (!device || !state)
                return -EINVAL;
 
+       parent = acpi_dev_parent(device);
+
        if (!device->flags.power_manageable) {
                /* TBD: Non-recursive algorithm for walking up hierarchy. */
-               *state = device->parent ?
-                       device->parent->power.state : ACPI_STATE_D0;
+               *state = parent ? parent->power.state : ACPI_STATE_D0;
                goto out;
        }
 
@@ -122,10 +124,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
         * point, the fact that the device is in D0 implies that the parent has
         * to be in D0 too, except if ignore_parent is set.
         */
-       if (!device->power.flags.ignore_parent && device->parent
-           && device->parent->power.state == ACPI_STATE_UNKNOWN
-           && result == ACPI_STATE_D0)
-               device->parent->power.state = ACPI_STATE_D0;
+       if (!device->power.flags.ignore_parent && parent &&
+           parent->power.state == ACPI_STATE_UNKNOWN &&
+           result == ACPI_STATE_D0)
+               parent->power.state = ACPI_STATE_D0;
 
        *state = result;
 
@@ -191,13 +193,17 @@ int acpi_device_set_power(struct acpi_device *device, int state)
                return -ENODEV;
        }
 
-       if (!device->power.flags.ignore_parent && device->parent &&
-           state < device->parent->power.state) {
-               acpi_handle_debug(device->handle,
-                                 "Cannot transition to %s for parent in %s\n",
-                                 acpi_power_state_string(state),
-                                 acpi_power_state_string(device->parent->power.state));
-               return -ENODEV;
+       if (!device->power.flags.ignore_parent) {
+               struct acpi_device *parent;
+
+               parent = acpi_dev_parent(device);
+               if (parent && state < parent->power.state) {
+                       acpi_handle_debug(device->handle,
+                                         "Cannot transition to %s for parent in %s\n",
+                                         acpi_power_state_string(state),
+                                         acpi_power_state_string(parent->power.state));
+                       return -ENODEV;
+               }
        }
 
        /*
@@ -497,7 +503,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
 
        acpi_handle_debug(handle, "Wake notify\n");
 
-       adev = acpi_bus_get_acpi_device(handle);
+       adev = acpi_get_acpi_dev(handle);
        if (!adev)
                return;
 
@@ -515,7 +521,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
 
        mutex_unlock(&acpi_pm_notifier_lock);
 
-       acpi_bus_put_acpi_device(adev);
+       acpi_put_acpi_dev(adev);
 }
 
 /**
@@ -1460,7 +1466,7 @@ EXPORT_SYMBOL_GPL(acpi_storage_d3);
  * not valid to ask for the ACPI power state of the device in that time frame.
  *
  * This function is intended to be used in a driver's probe or remove
- * function. See Documentation/firmware-guide/acpi/low-power-probe.rst for
+ * function. See Documentation/firmware-guide/acpi/non-d0-probe.rst for
  * more information.
  */
 bool acpi_dev_state_d0(struct device *dev)
index 1e8c7ce..4b3fdc0 100644 (file)
@@ -11,9 +11,6 @@ menuconfig ACPI_DPTF
          a coordinated approach for different policies to effect the hardware
          state of a system.
 
-         For more information see:
-         <https://01.org/intel%C2%AE-dynamic-platform-and-thermal-framework-dptf-chromium-os/overview>
-
 if ACPI_DPTF
 
 config DPTF_POWER
index c95e535..9b42628 100644 (file)
@@ -917,14 +917,10 @@ EXPORT_SYMBOL(ec_read);
 
 int ec_write(u8 addr, u8 val)
 {
-       int err;
-
        if (!first_ec)
                return -ENODEV;
 
-       err = acpi_ec_write(first_ec, addr, val);
-
-       return err;
+       return acpi_ec_write(first_ec, addr, val);
 }
 EXPORT_SYMBOL(ec_write);
 
index b9a9a59..52a0b30 100644 (file)
 
 #include "fan.h"
 
-MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION("ACPI Fan Driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_fan_probe(struct platform_device *pdev);
-static int acpi_fan_remove(struct platform_device *pdev);
-
 static const struct acpi_device_id fan_device_ids[] = {
        ACPI_FAN_DEVICE_IDS,
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 
-#ifdef CONFIG_PM_SLEEP
-static int acpi_fan_suspend(struct device *dev);
-static int acpi_fan_resume(struct device *dev);
-static const struct dev_pm_ops acpi_fan_pm = {
-       .resume = acpi_fan_resume,
-       .freeze = acpi_fan_suspend,
-       .thaw = acpi_fan_resume,
-       .restore = acpi_fan_resume,
-};
-#define FAN_PM_OPS_PTR (&acpi_fan_pm)
-#else
-#define FAN_PM_OPS_PTR NULL
-#endif
-
-static struct platform_driver acpi_fan_driver = {
-       .probe = acpi_fan_probe,
-       .remove = acpi_fan_remove,
-       .driver = {
-               .name = "acpi-fan",
-               .acpi_match_table = fan_device_ids,
-               .pm = FAN_PM_OPS_PTR,
-       },
-};
-
 /* thermal cooling device callbacks */
 static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
                             *state)
@@ -459,6 +428,33 @@ static int acpi_fan_resume(struct device *dev)
 
        return result;
 }
+
+static const struct dev_pm_ops acpi_fan_pm = {
+       .resume = acpi_fan_resume,
+       .freeze = acpi_fan_suspend,
+       .thaw = acpi_fan_resume,
+       .restore = acpi_fan_resume,
+};
+#define FAN_PM_OPS_PTR (&acpi_fan_pm)
+
+#else
+
+#define FAN_PM_OPS_PTR NULL
+
 #endif
 
+static struct platform_driver acpi_fan_driver = {
+       .probe = acpi_fan_probe,
+       .remove = acpi_fan_remove,
+       .driver = {
+               .name = "acpi-fan",
+               .acpi_match_table = fan_device_ids,
+               .pm = FAN_PM_OPS_PTR,
+       },
+};
+
 module_platform_driver(acpi_fan_driver);
+
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Fan Driver");
+MODULE_LICENSE("GPL");
index 628bf8f..219c02d 100644 (file)
@@ -102,10 +102,10 @@ struct acpi_device_bus_id {
        struct list_head node;
 };
 
-int acpi_device_add(struct acpi_device *device,
-                   void (*release)(struct device *));
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
-                            int type);
+                            int type, void (*release)(struct device *));
+int acpi_tie_acpi_dev(struct acpi_device *adev);
+int acpi_device_add(struct acpi_device *device);
 int acpi_device_setup_files(struct acpi_device *dev);
 void acpi_device_remove_files(struct acpi_device *dev);
 void acpi_device_add_finalize(struct acpi_device *device);
index dabe45e..4db5bb5 100644 (file)
@@ -118,12 +118,12 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source,
        if (WARN_ON(ACPI_FAILURE(status)))
                return NULL;
 
-       device = acpi_bus_get_acpi_device(handle);
+       device = acpi_get_acpi_dev(handle);
        if (WARN_ON(!device))
                return NULL;
 
        result = &device->fwnode;
-       acpi_bus_put_acpi_device(device);
+       acpi_put_acpi_dev(device);
        return result;
 }
 
index c3d783a..23f49a2 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 #define pr_fmt(fmt) "acpi/hmat: " fmt
-#define dev_fmt(fmt) "acpi/hmat: " fmt
 
 #include <linux/acpi.h>
 #include <linux/bitops.h>
@@ -302,7 +301,7 @@ static __init int hmat_parse_locality(union acpi_subtable_headers *header,
        u8 type, mem_hier;
 
        if (hmat_loc->header.length < sizeof(*hmat_loc)) {
-               pr_notice("HMAT: Unexpected locality header length: %u\n",
+               pr_notice("Unexpected locality header length: %u\n",
                         hmat_loc->header.length);
                return -EINVAL;
        }
@@ -314,12 +313,12 @@ static __init int hmat_parse_locality(union acpi_subtable_headers *header,
        total_size = sizeof(*hmat_loc) + sizeof(*entries) * ipds * tpds +
                     sizeof(*inits) * ipds + sizeof(*targs) * tpds;
        if (hmat_loc->header.length < total_size) {
-               pr_notice("HMAT: Unexpected locality header length:%u, minimum required:%u\n",
+               pr_notice("Unexpected locality header length:%u, minimum required:%u\n",
                         hmat_loc->header.length, total_size);
                return -EINVAL;
        }
 
-       pr_info("HMAT: Locality: Flags:%02x Type:%s Initiator Domains:%u Target Domains:%u Base:%lld\n",
+       pr_info("Locality: Flags:%02x Type:%s Initiator Domains:%u Target Domains:%u Base:%lld\n",
                hmat_loc->flags, hmat_data_type(type), ipds, tpds,
                hmat_loc->entry_base_unit);
 
@@ -363,13 +362,13 @@ static __init int hmat_parse_cache(union acpi_subtable_headers *header,
        u32 attrs;
 
        if (cache->header.length < sizeof(*cache)) {
-               pr_notice("HMAT: Unexpected cache header length: %u\n",
+               pr_notice("Unexpected cache header length: %u\n",
                         cache->header.length);
                return -EINVAL;
        }
 
        attrs = cache->cache_attributes;
-       pr_info("HMAT: Cache: Domain:%u Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
+       pr_info("Cache: Domain:%u Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
                cache->memory_PD, cache->cache_size, attrs,
                cache->number_of_SMBIOShandles);
 
@@ -424,24 +423,24 @@ static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *heade
        struct memory_target *target = NULL;
 
        if (p->header.length != sizeof(*p)) {
-               pr_notice("HMAT: Unexpected address range header length: %u\n",
+               pr_notice("Unexpected address range header length: %u\n",
                         p->header.length);
                return -EINVAL;
        }
 
        if (hmat_revision == 1)
-               pr_info("HMAT: Memory (%#llx length %#llx) Flags:%04x Processor Domain:%u Memory Domain:%u\n",
+               pr_info("Memory (%#llx length %#llx) Flags:%04x Processor Domain:%u Memory Domain:%u\n",
                        p->reserved3, p->reserved4, p->flags, p->processor_PD,
                        p->memory_PD);
        else
-               pr_info("HMAT: Memory Flags:%04x Processor Domain:%u Memory Domain:%u\n",
+               pr_info("Memory Flags:%04x Processor Domain:%u Memory Domain:%u\n",
                        p->flags, p->processor_PD, p->memory_PD);
 
        if ((hmat_revision == 1 && p->flags & ACPI_HMAT_MEMORY_PD_VALID) ||
            hmat_revision > 1) {
                target = find_mem_target(p->memory_PD);
                if (!target) {
-                       pr_debug("HMAT: Memory Domain missing from SRAT\n");
+                       pr_debug("Memory Domain missing from SRAT\n");
                        return -EINVAL;
                }
        }
@@ -449,7 +448,7 @@ static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *heade
                int p_node = pxm_to_node(p->processor_PD);
 
                if (p_node == NUMA_NO_NODE) {
-                       pr_debug("HMAT: Invalid Processor Domain\n");
+                       pr_debug("Invalid Processor Domain\n");
                        return -EINVAL;
                }
                target->processor_pxm = p->processor_PD;
@@ -840,7 +839,7 @@ static __init int hmat_init(void)
        case 2:
                break;
        default:
-               pr_notice("Ignoring HMAT: Unknown revision:%d\n", hmat_revision);
+               pr_notice("Ignoring: Unknown revision:%d\n", hmat_revision);
                goto out_put;
        }
 
@@ -848,7 +847,7 @@ static __init int hmat_init(void)
                if (acpi_table_parse_entries(ACPI_SIG_HMAT,
                                             sizeof(struct acpi_table_hmat), i,
                                             hmat_parse_subtable, 0) < 0) {
-                       pr_notice("Ignoring HMAT: Invalid table");
+                       pr_notice("Ignoring: Invalid table");
                        goto out_put;
                }
        }
index 9f68538..d4405e1 100644 (file)
@@ -44,30 +44,6 @@ osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
        {"Processor Device", true},
        {"3.0 _SCP Extensions", true},
        {"Processor Aggregator Device", true},
-       /*
-        * Linux-Dell-Video is used by BIOS to disable RTD3 for NVidia graphics
-        * cards as RTD3 is not supported by drivers now.  Systems with NVidia
-        * cards will hang without RTD3 disabled.
-        *
-        * Once NVidia drivers officially support RTD3, this _OSI strings can
-        * be removed if both new and old graphics cards are supported.
-        */
-       {"Linux-Dell-Video", true},
-       /*
-        * Linux-Lenovo-NV-HDMI-Audio is used by BIOS to power on NVidia's HDMI
-        * audio device which is turned off for power-saving in Windows OS.
-        * This power management feature observed on some Lenovo Thinkpad
-        * systems which will not be able to output audio via HDMI without
-        * a BIOS workaround.
-        */
-       {"Linux-Lenovo-NV-HDMI-Audio", true},
-       /*
-        * Linux-HPI-Hybrid-Graphics is used by BIOS to enable dGPU to
-        * output video directly to external monitors on HP Inc. mobile
-        * workstations as Nvidia and AMD VGA drivers provide limited
-        * hybrid graphics supports.
-        */
-       {"Linux-HPI-Hybrid-Graphics", true},
 };
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
index d57cf84..c8385ef 100644 (file)
@@ -312,76 +312,25 @@ struct acpi_handle_node {
  */
 struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
 {
-       int dev, fn;
-       unsigned long long adr;
-       acpi_status status;
-       acpi_handle phandle;
-       struct pci_bus *pbus;
-       struct pci_dev *pdev = NULL;
-       struct acpi_handle_node *node, *tmp;
-       struct acpi_pci_root *root;
-       LIST_HEAD(device_list);
-
-       /*
-        * Walk up the ACPI CA namespace until we reach a PCI root bridge.
-        */
-       phandle = handle;
-       while (!acpi_is_root_bridge(phandle)) {
-               node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
-               if (!node)
-                       goto out;
-
-               INIT_LIST_HEAD(&node->node);
-               node->handle = phandle;
-               list_add(&node->node, &device_list);
-
-               status = acpi_get_parent(phandle, &phandle);
-               if (ACPI_FAILURE(status))
-                       goto out;
-       }
-
-       root = acpi_pci_find_root(phandle);
-       if (!root)
-               goto out;
+       struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
+       struct acpi_device_physical_node *pn;
+       struct pci_dev *pci_dev = NULL;
 
-       pbus = root->bus;
-
-       /*
-        * Now, walk back down the PCI device tree until we return to our
-        * original handle. Assumes that everything between the PCI root
-        * bridge and the device we're looking for must be a P2P bridge.
-        */
-       list_for_each_entry(node, &device_list, node) {
-               acpi_handle hnd = node->handle;
-               status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
-               if (ACPI_FAILURE(status))
-                       goto out;
-               dev = (adr >> 16) & 0xffff;
-               fn  = adr & 0xffff;
-
-               pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
-               if (!pdev || hnd == handle)
-                       break;
+       if (!adev)
+               return NULL;
 
-               pbus = pdev->subordinate;
-               pci_dev_put(pdev);
+       mutex_lock(&adev->physical_node_lock);
 
-               /*
-                * This function may be called for a non-PCI device that has a
-                * PCI parent (eg. a disk under a PCI SATA controller).  In that
-                * case pdev->subordinate will be NULL for the parent.
-                */
-               if (!pbus) {
-                       dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge\n");
-                       pdev = NULL;
+       list_for_each_entry(pn, &adev->physical_node_list, node) {
+               if (dev_is_pci(pn->dev)) {
+                       pci_dev = to_pci_dev(pn->dev);
                        break;
                }
        }
-out:
-       list_for_each_entry_safe(node, tmp, &device_list, node)
-               kfree(node);
 
-       return pdev;
+       mutex_unlock(&adev->physical_node_lock);
+
+       return pci_dev;
 }
 EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 
index 8c4a73a..f2588ab 100644 (file)
@@ -944,13 +944,15 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
                return NULL;
 
        device = &resource->device;
-       acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER);
+       acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
+                               acpi_release_power_resource);
        mutex_init(&resource->resource_lock);
        INIT_LIST_HEAD(&resource->list_node);
        INIT_LIST_HEAD(&resource->dependents);
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
        device->power.state = ACPI_STATE_UNKNOWN;
+       device->flags.match_driver = true;
 
        /* Evaluate the object to get the system level and resource order. */
        status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
@@ -967,8 +969,11 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
 
        pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device));
 
-       device->flags.match_driver = true;
-       result = acpi_device_add(device, acpi_release_power_resource);
+       result = acpi_tie_acpi_dev(device);
+       if (result)
+               goto err;
+
+       result = acpi_device_add(device);
        if (result)
                goto err;
 
index 16a1663..acfabfe 100644 (file)
@@ -531,10 +531,27 @@ static void wait_for_freeze(void)
        /* No delay is needed if we are in guest */
        if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
                return;
+       /*
+        * Modern (>=Nehalem) Intel systems use ACPI via intel_idle,
+        * not this code.  Assume that any Intel systems using this
+        * are ancient and may need the dummy wait.  This also assumes
+        * that the motivating chipset issue was Intel-only.
+        */
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+               return;
 #endif
-       /* Dummy wait op - must do something useless after P_LVL2 read
-          because chipsets cannot guarantee that STPCLK# signal
-          gets asserted in time to freeze execution properly. */
+       /*
+        * Dummy wait op - must do something useless after P_LVL2 read
+        * because chipsets cannot guarantee that STPCLK# signal gets
+        * asserted in time to freeze execution properly
+        *
+        * This workaround has been in place since the original ACPI
+        * implementation was merged, circa 2002.
+        *
+        * If a profile is pointing to this instruction, please first
+        * consider moving your system to a more modern idle
+        * mechanism.
+        */
        inl(acpi_gbl_FADT.xpm_timer_block.address);
 }
 
@@ -787,7 +804,7 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
 
                state = &drv->states[count];
                snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
-               strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
+               strscpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
                state->exit_latency = cx->latency;
                state->target_residency = cx->latency * latency_factor;
                state->enter = acpi_idle_enter;
@@ -956,7 +973,7 @@ static int acpi_processor_evaluate_lpi(acpi_handle handle,
 
                obj = pkg_elem + 9;
                if (obj->type == ACPI_TYPE_STRING)
-                       strlcpy(lpi_state->desc, obj->string.pointer,
+                       strscpy(lpi_state->desc, obj->string.pointer,
                                ACPI_CX_DESC_LEN);
 
                lpi_state->index = state_idx;
@@ -1022,7 +1039,7 @@ static bool combine_lpi_states(struct acpi_lpi_state *local,
        result->arch_flags = parent->arch_flags;
        result->index = parent->index;
 
-       strlcpy(result->desc, local->desc, ACPI_CX_DESC_LEN);
+       strscpy(result->desc, local->desc, ACPI_CX_DESC_LEN);
        strlcat(result->desc, "+", ACPI_CX_DESC_LEN);
        strlcat(result->desc, parent->desc, ACPI_CX_DESC_LEN);
        return true;
@@ -1196,7 +1213,7 @@ static int acpi_processor_setup_lpi_states(struct acpi_processor *pr)
 
                state = &drv->states[i];
                snprintf(state->name, CPUIDLE_NAME_LEN, "LPI-%d", i);
-               strlcpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN);
+               strscpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN);
                state->exit_latency = lpi->wake_latency;
                state->target_residency = lpi->min_residency;
                if (lpi->arch_flags)
index d4c168c..b8d9eb9 100644 (file)
@@ -304,8 +304,10 @@ static void acpi_init_of_compatible(struct acpi_device *adev)
                ret = acpi_dev_get_property(adev, "compatible",
                                            ACPI_TYPE_STRING, &of_compatible);
                if (ret) {
-                       if (adev->parent
-                           && adev->parent->flags.of_compatible_ok)
+                       struct acpi_device *parent;
+
+                       parent = acpi_dev_parent(adev);
+                       if (parent && parent->flags.of_compatible_ok)
                                goto out;
 
                        return;
@@ -1267,10 +1269,11 @@ acpi_node_get_parent(const struct fwnode_handle *fwnode)
                return to_acpi_data_node(fwnode)->parent;
        }
        if (is_acpi_device_node(fwnode)) {
-               struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
+               struct acpi_device *parent;
 
-               if (dev)
-                       return acpi_fwnode_handle(to_acpi_device(dev));
+               parent = acpi_dev_parent(to_acpi_device_node(fwnode));
+               if (parent)
+                       return acpi_fwnode_handle(parent);
        }
 
        return NULL;
index 510cdec..514d896 100644 (file)
@@ -399,6 +399,31 @@ static const struct dmi_system_id medion_laptop[] = {
        { }
 };
 
+static const struct dmi_system_id asus_laptop[] = {
+       {
+               .ident = "Asus Vivobook K3402ZA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),
+               },
+       },
+       {
+               .ident = "Asus Vivobook K3502ZA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),
+               },
+       },
+       {
+               .ident = "Asus Vivobook S5402ZA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),
+               },
+       },
+       { }
+};
+
 struct irq_override_cmp {
        const struct dmi_system_id *system;
        unsigned char irq;
@@ -409,6 +434,7 @@ struct irq_override_cmp {
 
 static const struct irq_override_cmp skip_override_table[] = {
        { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 },
+       { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 },
 };
 
 static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
@@ -690,6 +716,9 @@ static int is_memory(struct acpi_resource *ares, void *not_used)
 
        memset(&win, 0, sizeof(win));
 
+       if (acpi_dev_filter_resource_type(ares, IORESOURCE_MEM))
+               return 1;
+
        return !(acpi_dev_resource_memory(ares, res)
               || acpi_dev_resource_address_space(ares, &win)
               || acpi_dev_resource_ext_address_space(ares, &win));
@@ -719,6 +748,23 @@ int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)
 EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);
 
 /**
+ * acpi_dev_get_memory_resources - Get current memory resources of a device.
+ * @adev: ACPI device node to get the resources for.
+ * @list: Head of the resultant list of resources (must be empty).
+ *
+ * This is a helper function that locates all memory type resources of @adev
+ * with acpi_dev_get_resources().
+ *
+ * The number of resources in the output list is returned on success, an error
+ * code reflecting the error condition is returned otherwise.
+ */
+int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list)
+{
+       return acpi_dev_get_resources(adev, list, is_memory, NULL);
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_memory_resources);
+
+/**
  * acpi_dev_filter_resource_type - Filter ACPI resource according to resource
  *                                types
  * @ares: Input ACPI resource object.
index 4938010..e6a01a8 100644 (file)
@@ -632,7 +632,7 @@ static int acpi_sbs_add(struct acpi_device *device)
 
        mutex_init(&sbs->lock);
 
-       sbs->hc = acpi_driver_data(device->parent);
+       sbs->hc = acpi_driver_data(acpi_dev_parent(device));
        sbs->device = device;
        strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
index 7c62e14..340e0b6 100644 (file)
@@ -266,7 +266,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
        mutex_init(&hc->lock);
        init_waitqueue_head(&hc->wait);
 
-       hc->ec = acpi_driver_data(device->parent);
+       hc->ec = acpi_driver_data(acpi_dev_parent(device));
        hc->offset = (val >> 8) & 0xff;
        hc->query_bit = val & 0xff;
        device->driver_data = hc;
index 42cec81..558664d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_data/x86/apple.h>
 #include <linux/pgtable.h>
 #include <linux/crc32.h>
+#include <linux/dma-direct.h>
 
 #include "internal.h"
 
@@ -29,8 +30,6 @@ extern struct acpi_device *acpi_root;
 #define ACPI_BUS_HID                   "LNXSYBUS"
 #define ACPI_BUS_DEVICE_NAME           "System Bus"
 
-#define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
-
 #define INVALID_ACPI_HANDLE    ((acpi_handle)empty_zero_page)
 
 static const char *dummy_hid = "device";
@@ -429,7 +428,7 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src)
        acpi_evaluate_ost(adev->handle, src, ost_code, NULL);
 
  out:
-       acpi_bus_put_acpi_device(adev);
+       acpi_put_acpi_dev(adev);
        mutex_unlock(&acpi_scan_lock);
        unlock_device_hotplug();
 }
@@ -599,11 +598,22 @@ static void get_acpi_device(void *dev)
        acpi_dev_get(dev);
 }
 
-struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
+/**
+ * acpi_get_acpi_dev - Retrieve ACPI device object and reference count it.
+ * @handle: ACPI handle associated with the requested ACPI device object.
+ *
+ * Return a pointer to the ACPI device object associated with @handle and bump
+ * up that object's reference counter (under the ACPI Namespace lock), if
+ * present, or return NULL otherwise.
+ *
+ * The ACPI device object reference acquired by this function needs to be
+ * dropped via acpi_dev_put().
+ */
+struct acpi_device *acpi_get_acpi_dev(acpi_handle handle)
 {
        return handle_to_device(handle, get_acpi_device);
 }
-EXPORT_SYMBOL_GPL(acpi_bus_get_acpi_device);
+EXPORT_SYMBOL_GPL(acpi_get_acpi_dev);
 
 static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id)
 {
@@ -632,7 +642,7 @@ static int acpi_device_set_name(struct acpi_device *device,
        return 0;
 }
 
-static int acpi_tie_acpi_dev(struct acpi_device *adev)
+int acpi_tie_acpi_dev(struct acpi_device *adev)
 {
        acpi_handle handle = adev->handle;
        acpi_status status;
@@ -662,8 +672,7 @@ static void acpi_store_pld_crc(struct acpi_device *adev)
        ACPI_FREE(pld);
 }
 
-static int __acpi_device_add(struct acpi_device *device,
-                            void (*release)(struct device *))
+int acpi_device_add(struct acpi_device *device)
 {
        struct acpi_device_bus_id *acpi_device_bus_id;
        int result;
@@ -719,11 +728,6 @@ static int __acpi_device_add(struct acpi_device *device,
 
        mutex_unlock(&acpi_device_lock);
 
-       if (device->parent)
-               device->dev.parent = &device->parent->dev;
-
-       device->dev.bus = &acpi_bus_type;
-       device->dev.release = release;
        result = device_add(&device->dev);
        if (result) {
                dev_err(&device->dev, "Error registering device\n");
@@ -750,17 +754,6 @@ err_unlock:
        return result;
 }
 
-int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *))
-{
-       int ret;
-
-       ret = acpi_tie_acpi_dev(adev);
-       if (ret)
-               return ret;
-
-       return __acpi_device_add(adev, release);
-}
-
 /* --------------------------------------------------------------------------
                                  Device Enumeration
    -------------------------------------------------------------------------- */
@@ -805,10 +798,9 @@ static const char * const acpi_honor_dep_ids[] = {
        NULL
 };
 
-static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
+static struct acpi_device *acpi_find_parent_acpi_dev(acpi_handle handle)
 {
-       struct acpi_device *device;
-       acpi_status status;
+       struct acpi_device *adev;
 
        /*
         * Fixed hardware devices do not appear in the namespace and do not
@@ -819,13 +811,18 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
                return acpi_root;
 
        do {
+               acpi_status status;
+
                status = acpi_get_parent(handle, &handle);
-               if (ACPI_FAILURE(status))
-                       return status == AE_NULL_ENTRY ? NULL : acpi_root;
+               if (ACPI_FAILURE(status)) {
+                       if (status != AE_NULL_ENTRY)
+                               return acpi_root;
 
-               device = acpi_fetch_acpi_dev(handle);
-       } while (!device);
-       return device;
+                       return NULL;
+               }
+               adev = acpi_fetch_acpi_dev(handle);
+       } while (!adev);
+       return adev;
 }
 
 acpi_status
@@ -1112,7 +1109,7 @@ static void acpi_device_get_busid(struct acpi_device *device)
         * The device's Bus ID is simply the object name.
         * TBD: Shouldn't this value be unique (within the ACPI namespace)?
         */
-       if (ACPI_IS_ROOT_DEVICE(device)) {
+       if (!acpi_dev_parent(device)) {
                strcpy(device->pnp.bus_id, "ACPI");
                return;
        }
@@ -1467,25 +1464,21 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
  * acpi_dma_get_range() - Get device DMA parameters.
  *
  * @dev: device to configure
- * @dma_addr: pointer device DMA address result
- * @offset: pointer to the DMA offset result
- * @size: pointer to DMA range size result
+ * @map: pointer to DMA ranges result
  *
- * Evaluate DMA regions and return respectively DMA region start, offset
- * and size in dma_addr, offset and size on parsing success; it does not
- * update the passed in values on failure.
+ * Evaluate DMA regions and return pointer to DMA regions on
+ * parsing success; it does not update the passed in values on failure.
  *
  * Return 0 on success, < 0 on failure.
  */
-int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
-                      u64 *size)
+int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
 {
        struct acpi_device *adev;
        LIST_HEAD(list);
        struct resource_entry *rentry;
        int ret;
        struct device *dma_dev = dev;
-       u64 len, dma_start = U64_MAX, dma_end = 0, dma_offset = 0;
+       struct bus_dma_region *r;
 
        /*
         * Walk the device tree chasing an ACPI companion with a _DMA
@@ -1510,31 +1503,28 @@ int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
 
        ret = acpi_dev_get_dma_resources(adev, &list);
        if (ret > 0) {
+               r = kcalloc(ret + 1, sizeof(*r), GFP_KERNEL);
+               if (!r) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
                list_for_each_entry(rentry, &list, node) {
-                       if (dma_offset && rentry->offset != dma_offset) {
+                       if (rentry->res->start >= rentry->res->end) {
+                               kfree(r);
                                ret = -EINVAL;
-                               dev_warn(dma_dev, "Can't handle multiple windows with different offsets\n");
+                               dev_dbg(dma_dev, "Invalid DMA regions configuration\n");
                                goto out;
                        }
-                       dma_offset = rentry->offset;
 
-                       /* Take lower and upper limits */
-                       if (rentry->res->start < dma_start)
-                               dma_start = rentry->res->start;
-                       if (rentry->res->end > dma_end)
-                               dma_end = rentry->res->end;
-               }
-
-               if (dma_start >= dma_end) {
-                       ret = -EINVAL;
-                       dev_dbg(dma_dev, "Invalid DMA regions configuration\n");
-                       goto out;
+                       r->cpu_start = rentry->res->start;
+                       r->dma_start = rentry->res->start - rentry->offset;
+                       r->size = resource_size(rentry->res);
+                       r->offset = rentry->offset;
+                       r++;
                }
 
-               *dma_addr = dma_start - dma_offset;
-               len = dma_end - dma_start;
-               *size = max(len, len + 1);
-               *offset = dma_offset;
+               *map = r;
        }
  out:
        acpi_dev_free_resource_list(&list);
@@ -1624,20 +1614,19 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
                          const u32 *input_id)
 {
        const struct iommu_ops *iommu;
-       u64 dma_addr = 0, size = 0;
 
        if (attr == DEV_DMA_NOT_SUPPORTED) {
                set_dma_ops(dev, &dma_dummy_ops);
                return 0;
        }
 
-       acpi_arch_dma_setup(dev, &dma_addr, &size);
+       acpi_arch_dma_setup(dev);
 
        iommu = acpi_iommu_configure_id(dev, input_id);
        if (PTR_ERR(iommu) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
 
-       arch_setup_dma_ops(dev, dma_addr, size,
+       arch_setup_dma_ops(dev, 0, U64_MAX,
                                iommu, attr == DEV_DMA_COHERENT);
 
        return 0;
@@ -1648,7 +1637,7 @@ static void acpi_init_coherency(struct acpi_device *adev)
 {
        unsigned long long cca = 0;
        acpi_status status;
-       struct acpi_device *parent = adev->parent;
+       struct acpi_device *parent = acpi_dev_parent(adev);
 
        if (parent && parent->flags.cca_seen) {
                /*
@@ -1692,7 +1681,7 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data)
 
 static bool acpi_is_indirect_io_slave(struct acpi_device *device)
 {
-       struct acpi_device *parent = device->parent;
+       struct acpi_device *parent = acpi_dev_parent(device);
        static const struct acpi_device_id indirect_io_hosts[] = {
                {"HISI0191", 0},
                {}
@@ -1762,12 +1751,16 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
 }
 
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
-                            int type)
+                            int type, void (*release)(struct device *))
 {
+       struct acpi_device *parent = acpi_find_parent_acpi_dev(handle);
+
        INIT_LIST_HEAD(&device->pnp.ids);
        device->device_type = type;
        device->handle = handle;
-       device->parent = acpi_bus_get_parent(handle);
+       device->dev.parent = parent ? &parent->dev : NULL;
+       device->dev.release = release;
+       device->dev.bus = &acpi_bus_type;
        fwnode_init(&device->fwnode, &acpi_device_fwnode_ops);
        acpi_set_device_status(device, ACPI_STA_DEFAULT);
        acpi_device_get_busid(device);
@@ -1821,7 +1814,7 @@ static int acpi_add_single_object(struct acpi_device **child,
        if (!device)
                return -ENOMEM;
 
-       acpi_init_device_object(device, handle, type);
+       acpi_init_device_object(device, handle, type, acpi_device_release);
        /*
         * Getting the status is delayed till here so that we can call
         * acpi_bus_get_status() and use its quirk handling.  Note that
@@ -1851,7 +1844,7 @@ static int acpi_add_single_object(struct acpi_device **child,
                mutex_unlock(&acpi_dep_list_lock);
 
        if (!result)
-               result = __acpi_device_add(device, acpi_device_release);
+               result = acpi_device_add(device);
 
        if (result) {
                acpi_device_release(&device->dev);
@@ -1862,8 +1855,8 @@ static int acpi_add_single_object(struct acpi_device **child,
        acpi_device_add_finalize(device);
 
        acpi_handle_debug(handle, "Added as %s, parent %s\n",
-                         dev_name(&device->dev), device->parent ?
-                               dev_name(&device->parent->dev) : "(null)");
+                         dev_name(&device->dev), device->dev.parent ?
+                               dev_name(device->dev.parent) : "(null)");
 
        *child = device;
        return 0;
@@ -2235,11 +2228,24 @@ ok:
        return 0;
 }
 
-static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
+static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
 {
-       struct acpi_device *adev;
+       struct acpi_device **adev_p = data;
+       struct acpi_device *adev = *adev_p;
 
-       adev = acpi_bus_get_acpi_device(dep->consumer);
+       /*
+        * If we're passed a 'previous' consumer device then we need to skip
+        * any consumers until we meet the previous one, and then NULL @data
+        * so the next one can be returned.
+        */
+       if (adev) {
+               if (dep->consumer == adev->handle)
+                       *adev_p = NULL;
+
+               return 0;
+       }
+
+       adev = acpi_get_acpi_dev(dep->consumer);
        if (adev) {
                *(struct acpi_device **)data = adev;
                return 1;
@@ -2292,7 +2298,7 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
 
 static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
 {
-       struct acpi_device *adev = acpi_bus_get_acpi_device(dep->consumer);
+       struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer);
 
        if (adev) {
                adev->dep_unmet--;
@@ -2368,25 +2374,32 @@ bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
 EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
 
 /**
- * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
+ * acpi_dev_get_next_consumer_dev - Return the next adev dependent on @supplier
  * @supplier: Pointer to the dependee device
+ * @start: Pointer to the current dependent device
  *
- * Returns the first &struct acpi_device which declares itself dependent on
+ * Returns the next &struct acpi_device which declares itself dependent on
  * @supplier via the _DEP buffer, parsed from the acpi_dep_list.
  *
- * The caller is responsible for putting the reference to adev when it is no
- * longer needed.
+ * If the returned adev is not passed as @start to this function, the caller is
+ * responsible for putting the reference to adev when it is no longer needed.
  */
-struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier)
+struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
+                                                  struct acpi_device *start)
 {
-       struct acpi_device *adev = NULL;
+       struct acpi_device *adev = start;
 
        acpi_walk_dep_device_list(supplier->handle,
-                                 acpi_dev_get_first_consumer_dev_cb, &adev);
+                                 acpi_dev_get_next_consumer_dev_cb, &adev);
+
+       acpi_dev_put(start);
+
+       if (adev == start)
+               return NULL;
 
        return adev;
 }
-EXPORT_SYMBOL_GPL(acpi_dev_get_first_consumer_dev);
+EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev);
 
 /**
  * acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
index 5a7b806..2ea1464 100644 (file)
@@ -794,6 +794,30 @@ bool acpi_dev_hid_uid_match(struct acpi_device *adev,
 EXPORT_SYMBOL(acpi_dev_hid_uid_match);
 
 /**
+ * acpi_dev_uid_to_integer - treat ACPI device _UID as integer
+ * @adev: ACPI device to get _UID from
+ * @integer: output buffer for integer
+ *
+ * Considers _UID as integer and converts it to @integer.
+ *
+ * Returns 0 on success, or negative error code otherwise.
+ */
+int acpi_dev_uid_to_integer(struct acpi_device *adev, u64 *integer)
+{
+       const char *uid;
+
+       if (!adev)
+               return -ENODEV;
+
+       uid = acpi_device_uid(adev);
+       if (!uid)
+               return -ENODATA;
+
+       return kstrtou64(uid, 0, integer);
+}
+EXPORT_SYMBOL(acpi_dev_uid_to_integer);
+
+/**
  * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
  * @hid: Hardware ID of the device.
  *
@@ -878,7 +902,7 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
        struct acpi_dev_match_info match = {};
        struct device *dev;
 
-       strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
+       strscpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
        match.uid = uid;
        match.hrv = hrv;
 
@@ -911,7 +935,7 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const cha
        struct acpi_dev_match_info match = {};
        struct device *dev;
 
-       strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
+       strscpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
        match.uid = uid;
        match.hrv = hrv;
 
@@ -961,7 +985,7 @@ EXPORT_SYMBOL(acpi_video_backlight_string);
 
 static int __init acpi_backlight(char *str)
 {
-       strlcpy(acpi_video_backlight_string, str,
+       strscpy(acpi_video_backlight_string, str,
                sizeof(acpi_video_backlight_string));
        return 1;
 }
index c285c91..8812ecd 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/bitmap.h>
 #include <linux/platform_data/x86/apple.h>
 #include <linux/uuid.h>
+#include "../internal.h"
 
 /* Apple _DSM device properties GUID */
 static const guid_t apple_prp_guid =
index f9ac12b..0155c1d 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/acpi.h>
 #include <linux/device.h>
+#include <linux/dmi.h>
 #include <linux/suspend.h>
 
 #include "../sleep.h"
@@ -27,6 +28,10 @@ static bool sleep_no_lps0 __read_mostly;
 module_param(sleep_no_lps0, bool, 0644);
 MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
 
+static bool prefer_microsoft_dsm_guid __read_mostly;
+module_param(prefer_microsoft_dsm_guid, bool, 0644);
+MODULE_PARM_DESC(prefer_microsoft_dsm_guid, "Prefer using Microsoft GUID in LPS0 device _DSM evaluation");
+
 static const struct acpi_device_id lps0_device_ids[] = {
        {"PNP0D80", },
        {"", },
@@ -363,40 +368,132 @@ out:
        return ret;
 }
 
+struct amd_lps0_hid_device_data {
+       const unsigned int rev_id;
+       const bool check_off_by_one;
+       const bool prefer_amd_guid;
+};
+
+static const struct amd_lps0_hid_device_data amd_picasso = {
+       .rev_id = 0,
+       .check_off_by_one = true,
+       .prefer_amd_guid = false,
+};
+
+static const struct amd_lps0_hid_device_data amd_cezanne = {
+       .rev_id = 0,
+       .check_off_by_one = false,
+       .prefer_amd_guid = false,
+};
+
+static const struct amd_lps0_hid_device_data amd_rembrandt = {
+       .rev_id = 2,
+       .check_off_by_one = false,
+       .prefer_amd_guid = true,
+};
+
+static const struct acpi_device_id amd_hid_ids[] = {
+       {"AMD0004",     (kernel_ulong_t)&amd_picasso,   },
+       {"AMD0005",     (kernel_ulong_t)&amd_picasso,   },
+       {"AMDI0005",    (kernel_ulong_t)&amd_picasso,   },
+       {"AMDI0006",    (kernel_ulong_t)&amd_cezanne,   },
+       {"AMDI0007",    (kernel_ulong_t)&amd_rembrandt, },
+       {}
+};
+
+static int lps0_prefer_microsoft(const struct dmi_system_id *id)
+{
+       pr_debug("Preferring Microsoft GUID.\n");
+       prefer_microsoft_dsm_guid = true;
+       return 0;
+}
+
+static const struct dmi_system_id s2idle_dmi_table[] __initconst = {
+       {
+               /*
+                * ASUS TUF Gaming A17 FA707RE
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216101
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ASUS TUF Gaming A17"),
+               },
+       },
+       {
+               /* ASUS ROG Zephyrus G14 (2022) */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ROG Zephyrus G14 GA402"),
+               },
+       },
+       {
+               /*
+                * Lenovo Yoga Slim 7 Pro X 14ARH7
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216473 : 82V2
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216438 : 82TL
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "82"),
+               },
+       },
+       {
+               /*
+                * ASUSTeK COMPUTER INC. ROG Flow X13 GV301RE_GV301RE
+                * https://gitlab.freedesktop.org/drm/amd/-/issues/2148
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X13 GV301"),
+               },
+       },
+       {
+               /*
+                * ASUSTeK COMPUTER INC. ROG Flow X16 GV601RW_GV601RW
+                * https://gitlab.freedesktop.org/drm/amd/-/issues/2148
+                */
+               .callback = lps0_prefer_microsoft,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow X16 GV601"),
+               },
+       },
+       {}
+};
+
 static int lps0_device_attach(struct acpi_device *adev,
                              const struct acpi_device_id *not_used)
 {
        if (lps0_device_handle)
                return 0;
 
+       lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
+                                                   ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
+                                                   &lps0_dsm_guid_microsoft);
        if (acpi_s2idle_vendor_amd()) {
-               /* AMD0004, AMD0005, AMDI0005:
-                * - Should use rev_id 0x0
-                * - function mask > 0x3: Should use AMD method, but has off by one bug
-                * - function mask = 0x3: Should use Microsoft method
-                * AMDI0006:
-                * - should use rev_id 0x0
-                * - function mask = 0x3: Should use Microsoft method
-                * AMDI0007:
-                * - Should use rev_id 0x2
-                * - Should only use AMD method
-                */
-               const char *hid = acpi_device_hid(adev);
-               rev_id = strcmp(hid, "AMDI0007") ? 0 : 2;
+               static const struct acpi_device_id *dev_id;
+               const struct amd_lps0_hid_device_data *data;
+
+               for (dev_id = &amd_hid_ids[0]; dev_id->id[0]; dev_id++)
+                       if (acpi_dev_hid_uid_match(adev, dev_id->id, NULL))
+                               break;
+               if (dev_id->id[0])
+                       data = (const struct amd_lps0_hid_device_data *) dev_id->driver_data;
+               else
+                       data = &amd_rembrandt;
+               rev_id = data->rev_id;
                lps0_dsm_func_mask = validate_dsm(adev->handle,
                                        ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
-               lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
-                                       ACPI_LPS0_DSM_UUID_MICROSOFT, 0,
-                                       &lps0_dsm_guid_microsoft);
-               if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
-                                                !strcmp(hid, "AMD0005") ||
-                                                !strcmp(hid, "AMDI0005"))) {
+               if (lps0_dsm_func_mask > 0x3 && data->check_off_by_one) {
                        lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
                        acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
                                          ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
-               } else if (lps0_dsm_func_mask_microsoft > 0 &&
-                               (!strcmp(hid, "AMDI0007") ||
-                                !strcmp(hid, "AMDI0008"))) {
+               } else if (lps0_dsm_func_mask_microsoft > 0 && data->prefer_amd_guid &&
+                               !prefer_microsoft_dsm_guid) {
                        lps0_dsm_func_mask_microsoft = -EINVAL;
                        acpi_handle_debug(adev->handle, "_DSM Using AMD method\n");
                }
@@ -404,7 +501,8 @@ static int lps0_device_attach(struct acpi_device *adev,
                rev_id = 1;
                lps0_dsm_func_mask = validate_dsm(adev->handle,
                                        ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
-               lps0_dsm_func_mask_microsoft = -EINVAL;
+               if (!prefer_microsoft_dsm_guid)
+                       lps0_dsm_func_mask_microsoft = -EINVAL;
        }
 
        if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
@@ -533,8 +631,9 @@ static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
        .end = acpi_s2idle_end,
 };
 
-void acpi_s2idle_setup(void)
+void __init acpi_s2idle_setup(void)
 {
+       dmi_check_system(s2idle_dmi_table);
        acpi_scan_add_handler(&lps0_handler);
        s2idle_set_ops(&acpi_s2idle_ops_lps0);
 }
index 664070f..f8a2cbd 100644 (file)
@@ -207,9 +207,26 @@ static const struct x86_cpu_id storage_d3_cpu_ids[] = {
        {}
 };
 
+static const struct dmi_system_id force_storage_d3_dmi[] = {
+       {
+               /*
+                * _ADR is ambiguous between GPP1.DEV0 and GPP1.NVME
+                * but .NVME is needed to get StorageD3Enable node
+                * https://bugzilla.kernel.org/show_bug.cgi?id=216440
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 14 7425 2-in-1"),
+               }
+       },
+       {}
+};
+
 bool force_storage_d3(void)
 {
-       return x86_match_cpu(storage_d3_cpu_ids);
+       const struct dmi_system_id *dmi_id = dmi_first_match(force_storage_d3_dmi);
+
+       return dmi_id || x86_match_cpu(storage_d3_cpu_ids);
 }
 
 /*
@@ -351,11 +368,17 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
        struct acpi_device *adev = ACPI_COMPANION(controller_parent);
        const struct dmi_system_id *dmi_id;
        long quirks = 0;
+       u64 uid;
+       int ret;
 
        *skip = false;
 
-       /* !dev_is_platform() to not match on PNP enumerated debug UARTs */
-       if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
+       ret = acpi_dev_uid_to_integer(adev, &uid);
+       if (ret)
+               return 0;
+
+       /* to not match on PNP enumerated debug UARTs */
+       if (!dev_is_platform(controller_parent))
                return 0;
 
        dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
@@ -363,10 +386,10 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
                quirks = (unsigned long)dmi_id->driver_data;
 
        if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
-               if (!strcmp(adev->pnp.unique_id, "1"))
+               if (uid == 1)
                        return -ENODEV; /* Create tty cdev instead of serdev */
 
-               if (!strcmp(adev->pnp.unique_id, "2"))
+               if (uid == 2)
                        *skip = true;
        }
 
index 32b0e0b..110a535 100644 (file)
@@ -209,6 +209,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
        struct amba_device *pcdev = to_amba_device(dev);
        struct amba_driver *pcdrv = to_amba_driver(drv);
 
+       mutex_lock(&pcdev->periphid_lock);
        if (!pcdev->periphid) {
                int ret = amba_read_periphid(pcdev);
 
@@ -218,11 +219,14 @@ static int amba_match(struct device *dev, struct device_driver *drv)
                 * permanent failure in reading pid and cid, simply map it to
                 * -EPROBE_DEFER.
                 */
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&pcdev->periphid_lock);
                        return -EPROBE_DEFER;
+               }
                dev_set_uevent_suppress(dev, false);
                kobject_uevent(&dev->kobj, KOBJ_ADD);
        }
+       mutex_unlock(&pcdev->periphid_lock);
 
        /* When driver_override is set, only bind to the matching driver */
        if (pcdev->driver_override)
@@ -532,6 +536,7 @@ static void amba_device_release(struct device *dev)
 
        if (d->res.parent)
                release_resource(&d->res);
+       mutex_destroy(&d->periphid_lock);
        kfree(d);
 }
 
@@ -584,6 +589,7 @@ static void amba_device_initialize(struct amba_device *dev, const char *name)
        dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
        dev->dev.dma_parms = &dev->dma_parms;
        dev->res.name = dev_name(&dev->dev);
+       mutex_init(&dev->periphid_lock);
 }
 
 /**
index c964d7c..6428f6b 100644 (file)
@@ -1385,6 +1385,18 @@ static int binder_inc_ref_for_node(struct binder_proc *proc,
        }
        ret = binder_inc_ref_olocked(ref, strong, target_list);
        *rdata = ref->data;
+       if (ret && ref == new_ref) {
+               /*
+                * Cleanup the failed reference here as the target
+                * could now be dead and have already released its
+                * references by now. Calling on the new reference
+                * with strong=0 and a tmp_refs will not decrement
+                * the node. The new_ref gets kfree'd below.
+                */
+               binder_cleanup_ref_olocked(new_ref);
+               ref = NULL;
+       }
+
        binder_proc_unlock(proc);
        if (new_ref && ref != new_ref)
                /*
index 51f4e1c..9b1778c 100644 (file)
@@ -322,7 +322,6 @@ static inline void binder_alloc_set_vma(struct binder_alloc *alloc,
         */
        if (vma) {
                vm_start = vma->vm_start;
-               alloc->vma_vm_mm = vma->vm_mm;
                mmap_assert_write_locked(alloc->vma_vm_mm);
        } else {
                mmap_assert_locked(alloc->vma_vm_mm);
@@ -795,7 +794,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
        binder_insert_free_buffer(alloc, buffer);
        alloc->free_async_space = alloc->buffer_size / 2;
        binder_alloc_set_vma(alloc, vma);
-       mmgrab(alloc->vma_vm_mm);
 
        return 0;
 
@@ -1091,6 +1089,8 @@ static struct shrinker binder_shrinker = {
 void binder_alloc_init(struct binder_alloc *alloc)
 {
        alloc->pid = current->group_leader->pid;
+       alloc->vma_vm_mm = current->mm;
+       mmgrab(alloc->vma_vm_mm);
        mutex_init(&alloc->mutex);
        INIT_LIST_HEAD(&alloc->buffers);
 }
index 826d41f..c9a9aa6 100644 (file)
@@ -3988,6 +3988,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* These specific Pioneer models have LPM issues */
+       { "PIONEER BD-RW   BDR-207M",   NULL,   ATA_HORKAGE_NOLPM },
+       { "PIONEER BD-RW   BDR-205",    NULL,   ATA_HORKAGE_NOLPM },
+
        /* Crucial BX100 SSD 500GB has broken LPM support */
        { "CT500BX100SSD1",             NULL,   ATA_HORKAGE_NOLPM },
 
index 7a5fe41..13b9d0f 100644 (file)
@@ -1018,26 +1018,25 @@ DEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show,
 EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
 
 /**
- *     __ata_change_queue_depth - helper for ata_scsi_change_queue_depth
- *     @ap: ATA port to which the device change the queue depth
+ *     ata_change_queue_depth - Set a device maximum queue depth
+ *     @ap: ATA port of the target device
+ *     @dev: target ATA device
  *     @sdev: SCSI device to configure queue depth for
  *     @queue_depth: new queue depth
  *
- *     libsas and libata have different approaches for associating a sdev to
- *     its ata_port.
+ *     Helper to set a device maximum queue depth, usable with both libsas
+ *     and libata.
  *
  */
-int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
-                            int queue_depth)
+int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
+                          struct scsi_device *sdev, int queue_depth)
 {
-       struct ata_device *dev;
        unsigned long flags;
 
-       if (queue_depth < 1 || queue_depth == sdev->queue_depth)
+       if (!dev || !ata_dev_enabled(dev))
                return sdev->queue_depth;
 
-       dev = ata_scsi_find_dev(ap, sdev);
-       if (!dev || !ata_dev_enabled(dev))
+       if (queue_depth < 1 || queue_depth == sdev->queue_depth)
                return sdev->queue_depth;
 
        /* NCQ enabled? */
@@ -1059,7 +1058,7 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
 
        return scsi_change_queue_depth(sdev, queue_depth);
 }
-EXPORT_SYMBOL_GPL(__ata_change_queue_depth);
+EXPORT_SYMBOL_GPL(ata_change_queue_depth);
 
 /**
  *     ata_scsi_change_queue_depth - SCSI callback for queue depth config
@@ -1080,7 +1079,8 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
 {
        struct ata_port *ap = ata_shost_to_port(sdev->host);
 
-       return __ata_change_queue_depth(ap, sdev, queue_depth);
+       return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev),
+                                     sdev, queue_depth);
 }
 EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
 
index 29e2f55..ff9602a 100644 (file)
@@ -1055,6 +1055,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_dma_need_drain);
 int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
 {
        struct request_queue *q = sdev->request_queue;
+       int depth = 1;
 
        if (!ata_id_has_unload(dev->id))
                dev->flags |= ATA_DFLAG_NO_UNLOAD;
@@ -1100,13 +1101,10 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
        if (dev->flags & ATA_DFLAG_AN)
                set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
 
-       if (dev->flags & ATA_DFLAG_NCQ) {
-               int depth;
-
+       if (dev->flags & ATA_DFLAG_NCQ)
                depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
-               depth = min(ATA_MAX_QUEUE, depth);
-               scsi_change_queue_depth(sdev, depth);
-       }
+       depth = min(ATA_MAX_QUEUE, depth);
+       scsi_change_queue_depth(sdev, depth);
 
        if (dev->flags & ATA_DFLAG_TRUSTED)
                sdev->security_supported = 1;
index 0424b59..dd90591 100644 (file)
@@ -353,7 +353,7 @@ void topology_init_cpu_capacity_cppc(void)
        struct cppc_perf_caps perf_caps;
        int cpu;
 
-       if (likely(acpi_disabled || !acpi_cpc_valid()))
+       if (likely(!acpi_cpc_valid()))
                return;
 
        raw_capacity = kcalloc(num_possible_cpus(), sizeof(*raw_capacity),
@@ -724,7 +724,7 @@ const struct cpumask *cpu_clustergroup_mask(int cpu)
         */
        if (cpumask_subset(cpu_coregroup_mask(cpu),
                           &cpu_topology[cpu].cluster_sibling))
-               return get_cpu_mask(cpu);
+               return topology_sibling_cpumask(cpu);
 
        return &cpu_topology[cpu].cluster_sibling;
 }
@@ -735,7 +735,7 @@ void update_siblings_masks(unsigned int cpuid)
        int cpu, ret;
 
        ret = detect_cache_attributes(cpuid);
-       if (ret)
+       if (ret && ret != -ENOENT)
                pr_info("Early cacheinfo failed, ret = %d\n", ret);
 
        /* update core and thread sibling masks */
index 753e7cc..5fb4bc5 100644 (file)
@@ -1625,7 +1625,7 @@ static int __init fw_devlink_setup(char *arg)
 }
 early_param("fw_devlink", fw_devlink_setup);
 
-static bool fw_devlink_strict = true;
+static bool fw_devlink_strict;
 static int __init fw_devlink_strict_setup(char *arg)
 {
        return strtobool(arg, &fw_devlink_strict);
index 70f79fc..ec69b43 100644 (file)
@@ -274,12 +274,42 @@ static int __init deferred_probe_timeout_setup(char *str)
 }
 __setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
 
+/**
+ * driver_deferred_probe_check_state() - Check deferred probe state
+ * @dev: device to check
+ *
+ * Return:
+ * * -ENODEV if initcalls have completed and modules are disabled.
+ * * -ETIMEDOUT if the deferred probe timeout was set and has expired
+ *   and modules are enabled.
+ * * -EPROBE_DEFER in other cases.
+ *
+ * Drivers or subsystems can opt-in to calling this function instead of directly
+ * returning -EPROBE_DEFER.
+ */
+int driver_deferred_probe_check_state(struct device *dev)
+{
+       if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) {
+               dev_warn(dev, "ignoring dependency for device, assuming no driver\n");
+               return -ENODEV;
+       }
+
+       if (!driver_deferred_probe_timeout && initcalls_done) {
+               dev_warn(dev, "deferred probe timeout, ignoring dependency\n");
+               return -ETIMEDOUT;
+       }
+
+       return -EPROBE_DEFER;
+}
+EXPORT_SYMBOL_GPL(driver_deferred_probe_check_state);
+
 static void deferred_probe_timeout_work_func(struct work_struct *work)
 {
        struct device_private *p;
 
        fw_devlink_drivers_done();
 
+       driver_deferred_probe_timeout = 0;
        driver_deferred_probe_trigger();
        flush_work(&deferred_probe_work);
 
@@ -881,6 +911,11 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
                dev_dbg(dev, "Device match requests probe deferral\n");
                dev->can_match = true;
                driver_deferred_probe_add(dev);
+               /*
+                * Device can't match with a driver right now, so don't attempt
+                * to match or bind with other drivers on the bus.
+                */
+               return ret;
        } else if (ret < 0) {
                dev_dbg(dev, "Bus failed to match device: %d\n", ret);
                return ret;
@@ -1120,6 +1155,11 @@ static int __driver_attach(struct device *dev, void *data)
                dev_dbg(dev, "Device match requests probe deferral\n");
                dev->can_match = true;
                driver_deferred_probe_add(dev);
+               /*
+                * Driver could not match with device, but may match with
+                * another device on the bus.
+                */
+               return 0;
        } else if (ret < 0) {
                dev_dbg(dev, "Bus failed to match device: %d\n", ret);
                return ret;
index 15a75af..676b627 100644 (file)
@@ -63,6 +63,12 @@ int driver_set_override(struct device *dev, const char **override,
        if (len >= (PAGE_SIZE - 1))
                return -EINVAL;
 
+       /*
+        * Compute the real length of the string in case userspace sends us a
+        * bunch of \0 characters like python likes to do.
+        */
+       len = strlen(s);
+
        if (!len) {
                /* Empty string passed - clear override */
                device_lock(dev);
index 77bad32..5b66b3d 100644 (file)
@@ -93,10 +93,9 @@ static void fw_dev_release(struct device *dev)
 {
        struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev);
 
-       if (fw_sysfs->fw_upload_priv) {
-               free_fw_priv(fw_sysfs->fw_priv);
-               kfree(fw_sysfs->fw_upload_priv);
-       }
+       if (fw_sysfs->fw_upload_priv)
+               fw_upload_free(fw_sysfs);
+
        kfree(fw_sysfs);
 }
 
index 5d8ff16..df1d5ad 100644 (file)
@@ -106,12 +106,17 @@ extern struct device_attribute dev_attr_cancel;
 extern struct device_attribute dev_attr_remaining_size;
 
 int fw_upload_start(struct fw_sysfs *fw_sysfs);
+void fw_upload_free(struct fw_sysfs *fw_sysfs);
 umode_t fw_upload_is_visible(struct kobject *kobj, struct attribute *attr, int n);
 #else
 static inline int fw_upload_start(struct fw_sysfs *fw_sysfs)
 {
        return 0;
 }
+
+static inline void fw_upload_free(struct fw_sysfs *fw_sysfs)
+{
+}
 #endif
 
 #endif /* __FIRMWARE_SYSFS_H */
index 87044d5..a0af8f5 100644 (file)
@@ -264,6 +264,15 @@ int fw_upload_start(struct fw_sysfs *fw_sysfs)
        return 0;
 }
 
+void fw_upload_free(struct fw_sysfs *fw_sysfs)
+{
+       struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv;
+
+       free_fw_priv(fw_sysfs->fw_priv);
+       kfree(fw_upload_priv->fw_upload);
+       kfree(fw_upload_priv);
+}
+
 /**
  * firmware_upload_register() - register for the firmware upload sysfs API
  * @module: kernel module of this device
@@ -377,6 +386,7 @@ void firmware_upload_unregister(struct fw_upload *fw_upload)
 {
        struct fw_sysfs *fw_sysfs = fw_upload->priv;
        struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv;
+       struct module *module = fw_upload_priv->module;
 
        mutex_lock(&fw_upload_priv->lock);
        if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) {
@@ -392,6 +402,6 @@ void firmware_upload_unregister(struct fw_upload *fw_upload)
 
 unregister:
        device_unregister(&fw_sysfs->dev);
-       module_put(fw_upload_priv->module);
+       module_put(module);
 }
 EXPORT_SYMBOL_GPL(firmware_upload_unregister);
index 5a2e023..55a10e6 100644 (file)
@@ -2733,7 +2733,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
                mutex_unlock(&gpd_list_lock);
                dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
                        __func__, PTR_ERR(pd));
-               return -ENODEV;
+               return driver_deferred_probe_check_state(base_dev);
        }
 
        dev_dbg(dev, "adding to PM domain %s\n", pd->name);
index 997be3a..b520490 100644 (file)
@@ -792,10 +792,13 @@ static int rpm_resume(struct device *dev, int rpmflags)
                DEFINE_WAIT(wait);
 
                if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
-                       if (dev->power.runtime_status == RPM_SUSPENDING)
+                       if (dev->power.runtime_status == RPM_SUSPENDING) {
                                dev->power.deferred_resume = true;
-                       else
+                               if (rpmflags & RPM_NOWAIT)
+                                       retval = -EINPROGRESS;
+                       } else {
                                retval = -EINPROGRESS;
+                       }
                        goto out;
                }
 
index e3befa2..7cc0c0c 100644 (file)
@@ -944,6 +944,8 @@ void pm_system_irq_wakeup(unsigned int irq_number)
        else
                irq_number = 0;
 
+       pm_pr_dbg("Triggering wakeup from IRQ %d\n", irq_number);
+
        raw_spin_unlock_irqrestore(&wakeup_irq_lock, flags);
 
        if (irq_number)
index 719323b..37ab23a 100644 (file)
@@ -113,6 +113,7 @@ static const struct regmap_bus *regmap_get_spi_bus(struct spi_device *spi,
                                                   const struct regmap_config *config)
 {
        size_t max_size = spi_max_transfer_size(spi);
+       size_t max_msg_size, reg_reserve_size;
        struct regmap_bus *bus;
 
        if (max_size != SIZE_MAX) {
@@ -120,9 +121,16 @@ static const struct regmap_bus *regmap_get_spi_bus(struct spi_device *spi,
                if (!bus)
                        return ERR_PTR(-ENOMEM);
 
+               max_msg_size = spi_max_message_size(spi);
+               reg_reserve_size = config->reg_bits / BITS_PER_BYTE
+                                + config->pad_bits / BITS_PER_BYTE;
+               if (max_size + reg_reserve_size > max_msg_size)
+                       max_size -= reg_reserve_size;
+
                bus->free_on_exit = true;
                bus->max_raw_read = max_size;
                bus->max_raw_write = max_size;
+
                return bus;
        }
 
index 30255fc..dd9a051 100644 (file)
@@ -322,14 +322,14 @@ static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx,
        if (unlikely(status))
                return status;
 
-       blk_mq_start_request(req);
-
        vbr->sg_table.nents = virtblk_map_data(hctx, req, vbr);
        if (unlikely(vbr->sg_table.nents < 0)) {
                virtblk_cleanup_cmd(req);
                return BLK_STS_RESOURCE;
        }
 
+       blk_mq_start_request(req);
+
        return BLK_STS_OK;
 }
 
@@ -391,8 +391,7 @@ static bool virtblk_prep_rq_batch(struct request *req)
 }
 
 static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
-                                       struct request **rqlist,
-                                       struct request **requeue_list)
+                                       struct request **rqlist)
 {
        unsigned long flags;
        int err;
@@ -408,7 +407,7 @@ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
                if (err) {
                        virtblk_unmap_data(req, vbr);
                        virtblk_cleanup_cmd(req);
-                       rq_list_add(requeue_list, req);
+                       blk_mq_requeue_request(req, true);
                }
        }
 
@@ -436,7 +435,7 @@ static void virtio_queue_rqs(struct request **rqlist)
 
                if (!next || req->mq_hctx != next->mq_hctx) {
                        req->rq_next = NULL;
-                       kick = virtblk_add_req_batch(vq, rqlist, &requeue_list);
+                       kick = virtblk_add_req_batch(vq, rqlist);
                        if (kick)
                                virtqueue_notify(vq->vq);
 
index bda5c81..a284734 100644 (file)
@@ -226,6 +226,9 @@ struct xen_vbd {
        sector_t                size;
        unsigned int            flush_support:1;
        unsigned int            discard_secure:1;
+       /* Connect-time cached feature_persistent parameter value */
+       unsigned int            feature_gnt_persistent_parm:1;
+       /* Persistent grants feature negotiation result */
        unsigned int            feature_gnt_persistent:1;
        unsigned int            overflow_max_grants:1;
 };
index ee7ad2f..c0227df 100644 (file)
@@ -907,7 +907,7 @@ again:
        xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
 
        err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u",
-                       be->blkif->vbd.feature_gnt_persistent);
+                       be->blkif->vbd.feature_gnt_persistent_parm);
        if (err) {
                xenbus_dev_fatal(dev, err, "writing %s/feature-persistent",
                                 dev->nodename);
@@ -1085,7 +1085,9 @@ static int connect_ring(struct backend_info *be)
                return -ENOSYS;
        }
 
-       blkif->vbd.feature_gnt_persistent = feature_persistent &&
+       blkif->vbd.feature_gnt_persistent_parm = feature_persistent;
+       blkif->vbd.feature_gnt_persistent =
+               blkif->vbd.feature_gnt_persistent_parm &&
                xenbus_read_unsigned(dev->otherend, "feature-persistent", 0);
 
        blkif->vbd.overflow_max_grants = 0;
index 8e56e69..35b9bca 100644 (file)
@@ -213,6 +213,9 @@ struct blkfront_info
        unsigned int feature_fua:1;
        unsigned int feature_discard:1;
        unsigned int feature_secdiscard:1;
+       /* Connect-time cached feature_persistent parameter */
+       unsigned int feature_persistent_parm:1;
+       /* Persistent grants feature negotiation result */
        unsigned int feature_persistent:1;
        unsigned int bounce:1;
        unsigned int discard_granularity;
@@ -1756,6 +1759,12 @@ abort_transaction:
        return err;
 }
 
+/* Enable the persistent grants feature. */
+static bool feature_persistent = true;
+module_param(feature_persistent, bool, 0644);
+MODULE_PARM_DESC(feature_persistent,
+               "Enables the persistent grants feature");
+
 /* Common code used when first setting up, and when resuming. */
 static int talk_to_blkback(struct xenbus_device *dev,
                           struct blkfront_info *info)
@@ -1847,8 +1856,9 @@ again:
                message = "writing protocol";
                goto abort_transaction;
        }
+       info->feature_persistent_parm = feature_persistent;
        err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u",
-                       info->feature_persistent);
+                       info->feature_persistent_parm);
        if (err)
                dev_warn(&dev->dev,
                         "writing persistent grants feature to xenbus");
@@ -1916,12 +1926,6 @@ static int negotiate_mq(struct blkfront_info *info)
        return 0;
 }
 
-/* Enable the persistent grants feature. */
-static bool feature_persistent = true;
-module_param(feature_persistent, bool, 0644);
-MODULE_PARM_DESC(feature_persistent,
-               "Enables the persistent grants feature");
-
 /*
  * Entry point to this code when a new device is created.  Allocate the basic
  * structures and the ring buffer for communication with the backend, and
@@ -2281,7 +2285,7 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
        if (xenbus_read_unsigned(info->xbdev->otherend, "feature-discard", 0))
                blkfront_setup_discard(info);
 
-       if (feature_persistent)
+       if (info->feature_persistent_parm)
                info->feature_persistent =
                        !!xenbus_read_unsigned(info->xbdev->otherend,
                                               "feature-persistent", 0);
index f3aef77..df0fbfe 100644 (file)
@@ -430,12 +430,25 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
 {
        struct mhi_event *mhi_event = dev;
        struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
-       struct mhi_event_ctxt *er_ctxt =
-               &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+       struct mhi_event_ctxt *er_ctxt;
        struct mhi_ring *ev_ring = &mhi_event->ring;
-       dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
+       dma_addr_t ptr;
        void *dev_rp;
 
+       /*
+        * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
+        * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
+        * before handling the IRQs.
+        */
+       if (!mhi_cntrl->mhi_ctxt) {
+               dev_dbg(&mhi_cntrl->mhi_dev->dev,
+                       "mhi_ctxt has been freed\n");
+               return IRQ_HANDLED;
+       }
+
+       er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+       ptr = le64_to_cpu(er_ctxt->rp);
+
        if (!is_valid_ring_ptr(ev_ring, ptr)) {
                dev_err(&mhi_cntrl->mhi_dev->dev,
                        "Event ring rp points outside of the event ring\n");
index 84ca98e..32a932a 100644 (file)
@@ -480,6 +480,11 @@ static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out,
        return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
 }
 
+static int uring_cmd_null(struct io_uring_cmd *ioucmd, unsigned int issue_flags)
+{
+       return 0;
+}
+
 static ssize_t read_iter_zero(struct kiocb *iocb, struct iov_iter *iter)
 {
        size_t written = 0;
@@ -663,6 +668,7 @@ static const struct file_operations null_fops = {
        .read_iter      = read_iter_null,
        .write_iter     = write_iter_null,
        .splice_write   = splice_write_null,
+       .uring_cmd      = uring_cmd_null,
 };
 
 static const struct file_operations __maybe_unused port_fops = {
index 1a098db..680f9d8 100644 (file)
@@ -726,6 +726,7 @@ void iproc_pll_clk_setup(struct device_node *node,
        const char *parent_name;
        struct iproc_clk *iclk_array;
        struct clk_hw_onecell_data *clk_data;
+       const char *clk_name;
 
        if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl))
                return;
@@ -773,7 +774,12 @@ void iproc_pll_clk_setup(struct device_node *node,
        iclk = &iclk_array[0];
        iclk->pll = pll;
 
-       init.name = node->name;
+       ret = of_property_read_string_index(node, "clock-output-names",
+                                           0, &clk_name);
+       if (WARN_ON(ret))
+               goto err_pll_register;
+
+       init.name = clk_name;
        init.ops = &iproc_pll_ops;
        init.flags = 0;
        parent_name = of_clk_get_parent_name(node, 0);
@@ -793,13 +799,11 @@ void iproc_pll_clk_setup(struct device_node *node,
                goto err_pll_register;
 
        clk_data->hws[0] = &iclk->hw;
+       parent_name = clk_name;
 
        /* now initialize and register all leaf clocks */
        for (i = 1; i < num_clks; i++) {
-               const char *clk_name;
-
                memset(&init, 0, sizeof(init));
-               parent_name = node->name;
 
                ret = of_property_read_string_index(node, "clock-output-names",
                                                    i, &clk_name);
index 7351800..876b37b 100644 (file)
@@ -203,7 +203,7 @@ static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw,
        ret = raspberrypi_clock_property(rpi->firmware, data,
                                         RPI_FIRMWARE_GET_CLOCK_RATE, &val);
        if (ret)
-               return ret;
+               return 0;
 
        return val;
 }
@@ -220,7 +220,7 @@ static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
        ret = raspberrypi_clock_property(rpi->firmware, data,
                                         RPI_FIRMWARE_SET_CLOCK_RATE, &_rate);
        if (ret)
-               dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
+               dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d\n",
                                    clk_hw_get_name(hw), ret);
 
        return ret;
@@ -288,7 +288,7 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
                                         RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
                                         &min_rate);
        if (ret) {
-               dev_err(rpi->dev, "Failed to get clock %d min freq: %d",
+               dev_err(rpi->dev, "Failed to get clock %d min freq: %d\n",
                        id, ret);
                return ERR_PTR(ret);
        }
@@ -344,8 +344,13 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
        struct rpi_firmware_get_clocks_response *clks;
        int ret;
 
+       /*
+        * The firmware doesn't guarantee that the last element of
+        * RPI_FIRMWARE_GET_CLOCKS is zeroed. So allocate an additional
+        * zero element as sentinel.
+        */
        clks = devm_kcalloc(rpi->dev,
-                           RPI_FIRMWARE_NUM_CLK_ID, sizeof(*clks),
+                           RPI_FIRMWARE_NUM_CLK_ID + 1, sizeof(*clks),
                            GFP_KERNEL);
        if (!clks)
                return -ENOMEM;
@@ -360,7 +365,8 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
                struct raspberrypi_clk_variant *variant;
 
                if (clks->id > RPI_FIRMWARE_NUM_CLK_ID) {
-                       dev_err(rpi->dev, "Unknown clock id: %u", clks->id);
+                       dev_err(rpi->dev, "Unknown clock id: %u (max: %u)\n",
+                                          clks->id, RPI_FIRMWARE_NUM_CLK_ID);
                        return -EINVAL;
                }
 
index e5fbefd..38f44b5 100644 (file)
@@ -200,7 +200,9 @@ static int tps68470_clk_probe(struct platform_device *pdev)
                .flags = CLK_SET_RATE_GATE,
        };
        struct tps68470_clkdata *tps68470_clkdata;
+       struct tps68470_clk_consumer *consumer;
        int ret;
+       int i;
 
        tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata),
                                        GFP_KERNEL);
@@ -223,10 +225,13 @@ static int tps68470_clk_probe(struct platform_device *pdev)
                return ret;
 
        if (pdata) {
-               ret = devm_clk_hw_register_clkdev(&pdev->dev,
-                                                 &tps68470_clkdata->clkout_hw,
-                                                 pdata->consumer_con_id,
-                                                 pdata->consumer_dev_name);
+               for (i = 0; i < pdata->n_consumers; i++) {
+                       consumer = &pdata->consumers[i];
+                       ret = devm_clk_hw_register_clkdev(&pdev->dev,
+                                                         &tps68470_clkdata->clkout_hw,
+                                                         consumer->consumer_con_id,
+                                                         consumer->consumer_dev_name);
+               }
        }
 
        return ret;
index 7fc191c..bd0b35c 100644 (file)
@@ -840,10 +840,9 @@ static void clk_core_unprepare(struct clk_core *core)
        if (core->ops->unprepare)
                core->ops->unprepare(core->hw);
 
-       clk_pm_runtime_put(core);
-
        trace_clk_unprepare_complete(core);
        clk_core_unprepare(core->parent);
+       clk_pm_runtime_put(core);
 }
 
 static void clk_core_unprepare_lock(struct clk_core *core)
index fc1bd23..598f3cf 100644 (file)
@@ -280,13 +280,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
        hws[IMX6SX_CLK_SSI3_SEL]           = imx_clk_hw_mux("ssi3_sel",         base + 0x1c,  14,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
        hws[IMX6SX_CLK_SSI2_SEL]           = imx_clk_hw_mux("ssi2_sel",         base + 0x1c,  12,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
        hws[IMX6SX_CLK_SSI1_SEL]           = imx_clk_hw_mux("ssi1_sel",         base + 0x1c,  10,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
-       hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux_flags("qspi1_sel", base + 0x1c,  7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux("qspi1_sel",        base + 0x1c,  7,      3,      qspi1_sels,        ARRAY_SIZE(qspi1_sels));
        hws[IMX6SX_CLK_PERCLK_SEL]         = imx_clk_hw_mux("perclk_sel",       base + 0x1c,  6,      1,      perclk_sels,       ARRAY_SIZE(perclk_sels));
        hws[IMX6SX_CLK_VID_SEL]            = imx_clk_hw_mux("vid_sel",          base + 0x20,  21,     3,      vid_sels,          ARRAY_SIZE(vid_sels));
        hws[IMX6SX_CLK_ESAI_SEL]           = imx_clk_hw_mux("esai_sel",         base + 0x20,  19,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
        hws[IMX6SX_CLK_CAN_SEL]            = imx_clk_hw_mux("can_sel",          base + 0x20,  8,      2,      can_sels,          ARRAY_SIZE(can_sels));
        hws[IMX6SX_CLK_UART_SEL]           = imx_clk_hw_mux("uart_sel",         base + 0x24,  6,      1,      uart_sels,         ARRAY_SIZE(uart_sels));
-       hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
+       hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux("qspi2_sel",        base + 0x2c,  15,     3,      qspi2_sels,        ARRAY_SIZE(qspi2_sels));
        hws[IMX6SX_CLK_SPDIF_SEL]          = imx_clk_hw_mux("spdif_sel",        base + 0x30,  20,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
        hws[IMX6SX_CLK_AUDIO_SEL]          = imx_clk_hw_mux("audio_sel",        base + 0x30,  7,      2,      audio_sels,        ARRAY_SIZE(audio_sels));
        hws[IMX6SX_CLK_ENET_PRE_SEL]       = imx_clk_hw_mux("enet_pre_sel",     base + 0x34,  15,     3,      enet_pre_sels,     ARRAY_SIZE(enet_pre_sels));
index f5c9fa4..dcc41d1 100644 (file)
@@ -332,7 +332,7 @@ static struct platform_driver imx93_clk_driver = {
        .driver = {
                .name = "imx93-ccm",
                .suppress_bind_attrs = true,
-               .of_match_table = of_match_ptr(imx93_clk_of_match),
+               .of_match_table = imx93_clk_of_match,
        },
 };
 module_platform_driver(imx93_clk_driver);
index 201bf6e..d5544cb 100644 (file)
@@ -101,15 +101,11 @@ static bool ingenic_tcu_enable_regs(struct clk_hw *hw)
        bool enabled = false;
 
        /*
-        * If the SoC has no global TCU clock, we must ungate the channel's
-        * clock to be able to access its registers.
-        * If we have a TCU clock, it will be enabled automatically as it has
-        * been attached to the regmap.
+        * According to the programming manual, a timer channel's registers can
+        * only be accessed when the channel's stop bit is clear.
         */
-       if (!tcu->clk) {
-               enabled = !!ingenic_tcu_is_enabled(hw);
-               regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
-       }
+       enabled = !!ingenic_tcu_is_enabled(hw);
+       regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
 
        return enabled;
 }
@@ -120,8 +116,7 @@ static void ingenic_tcu_disable_regs(struct clk_hw *hw)
        const struct ingenic_tcu_clk_info *info = tcu_clk->info;
        struct ingenic_tcu *tcu = tcu_clk->tcu;
 
-       if (!tcu->clk)
-               regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
+       regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
 }
 
 static u8 ingenic_tcu_get_parent(struct clk_hw *hw)
index 070c3b8..b6b8941 100644 (file)
@@ -239,6 +239,11 @@ static const struct clk_ops mpfs_clk_cfg_ops = {
        .hw.init = CLK_HW_INIT(_name, _parent, &mpfs_clk_cfg_ops, 0),                   \
 }
 
+#define CLK_CPU_OFFSET         0u
+#define CLK_AXI_OFFSET         1u
+#define CLK_AHB_OFFSET         2u
+#define CLK_RTCREF_OFFSET      3u
+
 static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = {
        CLK_CFG(CLK_CPU, "clk_cpu", "clk_msspll", 0, 2, mpfs_div_cpu_axi_table, 0,
                REG_CLOCK_CONFIG_CR),
@@ -362,7 +367,7 @@ static const struct clk_ops mpfs_periph_clk_ops = {
                                  _flags),                                      \
 }
 
-#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT].hw)
+#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT##_OFFSET].hw)
 
 /*
  * Critical clocks:
@@ -370,6 +375,8 @@ static const struct clk_ops mpfs_periph_clk_ops = {
  *   trap handler
  * - CLK_MMUART0: reserved by the hss
  * - CLK_DDRC: provides clock to the ddr subsystem
+ * - CLK_RTC: the onboard RTC's AHB bus clock must be kept running as the rtc will stop
+ *   if the AHB interface clock is disabled
  * - CLK_FICx: these provide the processor side clocks to the "FIC" (Fabric InterConnect)
  *   clock domain crossers which provide the interface to the FPGA fabric. Disabling them
  *   causes the FPGA fabric to go into reset.
@@ -394,7 +401,7 @@ static struct mpfs_periph_hw_clock mpfs_periph_clks[] = {
        CLK_PERIPH(CLK_CAN0, "clk_periph_can0", PARENT_CLK(AHB), 14, 0),
        CLK_PERIPH(CLK_CAN1, "clk_periph_can1", PARENT_CLK(AHB), 15, 0),
        CLK_PERIPH(CLK_USB, "clk_periph_usb", PARENT_CLK(AHB), 16, 0),
-       CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, 0),
+       CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, CLK_IS_CRITICAL),
        CLK_PERIPH(CLK_QSPI, "clk_periph_qspi", PARENT_CLK(AHB), 19, 0),
        CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", PARENT_CLK(AHB), 20, 0),
        CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", PARENT_CLK(AHB), 21, 0),
index 30056da..42568c6 100644 (file)
@@ -1191,9 +1191,13 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
        if (IS_ERR(reg))
                return PTR_ERR(reg);
 
-       /* Force PLL_GPU output divider bits to 0 */
+       /*
+        * Force PLL_GPU output divider bits to 0 and adjust
+        * multiplier to sensible default value of 432 MHz.
+        */
        val = readl(reg + SUN50I_H6_PLL_GPU_REG);
-       val &= ~BIT(0);
+       val &= ~(GENMASK(15, 8) | BIT(0));
+       val |= 17 << 8;
        writel(val, reg + SUN50I_H6_PLL_GPU_REG);
 
        /* Force GPU_CLK divider bits to 0 */
index ef2a445..373e943 100644 (file)
@@ -135,6 +135,7 @@ static struct device_node *ti_find_clock_provider(struct device_node *from,
                        continue;
 
                if (!strncmp(n, tmp, strlen(tmp))) {
+                       of_node_get(np);
                        found = true;
                        break;
                }
index 62c2b7a..4407203 100644 (file)
@@ -449,6 +449,9 @@ static int quad8_events_configure(struct counter_device *counter)
                        return -EINVAL;
                }
 
+               /* Enable IRQ line */
+               irq_enabled |= BIT(event_node->channel);
+
                /* Skip configuration if it is the same as previously set */
                if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
                        continue;
@@ -462,9 +465,6 @@ static int quad8_events_configure(struct counter_device *counter)
                          priv->irq_trigger[event_node->channel] << 3;
                iowrite8(QUAD8_CTR_IOR | ior_cfg,
                         &priv->reg->channel[event_node->channel].control);
-
-               /* Enable IRQ line */
-               irq_enabled |= BIT(event_node->channel);
        }
 
        iowrite8(irq_enabled, &priv->reg->index_interrupt);
index 9ac75c1..f52b8f2 100644 (file)
@@ -46,8 +46,8 @@
 #include <asm/cpu_device_id.h>
 #include "amd-pstate-trace.h"
 
-#define AMD_PSTATE_TRANSITION_LATENCY  0x20000
-#define AMD_PSTATE_TRANSITION_DELAY    500
+#define AMD_PSTATE_TRANSITION_LATENCY  20000
+#define AMD_PSTATE_TRANSITION_DELAY    1000
 
 /*
  * TODO: We need more time to fine tune processors with shared memory solution
@@ -120,7 +120,7 @@ struct amd_cpudata {
        struct amd_aperf_mperf cur;
        struct amd_aperf_mperf prev;
 
-       u64 freq;
+       u64     freq;
        bool    boost_supported;
 };
 
@@ -152,6 +152,7 @@ static inline int amd_pstate_enable(bool enable)
 static int pstate_init_perf(struct amd_cpudata *cpudata)
 {
        u64 cap1;
+       u32 highest_perf;
 
        int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
                                     &cap1);
@@ -163,7 +164,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
         *
         * CPPC entry doesn't indicate the highest performance in some ASICs.
         */
-       WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf());
+       highest_perf = amd_get_highest_perf();
+       if (highest_perf > AMD_CPPC_HIGHEST_PERF(cap1))
+               highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
+
+       WRITE_ONCE(cpudata->highest_perf, highest_perf);
 
        WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
        WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
@@ -175,12 +180,17 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
 static int cppc_init_perf(struct amd_cpudata *cpudata)
 {
        struct cppc_perf_caps cppc_perf;
+       u32 highest_perf;
 
        int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
        if (ret)
                return ret;
 
-       WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf());
+       highest_perf = amd_get_highest_perf();
+       if (highest_perf > cppc_perf.highest_perf)
+               highest_perf = cppc_perf.highest_perf;
+
+       WRITE_ONCE(cpudata->highest_perf, highest_perf);
 
        WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
        WRITE_ONCE(cpudata->lowest_nonlinear_perf,
@@ -269,6 +279,7 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
        u64 prev = READ_ONCE(cpudata->cppc_req_cached);
        u64 value = prev;
 
+       des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
        value &= ~AMD_CPPC_MIN_PERF(~0L);
        value |= AMD_CPPC_MIN_PERF(min_perf);
 
@@ -312,7 +323,7 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
                return -ENODEV;
 
        cap_perf = READ_ONCE(cpudata->highest_perf);
-       min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
+       min_perf = READ_ONCE(cpudata->lowest_perf);
        max_perf = cap_perf;
 
        freqs.old = policy->cur;
@@ -357,8 +368,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
        if (max_perf < min_perf)
                max_perf = min_perf;
 
-       des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
-
        amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true);
 }
 
@@ -555,9 +564,7 @@ free_cpudata1:
 
 static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
 {
-       struct amd_cpudata *cpudata;
-
-       cpudata = policy->driver_data;
+       struct amd_cpudata *cpudata = policy->driver_data;
 
        freq_qos_remove_request(&cpudata->req[1]);
        freq_qos_remove_request(&cpudata->req[0]);
@@ -599,9 +606,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
                                        char *buf)
 {
        int max_freq;
-       struct amd_cpudata *cpudata;
-
-       cpudata = policy->driver_data;
+       struct amd_cpudata *cpudata = policy->driver_data;
 
        max_freq = amd_get_max_freq(cpudata);
        if (max_freq < 0)
@@ -614,9 +619,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli
                                                     char *buf)
 {
        int freq;
-       struct amd_cpudata *cpudata;
-
-       cpudata = policy->driver_data;
+       struct amd_cpudata *cpudata = policy->driver_data;
 
        freq = amd_get_lowest_nonlinear_freq(cpudata);
        if (freq < 0)
@@ -662,7 +665,7 @@ static struct cpufreq_driver amd_pstate_driver = {
        .resume         = amd_pstate_cpu_resume,
        .set_boost      = amd_pstate_set_boost,
        .name           = "amd-pstate",
-       .attr           = amd_pstate_attr,
+       .attr           = amd_pstate_attr,
 };
 
 static int __init amd_pstate_init(void)
@@ -673,7 +676,7 @@ static int __init amd_pstate_init(void)
                return -ENODEV;
 
        if (!acpi_cpc_valid()) {
-               pr_debug("the _CPC object is not present in SBIOS\n");
+               pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n");
                return -ENODEV;
        }
 
index f7c23fa..39221a9 100644 (file)
@@ -156,7 +156,7 @@ static struct cpufreq_driver bmips_cpufreq_driver = {
        .name           = BMIPS_CPUFREQ_PREFIX,
 };
 
-static int __init bmips_cpufreq_probe(void)
+static int __init bmips_cpufreq_driver_init(void)
 {
        struct cpufreq_compat *cc;
        struct device_node *np;
@@ -176,7 +176,13 @@ static int __init bmips_cpufreq_probe(void)
 
        return cpufreq_register_driver(&bmips_cpufreq_driver);
 }
-device_initcall(bmips_cpufreq_probe);
+module_init(bmips_cpufreq_driver_init);
+
+static void __exit bmips_cpufreq_driver_exit(void)
+{
+       cpufreq_unregister_driver(&bmips_cpufreq_driver);
+}
+module_exit(bmips_cpufreq_driver_exit);
 
 MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
 MODULE_DESCRIPTION("CPUfreq driver for Broadcom BMIPS SoCs");
index 24eaf0e..432dfb4 100644 (file)
@@ -63,7 +63,15 @@ static struct cppc_workaround_oem_info wa_info[] = {
 
 static struct cpufreq_driver cppc_cpufreq_driver;
 
+static enum {
+       FIE_UNSET = -1,
+       FIE_ENABLED,
+       FIE_DISABLED
+} fie_disabled = FIE_UNSET;
+
 #ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
+module_param(fie_disabled, int, 0444);
+MODULE_PARM_DESC(fie_disabled, "Disable Frequency Invariance Engine (FIE)");
 
 /* Frequency invariance support */
 struct cppc_freq_invariance {
@@ -158,7 +166,7 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
        struct cppc_freq_invariance *cppc_fi;
        int cpu, ret;
 
-       if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
+       if (fie_disabled)
                return;
 
        for_each_cpu(cpu, policy->cpus) {
@@ -199,7 +207,7 @@ static void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy)
        struct cppc_freq_invariance *cppc_fi;
        int cpu;
 
-       if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
+       if (fie_disabled)
                return;
 
        /* policy->cpus will be empty here, use related_cpus instead */
@@ -229,7 +237,15 @@ static void __init cppc_freq_invariance_init(void)
        };
        int ret;
 
-       if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
+       if (fie_disabled != FIE_ENABLED && fie_disabled != FIE_DISABLED) {
+               fie_disabled = FIE_ENABLED;
+               if (cppc_perf_ctrs_in_pcc()) {
+                       pr_info("FIE not enabled on systems with registers in PCC\n");
+                       fie_disabled = FIE_DISABLED;
+               }
+       }
+
+       if (fie_disabled)
                return;
 
        kworker_fie = kthread_create_worker(0, "cppc_fie");
@@ -247,7 +263,7 @@ static void __init cppc_freq_invariance_init(void)
 
 static void cppc_freq_invariance_exit(void)
 {
-       if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
+       if (fie_disabled)
                return;
 
        kthread_destroy_worker(kworker_fie);
@@ -936,6 +952,7 @@ static void cppc_check_hisi_workaround(void)
                    wa_info[i].oem_revision == tbl->oem_revision) {
                        /* Overwrite the get() callback */
                        cppc_cpufreq_driver.get = hisi_cppc_cpufreq_get_rate;
+                       fie_disabled = FIE_DISABLED;
                        break;
                }
        }
@@ -947,7 +964,7 @@ static int __init cppc_cpufreq_init(void)
 {
        int ret;
 
-       if ((acpi_disabled) || !acpi_cpc_valid())
+       if (!acpi_cpc_valid())
                return -ENODEV;
 
        cppc_check_hisi_workaround();
index 2c96de3..6ac3800 100644 (file)
@@ -146,6 +146,7 @@ static const struct of_device_id blocklist[] __initconst = {
        { .compatible = "qcom,sc8180x", },
        { .compatible = "qcom,sc8280xp", },
        { .compatible = "qcom,sdm845", },
+       { .compatible = "qcom,sm6115", },
        { .compatible = "qcom,sm6350", },
        { .compatible = "qcom,sm8150", },
        { .compatible = "qcom,sm8250", },
index ac57cdd..a458647 100644 (file)
@@ -55,7 +55,7 @@ static struct notifier_block hb_cpufreq_clk_nb = {
        .notifier_call = hb_cpufreq_clk_notify,
 };
 
-static int hb_cpufreq_driver_init(void)
+static int __init hb_cpufreq_driver_init(void)
 {
        struct platform_device_info devinfo = { .name = "cpufreq-dt", };
        struct device *cpu_dev;
index 57cdb36..fc3ebeb 100644 (file)
@@ -2416,6 +2416,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        X86_MATCH(SKYLAKE_X,            core_funcs),
        X86_MATCH(COMETLAKE,            core_funcs),
        X86_MATCH(ICELAKE_X,            core_funcs),
+       X86_MATCH(TIGERLAKE,            core_funcs),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
index d5ef3c6..833589b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/units.h>
@@ -56,6 +57,8 @@ struct qcom_cpufreq_data {
        struct cpufreq_policy *policy;
 
        bool per_core_dcvs;
+
+       struct freq_qos_request throttle_freq_req;
 };
 
 static unsigned long cpu_hw_rate, xo_rate;
@@ -316,14 +319,16 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
        if (IS_ERR(opp)) {
                dev_warn(dev, "Can't find the OPP for throttling: %pe!\n", opp);
        } else {
-               throttled_freq = freq_hz / HZ_PER_KHZ;
-
-               /* Update thermal pressure (the boost frequencies are accepted) */
-               arch_update_thermal_pressure(policy->related_cpus, throttled_freq);
-
                dev_pm_opp_put(opp);
        }
 
+       throttled_freq = freq_hz / HZ_PER_KHZ;
+
+       freq_qos_update_request(&data->throttle_freq_req, throttled_freq);
+
+       /* Update thermal pressure (the boost frequencies are accepted) */
+       arch_update_thermal_pressure(policy->related_cpus, throttled_freq);
+
        /*
         * In the unlikely case policy is unregistered do not enable
         * polling or h/w interrupt
@@ -413,6 +418,14 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
        if (data->throttle_irq < 0)
                return data->throttle_irq;
 
+       ret = freq_qos_add_request(&policy->constraints,
+                                  &data->throttle_freq_req, FREQ_QOS_MAX,
+                                  FREQ_QOS_MAX_DEFAULT_VALUE);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to add freq constraint (%d)\n", ret);
+               return ret;
+       }
+
        data->cancel_throttle = false;
        data->policy = policy;
 
@@ -479,6 +492,7 @@ static void qcom_cpufreq_hw_lmh_exit(struct qcom_cpufreq_data *data)
        if (data->throttle_irq <= 0)
                return;
 
+       freq_qos_remove_request(&data->throttle_freq_req);
        free_irq(data->throttle_irq, data);
 }
 
index a67df90..1a63aee 100644 (file)
@@ -252,7 +252,7 @@ static int sti_cpufreq_fetch_syscon_registers(void)
        return 0;
 }
 
-static int sti_cpufreq_init(void)
+static int __init sti_cpufreq_init(void)
 {
        int ret;
 
index 1216046..c2004ca 100644 (file)
 /* cpufreq transisition latency */
 #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */
 
-enum cluster {
-       CLUSTER0,
-       CLUSTER1,
-       CLUSTER2,
-       CLUSTER3,
-       MAX_CLUSTERS,
-};
-
 struct tegra_cpu_ctr {
        u32 cpu;
        u32 coreclk_cnt, last_coreclk_cnt;
@@ -67,12 +59,12 @@ struct tegra_cpufreq_ops {
 struct tegra_cpufreq_soc {
        struct tegra_cpufreq_ops *ops;
        int maxcpus_per_cluster;
+       unsigned int num_clusters;
        phys_addr_t actmon_cntr_base;
 };
 
 struct tegra194_cpufreq_data {
        void __iomem *regs;
-       size_t num_clusters;
        struct cpufreq_frequency_table **tables;
        const struct tegra_cpufreq_soc *soc;
 };
@@ -166,6 +158,14 @@ static const struct tegra_cpufreq_soc tegra234_cpufreq_soc = {
        .ops = &tegra234_cpufreq_ops,
        .actmon_cntr_base = 0x9000,
        .maxcpus_per_cluster = 4,
+       .num_clusters = 3,
+};
+
+static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = {
+       .ops = &tegra234_cpufreq_ops,
+       .actmon_cntr_base = 0x4000,
+       .maxcpus_per_cluster = 8,
+       .num_clusters = 1,
 };
 
 static void tegra194_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid)
@@ -314,11 +314,7 @@ static void tegra194_get_cpu_ndiv_sysreg(void *ndiv)
 
 static int tegra194_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
 {
-       int ret;
-
-       ret = smp_call_function_single(cpu, tegra194_get_cpu_ndiv_sysreg, &ndiv, true);
-
-       return ret;
+       return smp_call_function_single(cpu, tegra194_get_cpu_ndiv_sysreg, &ndiv, true);
 }
 
 static void tegra194_set_cpu_ndiv_sysreg(void *data)
@@ -382,7 +378,7 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
 
        data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid);
 
-       if (clusterid >= data->num_clusters || !data->tables[clusterid])
+       if (clusterid >= data->soc->num_clusters || !data->tables[clusterid])
                return -EINVAL;
 
        start_cpu = rounddown(policy->cpu, maxcpus_per_cluster);
@@ -433,6 +429,7 @@ static struct tegra_cpufreq_ops tegra194_cpufreq_ops = {
 static const struct tegra_cpufreq_soc tegra194_cpufreq_soc = {
        .ops = &tegra194_cpufreq_ops,
        .maxcpus_per_cluster = 2,
+       .num_clusters = 4,
 };
 
 static void tegra194_cpufreq_free_resources(void)
@@ -525,15 +522,14 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
 
        soc = of_device_get_match_data(&pdev->dev);
 
-       if (soc->ops && soc->maxcpus_per_cluster) {
+       if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters) {
                data->soc = soc;
        } else {
                dev_err(&pdev->dev, "soc data missing\n");
                return -EINVAL;
        }
 
-       data->num_clusters = MAX_CLUSTERS;
-       data->tables = devm_kcalloc(&pdev->dev, data->num_clusters,
+       data->tables = devm_kcalloc(&pdev->dev, data->soc->num_clusters,
                                    sizeof(*data->tables), GFP_KERNEL);
        if (!data->tables)
                return -ENOMEM;
@@ -558,7 +554,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
                goto put_bpmp;
        }
 
-       for (i = 0; i < data->num_clusters; i++) {
+       for (i = 0; i < data->soc->num_clusters; i++) {
                data->tables[i] = init_freq_table(pdev, bpmp, i);
                if (IS_ERR(data->tables[i])) {
                        err = PTR_ERR(data->tables[i]);
@@ -590,6 +586,7 @@ static int tegra194_cpufreq_remove(struct platform_device *pdev)
 static const struct of_device_id tegra194_cpufreq_of_match[] = {
        { .compatible = "nvidia,tegra194-ccplex", .data = &tegra194_cpufreq_soc },
        { .compatible = "nvidia,tegra234-ccplex-cluster", .data = &tegra234_cpufreq_soc },
+       { .compatible = "nvidia,tegra239-ccplex-cluster", .data = &tegra239_cpufreq_soc },
        { /* sentinel */ }
 };
 
index df85a77..f64180d 100644 (file)
@@ -398,7 +398,7 @@ fail_put_node:
        return ret;
 }
 
-static int ti_cpufreq_init(void)
+static int __init ti_cpufreq_init(void)
 {
        const struct of_device_id *match;
 
index 7406874..9acde71 100644 (file)
@@ -54,7 +54,7 @@
  * variable is not locked.  It is only written from the cpu that
  * it stores (or by the on/offlining cpu if that cpu is offline),
  * and only read after all the cpus are ready for the coupled idle
- * state are are no longer updating it.
+ * state are no longer updating it.
  *
  * Three atomic counters are used.  alive_count tracks the number
  * of cpus in the coupled set that are currently or soon will be
index c32c600..0b5461b 100644 (file)
@@ -233,8 +233,8 @@ static inline void add_powernv_state(int index, const char *name,
                                     unsigned int exit_latency,
                                     u64 psscr_val, u64 psscr_mask)
 {
-       strlcpy(powernv_states[index].name, name, CPUIDLE_NAME_LEN);
-       strlcpy(powernv_states[index].desc, name, CPUIDLE_NAME_LEN);
+       strscpy(powernv_states[index].name, name, CPUIDLE_NAME_LEN);
+       strscpy(powernv_states[index].desc, name, CPUIDLE_NAME_LEN);
        powernv_states[index].flags = flags;
        powernv_states[index].target_residency = target_residency;
        powernv_states[index].exit_latency = exit_latency;
index 29acaf4..0d0f975 100644 (file)
@@ -63,12 +63,11 @@ int cpuidle_switch_governor(struct cpuidle_governor *gov)
 
        cpuidle_curr_governor = gov;
 
-       if (gov) {
-               list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
-                       cpuidle_enable_device(dev);
-               cpuidle_install_idle_handler();
-               printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
-       }
+       list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
+               cpuidle_enable_device(dev);
+
+       cpuidle_install_idle_handler();
+       pr_info("cpuidle: using governor %s\n", gov->name);
 
        return 0;
 }
index 2a60d05..1681956 100644 (file)
@@ -56,6 +56,10 @@ static void virtio_crypto_akcipher_finalize_req(
        struct virtio_crypto_akcipher_request *vc_akcipher_req,
        struct akcipher_request *req, int err)
 {
+       kfree(vc_akcipher_req->src_buf);
+       kfree(vc_akcipher_req->dst_buf);
+       vc_akcipher_req->src_buf = NULL;
+       vc_akcipher_req->dst_buf = NULL;
        virtcrypto_clear_request(&vc_akcipher_req->base);
 
        crypto_finalize_akcipher_request(vc_akcipher_req->base.dataq->engine, req, err);
index cb6401c..acf31cc 100644 (file)
@@ -15,6 +15,7 @@ void hmem_register_device(int target_nid, struct resource *r)
                .start = r->start,
                .end = r->end,
                .flags = IORESOURCE_MEM,
+               .desc = IORES_DESC_SOFT_RESERVED,
        };
        struct platform_device *pdev;
        struct memregion_info info;
index 9a88faa..39ac069 100644 (file)
@@ -189,10 +189,9 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
                return PTR_ERR(data->regs);
 
        data->clk = devm_clk_get(dev, "pclk_ddr_mon");
-       if (IS_ERR(data->clk)) {
-               dev_err(dev, "Cannot get the clk dmc_clk\n");
-               return PTR_ERR(data->clk);
-       }
+       if (IS_ERR(data->clk))
+               return dev_err_probe(dev, PTR_ERR(data->clk),
+                                    "Cannot get the clk pclk_ddr_mon\n");
 
        /* try to find the optional reference to the pmu syscon */
        node = of_parse_phandle(np, "rockchip,pmu", 0);
index 71abb3f..e5458ad 100644 (file)
@@ -291,9 +291,13 @@ static int mtk_ccifreq_probe(struct platform_device *pdev)
        }
 
        drv->sram_reg = devm_regulator_get_optional(dev, "sram");
-       if (IS_ERR(drv->sram_reg))
+       if (IS_ERR(drv->sram_reg)) {
+               ret = PTR_ERR(drv->sram_reg);
+               if (ret == -EPROBE_DEFER)
+                       goto out_free_resources;
+
                drv->sram_reg = NULL;
-       else {
+       else {
                ret = regulator_enable(drv->sram_reg);
                if (ret) {
                        dev_err(dev, "failed to enable sram regulator\n");
index 205acb2..e3885c9 100644 (file)
@@ -295,7 +295,8 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
                enum dma_resv_usage old_usage;
 
                dma_resv_list_entry(fobj, i, obj, &old, &old_usage);
-               if ((old->context == fence->context && old_usage >= usage) ||
+               if ((old->context == fence->context && old_usage >= usage &&
+                    dma_fence_is_later(fence, old)) ||
                    dma_fence_is_signaled(old)) {
                        dma_resv_list_set(fobj, i, fence, usage);
                        dma_fence_put(old);
index d4f1e4e..85e0070 100644 (file)
@@ -31,14 +31,14 @@ struct udma_dev *of_xudma_dev_get(struct device_node *np, const char *property)
        }
 
        pdev = of_find_device_by_node(udma_node);
+       if (np != udma_node)
+               of_node_put(udma_node);
+
        if (!pdev) {
                pr_debug("UDMA device not found\n");
                return ERR_PTR(-EPROBE_DEFER);
        }
 
-       if (np != udma_node)
-               of_node_put(udma_node);
-
        ud = platform_get_drvdata(pdev);
        if (!ud) {
                pr_debug("UDMA has not been probed\n");
index 6276934..8cd4e69 100644 (file)
@@ -3040,9 +3040,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 
        /* Request and map I/O memory */
        xdev->regs = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(xdev->regs))
-               return PTR_ERR(xdev->regs);
-
+       if (IS_ERR(xdev->regs)) {
+               err = PTR_ERR(xdev->regs);
+               goto disable_clks;
+       }
        /* Retrieve the DMA engine properties from the device tree */
        xdev->max_buffer_len = GENMASK(XILINX_DMA_MAX_TRANS_LEN_MAX - 1, 0);
        xdev->s2mm_chan_id = xdev->dma_config->max_channels / 2;
@@ -3070,7 +3071,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
                if (err < 0) {
                        dev_err(xdev->dev,
                                "missing xlnx,num-fstores property\n");
-                       return err;
+                       goto disable_clks;
                }
 
                err = of_property_read_u32(node, "xlnx,flush-fsync",
@@ -3090,7 +3091,11 @@ static int xilinx_dma_probe(struct platform_device *pdev)
                xdev->ext_addr = false;
 
        /* Set the dma mask bits */
-       dma_set_mask_and_coherent(xdev->dev, DMA_BIT_MASK(addr_width));
+       err = dma_set_mask_and_coherent(xdev->dev, DMA_BIT_MASK(addr_width));
+       if (err < 0) {
+               dev_err(xdev->dev, "DMA mask error %d\n", err);
+               goto disable_clks;
+       }
 
        /* Initialize the DMA engine */
        xdev->common.dev = &pdev->dev;
@@ -3137,7 +3142,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
        for_each_child_of_node(node, child) {
                err = xilinx_dma_child_probe(xdev, child);
                if (err < 0)
-                       goto disable_clks;
+                       goto error;
        }
 
        if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
@@ -3172,12 +3177,12 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 
        return 0;
 
-disable_clks:
-       xdma_disable_allclks(xdev);
 error:
        for (i = 0; i < xdev->dma_config->max_channels; i++)
                if (xdev->chan[i])
                        xilinx_dma_chan_remove(xdev->chan[i]);
+disable_clks:
+       xdma_disable_allclks(xdev);
 
        return err;
 }
index dc299ab..3f4ee39 100644 (file)
@@ -849,7 +849,7 @@ static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy(
 
        zynqmp_dma_desc_config_eod(chan, desc);
        async_tx_ack(&first->async_tx);
-       first->async_tx.flags = flags;
+       first->async_tx.flags = (enum dma_ctrl_flags)flags;
        return &first->async_tx;
 }
 
index 3ed7ae0..96060bf 100644 (file)
@@ -450,9 +450,13 @@ static int scmi_clock_count_get(const struct scmi_protocol_handle *ph)
 static const struct scmi_clock_info *
 scmi_clock_info_get(const struct scmi_protocol_handle *ph, u32 clk_id)
 {
+       struct scmi_clock_info *clk;
        struct clock_info *ci = ph->get_priv(ph);
-       struct scmi_clock_info *clk = ci->clk + clk_id;
 
+       if (clk_id >= ci->num_clocks)
+               return NULL;
+
+       clk = ci->clk + clk_id;
        if (!clk->name[0])
                return NULL;
 
index 8abace5..f42dad9 100644 (file)
@@ -106,6 +106,7 @@ enum scmi_optee_pta_cmd {
  * @channel_id: OP-TEE channel ID used for this transport
  * @tee_session: TEE session identifier
  * @caps: OP-TEE SCMI channel capabilities
+ * @rx_len: Response size
  * @mu: Mutex protection on channel access
  * @cinfo: SCMI channel information
  * @shmem: Virtual base address of the shared memory
index 673f3eb..e9afa8c 100644 (file)
@@ -166,9 +166,13 @@ static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
        struct scmi_xfer *t;
        struct scmi_msg_reset_domain_reset *dom;
        struct scmi_reset_info *pi = ph->get_priv(ph);
-       struct reset_dom_info *rdom = pi->dom_info + domain;
+       struct reset_dom_info *rdom;
 
-       if (rdom->async_reset)
+       if (domain >= pi->num_domains)
+               return -EINVAL;
+
+       rdom = pi->dom_info + domain;
+       if (rdom->async_reset && flags & AUTONOMOUS_RESET)
                flags |= ASYNCHRONOUS_RESET;
 
        ret = ph->xops->xfer_get_init(ph, RESET, sizeof(*dom), 0, &t);
@@ -180,7 +184,7 @@ static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
        dom->flags = cpu_to_le32(flags);
        dom->reset_state = cpu_to_le32(state);
 
-       if (rdom->async_reset)
+       if (flags & ASYNCHRONOUS_RESET)
                ret = ph->xops->do_xfer_with_response(ph, t);
        else
                ret = ph->xops->do_xfer(ph, t);
index 581d34c..0e05a79 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/pm_clock.h>
 #include <linux/pm_domain.h>
 #include <linux/scmi_protocol.h>
 
@@ -53,27 +52,6 @@ static int scmi_pd_power_off(struct generic_pm_domain *domain)
        return scmi_pd_power(domain, false);
 }
 
-static int scmi_pd_attach_dev(struct generic_pm_domain *pd, struct device *dev)
-{
-       int ret;
-
-       ret = pm_clk_create(dev);
-       if (ret)
-               return ret;
-
-       ret = of_pm_clk_add_clks(dev);
-       if (ret >= 0)
-               return 0;
-
-       pm_clk_destroy(dev);
-       return ret;
-}
-
-static void scmi_pd_detach_dev(struct generic_pm_domain *pd, struct device *dev)
-{
-       pm_clk_destroy(dev);
-}
-
 static int scmi_pm_domain_probe(struct scmi_device *sdev)
 {
        int num_domains, i;
@@ -124,10 +102,6 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
                scmi_pd->genpd.name = scmi_pd->name;
                scmi_pd->genpd.power_off = scmi_pd_power_off;
                scmi_pd->genpd.power_on = scmi_pd_power_on;
-               scmi_pd->genpd.attach_dev = scmi_pd_attach_dev;
-               scmi_pd->genpd.detach_dev = scmi_pd_detach_dev;
-               scmi_pd->genpd.flags = GENPD_FLAG_PM_CLK |
-                                      GENPD_FLAG_ACTIVE_WAKEUP;
 
                pm_genpd_init(&scmi_pd->genpd, NULL,
                              state == SCMI_POWER_STATE_GENERIC_OFF);
@@ -138,9 +112,28 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
        scmi_pd_data->domains = domains;
        scmi_pd_data->num_domains = num_domains;
 
+       dev_set_drvdata(dev, scmi_pd_data);
+
        return of_genpd_add_provider_onecell(np, scmi_pd_data);
 }
 
+static void scmi_pm_domain_remove(struct scmi_device *sdev)
+{
+       int i;
+       struct genpd_onecell_data *scmi_pd_data;
+       struct device *dev = &sdev->dev;
+       struct device_node *np = dev->of_node;
+
+       of_genpd_del_provider(np);
+
+       scmi_pd_data = dev_get_drvdata(dev);
+       for (i = 0; i < scmi_pd_data->num_domains; i++) {
+               if (!scmi_pd_data->domains[i])
+                       continue;
+               pm_genpd_remove(scmi_pd_data->domains[i]);
+       }
+}
+
 static const struct scmi_device_id scmi_id_table[] = {
        { SCMI_PROTOCOL_POWER, "genpd" },
        { },
@@ -150,6 +143,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table);
 static struct scmi_driver scmi_power_domain_driver = {
        .name = "scmi-power-domain",
        .probe = scmi_pm_domain_probe,
+       .remove = scmi_pm_domain_remove,
        .id_table = scmi_id_table,
 };
 module_scmi_driver(scmi_power_domain_driver);
index 7288c61..0b5853f 100644 (file)
@@ -762,6 +762,10 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
 {
        int ret;
        struct scmi_xfer *t;
+       struct sensors_info *si = ph->get_priv(ph);
+
+       if (sensor_id >= si->num_sensors)
+               return -EINVAL;
 
        ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_GET,
                                      sizeof(__le32), sizeof(__le32), &t);
@@ -771,7 +775,6 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
        put_unaligned_le32(sensor_id, t->tx.buf);
        ret = ph->xops->do_xfer(ph, t);
        if (!ret) {
-               struct sensors_info *si = ph->get_priv(ph);
                struct scmi_sensor_info *s = si->sensors + sensor_id;
 
                *sensor_config = get_unaligned_le64(t->rx.buf);
@@ -788,6 +791,10 @@ static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
        int ret;
        struct scmi_xfer *t;
        struct scmi_msg_sensor_config_set *msg;
+       struct sensors_info *si = ph->get_priv(ph);
+
+       if (sensor_id >= si->num_sensors)
+               return -EINVAL;
 
        ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_SET,
                                      sizeof(*msg), 0, &t);
@@ -800,7 +807,6 @@ static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
 
        ret = ph->xops->do_xfer(ph, t);
        if (!ret) {
-               struct sensors_info *si = ph->get_priv(ph);
                struct scmi_sensor_info *s = si->sensors + sensor_id;
 
                s->sensor_config = sensor_config;
@@ -831,8 +837,11 @@ static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
        int ret;
        struct scmi_xfer *t;
        struct scmi_msg_sensor_reading_get *sensor;
+       struct scmi_sensor_info *s;
        struct sensors_info *si = ph->get_priv(ph);
-       struct scmi_sensor_info *s = si->sensors + sensor_id;
+
+       if (sensor_id >= si->num_sensors)
+               return -EINVAL;
 
        ret = ph->xops->xfer_get_init(ph, SENSOR_READING_GET,
                                      sizeof(*sensor), 0, &t);
@@ -841,6 +850,7 @@ static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
 
        sensor = t->tx.buf;
        sensor->id = cpu_to_le32(sensor_id);
+       s = si->sensors + sensor_id;
        if (s->async) {
                sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
                ret = ph->xops->do_xfer_with_response(ph, t);
@@ -895,9 +905,13 @@ scmi_sensor_reading_get_timestamped(const struct scmi_protocol_handle *ph,
        int ret;
        struct scmi_xfer *t;
        struct scmi_msg_sensor_reading_get *sensor;
+       struct scmi_sensor_info *s;
        struct sensors_info *si = ph->get_priv(ph);
-       struct scmi_sensor_info *s = si->sensors + sensor_id;
 
+       if (sensor_id >= si->num_sensors)
+               return -EINVAL;
+
+       s = si->sensors + sensor_id;
        if (!count || !readings ||
            (!s->num_axis && count > 1) || (s->num_axis && count > s->num_axis))
                return -EINVAL;
@@ -948,6 +962,9 @@ scmi_sensor_info_get(const struct scmi_protocol_handle *ph, u32 sensor_id)
 {
        struct sensors_info *si = ph->get_priv(ph);
 
+       if (sensor_id >= si->num_sensors)
+               return NULL;
+
        return si->sensors + sensor_id;
 }
 
index 4dde8ed..3e8d4b5 100644 (file)
@@ -243,29 +243,6 @@ failed:
 }
 
 /**
- * efi_capsule_flush - called by file close or file flush
- * @file: file pointer
- * @id: not used
- *
- *     If a capsule is being partially uploaded then calling this function
- *     will be treated as upload termination and will free those completed
- *     buffer pages and -ECANCELED will be returned.
- **/
-static int efi_capsule_flush(struct file *file, fl_owner_t id)
-{
-       int ret = 0;
-       struct capsule_info *cap_info = file->private_data;
-
-       if (cap_info->index > 0) {
-               pr_err("capsule upload not complete\n");
-               efi_free_all_buff_pages(cap_info);
-               ret = -ECANCELED;
-       }
-
-       return ret;
-}
-
-/**
  * efi_capsule_release - called by file close
  * @inode: not used
  * @file: file pointer
@@ -277,6 +254,13 @@ static int efi_capsule_release(struct inode *inode, struct file *file)
 {
        struct capsule_info *cap_info = file->private_data;
 
+       if (cap_info->index > 0 &&
+           (cap_info->header.headersize == 0 ||
+            cap_info->count < cap_info->total_size)) {
+               pr_err("capsule upload not complete\n");
+               efi_free_all_buff_pages(cap_info);
+       }
+
        kfree(cap_info->pages);
        kfree(cap_info->phys);
        kfree(file->private_data);
@@ -324,7 +308,6 @@ static const struct file_operations efi_capsule_fops = {
        .owner = THIS_MODULE,
        .open = efi_capsule_open,
        .write = efi_capsule_write,
-       .flush = efi_capsule_flush,
        .release = efi_capsule_release,
        .llseek = no_llseek,
 };
index eb9c65f..f80d87c 100644 (file)
 static long __init parse_acpi_path(const struct efi_dev_path *node,
                                   struct device *parent, struct device **child)
 {
-       char hid[ACPI_ID_LEN], uid[11]; /* UINT_MAX + null byte */
        struct acpi_device *adev;
        struct device *phys_dev;
+       char hid[ACPI_ID_LEN];
+       u64 uid;
+       int ret;
 
        if (node->header.length != 12)
                return -EINVAL;
@@ -27,12 +29,12 @@ static long __init parse_acpi_path(const struct efi_dev_path *node,
                'A' + ((node->acpi.hid >>  5) & 0x1f) - 1,
                'A' + ((node->acpi.hid >>  0) & 0x1f) - 1,
                        node->acpi.hid >> 16);
-       sprintf(uid, "%u", node->acpi.uid);
 
        for_each_acpi_dev_match(adev, hid, NULL, -1) {
-               if (adev->pnp.unique_id && !strcmp(adev->pnp.unique_id, uid))
+               ret = acpi_dev_uid_to_integer(adev, &uid);
+               if (ret == 0 && node->acpi.uid == uid)
                        break;
-               if (!adev->pnp.unique_id && node->acpi.uid == 0)
+               if (ret == -ENODATA && node->acpi.uid == 0)
                        break;
        }
        if (!adev)
index 8ced7af..4f9fb08 100644 (file)
@@ -48,6 +48,9 @@ static int efibc_reboot_notifier_call(struct notifier_block *notifier,
                return NOTIFY_DONE;
 
        wdata = kmalloc(MAX_DATA_LEN * sizeof(efi_char16_t), GFP_KERNEL);
+       if (!wdata)
+               return NOTIFY_DONE;
+
        for (l = 0; l < MAX_DATA_LEN - 1 && str[l] != '\0'; l++)
                wdata[l] = str[l];
        wdata[l] = L'\0';
index d053757..2c67f71 100644 (file)
@@ -37,6 +37,13 @@ KBUILD_CFLAGS                        := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
                                   $(call cc-option,-fno-addrsig) \
                                   -D__DISABLE_EXPORTS
 
+#
+# struct randomization only makes sense for Linux internal types, which the EFI
+# stub code never touches, so let's turn off struct randomization for the stub
+# altogether
+#
+KBUILD_CFLAGS := $(filter-out $(RANDSTRUCT_CFLAGS), $(KBUILD_CFLAGS))
+
 # remove SCS flags from all objects in this directory
 KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_SCS), $(KBUILD_CFLAGS))
 # disable LTO
index 8a18930..516f4f0 100644 (file)
@@ -14,7 +14,7 @@
 
 /* SHIM variables */
 static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
-static const efi_char16_t shim_MokSBState_name[] = L"MokSBState";
+static const efi_char16_t shim_MokSBState_name[] = L"MokSBStateRT";
 
 static efi_status_t get_var(efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
                            unsigned long *data_size, void *data)
@@ -43,8 +43,8 @@ enum efi_secureboot_mode efi_get_secureboot(void)
 
        /*
         * See if a user has put the shim into insecure mode. If so, and if the
-        * variable doesn't have the runtime attribute set, we might as well
-        * honor that.
+        * variable doesn't have the non-volatile attribute set, we might as
+        * well honor that.
         */
        size = sizeof(moksbstate);
        status = get_efi_var(shim_MokSBState_name, &shim_guid,
@@ -53,7 +53,7 @@ enum efi_secureboot_mode efi_get_secureboot(void)
        /* If it fails, we don't care why. Default to secure */
        if (status != EFI_SUCCESS)
                goto secure_boot_enabled;
-       if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS) && moksbstate == 1)
+       if (!(attr & EFI_VARIABLE_NON_VOLATILE) && moksbstate == 1)
                return efi_secureboot_mode_disabled;
 
 secure_boot_enabled:
index 05ae8bc..7a7abc8 100644 (file)
@@ -220,7 +220,6 @@ adjust_memory_range_protection(unsigned long start, unsigned long size)
        unsigned long end, next;
        unsigned long rounded_start, rounded_end;
        unsigned long unprotect_start, unprotect_size;
-       int has_system_memory = 0;
 
        if (efi_dxe_table == NULL)
                return;
@@ -517,6 +516,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        hdr->ramdisk_image = 0;
        hdr->ramdisk_size = 0;
 
+       /*
+        * Disregard any setup data that was provided by the bootloader:
+        * setup_data could be pointing anywhere, and we have no way of
+        * authenticating or validating the payload.
+        */
+       hdr->setup_data = 0;
+
        efi_stub_entry(handle, sys_table_arg, boot_params);
        /* not reached */
 
index 72c677c..133e511 100644 (file)
@@ -148,10 +148,6 @@ static ssize_t flash_count_show(struct device *dev,
        stride = regmap_get_reg_stride(sec->m10bmc->regmap);
        num_bits = FLASH_COUNT_SIZE * 8;
 
-       flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
-       if (!flash_buf)
-               return -ENOMEM;
-
        if (FLASH_COUNT_SIZE % stride) {
                dev_err(sec->dev,
                        "FLASH_COUNT_SIZE (0x%x) not aligned to stride (0x%x)\n",
@@ -160,6 +156,10 @@ static ssize_t flash_count_show(struct device *dev,
                return -EINVAL;
        }
 
+       flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);
+       if (!flash_buf)
+               return -ENOMEM;
+
        ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,
                               flash_buf, FLASH_COUNT_SIZE / stride);
        if (ret) {
index a415518..74cc71b 100644 (file)
@@ -164,6 +164,7 @@ static void dio48e_irq_mask(struct irq_data *data)
                dio48egpio->irq_mask &= ~BIT(0);
        else
                dio48egpio->irq_mask &= ~BIT(1);
+       gpiochip_disable_irq(chip, offset);
 
        if (!dio48egpio->irq_mask)
                /* disable interrupts */
@@ -191,6 +192,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
                iowrite8(0x00, &dio48egpio->reg->enable_interrupt);
        }
 
+       gpiochip_enable_irq(chip, offset);
        if (offset == 19)
                dio48egpio->irq_mask |= BIT(0);
        else
@@ -213,12 +215,14 @@ static int dio48e_irq_set_type(struct irq_data *data, unsigned int flow_type)
        return 0;
 }
 
-static struct irq_chip dio48e_irqchip = {
+static const struct irq_chip dio48e_irqchip = {
        .name = "104-dio-48e",
        .irq_ack = dio48e_irq_ack,
        .irq_mask = dio48e_irq_mask,
        .irq_unmask = dio48e_irq_unmask,
-       .irq_set_type = dio48e_irq_set_type
+       .irq_set_type = dio48e_irq_set_type,
+       .flags = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
@@ -322,7 +326,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
        dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
 
        girq = &dio48egpio->chip.irq;
-       girq->chip = &dio48e_irqchip;
+       gpio_irq_chip_set_chip(girq, &dio48e_irqchip);
        /* This will let us handle the parent IRQ in the driver */
        girq->parent_handler = NULL;
        girq->num_parents = 0;
index 40be76e..3286b91 100644 (file)
@@ -113,6 +113,7 @@ static void idi_48_irq_mask(struct irq_data *data)
        spin_lock_irqsave(&idi48gpio->lock, flags);
 
        idi48gpio->irq_mask[boundary] &= ~mask;
+       gpiochip_disable_irq(chip, offset);
 
        /* Exit early if there are still input lines with IRQ unmasked */
        if (idi48gpio->irq_mask[boundary])
@@ -140,6 +141,7 @@ static void idi_48_irq_unmask(struct irq_data *data)
 
        prev_irq_mask = idi48gpio->irq_mask[boundary];
 
+       gpiochip_enable_irq(chip, offset);
        idi48gpio->irq_mask[boundary] |= mask;
 
        /* Exit early if IRQ was already unmasked for this boundary */
@@ -164,12 +166,14 @@ static int idi_48_irq_set_type(struct irq_data *data, unsigned int flow_type)
        return 0;
 }
 
-static struct irq_chip idi_48_irqchip = {
+static const struct irq_chip idi_48_irqchip = {
        .name = "104-idi-48",
        .irq_ack = idi_48_irq_ack,
        .irq_mask = idi_48_irq_mask,
        .irq_unmask = idi_48_irq_unmask,
-       .irq_set_type = idi_48_irq_set_type
+       .irq_set_type = idi_48_irq_set_type,
+       .flags = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
@@ -267,7 +271,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
        idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
 
        girq = &idi48gpio->chip.irq;
-       girq->chip = &idi_48_irqchip;
+       gpio_irq_chip_set_chip(girq, &idi_48_irqchip);
        /* This will let us handle the parent IRQ in the driver */
        girq->parent_handler = NULL;
        girq->num_parents = 0;
index 65a5f58..4756e58 100644 (file)
@@ -174,10 +174,11 @@ static void idio_16_irq_mask(struct irq_data *data)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-       const unsigned long mask = BIT(irqd_to_hwirq(data));
+       const unsigned long offset = irqd_to_hwirq(data);
        unsigned long flags;
 
-       idio16gpio->irq_mask &= ~mask;
+       idio16gpio->irq_mask &= ~BIT(offset);
+       gpiochip_disable_irq(chip, offset);
 
        if (!idio16gpio->irq_mask) {
                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
@@ -192,11 +193,12 @@ static void idio_16_irq_unmask(struct irq_data *data)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
        struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-       const unsigned long mask = BIT(irqd_to_hwirq(data));
+       const unsigned long offset = irqd_to_hwirq(data);
        const unsigned long prev_irq_mask = idio16gpio->irq_mask;
        unsigned long flags;
 
-       idio16gpio->irq_mask |= mask;
+       gpiochip_enable_irq(chip, offset);
+       idio16gpio->irq_mask |= BIT(offset);
 
        if (!prev_irq_mask) {
                raw_spin_lock_irqsave(&idio16gpio->lock, flags);
@@ -217,12 +219,14 @@ static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
        return 0;
 }
 
-static struct irq_chip idio_16_irqchip = {
+static const struct irq_chip idio_16_irqchip = {
        .name = "104-idio-16",
        .irq_ack = idio_16_irq_ack,
        .irq_mask = idio_16_irq_mask,
        .irq_unmask = idio_16_irq_unmask,
-       .irq_set_type = idio_16_irq_set_type
+       .irq_set_type = idio_16_irq_set_type,
+       .flags = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
@@ -299,7 +303,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
        idio16gpio->out_state = 0xFFFF;
 
        girq = &idio16gpio->chip.irq;
-       girq->chip = &idio_16_irqchip;
+       gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
        /* This will let us handle the parent IRQ in the driver */
        girq->parent_handler = NULL;
        girq->num_parents = 0;
index f422c3e..f77a965 100644 (file)
  * struct ftgpio_gpio - Gemini GPIO state container
  * @dev: containing device for this instance
  * @gc: gpiochip for this instance
- * @irq: irqchip for this instance
  * @base: remapped I/O-memory base
  * @clk: silicon clock
  */
 struct ftgpio_gpio {
        struct device *dev;
        struct gpio_chip gc;
-       struct irq_chip irq;
        void __iomem *base;
        struct clk *clk;
 };
@@ -70,6 +68,7 @@ static void ftgpio_gpio_mask_irq(struct irq_data *d)
        val = readl(g->base + GPIO_INT_EN);
        val &= ~BIT(irqd_to_hwirq(d));
        writel(val, g->base + GPIO_INT_EN);
+       gpiochip_disable_irq(gc, irqd_to_hwirq(d));
 }
 
 static void ftgpio_gpio_unmask_irq(struct irq_data *d)
@@ -78,6 +77,7 @@ static void ftgpio_gpio_unmask_irq(struct irq_data *d)
        struct ftgpio_gpio *g = gpiochip_get_data(gc);
        u32 val;
 
+       gpiochip_enable_irq(gc, irqd_to_hwirq(d));
        val = readl(g->base + GPIO_INT_EN);
        val |= BIT(irqd_to_hwirq(d));
        writel(val, g->base + GPIO_INT_EN);
@@ -221,6 +221,16 @@ static int ftgpio_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
        return 0;
 }
 
+static const struct irq_chip ftgpio_irq_chip = {
+       .name = "FTGPIO010",
+       .irq_ack = ftgpio_gpio_ack_irq,
+       .irq_mask = ftgpio_gpio_mask_irq,
+       .irq_unmask = ftgpio_gpio_unmask_irq,
+       .irq_set_type = ftgpio_gpio_set_irq_type,
+       .flags = IRQCHIP_IMMUTABLE,
+        GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
 static int ftgpio_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -277,14 +287,8 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
        if (!IS_ERR(g->clk))
                g->gc.set_config = ftgpio_gpio_set_config;
 
-       g->irq.name = "FTGPIO010";
-       g->irq.irq_ack = ftgpio_gpio_ack_irq;
-       g->irq.irq_mask = ftgpio_gpio_mask_irq;
-       g->irq.irq_unmask = ftgpio_gpio_unmask_irq;
-       g->irq.irq_set_type = ftgpio_gpio_set_irq_type;
-
        girq = &g->gc.irq;
-       girq->chip = &g->irq;
+       gpio_irq_chip_set_chip(girq, &ftgpio_irq_chip);
        girq->parent_handler = ftgpio_gpio_irq_handler;
        girq->num_parents = 1;
        girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
index 312309b..56656fb 100644 (file)
@@ -63,6 +63,14 @@ static void ixp4xx_gpio_irq_ack(struct irq_data *d)
        __raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);
 }
 
+static void ixp4xx_gpio_mask_irq(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+
+       irq_chip_mask_parent(d);
+       gpiochip_disable_irq(gc, d->hwirq);
+}
+
 static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -72,6 +80,7 @@ static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
        if (!(g->irq_edge & BIT(d->hwirq)))
                ixp4xx_gpio_irq_ack(d);
 
+       gpiochip_enable_irq(gc, d->hwirq);
        irq_chip_unmask_parent(d);
 }
 
@@ -149,12 +158,14 @@ static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
 }
 
-static struct irq_chip ixp4xx_gpio_irqchip = {
+static const struct irq_chip ixp4xx_gpio_irqchip = {
        .name = "IXP4GPIO",
        .irq_ack = ixp4xx_gpio_irq_ack,
-       .irq_mask = irq_chip_mask_parent,
+       .irq_mask = ixp4xx_gpio_mask_irq,
        .irq_unmask = ixp4xx_gpio_irq_unmask,
        .irq_set_type = ixp4xx_gpio_irq_set_type,
+       .flags = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static int ixp4xx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
@@ -263,7 +274,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
        g->gc.owner = THIS_MODULE;
 
        girq = &g->gc.irq;
-       girq->chip = &ixp4xx_gpio_irqchip;
+       gpio_irq_chip_set_chip(girq, &ixp4xx_gpio_irqchip);
        girq->fwnode = g->fwnode;
        girq->parent_domain = parent;
        girq->child_to_parent_hwirq = ixp4xx_gpio_child_to_parent_hwirq;
index 8943cea..523dfd1 100644 (file)
@@ -373,6 +373,13 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
        }
 }
 
+static void gpio_mockup_debugfs_cleanup(void *data)
+{
+       struct gpio_mockup_chip *chip = data;
+
+       debugfs_remove_recursive(chip->dbg_dir);
+}
+
 static void gpio_mockup_dispose_mappings(void *data)
 {
        struct gpio_mockup_chip *chip = data;
@@ -455,7 +462,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
 
        gpio_mockup_debugfs_setup(dev, chip);
 
-       return 0;
+       return devm_add_action_or_reset(dev, gpio_mockup_debugfs_cleanup, chip);
 }
 
 static const struct of_device_id gpio_mockup_of_match[] = {
@@ -526,8 +533,10 @@ static int __init gpio_mockup_register_chip(int idx)
        }
 
        fwnode = fwnode_create_software_node(properties, NULL);
-       if (IS_ERR(fwnode))
+       if (IS_ERR(fwnode)) {
+               kfree_strarray(line_names, ngpio);
                return PTR_ERR(fwnode);
+       }
 
        pdevinfo.name = "gpio-mockup";
        pdevinfo.id = idx;
@@ -590,9 +599,9 @@ static int __init gpio_mockup_init(void)
 
 static void __exit gpio_mockup_exit(void)
 {
+       gpio_mockup_unregister_pdevs();
        debugfs_remove_recursive(gpio_mockup_dbg_dir);
        platform_driver_unregister(&gpio_mockup_driver);
-       gpio_mockup_unregister_pdevs();
 }
 
 module_init(gpio_mockup_init);
index 1504982..3eb08cd 100644 (file)
@@ -169,6 +169,7 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 
        switch (flow_type) {
        case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_LEVEL_LOW:
                raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
                gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
                        gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
index d8a26e5..f163f5c 100644 (file)
@@ -112,6 +112,8 @@ mediatek_gpio_irq_unmask(struct irq_data *d)
        unsigned long flags;
        u32 rise, fall, high, low;
 
+       gpiochip_enable_irq(gc, d->hwirq);
+
        spin_lock_irqsave(&rg->lock, flags);
        rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
        fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
@@ -143,6 +145,8 @@ mediatek_gpio_irq_mask(struct irq_data *d)
        mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin));
        mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin));
        spin_unlock_irqrestore(&rg->lock, flags);
+
+       gpiochip_disable_irq(gc, d->hwirq);
 }
 
 static int
@@ -204,6 +208,16 @@ mediatek_gpio_xlate(struct gpio_chip *chip,
        return gpio % MTK_BANK_WIDTH;
 }
 
+static const struct irq_chip mt7621_irq_chip = {
+       .name           = "mt7621-gpio",
+       .irq_mask_ack   = mediatek_gpio_irq_mask,
+       .irq_mask       = mediatek_gpio_irq_mask,
+       .irq_unmask     = mediatek_gpio_irq_unmask,
+       .irq_set_type   = mediatek_gpio_irq_type,
+       .flags          = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
 static int
 mediatek_gpio_bank_probe(struct device *dev, int bank)
 {
@@ -238,11 +252,6 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
                return -ENOMEM;
 
        rg->chip.offset = bank * MTK_BANK_WIDTH;
-       rg->irq_chip.name = dev_name(dev);
-       rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
-       rg->irq_chip.irq_mask = mediatek_gpio_irq_mask;
-       rg->irq_chip.irq_mask_ack = mediatek_gpio_irq_mask;
-       rg->irq_chip.irq_set_type = mediatek_gpio_irq_type;
 
        if (mtk->gpio_irq) {
                struct gpio_irq_chip *girq;
@@ -262,7 +271,7 @@ mediatek_gpio_bank_probe(struct device *dev, int bank)
                }
 
                girq = &rg->chip.irq;
-               girq->chip = &rg->irq_chip;
+               gpio_irq_chip_set_chip(girq, &mt7621_irq_chip);
                /* This will let us handle the parent IRQ in the driver */
                girq->parent_handler = NULL;
                girq->num_parents = 0;
index aa126ab..1bb317b 100644 (file)
@@ -790,8 +790,12 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
        u32 offset;
        u32 set;
 
-       if (of_device_is_compatible(mvchip->chip.of_node,
-                                   "marvell,armada-370-gpio")) {
+       if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
+               int ret = of_property_read_u32(dev->of_node,
+                                              "marvell,pwm-offset", &offset);
+               if (ret < 0)
+                       return 0;
+       } else {
                /*
                 * There are only two sets of PWM configuration registers for
                 * all the GPIO lines on those SoCs which this driver reserves
@@ -801,13 +805,6 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
                if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"))
                        return 0;
                offset = 0;
-       } else if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) {
-               int ret = of_property_read_u32(dev->of_node,
-                                              "marvell,pwm-offset", &offset);
-               if (ret < 0)
-                       return 0;
-       } else {
-               return 0;
        }
 
        if (IS_ERR(mvchip->clk))
index ecd7d16..2925f4d 100644 (file)
@@ -1175,7 +1175,9 @@ static int pca953x_suspend(struct device *dev)
 {
        struct pca953x_chip *chip = dev_get_drvdata(dev);
 
+       mutex_lock(&chip->i2c_lock);
        regcache_cache_only(chip->regmap, true);
+       mutex_unlock(&chip->i2c_lock);
 
        if (atomic_read(&chip->wakeup_path))
                device_set_wakeup_path(dev);
@@ -1198,13 +1200,17 @@ static int pca953x_resume(struct device *dev)
                }
        }
 
+       mutex_lock(&chip->i2c_lock);
        regcache_cache_only(chip->regmap, false);
        regcache_mark_dirty(chip->regmap);
        ret = pca953x_regcache_sync(dev);
-       if (ret)
+       if (ret) {
+               mutex_unlock(&chip->i2c_lock);
                return ret;
+       }
 
        ret = regcache_sync(chip->regmap);
+       mutex_unlock(&chip->i2c_lock);
        if (ret) {
                dev_err(dev, "Failed to restore register map: %d\n", ret);
                return ret;
index c7fbfa3..1198ab0 100644 (file)
@@ -661,24 +661,17 @@ static int pxa_gpio_probe(struct platform_device *pdev)
        if (IS_ERR(gpio_reg_base))
                return PTR_ERR(gpio_reg_base);
 
-       clk = clk_get(&pdev->dev, NULL);
+       clk = devm_clk_get_enabled(&pdev->dev, NULL);
        if (IS_ERR(clk)) {
                dev_err(&pdev->dev, "Error %ld to get gpio clock\n",
                        PTR_ERR(clk));
                return PTR_ERR(clk);
        }
-       ret = clk_prepare_enable(clk);
-       if (ret) {
-               clk_put(clk);
-               return ret;
-       }
 
        /* Initialize GPIO chips */
        ret = pxa_init_gpio_chip(pchip, pxa_last_gpio + 1, gpio_reg_base);
-       if (ret) {
-               clk_put(clk);
+       if (ret)
                return ret;
-       }
 
        /* clear all GPIO edge detects */
        for_each_gpio_bank(gpio, c, pchip) {
index 63dcf42..d6418f8 100644 (file)
  * @lock: Lock for accessing the IRQ registers and values
  * @intr_mask: Mask for interrupts lines
  * @intr_type: Interrupt type selection
+ * @bank_read: Read a bank setting as a single 32-bit value
+ * @bank_write: Write a bank setting as a single 32-bit value
+ * @imr_line_pos: Bit shift of an IRQ line's IMR value.
+ *
+ * The DIR, DATA, and ISR registers consist of four 8-bit port values, packed
+ * into a single 32-bit register. Use @bank_read (@bank_write) to get (assign)
+ * a value from (to) these registers. The IMR register consists of four 16-bit
+ * port values, packed into two 32-bit registers. Use @imr_line_pos to get the
+ * bit shift of the 2-bit field for a line's IMR settings. Shifts larger than
+ * 32 overflow into the second register.
  *
  * Because the interrupt mask register (IMR) combines the function of IRQ type
  * selection and masking, two extra values are stored. @intr_mask is used to
- * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
+ * mask/unmask the interrupts for a GPIO line, and @intr_type is used to store
  * the selected interrupt types. The logical AND of these values is written to
  * IMR on changes.
  */
@@ -59,10 +69,11 @@ struct realtek_gpio_ctrl {
        void __iomem *cpumask_base;
        struct cpumask cpu_irq_maskable;
        raw_spinlock_t lock;
-       u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
-       u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
-       unsigned int (*port_offset_u8)(unsigned int port);
-       unsigned int (*port_offset_u16)(unsigned int port);
+       u8 intr_mask[REALTEK_GPIO_MAX];
+       u8 intr_type[REALTEK_GPIO_MAX];
+       u32 (*bank_read)(void __iomem *reg);
+       void (*bank_write)(void __iomem *reg, u32 value);
+       unsigned int (*line_imr_pos)(unsigned int line);
 };
 
 /* Expand with more flags as devices with other quirks are added */
@@ -101,14 +112,22 @@ static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
  * port. The two interrupt mask registers store two bits per GPIO, so use u16
  * values.
  */
-static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
+static u32 realtek_gpio_bank_read_swapped(void __iomem *reg)
 {
-       return port;
+       return ioread32be(reg);
 }
 
-static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
+static void realtek_gpio_bank_write_swapped(void __iomem *reg, u32 value)
 {
-       return 2 * port;
+       iowrite32be(value, reg);
+}
+
+static unsigned int realtek_gpio_line_imr_pos_swapped(unsigned int line)
+{
+       unsigned int port_pin = line % 8;
+       unsigned int port = line / 8;
+
+       return 2 * (8 * (port ^ 1) + port_pin);
 }
 
 /*
@@ -119,66 +138,67 @@ static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
  * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
  * second ports 3 and 2.
  */
-static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
+static u32 realtek_gpio_bank_read(void __iomem *reg)
 {
-       return 3 - port;
+       return ioread32(reg);
 }
 
-static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
+static void realtek_gpio_bank_write(void __iomem *reg, u32 value)
 {
-       return 2 * (port ^ 1);
+       iowrite32(value, reg);
 }
 
-static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
-       unsigned int port, u16 irq_type, u16 irq_mask)
+static unsigned int realtek_gpio_line_imr_pos(unsigned int line)
 {
-       iowrite16(irq_type & irq_mask,
-               ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
+       return 2 * line;
 }
 
-static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
-       unsigned int port, u8 mask)
+static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl, u32 mask)
 {
-       iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
+       ctrl->bank_write(ctrl->base + REALTEK_GPIO_REG_ISR, mask);
 }
 
-static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
+static u32 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl)
 {
-       return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
+       return ctrl->bank_read(ctrl->base + REALTEK_GPIO_REG_ISR);
 }
 
-/* Set the rising and falling edge mask bits for a GPIO port pin */
-static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
+/* Set the rising and falling edge mask bits for a GPIO pin */
+static void realtek_gpio_update_line_imr(struct realtek_gpio_ctrl *ctrl, unsigned int line)
 {
-       return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
+       void __iomem *reg = ctrl->base + REALTEK_GPIO_REG_IMR;
+       unsigned int line_shift = ctrl->line_imr_pos(line);
+       unsigned int shift = line_shift % 32;
+       u32 irq_type = ctrl->intr_type[line];
+       u32 irq_mask = ctrl->intr_mask[line];
+       u32 reg_val;
+
+       reg += 4 * (line_shift / 32);
+       reg_val = ioread32(reg);
+       reg_val &= ~(REALTEK_GPIO_IMR_LINE_MASK << shift);
+       reg_val |= (irq_type & irq_mask & REALTEK_GPIO_IMR_LINE_MASK) << shift;
+       iowrite32(reg_val, reg);
 }
 
 static void realtek_gpio_irq_ack(struct irq_data *data)
 {
        struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
        irq_hw_number_t line = irqd_to_hwirq(data);
-       unsigned int port = line / 8;
-       unsigned int port_pin = line % 8;
 
-       realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
+       realtek_gpio_clear_isr(ctrl, BIT(line));
 }
 
 static void realtek_gpio_irq_unmask(struct irq_data *data)
 {
        struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
        unsigned int line = irqd_to_hwirq(data);
-       unsigned int port = line / 8;
-       unsigned int port_pin = line % 8;
        unsigned long flags;
-       u16 m;
 
        gpiochip_enable_irq(&ctrl->gc, line);
 
        raw_spin_lock_irqsave(&ctrl->lock, flags);
-       m = ctrl->intr_mask[port];
-       m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-       ctrl->intr_mask[port] = m;
-       realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
+       ctrl->intr_mask[line] = REALTEK_GPIO_IMR_LINE_MASK;
+       realtek_gpio_update_line_imr(ctrl, line);
        raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
@@ -186,16 +206,11 @@ static void realtek_gpio_irq_mask(struct irq_data *data)
 {
        struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
        unsigned int line = irqd_to_hwirq(data);
-       unsigned int port = line / 8;
-       unsigned int port_pin = line % 8;
        unsigned long flags;
-       u16 m;
 
        raw_spin_lock_irqsave(&ctrl->lock, flags);
-       m = ctrl->intr_mask[port];
-       m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-       ctrl->intr_mask[port] = m;
-       realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
+       ctrl->intr_mask[line] = 0;
+       realtek_gpio_update_line_imr(ctrl, line);
        raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 
        gpiochip_disable_irq(&ctrl->gc, line);
@@ -205,10 +220,8 @@ static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_ty
 {
        struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
        unsigned int line = irqd_to_hwirq(data);
-       unsigned int port = line / 8;
-       unsigned int port_pin = line % 8;
        unsigned long flags;
-       u16 type, t;
+       u8 type;
 
        switch (flow_type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_FALLING:
@@ -227,11 +240,8 @@ static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_ty
        irq_set_handler_locked(data, handle_edge_irq);
 
        raw_spin_lock_irqsave(&ctrl->lock, flags);
-       t = ctrl->intr_type[port];
-       t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-       t |= realtek_gpio_imr_bits(port_pin, type);
-       ctrl->intr_type[port] = t;
-       realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
+       ctrl->intr_type[line] = type;
+       realtek_gpio_update_line_imr(ctrl, line);
        raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 
        return 0;
@@ -242,28 +252,21 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc)
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
        struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-       unsigned int lines_done;
-       unsigned int port_pin_count;
        unsigned long status;
        int offset;
 
        chained_irq_enter(irq_chip, desc);
 
-       for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
-               status = realtek_gpio_read_isr(ctrl, lines_done / 8);
-               port_pin_count = min(gc->ngpio - lines_done, 8U);
-               for_each_set_bit(offset, &status, port_pin_count)
-                       generic_handle_domain_irq(gc->irq.domain, offset + lines_done);
-       }
+       status = realtek_gpio_read_isr(ctrl);
+       for_each_set_bit(offset, &status, gc->ngpio)
+               generic_handle_domain_irq(gc->irq.domain, offset);
 
        chained_irq_exit(irq_chip, desc);
 }
 
-static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
-       unsigned int port, int cpu)
+static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl, int cpu)
 {
-       return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
-               REALTEK_GPIO_PORTS_PER_BANK * cpu;
+       return ctrl->cpumask_base + REALTEK_GPIO_PORTS_PER_BANK * cpu;
 }
 
 static int realtek_gpio_irq_set_affinity(struct irq_data *data,
@@ -271,12 +274,10 @@ static int realtek_gpio_irq_set_affinity(struct irq_data *data,
 {
        struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
        unsigned int line = irqd_to_hwirq(data);
-       unsigned int port = line / 8;
-       unsigned int port_pin = line % 8;
        void __iomem *irq_cpu_mask;
        unsigned long flags;
        int cpu;
-       u8 v;
+       u32 v;
 
        if (!ctrl->cpumask_base)
                return -ENXIO;
@@ -284,15 +285,15 @@ static int realtek_gpio_irq_set_affinity(struct irq_data *data,
        raw_spin_lock_irqsave(&ctrl->lock, flags);
 
        for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
-               irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
-               v = ioread8(irq_cpu_mask);
+               irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
+               v = ctrl->bank_read(irq_cpu_mask);
 
                if (cpumask_test_cpu(cpu, dest))
-                       v |= BIT(port_pin);
+                       v |= BIT(line);
                else
-                       v &= ~BIT(port_pin);
+                       v &= ~BIT(line);
 
-               iowrite8(v, irq_cpu_mask);
+               ctrl->bank_write(irq_cpu_mask, v);
        }
 
        raw_spin_unlock_irqrestore(&ctrl->lock, flags);
@@ -305,16 +306,17 @@ static int realtek_gpio_irq_set_affinity(struct irq_data *data,
 static int realtek_gpio_irq_init(struct gpio_chip *gc)
 {
        struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
-       unsigned int port;
+       u32 mask_all = GENMASK(gc->ngpio - 1, 0);
+       unsigned int line;
        int cpu;
 
-       for (port = 0; (port * 8) < gc->ngpio; port++) {
-               realtek_gpio_write_imr(ctrl, port, 0, 0);
-               realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
+       for (line = 0; line < gc->ngpio; line++)
+               realtek_gpio_update_line_imr(ctrl, line);
 
-               for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
-                       iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
-       }
+       realtek_gpio_clear_isr(ctrl, mask_all);
+
+       for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
+               ctrl->bank_write(realtek_gpio_irq_cpu_mask(ctrl, cpu), mask_all);
 
        return 0;
 }
@@ -387,12 +389,14 @@ static int realtek_gpio_probe(struct platform_device *pdev)
 
        if (dev_flags & GPIO_PORTS_REVERSED) {
                bgpio_flags = 0;
-               ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
-               ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
+               ctrl->bank_read = realtek_gpio_bank_read;
+               ctrl->bank_write = realtek_gpio_bank_write;
+               ctrl->line_imr_pos = realtek_gpio_line_imr_pos;
        } else {
                bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
-               ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
-               ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
+               ctrl->bank_read = realtek_gpio_bank_read_swapped;
+               ctrl->bank_write = realtek_gpio_bank_write_swapped;
+               ctrl->line_imr_pos = realtek_gpio_line_imr_pos_swapped;
        }
 
        err = bgpio_init(&ctrl->gc, dev, 4,
index f91e876..bb50335 100644 (file)
@@ -419,11 +419,11 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
                        goto out;
                } else {
                        bank->toggle_edge_mode |= mask;
-                       level |= mask;
+                       level &= ~mask;
 
                        /*
                         * Determine gpio state. If 1 next interrupt should be
-                        * falling otherwise rising.
+                        * low otherwise high.
                         */
                        data = readl(bank->reg_base + bank->gpio_regs->ext_port);
                        if (data & mask)
index fa4bc74..e739dce 100644 (file)
@@ -307,6 +307,8 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
                girq->default_type = IRQ_TYPE_NONE;
                girq->handler = handle_simple_irq;
                girq->init_valid_mask = tqmx86_init_irq_valid_mask;
+
+               irq_domain_set_pm_device(girq->domain, dev);
        }
 
        ret = devm_gpiochip_add_data(dev, chip, gpio);
@@ -315,8 +317,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
                goto out_pm_dis;
        }
 
-       irq_domain_set_pm_device(girq->domain, dev);
-
        dev_info(dev, "GPIO functionality initialized with %d pins\n",
                 chip->ngpio);
 
index b098f2d..59fb106 100644 (file)
@@ -265,6 +265,7 @@ static void ws16c48_irq_mask(struct irq_data *data)
        raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
        ws16c48gpio->irq_mask &= ~mask;
+       gpiochip_disable_irq(chip, offset);
        port_state = ws16c48gpio->irq_mask >> (8 * port);
 
        /* Select Register Page 2; Unlock all I/O ports */
@@ -295,6 +296,7 @@ static void ws16c48_irq_unmask(struct irq_data *data)
 
        raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
+       gpiochip_enable_irq(chip, offset);
        ws16c48gpio->irq_mask |= mask;
        port_state = ws16c48gpio->irq_mask >> (8 * port);
 
@@ -356,12 +358,14 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
        return 0;
 }
 
-static struct irq_chip ws16c48_irqchip = {
+static const struct irq_chip ws16c48_irqchip = {
        .name = "ws16c48",
        .irq_ack = ws16c48_irq_ack,
        .irq_mask = ws16c48_irq_mask,
        .irq_unmask = ws16c48_irq_unmask,
-       .irq_set_type = ws16c48_irq_set_type
+       .irq_set_type = ws16c48_irq_set_type,
+       .flags = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
 };
 
 static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id)
@@ -463,7 +467,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
        ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
 
        girq = &ws16c48gpio->chip.irq;
-       girq->chip = &ws16c48_irqchip;
+       gpio_irq_chip_set_chip(girq, &ws16c48_irqchip);
        /* This will let us handle the parent IRQ in the driver */
        girq->parent_handler = NULL;
        girq->num_parents = 0;
index f8041d4..92f1855 100644 (file)
@@ -1986,7 +1986,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
                ret = -ENODEV;
                goto out_free_le;
        }
-       le->irq = irq;
 
        if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
                irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
@@ -2000,7 +1999,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        init_waitqueue_head(&le->wait);
 
        /* Request a thread to read the events */
-       ret = request_threaded_irq(le->irq,
+       ret = request_threaded_irq(irq,
                                   lineevent_irq_handler,
                                   lineevent_irq_thread,
                                   irqflags,
@@ -2009,6 +2008,8 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        if (ret)
                goto out_free_le;
 
+       le->irq = irq;
+
        fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
        if (fd < 0) {
                ret = fd;
index 1300608..48bd660 100644 (file)
@@ -1050,6 +1050,10 @@ 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;
 }
 
index cbd593f..2170db8 100644 (file)
@@ -1728,7 +1728,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
        add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr);
 
        if (user_addr) {
-               pr_debug("creating userptr BO for user_addr = %llu\n", user_addr);
+               pr_debug("creating userptr BO for user_addr = %llx\n", user_addr);
                ret = init_user_pages(*mem, user_addr, criu_resume);
                if (ret)
                        goto allocate_init_user_pages_failed;
index f095a25..25e1f5e 100644 (file)
@@ -2365,8 +2365,16 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                }
                adev->ip_blocks[i].status.sw = true;
 
-               /* need to do gmc hw init early so we can allocate gpu mem */
-               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
+               if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON) {
+                       /* need to do common hw init early so everything is set up for gmc */
+                       r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
+                       if (r) {
+                               DRM_ERROR("hw_init %d failed %d\n", i, r);
+                               goto init_failed;
+                       }
+                       adev->ip_blocks[i].status.hw = true;
+               } else if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
+                       /* need to do gmc hw init early so we can allocate gpu mem */
                        /* Try to reserve bad pages early */
                        if (amdgpu_sriov_vf(adev))
                                amdgpu_virt_exchange_data(adev);
@@ -3052,8 +3060,8 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
        int i, r;
 
        static enum amd_ip_block_type ip_order[] = {
-               AMD_IP_BLOCK_TYPE_GMC,
                AMD_IP_BLOCK_TYPE_COMMON,
+               AMD_IP_BLOCK_TYPE_GMC,
                AMD_IP_BLOCK_TYPE_PSP,
                AMD_IP_BLOCK_TYPE_IH,
        };
@@ -3144,7 +3152,8 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
                        continue;
                if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
                    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
-                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
+                   adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
+                   (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP && amdgpu_sriov_vf(adev))) {
 
                        r = adev->ip_blocks[i].version->funcs->resume(adev);
                        if (r) {
@@ -4056,12 +4065,20 @@ static void amdgpu_device_evict_resources(struct amdgpu_device *adev)
 int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
 {
        struct amdgpu_device *adev = drm_to_adev(dev);
+       int r = 0;
 
        if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
 
        adev->in_suspend = true;
 
+       if (amdgpu_sriov_vf(adev)) {
+               amdgpu_virt_fini_data_exchange(adev);
+               r = amdgpu_virt_request_full_gpu(adev, false);
+               if (r)
+                       return r;
+       }
+
        if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
                DRM_WARN("smart shift update failed\n");
 
@@ -4085,6 +4102,9 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
 
        amdgpu_device_ip_suspend_phase2(adev);
 
+       if (amdgpu_sriov_vf(adev))
+               amdgpu_virt_release_full_gpu(adev, false);
+
        return 0;
 }
 
@@ -4103,6 +4123,12 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
        struct amdgpu_device *adev = drm_to_adev(dev);
        int r = 0;
 
+       if (amdgpu_sriov_vf(adev)) {
+               r = amdgpu_virt_request_full_gpu(adev, true);
+               if (r)
+                       return r;
+       }
+
        if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
 
@@ -4117,6 +4143,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
        }
 
        r = amdgpu_device_ip_resume(adev);
+
+       /* no matter what r is, always need to properly release full GPU */
+       if (amdgpu_sriov_vf(adev)) {
+               amdgpu_virt_init_data_exchange(adev);
+               amdgpu_virt_release_full_gpu(adev, true);
+       }
+
        if (r) {
                dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
                return r;
@@ -5524,7 +5557,8 @@ bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
                ~*peer_adev->dev->dma_mask : ~((1ULL << 32) - 1);
        resource_size_t aper_limit =
                adev->gmc.aper_base + adev->gmc.aper_size - 1;
-       bool p2p_access = !(pci_p2pdma_distance_many(adev->pdev,
+       bool p2p_access = !adev->gmc.xgmi.connected_to_cpu &&
+                         !(pci_p2pdma_distance_many(adev->pdev,
                                        &peer_adev->dev, 1, true) < 0);
 
        return pcie_p2p && p2p_access && (adev->gmc.visible_vram_size &&
index c20922a..23998f7 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_fb_helper.h>
@@ -498,6 +500,12 @@ static const struct drm_framebuffer_funcs amdgpu_fb_funcs = {
        .create_handle = drm_gem_fb_create_handle,
 };
 
+static const struct drm_framebuffer_funcs amdgpu_fb_funcs_atomic = {
+       .destroy = drm_gem_fb_destroy,
+       .create_handle = drm_gem_fb_create_handle,
+       .dirty = drm_atomic_helper_dirtyfb,
+};
+
 uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
                                          uint64_t bo_flags)
 {
@@ -1100,7 +1108,10 @@ static int amdgpu_display_gem_fb_verify_and_init(struct drm_device *dev,
        if (ret)
                goto err;
 
-       ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
+       if (drm_drv_uses_atomic_modeset(dev))
+               ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs_atomic);
+       else
+               ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs);
        if (ret)
                goto err;
 
index 8adeb74..d0d99ed 100644 (file)
@@ -400,7 +400,6 @@ unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring)
        /* We are not protected by ring lock when reading the last sequence
         * but it's ok to report slightly wrong fence count here.
         */
-       amdgpu_fence_process(ring);
        emitted = 0x100000000ull;
        emitted -= atomic_read(&ring->fence_drv.last_seq);
        emitted += READ_ONCE(ring->fence_drv.sync_seq);
index ecada5e..e325150 100644 (file)
@@ -66,10 +66,15 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
                return true;
        case CHIP_SIENNA_CICHLID:
                if (strnstr(atom_ctx->vbios_version, "D603",
+                   sizeof(atom_ctx->vbios_version))) {
+                       if (strnstr(atom_ctx->vbios_version, "D603GLXE",
                            sizeof(atom_ctx->vbios_version)))
-                       return true;
-               else
+                               return false;
+                       else
+                               return true;
+               } else {
                        return false;
+               }
        default:
                return false;
        }
index 23a696d..de5b936 100644 (file)
@@ -304,6 +304,10 @@ struct amdgpu_gfx {
        uint32_t                        rlc_srlg_feature_version;
        uint32_t                        rlc_srls_fw_version;
        uint32_t                        rlc_srls_feature_version;
+       uint32_t                        rlcp_ucode_version;
+       uint32_t                        rlcp_ucode_feature_version;
+       uint32_t                        rlcv_ucode_version;
+       uint32_t                        rlcv_ucode_feature_version;
        uint32_t                        mec_feature_version;
        uint32_t                        mec2_feature_version;
        bool                            mec_fw_write_wait;
index b1099ee..c2fd6f3 100644 (file)
@@ -159,7 +159,10 @@ void amdgpu_job_free(struct amdgpu_job *job)
        amdgpu_sync_free(&job->sync);
        amdgpu_sync_free(&job->sched_sync);
 
-       dma_fence_put(&job->hw_fence);
+       if (!job->hw_fence.ops)
+               kfree(job);
+       else
+               dma_fence_put(&job->hw_fence);
 }
 
 int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
index fe82b8b..0c54624 100644 (file)
@@ -181,6 +181,9 @@ int amdgpu_mes_init(struct amdgpu_device *adev)
        for (i = 0; i < AMDGPU_MES_MAX_SDMA_PIPES; i++) {
                if (adev->ip_versions[SDMA0_HWIP][0] < IP_VERSION(6, 0, 0))
                        adev->mes.sdma_hqd_mask[i] = i ? 0 : 0x3fc;
+               /* zero sdma_hqd_mask for non-existent engine */
+               else if (adev->sdma.num_instances == 1)
+                       adev->mes.sdma_hqd_mask[i] = i ? 0 : 0xfc;
                else
                        adev->mes.sdma_hqd_mask[i] = 0xfc;
        }
index 7b46f6b..ad980f4 100644 (file)
@@ -222,6 +222,8 @@ struct mes_add_queue_input {
        uint64_t        tba_addr;
        uint64_t        tma_addr;
        uint32_t        is_kfd_process;
+       uint32_t        is_aql_queue;
+       uint32_t        queue_size;
 };
 
 struct mes_remove_queue_input {
index 1036446..c9dec24 100644 (file)
@@ -486,11 +486,14 @@ static int psp_sw_fini(void *handle)
                release_firmware(psp->ta_fw);
                psp->ta_fw = NULL;
        }
-       if (adev->psp.cap_fw) {
+       if (psp->cap_fw) {
                release_firmware(psp->cap_fw);
                psp->cap_fw = NULL;
        }
-
+       if (psp->toc_fw) {
+               release_firmware(psp->toc_fw);
+               psp->toc_fw = NULL;
+       }
        if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
            adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
                psp_sysfs_fini(adev);
@@ -753,7 +756,7 @@ static int psp_tmr_init(struct psp_context *psp)
        }
 
        pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
-       ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, PSP_TMR_SIZE(psp->adev),
+       ret = amdgpu_bo_create_kernel(psp->adev, tmr_size, PSP_TMR_ALIGNMENT,
                                      AMDGPU_GEM_DOMAIN_VRAM,
                                      &psp->tmr_bo, &psp->tmr_mc_addr, pptr);
 
@@ -2401,7 +2404,7 @@ static int psp_load_smu_fw(struct psp_context *psp)
 static bool fw_load_skip_check(struct psp_context *psp,
                               struct amdgpu_firmware_info *ucode)
 {
-       if (!ucode->fw)
+       if (!ucode->fw || !ucode->ucode_size)
                return true;
 
        if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
index c32b74b..e593e8c 100644 (file)
@@ -36,6 +36,7 @@
 #define PSP_CMD_BUFFER_SIZE    0x1000
 #define PSP_1_MEG              0x100000
 #define PSP_TMR_SIZE(adev)     ((adev)->asic_type == CHIP_ALDEBARAN ? 0x800000 : 0x400000)
+#define PSP_TMR_ALIGNMENT      0x100000
 #define PSP_FW_NAME_LEN                0x24
 
 enum psp_shared_mem_size {
index ff5361f..12c6f97 100644 (file)
@@ -1811,7 +1811,8 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev)
                amdgpu_ras_query_error_status(adev, &info);
 
                if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) &&
-                   adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) {
+                   adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4) &&
+                   adev->ip_versions[MP0_HWIP][0] != IP_VERSION(13, 0, 0)) {
                        if (amdgpu_ras_reset_error_status(adev, info.head.block))
                                dev_warn(adev->dev, "Failed to reset error counter and error status");
                }
index 6373bfb..e23f619 100644 (file)
@@ -272,3 +272,267 @@ void amdgpu_gfx_rlc_fini(struct amdgpu_device *adev)
                              &adev->gfx.rlc.cp_table_gpu_addr,
                              (void **)&adev->gfx.rlc.cp_table_ptr);
 }
+
+static int amdgpu_gfx_rlc_init_microcode_v2_0(struct amdgpu_device *adev)
+{
+       const struct common_firmware_header *common_hdr;
+       const struct rlc_firmware_header_v2_0 *rlc_hdr;
+       struct amdgpu_firmware_info *info;
+       unsigned int *tmp;
+       unsigned int i;
+
+       rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
+
+       adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
+       adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
+       adev->gfx.rlc.save_and_restore_offset =
+               le32_to_cpu(rlc_hdr->save_and_restore_offset);
+       adev->gfx.rlc.clear_state_descriptor_offset =
+               le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
+       adev->gfx.rlc.avail_scratch_ram_locations =
+               le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
+       adev->gfx.rlc.reg_restore_list_size =
+               le32_to_cpu(rlc_hdr->reg_restore_list_size);
+       adev->gfx.rlc.reg_list_format_start =
+               le32_to_cpu(rlc_hdr->reg_list_format_start);
+       adev->gfx.rlc.reg_list_format_separate_start =
+               le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
+       adev->gfx.rlc.starting_offsets_start =
+               le32_to_cpu(rlc_hdr->starting_offsets_start);
+       adev->gfx.rlc.reg_list_format_size_bytes =
+               le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
+       adev->gfx.rlc.reg_list_size_bytes =
+               le32_to_cpu(rlc_hdr->reg_list_size_bytes);
+       adev->gfx.rlc.register_list_format =
+               kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
+                       adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
+       if (!adev->gfx.rlc.register_list_format) {
+               dev_err(adev->dev, "failed to allocate memory for rlc register_list_format\n");
+               return -ENOMEM;
+       }
+
+       tmp = (unsigned int *)((uintptr_t)rlc_hdr +
+                       le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
+       for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
+               adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
+
+       adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
+
+       tmp = (unsigned int *)((uintptr_t)rlc_hdr +
+                       le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
+       for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
+               adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
+
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
+               info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
+               info->fw = adev->gfx.rlc_fw;
+               if (info->fw) {
+                       common_hdr = (const struct common_firmware_header *)info->fw->data;
+                       adev->firmware.fw_size +=
+                               ALIGN(le32_to_cpu(common_hdr->ucode_size_bytes), PAGE_SIZE);
+               }
+       }
+
+       return 0;
+}
+
+static void amdgpu_gfx_rlc_init_microcode_v2_1(struct amdgpu_device *adev)
+{
+       const struct rlc_firmware_header_v2_1 *rlc_hdr;
+       struct amdgpu_firmware_info *info;
+
+       rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
+       adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
+       adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
+       adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
+       adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
+       adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
+       adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
+       adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
+       adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
+       adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
+       adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
+       adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
+       adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
+       adev->gfx.rlc.reg_list_format_direct_reg_list_length =
+               le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
+
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+               if (adev->gfx.rlc.save_restore_list_gpm_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
+                       info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.save_restore_list_srm_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
+                       info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
+               }
+       }
+}
+
+static void amdgpu_gfx_rlc_init_microcode_v2_2(struct amdgpu_device *adev)
+{
+       const struct rlc_firmware_header_v2_2 *rlc_hdr;
+       struct amdgpu_firmware_info *info;
+
+       rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data;
+       adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes);
+       adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes);
+       adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes);
+       adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes);
+
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+               if (adev->gfx.rlc.rlc_iram_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM];
+                       info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.rlc_dram_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM];
+                       info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE);
+               }
+       }
+}
+
+static void amdgpu_gfx_rlc_init_microcode_v2_3(struct amdgpu_device *adev)
+{
+       const struct rlc_firmware_header_v2_3 *rlc_hdr;
+       struct amdgpu_firmware_info *info;
+
+       rlc_hdr = (const struct rlc_firmware_header_v2_3 *)adev->gfx.rlc_fw->data;
+       adev->gfx.rlcp_ucode_version = le32_to_cpu(rlc_hdr->rlcp_ucode_version);
+       adev->gfx.rlcp_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcp_ucode_feature_version);
+       adev->gfx.rlc.rlcp_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcp_ucode_size_bytes);
+       adev->gfx.rlc.rlcp_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcp_ucode_offset_bytes);
+
+       adev->gfx.rlcv_ucode_version = le32_to_cpu(rlc_hdr->rlcv_ucode_version);
+       adev->gfx.rlcv_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcv_ucode_feature_version);
+       adev->gfx.rlc.rlcv_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcv_ucode_size_bytes);
+       adev->gfx.rlc.rlcv_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcv_ucode_offset_bytes);
+
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+               if (adev->gfx.rlc.rlcp_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_P];
+                       info->ucode_id = AMDGPU_UCODE_ID_RLC_P;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.rlcp_ucode_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.rlcv_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_V];
+                       info->ucode_id = AMDGPU_UCODE_ID_RLC_V;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.rlcv_ucode_size_bytes, PAGE_SIZE);
+               }
+       }
+}
+
+static void amdgpu_gfx_rlc_init_microcode_v2_4(struct amdgpu_device *adev)
+{
+       const struct rlc_firmware_header_v2_4 *rlc_hdr;
+       struct amdgpu_firmware_info *info;
+
+       rlc_hdr = (const struct rlc_firmware_header_v2_4 *)adev->gfx.rlc_fw->data;
+       adev->gfx.rlc.global_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->global_tap_delays_ucode_size_bytes);
+       adev->gfx.rlc.global_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->global_tap_delays_ucode_offset_bytes);
+       adev->gfx.rlc.se0_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_size_bytes);
+       adev->gfx.rlc.se0_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_offset_bytes);
+       adev->gfx.rlc.se1_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_size_bytes);
+       adev->gfx.rlc.se1_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_offset_bytes);
+       adev->gfx.rlc.se2_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_size_bytes);
+       adev->gfx.rlc.se2_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_offset_bytes);
+       adev->gfx.rlc.se3_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_size_bytes);
+       adev->gfx.rlc.se3_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_offset_bytes);
+
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+               if (adev->gfx.rlc.global_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.global_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.se0_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE0_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE0_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se0_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.se1_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE1_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE1_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se1_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.se2_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE2_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE2_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se2_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
+
+               if (adev->gfx.rlc.se3_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE3_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE3_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se3_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
+       }
+}
+
+int amdgpu_gfx_rlc_init_microcode(struct amdgpu_device *adev,
+                                 uint16_t version_major,
+                                 uint16_t version_minor)
+{
+       int err;
+
+       if (version_major < 2) {
+               /* only support rlc_hdr v2.x and onwards */
+               dev_err(adev->dev, "unsupported rlc fw hdr\n");
+               return -EINVAL;
+       }
+
+       /* is_rlc_v2_1 is still used in APU code path */
+       if (version_major == 2 && version_minor == 1)
+               adev->gfx.rlc.is_rlc_v2_1 = true;
+
+       if (version_minor >= 0) {
+               err = amdgpu_gfx_rlc_init_microcode_v2_0(adev);
+               if (err) {
+                       dev_err(adev->dev, "fail to init rlc v2_0 microcode\n");
+                       return err;
+               }
+       }
+       if (version_minor >= 1)
+               amdgpu_gfx_rlc_init_microcode_v2_1(adev);
+       if (version_minor >= 2)
+               amdgpu_gfx_rlc_init_microcode_v2_2(adev);
+       if (version_minor == 3)
+               amdgpu_gfx_rlc_init_microcode_v2_3(adev);
+       if (version_minor == 4)
+               amdgpu_gfx_rlc_init_microcode_v2_4(adev);
+
+       return 0;
+}
index 03ac36b..23f060d 100644 (file)
@@ -267,5 +267,7 @@ int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev);
 int amdgpu_gfx_rlc_init_cpt(struct amdgpu_device *adev);
 void amdgpu_gfx_rlc_setup_cp_table(struct amdgpu_device *adev);
 void amdgpu_gfx_rlc_fini(struct amdgpu_device *adev);
-
+int amdgpu_gfx_rlc_init_microcode(struct amdgpu_device *adev,
+                                 uint16_t version_major,
+                                 uint16_t version_minor);
 #endif
index ebed3f5..59edf32 100644 (file)
@@ -260,8 +260,12 @@ struct rlc_firmware_header_v2_2 {
 /* version_major=2, version_minor=3 */
 struct rlc_firmware_header_v2_3 {
     struct rlc_firmware_header_v2_2 v2_2;
+    uint32_t rlcp_ucode_version;
+    uint32_t rlcp_ucode_feature_version;
     uint32_t rlcp_ucode_size_bytes;
     uint32_t rlcp_ucode_offset_bytes;
+    uint32_t rlcv_ucode_version;
+    uint32_t rlcv_ucode_feature_version;
     uint32_t rlcv_ucode_size_bytes;
     uint32_t rlcv_ucode_offset_bytes;
 };
@@ -390,6 +394,7 @@ union amdgpu_firmware_header {
        struct rlc_firmware_header_v2_1 rlc_v2_1;
        struct rlc_firmware_header_v2_2 rlc_v2_2;
        struct rlc_firmware_header_v2_3 rlc_v2_3;
+       struct rlc_firmware_header_v2_4 rlc_v2_4;
        struct sdma_firmware_header_v1_0 sdma;
        struct sdma_firmware_header_v1_1 sdma_v1_1;
        struct sdma_firmware_header_v2_0 sdma_v2_0;
index f36e4f0..0b52af4 100644 (file)
@@ -191,7 +191,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
                fw_name = FIRMWARE_VCN4_0_2;
                if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
                        (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
-                       adev->vcn.indirect_sram = false;
+                       adev->vcn.indirect_sram = true;
                break;
        case IP_VERSION(4, 0, 4):
                fw_name = FIRMWARE_VCN4_0_4;
index 59cac34..690fd4f 100644 (file)
@@ -2484,8 +2484,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
                /* Intentionally setting invalid PTE flag
                 * combination to force a no-retry-fault
                 */
-               flags = AMDGPU_PTE_EXECUTABLE | AMDGPU_PDE_PTE |
-                       AMDGPU_PTE_TF;
+               flags = AMDGPU_PTE_SNOOPED | AMDGPU_PTE_PRT;
                value = 0;
        } else if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_NEVER) {
                /* Redirect the access to the dummy page */
index a2a4dc1..a3cd5c1 100644 (file)
@@ -4274,35 +4274,45 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
 
                }
 
-               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS];
-               info->ucode_id = AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS;
-               info->fw = adev->gfx.rlc_fw;
-               adev->firmware.fw_size +=
-                       ALIGN(adev->gfx.rlc.global_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               if (adev->gfx.rlc.global_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.global_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
 
-               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE0_TAP_DELAYS];
-               info->ucode_id = AMDGPU_UCODE_ID_SE0_TAP_DELAYS;
-               info->fw = adev->gfx.rlc_fw;
-               adev->firmware.fw_size +=
-                       ALIGN(adev->gfx.rlc.se0_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               if (adev->gfx.rlc.se0_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE0_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE0_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se0_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
 
-               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE1_TAP_DELAYS];
-               info->ucode_id = AMDGPU_UCODE_ID_SE1_TAP_DELAYS;
-               info->fw = adev->gfx.rlc_fw;
-               adev->firmware.fw_size +=
-                       ALIGN(adev->gfx.rlc.se1_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               if (adev->gfx.rlc.se1_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE1_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE1_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se1_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
 
-               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE2_TAP_DELAYS];
-               info->ucode_id = AMDGPU_UCODE_ID_SE2_TAP_DELAYS;
-               info->fw = adev->gfx.rlc_fw;
-               adev->firmware.fw_size +=
-                       ALIGN(adev->gfx.rlc.se2_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               if (adev->gfx.rlc.se2_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE2_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE2_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se2_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
 
-               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE3_TAP_DELAYS];
-               info->ucode_id = AMDGPU_UCODE_ID_SE3_TAP_DELAYS;
-               info->fw = adev->gfx.rlc_fw;
-               adev->firmware.fw_size +=
-                       ALIGN(adev->gfx.rlc.se3_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               if (adev->gfx.rlc.se3_tap_delays_ucode_size_bytes) {
+                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE3_TAP_DELAYS];
+                       info->ucode_id = AMDGPU_UCODE_ID_SE3_TAP_DELAYS;
+                       info->fw = adev->gfx.rlc_fw;
+                       adev->firmware.fw_size +=
+                               ALIGN(adev->gfx.rlc.se3_tap_delays_ucode_size_bytes, PAGE_SIZE);
+               }
 
                info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
                info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1;
index f6b1bb4..daf8ba8 100644 (file)
@@ -474,49 +474,6 @@ static void gfx_v11_0_free_microcode(struct amdgpu_device *adev)
        kfree(adev->gfx.rlc.register_list_format);
 }
 
-static void gfx_v11_0_init_rlc_ext_microcode(struct amdgpu_device *adev)
-{
-       const struct rlc_firmware_header_v2_1 *rlc_hdr;
-
-       rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
-       adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
-       adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
-       adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
-       adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
-       adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
-       adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
-       adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
-       adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
-       adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
-       adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
-       adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
-       adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
-       adev->gfx.rlc.reg_list_format_direct_reg_list_length =
-                       le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
-}
-
-static void gfx_v11_0_init_rlc_iram_dram_microcode(struct amdgpu_device *adev)
-{
-       const struct rlc_firmware_header_v2_2 *rlc_hdr;
-
-       rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data;
-       adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes);
-       adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes);
-       adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes);
-       adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes);
-}
-
-static void gfx_v11_0_init_rlcp_rlcv_microcode(struct amdgpu_device *adev)
-{
-       const struct rlc_firmware_header_v2_3 *rlc_hdr;
-
-       rlc_hdr = (const struct rlc_firmware_header_v2_3 *)adev->gfx.rlc_fw->data;
-       adev->gfx.rlc.rlcp_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcp_ucode_size_bytes);
-       adev->gfx.rlc.rlcp_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcp_ucode_offset_bytes);
-       adev->gfx.rlc.rlcv_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcv_ucode_size_bytes);
-       adev->gfx.rlc.rlcv_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcv_ucode_offset_bytes);
-}
-
 static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
 {
        char fw_name[40];
@@ -527,8 +484,6 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
        const struct gfx_firmware_header_v1_0 *cp_hdr;
        const struct gfx_firmware_header_v2_0 *cp_hdr_v2_0;
        const struct rlc_firmware_header_v2_0 *rlc_hdr;
-       unsigned int *tmp = NULL;
-       unsigned int i = 0;
        uint16_t version_major;
        uint16_t version_minor;
 
@@ -583,58 +538,14 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
                if (err)
                        goto out;
                err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
+               if (err)
+                       goto out;
                rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
                version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
                version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
-
-               adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
-               adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
-               adev->gfx.rlc.save_and_restore_offset =
-                       le32_to_cpu(rlc_hdr->save_and_restore_offset);
-               adev->gfx.rlc.clear_state_descriptor_offset =
-                       le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
-               adev->gfx.rlc.avail_scratch_ram_locations =
-                       le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
-               adev->gfx.rlc.reg_restore_list_size =
-                       le32_to_cpu(rlc_hdr->reg_restore_list_size);
-               adev->gfx.rlc.reg_list_format_start =
-                       le32_to_cpu(rlc_hdr->reg_list_format_start);
-               adev->gfx.rlc.reg_list_format_separate_start =
-                       le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
-               adev->gfx.rlc.starting_offsets_start =
-                       le32_to_cpu(rlc_hdr->starting_offsets_start);
-               adev->gfx.rlc.reg_list_format_size_bytes =
-                       le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
-               adev->gfx.rlc.reg_list_size_bytes =
-                       le32_to_cpu(rlc_hdr->reg_list_size_bytes);
-               adev->gfx.rlc.register_list_format =
-                       kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
-                                       adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
-               if (!adev->gfx.rlc.register_list_format) {
-                       err = -ENOMEM;
+               err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
+               if (err)
                        goto out;
-               }
-
-               tmp = (unsigned int *)((uintptr_t)rlc_hdr +
-                                                          le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
-               for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
-                       adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
-
-               adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
-
-               tmp = (unsigned int *)((uintptr_t)rlc_hdr +
-                                                          le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
-               for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
-                       adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
-
-               if (version_major == 2) {
-                       if (version_minor >= 1)
-                               gfx_v11_0_init_rlc_ext_microcode(adev);
-                       if (version_minor >= 2)
-                               gfx_v11_0_init_rlc_iram_dram_microcode(adev);
-                       if (version_minor == 3)
-                               gfx_v11_0_init_rlcp_rlcv_microcode(adev);
-               }
        }
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", ucode_prefix);
@@ -769,60 +680,6 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
                        adev->firmware.fw_size +=
                                ALIGN(le32_to_cpu(cp_hdr->jt_size) * 4, PAGE_SIZE);
                }
-
-               info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
-               info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
-               info->fw = adev->gfx.rlc_fw;
-               if (info->fw) {
-                       header = (const struct common_firmware_header *)info->fw->data;
-                       adev->firmware.fw_size +=
-                               ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
-               }
-               if (adev->gfx.rlc.save_restore_list_gpm_size_bytes &&
-                   adev->gfx.rlc.save_restore_list_srm_size_bytes) {
-                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
-                       info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
-                       info->fw = adev->gfx.rlc_fw;
-                       adev->firmware.fw_size +=
-                               ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
-
-                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
-                       info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
-                       info->fw = adev->gfx.rlc_fw;
-                       adev->firmware.fw_size +=
-                               ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
-               }
-
-               if (adev->gfx.rlc.rlc_iram_ucode_size_bytes &&
-                   adev->gfx.rlc.rlc_dram_ucode_size_bytes) {
-                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM];
-                       info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM;
-                       info->fw = adev->gfx.rlc_fw;
-                       adev->firmware.fw_size +=
-                               ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE);
-
-                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM];
-                       info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM;
-                       info->fw = adev->gfx.rlc_fw;
-                       adev->firmware.fw_size +=
-                               ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE);
-               }
-
-               if (adev->gfx.rlc.rlcp_ucode_size_bytes) {
-                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_P];
-                       info->ucode_id = AMDGPU_UCODE_ID_RLC_P;
-                       info->fw = adev->gfx.rlc_fw;
-                       adev->firmware.fw_size +=
-                               ALIGN(adev->gfx.rlc.rlcp_ucode_size_bytes, PAGE_SIZE);
-               }
-
-               if (adev->gfx.rlc.rlcv_ucode_size_bytes) {
-                       info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_V];
-                       info->ucode_id = AMDGPU_UCODE_ID_RLC_V;
-                       info->fw = adev->gfx.rlc_fw;
-                       adev->firmware.fw_size +=
-                               ALIGN(adev->gfx.rlc.rlcv_ucode_size_bytes, PAGE_SIZE);
-               }
        }
 
 out:
@@ -5260,6 +5117,8 @@ static void gfx_v11_0_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
 {
        u32 reg, data;
 
+       amdgpu_gfx_off_ctrl(adev, false);
+
        reg = SOC15_REG_OFFSET(GC, 0, regRLC_SPM_MC_CNTL);
        if (amdgpu_sriov_is_pp_one_vf(adev))
                data = RREG32_NO_KIQ(reg);
@@ -5273,6 +5132,8 @@ static void gfx_v11_0_update_spm_vmid(struct amdgpu_device *adev, unsigned vmid)
                WREG32_SOC15_NO_KIQ(GC, 0, regRLC_SPM_MC_CNTL, data);
        else
                WREG32_SOC15(GC, 0, regRLC_SPM_MC_CNTL, data);
+
+       amdgpu_gfx_off_ctrl(adev, true);
 }
 
 static const struct amdgpu_rlc_funcs gfx_v11_0_rlc_funcs = {
index fc9c104..037af83 100644 (file)
@@ -5597,7 +5597,7 @@ static void gfx_v9_0_ring_emit_patch_cond_exec(struct amdgpu_ring *ring, unsigne
        BUG_ON(offset > ring->buf_mask);
        BUG_ON(ring->ring[offset] != 0x55aa55aa);
 
-       cur = (ring->wptr & ring->buf_mask) - 1;
+       cur = (ring->wptr - 1) & ring->buf_mask;
        if (likely(cur > offset))
                ring->ring[offset] = cur - offset;
        else
index 4603653..67ca16a 100644 (file)
@@ -1103,10 +1103,13 @@ static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level,
                        *flags |= AMDGPU_PDE_BFS(0x9);
 
        } else if (level == AMDGPU_VM_PDB0) {
-               if (*flags & AMDGPU_PDE_PTE)
+               if (*flags & AMDGPU_PDE_PTE) {
                        *flags &= ~AMDGPU_PDE_PTE;
-               else
+                       if (!(*flags & AMDGPU_PTE_VALID))
+                               *addr |= 1 << PAGE_SHIFT;
+               } else {
                        *flags |= AMDGPU_PTE_TF;
+               }
        }
 }
 
index 120ea29..f92744b 100644 (file)
@@ -183,6 +183,11 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
        mes_add_queue_pkt.trap_handler_addr = input->tba_addr;
        mes_add_queue_pkt.tma_addr = input->tma_addr;
        mes_add_queue_pkt.is_kfd_process = input->is_kfd_process;
+       mes_add_queue_pkt.trap_en = 1;
+
+       /* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
+       mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
+       mes_add_queue_pkt.gds_size = input->queue_size;
 
        return mes_v11_0_submit_pkt_and_poll_completion(mes,
                        &mes_add_queue_pkt, sizeof(mes_add_queue_pkt),
index b465baa..aa761ff 100644 (file)
@@ -380,6 +380,7 @@ static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
                WREG32_PCIE(smnPCIE_LC_CNTL, data);
 }
 
+#ifdef CONFIG_PCIEASPM
 static void nbio_v2_3_program_ltr(struct amdgpu_device *adev)
 {
        uint32_t def, data;
@@ -401,9 +402,11 @@ static void nbio_v2_3_program_ltr(struct amdgpu_device *adev)
        if (def != data)
                WREG32_PCIE(smnBIF_CFG_DEV0_EPF0_DEVICE_CNTL2, data);
 }
+#endif
 
 static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
 {
+#ifdef CONFIG_PCIEASPM
        uint32_t def, data;
 
        def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
@@ -459,7 +462,10 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
        if (def != data)
                WREG32_PCIE(smnPCIE_LC_CNTL6, data);
 
-       nbio_v2_3_program_ltr(adev);
+       /* Don't bother about LTR if LTR is not enabled
+        * in the path */
+       if (adev->pdev->ltr_path)
+               nbio_v2_3_program_ltr(adev);
 
        def = data = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP3);
        data |= 0x5DE0 << RCC_BIF_STRAP3__STRAP_VLINK_ASPM_IDLE_TIMER__SHIFT;
@@ -483,6 +489,7 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
        data &= ~PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK_MASK;
        if (def != data)
                WREG32_PCIE(smnPCIE_LC_CNTL3, data);
+#endif
 }
 
 static void nbio_v2_3_apply_lc_spc_mode_wa(struct amdgpu_device *adev)
index f7f6dde..37615a7 100644 (file)
@@ -282,6 +282,7 @@ static void nbio_v6_1_init_registers(struct amdgpu_device *adev)
                        mmBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2;
 }
 
+#ifdef CONFIG_PCIEASPM
 static void nbio_v6_1_program_ltr(struct amdgpu_device *adev)
 {
        uint32_t def, data;
@@ -303,9 +304,11 @@ static void nbio_v6_1_program_ltr(struct amdgpu_device *adev)
        if (def != data)
                WREG32_PCIE(smnBIF_CFG_DEV0_EPF0_DEVICE_CNTL2, data);
 }
+#endif
 
 static void nbio_v6_1_program_aspm(struct amdgpu_device *adev)
 {
+#ifdef CONFIG_PCIEASPM
        uint32_t def, data;
 
        def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
@@ -361,7 +364,10 @@ static void nbio_v6_1_program_aspm(struct amdgpu_device *adev)
        if (def != data)
                WREG32_PCIE(smnPCIE_LC_CNTL6, data);
 
-       nbio_v6_1_program_ltr(adev);
+       /* Don't bother about LTR if LTR is not enabled
+        * in the path */
+       if (adev->pdev->ltr_path)
+               nbio_v6_1_program_ltr(adev);
 
        def = data = RREG32_PCIE(smnRCC_BIF_STRAP3);
        data |= 0x5DE0 << RCC_BIF_STRAP3__STRAP_VLINK_ASPM_IDLE_TIMER__SHIFT;
@@ -385,6 +391,7 @@ static void nbio_v6_1_program_aspm(struct amdgpu_device *adev)
        data &= ~PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK_MASK;
        if (def != data)
                WREG32_PCIE(smnPCIE_LC_CNTL3, data);
+#endif
 }
 
 const struct amdgpu_nbio_funcs nbio_v6_1_funcs = {
index 11848d1..19455a7 100644 (file)
@@ -673,6 +673,7 @@ struct amdgpu_nbio_ras nbio_v7_4_ras = {
 };
 
 
+#ifdef CONFIG_PCIEASPM
 static void nbio_v7_4_program_ltr(struct amdgpu_device *adev)
 {
        uint32_t def, data;
@@ -694,9 +695,11 @@ static void nbio_v7_4_program_ltr(struct amdgpu_device *adev)
        if (def != data)
                WREG32_PCIE(smnBIF_CFG_DEV0_EPF0_DEVICE_CNTL2, data);
 }
+#endif
 
 static void nbio_v7_4_program_aspm(struct amdgpu_device *adev)
 {
+#ifdef CONFIG_PCIEASPM
        uint32_t def, data;
 
        if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(7, 4, 4))
@@ -755,7 +758,10 @@ static void nbio_v7_4_program_aspm(struct amdgpu_device *adev)
        if (def != data)
                WREG32_PCIE(smnPCIE_LC_CNTL6, data);
 
-       nbio_v7_4_program_ltr(adev);
+       /* Don't bother about LTR if LTR is not enabled
+        * in the path */
+       if (adev->pdev->ltr_path)
+               nbio_v7_4_program_ltr(adev);
 
        def = data = RREG32_PCIE(smnRCC_BIF_STRAP3);
        data |= 0x5DE0 << RCC_BIF_STRAP3__STRAP_VLINK_ASPM_IDLE_TIMER__SHIFT;
@@ -779,6 +785,7 @@ static void nbio_v7_4_program_aspm(struct amdgpu_device *adev)
        data &= ~PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK_MASK;
        if (def != data)
                WREG32_PCIE(smnPCIE_LC_CNTL3, data);
+#endif
 }
 
 const struct amdgpu_nbio_funcs nbio_v7_4_funcs = {
index 1dc95ef..def8937 100644 (file)
 #include "nbio/nbio_7_7_0_sh_mask.h"
 #include <uapi/linux/kfd_ioctl.h>
 
+static void nbio_v7_7_remap_hdp_registers(struct amdgpu_device *adev)
+{
+       WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL,
+                    adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL);
+       WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_REG_FLUSH_CNTL,
+                    adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL);
+}
+
 static u32 nbio_v7_7_get_rev_id(struct amdgpu_device *adev)
 {
        u32 tmp;
@@ -68,12 +76,6 @@ static void nbio_v7_7_sdma_doorbell_range(struct amdgpu_device *adev, int instan
                doorbell_range = REG_SET_FIELD(doorbell_range,
                                               GDC0_BIF_CSDMA_DOORBELL_RANGE,
                                               SIZE, doorbell_size);
-               doorbell_range = REG_SET_FIELD(doorbell_range,
-                                              GDC0_BIF_SDMA0_DOORBELL_RANGE,
-                                              OFFSET, doorbell_index);
-               doorbell_range = REG_SET_FIELD(doorbell_range,
-                                              GDC0_BIF_SDMA0_DOORBELL_RANGE,
-                                              SIZE, doorbell_size);
        } else {
                doorbell_range = REG_SET_FIELD(doorbell_range,
                                               GDC0_BIF_SDMA0_DOORBELL_RANGE,
@@ -342,4 +344,5 @@ const struct amdgpu_nbio_funcs nbio_v7_7_funcs = {
        .get_clockgating_state = nbio_v7_7_get_clockgating_state,
        .ih_control = nbio_v7_7_ih_control,
        .init_registers = nbio_v7_7_init_registers,
+       .remap_hdp_registers = nbio_v7_7_remap_hdp_registers,
 };
index 65181ef..56424f7 100644 (file)
@@ -1504,6 +1504,11 @@ static int sdma_v4_0_start(struct amdgpu_device *adev)
                WREG32_SDMA(i, mmSDMA0_CNTL, temp);
 
                if (!amdgpu_sriov_vf(adev)) {
+                       ring = &adev->sdma.instance[i].ring;
+                       adev->nbio.funcs->sdma_doorbell_range(adev, i,
+                               ring->use_doorbell, ring->doorbell_index,
+                               adev->doorbell_index.sdma_doorbell_range);
+
                        /* unhalt engine */
                        temp = RREG32_SDMA(i, mmSDMA0_F32_CNTL);
                        temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0);
index fde6154..183024d 100644 (file)
@@ -1211,25 +1211,6 @@ static int soc15_common_sw_fini(void *handle)
        return 0;
 }
 
-static void soc15_doorbell_range_init(struct amdgpu_device *adev)
-{
-       int i;
-       struct amdgpu_ring *ring;
-
-       /* sdma/ih doorbell range are programed by hypervisor */
-       if (!amdgpu_sriov_vf(adev)) {
-               for (i = 0; i < adev->sdma.num_instances; i++) {
-                       ring = &adev->sdma.instance[i].ring;
-                       adev->nbio.funcs->sdma_doorbell_range(adev, i,
-                               ring->use_doorbell, ring->doorbell_index,
-                               adev->doorbell_index.sdma_doorbell_range);
-               }
-
-               adev->nbio.funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
-                                               adev->irq.ih.doorbell_index);
-       }
-}
-
 static int soc15_common_hw_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1249,12 +1230,6 @@ static int soc15_common_hw_init(void *handle)
 
        /* enable the doorbell aperture */
        soc15_enable_doorbell_aperture(adev, true);
-       /* HW doorbell routing policy: doorbell writing not
-        * in SDMA/IH/MM/ACV range will be routed to CP. So
-        * we need to init SDMA/IH/MM/ACV doorbell range prior
-        * to CP ip block init and ring test.
-        */
-       soc15_doorbell_range_init(adev);
 
        return 0;
 }
index 55284b2..6e564b5 100644 (file)
@@ -421,6 +421,7 @@ static bool soc21_need_full_reset(struct amdgpu_device *adev)
 {
        switch (adev->ip_versions[GC_HWIP][0]) {
        case IP_VERSION(11, 0, 0):
+               return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC);
        case IP_VERSION(11, 0, 2):
                return false;
        default:
@@ -624,6 +625,7 @@ static int soc21_common_early_init(void *handle)
                        AMD_CG_SUPPORT_JPEG_MGCG;
                adev->pg_flags =
                        AMD_PG_SUPPORT_GFX_PG |
+                       AMD_PG_SUPPORT_VCN_DPG |
                        AMD_PG_SUPPORT_JPEG;
                adev->external_rev_id = adev->rev_id + 0x1;
                break;
index 03b7066..1e83db0 100644 (file)
@@ -289,6 +289,10 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
                }
        }
 
+       if (!amdgpu_sriov_vf(adev))
+               adev->nbio.funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
+                                                   adev->irq.ih.doorbell_index);
+
        pci_set_master(adev->pdev);
 
        /* enable interrupts */
index 2022ffb..59dfca0 100644 (file)
@@ -340,6 +340,10 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
                }
        }
 
+       if (!amdgpu_sriov_vf(adev))
+               adev->nbio.funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
+                                                   adev->irq.ih.doorbell_index);
+
        pci_set_master(adev->pdev);
 
        /* enable interrupts */
index e83725a..007a3db 100644 (file)
@@ -205,6 +205,8 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
        }
 
        queue_input.is_kfd_process = 1;
+       queue_input.is_aql_queue = (q->properties.format == KFD_QUEUE_FORMAT_AQL);
+       queue_input.queue_size = q->properties.queue_size >> 2;
 
        queue_input.paging = false;
        queue_input.tba_addr = qpd->tba_addr;
index a6fcbee..0d53f60 100644 (file)
@@ -350,11 +350,11 @@ static void event_interrupt_wq_v11(struct kfd_dev *dev,
                                print_sq_intr_info_inst(context_id0, context_id1);
                                sq_int_priv = REG_GET_FIELD(context_id0,
                                                SQ_INTERRUPT_WORD_WAVE_CTXID0, PRIV);
-                               if (sq_int_priv /*&& (kfd_set_dbg_ev_from_interrupt(dev, pasid,
+                               /*if (sq_int_priv && (kfd_set_dbg_ev_from_interrupt(dev, pasid,
                                                KFD_CTXID0_DOORBELL_ID(context_id0),
                                                KFD_CTXID0_TRAP_CODE(context_id0),
-                                               NULL, 0))*/)
-                                       return;
+                                               NULL, 0)))
+                                       return;*/
                                break;
                        case SQ_INTERRUPT_WORD_ENCODING_ERROR:
                                print_sq_intr_info_error(context_id0, context_id1);
index b8e14c2..3ae3502 100644 (file)
@@ -126,6 +126,10 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
        m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF;
        m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF;
        m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF;
+       m->compute_static_thread_mgmt_se4 = 0xFFFFFFFF;
+       m->compute_static_thread_mgmt_se5 = 0xFFFFFFFF;
+       m->compute_static_thread_mgmt_se6 = 0xFFFFFFFF;
+       m->compute_static_thread_mgmt_se7 = 0xFFFFFFFF;
 
        m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
                        0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
index 5140d9c..1efe7fa 100644 (file)
@@ -4759,7 +4759,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
        plane_info->visible = true;
        plane_info->stereo_format = PLANE_STEREO_FORMAT_NONE;
 
-       plane_info->layer_index = 0;
+       plane_info->layer_index = plane_state->normalized_zpos;
 
        ret = fill_plane_color_attributes(plane_state, plane_info->format,
                                          &plane_info->color_space);
@@ -4827,7 +4827,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
        dc_plane_state->global_alpha = plane_info.global_alpha;
        dc_plane_state->global_alpha_value = plane_info.global_alpha_value;
        dc_plane_state->dcc = plane_info.dcc;
-       dc_plane_state->layer_index = plane_info.layer_index; // Always returns 0
+       dc_plane_state->layer_index = plane_info.layer_index;
        dc_plane_state->flip_int_enabled = true;
 
        /*
@@ -9485,6 +9485,14 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                }
        }
 
+       /*
+        * DC consults the zpos (layer_index in DC terminology) to determine the
+        * hw plane on which to enable the hw cursor (see
+        * `dcn10_can_pipe_disable_cursor`). By now, all modified planes are in
+        * atomic state, so call drm helper to normalize zpos.
+        */
+       drm_atomic_normalize_zpos(dev, state);
+
        /* Remove exiting planes if they are modified */
        for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
                ret = dm_update_plane_state(dc, state, plane,
index 0e48824..ee242d9 100644 (file)
@@ -3288,6 +3288,7 @@ void crtc_debugfs_init(struct drm_crtc *crtc)
                                   &crc_win_y_end_fops);
        debugfs_create_file_unsafe("crc_win_update", 0644, dir, crtc,
                                   &crc_win_update_fops);
+       dput(dir);
 #endif
        debugfs_create_file("amdgpu_current_bpc", 0644, crtc->debugfs_entry,
                            crtc, &amdgpu_current_bpc_fops);
index c8da18e..8ca10ab 100644 (file)
@@ -170,7 +170,13 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
                                           &stream, 1,
                                           &params);
 
-       power_opt |= psr_power_opt_z10_static_screen;
+       /*
+        * Only enable static-screen optimizations for PSR1. For PSR SU, this
+        * causes vstartup interrupt issues, used by amdgpu_dm to send vblank
+        * events.
+        */
+       if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
+               power_opt |= psr_power_opt_z10_static_screen;
 
        return dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt);
 }
index c09be3f..23a299c 100644 (file)
@@ -99,7 +99,7 @@ static int dcn31_get_active_display_cnt_wa(
        return display_count;
 }
 
-static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
+static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
 {
        struct dc *dc = clk_mgr_base->ctx->dc;
        int i;
@@ -110,9 +110,10 @@ static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
                if (pipe->top_pipe || pipe->prev_odm_pipe)
                        continue;
                if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) {
-                       if (disable)
+                       if (disable) {
                                pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
-                       else
+                               reset_sync_context_for_pipe(dc, context, i);
+                       } else
                                pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
                }
        }
@@ -211,11 +212,11 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
-               dcn31_disable_otg_wa(clk_mgr_base, true);
+               dcn31_disable_otg_wa(clk_mgr_base, context, true);
 
                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
                dcn31_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
-               dcn31_disable_otg_wa(clk_mgr_base, false);
+               dcn31_disable_otg_wa(clk_mgr_base, context, false);
 
                update_dispclk = true;
        }
index beb025c..4a15aa7 100644 (file)
@@ -119,7 +119,7 @@ static int dcn314_get_active_display_cnt_wa(
        return display_count;
 }
 
-static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
+static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
 {
        struct dc *dc = clk_mgr_base->ctx->dc;
        int i;
@@ -129,12 +129,21 @@ static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
 
                if (pipe->top_pipe || pipe->prev_odm_pipe)
                        continue;
-               if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL ||
-                                    dc_is_virtual_signal(pipe->stream->signal))) {
-                       if (disable)
+               if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) {
+                       struct stream_encoder *stream_enc = pipe->stream_res.stream_enc;
+
+                       if (disable) {
+                               if (stream_enc && stream_enc->funcs->disable_fifo)
+                                       pipe->stream_res.stream_enc->funcs->disable_fifo(stream_enc);
+
                                pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
-                       else
+                               reset_sync_context_for_pipe(dc, context, i);
+                       } else {
                                pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+
+                               if (stream_enc && stream_enc->funcs->enable_fifo)
+                                       pipe->stream_res.stream_enc->funcs->enable_fifo(stream_enc);
+                       }
                }
        }
 }
@@ -233,11 +242,11 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
-               dcn314_disable_otg_wa(clk_mgr_base, true);
+               dcn314_disable_otg_wa(clk_mgr_base, context, true);
 
                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
                dcn314_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
-               dcn314_disable_otg_wa(clk_mgr_base, false);
+               dcn314_disable_otg_wa(clk_mgr_base, context, false);
 
                update_dispclk = true;
        }
@@ -670,6 +679,8 @@ static void dcn314_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *cl
        }
        ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz);
        bw_params->vram_type = bios_info->memory_type;
+
+       bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4;
        bw_params->num_channels = bios_info->ma_channel_number ? bios_info->ma_channel_number : 4;
 
        for (i = 0; i < WM_SET_COUNT; i++) {
index cc07662..98ad8e0 100644 (file)
@@ -46,6 +46,9 @@
 #define TO_CLK_MGR_DCN315(clk_mgr)\
        container_of(clk_mgr, struct clk_mgr_dcn315, base)
 
+#define UNSUPPORTED_DCFCLK 10000000
+#define MIN_DPP_DISP_CLK     100000
+
 static int dcn315_get_active_display_cnt_wa(
                struct dc *dc,
                struct dc_state *context)
@@ -79,7 +82,7 @@ static int dcn315_get_active_display_cnt_wa(
        return display_count;
 }
 
-static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
+static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
 {
        struct dc *dc = clk_mgr_base->ctx->dc;
        int i;
@@ -91,9 +94,10 @@ static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
                        continue;
                if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL ||
                                     dc_is_virtual_signal(pipe->stream->signal))) {
-                       if (disable)
+                       if (disable) {
                                pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
-                       else
+                               reset_sync_context_for_pipe(dc, context, i);
+                       } else
                                pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
                }
        }
@@ -146,6 +150,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
                }
        }
 
+       /* Lock pstate by requesting unsupported dcfclk if change is unsupported */
+       if (!new_clocks->p_state_change_support)
+               new_clocks->dcfclk_khz = UNSUPPORTED_DCFCLK;
        if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
                clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
                dcn315_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
@@ -159,10 +166,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
 
        // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
        if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
-               if (new_clocks->dppclk_khz < 100000)
-                       new_clocks->dppclk_khz = 100000;
-               if (new_clocks->dispclk_khz < 100000)
-                       new_clocks->dispclk_khz = 100000;
+               if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK)
+                       new_clocks->dppclk_khz = MIN_DPP_DISP_CLK;
+               if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK)
+                       new_clocks->dispclk_khz = MIN_DPP_DISP_CLK;
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
@@ -175,12 +182,12 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
        if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
                /* No need to apply the w/a if we haven't taken over from bios yet */
                if (clk_mgr_base->clks.dispclk_khz)
-                       dcn315_disable_otg_wa(clk_mgr_base, true);
+                       dcn315_disable_otg_wa(clk_mgr_base, context, true);
 
                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
                dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
                if (clk_mgr_base->clks.dispclk_khz)
-                       dcn315_disable_otg_wa(clk_mgr_base, false);
+                       dcn315_disable_otg_wa(clk_mgr_base, context, false);
 
                update_dispclk = true;
        }
@@ -275,7 +282,7 @@ static struct wm_table ddr5_wm_table = {
                {
                        .wm_inst = WM_A,
                        .wm_type = WM_TYPE_PSTATE_CHG,
-                       .pstate_latency_us = 64.0,
+                       .pstate_latency_us = 129.0,
                        .sr_exit_time_us = 11.5,
                        .sr_enter_plus_exit_time_us = 14.5,
                        .valid = true,
@@ -283,7 +290,7 @@ static struct wm_table ddr5_wm_table = {
                {
                        .wm_inst = WM_B,
                        .wm_type = WM_TYPE_PSTATE_CHG,
-                       .pstate_latency_us = 64.0,
+                       .pstate_latency_us = 129.0,
                        .sr_exit_time_us = 11.5,
                        .sr_enter_plus_exit_time_us = 14.5,
                        .valid = true,
@@ -291,7 +298,7 @@ static struct wm_table ddr5_wm_table = {
                {
                        .wm_inst = WM_C,
                        .wm_type = WM_TYPE_PSTATE_CHG,
-                       .pstate_latency_us = 64.0,
+                       .pstate_latency_us = 129.0,
                        .sr_exit_time_us = 11.5,
                        .sr_enter_plus_exit_time_us = 14.5,
                        .valid = true,
@@ -299,7 +306,7 @@ static struct wm_table ddr5_wm_table = {
                {
                        .wm_inst = WM_D,
                        .wm_type = WM_TYPE_PSTATE_CHG,
-                       .pstate_latency_us = 64.0,
+                       .pstate_latency_us = 129.0,
                        .sr_exit_time_us = 11.5,
                        .sr_enter_plus_exit_time_us = 14.5,
                        .valid = true,
@@ -556,8 +563,7 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
        ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz);
        bw_params->vram_type = bios_info->memory_type;
        bw_params->num_channels = bios_info->ma_channel_number;
-       if (!bw_params->num_channels)
-               bw_params->num_channels = 2;
+       bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4;
 
        for (i = 0; i < WM_SET_COUNT; i++) {
                bw_params->wm_table.entries[i].wm_inst = i;
index 0cd3d2e..187f5b2 100644 (file)
@@ -112,7 +112,7 @@ static int dcn316_get_active_display_cnt_wa(
        return display_count;
 }
 
-static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
+static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
 {
        struct dc *dc = clk_mgr_base->ctx->dc;
        int i;
@@ -124,9 +124,10 @@ static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable)
                        continue;
                if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL ||
                                     dc_is_virtual_signal(pipe->stream->signal))) {
-                       if (disable)
+                       if (disable) {
                                pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
-                       else
+                               reset_sync_context_for_pipe(dc, context, i);
+                       } else
                                pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
                }
        }
@@ -221,11 +222,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
        }
 
        if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
-               dcn316_disable_otg_wa(clk_mgr_base, true);
+               dcn316_disable_otg_wa(clk_mgr_base, context, true);
 
                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
                dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
-               dcn316_disable_otg_wa(clk_mgr_base, false);
+               dcn316_disable_otg_wa(clk_mgr_base, context, false);
 
                update_dispclk = true;
        }
index c678596..f0f3f66 100644 (file)
@@ -156,12 +156,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
 {
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
        unsigned int num_levels;
+       unsigned int num_dcfclk_levels, num_dtbclk_levels, num_dispclk_levels;
 
        memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
        clk_mgr_base->clks.p_state_change_support = true;
        clk_mgr_base->clks.prev_p_state_change_support = true;
        clk_mgr_base->clks.fclk_prev_p_state_change_support = true;
        clk_mgr->smu_present = false;
+       clk_mgr->dpm_present = false;
 
        if (!clk_mgr_base->bw_params)
                return;
@@ -179,6 +181,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
        dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
                        &num_levels);
+       num_dcfclk_levels = num_levels;
 
        /* SOCCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
@@ -189,11 +192,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
                dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
                                &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
                                &num_levels);
+       num_dtbclk_levels = num_levels;
 
        /* DISPCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
                        &num_levels);
+       num_dispclk_levels = num_levels;
+
+       if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels)
+               clk_mgr->dpm_present = true;
 
        if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
                unsigned int i;
@@ -658,6 +666,12 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
                        &num_levels);
        clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
 
+       if (clk_mgr->dpm_present && !num_levels)
+               clk_mgr->dpm_present = false;
+
+       if (!clk_mgr->dpm_present)
+               dcn32_patch_dpm_table(clk_mgr_base->bw_params);
+
        DC_FP_START();
        /* Refresh bounding box */
        clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
index aeecca6..fb22c3d 100644 (file)
@@ -1094,7 +1094,8 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
                                dc->current_state->stream_count != context->stream_count)
                        should_disable = true;
 
-               if (old_stream && !dc->current_state->res_ctx.pipe_ctx[i].top_pipe) {
+               if (old_stream && !dc->current_state->res_ctx.pipe_ctx[i].top_pipe &&
+                               !dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe) {
                        struct pipe_ctx *old_pipe, *new_pipe;
 
                        old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
index 48dad09..780f7f4 100644 (file)
@@ -2758,8 +2758,14 @@ bool perform_link_training_with_retries(
                                                skip_video_pattern);
 
                                /* Transmit idle pattern once training successful. */
-                               if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
+                               if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) {
                                        dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
+                                       /* Update verified link settings to current one
+                                        * Because DPIA LT might fallback to lower link setting.
+                                        */
+                                       link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
+                                       link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
+                               }
                        } else {
                                status = dc_link_dp_perform_link_training(link,
                                                &pipe_ctx->link_res,
@@ -5121,6 +5127,14 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
                                lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES -
                                                                DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
 
+               /* If this chip cap is set, at least one retimer must exist in the chain
+                * Override count to 1 if we receive a known bad count (0 or an invalid value) */
+               if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
+                               (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
+                       ASSERT(0);
+                       link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
+               }
+
                /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
                is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
                                link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
index 7dbab15..ccf7bd3 100644 (file)
@@ -3584,6 +3584,23 @@ void check_syncd_pipes_for_disabled_master_pipe(struct dc *dc,
        }
 }
 
+void reset_sync_context_for_pipe(const struct dc *dc,
+       struct dc_state *context,
+       uint8_t pipe_idx)
+{
+       int i;
+       struct pipe_ctx *pipe_ctx_reset;
+
+       /* reset the otg sync context for the pipe and its slave pipes if any */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               pipe_ctx_reset = &context->res_ctx.pipe_ctx[i];
+
+               if (((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx_reset) == pipe_idx) &&
+                       IS_PIPE_SYNCD_VALID(pipe_ctx_reset)) || (i == pipe_idx))
+                       SET_PIPE_SYNCD_TO_PIPE(pipe_ctx_reset, i);
+       }
+}
+
 uint8_t resource_transmitter_to_phy_idx(const struct dc *dc, enum transmitter transmitter)
 {
        /* TODO - get transmitter to phy idx mapping from DMUB */
index f62d509..0c85ab5 100644 (file)
@@ -329,7 +329,7 @@ bool dc_stream_set_cursor_attributes(
 
        dc = stream->ctx->dc;
 
-       if (attributes->height * attributes->width * 4 > 16384)
+       if (dc->debug.allow_sw_cursor_fallback && attributes->height * attributes->width * 4 > 16384)
                if (stream->mall_stream_config.type == SUBVP_MAIN)
                        return false;
 
index 5908b60..dbf8158 100644 (file)
@@ -745,6 +745,7 @@ struct dc_debug_options {
        bool disable_fixed_vs_aux_timeout_wa;
        bool force_disable_subvp;
        bool force_subvp_mclk_switch;
+       bool allow_sw_cursor_fallback;
        bool force_usr_allow;
        /* uses value at boot and disables switch */
        bool disable_dtb_ref_clk_switch;
index 09b3045..52a61b3 100644 (file)
@@ -417,44 +417,42 @@ static void populate_subvp_cmd_drr_info(struct dc *dc,
        struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
        struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
        struct dc_crtc_timing *drr_timing = &vblank_pipe->stream->timing;
-       int16_t drr_frame_us = 0;
-       int16_t min_drr_supported_us = 0;
-       int16_t max_drr_supported_us = 0;
-       int16_t max_drr_vblank_us = 0;
-       int16_t max_drr_mallregion_us = 0;
-       int16_t mall_region_us = 0;
-       int16_t prefetch_us = 0;
-       int16_t subvp_active_us = 0;
-       int16_t drr_active_us = 0;
-       int16_t min_vtotal_supported = 0;
-       int16_t max_vtotal_supported = 0;
+       uint16_t drr_frame_us = 0;
+       uint16_t min_drr_supported_us = 0;
+       uint16_t max_drr_supported_us = 0;
+       uint16_t max_drr_vblank_us = 0;
+       uint16_t max_drr_mallregion_us = 0;
+       uint16_t mall_region_us = 0;
+       uint16_t prefetch_us = 0;
+       uint16_t subvp_active_us = 0;
+       uint16_t drr_active_us = 0;
+       uint16_t min_vtotal_supported = 0;
+       uint16_t max_vtotal_supported = 0;
 
        pipe_data->pipe_config.vblank_data.drr_info.drr_in_use = true;
        pipe_data->pipe_config.vblank_data.drr_info.use_ramping = false; // for now don't use ramping
        pipe_data->pipe_config.vblank_data.drr_info.drr_window_size_ms = 4; // hardcode 4ms DRR window for now
 
-       drr_frame_us = div64_s64(drr_timing->v_total * drr_timing->h_total,
-                                (int64_t)(drr_timing->pix_clk_100hz * 100) * 1000000);
+       drr_frame_us = div64_u64(((uint64_t)drr_timing->v_total * drr_timing->h_total * 1000000),
+                       (((uint64_t)drr_timing->pix_clk_100hz * 100)));
        // P-State allow width and FW delays already included phantom_timing->v_addressable
-       mall_region_us = div64_s64(phantom_timing->v_addressable * phantom_timing->h_total,
-                                  (int64_t)(phantom_timing->pix_clk_100hz * 100) * 1000000);
+       mall_region_us = div64_u64(((uint64_t)phantom_timing->v_addressable * phantom_timing->h_total * 1000000),
+                       (((uint64_t)phantom_timing->pix_clk_100hz * 100)));
        min_drr_supported_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US;
-       min_vtotal_supported = div64_s64(drr_timing->pix_clk_100hz * 100 *
-                                        (div64_s64((int64_t)min_drr_supported_us, 1000000)),
-                                        (int64_t)drr_timing->h_total);
-
-       prefetch_us = div64_s64((phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total,
-                               (int64_t)(phantom_timing->pix_clk_100hz * 100) * 1000000 +
-                               dc->caps.subvp_prefetch_end_to_mall_start_us);
-       subvp_active_us = div64_s64(main_timing->v_addressable * main_timing->h_total,
-                                   (int64_t)(main_timing->pix_clk_100hz * 100) * 1000000);
-       drr_active_us = div64_s64(drr_timing->v_addressable * drr_timing->h_total,
-                                 (int64_t)(drr_timing->pix_clk_100hz * 100) * 1000000);
-       max_drr_vblank_us = div64_s64((int64_t)(subvp_active_us - prefetch_us - drr_active_us), 2) + drr_active_us;
+       min_vtotal_supported = div64_u64(((uint64_t)drr_timing->pix_clk_100hz * 100 * min_drr_supported_us),
+                       (((uint64_t)drr_timing->h_total * 1000000)));
+
+       prefetch_us = div64_u64(((uint64_t)(phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total * 1000000),
+                       (((uint64_t)phantom_timing->pix_clk_100hz * 100) + dc->caps.subvp_prefetch_end_to_mall_start_us));
+       subvp_active_us = div64_u64(((uint64_t)main_timing->v_addressable * main_timing->h_total * 1000000),
+                       (((uint64_t)main_timing->pix_clk_100hz * 100)));
+       drr_active_us = div64_u64(((uint64_t)drr_timing->v_addressable * drr_timing->h_total * 1000000),
+                       (((uint64_t)drr_timing->pix_clk_100hz * 100)));
+       max_drr_vblank_us = div64_u64((subvp_active_us - prefetch_us - drr_active_us), 2) + drr_active_us;
        max_drr_mallregion_us = subvp_active_us - prefetch_us - mall_region_us;
        max_drr_supported_us = max_drr_vblank_us > max_drr_mallregion_us ? max_drr_vblank_us : max_drr_mallregion_us;
-       max_vtotal_supported = div64_s64(drr_timing->pix_clk_100hz * 100 * (div64_s64((int64_t)max_drr_supported_us, 1000000)),
-                                        (int64_t)drr_timing->h_total);
+       max_vtotal_supported = div64_u64(((uint64_t)drr_timing->pix_clk_100hz * 100 * max_drr_supported_us),
+                       (((uint64_t)drr_timing->h_total * 1000000)));
 
        pipe_data->pipe_config.vblank_data.drr_info.min_vtotal_supported = min_vtotal_supported;
        pipe_data->pipe_config.vblank_data.drr_info.max_vtotal_supported = max_vtotal_supported;
@@ -548,10 +546,12 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
        struct dc_crtc_timing *phantom_timing1 = &subvp_pipes[1]->stream->mall_stream_config.paired_stream->timing;
        struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = NULL;
 
-       subvp0_prefetch_us = div64_s64((phantom_timing0->v_total - phantom_timing0->v_front_porch) * phantom_timing0->h_total,
-                                      (int64_t)(phantom_timing0->pix_clk_100hz * 100) * 1000000 + dc->caps.subvp_prefetch_end_to_mall_start_us);
-       subvp1_prefetch_us = div64_s64((phantom_timing1->v_total - phantom_timing1->v_front_porch) * phantom_timing1->h_total,
-                                      (int64_t)(phantom_timing1->pix_clk_100hz * 100) * 1000000 + dc->caps.subvp_prefetch_end_to_mall_start_us);
+       subvp0_prefetch_us = div64_u64(((uint64_t)(phantom_timing0->v_total - phantom_timing0->v_front_porch) *
+                       (uint64_t)phantom_timing0->h_total * 1000000),
+                       (((uint64_t)phantom_timing0->pix_clk_100hz * 100) + dc->caps.subvp_prefetch_end_to_mall_start_us));
+       subvp1_prefetch_us = div64_u64(((uint64_t)(phantom_timing1->v_total - phantom_timing1->v_front_porch) *
+                       (uint64_t)phantom_timing1->h_total * 1000000),
+                       (((uint64_t)phantom_timing1->pix_clk_100hz * 100) + dc->caps.subvp_prefetch_end_to_mall_start_us));
 
        // Whichever SubVP PIPE has the smaller prefetch (including the prefetch end to mall start time)
        // should increase it's prefetch time to match the other
@@ -559,16 +559,17 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
                pipe_data = &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[1];
                prefetch_delta_us = subvp0_prefetch_us - subvp1_prefetch_us;
                pipe_data->pipe_config.subvp_data.prefetch_to_mall_start_lines =
-                       div64_s64(((div64_s64((int64_t)(dc->caps.subvp_prefetch_end_to_mall_start_us + prefetch_delta_us), 1000000)) *
-                                  (phantom_timing1->pix_clk_100hz * 100) + phantom_timing1->h_total - 1),
-                                 (int64_t)phantom_timing1->h_total);
+                               div64_u64(((uint64_t)(dc->caps.subvp_prefetch_end_to_mall_start_us + prefetch_delta_us) *
+                                       ((uint64_t)phantom_timing1->pix_clk_100hz * 100) + ((uint64_t)phantom_timing1->h_total * 1000000 - 1)),
+                                       ((uint64_t)phantom_timing1->h_total * 1000000));
+
        } else if (subvp1_prefetch_us >  subvp0_prefetch_us) {
                pipe_data = &cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[0];
                prefetch_delta_us = subvp1_prefetch_us - subvp0_prefetch_us;
                pipe_data->pipe_config.subvp_data.prefetch_to_mall_start_lines =
-                       div64_s64(((div64_s64((int64_t)(dc->caps.subvp_prefetch_end_to_mall_start_us + prefetch_delta_us), 1000000)) *
-                                  (phantom_timing0->pix_clk_100hz * 100) + phantom_timing0->h_total - 1),
-                                 (int64_t)phantom_timing0->h_total);
+                               div64_u64(((uint64_t)(dc->caps.subvp_prefetch_end_to_mall_start_us + prefetch_delta_us) *
+                                       ((uint64_t)phantom_timing0->pix_clk_100hz * 100) + ((uint64_t)phantom_timing0->h_total * 1000000 - 1)),
+                                       ((uint64_t)phantom_timing0->h_total * 1000000));
        }
 }
 
@@ -630,13 +631,11 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
 
        // Round up
        pipe_data->pipe_config.subvp_data.prefetch_to_mall_start_lines =
-               div64_s64(((div64_s64((int64_t)dc->caps.subvp_prefetch_end_to_mall_start_us, 1000000)) *
-                          (phantom_timing->pix_clk_100hz * 100) + phantom_timing->h_total - 1),
-                         (int64_t)phantom_timing->h_total);
+                       div64_u64(((uint64_t)dc->caps.subvp_prefetch_end_to_mall_start_us * ((uint64_t)phantom_timing->pix_clk_100hz * 100) +
+                                       ((uint64_t)phantom_timing->h_total * 1000000 - 1)), ((uint64_t)phantom_timing->h_total * 1000000));
        pipe_data->pipe_config.subvp_data.processing_delay_lines =
-               div64_s64(((div64_s64((int64_t)dc->caps.subvp_fw_processing_delay_us, 1000000)) *
-                          (phantom_timing->pix_clk_100hz * 100) + phantom_timing->h_total - 1),
-                         (int64_t)phantom_timing->h_total);
+                       div64_u64(((uint64_t)(dc->caps.subvp_fw_processing_delay_us) * ((uint64_t)phantom_timing->pix_clk_100hz * 100) +
+                                       ((uint64_t)phantom_timing->h_total * 1000000 - 1)), ((uint64_t)phantom_timing->h_total * 1000000));
        // Find phantom pipe index based on phantom stream
        for (j = 0; j < dc->res_pool->pipe_count; j++) {
                struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j];
index cd26711..7ce64a3 100644 (file)
        type DSCRM_DSC_FORWARD_EN; \
        type DSCRM_DSC_OPP_PIPE_SOURCE
 
-#define DSC_REG_LIST_DCN314(id) \
-       SRI(DSC_TOP_CONTROL, DSC_TOP, id),\
-       SRI(DSC_DEBUG_CONTROL, DSC_TOP, id),\
-       SRI(DSCC_CONFIG0, DSCC, id),\
-       SRI(DSCC_CONFIG1, DSCC, id),\
-       SRI(DSCC_STATUS, DSCC, id),\
-       SRI(DSCC_INTERRUPT_CONTROL_STATUS, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG0, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG1, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG2, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG3, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG4, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG5, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG6, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG7, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG8, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG9, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG10, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG11, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG12, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG13, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG14, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG15, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG16, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG17, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG18, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG19, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG20, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG21, DSCC, id),\
-       SRI(DSCC_PPS_CONFIG22, DSCC, id),\
-       SRI(DSCC_MEM_POWER_CONTROL, DSCC, id),\
-       SRI(DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC, id),\
-       SRI(DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC, id),\
-       SRI(DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC, id),\
-       SRI(DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC, id),\
-       SRI(DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC, id),\
-       SRI(DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC, id),\
-       SRI(DSCC_MAX_ABS_ERROR0, DSCC, id),\
-       SRI(DSCC_MAX_ABS_ERROR1, DSCC, id),\
-       SRI(DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC, id),\
-       SRI(DSCCIF_CONFIG0, DSCCIF, id),\
-       SRI(DSCCIF_CONFIG1, DSCCIF, id),\
-       SRI(DSCRM_DSC_FORWARD_CONFIG, DSCRM, id)
-
-#define DSC_REG_LIST_SH_MASK_DCN314(mask_sh)\
-       DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_CLOCK_EN, mask_sh), \
-       DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DISPCLK_R_GATE_DIS, mask_sh), \
-       DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DSCCLK_R_GATE_DIS, mask_sh), \
-       DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_DBG_EN, mask_sh), \
-       DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_TEST_CLOCK_MUX_SEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_PER_LINE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_CONFIG0, ALTERNATE_ICH_ENCODING_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_IN_VERTICAL_DIRECTION, mask_sh), \
-       DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, mask_sh), \
-       /*DSC_SF(DSCC0_DSCC_CONFIG1, DSCC_DISABLE_ICH, mask_sh),*/ \
-       DSC_SF(DSCC0_DSCC_STATUS, DSCC_DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER0_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER1_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER2_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_BUFFER3_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL0_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL1_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL2_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_INTERRUPT_CONTROL_STATUS, DSCC_RATE_CONTROL_BUFFER_MODEL3_OVERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG0, DSC_VERSION_MAJOR, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG0, PPS_IDENTIFIER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG0, LINEBUF_DEPTH, mask_sh), \
-       DSC2_SF(DSCC0, DSCC_PPS_CONFIG0__BITS_PER_COMPONENT, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BITS_PER_PIXEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, VBR_ENABLE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, SIMPLE_422, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CONVERT_RGB, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_422, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, NATIVE_420, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG1, CHUNK_SIZE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_WIDTH, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG2, PIC_HEIGHT, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_WIDTH, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG3, SLICE_HEIGHT, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_XMIT_DELAY, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG4, INITIAL_DEC_DELAY, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG5, INITIAL_SCALE_VALUE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG5, SCALE_INCREMENT_INTERVAL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SCALE_DECREMENT_INTERVAL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG6, FIRST_LINE_BPG_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG6, SECOND_LINE_BPG_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG7, NFL_BPG_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG8, NSL_BPG_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG8, SECOND_LINE_OFFSET_ADJ, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG9, INITIAL_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG9, FINAL_OFFSET, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MIN_QP, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG10, FLATNESS_MAX_QP, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG10, RC_MODEL_SIZE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_EDGE_FACTOR, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT0, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_QUANT_INCR_LIMIT1, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_LO, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG11, RC_TGT_OFFSET_HI, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH0, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH1, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH2, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG12, RC_BUF_THRESH3, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH4, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH5, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH6, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG13, RC_BUF_THRESH7, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH8, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH9, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH10, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG14, RC_BUF_THRESH11, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH12, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RC_BUF_THRESH13, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MIN_QP0, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_MAX_QP0, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG15, RANGE_BPG_OFFSET0, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP1, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP1, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET1, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MIN_QP2, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_MAX_QP2, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG16, RANGE_BPG_OFFSET2, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP3, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP3, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET3, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MIN_QP4, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_MAX_QP4, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG17, RANGE_BPG_OFFSET4, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP5, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP5, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET5, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MIN_QP6, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_MAX_QP6, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG18, RANGE_BPG_OFFSET6, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP7, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP7, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET7, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MIN_QP8, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_MAX_QP8, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG19, RANGE_BPG_OFFSET8, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP9, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP9, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET9, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MIN_QP10, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_MAX_QP10, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG20, RANGE_BPG_OFFSET10, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP11, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP11, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET11, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MIN_QP12, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_MAX_QP12, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG21, RANGE_BPG_OFFSET12, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP13, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP13, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET13, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MIN_QP14, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_MAX_QP14, mask_sh), \
-       DSC_SF(DSCC0_DSCC_PPS_CONFIG22, RANGE_BPG_OFFSET14, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_DEFAULT_MEM_LOW_POWER_STATE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_FORCE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_DIS, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_MEM_PWR_STATE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_FORCE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_DIS, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MEM_POWER_CONTROL, DSCC_NATIVE_422_MEM_PWR_STATE, mask_sh), \
-       DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_LOWER, DSCC_R_Y_SQUARED_ERROR_LOWER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_R_Y_SQUARED_ERROR_UPPER, DSCC_R_Y_SQUARED_ERROR_UPPER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_LOWER, DSCC_G_CB_SQUARED_ERROR_LOWER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_G_CB_SQUARED_ERROR_UPPER, DSCC_G_CB_SQUARED_ERROR_UPPER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_LOWER, DSCC_B_CR_SQUARED_ERROR_LOWER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_B_CR_SQUARED_ERROR_UPPER, DSCC_B_CR_SQUARED_ERROR_UPPER, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_R_Y_MAX_ABS_ERROR, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR0, DSCC_G_CB_MAX_ABS_ERROR, mask_sh), \
-       DSC_SF(DSCC0_DSCC_MAX_ABS_ERROR1, DSCC_B_CR_MAX_ABS_ERROR, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER0_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER1_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_RECOVERY_EN, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_INT_EN, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_INTERFACE_UNDERFLOW_OCCURRED_STATUS, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG0, INPUT_PIXEL_FORMAT, mask_sh), \
-       DSC2_SF(DSCCIF0, DSCCIF_CONFIG0__BITS_PER_COMPONENT, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG0, DOUBLE_BUFFER_REG_UPDATE_PENDING, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_WIDTH, mask_sh), \
-       DSC_SF(DSCCIF0_DSCCIF_CONFIG1, PIC_HEIGHT, mask_sh), \
-       DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, mask_sh), \
-       DSC_SF(DSCRM0_DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_OPP_PIPE_SOURCE, mask_sh)
-
-
 struct dcn20_dsc_registers {
        uint32_t DSC_TOP_CONTROL;
        uint32_t DSC_DEBUG_CONTROL;
index 884fa06..598ce87 100644 (file)
@@ -1565,6 +1565,7 @@ static void dcn20_update_dchubp_dpp(
        /* Any updates are handled in dc interface, just need
         * to apply existing for plane enable / opp change */
        if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
+                       || pipe_ctx->update_flags.bits.plane_changed
                        || pipe_ctx->stream->update_flags.bits.gamut_remap
                        || pipe_ctx->stream->update_flags.bits.out_csc) {
                /* dpp/cm gamut remap*/
index a788d16..ab70ebd 100644 (file)
@@ -104,6 +104,9 @@ static bool has_query_dp_alt(struct link_encoder *enc)
 {
        struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv;
 
+       if (enc->ctx->dce_version >= DCN_VERSION_3_15)
+               return true;
+
        /* Supports development firmware and firmware >= 4.0.11 */
        return dc_dmub_srv &&
               !(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) &&
index 232cc15..fb72967 100644 (file)
 #define DC_LOGGER \
        dccg->ctx->logger
 
+static void dccg314_get_pixel_rate_div(
+               struct dccg *dccg,
+               uint32_t otg_inst,
+               enum pixel_rate_div *k1,
+               enum pixel_rate_div *k2)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+       uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
+
+       *k1 = PIXEL_RATE_DIV_NA;
+       *k2 = PIXEL_RATE_DIV_NA;
+
+       switch (otg_inst) {
+       case 0:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG0_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG0_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 1:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG1_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG1_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 2:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG2_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG2_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 3:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG3_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG3_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       *k1 = (enum pixel_rate_div)val_k1;
+       *k2 = (enum pixel_rate_div)val_k2;
+}
+
 static void dccg314_set_pixel_rate_div(
                struct dccg *dccg,
                uint32_t otg_inst,
@@ -52,6 +94,11 @@ static void dccg314_set_pixel_rate_div(
                enum pixel_rate_div k2)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+       enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+
+       dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
+       if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA || (k1 == cur_k1 && k2 == cur_k2))
+               return;
 
        switch (otg_inst) {
        case 0:
index b384f30..8c0ab01 100644 (file)
@@ -56,7 +56,8 @@ static void enc314_enable_fifo(struct stream_encoder *enc)
 
        /* TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON */
        REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000);
-       REG_UPDATE_2(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1, DIG_FIFO_READ_START_LEVEL, 0x7);
+       REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
+       REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
        REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000);
        REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0);
        REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000);
@@ -67,8 +68,7 @@ static void enc314_disable_fifo(struct stream_encoder *enc)
 {
        struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
 
-       REG_UPDATE_2(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0,
-                    DIG_FIFO_READ_START_LEVEL, 0);
+       REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0);
 }
 
 static void enc314_dp_set_odm_combine(
@@ -262,6 +262,16 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
        return two_pix;
 }
 
+void enc314_stream_encoder_dp_blank(
+       struct dc_link *link,
+       struct stream_encoder *enc)
+{
+       /* New to DCN314 - disable the FIFO before VID stream disable. */
+       enc314_disable_fifo(enc);
+
+       enc1_stream_encoder_dp_blank(link, enc);
+}
+
 static void enc314_stream_encoder_dp_unblank(
                struct dc_link *link,
                struct stream_encoder *enc,
@@ -322,9 +332,6 @@ static void enc314_stream_encoder_dp_unblank(
 
        REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
 
-       /* DIG Resync FIFO now needs to be explicitly enabled. */
-       enc314_enable_fifo(enc);
-
        /* wait 100us for DIG/DP logic to prime
         * (i.e. a few video lines)
         */
@@ -340,6 +347,12 @@ static void enc314_stream_encoder_dp_unblank(
 
        REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true);
 
+       /*
+        * DIG Resync FIFO now needs to be explicitly enabled.
+        * This should come after DP_VID_STREAM_ENABLE per HW docs.
+        */
+       enc314_enable_fifo(enc);
+
        dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM);
 }
 
@@ -408,7 +421,7 @@ static const struct stream_encoder_funcs dcn314_str_enc_funcs = {
        .stop_dp_info_packets =
                enc1_stream_encoder_stop_dp_info_packets,
        .dp_blank =
-               enc1_stream_encoder_dp_blank,
+               enc314_stream_encoder_dp_blank,
        .dp_unblank =
                enc314_stream_encoder_dp_unblank,
        .audio_mute_control = enc3_audio_mute_control,
index 39931d4..f4d1b83 100644 (file)
@@ -343,7 +343,6 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
 {
        struct dc_stream_state *stream = pipe_ctx->stream;
        unsigned int odm_combine_factor = 0;
-       struct dc *dc = pipe_ctx->stream->ctx->dc;
        bool two_pix_per_container = false;
 
        two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
@@ -364,7 +363,7 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
                } else {
                        *k1_div = PIXEL_RATE_DIV_BY_1;
                        *k2_div = PIXEL_RATE_DIV_BY_4;
-                       if ((odm_combine_factor == 2) || dc->debug.enable_dp_dig_pixel_rate_div_policy)
+                       if (odm_combine_factor == 2)
                                *k2_div = PIXEL_RATE_DIV_BY_2;
                }
        }
@@ -384,21 +383,10 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
                return;
 
        odm_combine_factor = get_odm_config(pipe_ctx, NULL);
-       if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1
-               || dcn314_is_dp_dig_pixel_rate_div_policy(pipe_ctx))
+       if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1)
                pix_per_cycle = 2;
 
        if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
                pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc,
                                pix_per_cycle);
 }
-
-bool dcn314_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
-{
-       struct dc *dc = pipe_ctx->stream->ctx->dc;
-
-       if (dc_is_dp_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx) &&
-               dc->debug.enable_dp_dig_pixel_rate_div_policy)
-               return true;
-       return false;
-}
index d014580..2442802 100644 (file)
@@ -41,6 +41,4 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig
 
 void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx);
 
-bool dcn314_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
-
 #endif /* __DC_HWSS_DCN314_H__ */
index fcf67eb..72a563a 100644 (file)
@@ -146,7 +146,6 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
        .setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
        .calculate_dccg_k1_k2_values = dcn314_calculate_dccg_k1_k2_values,
        .set_pixels_per_cycle = dcn314_set_pixels_per_cycle,
-       .is_dp_dig_pixel_rate_div_policy = dcn314_is_dp_dig_pixel_rate_div_policy,
 };
 
 void dcn314_hw_sequencer_construct(struct dc *dc)
index 0c79802..38aa28e 100644 (file)
@@ -98,7 +98,8 @@ static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id,
        REG_UPDATE(OPTC_WIDTH_CONTROL,
                        OPTC_SEGMENT_WIDTH, mpcc_hactive);
 
-       REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
+       REG_UPDATE(OTG_H_TIMING_CNTL,
+                       OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
        optc1->opp_count = opp_cnt;
 }
 
index 3a9e387..44ac1c2 100644 (file)
@@ -87,6 +87,9 @@
 #define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH__SHIFT                0x10
 #define DCHUBBUB_DEBUG_CTRL_0__DET_DEPTH_MASK          0x01FF0000L
 
+#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE__SHIFT                   0x0
+#define DSCC0_DSCC_CONFIG0__ICH_RESET_AT_END_OF_LINE_MASK                     0x0000000FL
+
 #include "reg_helper.h"
 #include "dce/dmub_abm.h"
 #include "dce/dmub_psr.h"
@@ -454,6 +457,7 @@ static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs
        hpo_dp_stream_encoder_reg_list(0),
        hpo_dp_stream_encoder_reg_list(1),
        hpo_dp_stream_encoder_reg_list(2),
+       hpo_dp_stream_encoder_reg_list(3)
 };
 
 static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {
@@ -578,7 +582,7 @@ static const struct dcn30_mmhubbub_mask mcif_wb30_mask = {
 
 #define dsc_regsDCN314(id)\
 [id] = {\
-       DSC_REG_LIST_DCN314(id)\
+       DSC_REG_LIST_DCN20(id)\
 }
 
 static const struct dcn20_dsc_registers dsc_regs[] = {
@@ -589,11 +593,11 @@ static const struct dcn20_dsc_registers dsc_regs[] = {
 };
 
 static const struct dcn20_dsc_shift dsc_shift = {
-       DSC_REG_LIST_SH_MASK_DCN314(__SHIFT)
+       DSC_REG_LIST_SH_MASK_DCN20(__SHIFT)
 };
 
 static const struct dcn20_dsc_mask dsc_mask = {
-       DSC_REG_LIST_SH_MASK_DCN314(_MASK)
+       DSC_REG_LIST_SH_MASK_DCN20(_MASK)
 };
 
 static const struct dcn30_mpc_registers mpc_regs = {
@@ -843,7 +847,7 @@ static const struct resource_caps res_cap_dcn314 = {
        .num_ddc = 5,
        .num_vmid = 16,
        .num_mpc_3dlut = 2,
-       .num_dsc = 4,
+       .num_dsc = 3,
 };
 
 static const struct dc_plane_cap plane_cap = {
index a31c64b..6640d0a 100644 (file)
 #define DC_LOGGER \
        dccg->ctx->logger
 
+static void dccg32_get_pixel_rate_div(
+               struct dccg *dccg,
+               uint32_t otg_inst,
+               enum pixel_rate_div *k1,
+               enum pixel_rate_div *k2)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+       uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
+
+       *k1 = PIXEL_RATE_DIV_NA;
+       *k2 = PIXEL_RATE_DIV_NA;
+
+       switch (otg_inst) {
+       case 0:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG0_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG0_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 1:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG1_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG1_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 2:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG2_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG2_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 3:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG3_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG3_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       *k1 = (enum pixel_rate_div)val_k1;
+       *k2 = (enum pixel_rate_div)val_k2;
+}
+
 static void dccg32_set_pixel_rate_div(
                struct dccg *dccg,
                uint32_t otg_inst,
@@ -50,6 +92,17 @@ static void dccg32_set_pixel_rate_div(
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
 
+       enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+
+       // Don't program 0xF into the register field. Not valid since
+       // K1 / K2 field is only 1 / 2 bits wide
+       if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA)
+               return;
+
+       dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
+       if (k1 == cur_k1 && k2 == cur_k2)
+               return;
+
        switch (otg_inst) {
        case 0:
                REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
@@ -225,19 +278,19 @@ void dccg32_set_dpstreamclk(
        case 0:
                REG_UPDATE_2(DPSTREAMCLK_CNTL,
                             DPSTREAMCLK0_EN,
-                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, 0);
+                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);
                break;
        case 1:
                REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,
-                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, 1);
+                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);
                break;
        case 2:
                REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,
-                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, 2);
+                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);
                break;
        case 3:
                REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,
-                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, 3);
+                            (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);
                break;
        default:
                BREAK_TO_DEBUGGER();
index 26648ce..38a4898 100644 (file)
@@ -310,6 +310,11 @@ static void enc32_stream_encoder_dp_unblank(
        // TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON
        REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000);
 
+       /* read start level = 0 will bring underflow / overflow and DIG_FIFO_ERROR = 1
+        * so set it to 1/2 full = 7 before reset as suggested by hardware team.
+        */
+       REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7);
+
        REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
 
        REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000);
index 99eb239..9aebc1b 100644 (file)
@@ -98,9 +98,13 @@ static void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigne
        default:
                break;
        }
-       /* Should never be hit, if it is we have an erroneous hw config*/
-       ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
-                       + hubbub2->det3_size + hubbub2->compbuf_size_segments <= hubbub2->crb_size_segs);
+       if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size
+                       + hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) {
+               /* This may happen during seamless transition from ODM 2:1 to ODM4:1 */
+               DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) >  CRB segments (%d)\n",
+                                               hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size,
+                                               hubbub2->compbuf_size_segments, hubbub2->crb_size_segs);
+       }
 }
 
 static void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)
index 6ec1c52..2038cbd 100644 (file)
@@ -103,6 +103,11 @@ void hubp32_cursor_set_attributes(
        enum cursor_lines_per_chunk lpc = hubp2_get_lines_per_chunk(
                        attr->width, attr->color_format);
 
+       //Round cursor width up to next multiple of 64
+       uint32_t cursor_width = ((attr->width + 63) / 64) * 64;
+       uint32_t cursor_height = attr->height;
+       uint32_t cursor_size = cursor_width * cursor_height;
+
        hubp->curs_attr = *attr;
 
        REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
@@ -126,7 +131,24 @@ void hubp32_cursor_set_attributes(
                         /* used to shift the cursor chunk request deadline */
                        CURSOR0_CHUNK_HDL_ADJUST, 3);
 
-       if (attr->width * attr->height * 4 > 16384)
+       switch (attr->color_format) {
+       case CURSOR_MODE_MONO:
+               cursor_size /= 2;
+               break;
+       case CURSOR_MODE_COLOR_1BIT_AND:
+       case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
+       case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
+               cursor_size *= 4;
+               break;
+
+       case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
+       case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
+       default:
+               cursor_size *= 8;
+               break;
+       }
+
+       if (cursor_size > 16384)
                REG_UPDATE(DCHUBP_MALL_CONFIG, USE_MALL_FOR_CURSOR, true);
        else
                REG_UPDATE(DCHUBP_MALL_CONFIG, USE_MALL_FOR_CURSOR, false);
index ebd3945..344fe75 100644 (file)
@@ -295,24 +295,38 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c
                }
 
                // Include cursor size for CAB allocation
-               if (stream->cursor_position.enable && plane->address.grph.cursor_cache_addr.quad_part) {
-                       cursor_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size;
-                       switch (stream->cursor_attributes.color_format) {
-                       case CURSOR_MODE_MONO:
-                               cursor_size /= 2;
-                               break;
-                       case CURSOR_MODE_COLOR_1BIT_AND:
-                       case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
-                       case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
-                               cursor_size *= 4;
-                               break;
+               for (j = 0; j < dc->res_pool->pipe_count; j++) {
+                       struct pipe_ctx *pipe = &ctx->res_ctx.pipe_ctx[j];
+                       struct hubp *hubp = pipe->plane_res.hubp;
 
-                       case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
-                       case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
-                               cursor_size *= 8;
-                               break;
-                       }
-                       cache_lines_used += dcn32_cache_lines_for_surface(dc, surface_size,
+                       if (pipe->stream && pipe->plane_state && hubp)
+                               /* Find the cursor plane and use the exact size instead of
+                                * using the max for calculation
+                                */
+                               if (hubp->curs_attr.width > 0) {
+                                       cursor_size = hubp->curs_attr.width * hubp->curs_attr.height;
+                                       break;
+                               }
+               }
+
+               switch (stream->cursor_attributes.color_format) {
+               case CURSOR_MODE_MONO:
+                       cursor_size /= 2;
+                       break;
+               case CURSOR_MODE_COLOR_1BIT_AND:
+               case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
+               case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
+                       cursor_size *= 4;
+                       break;
+
+               case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
+               case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
+                       cursor_size *= 8;
+                       break;
+               }
+
+               if (stream->cursor_position.enable && plane->address.grph.cursor_cache_addr.quad_part) {
+                       cache_lines_used += dcn32_cache_lines_for_surface(dc, cursor_size,
                                        plane->address.grph.cursor_cache_addr.quad_part);
                }
        }
@@ -325,6 +339,26 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c
        if (cache_lines_used % lines_per_way > 0)
                num_ways++;
 
+       for (i = 0; i < ctx->stream_count; i++) {
+               stream = ctx->streams[i];
+               for (j = 0; j < ctx->stream_status[i].plane_count; j++) {
+                       plane = ctx->stream_status[i].plane_states[j];
+
+                       if (stream->cursor_position.enable && plane &&
+                               !plane->address.grph.cursor_cache_addr.quad_part &&
+                               cursor_size > 16384) {
+                               /* Cursor caching is not supported since it won't be on the same line.
+                                * So we need an extra line to accommodate it. With large cursors and a single 4k monitor
+                                * this case triggers corruption. If we're at the edge, then dont trigger display refresh
+                                * from MALL. We only need to cache cursor if its greater that 64x64 at 4 bpp.
+                                */
+                               num_ways++;
+                               /* We only expect one cursor plane */
+                               break;
+                       }
+               }
+       }
+
        return num_ways;
 }
 
@@ -707,7 +741,29 @@ void dcn32_update_mall_sel(struct dc *dc, struct dc_state *context)
                struct hubp *hubp = pipe->plane_res.hubp;
 
                if (pipe->stream && pipe->plane_state && hubp && hubp->funcs->hubp_update_mall_sel) {
-                       if (hubp->curs_attr.width * hubp->curs_attr.height * 4 > 16384)
+                       //Round cursor width up to next multiple of 64
+                       int cursor_width = ((hubp->curs_attr.width + 63) / 64) * 64;
+                       int cursor_height = hubp->curs_attr.height;
+                       int cursor_size = cursor_width * cursor_height;
+
+                       switch (hubp->curs_attr.color_format) {
+                       case CURSOR_MODE_MONO:
+                               cursor_size /= 2;
+                               break;
+                       case CURSOR_MODE_COLOR_1BIT_AND:
+                       case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
+                       case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
+                               cursor_size *= 4;
+                               break;
+
+                       case CURSOR_MODE_COLOR_64BIT_FP_PRE_MULTIPLIED:
+                       case CURSOR_MODE_COLOR_64BIT_FP_UN_PRE_MULTIPLIED:
+                       default:
+                               cursor_size *= 8;
+                               break;
+                       }
+
+                       if (cursor_size > 16384)
                                cache_cursor = true;
 
                        if (pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
index 8b887b5..c3b783c 100644 (file)
@@ -871,6 +871,7 @@ static const struct dc_debug_options debug_defaults_drv = {
        .exit_idle_opt_for_cursor_updates = true,
        .enable_single_display_2to1_odm_policy = true,
        .enable_dp_dig_pixel_rate_div_policy = 1,
+       .allow_sw_cursor_fallback = false,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
@@ -2039,7 +2040,8 @@ static bool dcn32_resource_construct(
        dc->caps.max_downscale_ratio = 600;
        dc->caps.i2c_speed_in_khz = 100;
        dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/
-       dc->caps.max_cursor_size = 256;
+       /* TODO: Bring max_cursor_size back to 256 after subvp cursor corruption is fixed*/
+       dc->caps.max_cursor_size = 64;
        dc->caps.min_horizontal_blanking_period = 80;
        dc->caps.dmdata_alloc_size = 2048;
        dc->caps.mall_size_per_mem_channel = 0;
index 1e7e620..cf15d0e 100644 (file)
@@ -30,6 +30,9 @@
 
 #define DCN3_2_DET_SEG_SIZE 64
 #define DCN3_2_MALL_MBLK_SIZE_BYTES 65536 // 64 * 1024
+#define DCN3_2_MBLK_WIDTH 128
+#define DCN3_2_MBLK_HEIGHT_4BPE 128
+#define DCN3_2_MBLK_HEIGHT_8BPE 64
 
 #define TO_DCN32_RES_POOL(pool)\
        container_of(pool, struct dcn32_resource_pool, base)
index 955f52e..1f195c5 100644 (file)
@@ -46,7 +46,6 @@
 uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_state *context)
 {
        uint32_t num_ways = 0;
-       uint32_t mall_region_pixels = 0;
        uint32_t bytes_per_pixel = 0;
        uint32_t cache_lines_used = 0;
        uint32_t lines_per_way = 0;
@@ -54,20 +53,64 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat
        uint32_t bytes_in_mall = 0;
        uint32_t num_mblks = 0;
        uint32_t cache_lines_per_plane = 0;
-       uint32_t i = 0;
+       uint32_t i = 0, j = 0;
+       uint32_t mblk_width = 0;
+       uint32_t mblk_height = 0;
+       uint32_t full_vp_width_blk_aligned = 0;
+       uint32_t full_vp_height_blk_aligned = 0;
+       uint32_t mall_alloc_width_blk_aligned = 0;
+       uint32_t mall_alloc_height_blk_aligned = 0;
+       uint32_t full_vp_height = 0;
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
 
                // Find the phantom pipes
-               if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
+               if (pipe->stream && pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe &&
                                pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
-                       bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4;
-                       mall_region_pixels = pipe->plane_state->plane_size.surface_pitch * pipe->stream->timing.v_addressable;
+                       struct pipe_ctx *main_pipe = NULL;
 
-                       // For bytes required in MALL, calculate based on number of MBlks required
-                       num_mblks = (mall_region_pixels * bytes_per_pixel +
-                                       DCN3_2_MALL_MBLK_SIZE_BYTES - 1) / DCN3_2_MALL_MBLK_SIZE_BYTES;
+                       /* Get full viewport height from main pipe (required for MBLK calculation) */
+                       for (j = 0; j < dc->res_pool->pipe_count; j++) {
+                               main_pipe = &context->res_ctx.pipe_ctx[j];
+                               if (main_pipe->stream == pipe->stream->mall_stream_config.paired_stream) {
+                                       full_vp_height = main_pipe->plane_res.scl_data.viewport.height;
+                                       break;
+                               }
+                       }
+
+                       bytes_per_pixel = pipe->plane_state->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4;
+                       mblk_width = DCN3_2_MBLK_WIDTH;
+                       mblk_height = bytes_per_pixel == 4 ? DCN3_2_MBLK_HEIGHT_4BPE : DCN3_2_MBLK_HEIGHT_8BPE;
+
+                       /* full_vp_width_blk_aligned = FLOOR(vp_x_start + full_vp_width + blk_width - 1, blk_width) -
+                        * FLOOR(vp_x_start, blk_width)
+                        */
+                       full_vp_width_blk_aligned = ((pipe->plane_res.scl_data.viewport.x +
+                                       pipe->plane_res.scl_data.viewport.width + mblk_width - 1) / mblk_width * mblk_width) +
+                                       (pipe->plane_res.scl_data.viewport.x / mblk_width * mblk_width);
+
+                       /* full_vp_height_blk_aligned = FLOOR(vp_y_start + full_vp_height + blk_height - 1, blk_height) -
+                        * FLOOR(vp_y_start, blk_height)
+                        */
+                       full_vp_height_blk_aligned = ((pipe->plane_res.scl_data.viewport.y +
+                                       full_vp_height + mblk_height - 1) / mblk_height * mblk_height) +
+                                       (pipe->plane_res.scl_data.viewport.y / mblk_height * mblk_height);
+
+                       /* mall_alloc_width_blk_aligned_l/c = full_vp_width_blk_aligned_l/c */
+                       mall_alloc_width_blk_aligned = full_vp_width_blk_aligned;
+
+                       /* mall_alloc_height_blk_aligned_l/c = CEILING(sub_vp_height_l/c - 1, blk_height_l/c) + blk_height_l/c */
+                       mall_alloc_height_blk_aligned = (pipe->stream->timing.v_addressable - 1 + mblk_height - 1) /
+                                       mblk_height * mblk_height + mblk_height;
+
+                       /* full_mblk_width_ub_l/c = mall_alloc_width_blk_aligned_l/c;
+                        * full_mblk_height_ub_l/c = mall_alloc_height_blk_aligned_l/c;
+                        * num_mblk_l/c = (full_mblk_width_ub_l/c / mblk_width_l/c) * (full_mblk_height_ub_l/c / mblk_height_l/c);
+                        * (Should be divisible, but round up if not)
+                        */
+                       num_mblks = ((mall_alloc_width_blk_aligned + mblk_width - 1) / mblk_width) *
+                                       ((mall_alloc_height_blk_aligned + mblk_height - 1) / mblk_height);
                        bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES;
                        // cache lines used is total bytes / cache_line size. Add +2 for worst case alignment
                        // (MALL is 64-byte aligned)
@@ -144,7 +187,7 @@ bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc,
                struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
 
                if (!pipe->stream)
-                       continue;
+                       return false;
 
                if (!pipe->plane_state)
                        return false;
index c8b7d6f..7309eed 100644 (file)
@@ -872,6 +872,7 @@ static const struct dc_debug_options debug_defaults_drv = {
        .exit_idle_opt_for_cursor_updates = true,
        .enable_single_display_2to1_odm_policy = true,
        .enable_dp_dig_pixel_rate_div_policy = 1,
+       .allow_sw_cursor_fallback = false,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
@@ -1651,7 +1652,8 @@ static bool dcn321_resource_construct(
        dc->caps.max_downscale_ratio = 600;
        dc->caps.i2c_speed_in_khz = 100;
        dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/
-       dc->caps.max_cursor_size = 256;
+       /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/
+       dc->caps.max_cursor_size = 64;
        dc->caps.min_horizontal_blanking_period = 80;
        dc->caps.dmdata_alloc_size = 2048;
        dc->caps.mall_size_per_mem_channel = 0;
index 86a3b5b..cb81ed2 100644 (file)
@@ -70,6 +70,8 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn314/display_mode_vba_314.o := $(dml_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml/dcn314/display_rq_dlg_calc_314.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn314/dcn314_fpu.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/dcn30_fpu.o := $(dml_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/dml/dcn32/dcn32_fpu.o := $(dml_ccflags)
@@ -123,6 +125,7 @@ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
 DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
 DML += dcn30/dcn30_fpu.o dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
 DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o
+DML += dcn314/display_mode_vba_314.o dcn314/display_rq_dlg_calc_314.o
 DML += dcn32/display_mode_vba_32.o dcn32/display_rq_dlg_calc_32.o dcn32/display_mode_vba_util_32.o
 DML += dcn31/dcn31_fpu.o
 DML += dcn32/dcn32_fpu.o
index 876b321..1cb858d 100644 (file)
@@ -6610,8 +6610,7 @@ static double CalculateUrgentLatency(
        return ret;
 }
 
-
-static void UseMinimumDCFCLK(
+static noinline_for_stack void UseMinimumDCFCLK(
                struct display_mode_lib *mode_lib,
                int MaxInterDCNTileRepeaters,
                int MaxPrefetchMode,
index 149a1b1..fa7b029 100644 (file)
@@ -291,6 +291,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
        .do_urgent_latency_adjustment = false,
        .urgent_latency_adjustment_fabric_clock_component_us = 0,
        .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+       .num_chans = 4,
 };
 
 struct _vcs_dpi_ip_params_st dcn3_16_ip = {
@@ -680,7 +681,11 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
 
        dcn3_15_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
        dcn3_15_ip.max_num_dpp = dc->res_pool->pipe_count;
-       dcn3_15_soc.num_chans = bw_params->num_channels;
+
+       if (bw_params->num_channels > 0)
+               dcn3_15_soc.num_chans = bw_params->num_channels;
+       if (bw_params->dram_channel_width_bytes > 0)
+               dcn3_15_soc.dram_channel_width_bytes = bw_params->dram_channel_width_bytes;
 
        ASSERT(clk_table->num_entries);
 
index d63b420..8ca66f1 100644 (file)
@@ -251,33 +251,13 @@ static void CalculateRowBandwidth(
 
 static void CalculateFlipSchedule(
                struct display_mode_lib *mode_lib,
+               unsigned int k,
                double HostVMInefficiencyFactor,
                double UrgentExtraLatency,
                double UrgentLatency,
-               unsigned int GPUVMMaxPageTableLevels,
-               bool HostVMEnable,
-               unsigned int HostVMMaxNonCachedPageTableLevels,
-               bool GPUVMEnable,
-               double HostVMMinPageSize,
                double PDEAndMetaPTEBytesPerFrame,
                double MetaRowBytes,
-               double DPTEBytesPerRow,
-               double BandwidthAvailableForImmediateFlip,
-               unsigned int TotImmediateFlipBytes,
-               enum source_format_class SourcePixelFormat,
-               double LineTime,
-               double VRatio,
-               double VRatioChroma,
-               double Tno_bw,
-               bool DCCEnable,
-               unsigned int dpte_row_height,
-               unsigned int meta_row_height,
-               unsigned int dpte_row_height_chroma,
-               unsigned int meta_row_height_chroma,
-               double *DestinationLinesToRequestVMInImmediateFlip,
-               double *DestinationLinesToRequestRowInImmediateFlip,
-               double *final_flip_bw,
-               bool *ImmediateFlipSupportedForPipe);
+               double DPTEBytesPerRow);
 static double CalculateWriteBackDelay(
                enum source_format_class WritebackPixelFormat,
                double WritebackHRatio,
@@ -311,64 +291,28 @@ static void CalculateVupdateAndDynamicMetadataParameters(
 static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                struct display_mode_lib *mode_lib,
                unsigned int PrefetchMode,
-               unsigned int NumberOfActivePlanes,
-               unsigned int MaxLineBufferLines,
-               unsigned int LineBufferSize,
-               unsigned int WritebackInterfaceBufferSize,
                double DCFCLK,
                double ReturnBW,
-               bool SynchronizedVBlank,
-               unsigned int dpte_group_bytes[],
-               unsigned int MetaChunkSize,
                double UrgentLatency,
                double ExtraLatency,
-               double WritebackLatency,
-               double WritebackChunkSize,
                double SOCCLK,
-               double DRAMClockChangeLatency,
-               double SRExitTime,
-               double SREnterPlusExitTime,
-               double SRExitZ8Time,
-               double SREnterPlusExitZ8Time,
                double DCFCLKDeepSleep,
                unsigned int DETBufferSizeY[],
                unsigned int DETBufferSizeC[],
                unsigned int SwathHeightY[],
                unsigned int SwathHeightC[],
-               unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double SwathWidthC[],
-               double HRatio[],
-               double HRatioChroma[],
-               unsigned int vtaps[],
-               unsigned int VTAPsChroma[],
-               double VRatio[],
-               double VRatioChroma[],
-               unsigned int HTotal[],
-               double PixelClock[],
-               unsigned int BlendingAndTiming[],
                unsigned int DPPPerPlane[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
-               double DSTXAfterScaler[],
-               double DSTYAfterScaler[],
-               bool WritebackEnable[],
-               enum source_format_class WritebackPixelFormat[],
-               double WritebackDestinationWidth[],
-               double WritebackDestinationHeight[],
-               double WritebackSourceHeight[],
                bool UnboundedRequestEnabled,
                int unsigned CompressedBufferSizeInkByte,
                enum clock_change_support *DRAMClockChangeSupport,
-               double *UrgentWatermark,
-               double *WritebackUrgentWatermark,
-               double *DRAMClockChangeWatermark,
-               double *WritebackDRAMClockChangeWatermark,
                double *StutterExitWatermark,
                double *StutterEnterPlusExitWatermark,
                double *Z8StutterExitWatermark,
-               double *Z8StutterEnterPlusExitWatermark,
-               double *MinActiveDRAMClockChangeLatencySupported);
+               double *Z8StutterEnterPlusExitWatermark);
 
 static void CalculateDCFCLKDeepSleep(
                struct display_mode_lib *mode_lib,
@@ -2904,33 +2848,13 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                        for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                                CalculateFlipSchedule(
                                                mode_lib,
+                                               k,
                                                HostVMInefficiencyFactor,
                                                v->UrgentExtraLatency,
                                                v->UrgentLatency,
-                                               v->GPUVMMaxPageTableLevels,
-                                               v->HostVMEnable,
-                                               v->HostVMMaxNonCachedPageTableLevels,
-                                               v->GPUVMEnable,
-                                               v->HostVMMinPageSize,
                                                v->PDEAndMetaPTEBytesFrame[k],
                                                v->MetaRowByte[k],
-                                               v->PixelPTEBytesPerRow[k],
-                                               v->BandwidthAvailableForImmediateFlip,
-                                               v->TotImmediateFlipBytes,
-                                               v->SourcePixelFormat[k],
-                                               v->HTotal[k] / v->PixelClock[k],
-                                               v->VRatio[k],
-                                               v->VRatioChroma[k],
-                                               v->Tno_bw[k],
-                                               v->DCCEnable[k],
-                                               v->dpte_row_height[k],
-                                               v->meta_row_height[k],
-                                               v->dpte_row_height_chroma[k],
-                                               v->meta_row_height_chroma[k],
-                                               &v->DestinationLinesToRequestVMInImmediateFlip[k],
-                                               &v->DestinationLinesToRequestRowInImmediateFlip[k],
-                                               &v->final_flip_bw[k],
-                                               &v->ImmediateFlipSupportedForPipe[k]);
+                                               v->PixelPTEBytesPerRow[k]);
                        }
 
                        v->total_dcn_read_bw_with_flip = 0.0;
@@ -3017,64 +2941,28 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                CalculateWatermarksAndDRAMSpeedChangeSupport(
                                mode_lib,
                                PrefetchMode,
-                               v->NumberOfActivePlanes,
-                               v->MaxLineBufferLines,
-                               v->LineBufferSize,
-                               v->WritebackInterfaceBufferSize,
                                v->DCFCLK,
                                v->ReturnBW,
-                               v->SynchronizedVBlank,
-                               v->dpte_group_bytes,
-                               v->MetaChunkSize,
                                v->UrgentLatency,
                                v->UrgentExtraLatency,
-                               v->WritebackLatency,
-                               v->WritebackChunkSize,
                                v->SOCCLK,
-                               v->DRAMClockChangeLatency,
-                               v->SRExitTime,
-                               v->SREnterPlusExitTime,
-                               v->SRExitZ8Time,
-                               v->SREnterPlusExitZ8Time,
                                v->DCFCLKDeepSleep,
                                v->DETBufferSizeY,
                                v->DETBufferSizeC,
                                v->SwathHeightY,
                                v->SwathHeightC,
-                               v->LBBitPerPixel,
                                v->SwathWidthY,
                                v->SwathWidthC,
-                               v->HRatio,
-                               v->HRatioChroma,
-                               v->vtaps,
-                               v->VTAPsChroma,
-                               v->VRatio,
-                               v->VRatioChroma,
-                               v->HTotal,
-                               v->PixelClock,
-                               v->BlendingAndTiming,
                                v->DPPPerPlane,
                                v->BytePerPixelDETY,
                                v->BytePerPixelDETC,
-                               v->DSTXAfterScaler,
-                               v->DSTYAfterScaler,
-                               v->WritebackEnable,
-                               v->WritebackPixelFormat,
-                               v->WritebackDestinationWidth,
-                               v->WritebackDestinationHeight,
-                               v->WritebackSourceHeight,
                                v->UnboundedRequestEnabled,
                                v->CompressedBufferSizeInkByte,
                                &DRAMClockChangeSupport,
-                               &v->UrgentWatermark,
-                               &v->WritebackUrgentWatermark,
-                               &v->DRAMClockChangeWatermark,
-                               &v->WritebackDRAMClockChangeWatermark,
                                &v->StutterExitWatermark,
                                &v->StutterEnterPlusExitWatermark,
                                &v->Z8StutterExitWatermark,
-                               &v->Z8StutterEnterPlusExitWatermark,
-                               &v->MinActiveDRAMClockChangeLatencySupported);
+                               &v->Z8StutterEnterPlusExitWatermark);
 
                for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                        if (v->WritebackEnable[k] == true) {
@@ -3598,61 +3486,43 @@ static void CalculateRowBandwidth(
 
 static void CalculateFlipSchedule(
                struct display_mode_lib *mode_lib,
+               unsigned int k,
                double HostVMInefficiencyFactor,
                double UrgentExtraLatency,
                double UrgentLatency,
-               unsigned int GPUVMMaxPageTableLevels,
-               bool HostVMEnable,
-               unsigned int HostVMMaxNonCachedPageTableLevels,
-               bool GPUVMEnable,
-               double HostVMMinPageSize,
                double PDEAndMetaPTEBytesPerFrame,
                double MetaRowBytes,
-               double DPTEBytesPerRow,
-               double BandwidthAvailableForImmediateFlip,
-               unsigned int TotImmediateFlipBytes,
-               enum source_format_class SourcePixelFormat,
-               double LineTime,
-               double VRatio,
-               double VRatioChroma,
-               double Tno_bw,
-               bool DCCEnable,
-               unsigned int dpte_row_height,
-               unsigned int meta_row_height,
-               unsigned int dpte_row_height_chroma,
-               unsigned int meta_row_height_chroma,
-               double *DestinationLinesToRequestVMInImmediateFlip,
-               double *DestinationLinesToRequestRowInImmediateFlip,
-               double *final_flip_bw,
-               bool *ImmediateFlipSupportedForPipe)
+               double DPTEBytesPerRow)
 {
+       struct vba_vars_st *v = &mode_lib->vba;
        double min_row_time = 0.0;
        unsigned int HostVMDynamicLevelsTrips;
        double TimeForFetchingMetaPTEImmediateFlip;
        double TimeForFetchingRowInVBlankImmediateFlip;
        double ImmediateFlipBW;
+       double LineTime = v->HTotal[k] / v->PixelClock[k];
 
-       if (GPUVMEnable == true && HostVMEnable == true) {
-               HostVMDynamicLevelsTrips = HostVMMaxNonCachedPageTableLevels;
+       if (v->GPUVMEnable == true && v->HostVMEnable == true) {
+               HostVMDynamicLevelsTrips = v->HostVMMaxNonCachedPageTableLevels;
        } else {
                HostVMDynamicLevelsTrips = 0;
        }
 
-       if (GPUVMEnable == true || DCCEnable == true) {
-               ImmediateFlipBW = (PDEAndMetaPTEBytesPerFrame + MetaRowBytes + DPTEBytesPerRow) * BandwidthAvailableForImmediateFlip / TotImmediateFlipBytes;
+       if (v->GPUVMEnable == true || v->DCCEnable[k] == true) {
+               ImmediateFlipBW = (PDEAndMetaPTEBytesPerFrame + MetaRowBytes + DPTEBytesPerRow) * v->BandwidthAvailableForImmediateFlip / v->TotImmediateFlipBytes;
        }
 
-       if (GPUVMEnable == true) {
+       if (v->GPUVMEnable == true) {
                TimeForFetchingMetaPTEImmediateFlip = dml_max3(
-                               Tno_bw + PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / ImmediateFlipBW,
-                               UrgentExtraLatency + UrgentLatency * (GPUVMMaxPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1),
+                               v->Tno_bw[k] + PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / ImmediateFlipBW,
+                               UrgentExtraLatency + UrgentLatency * (v->GPUVMMaxPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1),
                                LineTime / 4.0);
        } else {
                TimeForFetchingMetaPTEImmediateFlip = 0;
        }
 
-       *DestinationLinesToRequestVMInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime), 1) / 4.0;
-       if ((GPUVMEnable == true || DCCEnable == true)) {
+       v->DestinationLinesToRequestVMInImmediateFlip[k] = dml_ceil(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime), 1) / 4.0;
+       if ((v->GPUVMEnable == true || v->DCCEnable[k] == true)) {
                TimeForFetchingRowInVBlankImmediateFlip = dml_max3(
                                (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / ImmediateFlipBW,
                                UrgentLatency * (HostVMDynamicLevelsTrips + 1),
@@ -3661,54 +3531,54 @@ static void CalculateFlipSchedule(
                TimeForFetchingRowInVBlankImmediateFlip = 0;
        }
 
-       *DestinationLinesToRequestRowInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime), 1) / 4.0;
+       v->DestinationLinesToRequestRowInImmediateFlip[k] = dml_ceil(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime), 1) / 4.0;
 
-       if (GPUVMEnable == true) {
-               *final_flip_bw = dml_max(
-                               PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / (*DestinationLinesToRequestVMInImmediateFlip * LineTime),
-                               (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (*DestinationLinesToRequestRowInImmediateFlip * LineTime));
-       } else if ((GPUVMEnable == true || DCCEnable == true)) {
-               *final_flip_bw = (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (*DestinationLinesToRequestRowInImmediateFlip * LineTime);
+       if (v->GPUVMEnable == true) {
+               v->final_flip_bw[k] = dml_max(
+                               PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / (v->DestinationLinesToRequestVMInImmediateFlip[k] * LineTime),
+                               (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (v->DestinationLinesToRequestRowInImmediateFlip[k] * LineTime));
+       } else if ((v->GPUVMEnable == true || v->DCCEnable[k] == true)) {
+               v->final_flip_bw[k] = (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (v->DestinationLinesToRequestRowInImmediateFlip[k] * LineTime);
        } else {
-               *final_flip_bw = 0;
+               v->final_flip_bw[k] = 0;
        }
 
-       if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10 || SourcePixelFormat == dm_rgbe_alpha) {
-               if (GPUVMEnable == true && DCCEnable != true) {
-                       min_row_time = dml_min(dpte_row_height * LineTime / VRatio, dpte_row_height_chroma * LineTime / VRatioChroma);
-               } else if (GPUVMEnable != true && DCCEnable == true) {
-                       min_row_time = dml_min(meta_row_height * LineTime / VRatio, meta_row_height_chroma * LineTime / VRatioChroma);
+       if (v->SourcePixelFormat[k] == dm_420_8 || v->SourcePixelFormat[k] == dm_420_10 || v->SourcePixelFormat[k] == dm_rgbe_alpha) {
+               if (v->GPUVMEnable == true && v->DCCEnable[k] != true) {
+                       min_row_time = dml_min(v->dpte_row_height[k] * LineTime / v->VRatio[k], v->dpte_row_height_chroma[k] * LineTime / v->VRatioChroma[k]);
+               } else if (v->GPUVMEnable != true && v->DCCEnable[k] == true) {
+                       min_row_time = dml_min(v->meta_row_height[k] * LineTime / v->VRatio[k], v->meta_row_height_chroma[k] * LineTime / v->VRatioChroma[k]);
                } else {
                        min_row_time = dml_min4(
-                                       dpte_row_height * LineTime / VRatio,
-                                       meta_row_height * LineTime / VRatio,
-                                       dpte_row_height_chroma * LineTime / VRatioChroma,
-                                       meta_row_height_chroma * LineTime / VRatioChroma);
+                                       v->dpte_row_height[k] * LineTime / v->VRatio[k],
+                                       v->meta_row_height[k] * LineTime / v->VRatio[k],
+                                       v->dpte_row_height_chroma[k] * LineTime / v->VRatioChroma[k],
+                                       v->meta_row_height_chroma[k] * LineTime / v->VRatioChroma[k]);
                }
        } else {
-               if (GPUVMEnable == true && DCCEnable != true) {
-                       min_row_time = dpte_row_height * LineTime / VRatio;
-               } else if (GPUVMEnable != true && DCCEnable == true) {
-                       min_row_time = meta_row_height * LineTime / VRatio;
+               if (v->GPUVMEnable == true && v->DCCEnable[k] != true) {
+                       min_row_time = v->dpte_row_height[k] * LineTime / v->VRatio[k];
+               } else if (v->GPUVMEnable != true && v->DCCEnable[k] == true) {
+                       min_row_time = v->meta_row_height[k] * LineTime / v->VRatio[k];
                } else {
-                       min_row_time = dml_min(dpte_row_height * LineTime / VRatio, meta_row_height * LineTime / VRatio);
+                       min_row_time = dml_min(v->dpte_row_height[k] * LineTime / v->VRatio[k], v->meta_row_height[k] * LineTime / v->VRatio[k]);
                }
        }
 
-       if (*DestinationLinesToRequestVMInImmediateFlip >= 32 || *DestinationLinesToRequestRowInImmediateFlip >= 16
+       if (v->DestinationLinesToRequestVMInImmediateFlip[k] >= 32 || v->DestinationLinesToRequestRowInImmediateFlip[k] >= 16
                        || TimeForFetchingMetaPTEImmediateFlip + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) {
-               *ImmediateFlipSupportedForPipe = false;
+               v->ImmediateFlipSupportedForPipe[k] = false;
        } else {
-               *ImmediateFlipSupportedForPipe = true;
+               v->ImmediateFlipSupportedForPipe[k] = true;
        }
 
 #ifdef __DML_VBA_DEBUG__
-       dml_print("DML::%s: DestinationLinesToRequestVMInImmediateFlip = %f\n", __func__, *DestinationLinesToRequestVMInImmediateFlip);
-       dml_print("DML::%s: DestinationLinesToRequestRowInImmediateFlip = %f\n", __func__, *DestinationLinesToRequestRowInImmediateFlip);
+       dml_print("DML::%s: DestinationLinesToRequestVMInImmediateFlip = %f\n", __func__, v->DestinationLinesToRequestVMInImmediateFlip[k]);
+       dml_print("DML::%s: DestinationLinesToRequestRowInImmediateFlip = %f\n", __func__, v->DestinationLinesToRequestRowInImmediateFlip[k]);
        dml_print("DML::%s: TimeForFetchingMetaPTEImmediateFlip = %f\n", __func__, TimeForFetchingMetaPTEImmediateFlip);
        dml_print("DML::%s: TimeForFetchingRowInVBlankImmediateFlip = %f\n", __func__, TimeForFetchingRowInVBlankImmediateFlip);
        dml_print("DML::%s: min_row_time = %f\n", __func__, min_row_time);
-       dml_print("DML::%s: ImmediateFlipSupportedForPipe = %d\n", __func__, *ImmediateFlipSupportedForPipe);
+       dml_print("DML::%s: ImmediateFlipSupportedForPipe = %d\n", __func__, v->ImmediateFlipSupportedForPipe[k]);
 #endif
 
 }
@@ -5300,33 +5170,13 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                        for (k = 0; k < v->NumberOfActivePlanes; k++) {
                                                CalculateFlipSchedule(
                                                                mode_lib,
+                                                               k,
                                                                HostVMInefficiencyFactor,
                                                                v->ExtraLatency,
                                                                v->UrgLatency[i],
-                                                               v->GPUVMMaxPageTableLevels,
-                                                               v->HostVMEnable,
-                                                               v->HostVMMaxNonCachedPageTableLevels,
-                                                               v->GPUVMEnable,
-                                                               v->HostVMMinPageSize,
                                                                v->PDEAndMetaPTEBytesPerFrame[i][j][k],
                                                                v->MetaRowBytes[i][j][k],
-                                                               v->DPTEBytesPerRow[i][j][k],
-                                                               v->BandwidthAvailableForImmediateFlip,
-                                                               v->TotImmediateFlipBytes,
-                                                               v->SourcePixelFormat[k],
-                                                               v->HTotal[k] / v->PixelClock[k],
-                                                               v->VRatio[k],
-                                                               v->VRatioChroma[k],
-                                                               v->Tno_bw[k],
-                                                               v->DCCEnable[k],
-                                                               v->dpte_row_height[k],
-                                                               v->meta_row_height[k],
-                                                               v->dpte_row_height_chroma[k],
-                                                               v->meta_row_height_chroma[k],
-                                                               &v->DestinationLinesToRequestVMInImmediateFlip[k],
-                                                               &v->DestinationLinesToRequestRowInImmediateFlip[k],
-                                                               &v->final_flip_bw[k],
-                                                               &v->ImmediateFlipSupportedForPipe[k]);
+                                                               v->DPTEBytesPerRow[i][j][k]);
                                        }
                                        v->total_dcn_read_bw_with_flip = 0.0;
                                        for (k = 0; k < v->NumberOfActivePlanes; k++) {
@@ -5384,64 +5234,28 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                        CalculateWatermarksAndDRAMSpeedChangeSupport(
                                        mode_lib,
                                        v->PrefetchModePerState[i][j],
-                                       v->NumberOfActivePlanes,
-                                       v->MaxLineBufferLines,
-                                       v->LineBufferSize,
-                                       v->WritebackInterfaceBufferSize,
                                        v->DCFCLKState[i][j],
                                        v->ReturnBWPerState[i][j],
-                                       v->SynchronizedVBlank,
-                                       v->dpte_group_bytes,
-                                       v->MetaChunkSize,
                                        v->UrgLatency[i],
                                        v->ExtraLatency,
-                                       v->WritebackLatency,
-                                       v->WritebackChunkSize,
                                        v->SOCCLKPerState[i],
-                                       v->DRAMClockChangeLatency,
-                                       v->SRExitTime,
-                                       v->SREnterPlusExitTime,
-                                       v->SRExitZ8Time,
-                                       v->SREnterPlusExitZ8Time,
                                        v->ProjectedDCFCLKDeepSleep[i][j],
                                        v->DETBufferSizeYThisState,
                                        v->DETBufferSizeCThisState,
                                        v->SwathHeightYThisState,
                                        v->SwathHeightCThisState,
-                                       v->LBBitPerPixel,
                                        v->SwathWidthYThisState,
                                        v->SwathWidthCThisState,
-                                       v->HRatio,
-                                       v->HRatioChroma,
-                                       v->vtaps,
-                                       v->VTAPsChroma,
-                                       v->VRatio,
-                                       v->VRatioChroma,
-                                       v->HTotal,
-                                       v->PixelClock,
-                                       v->BlendingAndTiming,
                                        v->NoOfDPPThisState,
                                        v->BytePerPixelInDETY,
                                        v->BytePerPixelInDETC,
-                                       v->DSTXAfterScaler,
-                                       v->DSTYAfterScaler,
-                                       v->WritebackEnable,
-                                       v->WritebackPixelFormat,
-                                       v->WritebackDestinationWidth,
-                                       v->WritebackDestinationHeight,
-                                       v->WritebackSourceHeight,
                                        UnboundedRequestEnabledThisState,
                                        CompressedBufferSizeInkByteThisState,
                                        &v->DRAMClockChangeSupport[i][j],
-                                       &v->UrgentWatermark,
-                                       &v->WritebackUrgentWatermark,
-                                       &v->DRAMClockChangeWatermark,
-                                       &v->WritebackDRAMClockChangeWatermark,
-                                       &dummy,
                                        &dummy,
                                        &dummy,
                                        &dummy,
-                                       &v->MinActiveDRAMClockChangeLatencySupported);
+                                       &dummy);
                }
        }
 
@@ -5566,64 +5380,28 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                struct display_mode_lib *mode_lib,
                unsigned int PrefetchMode,
-               unsigned int NumberOfActivePlanes,
-               unsigned int MaxLineBufferLines,
-               unsigned int LineBufferSize,
-               unsigned int WritebackInterfaceBufferSize,
                double DCFCLK,
                double ReturnBW,
-               bool SynchronizedVBlank,
-               unsigned int dpte_group_bytes[],
-               unsigned int MetaChunkSize,
                double UrgentLatency,
                double ExtraLatency,
-               double WritebackLatency,
-               double WritebackChunkSize,
                double SOCCLK,
-               double DRAMClockChangeLatency,
-               double SRExitTime,
-               double SREnterPlusExitTime,
-               double SRExitZ8Time,
-               double SREnterPlusExitZ8Time,
                double DCFCLKDeepSleep,
                unsigned int DETBufferSizeY[],
                unsigned int DETBufferSizeC[],
                unsigned int SwathHeightY[],
                unsigned int SwathHeightC[],
-               unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double SwathWidthC[],
-               double HRatio[],
-               double HRatioChroma[],
-               unsigned int vtaps[],
-               unsigned int VTAPsChroma[],
-               double VRatio[],
-               double VRatioChroma[],
-               unsigned int HTotal[],
-               double PixelClock[],
-               unsigned int BlendingAndTiming[],
                unsigned int DPPPerPlane[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
-               double DSTXAfterScaler[],
-               double DSTYAfterScaler[],
-               bool WritebackEnable[],
-               enum source_format_class WritebackPixelFormat[],
-               double WritebackDestinationWidth[],
-               double WritebackDestinationHeight[],
-               double WritebackSourceHeight[],
                bool UnboundedRequestEnabled,
                int unsigned CompressedBufferSizeInkByte,
                enum clock_change_support *DRAMClockChangeSupport,
-               double *UrgentWatermark,
-               double *WritebackUrgentWatermark,
-               double *DRAMClockChangeWatermark,
-               double *WritebackDRAMClockChangeWatermark,
                double *StutterExitWatermark,
                double *StutterEnterPlusExitWatermark,
                double *Z8StutterExitWatermark,
-               double *Z8StutterEnterPlusExitWatermark,
-               double *MinActiveDRAMClockChangeLatencySupported)
+               double *Z8StutterEnterPlusExitWatermark)
 {
        struct vba_vars_st *v = &mode_lib->vba;
        double EffectiveLBLatencyHidingY;
@@ -5643,103 +5421,103 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
        double TotalPixelBW = 0.0;
        int k, j;
 
-       *UrgentWatermark = UrgentLatency + ExtraLatency;
+       v->UrgentWatermark = UrgentLatency + ExtraLatency;
 
 #ifdef __DML_VBA_DEBUG__
        dml_print("DML::%s: UrgentLatency = %f\n", __func__, UrgentLatency);
        dml_print("DML::%s: ExtraLatency = %f\n", __func__, ExtraLatency);
-       dml_print("DML::%s: UrgentWatermark = %f\n", __func__, *UrgentWatermark);
+       dml_print("DML::%s: UrgentWatermark = %f\n", __func__, v->UrgentWatermark);
 #endif
 
-       *DRAMClockChangeWatermark = DRAMClockChangeLatency + *UrgentWatermark;
+       v->DRAMClockChangeWatermark = v->DRAMClockChangeLatency + v->UrgentWatermark;
 
 #ifdef __DML_VBA_DEBUG__
-       dml_print("DML::%s: DRAMClockChangeLatency = %f\n", __func__, DRAMClockChangeLatency);
-       dml_print("DML::%s: DRAMClockChangeWatermark = %f\n", __func__, *DRAMClockChangeWatermark);
+       dml_print("DML::%s: v->DRAMClockChangeLatency = %f\n", __func__, v->DRAMClockChangeLatency);
+       dml_print("DML::%s: DRAMClockChangeWatermark = %f\n", __func__, v->DRAMClockChangeWatermark);
 #endif
 
        v->TotalActiveWriteback = 0;
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
-               if (WritebackEnable[k] == true) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
+               if (v->WritebackEnable[k] == true) {
                        v->TotalActiveWriteback = v->TotalActiveWriteback + 1;
                }
        }
 
        if (v->TotalActiveWriteback <= 1) {
-               *WritebackUrgentWatermark = WritebackLatency;
+               v->WritebackUrgentWatermark = v->WritebackLatency;
        } else {
-               *WritebackUrgentWatermark = WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
+               v->WritebackUrgentWatermark = v->WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
        }
 
        if (v->TotalActiveWriteback <= 1) {
-               *WritebackDRAMClockChangeWatermark = DRAMClockChangeLatency + WritebackLatency;
+               v->WritebackDRAMClockChangeWatermark = v->DRAMClockChangeLatency + v->WritebackLatency;
        } else {
-               *WritebackDRAMClockChangeWatermark = DRAMClockChangeLatency + WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
+               v->WritebackDRAMClockChangeWatermark = v->DRAMClockChangeLatency + v->WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
        }
 
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                TotalPixelBW = TotalPixelBW
-                               + DPPPerPlane[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] + SwathWidthC[k] * BytePerPixelDETC[k] * VRatioChroma[k])
-                                               / (HTotal[k] / PixelClock[k]);
+                               + DPPPerPlane[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * v->VRatio[k] + SwathWidthC[k] * BytePerPixelDETC[k] * v->VRatioChroma[k])
+                                               / (v->HTotal[k] / v->PixelClock[k]);
        }
 
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                double EffectiveDETBufferSizeY = DETBufferSizeY[k];
 
                v->LBLatencyHidingSourceLinesY = dml_min(
-                               (double) MaxLineBufferLines,
-                               dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(HRatio[k], 1.0)), 1)) - (vtaps[k] - 1);
+                               (double) v->MaxLineBufferLines,
+                               dml_floor(v->LineBufferSize / v->LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(v->HRatio[k], 1.0)), 1)) - (v->vtaps[k] - 1);
 
                v->LBLatencyHidingSourceLinesC = dml_min(
-                               (double) MaxLineBufferLines,
-                               dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(HRatioChroma[k], 1.0)), 1)) - (VTAPsChroma[k] - 1);
+                               (double) v->MaxLineBufferLines,
+                               dml_floor(v->LineBufferSize / v->LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(v->HRatioChroma[k], 1.0)), 1)) - (v->VTAPsChroma[k] - 1);
 
-               EffectiveLBLatencyHidingY = v->LBLatencyHidingSourceLinesY / VRatio[k] * (HTotal[k] / PixelClock[k]);
+               EffectiveLBLatencyHidingY = v->LBLatencyHidingSourceLinesY / v->VRatio[k] * (v->HTotal[k] / v->PixelClock[k]);
 
-               EffectiveLBLatencyHidingC = v->LBLatencyHidingSourceLinesC / VRatioChroma[k] * (HTotal[k] / PixelClock[k]);
+               EffectiveLBLatencyHidingC = v->LBLatencyHidingSourceLinesC / v->VRatioChroma[k] * (v->HTotal[k] / v->PixelClock[k]);
 
                if (UnboundedRequestEnabled) {
                        EffectiveDETBufferSizeY = EffectiveDETBufferSizeY
-                                       + CompressedBufferSizeInkByte * 1024 * SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] / (HTotal[k] / PixelClock[k]) / TotalPixelBW;
+                                       + CompressedBufferSizeInkByte * 1024 * SwathWidthY[k] * BytePerPixelDETY[k] * v->VRatio[k] / (v->HTotal[k] / v->PixelClock[k]) / TotalPixelBW;
                }
 
                LinesInDETY[k] = (double) EffectiveDETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k];
                LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]);
-               FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k];
+               FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (v->HTotal[k] / v->PixelClock[k]) / v->VRatio[k];
                if (BytePerPixelDETC[k] > 0) {
                        LinesInDETC = v->DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k];
                        LinesInDETCRoundedDownToSwath = dml_floor(LinesInDETC, SwathHeightC[k]);
-                       FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (HTotal[k] / PixelClock[k]) / VRatioChroma[k];
+                       FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (v->HTotal[k] / v->PixelClock[k]) / v->VRatioChroma[k];
                } else {
                        LinesInDETC = 0;
                        FullDETBufferingTimeC = 999999;
                }
 
                ActiveDRAMClockChangeLatencyMarginY = EffectiveLBLatencyHidingY + FullDETBufferingTimeY
-                               - ((double) DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k] - *UrgentWatermark - *DRAMClockChangeWatermark;
+                               - ((double) v->DSTXAfterScaler[k] / v->HTotal[k] + v->DSTYAfterScaler[k]) * v->HTotal[k] / v->PixelClock[k] - v->UrgentWatermark - v->DRAMClockChangeWatermark;
 
-               if (NumberOfActivePlanes > 1) {
+               if (v->NumberOfActivePlanes > 1) {
                        ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY
-                                       - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightY[k] * HTotal[k] / PixelClock[k] / VRatio[k];
+                                       - (1 - 1.0 / v->NumberOfActivePlanes) * SwathHeightY[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatio[k];
                }
 
                if (BytePerPixelDETC[k] > 0) {
                        ActiveDRAMClockChangeLatencyMarginC = EffectiveLBLatencyHidingC + FullDETBufferingTimeC
-                                       - ((double) DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k] - *UrgentWatermark - *DRAMClockChangeWatermark;
+                                       - ((double) v->DSTXAfterScaler[k] / v->HTotal[k] + v->DSTYAfterScaler[k]) * v->HTotal[k] / v->PixelClock[k] - v->UrgentWatermark - v->DRAMClockChangeWatermark;
 
-                       if (NumberOfActivePlanes > 1) {
+                       if (v->NumberOfActivePlanes > 1) {
                                ActiveDRAMClockChangeLatencyMarginC = ActiveDRAMClockChangeLatencyMarginC
-                                               - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightC[k] * HTotal[k] / PixelClock[k] / VRatioChroma[k];
+                                               - (1 - 1.0 / v->NumberOfActivePlanes) * SwathHeightC[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatioChroma[k];
                        }
                        v->ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, ActiveDRAMClockChangeLatencyMarginC);
                } else {
                        v->ActiveDRAMClockChangeLatencyMargin[k] = ActiveDRAMClockChangeLatencyMarginY;
                }
 
-               if (WritebackEnable[k] == true) {
-                       WritebackDRAMClockChangeLatencyHiding = WritebackInterfaceBufferSize * 1024
-                                       / (WritebackDestinationWidth[k] * WritebackDestinationHeight[k] / (WritebackSourceHeight[k] * HTotal[k] / PixelClock[k]) * 4);
-                       if (WritebackPixelFormat[k] == dm_444_64) {
+               if (v->WritebackEnable[k] == true) {
+                       WritebackDRAMClockChangeLatencyHiding = v->WritebackInterfaceBufferSize * 1024
+                                       / (v->WritebackDestinationWidth[k] * v->WritebackDestinationHeight[k] / (v->WritebackSourceHeight[k] * v->HTotal[k] / v->PixelClock[k]) * 4);
+                       if (v->WritebackPixelFormat[k] == dm_444_64) {
                                WritebackDRAMClockChangeLatencyHiding = WritebackDRAMClockChangeLatencyHiding / 2;
                        }
                        WritebackDRAMClockChangeLatencyMargin = WritebackDRAMClockChangeLatencyHiding - v->WritebackDRAMClockChangeWatermark;
@@ -5749,14 +5527,14 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
 
        v->MinActiveDRAMClockChangeMargin = 999999;
        PlaneWithMinActiveDRAMClockChangeMargin = 0;
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                if (v->ActiveDRAMClockChangeLatencyMargin[k] < v->MinActiveDRAMClockChangeMargin) {
                        v->MinActiveDRAMClockChangeMargin = v->ActiveDRAMClockChangeLatencyMargin[k];
-                       if (BlendingAndTiming[k] == k) {
+                       if (v->BlendingAndTiming[k] == k) {
                                PlaneWithMinActiveDRAMClockChangeMargin = k;
                        } else {
-                               for (j = 0; j < NumberOfActivePlanes; ++j) {
-                                       if (BlendingAndTiming[k] == j) {
+                               for (j = 0; j < v->NumberOfActivePlanes; ++j) {
+                                       if (v->BlendingAndTiming[k] == j) {
                                                PlaneWithMinActiveDRAMClockChangeMargin = j;
                                        }
                                }
@@ -5764,11 +5542,11 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                }
        }
 
-       *MinActiveDRAMClockChangeLatencySupported = v->MinActiveDRAMClockChangeMargin + DRAMClockChangeLatency;
+       v->MinActiveDRAMClockChangeLatencySupported = v->MinActiveDRAMClockChangeMargin + v->DRAMClockChangeLatency ;
 
        SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = 999999;
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
-               if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (BlendingAndTiming[k] == k)) && !(BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin)
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
+               if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (v->BlendingAndTiming[k] == k)) && !(v->BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin)
                                && v->ActiveDRAMClockChangeLatencyMargin[k] < SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank) {
                        SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = v->ActiveDRAMClockChangeLatencyMargin[k];
                }
@@ -5776,25 +5554,25 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
 
        v->TotalNumberOfActiveOTG = 0;
 
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
-               if (BlendingAndTiming[k] == k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
+               if (v->BlendingAndTiming[k] == k) {
                        v->TotalNumberOfActiveOTG = v->TotalNumberOfActiveOTG + 1;
                }
        }
 
        if (v->MinActiveDRAMClockChangeMargin > 0 && PrefetchMode == 0) {
                *DRAMClockChangeSupport = dm_dram_clock_change_vactive;
-       } else if ((SynchronizedVBlank == true || v->TotalNumberOfActiveOTG == 1
+       } else if ((v->SynchronizedVBlank == true || v->TotalNumberOfActiveOTG == 1
                        || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0) && PrefetchMode == 0) {
                *DRAMClockChangeSupport = dm_dram_clock_change_vblank;
        } else {
                *DRAMClockChangeSupport = dm_dram_clock_change_unsupported;
        }
 
-       *StutterExitWatermark = SRExitTime + ExtraLatency + 10 / DCFCLKDeepSleep;
-       *StutterEnterPlusExitWatermark = (SREnterPlusExitTime + ExtraLatency + 10 / DCFCLKDeepSleep);
-       *Z8StutterExitWatermark = SRExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
-       *Z8StutterEnterPlusExitWatermark = SREnterPlusExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
+       *StutterExitWatermark = v->SRExitTime + ExtraLatency + 10 / DCFCLKDeepSleep;
+       *StutterEnterPlusExitWatermark = (v->SREnterPlusExitTime + ExtraLatency + 10 / DCFCLKDeepSleep);
+       *Z8StutterExitWatermark = v->SRExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
+       *Z8StutterEnterPlusExitWatermark = v->SREnterPlusExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
 
 #ifdef __DML_VBA_DEBUG__
        dml_print("DML::%s: StutterExitWatermark = %f\n", __func__, *StutterExitWatermark);
index 34a5d0f..4bb3b31 100644 (file)
@@ -194,6 +194,9 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
                dcn3_14_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator;
                dcn3_14_ip.max_num_dpp = dc->res_pool->pipe_count;
 
+               if (bw_params->dram_channel_width_bytes > 0)
+                       dcn3_14_soc.dram_channel_width_bytes = bw_params->dram_channel_width_bytes;
+
                if (bw_params->num_channels > 0)
                        dcn3_14_soc.num_chans = bw_params->num_channels;
 
@@ -262,7 +265,7 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
        }
 
        if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
-               dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31);
+               dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN314);
        else
                dml_init_instance(&dc->dml, &dcn3_14_soc, &dcn3_14_ip, DML_PROJECT_DCN31_FPGA);
 }
index fc4d747..ee821c4 100644 (file)
@@ -61,7 +61,7 @@
 // fudge factor for min dcfclk calclation
 #define __DML_MIN_DCFCLK_FACTOR__   1.15
 
-struct {
+typedef struct {
        double DPPCLK;
        double DISPCLK;
        double PixelClock;
@@ -265,33 +265,13 @@ static void CalculateRowBandwidth(
 
 static void CalculateFlipSchedule(
                struct display_mode_lib *mode_lib,
+               unsigned int k,
                double HostVMInefficiencyFactor,
                double UrgentExtraLatency,
                double UrgentLatency,
-               unsigned int GPUVMMaxPageTableLevels,
-               bool HostVMEnable,
-               unsigned int HostVMMaxNonCachedPageTableLevels,
-               bool GPUVMEnable,
-               double HostVMMinPageSize,
                double PDEAndMetaPTEBytesPerFrame,
                double MetaRowBytes,
-               double DPTEBytesPerRow,
-               double BandwidthAvailableForImmediateFlip,
-               unsigned int TotImmediateFlipBytes,
-               enum source_format_class SourcePixelFormat,
-               double LineTime,
-               double VRatio,
-               double VRatioChroma,
-               double Tno_bw,
-               bool DCCEnable,
-               unsigned int dpte_row_height,
-               unsigned int meta_row_height,
-               unsigned int dpte_row_height_chroma,
-               unsigned int meta_row_height_chroma,
-               double *DestinationLinesToRequestVMInImmediateFlip,
-               double *DestinationLinesToRequestRowInImmediateFlip,
-               double *final_flip_bw,
-               bool *ImmediateFlipSupportedForPipe);
+               double DPTEBytesPerRow);
 static double CalculateWriteBackDelay(
                enum source_format_class WritebackPixelFormat,
                double WritebackHRatio,
@@ -325,64 +305,28 @@ static void CalculateVupdateAndDynamicMetadataParameters(
 static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                struct display_mode_lib *mode_lib,
                unsigned int PrefetchMode,
-               unsigned int NumberOfActivePlanes,
-               unsigned int MaxLineBufferLines,
-               unsigned int LineBufferSize,
-               unsigned int WritebackInterfaceBufferSize,
                double DCFCLK,
                double ReturnBW,
-               bool SynchronizedVBlank,
-               unsigned int dpte_group_bytes[],
-               unsigned int MetaChunkSize,
                double UrgentLatency,
                double ExtraLatency,
-               double WritebackLatency,
-               double WritebackChunkSize,
                double SOCCLK,
-               double DRAMClockChangeLatency,
-               double SRExitTime,
-               double SREnterPlusExitTime,
-               double SRExitZ8Time,
-               double SREnterPlusExitZ8Time,
                double DCFCLKDeepSleep,
                unsigned int DETBufferSizeY[],
                unsigned int DETBufferSizeC[],
                unsigned int SwathHeightY[],
                unsigned int SwathHeightC[],
-               unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double SwathWidthC[],
-               double HRatio[],
-               double HRatioChroma[],
-               unsigned int vtaps[],
-               unsigned int VTAPsChroma[],
-               double VRatio[],
-               double VRatioChroma[],
-               unsigned int HTotal[],
-               double PixelClock[],
-               unsigned int BlendingAndTiming[],
                unsigned int DPPPerPlane[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
-               double DSTXAfterScaler[],
-               double DSTYAfterScaler[],
-               bool WritebackEnable[],
-               enum source_format_class WritebackPixelFormat[],
-               double WritebackDestinationWidth[],
-               double WritebackDestinationHeight[],
-               double WritebackSourceHeight[],
                bool UnboundedRequestEnabled,
                unsigned int CompressedBufferSizeInkByte,
                enum clock_change_support *DRAMClockChangeSupport,
-               double *UrgentWatermark,
-               double *WritebackUrgentWatermark,
-               double *DRAMClockChangeWatermark,
-               double *WritebackDRAMClockChangeWatermark,
                double *StutterExitWatermark,
                double *StutterEnterPlusExitWatermark,
                double *Z8StutterExitWatermark,
-               double *Z8StutterEnterPlusExitWatermark,
-               double *MinActiveDRAMClockChangeLatencySupported);
+               double *Z8StutterEnterPlusExitWatermark);
 
 static void CalculateDCFCLKDeepSleep(
                struct display_mode_lib *mode_lib,
@@ -1599,7 +1543,7 @@ static void CalculateDCCConfiguration(
        int segment_order_vert_contiguous_luma;
        int segment_order_vert_contiguous_chroma;
 
-       enum {
+       typedef enum {
                REQ_256Bytes, REQ_128BytesNonContiguous, REQ_128BytesContiguous, REQ_NA
        } RequestType;
        RequestType RequestLuma;
@@ -2928,33 +2872,13 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                        for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                                CalculateFlipSchedule(
                                                mode_lib,
+                                               k,
                                                HostVMInefficiencyFactor,
                                                v->UrgentExtraLatency,
                                                v->UrgentLatency,
-                                               v->GPUVMMaxPageTableLevels,
-                                               v->HostVMEnable,
-                                               v->HostVMMaxNonCachedPageTableLevels,
-                                               v->GPUVMEnable,
-                                               v->HostVMMinPageSize,
                                                v->PDEAndMetaPTEBytesFrame[k],
                                                v->MetaRowByte[k],
-                                               v->PixelPTEBytesPerRow[k],
-                                               v->BandwidthAvailableForImmediateFlip,
-                                               v->TotImmediateFlipBytes,
-                                               v->SourcePixelFormat[k],
-                                               v->HTotal[k] / v->PixelClock[k],
-                                               v->VRatio[k],
-                                               v->VRatioChroma[k],
-                                               v->Tno_bw[k],
-                                               v->DCCEnable[k],
-                                               v->dpte_row_height[k],
-                                               v->meta_row_height[k],
-                                               v->dpte_row_height_chroma[k],
-                                               v->meta_row_height_chroma[k],
-                                               &v->DestinationLinesToRequestVMInImmediateFlip[k],
-                                               &v->DestinationLinesToRequestRowInImmediateFlip[k],
-                                               &v->final_flip_bw[k],
-                                               &v->ImmediateFlipSupportedForPipe[k]);
+                                               v->PixelPTEBytesPerRow[k]);
                        }
 
                        v->total_dcn_read_bw_with_flip = 0.0;
@@ -3041,64 +2965,28 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                CalculateWatermarksAndDRAMSpeedChangeSupport(
                                mode_lib,
                                PrefetchMode,
-                               v->NumberOfActivePlanes,
-                               v->MaxLineBufferLines,
-                               v->LineBufferSize,
-                               v->WritebackInterfaceBufferSize,
                                v->DCFCLK,
                                v->ReturnBW,
-                               v->SynchronizedVBlank,
-                               v->dpte_group_bytes,
-                               v->MetaChunkSize,
                                v->UrgentLatency,
                                v->UrgentExtraLatency,
-                               v->WritebackLatency,
-                               v->WritebackChunkSize,
                                v->SOCCLK,
-                               v->DRAMClockChangeLatency,
-                               v->SRExitTime,
-                               v->SREnterPlusExitTime,
-                               v->SRExitZ8Time,
-                               v->SREnterPlusExitZ8Time,
                                v->DCFCLKDeepSleep,
                                v->DETBufferSizeY,
                                v->DETBufferSizeC,
                                v->SwathHeightY,
                                v->SwathHeightC,
-                               v->LBBitPerPixel,
                                v->SwathWidthY,
                                v->SwathWidthC,
-                               v->HRatio,
-                               v->HRatioChroma,
-                               v->vtaps,
-                               v->VTAPsChroma,
-                               v->VRatio,
-                               v->VRatioChroma,
-                               v->HTotal,
-                               v->PixelClock,
-                               v->BlendingAndTiming,
                                v->DPPPerPlane,
                                v->BytePerPixelDETY,
                                v->BytePerPixelDETC,
-                               v->DSTXAfterScaler,
-                               v->DSTYAfterScaler,
-                               v->WritebackEnable,
-                               v->WritebackPixelFormat,
-                               v->WritebackDestinationWidth,
-                               v->WritebackDestinationHeight,
-                               v->WritebackSourceHeight,
                                v->UnboundedRequestEnabled,
                                v->CompressedBufferSizeInkByte,
                                &DRAMClockChangeSupport,
-                               &v->UrgentWatermark,
-                               &v->WritebackUrgentWatermark,
-                               &v->DRAMClockChangeWatermark,
-                               &v->WritebackDRAMClockChangeWatermark,
                                &v->StutterExitWatermark,
                                &v->StutterEnterPlusExitWatermark,
                                &v->Z8StutterExitWatermark,
-                               &v->Z8StutterEnterPlusExitWatermark,
-                               &v->MinActiveDRAMClockChangeLatencySupported);
+                               &v->Z8StutterEnterPlusExitWatermark);
 
                for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                        if (v->WritebackEnable[k] == true) {
@@ -3710,61 +3598,43 @@ static void CalculateRowBandwidth(
 
 static void CalculateFlipSchedule(
                struct display_mode_lib *mode_lib,
+               unsigned int k,
                double HostVMInefficiencyFactor,
                double UrgentExtraLatency,
                double UrgentLatency,
-               unsigned int GPUVMMaxPageTableLevels,
-               bool HostVMEnable,
-               unsigned int HostVMMaxNonCachedPageTableLevels,
-               bool GPUVMEnable,
-               double HostVMMinPageSize,
                double PDEAndMetaPTEBytesPerFrame,
                double MetaRowBytes,
-               double DPTEBytesPerRow,
-               double BandwidthAvailableForImmediateFlip,
-               unsigned int TotImmediateFlipBytes,
-               enum source_format_class SourcePixelFormat,
-               double LineTime,
-               double VRatio,
-               double VRatioChroma,
-               double Tno_bw,
-               bool DCCEnable,
-               unsigned int dpte_row_height,
-               unsigned int meta_row_height,
-               unsigned int dpte_row_height_chroma,
-               unsigned int meta_row_height_chroma,
-               double *DestinationLinesToRequestVMInImmediateFlip,
-               double *DestinationLinesToRequestRowInImmediateFlip,
-               double *final_flip_bw,
-               bool *ImmediateFlipSupportedForPipe)
+               double DPTEBytesPerRow)
 {
+       struct vba_vars_st *v = &mode_lib->vba;
        double min_row_time = 0.0;
        unsigned int HostVMDynamicLevelsTrips;
        double TimeForFetchingMetaPTEImmediateFlip;
        double TimeForFetchingRowInVBlankImmediateFlip;
        double ImmediateFlipBW;
+       double LineTime = v->HTotal[k] / v->PixelClock[k];
 
-       if (GPUVMEnable == true && HostVMEnable == true) {
-               HostVMDynamicLevelsTrips = HostVMMaxNonCachedPageTableLevels;
+       if (v->GPUVMEnable == true && v->HostVMEnable == true) {
+               HostVMDynamicLevelsTrips = v->HostVMMaxNonCachedPageTableLevels;
        } else {
                HostVMDynamicLevelsTrips = 0;
        }
 
-       if (GPUVMEnable == true || DCCEnable == true) {
-               ImmediateFlipBW = (PDEAndMetaPTEBytesPerFrame + MetaRowBytes + DPTEBytesPerRow) * BandwidthAvailableForImmediateFlip / TotImmediateFlipBytes;
+       if (v->GPUVMEnable == true || v->DCCEnable[k] == true) {
+               ImmediateFlipBW = (PDEAndMetaPTEBytesPerFrame + MetaRowBytes + DPTEBytesPerRow) * v->BandwidthAvailableForImmediateFlip / v->TotImmediateFlipBytes;
        }
 
-       if (GPUVMEnable == true) {
+       if (v->GPUVMEnable == true) {
                TimeForFetchingMetaPTEImmediateFlip = dml_max3(
-                               Tno_bw + PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / ImmediateFlipBW,
-                               UrgentExtraLatency + UrgentLatency * (GPUVMMaxPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1),
+                               v->Tno_bw[k] + PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / ImmediateFlipBW,
+                               UrgentExtraLatency + UrgentLatency * (v->GPUVMMaxPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1),
                                LineTime / 4.0);
        } else {
                TimeForFetchingMetaPTEImmediateFlip = 0;
        }
 
-       *DestinationLinesToRequestVMInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime), 1) / 4.0;
-       if ((GPUVMEnable == true || DCCEnable == true)) {
+       v->DestinationLinesToRequestVMInImmediateFlip[k] = dml_ceil(4.0 * (TimeForFetchingMetaPTEImmediateFlip / LineTime), 1) / 4.0;
+       if ((v->GPUVMEnable == true || v->DCCEnable[k] == true)) {
                TimeForFetchingRowInVBlankImmediateFlip = dml_max3(
                                (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / ImmediateFlipBW,
                                UrgentLatency * (HostVMDynamicLevelsTrips + 1),
@@ -3773,54 +3643,54 @@ static void CalculateFlipSchedule(
                TimeForFetchingRowInVBlankImmediateFlip = 0;
        }
 
-       *DestinationLinesToRequestRowInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime), 1) / 4.0;
+       v->DestinationLinesToRequestRowInImmediateFlip[k] = dml_ceil(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime), 1) / 4.0;
 
-       if (GPUVMEnable == true) {
-               *final_flip_bw = dml_max(
-                               PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / (*DestinationLinesToRequestVMInImmediateFlip * LineTime),
-                               (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (*DestinationLinesToRequestRowInImmediateFlip * LineTime));
-       } else if ((GPUVMEnable == true || DCCEnable == true)) {
-               *final_flip_bw = (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (*DestinationLinesToRequestRowInImmediateFlip * LineTime);
+       if (v->GPUVMEnable == true) {
+               v->final_flip_bw[k] = dml_max(
+                               PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / (v->DestinationLinesToRequestVMInImmediateFlip[k] * LineTime),
+                               (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (v->DestinationLinesToRequestRowInImmediateFlip[k] * LineTime));
+       } else if ((v->GPUVMEnable == true || v->DCCEnable[k] == true)) {
+               v->final_flip_bw[k] = (MetaRowBytes + DPTEBytesPerRow * HostVMInefficiencyFactor) / (v->DestinationLinesToRequestRowInImmediateFlip[k] * LineTime);
        } else {
-               *final_flip_bw = 0;
+               v->final_flip_bw[k] = 0;
        }
 
-       if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10 || SourcePixelFormat == dm_rgbe_alpha) {
-               if (GPUVMEnable == true && DCCEnable != true) {
-                       min_row_time = dml_min(dpte_row_height * LineTime / VRatio, dpte_row_height_chroma * LineTime / VRatioChroma);
-               } else if (GPUVMEnable != true && DCCEnable == true) {
-                       min_row_time = dml_min(meta_row_height * LineTime / VRatio, meta_row_height_chroma * LineTime / VRatioChroma);
+       if (v->SourcePixelFormat[k] == dm_420_8 || v->SourcePixelFormat[k] == dm_420_10 || v->SourcePixelFormat[k] == dm_rgbe_alpha) {
+               if (v->GPUVMEnable == true && v->DCCEnable[k] != true) {
+                       min_row_time = dml_min(v->dpte_row_height[k] * LineTime / v->VRatio[k], v->dpte_row_height_chroma[k] * LineTime / v->VRatioChroma[k]);
+               } else if (v->GPUVMEnable != true && v->DCCEnable[k] == true) {
+                       min_row_time = dml_min(v->meta_row_height[k] * LineTime / v->VRatio[k], v->meta_row_height_chroma[k] * LineTime / v->VRatioChroma[k]);
                } else {
                        min_row_time = dml_min4(
-                                       dpte_row_height * LineTime / VRatio,
-                                       meta_row_height * LineTime / VRatio,
-                                       dpte_row_height_chroma * LineTime / VRatioChroma,
-                                       meta_row_height_chroma * LineTime / VRatioChroma);
+                                       v->dpte_row_height[k] * LineTime / v->VRatio[k],
+                                       v->meta_row_height[k] * LineTime / v->VRatio[k],
+                                       v->dpte_row_height_chroma[k] * LineTime / v->VRatioChroma[k],
+                                       v->meta_row_height_chroma[k] * LineTime / v->VRatioChroma[k]);
                }
        } else {
-               if (GPUVMEnable == true && DCCEnable != true) {
-                       min_row_time = dpte_row_height * LineTime / VRatio;
-               } else if (GPUVMEnable != true && DCCEnable == true) {
-                       min_row_time = meta_row_height * LineTime / VRatio;
+               if (v->GPUVMEnable == true && v->DCCEnable[k] != true) {
+                       min_row_time = v->dpte_row_height[k] * LineTime / v->VRatio[k];
+               } else if (v->GPUVMEnable != true && v->DCCEnable[k] == true) {
+                       min_row_time = v->meta_row_height[k] * LineTime / v->VRatio[k];
                } else {
-                       min_row_time = dml_min(dpte_row_height * LineTime / VRatio, meta_row_height * LineTime / VRatio);
+                       min_row_time = dml_min(v->dpte_row_height[k] * LineTime / v->VRatio[k], v->meta_row_height[k] * LineTime / v->VRatio[k]);
                }
        }
 
-       if (*DestinationLinesToRequestVMInImmediateFlip >= 32 || *DestinationLinesToRequestRowInImmediateFlip >= 16
+       if (v->DestinationLinesToRequestVMInImmediateFlip[k] >= 32 || v->DestinationLinesToRequestRowInImmediateFlip[k] >= 16
                        || TimeForFetchingMetaPTEImmediateFlip + 2 * TimeForFetchingRowInVBlankImmediateFlip > min_row_time) {
-               *ImmediateFlipSupportedForPipe = false;
+               v->ImmediateFlipSupportedForPipe[k] = false;
        } else {
-               *ImmediateFlipSupportedForPipe = true;
+               v->ImmediateFlipSupportedForPipe[k] = true;
        }
 
 #ifdef __DML_VBA_DEBUG__
-       dml_print("DML::%s: DestinationLinesToRequestVMInImmediateFlip = %f\n", __func__, *DestinationLinesToRequestVMInImmediateFlip);
-       dml_print("DML::%s: DestinationLinesToRequestRowInImmediateFlip = %f\n", __func__, *DestinationLinesToRequestRowInImmediateFlip);
+       dml_print("DML::%s: DestinationLinesToRequestVMInImmediateFlip = %f\n", __func__, v->DestinationLinesToRequestVMInImmediateFlip[k]);
+       dml_print("DML::%s: DestinationLinesToRequestRowInImmediateFlip = %f\n", __func__, v->DestinationLinesToRequestRowInImmediateFlip[k]);
        dml_print("DML::%s: TimeForFetchingMetaPTEImmediateFlip = %f\n", __func__, TimeForFetchingMetaPTEImmediateFlip);
        dml_print("DML::%s: TimeForFetchingRowInVBlankImmediateFlip = %f\n", __func__, TimeForFetchingRowInVBlankImmediateFlip);
        dml_print("DML::%s: min_row_time = %f\n", __func__, min_row_time);
-       dml_print("DML::%s: ImmediateFlipSupportedForPipe = %d\n", __func__, *ImmediateFlipSupportedForPipe);
+       dml_print("DML::%s: ImmediateFlipSupportedForPipe = %d\n", __func__, v->ImmediateFlipSupportedForPipe[k]);
 #endif
 
 }
@@ -4071,9 +3941,7 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
 
        v->SourceFormatPixelAndScanSupport = true;
        for (k = 0; k < v->NumberOfActivePlanes; k++) {
-               if ((v->SurfaceTiling[k] == dm_sw_linear && (!(v->SourceScan[k] != dm_vert) || v->DCCEnable[k] == true))
-                               || ((v->SurfaceTiling[k] == dm_sw_64kb_d || v->SurfaceTiling[k] == dm_sw_64kb_d_t
-                                               || v->SurfaceTiling[k] == dm_sw_64kb_d_x) && !(v->SourcePixelFormat[k] == dm_444_64))) {
+               if (v->SurfaceTiling[k] == dm_sw_linear && (!(v->SourceScan[k] != dm_vert) || v->DCCEnable[k] == true)) {
                        v->SourceFormatPixelAndScanSupport = false;
                }
        }
@@ -5414,33 +5282,13 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
                                        for (k = 0; k < v->NumberOfActivePlanes; k++) {
                                                CalculateFlipSchedule(
                                                                mode_lib,
+                                                               k,
                                                                HostVMInefficiencyFactor,
                                                                v->ExtraLatency,
                                                                v->UrgLatency[i],
-                                                               v->GPUVMMaxPageTableLevels,
-                                                               v->HostVMEnable,
-                                                               v->HostVMMaxNonCachedPageTableLevels,
-                                                               v->GPUVMEnable,
-                                                               v->HostVMMinPageSize,
                                                                v->PDEAndMetaPTEBytesPerFrame[i][j][k],
                                                                v->MetaRowBytes[i][j][k],
-                                                               v->DPTEBytesPerRow[i][j][k],
-                                                               v->BandwidthAvailableForImmediateFlip,
-                                                               v->TotImmediateFlipBytes,
-                                                               v->SourcePixelFormat[k],
-                                                               v->HTotal[k] / v->PixelClock[k],
-                                                               v->VRatio[k],
-                                                               v->VRatioChroma[k],
-                                                               v->Tno_bw[k],
-                                                               v->DCCEnable[k],
-                                                               v->dpte_row_height[k],
-                                                               v->meta_row_height[k],
-                                                               v->dpte_row_height_chroma[k],
-                                                               v->meta_row_height_chroma[k],
-                                                               &v->DestinationLinesToRequestVMInImmediateFlip[k],
-                                                               &v->DestinationLinesToRequestRowInImmediateFlip[k],
-                                                               &v->final_flip_bw[k],
-                                                               &v->ImmediateFlipSupportedForPipe[k]);
+                                                               v->DPTEBytesPerRow[i][j][k]);
                                        }
                                        v->total_dcn_read_bw_with_flip = 0.0;
                                        for (k = 0; k < v->NumberOfActivePlanes; k++) {
@@ -5498,64 +5346,28 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
                        CalculateWatermarksAndDRAMSpeedChangeSupport(
                                        mode_lib,
                                        v->PrefetchModePerState[i][j],
-                                       v->NumberOfActivePlanes,
-                                       v->MaxLineBufferLines,
-                                       v->LineBufferSize,
-                                       v->WritebackInterfaceBufferSize,
                                        v->DCFCLKState[i][j],
                                        v->ReturnBWPerState[i][j],
-                                       v->SynchronizedVBlank,
-                                       v->dpte_group_bytes,
-                                       v->MetaChunkSize,
                                        v->UrgLatency[i],
                                        v->ExtraLatency,
-                                       v->WritebackLatency,
-                                       v->WritebackChunkSize,
                                        v->SOCCLKPerState[i],
-                                       v->DRAMClockChangeLatency,
-                                       v->SRExitTime,
-                                       v->SREnterPlusExitTime,
-                                       v->SRExitZ8Time,
-                                       v->SREnterPlusExitZ8Time,
                                        v->ProjectedDCFCLKDeepSleep[i][j],
                                        v->DETBufferSizeYThisState,
                                        v->DETBufferSizeCThisState,
                                        v->SwathHeightYThisState,
                                        v->SwathHeightCThisState,
-                                       v->LBBitPerPixel,
                                        v->SwathWidthYThisState,
                                        v->SwathWidthCThisState,
-                                       v->HRatio,
-                                       v->HRatioChroma,
-                                       v->vtaps,
-                                       v->VTAPsChroma,
-                                       v->VRatio,
-                                       v->VRatioChroma,
-                                       v->HTotal,
-                                       v->PixelClock,
-                                       v->BlendingAndTiming,
                                        v->NoOfDPPThisState,
                                        v->BytePerPixelInDETY,
                                        v->BytePerPixelInDETC,
-                                       v->DSTXAfterScaler,
-                                       v->DSTYAfterScaler,
-                                       v->WritebackEnable,
-                                       v->WritebackPixelFormat,
-                                       v->WritebackDestinationWidth,
-                                       v->WritebackDestinationHeight,
-                                       v->WritebackSourceHeight,
                                        UnboundedRequestEnabledThisState,
                                        CompressedBufferSizeInkByteThisState,
                                        &v->DRAMClockChangeSupport[i][j],
-                                       &v->UrgentWatermark,
-                                       &v->WritebackUrgentWatermark,
-                                       &v->DRAMClockChangeWatermark,
-                                       &v->WritebackDRAMClockChangeWatermark,
-                                       &dummy,
                                        &dummy,
                                        &dummy,
                                        &dummy,
-                                       &v->MinActiveDRAMClockChangeLatencySupported);
+                                       &dummy);
                }
        }
 
@@ -5681,64 +5493,28 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
 static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                struct display_mode_lib *mode_lib,
                unsigned int PrefetchMode,
-               unsigned int NumberOfActivePlanes,
-               unsigned int MaxLineBufferLines,
-               unsigned int LineBufferSize,
-               unsigned int WritebackInterfaceBufferSize,
                double DCFCLK,
                double ReturnBW,
-               bool SynchronizedVBlank,
-               unsigned int dpte_group_bytes[],
-               unsigned int MetaChunkSize,
                double UrgentLatency,
                double ExtraLatency,
-               double WritebackLatency,
-               double WritebackChunkSize,
                double SOCCLK,
-               double DRAMClockChangeLatency,
-               double SRExitTime,
-               double SREnterPlusExitTime,
-               double SRExitZ8Time,
-               double SREnterPlusExitZ8Time,
                double DCFCLKDeepSleep,
                unsigned int DETBufferSizeY[],
                unsigned int DETBufferSizeC[],
                unsigned int SwathHeightY[],
                unsigned int SwathHeightC[],
-               unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double SwathWidthC[],
-               double HRatio[],
-               double HRatioChroma[],
-               unsigned int vtaps[],
-               unsigned int VTAPsChroma[],
-               double VRatio[],
-               double VRatioChroma[],
-               unsigned int HTotal[],
-               double PixelClock[],
-               unsigned int BlendingAndTiming[],
                unsigned int DPPPerPlane[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
-               double DSTXAfterScaler[],
-               double DSTYAfterScaler[],
-               bool WritebackEnable[],
-               enum source_format_class WritebackPixelFormat[],
-               double WritebackDestinationWidth[],
-               double WritebackDestinationHeight[],
-               double WritebackSourceHeight[],
                bool UnboundedRequestEnabled,
                unsigned int CompressedBufferSizeInkByte,
                enum clock_change_support *DRAMClockChangeSupport,
-               double *UrgentWatermark,
-               double *WritebackUrgentWatermark,
-               double *DRAMClockChangeWatermark,
-               double *WritebackDRAMClockChangeWatermark,
                double *StutterExitWatermark,
                double *StutterEnterPlusExitWatermark,
                double *Z8StutterExitWatermark,
-               double *Z8StutterEnterPlusExitWatermark,
-               double *MinActiveDRAMClockChangeLatencySupported)
+               double *Z8StutterEnterPlusExitWatermark)
 {
        struct vba_vars_st *v = &mode_lib->vba;
        double EffectiveLBLatencyHidingY;
@@ -5758,103 +5534,103 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
        double TotalPixelBW = 0.0;
        int k, j;
 
-       *UrgentWatermark = UrgentLatency + ExtraLatency;
+       v->UrgentWatermark = UrgentLatency + ExtraLatency;
 
 #ifdef __DML_VBA_DEBUG__
        dml_print("DML::%s: UrgentLatency = %f\n", __func__, UrgentLatency);
        dml_print("DML::%s: ExtraLatency = %f\n", __func__, ExtraLatency);
-       dml_print("DML::%s: UrgentWatermark = %f\n", __func__, *UrgentWatermark);
+       dml_print("DML::%s: UrgentWatermark = %f\n", __func__, v->UrgentWatermark);
 #endif
 
-       *DRAMClockChangeWatermark = DRAMClockChangeLatency + *UrgentWatermark;
+       v->DRAMClockChangeWatermark = v->DRAMClockChangeLatency + v->UrgentWatermark;
 
 #ifdef __DML_VBA_DEBUG__
-       dml_print("DML::%s: DRAMClockChangeLatency = %f\n", __func__, DRAMClockChangeLatency);
-       dml_print("DML::%s: DRAMClockChangeWatermark = %f\n", __func__, *DRAMClockChangeWatermark);
+       dml_print("DML::%s: v->DRAMClockChangeLatency = %f\n", __func__, v->DRAMClockChangeLatency);
+       dml_print("DML::%s: DRAMClockChangeWatermark = %f\n", __func__, v->DRAMClockChangeWatermark);
 #endif
 
        v->TotalActiveWriteback = 0;
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
-               if (WritebackEnable[k] == true) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
+               if (v->WritebackEnable[k] == true) {
                        v->TotalActiveWriteback = v->TotalActiveWriteback + 1;
                }
        }
 
        if (v->TotalActiveWriteback <= 1) {
-               *WritebackUrgentWatermark = WritebackLatency;
+               v->WritebackUrgentWatermark = v->WritebackLatency;
        } else {
-               *WritebackUrgentWatermark = WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
+               v->WritebackUrgentWatermark = v->WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
        }
 
        if (v->TotalActiveWriteback <= 1) {
-               *WritebackDRAMClockChangeWatermark = DRAMClockChangeLatency + WritebackLatency;
+               v->WritebackDRAMClockChangeWatermark = v->DRAMClockChangeLatency + v->WritebackLatency;
        } else {
-               *WritebackDRAMClockChangeWatermark = DRAMClockChangeLatency + WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
+               v->WritebackDRAMClockChangeWatermark = v->DRAMClockChangeLatency + v->WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
        }
 
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                TotalPixelBW = TotalPixelBW
-                               + DPPPerPlane[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] + SwathWidthC[k] * BytePerPixelDETC[k] * VRatioChroma[k])
-                                               / (HTotal[k] / PixelClock[k]);
+                               + DPPPerPlane[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * v->VRatio[k] + SwathWidthC[k] * BytePerPixelDETC[k] * v->VRatioChroma[k])
+                                               / (v->HTotal[k] / v->PixelClock[k]);
        }
 
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                double EffectiveDETBufferSizeY = DETBufferSizeY[k];
 
                v->LBLatencyHidingSourceLinesY = dml_min(
-                               (double) MaxLineBufferLines,
-                               dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(HRatio[k], 1.0)), 1)) - (vtaps[k] - 1);
+                               (double) v->MaxLineBufferLines,
+                               dml_floor(v->LineBufferSize / v->LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(v->HRatio[k], 1.0)), 1)) - (v->vtaps[k] - 1);
 
                v->LBLatencyHidingSourceLinesC = dml_min(
-                               (double) MaxLineBufferLines,
-                               dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(HRatioChroma[k], 1.0)), 1)) - (VTAPsChroma[k] - 1);
+                               (double) v->MaxLineBufferLines,
+                               dml_floor(v->LineBufferSize / v->LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(v->HRatioChroma[k], 1.0)), 1)) - (v->VTAPsChroma[k] - 1);
 
-               EffectiveLBLatencyHidingY = v->LBLatencyHidingSourceLinesY / VRatio[k] * (HTotal[k] / PixelClock[k]);
+               EffectiveLBLatencyHidingY = v->LBLatencyHidingSourceLinesY / v->VRatio[k] * (v->HTotal[k] / v->PixelClock[k]);
 
-               EffectiveLBLatencyHidingC = v->LBLatencyHidingSourceLinesC / VRatioChroma[k] * (HTotal[k] / PixelClock[k]);
+               EffectiveLBLatencyHidingC = v->LBLatencyHidingSourceLinesC / v->VRatioChroma[k] * (v->HTotal[k] / v->PixelClock[k]);
 
                if (UnboundedRequestEnabled) {
                        EffectiveDETBufferSizeY = EffectiveDETBufferSizeY
-                                       + CompressedBufferSizeInkByte * 1024 * SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] / (HTotal[k] / PixelClock[k]) / TotalPixelBW;
+                                       + CompressedBufferSizeInkByte * 1024 * SwathWidthY[k] * BytePerPixelDETY[k] * v->VRatio[k] / (v->HTotal[k] / v->PixelClock[k]) / TotalPixelBW;
                }
 
                LinesInDETY[k] = (double) EffectiveDETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k];
                LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]);
-               FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k];
+               FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (v->HTotal[k] / v->PixelClock[k]) / v->VRatio[k];
                if (BytePerPixelDETC[k] > 0) {
                        LinesInDETC = v->DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k];
                        LinesInDETCRoundedDownToSwath = dml_floor(LinesInDETC, SwathHeightC[k]);
-                       FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (HTotal[k] / PixelClock[k]) / VRatioChroma[k];
+                       FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (v->HTotal[k] / v->PixelClock[k]) / v->VRatioChroma[k];
                } else {
                        LinesInDETC = 0;
                        FullDETBufferingTimeC = 999999;
                }
 
                ActiveDRAMClockChangeLatencyMarginY = EffectiveLBLatencyHidingY + FullDETBufferingTimeY
-                               - ((double) DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k] - *UrgentWatermark - *DRAMClockChangeWatermark;
+                               - ((double) v->DSTXAfterScaler[k] / v->HTotal[k] + v->DSTYAfterScaler[k]) * v->HTotal[k] / v->PixelClock[k] - v->UrgentWatermark - v->DRAMClockChangeWatermark;
 
-               if (NumberOfActivePlanes > 1) {
+               if (v->NumberOfActivePlanes > 1) {
                        ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY
-                                       - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightY[k] * HTotal[k] / PixelClock[k] / VRatio[k];
+                                       - (1 - 1.0 / v->NumberOfActivePlanes) * SwathHeightY[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatio[k];
                }
 
                if (BytePerPixelDETC[k] > 0) {
                        ActiveDRAMClockChangeLatencyMarginC = EffectiveLBLatencyHidingC + FullDETBufferingTimeC
-                                       - ((double) DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k] - *UrgentWatermark - *DRAMClockChangeWatermark;
+                                       - ((double) v->DSTXAfterScaler[k] / v->HTotal[k] + v->DSTYAfterScaler[k]) * v->HTotal[k] / v->PixelClock[k] - v->UrgentWatermark - v->DRAMClockChangeWatermark;
 
-                       if (NumberOfActivePlanes > 1) {
+                       if (v->NumberOfActivePlanes > 1) {
                                ActiveDRAMClockChangeLatencyMarginC = ActiveDRAMClockChangeLatencyMarginC
-                                               - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightC[k] * HTotal[k] / PixelClock[k] / VRatioChroma[k];
+                                               - (1 - 1.0 / v->NumberOfActivePlanes) * SwathHeightC[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatioChroma[k];
                        }
                        v->ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, ActiveDRAMClockChangeLatencyMarginC);
                } else {
                        v->ActiveDRAMClockChangeLatencyMargin[k] = ActiveDRAMClockChangeLatencyMarginY;
                }
 
-               if (WritebackEnable[k] == true) {
-                       WritebackDRAMClockChangeLatencyHiding = WritebackInterfaceBufferSize * 1024
-                                       / (WritebackDestinationWidth[k] * WritebackDestinationHeight[k] / (WritebackSourceHeight[k] * HTotal[k] / PixelClock[k]) * 4);
-                       if (WritebackPixelFormat[k] == dm_444_64) {
+               if (v->WritebackEnable[k] == true) {
+                       WritebackDRAMClockChangeLatencyHiding = v->WritebackInterfaceBufferSize * 1024
+                                       / (v->WritebackDestinationWidth[k] * v->WritebackDestinationHeight[k] / (v->WritebackSourceHeight[k] * v->HTotal[k] / v->PixelClock[k]) * 4);
+                       if (v->WritebackPixelFormat[k] == dm_444_64) {
                                WritebackDRAMClockChangeLatencyHiding = WritebackDRAMClockChangeLatencyHiding / 2;
                        }
                        WritebackDRAMClockChangeLatencyMargin = WritebackDRAMClockChangeLatencyHiding - v->WritebackDRAMClockChangeWatermark;
@@ -5864,14 +5640,14 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
 
        v->MinActiveDRAMClockChangeMargin = 999999;
        PlaneWithMinActiveDRAMClockChangeMargin = 0;
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
                if (v->ActiveDRAMClockChangeLatencyMargin[k] < v->MinActiveDRAMClockChangeMargin) {
                        v->MinActiveDRAMClockChangeMargin = v->ActiveDRAMClockChangeLatencyMargin[k];
-                       if (BlendingAndTiming[k] == k) {
+                       if (v->BlendingAndTiming[k] == k) {
                                PlaneWithMinActiveDRAMClockChangeMargin = k;
                        } else {
-                               for (j = 0; j < NumberOfActivePlanes; ++j) {
-                                       if (BlendingAndTiming[k] == j) {
+                               for (j = 0; j < v->NumberOfActivePlanes; ++j) {
+                                       if (v->BlendingAndTiming[k] == j) {
                                                PlaneWithMinActiveDRAMClockChangeMargin = j;
                                        }
                                }
@@ -5879,11 +5655,11 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
                }
        }
 
-       *MinActiveDRAMClockChangeLatencySupported = v->MinActiveDRAMClockChangeMargin + DRAMClockChangeLatency;
+       v->MinActiveDRAMClockChangeLatencySupported = v->MinActiveDRAMClockChangeMargin + v->DRAMClockChangeLatency ;
 
        SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = 999999;
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
-               if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (BlendingAndTiming[k] == k)) && !(BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin)
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
+               if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (v->BlendingAndTiming[k] == k)) && !(v->BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin)
                                && v->ActiveDRAMClockChangeLatencyMargin[k] < SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank) {
                        SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = v->ActiveDRAMClockChangeLatencyMargin[k];
                }
@@ -5891,25 +5667,25 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
 
        v->TotalNumberOfActiveOTG = 0;
 
-       for (k = 0; k < NumberOfActivePlanes; ++k) {
-               if (BlendingAndTiming[k] == k) {
+       for (k = 0; k < v->NumberOfActivePlanes; ++k) {
+               if (v->BlendingAndTiming[k] == k) {
                        v->TotalNumberOfActiveOTG = v->TotalNumberOfActiveOTG + 1;
                }
        }
 
        if (v->MinActiveDRAMClockChangeMargin > 0 && PrefetchMode == 0) {
                *DRAMClockChangeSupport = dm_dram_clock_change_vactive;
-       } else if ((SynchronizedVBlank == true || v->TotalNumberOfActiveOTG == 1
+       } else if ((v->SynchronizedVBlank == true || v->TotalNumberOfActiveOTG == 1
                        || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0) && PrefetchMode == 0) {
                *DRAMClockChangeSupport = dm_dram_clock_change_vblank;
        } else {
                *DRAMClockChangeSupport = dm_dram_clock_change_unsupported;
        }
 
-       *StutterExitWatermark = SRExitTime + ExtraLatency + 10 / DCFCLKDeepSleep;
-       *StutterEnterPlusExitWatermark = (SREnterPlusExitTime + ExtraLatency + 10 / DCFCLKDeepSleep);
-       *Z8StutterExitWatermark = SRExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
-       *Z8StutterEnterPlusExitWatermark = SREnterPlusExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
+       *StutterExitWatermark = v->SRExitTime + ExtraLatency + 10 / DCFCLKDeepSleep;
+       *StutterEnterPlusExitWatermark = (v->SREnterPlusExitTime + ExtraLatency + 10 / DCFCLKDeepSleep);
+       *Z8StutterExitWatermark = v->SRExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
+       *Z8StutterEnterPlusExitWatermark = v->SREnterPlusExitZ8Time + ExtraLatency + 10 / DCFCLKDeepSleep;
 
 #ifdef __DML_VBA_DEBUG__
        dml_print("DML::%s: StutterExitWatermark = %f\n", __func__, *StutterExitWatermark);
@@ -7157,12 +6933,13 @@ static double CalculateExtraLatencyBytes(
                        HostVMDynamicLevels = dml_max(0, (int) HostVMMaxNonCachedPageTableLevels - 1);
                else
                        HostVMDynamicLevels = dml_max(0, (int) HostVMMaxNonCachedPageTableLevels - 2);
-       else
+       } else {
                HostVMDynamicLevels = 0;
+       }
 
        ret = ReorderingBytes + (TotalNumberOfActiveDPP * PixelChunkSizeInKByte + TotalNumberOfDCCActiveDPP * MetaChunkSize) * 1024.0;
 
-       if (GPUVMEnable == true)
+       if (GPUVMEnable == true) {
                for (k = 0; k < NumberOfActivePlanes; ++k)
                        ret = ret + NumberOfDPP[k] * dpte_group_bytes[k] * (1 + 8 * HostVMDynamicLevels) * HostVMInefficiencyFactor;
        }
index 8118cfc..e573e70 100644 (file)
@@ -121,8 +121,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc = {
                },
        },
        .num_states = 1,
-       .sr_exit_time_us = 20.16,
-       .sr_enter_plus_exit_time_us = 27.13,
+       .sr_exit_time_us = 42.97,
+       .sr_enter_plus_exit_time_us = 49.94,
        .sr_exit_z8_time_us = 285.0,
        .sr_enter_plus_exit_z8_time_us = 320,
        .writeback_latency_us = 12.0,
@@ -244,6 +244,50 @@ void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr)
 }
 
 /**
+ * Finds dummy_latency_index when MCLK switching using firmware based
+ * vblank stretch is enabled. This function will iterate through the
+ * table of dummy pstate latencies until the lowest value that allows
+ * dm_allow_self_refresh_and_mclk_switch to happen is found
+ */
+int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
+                                                           struct dc_state *context,
+                                                           display_e2e_pipe_params_st *pipes,
+                                                           int pipe_cnt,
+                                                           int vlevel)
+{
+       const int max_latency_table_entries = 4;
+       const struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+       int dummy_latency_index = 0;
+
+       dc_assert_fp_enabled();
+
+       while (dummy_latency_index < max_latency_table_entries) {
+               context->bw_ctx.dml.soc.dram_clock_change_latency_us =
+                               dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
+               dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
+
+               if (vlevel < context->bw_ctx.dml.vba.soc.num_states &&
+                               vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported)
+                       break;
+
+               dummy_latency_index++;
+       }
+
+       if (dummy_latency_index == max_latency_table_entries) {
+               ASSERT(dummy_latency_index != max_latency_table_entries);
+               /* If the execution gets here, it means dummy p_states are
+                * not possible. This should never happen and would mean
+                * something is severely wrong.
+                * Here we reset dummy_latency_index to 3, because it is
+                * better to have underflows than system crashes.
+                */
+               dummy_latency_index = max_latency_table_entries - 1;
+       }
+
+       return dummy_latency_index;
+}
+
+/**
  * dcn32_helper_populate_phantom_dlg_params - Get DLG params for phantom pipes
  * and populate pipe_ctx with those params.
  *
@@ -1014,6 +1058,15 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
            dc->debug.force_subvp_mclk_switch)) {
 
                dcn32_merge_pipes_for_subvp(dc, context);
+               // to re-initialize viewport after the pipe merge
+               for (int i = 0; i < dc->res_pool->pipe_count; i++) {
+                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+                       if (!pipe_ctx->plane_state || !pipe_ctx->stream)
+                               continue;
+
+                       resource_build_scaling_params(pipe_ctx);
+               }
 
                while (!found_supported_config && dcn32_enough_pipes_for_subvp(dc, context) &&
                        dcn32_assign_subvp_pipe(dc, context, &dc_pipe_idx)) {
@@ -1637,7 +1690,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
                        dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(dc, context);
 
                if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
-                       dummy_latency_index = dcn30_find_dummy_latency_index_for_fw_based_mclk_switch(dc,
+                       dummy_latency_index = dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(dc,
                                context, pipes, pipe_cnt, vlevel);
 
                        /* After calling dcn30_find_dummy_latency_index_for_fw_based_mclk_switch
@@ -1873,6 +1926,45 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st
        memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st));
 }
 
+void dcn32_patch_dpm_table(struct clk_bw_params *bw_params)
+{
+       int i;
+       unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
+                       max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
+
+       for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
+               if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
+                       max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
+               if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
+                       max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
+               if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
+                       max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
+               if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
+                       max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
+               if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
+                       max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
+               if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
+                       max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
+               if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
+                       max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
+       }
+
+       /* Scan through clock values we currently have and if they are 0,
+        *  then populate it with dcn3_2_soc.clock_limits[] value.
+        *
+        * Do it for DCFCLK, DISPCLK, DTBCLK and UCLK as any of those being
+        *  0, will cause it to skip building the clock table.
+        */
+       if (max_dcfclk_mhz == 0)
+               bw_params->clk_table.entries[0].dcfclk_mhz = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
+       if (max_dispclk_mhz == 0)
+               bw_params->clk_table.entries[0].dispclk_mhz = dcn3_2_soc.clock_limits[0].dispclk_mhz;
+       if (max_dtbclk_mhz == 0)
+               bw_params->clk_table.entries[0].dtbclk_mhz = dcn3_2_soc.clock_limits[0].dtbclk_mhz;
+       if (max_uclk_mhz == 0)
+               bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16;
+}
+
 static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
                struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
 {
index 3ed06ab..e1b79e2 100644 (file)
@@ -71,4 +71,12 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
 
 void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params);
 
+int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
+                                                           struct dc_state *context,
+                                                           display_e2e_pipe_params_st *pipes,
+                                                           int pipe_cnt,
+                                                           int vlevel);
+
+void dcn32_patch_dpm_table(struct clk_bw_params *bw_params);
+
 #endif
index cb20257..6980f69 100644 (file)
@@ -755,30 +755,18 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                        v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.BytePerPixelY = v->BytePerPixelY[k];
                        v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.BytePerPixelC = v->BytePerPixelC[k];
                        v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe.ProgressiveToInterlaceUnitInOPP = mode_lib->vba.ProgressiveToInterlaceUnitInOPP;
-                       v->ErrorResult[k] = dml32_CalculatePrefetchSchedule(v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.HostVMInefficiencyFactor,
-                                       &v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe, v->DSCDelay[k],
-                                       mode_lib->vba.DPPCLKDelaySubtotal + mode_lib->vba.DPPCLKDelayCNVCFormater,
-                                       mode_lib->vba.DPPCLKDelaySCL,
-                                       mode_lib->vba.DPPCLKDelaySCLLBOnly,
-                                       mode_lib->vba.DPPCLKDelayCNVCCursor,
-                                       mode_lib->vba.DISPCLKDelaySubtotal,
-                                       (unsigned int) (v->SwathWidthY[k] / mode_lib->vba.HRatio[k]),
-                                       mode_lib->vba.OutputFormat[k],
-                                       mode_lib->vba.MaxInterDCNTileRepeaters,
+                       v->ErrorResult[k] = dml32_CalculatePrefetchSchedule(
+                                       v,
+                                       k,
+                                       v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.HostVMInefficiencyFactor,
+                                       &v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.myPipe,
+                                       v->DSCDelay[k],
+                                       (unsigned int) (v->SwathWidthY[k] / v->HRatio[k]),
                                        dml_min(v->VStartupLines, v->MaxVStartupLines[k]),
                                        v->MaxVStartupLines[k],
-                                       mode_lib->vba.GPUVMMaxPageTableLevels,
-                                       mode_lib->vba.GPUVMEnable,
-                                       mode_lib->vba.HostVMEnable,
-                                       mode_lib->vba.HostVMMaxNonCachedPageTableLevels,
-                                       mode_lib->vba.HostVMMinPageSize,
-                                       mode_lib->vba.DynamicMetadataEnable[k],
-                                       mode_lib->vba.DynamicMetadataVMEnabled,
-                                       mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k],
-                                       mode_lib->vba.DynamicMetadataTransmittedBytes[k],
                                        v->UrgentLatency,
                                        v->UrgentExtraLatency,
-                                       mode_lib->vba.TCalc,
+                                       v->TCalc,
                                        v->PDEAndMetaPTEBytesFrame[k],
                                        v->MetaRowByte[k],
                                        v->PixelPTEBytesPerRow[k],
@@ -792,8 +780,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                                        v->MaxNumSwathC[k],
                                        v->swath_width_luma_ub[k],
                                        v->swath_width_chroma_ub[k],
-                                       mode_lib->vba.SwathHeightY[k],
-                                       mode_lib->vba.SwathHeightC[k],
+                                       v->SwathHeightY[k],
+                                       v->SwathHeightC[k],
                                        TWait,
                                        /* Output */
                                        &v->DSTXAfterScaler[k],
@@ -1163,58 +1151,28 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.mmSOCParameters.SMNLatency = mode_lib->vba.SMNLatency;
 
                dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
-                       mode_lib->vba.USRRetrainingRequiredFinal,
-                       mode_lib->vba.UsesMALLForPStateChange,
-                       mode_lib->vba.PrefetchModePerState[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb],
-                       mode_lib->vba.NumberOfActiveSurfaces,
-                       mode_lib->vba.MaxLineBufferLines,
-                       mode_lib->vba.LineBufferSizeFinal,
-                       mode_lib->vba.WritebackInterfaceBufferSize,
-                       mode_lib->vba.DCFCLK,
-                       mode_lib->vba.ReturnBW,
-                       mode_lib->vba.SynchronizeTimingsFinal,
-                       mode_lib->vba.SynchronizeDRRDisplaysForUCLKPStateChangeFinal,
-                       mode_lib->vba.DRRDisplay,
-                       v->dpte_group_bytes,
-                       v->meta_row_height,
-                       v->meta_row_height_chroma,
+                       v,
+                       v->PrefetchModePerState[v->VoltageLevel][v->maxMpcComb],
+                       v->DCFCLK,
+                       v->ReturnBW,
                        v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.mmSOCParameters,
-                       mode_lib->vba.WritebackChunkSize,
-                       mode_lib->vba.SOCCLK,
+                       v->SOCCLK,
                        v->DCFCLKDeepSleep,
-                       mode_lib->vba.DETBufferSizeY,
-                       mode_lib->vba.DETBufferSizeC,
-                       mode_lib->vba.SwathHeightY,
-                       mode_lib->vba.SwathHeightC,
-                       mode_lib->vba.LBBitPerPixel,
+                       v->DETBufferSizeY,
+                       v->DETBufferSizeC,
+                       v->SwathHeightY,
+                       v->SwathHeightC,
                        v->SwathWidthY,
                        v->SwathWidthC,
-                       mode_lib->vba.HRatio,
-                       mode_lib->vba.HRatioChroma,
-                       mode_lib->vba.vtaps,
-                       mode_lib->vba.VTAPsChroma,
-                       mode_lib->vba.VRatio,
-                       mode_lib->vba.VRatioChroma,
-                       mode_lib->vba.HTotal,
-                       mode_lib->vba.VTotal,
-                       mode_lib->vba.VActive,
-                       mode_lib->vba.PixelClock,
-                       mode_lib->vba.BlendingAndTiming,
-                       mode_lib->vba.DPPPerPlane,
+                       v->DPPPerPlane,
                        v->BytePerPixelDETY,
                        v->BytePerPixelDETC,
                        v->DSTXAfterScaler,
                        v->DSTYAfterScaler,
-                       mode_lib->vba.WritebackEnable,
-                       mode_lib->vba.WritebackPixelFormat,
-                       mode_lib->vba.WritebackDestinationWidth,
-                       mode_lib->vba.WritebackDestinationHeight,
-                       mode_lib->vba.WritebackSourceHeight,
                        v->UnboundedRequestEnabled,
                        v->CompressedBufferSizeInkByte,
 
                        /* Output */
-                       &v->Watermark,
                        &v->dummy_vars.DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation.dummy_dramchange_support,
                        v->MaxActiveDRAMClockChangeLatencySupported,
                        v->SubViewportLinesNeededInMALL,
@@ -1806,10 +1764,10 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                &mode_lib->vba.Read256BlockHeightC[k],
                                &mode_lib->vba.Read256BlockWidthY[k],
                                &mode_lib->vba.Read256BlockWidthC[k],
-                               &mode_lib->vba.MicroTileHeightY[k],
-                               &mode_lib->vba.MicroTileHeightC[k],
-                               &mode_lib->vba.MicroTileWidthY[k],
-                               &mode_lib->vba.MicroTileWidthC[k]);
+                               &mode_lib->vba.MacroTileHeightY[k],
+                               &mode_lib->vba.MacroTileHeightC[k],
+                               &mode_lib->vba.MacroTileWidthY[k],
+                               &mode_lib->vba.MacroTileWidthC[k]);
        }
 
        /*Bandwidth Support Check*/
@@ -2034,6 +1992,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                dml32_CalculateODMMode(
                                                mode_lib->vba.MaximumPixelsPerLinePerDSCUnit,
                                                mode_lib->vba.HActive[k],
+                                               mode_lib->vba.OutputFormat[k],
                                                mode_lib->vba.Output[k],
                                                mode_lib->vba.ODMUse[k],
                                                mode_lib->vba.MaxDispclk[i],
@@ -2055,6 +2014,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                dml32_CalculateODMMode(
                                                mode_lib->vba.MaximumPixelsPerLinePerDSCUnit,
                                                mode_lib->vba.HActive[k],
+                                               mode_lib->vba.OutputFormat[k],
                                                mode_lib->vba.Output[k],
                                                mode_lib->vba.ODMUse[k],
                                                mode_lib->vba.MaxDispclk[i],
@@ -2659,10 +2619,10 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                        mode_lib->vba.Read256BlockWidthC,
                        mode_lib->vba.Read256BlockHeightY,
                        mode_lib->vba.Read256BlockHeightC,
-                       mode_lib->vba.MicroTileWidthY,
-                       mode_lib->vba.MicroTileWidthC,
-                       mode_lib->vba.MicroTileHeightY,
-                       mode_lib->vba.MicroTileHeightC,
+                       mode_lib->vba.MacroTileWidthY,
+                       mode_lib->vba.MacroTileWidthC,
+                       mode_lib->vba.MacroTileHeightY,
+                       mode_lib->vba.MacroTileHeightC,
 
                        /* Output */
                        mode_lib->vba.SurfaceSizeInMALL,
@@ -2709,10 +2669,10 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockHeight256BytesY = mode_lib->vba.Read256BlockHeightY[k];
                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockWidth256BytesC = mode_lib->vba.Read256BlockWidthC[k];
                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockHeight256BytesC = mode_lib->vba.Read256BlockHeightC[k];
-                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockWidthY = mode_lib->vba.MicroTileWidthY[k];
-                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockHeightY = mode_lib->vba.MicroTileHeightY[k];
-                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockWidthC = mode_lib->vba.MicroTileWidthC[k];
-                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockHeightC = mode_lib->vba.MicroTileHeightC[k];
+                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockWidthY = mode_lib->vba.MacroTileWidthY[k];
+                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockHeightY = mode_lib->vba.MacroTileHeightY[k];
+                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockWidthC = mode_lib->vba.MacroTileWidthC[k];
+                               v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].BlockHeightC = mode_lib->vba.MacroTileHeightC[k];
                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].InterlaceEnable = mode_lib->vba.Interlace[k];
                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].HTotal = mode_lib->vba.HTotal[k];
                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.SurfParameters[k].DCCEnable = mode_lib->vba.DCCEnable[k];
@@ -3258,63 +3218,47 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 
                                        mode_lib->vba.NoTimeForPrefetch[i][j][k] =
                                                dml32_CalculatePrefetchSchedule(
+                                                       v,
+                                                       k,
                                                        v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.HostVMInefficiencyFactor,
                                                        &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.myPipe,
-                                                       mode_lib->vba.DSCDelayPerState[i][k],
-                                                       mode_lib->vba.DPPCLKDelaySubtotal +
-                                                               mode_lib->vba.DPPCLKDelayCNVCFormater,
-                                                       mode_lib->vba.DPPCLKDelaySCL,
-                                                       mode_lib->vba.DPPCLKDelaySCLLBOnly,
-                                                       mode_lib->vba.DPPCLKDelayCNVCCursor,
-                                                       mode_lib->vba.DISPCLKDelaySubtotal,
-                                                       mode_lib->vba.SwathWidthYThisState[k] /
-                                                               mode_lib->vba.HRatio[k],
-                                                       mode_lib->vba.OutputFormat[k],
-                                                       mode_lib->vba.MaxInterDCNTileRepeaters,
-                                                       dml_min(mode_lib->vba.MaxVStartup,
-                                                                       mode_lib->vba.MaximumVStartup[i][j][k]),
-                                                       mode_lib->vba.MaximumVStartup[i][j][k],
-                                                       mode_lib->vba.GPUVMMaxPageTableLevels,
-                                                       mode_lib->vba.GPUVMEnable, mode_lib->vba.HostVMEnable,
-                                                       mode_lib->vba.HostVMMaxNonCachedPageTableLevels,
-                                                       mode_lib->vba.HostVMMinPageSize,
-                                                       mode_lib->vba.DynamicMetadataEnable[k],
-                                                       mode_lib->vba.DynamicMetadataVMEnabled,
-                                                       mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k],
-                                                       mode_lib->vba.DynamicMetadataTransmittedBytes[k],
-                                                       mode_lib->vba.UrgLatency[i],
-                                                       mode_lib->vba.ExtraLatency,
-                                                       mode_lib->vba.TimeCalc,
-                                                       mode_lib->vba.PDEAndMetaPTEBytesPerFrame[i][j][k],
-                                                       mode_lib->vba.MetaRowBytes[i][j][k],
-                                                       mode_lib->vba.DPTEBytesPerRow[i][j][k],
-                                                       mode_lib->vba.PrefetchLinesY[i][j][k],
-                                                       mode_lib->vba.SwathWidthYThisState[k],
-                                                       mode_lib->vba.PrefillY[k],
-                                                       mode_lib->vba.MaxNumSwY[k],
-                                                       mode_lib->vba.PrefetchLinesC[i][j][k],
-                                                       mode_lib->vba.SwathWidthCThisState[k],
-                                                       mode_lib->vba.PrefillC[k],
-                                                       mode_lib->vba.MaxNumSwC[k],
-                                                       mode_lib->vba.swath_width_luma_ub_this_state[k],
-                                                       mode_lib->vba.swath_width_chroma_ub_this_state[k],
-                                                       mode_lib->vba.SwathHeightYThisState[k],
-                                                       mode_lib->vba.SwathHeightCThisState[k], mode_lib->vba.TWait,
+                                                       v->DSCDelayPerState[i][k],
+                                                       v->SwathWidthYThisState[k] / v->HRatio[k],
+                                                       dml_min(v->MaxVStartup, v->MaximumVStartup[i][j][k]),
+                                                       v->MaximumVStartup[i][j][k],
+                                                       v->UrgLatency[i],
+                                                       v->ExtraLatency,
+                                                       v->TimeCalc,
+                                                       v->PDEAndMetaPTEBytesPerFrame[i][j][k],
+                                                       v->MetaRowBytes[i][j][k],
+                                                       v->DPTEBytesPerRow[i][j][k],
+                                                       v->PrefetchLinesY[i][j][k],
+                                                       v->SwathWidthYThisState[k],
+                                                       v->PrefillY[k],
+                                                       v->MaxNumSwY[k],
+                                                       v->PrefetchLinesC[i][j][k],
+                                                       v->SwathWidthCThisState[k],
+                                                       v->PrefillC[k],
+                                                       v->MaxNumSwC[k],
+                                                       v->swath_width_luma_ub_this_state[k],
+                                                       v->swath_width_chroma_ub_this_state[k],
+                                                       v->SwathHeightYThisState[k],
+                                                       v->SwathHeightCThisState[k], v->TWait,
 
                                                        /* Output */
                                                        &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTXAfterScaler[k],
                                                        &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTYAfterScaler[k],
-                                                       &mode_lib->vba.LineTimesForPrefetch[k],
-                                                       &mode_lib->vba.PrefetchBW[k],
-                                                       &mode_lib->vba.LinesForMetaPTE[k],
-                                                       &mode_lib->vba.LinesForMetaAndDPTERow[k],
-                                                       &mode_lib->vba.VRatioPreY[i][j][k],
-                                                       &mode_lib->vba.VRatioPreC[i][j][k],
-                                                       &mode_lib->vba.RequiredPrefetchPixelDataBWLuma[0][0][k],
-                                                       &mode_lib->vba.RequiredPrefetchPixelDataBWChroma[0][0][k],
-                                                       &mode_lib->vba.NoTimeForDynamicMetadata[i][j][k],
-                                                       &mode_lib->vba.Tno_bw[k],
-                                                       &mode_lib->vba.prefetch_vmrow_bw[k],
+                                                       &v->LineTimesForPrefetch[k],
+                                                       &v->PrefetchBW[k],
+                                                       &v->LinesForMetaPTE[k],
+                                                       &v->LinesForMetaAndDPTERow[k],
+                                                       &v->VRatioPreY[i][j][k],
+                                                       &v->VRatioPreC[i][j][k],
+                                                       &v->RequiredPrefetchPixelDataBWLuma[0][0][k],
+                                                       &v->RequiredPrefetchPixelDataBWChroma[0][0][k],
+                                                       &v->NoTimeForDynamicMetadata[i][j][k],
+                                                       &v->Tno_bw[k],
+                                                       &v->prefetch_vmrow_bw[k],
                                                        &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_single[0],         // double *Tdmdl_vm
                                                        &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_single[1],         // double *Tdmdl
                                                        &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_single[2],         // double *TSetup
@@ -3557,62 +3501,32 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
 
                        {
                                dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
-                                               mode_lib->vba.USRRetrainingRequiredFinal,
-                                               mode_lib->vba.UsesMALLForPStateChange,
-                                               mode_lib->vba.PrefetchModePerState[i][j],
-                                               mode_lib->vba.NumberOfActiveSurfaces,
-                                               mode_lib->vba.MaxLineBufferLines,
-                                               mode_lib->vba.LineBufferSizeFinal,
-                                               mode_lib->vba.WritebackInterfaceBufferSize,
-                                               mode_lib->vba.DCFCLKState[i][j],
-                                               mode_lib->vba.ReturnBWPerState[i][j],
-                                               mode_lib->vba.SynchronizeTimingsFinal,
-                                               mode_lib->vba.SynchronizeDRRDisplaysForUCLKPStateChangeFinal,
-                                               mode_lib->vba.DRRDisplay,
-                                               mode_lib->vba.dpte_group_bytes,
-                                               mode_lib->vba.meta_row_height,
-                                               mode_lib->vba.meta_row_height_chroma,
+                                               v,
+                                               v->PrefetchModePerState[i][j],
+                                               v->DCFCLKState[i][j],
+                                               v->ReturnBWPerState[i][j],
                                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.mSOCParameters,
-                                               mode_lib->vba.WritebackChunkSize,
-                                               mode_lib->vba.SOCCLKPerState[i],
-                                               mode_lib->vba.ProjectedDCFCLKDeepSleep[i][j],
-                                               mode_lib->vba.DETBufferSizeYThisState,
-                                               mode_lib->vba.DETBufferSizeCThisState,
-                                               mode_lib->vba.SwathHeightYThisState,
-                                               mode_lib->vba.SwathHeightCThisState,
-                                               mode_lib->vba.LBBitPerPixel,
-                                               mode_lib->vba.SwathWidthYThisState, // 24
-                                               mode_lib->vba.SwathWidthCThisState,
-                                               mode_lib->vba.HRatio,
-                                               mode_lib->vba.HRatioChroma,
-                                               mode_lib->vba.vtaps,
-                                               mode_lib->vba.VTAPsChroma,
-                                               mode_lib->vba.VRatio,
-                                               mode_lib->vba.VRatioChroma,
-                                               mode_lib->vba.HTotal,
-                                               mode_lib->vba.VTotal,
-                                               mode_lib->vba.VActive,
-                                               mode_lib->vba.PixelClock,
-                                               mode_lib->vba.BlendingAndTiming,
-                                               mode_lib->vba.NoOfDPPThisState,
-                                               mode_lib->vba.BytePerPixelInDETY,
-                                               mode_lib->vba.BytePerPixelInDETC,
+                                               v->SOCCLKPerState[i],
+                                               v->ProjectedDCFCLKDeepSleep[i][j],
+                                               v->DETBufferSizeYThisState,
+                                               v->DETBufferSizeCThisState,
+                                               v->SwathHeightYThisState,
+                                               v->SwathHeightCThisState,
+                                               v->SwathWidthYThisState, // 24
+                                               v->SwathWidthCThisState,
+                                               v->NoOfDPPThisState,
+                                               v->BytePerPixelInDETY,
+                                               v->BytePerPixelInDETC,
                                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTXAfterScaler,
                                                v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.DSTYAfterScaler,
-                                               mode_lib->vba.WritebackEnable,
-                                               mode_lib->vba.WritebackPixelFormat,
-                                               mode_lib->vba.WritebackDestinationWidth,
-                                               mode_lib->vba.WritebackDestinationHeight,
-                                               mode_lib->vba.WritebackSourceHeight,
-                                               mode_lib->vba.UnboundedRequestEnabledThisState,
-                                               mode_lib->vba.CompressedBufferSizeInkByteThisState,
+                                               v->UnboundedRequestEnabledThisState,
+                                               v->CompressedBufferSizeInkByteThisState,
 
                                                /* Output */
-                                               &mode_lib->vba.Watermark, // Store the values in vba
-                                               &mode_lib->vba.DRAMClockChangeSupport[i][j],
+                                               &v->DRAMClockChangeSupport[i][j],
                                                &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_single2[0], // double *MaxActiveDRAMClockChangeLatencySupported
                                                &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_integer[0], // Long SubViewportLinesNeededInMALL[]
-                                               &mode_lib->vba.FCLKChangeSupport[i][j],
+                                               &v->FCLKChangeSupport[i][j],
                                                &v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.dummy_single2[1], // double *MinActiveFCLKChangeLatencySupported
                                                &mode_lib->vba.USRRetrainingSupport[i][j],
                                                mode_lib->vba.ActiveDRAMClockChangeLatencyMargin);
index 05fc14a..365d290 100644 (file)
@@ -27,6 +27,8 @@
 #include "display_mode_vba_32.h"
 #include "../display_mode_lib.h"
 
+#define DCN32_MAX_FMT_420_BUFFER_WIDTH 4096
+
 unsigned int dml32_dscceComputeDelay(
                unsigned int bpc,
                double BPP,
@@ -1182,6 +1184,7 @@ void dml32_CalculateDETBufferSize(
 void dml32_CalculateODMMode(
                unsigned int MaximumPixelsPerLinePerDSCUnit,
                unsigned int HActive,
+               enum output_format_class OutFormat,
                enum output_encoder_class Output,
                enum odm_combine_policy ODMUse,
                double StateDispclk,
@@ -1253,6 +1256,29 @@ void dml32_CalculateODMMode(
                else
                        *TotalAvailablePipesSupport = false;
        }
+       if (OutFormat == dm_420 && HActive > DCN32_MAX_FMT_420_BUFFER_WIDTH &&
+                       ODMUse != dm_odm_combine_policy_4to1) {
+               if (HActive > DCN32_MAX_FMT_420_BUFFER_WIDTH * 4) {
+                       *ODMMode = dm_odm_combine_mode_disabled;
+                       *NumberOfDPP = 0;
+                       *TotalAvailablePipesSupport = false;
+               } else if (HActive > DCN32_MAX_FMT_420_BUFFER_WIDTH * 2 ||
+                               *ODMMode == dm_odm_combine_mode_4to1) {
+                       *ODMMode = dm_odm_combine_mode_4to1;
+                       *RequiredDISPCLKPerSurface = SurfaceRequiredDISPCLKWithODMCombineFourToOne;
+                       *NumberOfDPP = 4;
+               } else {
+                       *ODMMode = dm_odm_combine_mode_2to1;
+                       *RequiredDISPCLKPerSurface = SurfaceRequiredDISPCLKWithODMCombineTwoToOne;
+                       *NumberOfDPP = 2;
+               }
+       }
+       if (Output == dm_hdmi && OutFormat == dm_420 &&
+                       HActive > DCN32_MAX_FMT_420_BUFFER_WIDTH) {
+               *ODMMode = dm_odm_combine_mode_disabled;
+               *NumberOfDPP = 0;
+               *TotalAvailablePipesSupport = false;
+       }
 }
 
 double dml32_CalculateRequiredDispclk(
@@ -3363,28 +3389,14 @@ double dml32_CalculateExtraLatency(
 } // CalculateExtraLatency
 
 bool dml32_CalculatePrefetchSchedule(
+               struct vba_vars_st *v,
+               unsigned int k,
                double HostVMInefficiencyFactor,
                DmlPipe *myPipe,
                unsigned int DSCDelay,
-               double DPPCLKDelaySubtotalPlusCNVCFormater,
-               double DPPCLKDelaySCL,
-               double DPPCLKDelaySCLLBOnly,
-               double DPPCLKDelayCNVCCursor,
-               double DISPCLKDelaySubtotal,
                unsigned int DPP_RECOUT_WIDTH,
-               enum output_format_class OutputFormat,
-               unsigned int MaxInterDCNTileRepeaters,
                unsigned int VStartup,
                unsigned int MaxVStartup,
-               unsigned int GPUVMPageTableLevels,
-               bool GPUVMEnable,
-               bool HostVMEnable,
-               unsigned int HostVMMaxNonCachedPageTableLevels,
-               double HostVMMinPageSize,
-               bool DynamicMetadataEnable,
-               bool DynamicMetadataVMEnabled,
-               int DynamicMetadataLinesBeforeActiveRequired,
-               unsigned int DynamicMetadataTransmittedBytes,
                double UrgentLatency,
                double UrgentExtraLatency,
                double TCalc,
@@ -3425,6 +3437,7 @@ bool dml32_CalculatePrefetchSchedule(
                double   *VUpdateWidthPix,
                double   *VReadyOffsetPix)
 {
+       double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater;
        bool MyError = false;
        unsigned int DPPCycles, DISPCLKCycles;
        double DSTTotalPixelsAfterScaler;
@@ -3461,27 +3474,27 @@ bool dml32_CalculatePrefetchSchedule(
        double  Tsw_est1 = 0;
        double  Tsw_est3 = 0;
 
-       if (GPUVMEnable == true && HostVMEnable == true)
-               HostVMDynamicLevelsTrips = HostVMMaxNonCachedPageTableLevels;
+       if (v->GPUVMEnable == true && v->HostVMEnable == true)
+               HostVMDynamicLevelsTrips = v->HostVMMaxNonCachedPageTableLevels;
        else
                HostVMDynamicLevelsTrips = 0;
 #ifdef __DML_VBA_DEBUG__
-       dml_print("DML::%s: GPUVMEnable = %d\n", __func__, GPUVMEnable);
-       dml_print("DML::%s: GPUVMPageTableLevels = %d\n", __func__, GPUVMPageTableLevels);
+       dml_print("DML::%s: v->GPUVMEnable = %d\n", __func__, v->GPUVMEnable);
+       dml_print("DML::%s: v->GPUVMMaxPageTableLevels = %d\n", __func__, v->GPUVMMaxPageTableLevels);
        dml_print("DML::%s: DCCEnable = %d\n", __func__, myPipe->DCCEnable);
-       dml_print("DML::%s: HostVMEnable=%d HostVMInefficiencyFactor=%f\n",
-                       __func__, HostVMEnable, HostVMInefficiencyFactor);
+       dml_print("DML::%s: v->HostVMEnable=%d HostVMInefficiencyFactor=%f\n",
+                       __func__, v->HostVMEnable, HostVMInefficiencyFactor);
 #endif
        dml32_CalculateVUpdateAndDynamicMetadataParameters(
-                       MaxInterDCNTileRepeaters,
+                       v->MaxInterDCNTileRepeaters,
                        myPipe->Dppclk,
                        myPipe->Dispclk,
                        myPipe->DCFClkDeepSleep,
                        myPipe->PixelClock,
                        myPipe->HTotal,
                        myPipe->VBlank,
-                       DynamicMetadataTransmittedBytes,
-                       DynamicMetadataLinesBeforeActiveRequired,
+                       v->DynamicMetadataTransmittedBytes[k],
+                       v->DynamicMetadataLinesBeforeActiveRequired[k],
                        myPipe->InterlaceEnable,
                        myPipe->ProgressiveToInterlaceUnitInOPP,
                        TSetup,
@@ -3496,19 +3509,19 @@ bool dml32_CalculatePrefetchSchedule(
 
        LineTime = myPipe->HTotal / myPipe->PixelClock;
        trip_to_mem = UrgentLatency;
-       Tvm_trips = UrgentExtraLatency + trip_to_mem * (GPUVMPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1);
+       Tvm_trips = UrgentExtraLatency + trip_to_mem * (v->GPUVMMaxPageTableLevels * (HostVMDynamicLevelsTrips + 1) - 1);
 
-       if (DynamicMetadataVMEnabled == true)
+       if (v->DynamicMetadataVMEnabled == true)
                *Tdmdl = TWait + Tvm_trips + trip_to_mem;
        else
                *Tdmdl = TWait + UrgentExtraLatency;
 
 #ifdef __DML_VBA_ALLOW_DELTA__
-       if (DynamicMetadataEnable == false)
+       if (v->DynamicMetadataEnable[k] == false)
                *Tdmdl = 0.0;
 #endif
 
-       if (DynamicMetadataEnable == true) {
+       if (v->DynamicMetadataEnable[k] == true) {
                if (VStartup * LineTime < *TSetup + *Tdmdl + Tdmbf + Tdmec + Tdmsks) {
                        *NotEnoughTimeForDynamicMetadata = true;
 #ifdef __DML_VBA_DEBUG__
@@ -3528,17 +3541,17 @@ bool dml32_CalculatePrefetchSchedule(
                *NotEnoughTimeForDynamicMetadata = false;
        }
 
-       *Tdmdl_vm =  (DynamicMetadataEnable == true && DynamicMetadataVMEnabled == true &&
-                       GPUVMEnable == true ? TWait + Tvm_trips : 0);
+       *Tdmdl_vm =  (v->DynamicMetadataEnable[k] == true && v->DynamicMetadataVMEnabled == true &&
+                       v->GPUVMEnable == true ? TWait + Tvm_trips : 0);
 
        if (myPipe->ScalerEnabled)
-               DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + DPPCLKDelaySCL;
+               DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + v->DPPCLKDelaySCL;
        else
-               DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + DPPCLKDelaySCLLBOnly;
+               DPPCycles = DPPCLKDelaySubtotalPlusCNVCFormater + v->DPPCLKDelaySCLLBOnly;
 
-       DPPCycles = DPPCycles + myPipe->NumberOfCursors * DPPCLKDelayCNVCCursor;
+       DPPCycles = DPPCycles + myPipe->NumberOfCursors * v->DPPCLKDelayCNVCCursor;
 
-       DISPCLKCycles = DISPCLKDelaySubtotal;
+       DISPCLKCycles = v->DISPCLKDelaySubtotal;
 
        if (myPipe->Dppclk == 0.0 || myPipe->Dispclk == 0.0)
                return true;
@@ -3564,7 +3577,7 @@ bool dml32_CalculatePrefetchSchedule(
        dml_print("DML::%s: DSTXAfterScaler: %d\n", __func__,  *DSTXAfterScaler);
 #endif
 
-       if (OutputFormat == dm_420 || (myPipe->InterlaceEnable && myPipe->ProgressiveToInterlaceUnitInOPP))
+       if (v->OutputFormat[k] == dm_420 || (myPipe->InterlaceEnable && myPipe->ProgressiveToInterlaceUnitInOPP))
                *DSTYAfterScaler = 1;
        else
                *DSTYAfterScaler = 0;
@@ -3581,13 +3594,13 @@ bool dml32_CalculatePrefetchSchedule(
 
        Tr0_trips = trip_to_mem * (HostVMDynamicLevelsTrips + 1);
 
-       if (GPUVMEnable == true) {
+       if (v->GPUVMEnable == true) {
                Tvm_trips_rounded = dml_ceil(4.0 * Tvm_trips / LineTime, 1.0) / 4.0 * LineTime;
                Tr0_trips_rounded = dml_ceil(4.0 * Tr0_trips / LineTime, 1.0) / 4.0 * LineTime;
-               if (GPUVMPageTableLevels >= 3) {
+               if (v->GPUVMMaxPageTableLevels >= 3) {
                        *Tno_bw = UrgentExtraLatency + trip_to_mem *
-                                       (double) ((GPUVMPageTableLevels - 2) * (HostVMDynamicLevelsTrips + 1) - 1);
-               } else if (GPUVMPageTableLevels == 1 && myPipe->DCCEnable != true) {
+                                       (double) ((v->GPUVMMaxPageTableLevels - 2) * (HostVMDynamicLevelsTrips + 1) - 1);
+               } else if (v->GPUVMMaxPageTableLevels == 1 && myPipe->DCCEnable != true) {
                        Tr0_trips_rounded = dml_ceil(4.0 * UrgentExtraLatency / LineTime, 1.0) /
                                        4.0 * LineTime; // VBA_ERROR
                        *Tno_bw = UrgentExtraLatency;
@@ -3622,7 +3635,7 @@ bool dml32_CalculatePrefetchSchedule(
        min_Lsw = dml_max(min_Lsw, 1.0);
        Lsw_oto = dml_ceil(4.0 * dml_max(prefetch_sw_bytes / prefetch_bw_oto / LineTime, min_Lsw), 1.0) / 4.0;
 
-       if (GPUVMEnable == true) {
+       if (v->GPUVMEnable == true) {
                Tvm_oto = dml_max3(
                                Tvm_trips,
                                *Tno_bw + PDEAndMetaPTEBytesFrame * HostVMInefficiencyFactor / prefetch_bw_oto,
@@ -3630,7 +3643,7 @@ bool dml32_CalculatePrefetchSchedule(
        } else
                Tvm_oto = LineTime / 4.0;
 
-       if ((GPUVMEnable == true || myPipe->DCCEnable == true)) {
+       if ((v->GPUVMEnable == true || myPipe->DCCEnable == true)) {
                Tr0_oto = dml_max4(
                                Tr0_trips,
                                (MetaRowByte + PixelPTEBytesPerRow * HostVMInefficiencyFactor) / prefetch_bw_oto,
@@ -3833,7 +3846,7 @@ bool dml32_CalculatePrefetchSchedule(
 #endif
 
                        if (prefetch_bw_equ > 0) {
-                               if (GPUVMEnable == true) {
+                               if (v->GPUVMEnable == true) {
                                        Tvm_equ = dml_max3(*Tno_bw + PDEAndMetaPTEBytesFrame *
                                                        HostVMInefficiencyFactor / prefetch_bw_equ,
                                                        Tvm_trips, LineTime / 4);
@@ -3841,7 +3854,7 @@ bool dml32_CalculatePrefetchSchedule(
                                        Tvm_equ = LineTime / 4;
                                }
 
-                               if ((GPUVMEnable == true || myPipe->DCCEnable == true)) {
+                               if ((v->GPUVMEnable == true || myPipe->DCCEnable == true)) {
                                        Tr0_equ = dml_max4((MetaRowByte + PixelPTEBytesPerRow *
                                                        HostVMInefficiencyFactor) / prefetch_bw_equ, Tr0_trips,
                                                        (LineTime - Tvm_equ) / 2, LineTime / 4);
@@ -4206,58 +4219,28 @@ void dml32_CalculateFlipSchedule(
 } // CalculateFlipSchedule
 
 void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
-               bool USRRetrainingRequiredFinal,
-               enum dm_use_mall_for_pstate_change_mode UseMALLForPStateChange[],
+               struct vba_vars_st *v,
                unsigned int PrefetchMode,
-               unsigned int NumberOfActiveSurfaces,
-               unsigned int MaxLineBufferLines,
-               unsigned int LineBufferSize,
-               unsigned int WritebackInterfaceBufferSize,
                double DCFCLK,
                double ReturnBW,
-               bool SynchronizeTimingsFinal,
-               bool SynchronizeDRRDisplaysForUCLKPStateChangeFinal,
-               bool DRRDisplay[],
-               unsigned int dpte_group_bytes[],
-               unsigned int meta_row_height[],
-               unsigned int meta_row_height_chroma[],
                SOCParametersList mmSOCParameters,
-               unsigned int WritebackChunkSize,
                double SOCCLK,
                double DCFClkDeepSleep,
                unsigned int DETBufferSizeY[],
                unsigned int DETBufferSizeC[],
                unsigned int SwathHeightY[],
                unsigned int SwathHeightC[],
-               unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double SwathWidthC[],
-               double HRatio[],
-               double HRatioChroma[],
-               unsigned int VTaps[],
-               unsigned int VTapsChroma[],
-               double VRatio[],
-               double VRatioChroma[],
-               unsigned int HTotal[],
-               unsigned int VTotal[],
-               unsigned int VActive[],
-               double PixelClock[],
-               unsigned int BlendingAndTiming[],
                unsigned int DPPPerSurface[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                double DSTXAfterScaler[],
                double DSTYAfterScaler[],
-               bool WritebackEnable[],
-               enum source_format_class WritebackPixelFormat[],
-               double WritebackDestinationWidth[],
-               double WritebackDestinationHeight[],
-               double WritebackSourceHeight[],
                bool UnboundedRequestEnabled,
                unsigned int CompressedBufferSizeInkByte,
 
                /* Output */
-               Watermarks *Watermark,
                enum clock_change_support *DRAMClockChangeSupport,
                double MaxActiveDRAMClockChangeLatencySupported[],
                unsigned int SubViewportLinesNeededInMALL[],
@@ -4299,136 +4282,136 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
        unsigned int LBLatencyHidingSourceLinesY[DC__NUM_DPP__MAX];
        unsigned int LBLatencyHidingSourceLinesC[DC__NUM_DPP__MAX];
 
-       Watermark->UrgentWatermark = mmSOCParameters.UrgentLatency + mmSOCParameters.ExtraLatency;
-       Watermark->USRRetrainingWatermark = mmSOCParameters.UrgentLatency + mmSOCParameters.ExtraLatency
+       v->Watermark.UrgentWatermark = mmSOCParameters.UrgentLatency + mmSOCParameters.ExtraLatency;
+       v->Watermark.USRRetrainingWatermark = mmSOCParameters.UrgentLatency + mmSOCParameters.ExtraLatency
                        + mmSOCParameters.USRRetrainingLatency + mmSOCParameters.SMNLatency;
-       Watermark->DRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency + Watermark->UrgentWatermark;
-       Watermark->FCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency + Watermark->UrgentWatermark;
-       Watermark->StutterExitWatermark = mmSOCParameters.SRExitTime + mmSOCParameters.ExtraLatency
+       v->Watermark.DRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency + v->Watermark.UrgentWatermark;
+       v->Watermark.FCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency + v->Watermark.UrgentWatermark;
+       v->Watermark.StutterExitWatermark = mmSOCParameters.SRExitTime + mmSOCParameters.ExtraLatency
                        + 10 / DCFClkDeepSleep;
-       Watermark->StutterEnterPlusExitWatermark = mmSOCParameters.SREnterPlusExitTime + mmSOCParameters.ExtraLatency
+       v->Watermark.StutterEnterPlusExitWatermark = mmSOCParameters.SREnterPlusExitTime + mmSOCParameters.ExtraLatency
                        + 10 / DCFClkDeepSleep;
-       Watermark->Z8StutterExitWatermark = mmSOCParameters.SRExitZ8Time + mmSOCParameters.ExtraLatency
+       v->Watermark.Z8StutterExitWatermark = mmSOCParameters.SRExitZ8Time + mmSOCParameters.ExtraLatency
                        + 10 / DCFClkDeepSleep;
-       Watermark->Z8StutterEnterPlusExitWatermark = mmSOCParameters.SREnterPlusExitZ8Time
+       v->Watermark.Z8StutterEnterPlusExitWatermark = mmSOCParameters.SREnterPlusExitZ8Time
                        + mmSOCParameters.ExtraLatency + 10 / DCFClkDeepSleep;
 
 #ifdef __DML_VBA_DEBUG__
        dml_print("DML::%s: UrgentLatency = %f\n", __func__, mmSOCParameters.UrgentLatency);
        dml_print("DML::%s: ExtraLatency = %f\n", __func__, mmSOCParameters.ExtraLatency);
        dml_print("DML::%s: DRAMClockChangeLatency = %f\n", __func__, mmSOCParameters.DRAMClockChangeLatency);
-       dml_print("DML::%s: UrgentWatermark = %f\n", __func__, Watermark->UrgentWatermark);
-       dml_print("DML::%s: USRRetrainingWatermark = %f\n", __func__, Watermark->USRRetrainingWatermark);
-       dml_print("DML::%s: DRAMClockChangeWatermark = %f\n", __func__, Watermark->DRAMClockChangeWatermark);
-       dml_print("DML::%s: FCLKChangeWatermark = %f\n", __func__, Watermark->FCLKChangeWatermark);
-       dml_print("DML::%s: StutterExitWatermark = %f\n", __func__, Watermark->StutterExitWatermark);
-       dml_print("DML::%s: StutterEnterPlusExitWatermark = %f\n", __func__, Watermark->StutterEnterPlusExitWatermark);
-       dml_print("DML::%s: Z8StutterExitWatermark = %f\n", __func__, Watermark->Z8StutterExitWatermark);
+       dml_print("DML::%s: UrgentWatermark = %f\n", __func__, v->Watermark.UrgentWatermark);
+       dml_print("DML::%s: USRRetrainingWatermark = %f\n", __func__, v->Watermark.USRRetrainingWatermark);
+       dml_print("DML::%s: DRAMClockChangeWatermark = %f\n", __func__, v->Watermark.DRAMClockChangeWatermark);
+       dml_print("DML::%s: FCLKChangeWatermark = %f\n", __func__, v->Watermark.FCLKChangeWatermark);
+       dml_print("DML::%s: StutterExitWatermark = %f\n", __func__, v->Watermark.StutterExitWatermark);
+       dml_print("DML::%s: StutterEnterPlusExitWatermark = %f\n", __func__, v->Watermark.StutterEnterPlusExitWatermark);
+       dml_print("DML::%s: Z8StutterExitWatermark = %f\n", __func__, v->Watermark.Z8StutterExitWatermark);
        dml_print("DML::%s: Z8StutterEnterPlusExitWatermark = %f\n",
-                       __func__, Watermark->Z8StutterEnterPlusExitWatermark);
+                       __func__, v->Watermark.Z8StutterEnterPlusExitWatermark);
 #endif
 
 
        TotalActiveWriteback = 0;
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
-               if (WritebackEnable[k] == true)
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
+               if (v->WritebackEnable[k] == true)
                        TotalActiveWriteback = TotalActiveWriteback + 1;
        }
 
        if (TotalActiveWriteback <= 1) {
-               Watermark->WritebackUrgentWatermark = mmSOCParameters.WritebackLatency;
+               v->Watermark.WritebackUrgentWatermark = mmSOCParameters.WritebackLatency;
        } else {
-               Watermark->WritebackUrgentWatermark = mmSOCParameters.WritebackLatency
-                               + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
+               v->Watermark.WritebackUrgentWatermark = mmSOCParameters.WritebackLatency
+                               + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
        }
-       if (USRRetrainingRequiredFinal)
-               Watermark->WritebackUrgentWatermark = Watermark->WritebackUrgentWatermark
+       if (v->USRRetrainingRequiredFinal)
+               v->Watermark.WritebackUrgentWatermark = v->Watermark.WritebackUrgentWatermark
                                + mmSOCParameters.USRRetrainingLatency;
 
        if (TotalActiveWriteback <= 1) {
-               Watermark->WritebackDRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency
+               v->Watermark.WritebackDRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency
                                + mmSOCParameters.WritebackLatency;
-               Watermark->WritebackFCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency
+               v->Watermark.WritebackFCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency
                                + mmSOCParameters.WritebackLatency;
        } else {
-               Watermark->WritebackDRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency
-                               + mmSOCParameters.WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
-               Watermark->WritebackFCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency
-                               + mmSOCParameters.WritebackLatency + WritebackChunkSize * 1024 / 32 / SOCCLK;
+               v->Watermark.WritebackDRAMClockChangeWatermark = mmSOCParameters.DRAMClockChangeLatency
+                               + mmSOCParameters.WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
+               v->Watermark.WritebackFCLKChangeWatermark = mmSOCParameters.FCLKChangeLatency
+                               + mmSOCParameters.WritebackLatency + v->WritebackChunkSize * 1024 / 32 / SOCCLK;
        }
 
-       if (USRRetrainingRequiredFinal)
-               Watermark->WritebackDRAMClockChangeWatermark = Watermark->WritebackDRAMClockChangeWatermark
+       if (v->USRRetrainingRequiredFinal)
+               v->Watermark.WritebackDRAMClockChangeWatermark = v->Watermark.WritebackDRAMClockChangeWatermark
                                + mmSOCParameters.USRRetrainingLatency;
 
-       if (USRRetrainingRequiredFinal)
-               Watermark->WritebackFCLKChangeWatermark = Watermark->WritebackFCLKChangeWatermark
+       if (v->USRRetrainingRequiredFinal)
+               v->Watermark.WritebackFCLKChangeWatermark = v->Watermark.WritebackFCLKChangeWatermark
                                + mmSOCParameters.USRRetrainingLatency;
 
 #ifdef __DML_VBA_DEBUG__
        dml_print("DML::%s: WritebackDRAMClockChangeWatermark = %f\n",
-                       __func__, Watermark->WritebackDRAMClockChangeWatermark);
-       dml_print("DML::%s: WritebackFCLKChangeWatermark = %f\n", __func__, Watermark->WritebackFCLKChangeWatermark);
-       dml_print("DML::%s: WritebackUrgentWatermark = %f\n", __func__, Watermark->WritebackUrgentWatermark);
-       dml_print("DML::%s: USRRetrainingRequiredFinal = %d\n", __func__, USRRetrainingRequiredFinal);
+                       __func__, v->Watermark.WritebackDRAMClockChangeWatermark);
+       dml_print("DML::%s: WritebackFCLKChangeWatermark = %f\n", __func__, v->Watermark.WritebackFCLKChangeWatermark);
+       dml_print("DML::%s: WritebackUrgentWatermark = %f\n", __func__, v->Watermark.WritebackUrgentWatermark);
+       dml_print("DML::%s: v->USRRetrainingRequiredFinal = %d\n", __func__, v->USRRetrainingRequiredFinal);
        dml_print("DML::%s: USRRetrainingLatency = %f\n", __func__, mmSOCParameters.USRRetrainingLatency);
 #endif
 
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
-               TotalPixelBW = TotalPixelBW + DPPPerSurface[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k] +
-                               SwathWidthC[k] * BytePerPixelDETC[k] * VRatioChroma[k]) / (HTotal[k] / PixelClock[k]);
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
+               TotalPixelBW = TotalPixelBW + DPPPerSurface[k] * (SwathWidthY[k] * BytePerPixelDETY[k] * v->VRatio[k] +
+                               SwathWidthC[k] * BytePerPixelDETC[k] * v->VRatioChroma[k]) / (v->HTotal[k] / v->PixelClock[k]);
        }
 
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
 
-               LBLatencyHidingSourceLinesY[k] = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(HRatio[k], 1.0)), 1)) - (VTaps[k] - 1);
-               LBLatencyHidingSourceLinesC[k] = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(HRatioChroma[k], 1.0)), 1)) - (VTapsChroma[k] - 1);
+               LBLatencyHidingSourceLinesY[k] = dml_min((double) v->MaxLineBufferLines, dml_floor(v->LineBufferSizeFinal / v->LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(v->HRatio[k], 1.0)), 1)) - (v->vtaps[k] - 1);
+               LBLatencyHidingSourceLinesC[k] = dml_min((double) v->MaxLineBufferLines, dml_floor(v->LineBufferSizeFinal / v->LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(v->HRatioChroma[k], 1.0)), 1)) - (v->VTAPsChroma[k] - 1);
 
 
 #ifdef __DML_VBA_DEBUG__
-               dml_print("DML::%s: k=%d, MaxLineBufferLines = %d\n", __func__, k, MaxLineBufferLines);
-               dml_print("DML::%s: k=%d, LineBufferSize     = %d\n", __func__, k, LineBufferSize);
-               dml_print("DML::%s: k=%d, LBBitPerPixel      = %d\n", __func__, k, LBBitPerPixel[k]);
-               dml_print("DML::%s: k=%d, HRatio             = %f\n", __func__, k, HRatio[k]);
-               dml_print("DML::%s: k=%d, VTaps              = %d\n", __func__, k, VTaps[k]);
+               dml_print("DML::%s: k=%d, v->MaxLineBufferLines = %d\n", __func__, k, v->MaxLineBufferLines);
+               dml_print("DML::%s: k=%d, v->LineBufferSizeFinal     = %d\n", __func__, k, v->LineBufferSizeFinal);
+               dml_print("DML::%s: k=%d, v->LBBitPerPixel      = %d\n", __func__, k, v->LBBitPerPixel[k]);
+               dml_print("DML::%s: k=%d, v->HRatio             = %f\n", __func__, k, v->HRatio[k]);
+               dml_print("DML::%s: k=%d, v->vtaps              = %d\n", __func__, k, v->vtaps[k]);
 #endif
 
-               EffectiveLBLatencyHidingY = LBLatencyHidingSourceLinesY[k] / VRatio[k] * (HTotal[k] / PixelClock[k]);
-               EffectiveLBLatencyHidingC = LBLatencyHidingSourceLinesC[k] / VRatioChroma[k] * (HTotal[k] / PixelClock[k]);
+               EffectiveLBLatencyHidingY = LBLatencyHidingSourceLinesY[k] / v->VRatio[k] * (v->HTotal[k] / v->PixelClock[k]);
+               EffectiveLBLatencyHidingC = LBLatencyHidingSourceLinesC[k] / v->VRatioChroma[k] * (v->HTotal[k] / v->PixelClock[k]);
                EffectiveDETBufferSizeY = DETBufferSizeY[k];
 
                if (UnboundedRequestEnabled) {
                        EffectiveDETBufferSizeY = EffectiveDETBufferSizeY
                                        + CompressedBufferSizeInkByte * 1024
-                                                       * (SwathWidthY[k] * BytePerPixelDETY[k] * VRatio[k])
-                                                       / (HTotal[k] / PixelClock[k]) / TotalPixelBW;
+                                                       * (SwathWidthY[k] * BytePerPixelDETY[k] * v->VRatio[k])
+                                                       / (v->HTotal[k] / v->PixelClock[k]) / TotalPixelBW;
                }
 
                LinesInDETY[k] = (double) EffectiveDETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k];
                LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]);
-               FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k];
+               FullDETBufferingTimeY = LinesInDETYRoundedDownToSwath[k] * (v->HTotal[k] / v->PixelClock[k]) / v->VRatio[k];
 
                ActiveClockChangeLatencyHidingY = EffectiveLBLatencyHidingY + FullDETBufferingTimeY
-                               - (DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k] / PixelClock[k];
+                               - (DSTXAfterScaler[k] / v->HTotal[k] + DSTYAfterScaler[k]) * v->HTotal[k] / v->PixelClock[k];
 
-               if (NumberOfActiveSurfaces > 1) {
+               if (v->NumberOfActiveSurfaces > 1) {
                        ActiveClockChangeLatencyHidingY = ActiveClockChangeLatencyHidingY
-                                       - (1 - 1 / NumberOfActiveSurfaces) * SwathHeightY[k] * HTotal[k]
-                                                       / PixelClock[k] / VRatio[k];
+                                       - (1 - 1 / v->NumberOfActiveSurfaces) * SwathHeightY[k] * v->HTotal[k]
+                                                       / v->PixelClock[k] / v->VRatio[k];
                }
 
                if (BytePerPixelDETC[k] > 0) {
                        LinesInDETC[k] = DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k];
                        LinesInDETCRoundedDownToSwath[k] = dml_floor(LinesInDETC[k], SwathHeightC[k]);
-                       FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k])
-                                       / VRatioChroma[k];
+                       FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath[k] * (v->HTotal[k] / v->PixelClock[k])
+                                       / v->VRatioChroma[k];
                        ActiveClockChangeLatencyHidingC = EffectiveLBLatencyHidingC + FullDETBufferingTimeC
-                                       - (DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) * HTotal[k]
-                                                       / PixelClock[k];
-                       if (NumberOfActiveSurfaces > 1) {
+                                       - (DSTXAfterScaler[k] / v->HTotal[k] + DSTYAfterScaler[k]) * v->HTotal[k]
+                                                       / v->PixelClock[k];
+                       if (v->NumberOfActiveSurfaces > 1) {
                                ActiveClockChangeLatencyHidingC = ActiveClockChangeLatencyHidingC
-                                               - (1 - 1 / NumberOfActiveSurfaces) * SwathHeightC[k] * HTotal[k]
-                                                               / PixelClock[k] / VRatioChroma[k];
+                                               - (1 - 1 / v->NumberOfActiveSurfaces) * SwathHeightC[k] * v->HTotal[k]
+                                                               / v->PixelClock[k] / v->VRatioChroma[k];
                        }
                        ActiveClockChangeLatencyHiding = dml_min(ActiveClockChangeLatencyHidingY,
                                        ActiveClockChangeLatencyHidingC);
@@ -4436,24 +4419,24 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
                        ActiveClockChangeLatencyHiding = ActiveClockChangeLatencyHidingY;
                }
 
-               ActiveDRAMClockChangeLatencyMargin[k] = ActiveClockChangeLatencyHiding - Watermark->UrgentWatermark
-                               - Watermark->DRAMClockChangeWatermark;
-               ActiveFCLKChangeLatencyMargin[k] = ActiveClockChangeLatencyHiding - Watermark->UrgentWatermark
-                               - Watermark->FCLKChangeWatermark;
-               USRRetrainingLatencyMargin[k] = ActiveClockChangeLatencyHiding - Watermark->USRRetrainingWatermark;
-
-               if (WritebackEnable[k]) {
-                       WritebackLatencyHiding = WritebackInterfaceBufferSize * 1024
-                                       / (WritebackDestinationWidth[k] * WritebackDestinationHeight[k]
-                                                       / (WritebackSourceHeight[k] * HTotal[k] / PixelClock[k]) * 4);
-                       if (WritebackPixelFormat[k] == dm_444_64)
+               ActiveDRAMClockChangeLatencyMargin[k] = ActiveClockChangeLatencyHiding - v->Watermark.UrgentWatermark
+                               - v->Watermark.DRAMClockChangeWatermark;
+               ActiveFCLKChangeLatencyMargin[k] = ActiveClockChangeLatencyHiding - v->Watermark.UrgentWatermark
+                               - v->Watermark.FCLKChangeWatermark;
+               USRRetrainingLatencyMargin[k] = ActiveClockChangeLatencyHiding - v->Watermark.USRRetrainingWatermark;
+
+               if (v->WritebackEnable[k]) {
+                       WritebackLatencyHiding = v->WritebackInterfaceBufferSize * 1024
+                                       / (v->WritebackDestinationWidth[k] * v->WritebackDestinationHeight[k]
+                                                       / (v->WritebackSourceHeight[k] * v->HTotal[k] / v->PixelClock[k]) * 4);
+                       if (v->WritebackPixelFormat[k] == dm_444_64)
                                WritebackLatencyHiding = WritebackLatencyHiding / 2;
 
                        WritebackDRAMClockChangeLatencyMargin = WritebackLatencyHiding
-                                       - Watermark->WritebackDRAMClockChangeWatermark;
+                                       - v->Watermark.WritebackDRAMClockChangeWatermark;
 
                        WritebackFCLKChangeLatencyMargin = WritebackLatencyHiding
-                                       - Watermark->WritebackFCLKChangeWatermark;
+                                       - v->Watermark.WritebackFCLKChangeWatermark;
 
                        ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMargin[k],
                                        WritebackFCLKChangeLatencyMargin);
@@ -4461,22 +4444,22 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
                                        WritebackDRAMClockChangeLatencyMargin);
                }
                MaxActiveDRAMClockChangeLatencySupported[k] =
-                               (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_phantom_pipe) ?
+                               (v->UsesMALLForPStateChange[k] == dm_use_mall_pstate_change_phantom_pipe) ?
                                                0 :
                                                (ActiveDRAMClockChangeLatencyMargin[k]
                                                                + mmSOCParameters.DRAMClockChangeLatency);
        }
 
-       for (i = 0; i < NumberOfActiveSurfaces; ++i) {
-               for (j = 0; j < NumberOfActiveSurfaces; ++j) {
+       for (i = 0; i < v->NumberOfActiveSurfaces; ++i) {
+               for (j = 0; j < v->NumberOfActiveSurfaces; ++j) {
                        if (i == j ||
-                                       (BlendingAndTiming[i] == i && BlendingAndTiming[j] == i) ||
-                                       (BlendingAndTiming[j] == j && BlendingAndTiming[i] == j) ||
-                                       (BlendingAndTiming[i] == BlendingAndTiming[j] && BlendingAndTiming[i] != i) ||
-                                       (SynchronizeTimingsFinal && PixelClock[i] == PixelClock[j] &&
-                                       HTotal[i] == HTotal[j] && VTotal[i] == VTotal[j] &&
-                                       VActive[i] == VActive[j]) || (SynchronizeDRRDisplaysForUCLKPStateChangeFinal &&
-                                       (DRRDisplay[i] || DRRDisplay[j]))) {
+                                       (v->BlendingAndTiming[i] == i && v->BlendingAndTiming[j] == i) ||
+                                       (v->BlendingAndTiming[j] == j && v->BlendingAndTiming[i] == j) ||
+                                       (v->BlendingAndTiming[i] == v->BlendingAndTiming[j] && v->BlendingAndTiming[i] != i) ||
+                                       (v->SynchronizeTimingsFinal && v->PixelClock[i] == v->PixelClock[j] &&
+                                       v->HTotal[i] == v->HTotal[j] && v->VTotal[i] == v->VTotal[j] &&
+                                       v->VActive[i] == v->VActive[j]) || (v->SynchronizeDRRDisplaysForUCLKPStateChangeFinal &&
+                                       (v->DRRDisplay[i] || v->DRRDisplay[j]))) {
                                SynchronizedSurfaces[i][j] = true;
                        } else {
                                SynchronizedSurfaces[i][j] = false;
@@ -4484,8 +4467,8 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
                }
        }
 
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
-               if ((UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) &&
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
+               if ((v->UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) &&
                                (!FoundFirstSurfaceWithMinActiveFCLKChangeMargin ||
                                ActiveFCLKChangeLatencyMargin[k] < MinActiveFCLKChangeMargin)) {
                        FoundFirstSurfaceWithMinActiveFCLKChangeMargin = true;
@@ -4497,9 +4480,9 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
        *MinActiveFCLKChangeLatencySupported = MinActiveFCLKChangeMargin + mmSOCParameters.FCLKChangeLatency;
 
        SameTimingForFCLKChange = true;
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
                if (!SynchronizedSurfaces[k][SurfaceWithMinActiveFCLKChangeMargin]) {
-                       if ((UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) &&
+                       if ((v->UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) &&
                                        (SameTimingForFCLKChange ||
                                        ActiveFCLKChangeLatencyMargin[k] <
                                        SecondMinActiveFCLKChangeMarginOneDisplayInVBLank)) {
@@ -4519,17 +4502,17 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
        }
 
        *USRRetrainingSupport = true;
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
-               if ((UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) &&
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
+               if ((v->UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) &&
                                (USRRetrainingLatencyMargin[k] < 0)) {
                        *USRRetrainingSupport = false;
                }
        }
 
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
-               if (UseMALLForPStateChange[k] != dm_use_mall_pstate_change_full_frame &&
-                               UseMALLForPStateChange[k] != dm_use_mall_pstate_change_sub_viewport &&
-                               UseMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe &&
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
+               if (v->UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_full_frame &&
+                               v->UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_sub_viewport &&
+                               v->UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe &&
                                ActiveDRAMClockChangeLatencyMargin[k] < 0) {
                        if (PrefetchMode > 0) {
                                DRAMClockChangeSupportNumber = 2;
@@ -4543,10 +4526,10 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
                }
        }
 
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
-               if (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_full_frame)
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
+               if (v->UsesMALLForPStateChange[k] == dm_use_mall_pstate_change_full_frame)
                        DRAMClockChangeMethod = 1;
-               else if (UseMALLForPStateChange[k] == dm_use_mall_pstate_change_sub_viewport)
+               else if (v->UsesMALLForPStateChange[k] == dm_use_mall_pstate_change_sub_viewport)
                        DRAMClockChangeMethod = 2;
        }
 
@@ -4573,16 +4556,16 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
                        *DRAMClockChangeSupport = dm_dram_clock_change_unsupported;
        }
 
-       for (k = 0; k < NumberOfActiveSurfaces; ++k) {
+       for (k = 0; k < v->NumberOfActiveSurfaces; ++k) {
                unsigned int dst_y_pstate;
                unsigned int src_y_pstate_l;
                unsigned int src_y_pstate_c;
                unsigned int src_y_ahead_l, src_y_ahead_c, sub_vp_lines_l, sub_vp_lines_c;
 
-               dst_y_pstate = dml_ceil((mmSOCParameters.DRAMClockChangeLatency + mmSOCParameters.UrgentLatency) / (HTotal[k] / PixelClock[k]), 1);
-               src_y_pstate_l = dml_ceil(dst_y_pstate * VRatio[k], SwathHeightY[k]);
+               dst_y_pstate = dml_ceil((mmSOCParameters.DRAMClockChangeLatency + mmSOCParameters.UrgentLatency) / (v->HTotal[k] / v->PixelClock[k]), 1);
+               src_y_pstate_l = dml_ceil(dst_y_pstate * v->VRatio[k], SwathHeightY[k]);
                src_y_ahead_l = dml_floor(DETBufferSizeY[k] / BytePerPixelDETY[k] / SwathWidthY[k], SwathHeightY[k]) + LBLatencyHidingSourceLinesY[k];
-               sub_vp_lines_l = src_y_pstate_l + src_y_ahead_l + meta_row_height[k];
+               sub_vp_lines_l = src_y_pstate_l + src_y_ahead_l + v->meta_row_height[k];
 
 #ifdef __DML_VBA_DEBUG__
 dml_print("DML::%s: k=%d, DETBufferSizeY               = %d\n", __func__, k, DETBufferSizeY[k]);
@@ -4593,21 +4576,21 @@ dml_print("DML::%s: k=%d, LBLatencyHidingSourceLinesY  = %d\n", __func__, k, LBL
 dml_print("DML::%s: k=%d, dst_y_pstate      = %d\n", __func__, k, dst_y_pstate);
 dml_print("DML::%s: k=%d, src_y_pstate_l    = %d\n", __func__, k, src_y_pstate_l);
 dml_print("DML::%s: k=%d, src_y_ahead_l     = %d\n", __func__, k, src_y_ahead_l);
-dml_print("DML::%s: k=%d, meta_row_height   = %d\n", __func__, k, meta_row_height[k]);
+dml_print("DML::%s: k=%d, v->meta_row_height   = %d\n", __func__, k, v->meta_row_height[k]);
 dml_print("DML::%s: k=%d, sub_vp_lines_l    = %d\n", __func__, k, sub_vp_lines_l);
 #endif
                SubViewportLinesNeededInMALL[k] = sub_vp_lines_l;
 
                if (BytePerPixelDETC[k] > 0) {
-                       src_y_pstate_c = dml_ceil(dst_y_pstate * VRatioChroma[k], SwathHeightC[k]);
+                       src_y_pstate_c = dml_ceil(dst_y_pstate * v->VRatioChroma[k], SwathHeightC[k]);
                        src_y_ahead_c = dml_floor(DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k], SwathHeightC[k]) + LBLatencyHidingSourceLinesC[k];
-                       sub_vp_lines_c = src_y_pstate_c + src_y_ahead_c + meta_row_height_chroma[k];
+                       sub_vp_lines_c = src_y_pstate_c + src_y_ahead_c + v->meta_row_height_chroma[k];
                        SubViewportLinesNeededInMALL[k] = dml_max(sub_vp_lines_l, sub_vp_lines_c);
 
 #ifdef __DML_VBA_DEBUG__
 dml_print("DML::%s: k=%d, src_y_pstate_c            = %d\n", __func__, k, src_y_pstate_c);
 dml_print("DML::%s: k=%d, src_y_ahead_c             = %d\n", __func__, k, src_y_ahead_c);
-dml_print("DML::%s: k=%d, meta_row_height_chroma    = %d\n", __func__, k, meta_row_height_chroma[k]);
+dml_print("DML::%s: k=%d, v->meta_row_height_chroma    = %d\n", __func__, k, v->meta_row_height_chroma[k]);
 dml_print("DML::%s: k=%d, sub_vp_lines_c            = %d\n", __func__, k, sub_vp_lines_c);
 #endif
                }
index d293856..0b427d8 100644 (file)
@@ -30,6 +30,7 @@
 #include "os_types.h"
 #include "../dc_features.h"
 #include "../display_mode_structs.h"
+#include "dml/display_mode_vba.h"
 
 unsigned int dml32_dscceComputeDelay(
                unsigned int bpc,
@@ -215,6 +216,7 @@ void dml32_CalculateDETBufferSize(
 void dml32_CalculateODMMode(
                unsigned int MaximumPixelsPerLinePerDSCUnit,
                unsigned int HActive,
+               enum output_format_class OutFormat,
                enum output_encoder_class Output,
                enum odm_combine_policy ODMUse,
                double StateDispclk,
@@ -712,28 +714,14 @@ double dml32_CalculateExtraLatency(
                unsigned int HostVMMaxNonCachedPageTableLevels);
 
 bool dml32_CalculatePrefetchSchedule(
+               struct vba_vars_st *v,
+               unsigned int k,
                double HostVMInefficiencyFactor,
                DmlPipe *myPipe,
                unsigned int DSCDelay,
-               double DPPCLKDelaySubtotalPlusCNVCFormater,
-               double DPPCLKDelaySCL,
-               double DPPCLKDelaySCLLBOnly,
-               double DPPCLKDelayCNVCCursor,
-               double DISPCLKDelaySubtotal,
                unsigned int DPP_RECOUT_WIDTH,
-               enum output_format_class OutputFormat,
-               unsigned int MaxInterDCNTileRepeaters,
                unsigned int VStartup,
                unsigned int MaxVStartup,
-               unsigned int GPUVMPageTableLevels,
-               bool GPUVMEnable,
-               bool HostVMEnable,
-               unsigned int HostVMMaxNonCachedPageTableLevels,
-               double HostVMMinPageSize,
-               bool DynamicMetadataEnable,
-               bool DynamicMetadataVMEnabled,
-               int DynamicMetadataLinesBeforeActiveRequired,
-               unsigned int DynamicMetadataTransmittedBytes,
                double UrgentLatency,
                double UrgentExtraLatency,
                double TCalc,
@@ -807,58 +795,28 @@ void dml32_CalculateFlipSchedule(
                bool *ImmediateFlipSupportedForPipe);
 
 void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
-               bool USRRetrainingRequiredFinal,
-               enum dm_use_mall_for_pstate_change_mode UseMALLForPStateChange[],
+               struct vba_vars_st *v,
                unsigned int PrefetchMode,
-               unsigned int NumberOfActiveSurfaces,
-               unsigned int MaxLineBufferLines,
-               unsigned int LineBufferSize,
-               unsigned int WritebackInterfaceBufferSize,
                double DCFCLK,
                double ReturnBW,
-               bool SynchronizeTimingsFinal,
-               bool SynchronizeDRRDisplaysForUCLKPStateChangeFinal,
-               bool DRRDisplay[],
-               unsigned int dpte_group_bytes[],
-               unsigned int meta_row_height[],
-               unsigned int meta_row_height_chroma[],
                SOCParametersList mmSOCParameters,
-               unsigned int WritebackChunkSize,
                double SOCCLK,
                double DCFClkDeepSleep,
                unsigned int DETBufferSizeY[],
                unsigned int DETBufferSizeC[],
                unsigned int SwathHeightY[],
                unsigned int SwathHeightC[],
-               unsigned int LBBitPerPixel[],
                double SwathWidthY[],
                double SwathWidthC[],
-               double HRatio[],
-               double HRatioChroma[],
-               unsigned int VTaps[],
-               unsigned int VTapsChroma[],
-               double VRatio[],
-               double VRatioChroma[],
-               unsigned int HTotal[],
-               unsigned int VTotal[],
-               unsigned int VActive[],
-               double PixelClock[],
-               unsigned int BlendingAndTiming[],
                unsigned int DPPPerSurface[],
                double BytePerPixelDETY[],
                double BytePerPixelDETC[],
                double DSTXAfterScaler[],
                double DSTYAfterScaler[],
-               bool WritebackEnable[],
-               enum source_format_class WritebackPixelFormat[],
-               double WritebackDestinationWidth[],
-               double WritebackDestinationHeight[],
-               double WritebackSourceHeight[],
                bool UnboundedRequestEnabled,
                unsigned int CompressedBufferSizeInkByte,
 
                /* Output */
-               Watermarks *Watermark,
                enum clock_change_support *DRAMClockChangeSupport,
                double MaxActiveDRAMClockChangeLatencySupported[],
                unsigned int SubViewportLinesNeededInMALL[],
index 5d27ff0..f5400ed 100644 (file)
@@ -35,6 +35,8 @@
 #include "dcn30/display_rq_dlg_calc_30.h"
 #include "dcn31/display_mode_vba_31.h"
 #include "dcn31/display_rq_dlg_calc_31.h"
+#include "dcn314/display_mode_vba_314.h"
+#include "dcn314/display_rq_dlg_calc_314.h"
 #include "dcn32/display_mode_vba_32.h"
 #include "dcn32/display_rq_dlg_calc_32.h"
 #include "dml_logger.h"
@@ -74,6 +76,13 @@ const struct dml_funcs dml31_funcs = {
        .rq_dlg_get_rq_reg = dml31_rq_dlg_get_rq_reg
 };
 
+const struct dml_funcs dml314_funcs = {
+       .validate = dml314_ModeSupportAndSystemConfigurationFull,
+       .recalculate = dml314_recalculate,
+       .rq_dlg_get_dlg_reg = dml314_rq_dlg_get_dlg_reg,
+       .rq_dlg_get_rq_reg = dml314_rq_dlg_get_rq_reg
+};
+
 const struct dml_funcs dml32_funcs = {
        .validate = dml32_ModeSupportAndSystemConfigurationFull,
     .recalculate = dml32_recalculate,
@@ -107,6 +116,9 @@ void dml_init_instance(struct display_mode_lib *lib,
        case DML_PROJECT_DCN31_FPGA:
                lib->funcs = dml31_funcs;
                break;
+       case DML_PROJECT_DCN314:
+               lib->funcs = dml314_funcs;
+               break;
        case DML_PROJECT_DCN32:
                lib->funcs = dml32_funcs;
                break;
index 2bdd6ed..b1878a1 100644 (file)
@@ -41,6 +41,7 @@ enum dml_project {
        DML_PROJECT_DCN30,
        DML_PROJECT_DCN31,
        DML_PROJECT_DCN31_FPGA,
+       DML_PROJECT_DCN314,
        DML_PROJECT_DCN32,
 };
 
index 492aec6..2051dda 100644 (file)
@@ -651,10 +651,10 @@ struct vba_vars_st {
 
        unsigned int OutputTypeAndRatePerState[DC__VOLTAGE_STATES][DC__NUM_DPP__MAX];
        double RequiredDISPCLKPerSurface[DC__VOLTAGE_STATES][2][DC__NUM_DPP__MAX];
-       unsigned int MicroTileHeightY[DC__NUM_DPP__MAX];
-       unsigned int MicroTileHeightC[DC__NUM_DPP__MAX];
-       unsigned int MicroTileWidthY[DC__NUM_DPP__MAX];
-       unsigned int MicroTileWidthC[DC__NUM_DPP__MAX];
+       unsigned int MacroTileHeightY[DC__NUM_DPP__MAX];
+       unsigned int MacroTileHeightC[DC__NUM_DPP__MAX];
+       unsigned int MacroTileWidthY[DC__NUM_DPP__MAX];
+       unsigned int MacroTileWidthC[DC__NUM_DPP__MAX];
        bool ImmediateFlipRequiredFinal;
        bool DCCProgrammingAssumesScanDirectionUnknownFinal;
        bool EnoughWritebackUnits;
@@ -800,8 +800,6 @@ struct vba_vars_st {
        double PSCL_FACTOR[DC__NUM_DPP__MAX];
        double PSCL_FACTOR_CHROMA[DC__NUM_DPP__MAX];
        double MaximumVStartup[DC__VOLTAGE_STATES][2][DC__NUM_DPP__MAX];
-       unsigned int MacroTileWidthY[DC__NUM_DPP__MAX];
-       unsigned int MacroTileWidthC[DC__NUM_DPP__MAX];
        double AlignedDCCMetaPitch[DC__NUM_DPP__MAX];
        double AlignedYPitch[DC__NUM_DPP__MAX];
        double AlignedCPitch[DC__NUM_DPP__MAX];
index 5d2b028..d9f1b0a 100644 (file)
@@ -214,6 +214,7 @@ struct dummy_pstate_entry {
 struct clk_bw_params {
        unsigned int vram_type;
        unsigned int num_channels;
+       unsigned int dram_channel_width_bytes;
        unsigned int dispclk_vco_khz;
        unsigned int dc_mode_softmax_memclk;
        struct clk_limit_table clk_table;
index 68c2ed4..cff5fd5 100644 (file)
@@ -340,6 +340,8 @@ struct clk_mgr_internal {
        bool smu_present;
        void *wm_range_table;
        long long wm_range_table_addr;
+
+       bool dpm_present;
 };
 
 struct clk_mgr_internal_funcs {
index 5815876..7614125 100644 (file)
@@ -219,6 +219,10 @@ void check_syncd_pipes_for_disabled_master_pipe(struct dc *dc,
        struct dc_state *context,
        uint8_t disabled_master_pipe_idx);
 
+void reset_sync_context_for_pipe(const struct dc *dc,
+       struct dc_state *context,
+       uint8_t pipe_idx);
+
 uint8_t resource_transmitter_to_phy_idx(const struct dc *dc, enum transmitter transmitter);
 
 const struct link_hwss *get_link_hwss(const struct dc_link *link,
index db7b0b1..226af06 100644 (file)
@@ -116,7 +116,7 @@ static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
        dto_params.timing = &pipe_ctx->stream->timing;
        dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr);
 
-       dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, link_enc->inst);
+       dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, stream_enc->inst);
        dccg->funcs->enable_symclk32_se(dccg, stream_enc->inst, phyd32clk);
        dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
        stream_enc->funcs->enable_stream(stream_enc);
@@ -137,7 +137,7 @@ static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
        stream_enc->funcs->disable(stream_enc);
        dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
        dccg->funcs->disable_symclk32_se(dccg, stream_enc->inst);
-       dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst,  pipe_ctx->link_res.hpo_dp_link_enc->inst);
+       dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, stream_enc->inst);
 }
 
 static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
index 859ffd8..04f7656 100644 (file)
@@ -1600,6 +1600,7 @@ static void interpolate_user_regamma(uint32_t hw_points_num,
        struct fixed31_32 lut2;
        struct fixed31_32 delta_lut;
        struct fixed31_32 delta_index;
+       const struct fixed31_32 one = dc_fixpt_from_int(1);
 
        i = 0;
        /* fixed_pt library has problems handling too small values */
@@ -1628,6 +1629,9 @@ static void interpolate_user_regamma(uint32_t hw_points_num,
                        } else
                                hw_x = coordinates_x[i].x;
 
+                       if (dc_fixpt_le(one, hw_x))
+                               hw_x = one;
+
                        norm_x = dc_fixpt_mul(norm_factor, hw_x);
                        index = dc_fixpt_floor(norm_x);
                        if (index < 0 || index > 255)
index 80dab11..7e85cdc 100644 (file)
@@ -268,7 +268,9 @@ union MESAPI__ADD_QUEUE {
                        uint32_t is_tmz_queue           : 1;
                        uint32_t map_kiq_utility_queue  : 1;
                        uint32_t is_kfd_process         : 1;
-                       uint32_t reserved               : 22;
+                       uint32_t trap_en                : 1;
+                       uint32_t is_aql_queue           : 1;
+                       uint32_t reserved               : 20;
                };
                struct MES_API_STATUS           api_status;
                uint64_t                        tma_addr;
index f745cd8..063f4a7 100644 (file)
@@ -25,7 +25,7 @@
 #define SMU13_DRIVER_IF_V13_0_0_H
 
 //Increment this version if SkuTable_t or BoardTable_t change
-#define PPTABLE_VERSION 0x22
+#define PPTABLE_VERSION 0x24
 
 #define NUM_GFXCLK_DPM_LEVELS    16
 #define NUM_SOCCLK_DPM_LEVELS    8
index ac308e7..f442bf0 100644 (file)
@@ -30,7 +30,7 @@
 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x05
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x2E
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x30
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C
 
 #define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500  //500ms
@@ -291,5 +291,11 @@ int smu_v13_0_set_default_dpm_tables(struct smu_context *smu);
 void smu_v13_0_set_smu_mailbox_registers(struct smu_context *smu);
 
 int smu_v13_0_mode1_reset(struct smu_context *smu);
+
+int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu,
+                                       void **table,
+                                       uint32_t *size,
+                                       uint32_t pptable_id);
+
 #endif
 #endif
index 6db67f0..644ea15 100644 (file)
@@ -368,6 +368,17 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu)
                smu_baco->platform_support =
                        (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true :
                                                                        false;
+
+               /*
+                * Disable BACO entry/exit completely on below SKUs to
+                * avoid hardware intermittent failures.
+                */
+               if (((adev->pdev->device == 0x73A1) &&
+                   (adev->pdev->revision == 0x00)) ||
+                   ((adev->pdev->device == 0x73BF) &&
+                   (adev->pdev->revision == 0xCF)))
+                       smu_baco->platform_support = false;
+
        }
 }
 
index 18ee3b5..93f9b83 100644 (file)
@@ -84,9 +84,6 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_7.bin");
 static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
 static const int link_speed[] = {25, 50, 80, 160};
 
-static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **table, uint32_t *size,
-                                              uint32_t pptable_id);
-
 int smu_v13_0_init_microcode(struct smu_context *smu)
 {
        struct amdgpu_device *adev = smu->adev;
@@ -212,7 +209,8 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu)
        if (!adev->scpm_enabled)
                return 0;
 
-       if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7))
+       if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7)) ||
+           (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)))
                return 0;
 
        /* override pptable_id from driver parameter */
@@ -221,31 +219,6 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu)
                dev_info(adev->dev, "override pptable id %d\n", pptable_id);
        } else {
                pptable_id = smu->smu_table.boot_values.pp_table_id;
-
-               /*
-                * Temporary solution for SMU V13.0.0 with SCPM enabled:
-                *   - use 36831 signed pptable when pp_table_id is 3683
-                *   - use 37151 signed pptable when pp_table_id is 3715
-                *   - use 36641 signed pptable when pp_table_id is 3664 or 0
-                * TODO: drop these when the pptable carried in vbios is ready.
-                */
-               if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)) {
-                       switch (pptable_id) {
-                       case 0:
-                       case 3664:
-                               pptable_id = 36641;
-                               break;
-                       case 3683:
-                               pptable_id = 36831;
-                               break;
-                       case 3715:
-                               pptable_id = 37151;
-                               break;
-                       default:
-                               dev_err(adev->dev, "Unsupported pptable id %d\n", pptable_id);
-                               return -EINVAL;
-                       }
-               }
        }
 
        /* "pptable_id == 0" means vbios carries the pptable. */
@@ -425,8 +398,10 @@ static int smu_v13_0_get_pptable_from_vbios(struct smu_context *smu, void **tabl
        return 0;
 }
 
-static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **table, uint32_t *size,
-                                              uint32_t pptable_id)
+int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu,
+                                       void **table,
+                                       uint32_t *size,
+                                       uint32_t pptable_id)
 {
        const struct smc_firmware_header_v1_0 *hdr;
        struct amdgpu_device *adev = smu->adev;
@@ -476,26 +451,6 @@ int smu_v13_0_setup_pptable(struct smu_context *smu)
        } else {
                pptable_id = smu->smu_table.boot_values.pp_table_id;
 
-               /*
-                * Temporary solution for SMU V13.0.0 with SCPM disabled:
-                *   - use 3664, 3683 or 3715 on request
-                *   - use 3664 when pptable_id is 0
-                * TODO: drop these when the pptable carried in vbios is ready.
-                */
-               if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)) {
-                       switch (pptable_id) {
-                       case 0:
-                               pptable_id = 3664;
-                               break;
-                       case 3664:
-                       case 3683:
-                       case 3715:
-                               break;
-                       default:
-                               dev_err(adev->dev, "Unsupported pptable id %d\n", pptable_id);
-                               return -EINVAL;
-                       }
-               }
        }
 
        /* force using vbios pptable in sriov mode */
index df4a47a..1d45448 100644 (file)
@@ -239,82 +239,47 @@ smu_v13_0_0_get_allowed_feature_mask(struct smu_context *smu,
                                  uint32_t *feature_mask, uint32_t num)
 {
        struct amdgpu_device *adev = smu->adev;
+       u32 smu_version;
 
        if (num > 2)
                return -EINVAL;
 
-       memset(feature_mask, 0, sizeof(uint32_t) * num);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT);
+       memset(feature_mask, 0xff, sizeof(uint32_t) * num);
 
-       if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
+       if (!(adev->pm.pp_feature & PP_SCLK_DPM_MASK)) {
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_IMU_BIT);
        }
 
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT);
-
-       if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) &&
-           (adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
-
-       if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
-
-#if 0
-       if (adev->pm.pp_feature & PP_GFXOFF_MASK)
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
-#endif
+       if (!(adev->pg_flags & AMD_PG_SUPPORT_ATHUB) ||
+           !(adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
 
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT);
+       if (!(adev->pm.pp_feature & PP_SOCCLK_DPM_MASK))
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
 
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DF_CSTATE_BIT);
-
-       if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) {
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
+       /* PMFW 78.58 contains a critical fix for gfxoff feature */
+       smu_cmn_get_smc_version(smu, NULL, &smu_version);
+       if ((smu_version < 0x004e3a00) ||
+            !(adev->pm.pp_feature & PP_GFXOFF_MASK))
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFXOFF_BIT);
+
+       if (!(adev->pm.pp_feature & PP_MCLK_DPM_MASK)) {
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
        }
 
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MEM_TEMP_READ_BIT);
-
-       if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_MPCLK_DS_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_MPCLK_DS_BIT);
+       if (!(adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK))
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
 
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_FCLK_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCN_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_DCFCLK_BIT);
-
-       if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) {
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_LCLK_BIT);
+       if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_LINK_BIT);
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_LCLK_BIT);
        }
 
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT);
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_CG_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_FCLK_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_CTF_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_UCLK_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VR0HOT_BIT);
-
-       *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT);
-
-       if (adev->pm.pp_feature & PP_ULV_MASK)
-               *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT);
+       if (!(adev->pm.pp_feature & PP_ULV_MASK))
+               *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_ULV_BIT);
 
        return 0;
 }
@@ -388,30 +353,35 @@ static int smu_v13_0_0_append_powerplay_table(struct smu_context *smu)
        return 0;
 }
 
-static int smu_v13_0_0_setup_pptable(struct smu_context *smu)
+static int smu_v13_0_0_get_pptable_from_pmfw(struct smu_context *smu,
+                                            void **table,
+                                            uint32_t *size)
 {
        struct smu_table_context *smu_table = &smu->smu_table;
        void *combo_pptable = smu_table->combo_pptable;
-       struct amdgpu_device *adev = smu->adev;
        int ret = 0;
 
-       /*
-        * With SCPM enabled, the pptable used will be signed. It cannot
-        * be used directly by driver. To get the raw pptable, we need to
-        * rely on the combo pptable(and its revelant SMU message).
-        */
-       if (adev->scpm_enabled) {
-               ret = smu_cmn_get_combo_pptable(smu);
-               if (ret)
-                       return ret;
+       ret = smu_cmn_get_combo_pptable(smu);
+       if (ret)
+               return ret;
 
-               smu->smu_table.power_play_table = combo_pptable;
-               smu->smu_table.power_play_table_size = sizeof(struct smu_13_0_0_powerplay_table);
-       } else {
-               ret = smu_v13_0_setup_pptable(smu);
-               if (ret)
-                       return ret;
-       }
+       *table = combo_pptable;
+       *size = sizeof(struct smu_13_0_0_powerplay_table);
+
+       return 0;
+}
+
+static int smu_v13_0_0_setup_pptable(struct smu_context *smu)
+{
+       struct smu_table_context *smu_table = &smu->smu_table;
+       struct amdgpu_device *adev = smu->adev;
+       int ret = 0;
+
+       ret = smu_v13_0_0_get_pptable_from_pmfw(smu,
+                                               &smu_table->power_play_table,
+                                               &smu_table->power_play_table_size);
+       if (ret)
+               return ret;
 
        ret = smu_v13_0_0_store_powerplay_table(smu);
        if (ret)
index 1016d1c..c422bf8 100644 (file)
@@ -120,6 +120,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff,              0),
        MSG_MAP(Mode1Reset,             PPSMC_MSG_Mode1Reset,                  0),
        MSG_MAP(PrepareMp1ForUnload,            PPSMC_MSG_PrepareMp1ForUnload,         0),
+       MSG_MAP(SetMGpuFanBoostLimitRpm,        PPSMC_MSG_SetMGpuFanBoostLimitRpm,     0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
@@ -400,11 +401,27 @@ static int smu_v13_0_7_append_powerplay_table(struct smu_context *smu)
        return 0;
 }
 
+static int smu_v13_0_7_get_pptable_from_pmfw(struct smu_context *smu,
+                                            void **table,
+                                            uint32_t *size)
+{
+       struct smu_table_context *smu_table = &smu->smu_table;
+       void *combo_pptable = smu_table->combo_pptable;
+       int ret = 0;
+
+       ret = smu_cmn_get_combo_pptable(smu);
+       if (ret)
+               return ret;
+
+       *table = combo_pptable;
+       *size = sizeof(struct smu_13_0_7_powerplay_table);
+
+       return 0;
+}
 
 static int smu_v13_0_7_setup_pptable(struct smu_context *smu)
 {
        struct smu_table_context *smu_table = &smu->smu_table;
-       void *combo_pptable = smu_table->combo_pptable;
        struct amdgpu_device *adev = smu->adev;
        int ret = 0;
 
@@ -413,18 +430,11 @@ static int smu_v13_0_7_setup_pptable(struct smu_context *smu)
         * be used directly by driver. To get the raw pptable, we need to
         * rely on the combo pptable(and its revelant SMU message).
         */
-       if (adev->scpm_enabled) {
-               ret = smu_cmn_get_combo_pptable(smu);
-               if (ret)
-                       return ret;
-
-               smu->smu_table.power_play_table = combo_pptable;
-               smu->smu_table.power_play_table_size = sizeof(struct smu_13_0_7_powerplay_table);
-       } else {
-               ret = smu_v13_0_setup_pptable(smu);
-               if (ret)
-                       return ret;
-       }
+       ret = smu_v13_0_7_get_pptable_from_pmfw(smu,
+                                               &smu_table->power_play_table,
+                                               &smu_table->power_play_table_size);
+       if (ret)
+               return ret;
 
        ret = smu_v13_0_7_store_powerplay_table(smu);
        if (ret)
index 8aadcc0..df9370e 100644 (file)
@@ -1864,12 +1864,6 @@ EXPORT_SYMBOL_GPL(analogix_dp_remove);
 int analogix_dp_suspend(struct analogix_dp_device *dp)
 {
        clk_disable_unprepare(dp->clock);
-
-       if (dp->plat_data->panel) {
-               if (drm_panel_unprepare(dp->plat_data->panel))
-                       DRM_ERROR("failed to turnoff the panel\n");
-       }
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_suspend);
@@ -1884,13 +1878,6 @@ int analogix_dp_resume(struct analogix_dp_device *dp)
                return ret;
        }
 
-       if (dp->plat_data->panel) {
-               if (drm_panel_prepare(dp->plat_data->panel)) {
-                       DRM_ERROR("failed to setup the panel\n");
-                       return -EBUSY;
-               }
-       }
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_resume);
index 28bad30..5968f4a 100644 (file)
@@ -188,7 +188,7 @@ static int lt8912_write_lvds_config(struct lt8912 *lt)
                {0x03, 0xff},
        };
 
-       return regmap_multi_reg_write(lt->regmap[I2C_CEC_DSI], seq, ARRAY_SIZE(seq));
+       return regmap_multi_reg_write(lt->regmap[I2C_MAIN], seq, ARRAY_SIZE(seq));
 };
 
 static inline struct lt8912 *bridge_to_lt8912(struct drm_bridge *b)
@@ -268,7 +268,7 @@ static int lt8912_video_setup(struct lt8912 *lt)
        u32 hactive, h_total, hpw, hfp, hbp;
        u32 vactive, v_total, vpw, vfp, vbp;
        u8 settle = 0x08;
-       int ret;
+       int ret, hsync_activehigh, vsync_activehigh;
 
        if (!lt)
                return -EINVAL;
@@ -278,12 +278,14 @@ static int lt8912_video_setup(struct lt8912 *lt)
        hpw = lt->mode.hsync_len;
        hbp = lt->mode.hback_porch;
        h_total = hactive + hfp + hpw + hbp;
+       hsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH;
 
        vactive = lt->mode.vactive;
        vfp = lt->mode.vfront_porch;
        vpw = lt->mode.vsync_len;
        vbp = lt->mode.vback_porch;
        v_total = vactive + vfp + vpw + vbp;
+       vsync_activehigh = lt->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH;
 
        if (vactive <= 600)
                settle = 0x04;
@@ -317,6 +319,13 @@ static int lt8912_video_setup(struct lt8912 *lt)
        ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3e, hfp & 0xff);
        ret |= regmap_write(lt->regmap[I2C_CEC_DSI], 0x3f, hfp >> 8);
 
+       ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(0),
+                                 vsync_activehigh ? BIT(0) : 0);
+       ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xab, BIT(1),
+                                 hsync_activehigh ? BIT(1) : 0);
+       ret |= regmap_update_bits(lt->regmap[I2C_MAIN], 0xb2, BIT(0),
+                                 lt->connector.display_info.is_hdmi ? BIT(0) : 0);
+
        return ret;
 }
 
index 4939220..01ee3fe 100644 (file)
@@ -377,8 +377,8 @@ static int vrr_range_show(struct seq_file *m, void *data)
        if (connector->status != connector_status_connected)
                return -ENODEV;
 
-       seq_printf(m, "Min: %u\n", (u8)connector->display_info.monitor_range.min_vfreq);
-       seq_printf(m, "Max: %u\n", (u8)connector->display_info.monitor_range.max_vfreq);
+       seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq);
+       seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq);
 
        return 0;
 }
index bbc25e3..eaa8193 100644 (file)
@@ -5971,12 +5971,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
 }
 
 static
-void get_monitor_range(const struct detailed_timing *timing,
-                      void *info_monitor_range)
+void get_monitor_range(const struct detailed_timing *timing, void *c)
 {
-       struct drm_monitor_range_info *monitor_range = info_monitor_range;
+       struct detailed_mode_closure *closure = c;
+       struct drm_display_info *info = &closure->connector->display_info;
+       struct drm_monitor_range_info *monitor_range = &info->monitor_range;
        const struct detailed_non_pixel *data = &timing->data.other_data;
        const struct detailed_data_monitor_range *range = &data->data.range;
+       const struct edid *edid = closure->drm_edid->edid;
 
        if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
                return;
@@ -5992,18 +5994,28 @@ void get_monitor_range(const struct detailed_timing *timing,
 
        monitor_range->min_vfreq = range->min_vfreq;
        monitor_range->max_vfreq = range->max_vfreq;
+
+       if (edid->revision >= 4) {
+               if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ)
+                       monitor_range->min_vfreq += 255;
+               if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ)
+                       monitor_range->max_vfreq += 255;
+       }
 }
 
 static void drm_get_monitor_range(struct drm_connector *connector,
                                  const struct drm_edid *drm_edid)
 {
-       struct drm_display_info *info = &connector->display_info;
+       const struct drm_display_info *info = &connector->display_info;
+       struct detailed_mode_closure closure = {
+               .connector = connector,
+               .drm_edid = drm_edid,
+       };
 
        if (!version_greater(drm_edid, 1, 1))
                return;
 
-       drm_for_each_detailed_block(drm_edid, get_monitor_range,
-                                   &info->monitor_range);
+       drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);
 
        DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
                      info->monitor_range.min_vfreq,
index dd32b48..ce96234 100644 (file)
@@ -581,11 +581,9 @@ static const struct psb_offset cdv_regmap[2] = {
 static int cdv_chip_setup(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
-       struct pci_dev *pdev = to_pci_dev(dev->dev);
        INIT_WORK(&dev_priv->hotplug_work, cdv_hotplug_work_func);
 
-       if (pci_enable_msi(pdev))
-               dev_warn(dev->dev, "Enabling MSI failed!\n");
+       dev_priv->use_msi = true;
        dev_priv->regmap = cdv_regmap;
        gma_get_core_freq(dev);
        psb_intel_opregion_init(dev);
index dffe374..4b7627a 100644 (file)
@@ -112,12 +112,12 @@ static void psb_gem_free_object(struct drm_gem_object *obj)
 {
        struct psb_gem_object *pobj = to_psb_gem_object(obj);
 
-       drm_gem_object_release(obj);
-
        /* Undo the mmap pin if we are destroying the object */
        if (pobj->mmapping)
                psb_gem_unpin(pobj);
 
+       drm_gem_object_release(obj);
+
        WARN_ON(pobj->in_gart && !pobj->stolen);
 
        release_resource(&pobj->resource);
index bd40c04..2f52ece 100644 (file)
@@ -532,15 +532,18 @@ int gma_crtc_page_flip(struct drm_crtc *crtc,
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
                gma_crtc->page_flip_event = event;
+               spin_unlock_irqrestore(&dev->event_lock, flags);
 
                /* Call this locked if we want an event at vblank interrupt. */
                ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
                if (ret) {
-                       gma_crtc->page_flip_event = NULL;
-                       drm_crtc_vblank_put(crtc);
+                       spin_lock_irqsave(&dev->event_lock, flags);
+                       if (gma_crtc->page_flip_event) {
+                               gma_crtc->page_flip_event = NULL;
+                               drm_crtc_vblank_put(crtc);
+                       }
+                       spin_unlock_irqrestore(&dev->event_lock, flags);
                }
-
-               spin_unlock_irqrestore(&dev->event_lock, flags);
        } else {
                ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
        }
index 5923a9c..f90e628 100644 (file)
@@ -501,12 +501,9 @@ static const struct psb_offset oaktrail_regmap[2] = {
 static int oaktrail_chip_setup(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
-       struct pci_dev *pdev = to_pci_dev(dev->dev);
        int ret;
 
-       if (pci_enable_msi(pdev))
-               dev_warn(dev->dev, "Enabling MSI failed!\n");
-
+       dev_priv->use_msi = true;
        dev_priv->regmap = oaktrail_regmap;
 
        ret = mid_chip_setup(dev);
index b91de6d..6687308 100644 (file)
@@ -139,8 +139,6 @@ static void gma_suspend_pci(struct pci_dev *pdev)
        dev_priv->regs.saveBSM = bsm;
        pci_read_config_dword(pdev, 0xFC, &vbt);
        dev_priv->regs.saveVBT = vbt;
-       pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
-       pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
 
        pci_disable_device(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
@@ -168,9 +166,6 @@ static bool gma_resume_pci(struct pci_dev *pdev)
        pci_restore_state(pdev);
        pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM);
        pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT);
-       /* restoring MSI address and data in PCIx space */
-       pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
-       pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
        ret = pci_enable_device(pdev);
 
        if (ret != 0)
@@ -223,8 +218,7 @@ int gma_power_resume(struct device *_dev)
        mutex_lock(&power_mutex);
        gma_resume_pci(pdev);
        gma_resume_display(pdev);
-       gma_irq_preinstall(dev);
-       gma_irq_postinstall(dev);
+       gma_irq_install(dev);
        mutex_unlock(&power_mutex);
        return 0;
 }
index 1d8744f..54e756b 100644 (file)
@@ -383,7 +383,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
        PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
 
-       gma_irq_install(dev, pdev->irq);
+       gma_irq_install(dev);
 
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 
index 0ea3d23..731cc35 100644 (file)
@@ -490,6 +490,7 @@ struct drm_psb_private {
        int rpm_enabled;
 
        /* MID specific */
+       bool use_msi;
        bool has_gct;
        struct oaktrail_gct_data gct_data;
 
@@ -499,10 +500,6 @@ struct drm_psb_private {
        /* Register state */
        struct psb_save_area regs;
 
-       /* MSI reg save */
-       uint32_t msi_addr;
-       uint32_t msi_data;
-
        /* Hotplug handling */
        struct work_struct hotplug_work;
 
index e6e6d61..038f18e 100644 (file)
@@ -316,17 +316,24 @@ void gma_irq_postinstall(struct drm_device *dev)
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
 }
 
-int gma_irq_install(struct drm_device *dev, unsigned int irq)
+int gma_irq_install(struct drm_device *dev)
 {
+       struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
        int ret;
 
-       if (irq == IRQ_NOTCONNECTED)
+       if (dev_priv->use_msi && pci_enable_msi(pdev)) {
+               dev_warn(dev->dev, "Enabling MSI failed!\n");
+               dev_priv->use_msi = false;
+       }
+
+       if (pdev->irq == IRQ_NOTCONNECTED)
                return -ENOTCONN;
 
        gma_irq_preinstall(dev);
 
        /* PCI devices require shared interrupts. */
-       ret = request_irq(irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev);
+       ret = request_irq(pdev->irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev);
        if (ret)
                return ret;
 
@@ -369,6 +376,8 @@ void gma_irq_uninstall(struct drm_device *dev)
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
 
        free_irq(pdev->irq, dev);
+       if (dev_priv->use_msi)
+               pci_disable_msi(pdev);
 }
 
 int gma_crtc_enable_vblank(struct drm_crtc *crtc)
index b51e395..7648f69 100644 (file)
@@ -17,7 +17,7 @@ struct drm_device;
 
 void gma_irq_preinstall(struct drm_device *dev);
 void gma_irq_postinstall(struct drm_device *dev);
-int  gma_irq_install(struct drm_device *dev, unsigned int irq);
+int  gma_irq_install(struct drm_device *dev);
 void gma_irq_uninstall(struct drm_device *dev);
 
 int  gma_crtc_enable_vblank(struct drm_crtc *crtc);
index 073adfe..4e41c14 100644 (file)
@@ -2,6 +2,7 @@
 config DRM_HISI_HIBMC
        tristate "DRM Support for Hisilicon Hibmc"
        depends on DRM && PCI && (ARM64 || COMPILE_TEST)
+       depends on MMU
        select DRM_KMS_HELPER
        select DRM_VRAM_HELPER
        select DRM_TTM
index 6d11e79..f84d397 100644 (file)
@@ -23,9 +23,6 @@
 #define DRIVER_MAJOR 1
 #define DRIVER_MINOR 0
 
-#define PCI_VENDOR_ID_MICROSOFT 0x1414
-#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
-
 DEFINE_DRM_GEM_FOPS(hv_fops);
 
 static struct drm_driver hyperv_driver = {
@@ -133,7 +130,6 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
        }
 
        ret = hyperv_setup_vram(hv, hdev);
-
        if (ret)
                goto err_vmbus_close;
 
@@ -150,18 +146,20 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
 
        ret = hyperv_mode_config_init(hv);
        if (ret)
-               goto err_vmbus_close;
+               goto err_free_mmio;
 
        ret = drm_dev_register(dev, 0);
        if (ret) {
                drm_err(dev, "Failed to register drm driver.\n");
-               goto err_vmbus_close;
+               goto err_free_mmio;
        }
 
        drm_fbdev_generic_setup(dev, 0);
 
        return 0;
 
+err_free_mmio:
+       vmbus_free_mmio(hv->mem->start, hv->fb_size);
 err_vmbus_close:
        vmbus_close(hdev->channel);
 err_hv_set_drv_data:
index 5dcfa7f..1390729 100644 (file)
@@ -1629,6 +1629,8 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
        /* FIXME: initialize from VBT */
        vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
 
+       vdsc_cfg->pic_height = crtc_state->hw.adjusted_mode.crtc_vdisplay;
+
        ret = intel_dsc_compute_params(crtc_state);
        if (ret)
                return ret;
@@ -2070,7 +2072,14 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
        else
                intel_dsi->ports = BIT(port);
 
+       if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports))
+               intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports;
+
        intel_dsi->dcs_backlight_ports = intel_connector->panel.vbt.dsi.bl_ports;
+
+       if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports))
+               intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports;
+
        intel_dsi->dcs_cabc_ports = intel_connector->panel.vbt.dsi.cabc_ports;
 
        for_each_dsi_port(port, intel_dsi->ports) {
index 110fc98..f5e1d69 100644 (file)
@@ -16,6 +16,7 @@
 #include "intel_dsi_dcs_backlight.h"
 #include "intel_panel.h"
 #include "intel_pci_config.h"
+#include "intel_pps.h"
 
 /**
  * scale - scale values from one range to another
@@ -971,26 +972,24 @@ int intel_backlight_device_register(struct intel_connector *connector)
        if (!name)
                return -ENOMEM;
 
-       bd = backlight_device_register(name, connector->base.kdev, connector,
-                                      &intel_backlight_device_ops, &props);
-
-       /*
-        * Using the same name independent of the drm device or connector
-        * prevents registration of multiple backlight devices in the
-        * driver. However, we need to use the default name for backward
-        * compatibility. Use unique names for subsequent backlight devices as a
-        * fallback when the default name already exists.
-        */
-       if (IS_ERR(bd) && PTR_ERR(bd) == -EEXIST) {
+       bd = backlight_device_get_by_name(name);
+       if (bd) {
+               put_device(&bd->dev);
+               /*
+                * Using the same name independent of the drm device or connector
+                * prevents registration of multiple backlight devices in the
+                * driver. However, we need to use the default name for backward
+                * compatibility. Use unique names for subsequent backlight devices as a
+                * fallback when the default name already exists.
+                */
                kfree(name);
                name = kasprintf(GFP_KERNEL, "card%d-%s-backlight",
                                 i915->drm.primary->index, connector->base.name);
                if (!name)
                        return -ENOMEM;
-
-               bd = backlight_device_register(name, connector->base.kdev, connector,
-                                              &intel_backlight_device_ops, &props);
        }
+       bd = backlight_device_register(name, connector->base.kdev, connector,
+                                      &intel_backlight_device_ops, &props);
 
        if (IS_ERR(bd)) {
                drm_err(&i915->drm,
@@ -1773,9 +1772,13 @@ void intel_backlight_init_funcs(struct intel_panel *panel)
                panel->backlight.pwm_funcs = &i9xx_pwm_funcs;
        }
 
-       if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP &&
-           intel_dp_aux_init_backlight_funcs(connector) == 0)
-               return;
+       if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
+               if (intel_dp_aux_init_backlight_funcs(connector) == 0)
+                       return;
+
+               if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
+                       connector->panel.backlight.power = intel_pps_backlight_power;
+       }
 
        /* We're using a standard PWM backlight interface */
        panel->backlight.funcs = &pwm_bl_funcs;
index 51dde5b..7d6eb9a 100644 (file)
@@ -479,6 +479,13 @@ init_bdb_block(struct drm_i915_private *i915,
 
        block_size = get_blocksize(block);
 
+       /*
+        * Version number and new block size are considered
+        * part of the header for MIPI sequenece block v3+.
+        */
+       if (section_id == BDB_MIPI_SEQUENCE && *(const u8 *)block >= 3)
+               block_size += 5;
+
        entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
                        GFP_KERNEL);
        if (!entry) {
@@ -1596,6 +1603,8 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
                                      struct intel_panel *panel,
                                      enum port port)
 {
+       enum port port_bc = DISPLAY_VER(i915) >= 11 ? PORT_B : PORT_C;
+
        if (!panel->vbt.dsi.config->dual_link || i915->vbt.version < 197) {
                panel->vbt.dsi.bl_ports = BIT(port);
                if (panel->vbt.dsi.config->cabc_supported)
@@ -1609,11 +1618,11 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
                panel->vbt.dsi.bl_ports = BIT(PORT_A);
                break;
        case DL_DCS_PORT_C:
-               panel->vbt.dsi.bl_ports = BIT(PORT_C);
+               panel->vbt.dsi.bl_ports = BIT(port_bc);
                break;
        default:
        case DL_DCS_PORT_A_AND_C:
-               panel->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(PORT_C);
+               panel->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(port_bc);
                break;
        }
 
@@ -1625,12 +1634,12 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
                panel->vbt.dsi.cabc_ports = BIT(PORT_A);
                break;
        case DL_DCS_PORT_C:
-               panel->vbt.dsi.cabc_ports = BIT(PORT_C);
+               panel->vbt.dsi.cabc_ports = BIT(port_bc);
                break;
        default:
        case DL_DCS_PORT_A_AND_C:
                panel->vbt.dsi.cabc_ports =
-                                       BIT(PORT_A) | BIT(PORT_C);
+                                       BIT(PORT_A) | BIT(port_bc);
                break;
        }
 }
index 79269d2..3699869 100644 (file)
@@ -404,15 +404,17 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
                int clpchgroup;
                int j;
 
-               if (i < num_groups - 1)
-                       bi_next = &dev_priv->max_bw[i + 1];
-
                clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i;
 
-               if (i < num_groups - 1 && clpchgroup < clperchgroup)
-                       bi_next->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
-               else
-                       bi_next->num_planes = 0;
+               if (i < num_groups - 1) {
+                       bi_next = &dev_priv->max_bw[i + 1];
+
+                       if (clpchgroup < clperchgroup)
+                               bi_next->num_planes = (ipqdepth - clpchgroup) /
+                                                      clpchgroup + 1;
+                       else
+                               bi_next->num_planes = 0;
+               }
 
                bi->num_qgv_points = qi.num_points;
                bi->num_psf_gv_points = qi.num_psf_points;
index 32292c0..3ed7eea 100644 (file)
@@ -389,23 +389,13 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp)
        return intel_dp_is_edp(intel_dp) ? 810000 : 1350000;
 }
 
-static bool is_low_voltage_sku(struct drm_i915_private *i915, enum phy phy)
-{
-       u32 voltage;
-
-       voltage = intel_de_read(i915, ICL_PORT_COMP_DW3(phy)) & VOLTAGE_INFO_MASK;
-
-       return voltage == VOLTAGE_INFO_0_85V;
-}
-
 static int icl_max_source_rate(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
 
-       if (intel_phy_is_combo(dev_priv, phy) &&
-           (is_low_voltage_sku(dev_priv, phy) || !intel_dp_is_edp(intel_dp)))
+       if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
@@ -413,23 +403,7 @@ static int icl_max_source_rate(struct intel_dp *intel_dp)
 
 static int ehl_max_source_rate(struct intel_dp *intel_dp)
 {
-       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-       struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-       enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
-
-       if (intel_dp_is_edp(intel_dp) || is_low_voltage_sku(dev_priv, phy))
-               return 540000;
-
-       return 810000;
-}
-
-static int dg1_max_source_rate(struct intel_dp *intel_dp)
-{
-       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-       struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-       enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
-
-       if (intel_phy_is_combo(i915, phy) && is_low_voltage_sku(i915, phy))
+       if (intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
@@ -491,7 +465,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
                        max_rate = dg2_max_source_rate(intel_dp);
                else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) ||
                         IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
-                       max_rate = dg1_max_source_rate(intel_dp);
+                       max_rate = 810000;
                else if (IS_JSL_EHL(dev_priv))
                        max_rate = ehl_max_source_rate(intel_dp);
                else
@@ -1395,6 +1369,7 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
         * DP_DSC_RC_BUF_SIZE for this.
         */
        vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
+       vdsc_cfg->pic_height = crtc_state->hw.adjusted_mode.crtc_vdisplay;
 
        /*
         * Slice Height of 8 works for all currently available panels. So start
@@ -5293,8 +5268,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 
        intel_panel_init(intel_connector);
 
-       if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
-               intel_connector->panel.backlight.power = intel_pps_backlight_power;
        intel_backlight_setup(intel_connector, pipe);
 
        intel_edp_add_properties(intel_dp);
index 9feaf1a..d213d8a 100644 (file)
@@ -671,6 +671,28 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp,
        intel_dp_compute_rate(intel_dp, crtc_state->port_clock,
                              &link_bw, &rate_select);
 
+       /*
+        * WaEdpLinkRateDataReload
+        *
+        * Parade PS8461E MUX (used on varius TGL+ laptops) needs
+        * to snoop the link rates reported by the sink when we
+        * use LINK_RATE_SET in order to operate in jitter cleaning
+        * mode (as opposed to redriver mode). Unfortunately it
+        * loses track of the snooped link rates when powered down,
+        * so we need to make it re-snoop often. Without this high
+        * link rates are not stable.
+        */
+       if (!link_bw) {
+               struct intel_connector *connector = intel_dp->attached_connector;
+               __le16 sink_rates[DP_MAX_SUPPORTED_RATES];
+
+               drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] Reloading eDP link rates\n",
+                           connector->base.base.id, connector->base.name);
+
+               drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
+                                sink_rates, sizeof(sink_rates));
+       }
+
        if (link_bw)
                drm_dbg_kms(&i915->drm,
                            "[ENCODER:%d:%s] Using LINK_BW_SET value %02x\n",
index c8488f5..e415cd7 100644 (file)
@@ -191,6 +191,9 @@ static struct intel_quirk intel_quirks[] = {
        /* ASRock ITX*/
        { 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
        { 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
+       /* ECS Liva Q2 */
+       { 0x3185, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
+       { 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
 };
 
 void intel_init_quirks(struct drm_i915_private *i915)
index 43e1bbc..ca530f0 100644 (file)
@@ -460,7 +460,6 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
        u8 i = 0;
 
        vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay;
-       vdsc_cfg->pic_height = pipe_config->hw.adjusted_mode.crtc_vdisplay;
        vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width,
                                             pipe_config->dsc.slice_count);
 
index b9b1fed..35136d2 100644 (file)
@@ -1933,7 +1933,14 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
        else
                intel_dsi->ports = BIT(port);
 
+       if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports))
+               intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports;
+
        intel_dsi->dcs_backlight_ports = intel_connector->panel.vbt.dsi.bl_ports;
+
+       if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports))
+               intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports;
+
        intel_dsi->dcs_cabc_ports = intel_connector->panel.vbt.dsi.cabc_ports;
 
        /* Create a DSI host (and a device) for each port. */
index dabdfe0..0bcde53 100644 (file)
@@ -1269,6 +1269,10 @@ static void i915_gem_context_release_work(struct work_struct *work)
        trace_i915_context_free(ctx);
        GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
 
+       spin_lock(&ctx->i915->gem.contexts.lock);
+       list_del(&ctx->link);
+       spin_unlock(&ctx->i915->gem.contexts.lock);
+
        if (ctx->syncobj)
                drm_syncobj_put(ctx->syncobj);
 
@@ -1521,10 +1525,6 @@ static void context_close(struct i915_gem_context *ctx)
 
        ctx->file_priv = ERR_PTR(-EBADF);
 
-       spin_lock(&ctx->i915->gem.contexts.lock);
-       list_del(&ctx->link);
-       spin_unlock(&ctx->i915->gem.contexts.lock);
-
        client = ctx->client;
        if (client) {
                spin_lock(&client->ctx_lock);
index 389e9f1..85482a0 100644 (file)
@@ -723,6 +723,9 @@ bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj)
        bool lmem_placement = false;
        int i;
 
+       if (!HAS_FLAT_CCS(to_i915(obj->base.dev)))
+               return false;
+
        for (i = 0; i < obj->mm.n_placements; i++) {
                /* Compression is not allowed for the objects with smem placement */
                if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM)
index f131dc0..6f3ab7a 100644 (file)
@@ -297,7 +297,7 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
                i915_tt->is_shmem = true;
        }
 
-       if (HAS_FLAT_CCS(i915) && i915_gem_object_needs_ccs_pages(obj))
+       if (i915_gem_object_needs_ccs_pages(obj))
                ccs_pages = DIV_ROUND_UP(DIV_ROUND_UP(bo->base.size,
                                                      NUM_BYTES_PER_CCS_BYTE),
                                         PAGE_SIZE);
index 633a7e5..6b5d4ea 100644 (file)
@@ -166,6 +166,21 @@ struct intel_engine_execlists {
        struct timer_list preempt;
 
        /**
+        * @preempt_target: active request at the time of the preemption request
+        *
+        * We force a preemption to occur if the pending contexts have not
+        * been promoted to active upon receipt of the CS ack event within
+        * the timeout. This timeout maybe chosen based on the target,
+        * using a very short timeout if the context is no longer schedulable.
+        * That short timeout may not be applicable to other contexts, so
+        * if a context switch should happen within before the preemption
+        * timeout, we may shoot early at an innocent context. To prevent this,
+        * we record which context was active at the time of the preemption
+        * request and only reset that context upon the timeout.
+        */
+       const struct i915_request *preempt_target;
+
+       /**
         * @ccid: identifier for contexts submitted to this engine
         */
        u32 ccid;
index 4b909cb..c718e6d 100644 (file)
@@ -1241,6 +1241,9 @@ static unsigned long active_preempt_timeout(struct intel_engine_cs *engine,
        if (!rq)
                return 0;
 
+       /* Only allow ourselves to force reset the currently active context */
+       engine->execlists.preempt_target = rq;
+
        /* Force a fast reset for terminated contexts (ignoring sysfs!) */
        if (unlikely(intel_context_is_banned(rq->context) || bad_request(rq)))
                return INTEL_CONTEXT_BANNED_PREEMPT_TIMEOUT_MS;
@@ -2427,8 +2430,24 @@ static void execlists_submission_tasklet(struct tasklet_struct *t)
        GEM_BUG_ON(inactive - post > ARRAY_SIZE(post));
 
        if (unlikely(preempt_timeout(engine))) {
+               const struct i915_request *rq = *engine->execlists.active;
+
+               /*
+                * If after the preempt-timeout expired, we are still on the
+                * same active request/context as before we initiated the
+                * preemption, reset the engine.
+                *
+                * However, if we have processed a CS event to switch contexts,
+                * but not yet processed the CS event for the pending
+                * preemption, reset the timer allowing the new context to
+                * gracefully exit.
+                */
                cancel_timer(&engine->execlists.preempt);
-               engine->execlists.error_interrupt |= ERROR_PREEMPT;
+               if (rq == engine->execlists.preempt_target)
+                       engine->execlists.error_interrupt |= ERROR_PREEMPT;
+               else
+                       set_timer_ms(&engine->execlists.preempt,
+                                    active_preempt_timeout(engine, rq));
        }
 
        if (unlikely(READ_ONCE(engine->execlists.error_interrupt))) {
index 73a8b46..d09a0e8 100644 (file)
@@ -545,8 +545,7 @@ static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_ratl, RATL_MASK);
 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_thermalert, VR_THERMALERT_MASK);
 static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_tdc, VR_TDC_MASK);
 
-static const struct attribute *freq_attrs[] = {
-       &dev_attr_punit_req_freq_mhz.attr,
+static const struct attribute *throttle_reason_attrs[] = {
        &attr_throttle_reason_status.attr,
        &attr_throttle_reason_pl1.attr,
        &attr_throttle_reason_pl2.attr,
@@ -763,12 +762,20 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
        if (!is_object_gt(kobj))
                return;
 
-       ret = sysfs_create_files(kobj, freq_attrs);
+       ret = sysfs_create_file(kobj, &dev_attr_punit_req_freq_mhz.attr);
        if (ret)
                drm_warn(&gt->i915->drm,
-                        "failed to create gt%u throttle sysfs files (%pe)",
+                        "failed to create gt%u punit_req_freq_mhz sysfs (%pe)",
                         gt->info.id, ERR_PTR(ret));
 
+       if (GRAPHICS_VER(gt->i915) >= 11) {
+               ret = sysfs_create_files(kobj, throttle_reason_attrs);
+               if (ret)
+                       drm_warn(&gt->i915->drm,
+                                "failed to create gt%u throttle sysfs files (%pe)",
+                                gt->info.id, ERR_PTR(ret));
+       }
+
        if (HAS_MEDIA_RATIO_MODE(gt->i915) && intel_uc_uses_guc_slpc(&gt->uc)) {
                ret = sysfs_create_files(kobj, media_perf_power_attrs);
                if (ret)
index 14fe658..1d19c07 100644 (file)
@@ -12,6 +12,7 @@
 #include "intel_llc.h"
 #include "intel_mchbar_regs.h"
 #include "intel_pcode.h"
+#include "intel_rps.h"
 
 struct ia_constants {
        unsigned int min_gpu_freq;
@@ -55,9 +56,6 @@ static bool get_ia_constants(struct intel_llc *llc,
        if (!HAS_LLC(i915) || IS_DGFX(i915))
                return false;
 
-       if (rps->max_freq <= rps->min_freq)
-               return false;
-
        consts->max_ia_freq = cpu_max_MHz();
 
        consts->min_ring_freq =
@@ -65,13 +63,8 @@ static bool get_ia_constants(struct intel_llc *llc,
        /* convert DDR frequency from units of 266.6MHz to bandwidth */
        consts->min_ring_freq = mult_frac(consts->min_ring_freq, 8, 3);
 
-       consts->min_gpu_freq = rps->min_freq;
-       consts->max_gpu_freq = rps->max_freq;
-       if (GRAPHICS_VER(i915) >= 9) {
-               /* Convert GT frequency to 50 HZ units */
-               consts->min_gpu_freq /= GEN9_FREQ_SCALER;
-               consts->max_gpu_freq /= GEN9_FREQ_SCALER;
-       }
+       consts->min_gpu_freq = intel_rps_get_min_raw_freq(rps);
+       consts->max_gpu_freq = intel_rps_get_max_raw_freq(rps);
 
        return true;
 }
@@ -131,6 +124,12 @@ static void gen6_update_ring_freq(struct intel_llc *llc)
                return;
 
        /*
+        * Although this is unlikely on any platform during initialization,
+        * let's ensure we don't get accidentally into infinite loop
+        */
+       if (consts.max_gpu_freq <= consts.min_gpu_freq)
+               return;
+       /*
         * For each potential GPU frequency, load a ring frequency we'd like
         * to use for memory access.  We do this by specifying the IA frequency
         * the PCU should use as a reference to determine the ring frequency.
index 2b10b96..933648c 100644 (file)
@@ -638,9 +638,9 @@ static int emit_copy(struct i915_request *rq,
        return 0;
 }
 
-static int scatter_list_length(struct scatterlist *sg)
+static u64 scatter_list_length(struct scatterlist *sg)
 {
-       int len = 0;
+       u64 len = 0;
 
        while (sg && sg_dma_len(sg)) {
                len += sg_dma_len(sg);
@@ -650,28 +650,26 @@ static int scatter_list_length(struct scatterlist *sg)
        return len;
 }
 
-static void
+static int
 calculate_chunk_sz(struct drm_i915_private *i915, bool src_is_lmem,
-                  int *src_sz, u32 bytes_to_cpy, u32 ccs_bytes_to_cpy)
+                  u64 bytes_to_cpy, u64 ccs_bytes_to_cpy)
 {
-       if (ccs_bytes_to_cpy) {
-               if (!src_is_lmem)
-                       /*
-                        * When CHUNK_SZ is passed all the pages upto CHUNK_SZ
-                        * will be taken for the blt. in Flat-ccs supported
-                        * platform Smem obj will have more pages than required
-                        * for main meory hence limit it to the required size
-                        * for main memory
-                        */
-                       *src_sz = min_t(int, bytes_to_cpy, CHUNK_SZ);
-       } else { /* ccs handling is not required */
-               *src_sz = CHUNK_SZ;
-       }
+       if (ccs_bytes_to_cpy && !src_is_lmem)
+               /*
+                * When CHUNK_SZ is passed all the pages upto CHUNK_SZ
+                * will be taken for the blt. in Flat-ccs supported
+                * platform Smem obj will have more pages than required
+                * for main meory hence limit it to the required size
+                * for main memory
+                */
+               return min_t(u64, bytes_to_cpy, CHUNK_SZ);
+       else
+               return CHUNK_SZ;
 }
 
-static void get_ccs_sg_sgt(struct sgt_dma *it, u32 bytes_to_cpy)
+static void get_ccs_sg_sgt(struct sgt_dma *it, u64 bytes_to_cpy)
 {
-       u32 len;
+       u64 len;
 
        do {
                GEM_BUG_ON(!it->sg || !sg_dma_len(it->sg));
@@ -702,12 +700,12 @@ intel_context_migrate_copy(struct intel_context *ce,
 {
        struct sgt_dma it_src = sg_sgt(src), it_dst = sg_sgt(dst), it_ccs;
        struct drm_i915_private *i915 = ce->engine->i915;
-       u32 ccs_bytes_to_cpy = 0, bytes_to_cpy;
+       u64 ccs_bytes_to_cpy = 0, bytes_to_cpy;
        enum i915_cache_level ccs_cache_level;
        u32 src_offset, dst_offset;
        u8 src_access, dst_access;
        struct i915_request *rq;
-       int src_sz, dst_sz;
+       u64 src_sz, dst_sz;
        bool ccs_is_src, overwrite_ccs;
        int err;
 
@@ -790,8 +788,8 @@ intel_context_migrate_copy(struct intel_context *ce,
                if (err)
                        goto out_rq;
 
-               calculate_chunk_sz(i915, src_is_lmem, &src_sz,
-                                  bytes_to_cpy, ccs_bytes_to_cpy);
+               src_sz = calculate_chunk_sz(i915, src_is_lmem,
+                                           bytes_to_cpy, ccs_bytes_to_cpy);
 
                len = emit_pte(rq, &it_src, src_cache_level, src_is_lmem,
                               src_offset, src_sz);
index fb3f57e..7bb9670 100644 (file)
@@ -2126,6 +2126,31 @@ u32 intel_rps_get_max_frequency(struct intel_rps *rps)
                return intel_gpu_freq(rps, rps->max_freq_softlimit);
 }
 
+/**
+ * intel_rps_get_max_raw_freq - returns the max frequency in some raw format.
+ * @rps: the intel_rps structure
+ *
+ * Returns the max frequency in a raw format. In newer platforms raw is in
+ * units of 50 MHz.
+ */
+u32 intel_rps_get_max_raw_freq(struct intel_rps *rps)
+{
+       struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+       u32 freq;
+
+       if (rps_uses_slpc(rps)) {
+               return DIV_ROUND_CLOSEST(slpc->rp0_freq,
+                                        GT_FREQUENCY_MULTIPLIER);
+       } else {
+               freq = rps->max_freq;
+               if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
+                       /* Convert GT frequency to 50 MHz units */
+                       freq /= GEN9_FREQ_SCALER;
+               }
+               return freq;
+       }
+}
+
 u32 intel_rps_get_rp0_frequency(struct intel_rps *rps)
 {
        struct intel_guc_slpc *slpc = rps_to_slpc(rps);
@@ -2214,6 +2239,31 @@ u32 intel_rps_get_min_frequency(struct intel_rps *rps)
                return intel_gpu_freq(rps, rps->min_freq_softlimit);
 }
 
+/**
+ * intel_rps_get_min_raw_freq - returns the min frequency in some raw format.
+ * @rps: the intel_rps structure
+ *
+ * Returns the min frequency in a raw format. In newer platforms raw is in
+ * units of 50 MHz.
+ */
+u32 intel_rps_get_min_raw_freq(struct intel_rps *rps)
+{
+       struct intel_guc_slpc *slpc = rps_to_slpc(rps);
+       u32 freq;
+
+       if (rps_uses_slpc(rps)) {
+               return DIV_ROUND_CLOSEST(slpc->min_freq,
+                                        GT_FREQUENCY_MULTIPLIER);
+       } else {
+               freq = rps->min_freq;
+               if (GRAPHICS_VER(rps_to_i915(rps)) >= 9) {
+                       /* Convert GT frequency to 50 MHz units */
+                       freq /= GEN9_FREQ_SCALER;
+               }
+               return freq;
+       }
+}
+
 static int set_min_freq(struct intel_rps *rps, u32 val)
 {
        int ret = 0;
index 1e8d564..4509dfd 100644 (file)
@@ -37,8 +37,10 @@ u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
 u32 intel_rps_read_actual_frequency(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);
 int intel_rps_set_min_frequency(struct intel_rps *rps, u32 val);
 u32 intel_rps_get_max_frequency(struct intel_rps *rps);
+u32 intel_rps_get_max_raw_freq(struct intel_rps *rps);
 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);
index 76916ae..3e91f44 100644 (file)
@@ -1438,7 +1438,12 @@ void intel_guc_busyness_park(struct intel_gt *gt)
        if (!guc_submission_initialized(guc))
                return;
 
-       cancel_delayed_work(&guc->timestamp.work);
+       /*
+        * There is a race with suspend flow where the worker runs after suspend
+        * and causes an unclaimed register access warning. Cancel the worker
+        * synchronously here.
+        */
+       cancel_delayed_work_sync(&guc->timestamp.work);
 
        /*
         * Before parking, we should sample engine busyness stats if we need to.
@@ -4027,6 +4032,13 @@ static inline void guc_init_lrc_mapping(struct intel_guc *guc)
        xa_destroy(&guc->context_lookup);
 
        /*
+        * A reset might have occurred while we had a pending stalled request,
+        * so make sure we clean that up.
+        */
+       guc->stalled_request = NULL;
+       guc->submission_stall_reason = STALL_NONE;
+
+       /*
         * Some contexts might have been pinned before we enabled GuC
         * submission, so we need to add them to the GuC bookeeping.
         * Also, after a reset the of the GuC we want to make sure that the
index 557f331..3b81a6d 100644 (file)
@@ -298,7 +298,7 @@ no_enough_resource:
 }
 
 /**
- * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU
+ * intel_vgpu_free_resource() - free HW resource owned by a vGPU
  * @vgpu: a vGPU
  *
  * This function is used to free the HW resource owned by a vGPU.
@@ -328,7 +328,7 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
 }
 
 /**
- * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
+ * intel_vgpu_alloc_resource() - allocate HW resource for a vGPU
  * @vgpu: vGPU
  * @param: vGPU creation params
  *
index b4f6936..ce0eb03 100644 (file)
@@ -2341,7 +2341,7 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
                        gvt_vgpu_err("fail to populate guest ggtt entry\n");
                        /* guest driver may read/write the entry when partial
                         * update the entry in this situation p2m will fail
-                        * settting the shadow entry to point to a scratch page
+                        * setting the shadow entry to point to a scratch page
                         */
                        ops->set_pfn(&m, gvt->gtt.scratch_mfn);
                } else
index beea589..61423da 100644 (file)
@@ -905,7 +905,7 @@ static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu,
        else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX)
                index = FDI_RX_IMR_TO_PIPE(offset);
        else {
-               gvt_vgpu_err("Unsupport registers %x\n", offset);
+               gvt_vgpu_err("Unsupported registers %x\n", offset);
                return -EINVAL;
        }
 
@@ -3052,7 +3052,7 @@ int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
 }
 
 /**
- * intel_t_default_mmio_write - default MMIO write handler
+ * intel_vgpu_default_mmio_write() - default MMIO write handler
  * @vgpu: a vGPU
  * @offset: access offset
  * @p_data: write data buffer
index c85bafe..1c6e941 100644 (file)
@@ -546,7 +546,7 @@ static void switch_mmio(struct intel_vgpu *pre,
 }
 
 /**
- * intel_gvt_switch_render_mmio - switch mmio context of specific engine
+ * intel_gvt_switch_mmio - switch mmio context of specific engine
  * @pre: the last vGPU that own the engine
  * @next: the vGPU to switch to
  * @engine: the engine
index 702e5b8..b605d0c 100644 (file)
@@ -1191,7 +1191,8 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv)
 
        intel_uc_cleanup_firmwares(&to_gt(dev_priv)->uc);
 
-       i915_gem_drain_freed_objects(dev_priv);
+       /* Flush any outstanding work, including i915_gem_context.release_work. */
+       i915_gem_drain_workqueue(dev_priv);
 
        drm_WARN_ON(&dev_priv->drm, !list_empty(&dev_priv->gem.contexts.list));
 }
index 3168d70..135d04c 100644 (file)
 
 #define GT0_PERF_LIMIT_REASONS         _MMIO(0x1381a8)
 #define   GT0_PERF_LIMIT_REASONS_MASK  0xde3
-#define   PROCHOT_MASK                 REG_BIT(1)
-#define   THERMAL_LIMIT_MASK           REG_BIT(2)
-#define   RATL_MASK                    REG_BIT(6)
-#define   VR_THERMALERT_MASK           REG_BIT(7)
-#define   VR_TDC_MASK                  REG_BIT(8)
-#define   POWER_LIMIT_4_MASK           REG_BIT(9)
-#define   POWER_LIMIT_1_MASK           REG_BIT(11)
-#define   POWER_LIMIT_2_MASK           REG_BIT(12)
+#define   PROCHOT_MASK                 REG_BIT(0)
+#define   THERMAL_LIMIT_MASK           REG_BIT(1)
+#define   RATL_MASK                    REG_BIT(5)
+#define   VR_THERMALERT_MASK           REG_BIT(6)
+#define   VR_TDC_MASK                  REG_BIT(7)
+#define   POWER_LIMIT_4_MASK           REG_BIT(8)
+#define   POWER_LIMIT_1_MASK           REG_BIT(10)
+#define   POWER_LIMIT_2_MASK           REG_BIT(11)
 
 #define CHV_CLK_CTL1                   _MMIO(0x101100)
 #define VLV_CLK_CTL2                   _MMIO(0x101104)
index 2603717..373582c 100644 (file)
@@ -1882,12 +1882,13 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
                enum dma_resv_usage usage;
                int idx;
 
-               obj->read_domains = 0;
                if (flags & EXEC_OBJECT_WRITE) {
                        usage = DMA_RESV_USAGE_WRITE;
                        obj->write_domain = I915_GEM_DOMAIN_RENDER;
+                       obj->read_domains = 0;
                } else {
                        usage = DMA_RESV_USAGE_READ;
+                       obj->write_domain = 0;
                }
 
                dma_fence_array_for_each(curr, idx, fence)
index 157e166..5595639 100644 (file)
@@ -1076,7 +1076,8 @@ static int iterate_skl_plus_mmio(struct intel_gvt_mmio_table_iter *iter)
        MMIO_D(GEN8_HDC_CHICKEN1);
        MMIO_D(GEN9_WM_CHICKEN3);
 
-       if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv))
+       if (IS_KABYLAKE(dev_priv) ||
+           IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv))
                MMIO_D(GAMT_CHKN_BIT_REG);
        if (!IS_BROXTON(dev_priv))
                MMIO_D(GEN9_CTX_PREEMPT_REG);
index f06babd..9fe4b58 100644 (file)
@@ -6561,7 +6561,10 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
                enum plane_id plane_id;
                u8 slices;
 
-               skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
+               memset(&crtc_state->wm.skl.optimal, 0,
+                      sizeof(crtc_state->wm.skl.optimal));
+               if (crtc_state->hw.active)
+                       skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal);
                crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal;
 
                memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe]));
@@ -6572,6 +6575,9 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
                        struct skl_ddb_entry *ddb_y =
                                &crtc_state->wm.skl.plane_ddb_y[plane_id];
 
+                       if (!crtc_state->hw.active)
+                               continue;
+
                        skl_ddb_get_hw_plane_state(dev_priv, crtc->pipe,
                                                   plane_id, ddb, ddb_y);
 
index 2d72cc5..6b6d533 100644 (file)
@@ -157,7 +157,7 @@ static void mtk_dither_config(struct device *dev, unsigned int w,
 {
        struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
-       mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_REG_DITHER_SIZE);
+       mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_REG_DITHER_SIZE);
        mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, &priv->cmdq_reg, priv->regs,
                      DISP_REG_DITHER_CFG);
        mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, DISP_REG_DITHER_CFG,
index 9cc406e..3b7d130 100644 (file)
@@ -685,6 +685,16 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
        if (--dsi->refcount != 0)
                return;
 
+       /*
+        * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since
+        * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(),
+        * which needs irq for vblank, and mtk_dsi_stop() will disable irq.
+        * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(),
+        * after dsi is fully set.
+        */
+       mtk_dsi_stop(dsi);
+
+       mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
        mtk_dsi_reset_engine(dsi);
        mtk_dsi_lane0_ulp_mode_enter(dsi);
        mtk_dsi_clk_ulp_mode_enter(dsi);
@@ -735,17 +745,6 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
        if (!dsi->enabled)
                return;
 
-       /*
-        * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since
-        * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(),
-        * which needs irq for vblank, and mtk_dsi_stop() will disable irq.
-        * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(),
-        * after dsi is fully set.
-        */
-       mtk_dsi_stop(dsi);
-
-       mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
-
        dsi->enabled = false;
 }
 
@@ -808,10 +807,13 @@ static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
 
 static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = {
        .attach = mtk_dsi_bridge_attach,
+       .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
        .atomic_disable = mtk_dsi_bridge_atomic_disable,
+       .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
        .atomic_enable = mtk_dsi_bridge_atomic_enable,
        .atomic_pre_enable = mtk_dsi_bridge_atomic_pre_enable,
        .atomic_post_disable = mtk_dsi_bridge_atomic_post_disable,
+       .atomic_reset = drm_atomic_helper_bridge_reset,
        .mode_set = mtk_dsi_bridge_mode_set,
 };
 
index b9ac932..03acc68 100644 (file)
@@ -170,7 +170,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
 
        /* Enable OSD and BLK0, set max global alpha */
        priv->viu.osd1_ctrl_stat = OSD_ENABLE |
-                                  (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
+                                  (0x100 << OSD_GLOBAL_ALPHA_SHIFT) |
                                   OSD_BLK0_ENABLE;
 
        priv->viu.osd1_ctrl_stat2 = readl(priv->io_base +
index bb7e109..d4b9078 100644 (file)
@@ -94,7 +94,7 @@ static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
        writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
-       writel((m[11] & 0x1fff) << 16,
+       writel((m[11] & 0x1fff),
                priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
 
        writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
index 251a1bb..a222bf7 100644 (file)
@@ -262,7 +262,11 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ret)
                return ret;
 
-       drm_fbdev_generic_setup(dev, 0);
+       /*
+        * FIXME: A 24-bit color depth does not work with 24 bpp on
+        * G200ER. Force 32 bpp.
+        */
+       drm_fbdev_generic_setup(dev, 32);
 
        return 0;
 }
index c682d4e..52a6261 100644 (file)
@@ -2061,6 +2061,12 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
 
        intf_cfg.stream_sel = 0; /* Don't care value for video mode */
        intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+
+       if (phys_enc->hw_intf)
+               intf_cfg.intf = phys_enc->hw_intf->idx;
+       if (phys_enc->hw_wb)
+               intf_cfg.wb = phys_enc->hw_wb->idx;
+
        if (phys_enc->hw_pp->merge_3d)
                intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
 
index ab6aa13..013ca02 100644 (file)
@@ -1214,7 +1214,7 @@ static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,
        if (ret)
                return ret;
 
-       dp_ctrl_train_pattern_set(ctrl, pattern | DP_RECOVERED_CLOCK_OUT_EN);
+       dp_ctrl_train_pattern_set(ctrl, pattern);
 
        for (tries = 0; tries <= maximum_retries; tries++) {
                drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd);
index 2c23324..72c018e 100644 (file)
@@ -109,7 +109,7 @@ static const char * const dsi_8996_bus_clk_names[] = {
 static const struct msm_dsi_config msm8996_dsi_cfg = {
        .io_offset = DSI_6G_REG_SHIFT,
        .reg_cfg = {
-               .num = 2,
+               .num = 3,
                .regs = {
                        {"vdda", 18160, 1 },    /* 1.25 V */
                        {"vcca", 17000, 32 },   /* 0.925 V */
@@ -148,7 +148,7 @@ static const char * const dsi_sdm660_bus_clk_names[] = {
 static const struct msm_dsi_config sdm660_dsi_cfg = {
        .io_offset = DSI_6G_REG_SHIFT,
        .reg_cfg = {
-               .num = 2,
+               .num = 1,
                .regs = {
                        {"vdda", 12560, 4 },    /* 1.2 V */
                },
index a39de3b..56dfa2d 100644 (file)
@@ -347,7 +347,7 @@ int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
        } else {
                timing->shared_timings.clk_pre =
                        linear_inter(tmax, tmin, pcnt2, 0, false);
-                       timing->shared_timings.clk_pre_inc_by_2 = 0;
+               timing->shared_timings.clk_pre_inc_by_2 = 0;
        }
 
        timing->ta_go = 3;
index 1ed4cd0..16884db 100644 (file)
@@ -469,6 +469,8 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
                }
        }
 
+       drm_helper_move_panel_connectors_to_head(ddev);
+
        ddev->mode_config.funcs = &mode_config_funcs;
        ddev->mode_config.helper_private = &mode_config_helper_funcs;
 
index d1f7042..85c443a 100644 (file)
@@ -213,6 +213,8 @@ void msm_devfreq_init(struct msm_gpu *gpu)
 
        if (IS_ERR(df->devfreq)) {
                DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
+               dev_pm_qos_remove_request(&df->idle_freq);
+               dev_pm_qos_remove_request(&df->boost_freq);
                df->devfreq = NULL;
                return;
        }
index a92ffde..db2f847 100644 (file)
@@ -196,6 +196,9 @@ static int rd_open(struct inode *inode, struct file *file)
        file->private_data = rd;
        rd->open = true;
 
+       /* Reset fifo to clear any previously unread data: */
+       rd->fifo.head = rd->fifo.tail = 0;
+
        /* the parsing tools need to know gpu-id to know which
         * register database to load.
         *
index cdb154c..b75c690 100644 (file)
@@ -1295,7 +1295,8 @@ static const struct panel_desc innolux_n116bca_ea1 = {
        },
        .delay = {
                .hpd_absent = 200,
-               .prepare_to_enable = 80,
+               .enable = 80,
+               .disable = 50,
                .unprepare = 500,
        },
 };
index ff5e1a4..1e716c2 100644 (file)
@@ -2257,7 +2257,7 @@ static const struct panel_desc innolux_g121i1_l01 = {
                .enable = 200,
                .disable = 20,
        },
-       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
        .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
index 5110cd9..fe5f12f 100644 (file)
@@ -131,6 +131,17 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
                return PTR_ERR(opp);
 
        panfrost_devfreq_profile.initial_freq = cur_freq;
+
+       /*
+        * Set the recommend OPP this will enable and configure the regulator
+        * if any and will avoid a switch off by regulator_late_cleanup()
+        */
+       ret = dev_pm_opp_set_opp(dev, opp);
+       if (ret) {
+               DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n");
+               return ret;
+       }
+
        dev_pm_opp_put(opp);
 
        /*
index c204e9b..518ee13 100644 (file)
@@ -283,8 +283,9 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector)
        return ret;
 }
 
-static int cdn_dp_connector_mode_valid(struct drm_connector *connector,
-                                      struct drm_display_mode *mode)
+static enum drm_mode_status
+cdn_dp_connector_mode_valid(struct drm_connector *connector,
+                           struct drm_display_mode *mode)
 {
        struct cdn_dp_device *dp = connector_to_dp(connector);
        struct drm_display_info *display_info = &dp->connector.display_info;
index e4631f5..f9aa8b9 100644 (file)
@@ -1439,11 +1439,15 @@ static void rk3568_set_intf_mux(struct vop2_video_port *vp, int id,
                die &= ~RK3568_SYS_DSP_INFACE_EN_HDMI_MUX;
                die |= RK3568_SYS_DSP_INFACE_EN_HDMI |
                           FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_HDMI_MUX, vp->id);
+               dip &= ~RK3568_DSP_IF_POL__HDMI_PIN_POL;
+               dip |= FIELD_PREP(RK3568_DSP_IF_POL__HDMI_PIN_POL, polflags);
                break;
        case ROCKCHIP_VOP2_EP_EDP0:
                die &= ~RK3568_SYS_DSP_INFACE_EN_EDP_MUX;
                die |= RK3568_SYS_DSP_INFACE_EN_EDP |
                           FIELD_PREP(RK3568_SYS_DSP_INFACE_EN_EDP_MUX, vp->id);
+               dip &= ~RK3568_DSP_IF_POL__EDP_PIN_POL;
+               dip |= FIELD_PREP(RK3568_DSP_IF_POL__EDP_PIN_POL, polflags);
                break;
        case ROCKCHIP_VOP2_EP_MIPI0:
                die &= ~RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX;
index 1cbfb00..911141d 100644 (file)
@@ -236,16 +236,19 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        if (bo->type != ttm_bo_type_sg)
                fbo->base.base.resv = &fbo->base.base._resv;
 
-       if (fbo->base.resource) {
-               ttm_resource_set_bo(fbo->base.resource, &fbo->base);
-               bo->resource = NULL;
-       }
-
        dma_resv_init(&fbo->base.base._resv);
        fbo->base.base.dev = NULL;
        ret = dma_resv_trylock(&fbo->base.base._resv);
        WARN_ON(!ret);
 
+       if (fbo->base.resource) {
+               ttm_resource_set_bo(fbo->base.resource, &fbo->base);
+               bo->resource = NULL;
+               ttm_bo_set_bulk_move(&fbo->base, NULL);
+       } else {
+               fbo->base.bulk_move = NULL;
+       }
+
        ret = dma_resv_reserve_fences(&fbo->base.base._resv, 1);
        if (ret) {
                kfree(fbo);
index 4b90c86..47774b9 100644 (file)
@@ -288,11 +288,29 @@ int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
        return 0;
 }
 
+static const struct dmi_system_id dmi_nodevs[] = {
+       {
+               /*
+                * Google Chromebooks use Chrome OS Embedded Controller Sensor
+                * Hub instead of Sensor Hub Fusion and leaves MP2
+                * uninitialized, which disables all functionalities, even
+                * including the registers necessary for feature detections.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+               },
+       },
+       { }
+};
+
 static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct amd_mp2_dev *privdata;
        int rc;
 
+       if (dmi_first_match(dmi_nodevs))
+               return -ENODEV;
+
        privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
        if (!privdata)
                return -ENOMEM;
index 08c9a9a..b59c3da 100644 (file)
@@ -1212,6 +1212,13 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc = new_rdesc;
        }
 
+       if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD &&
+                       *rsize == 331 && rdesc[190] == 0x85 && rdesc[191] == 0x5a &&
+                       rdesc[204] == 0x95 && rdesc[205] == 0x05) {
+               hid_info(hdev, "Fixing up Asus N-KEY keyb report descriptor\n");
+               rdesc[205] = 0x01;
+       }
+
        return rdesc;
 }
 
index 0fb720a..f80d619 100644 (file)
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021   0x029c
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021   0x029a
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021   0x029f
+#define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102
+#define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302
 
 #define USB_VENDOR_ID_ASUS             0x0486
 #define USB_DEVICE_ID_ASUS_T91MT       0x0185
 #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN   0x2706
 #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 USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index 48c1c02..859aeb0 100644 (file)
@@ -383,6 +383,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
          HID_BATTERY_QUIRK_IGNORE },
        { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
@@ -1532,7 +1534,10 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
                         * assume ours
                         */
                        if (!report->tool)
-                               hid_report_set_tool(report, input, usage->code);
+                               report->tool = usage->code;
+
+                       /* drivers may have changed the value behind our back, resend it */
+                       hid_report_set_tool(report, input, report->tool);
                } else {
                        hid_report_release_tool(report, input, usage->code);
                }
index 92ac4f6..6028af3 100644 (file)
@@ -1221,6 +1221,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
 
        spin_lock_irqsave(&ctlr->lock, flags);
        if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
+           ctlr->ctlr_state != JOYCON_CTLR_STATE_REMOVED &&
            (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS &&
            (ctlr->rumble_queue_head != ctlr->rumble_queue_tail ||
             ctlr->rumble_zero_countdown > 0)) {
@@ -1545,12 +1546,13 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
                ctlr->rumble_queue_head = 0;
        memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
               JC_RUMBLE_DATA_SIZE);
-       spin_unlock_irqrestore(&ctlr->lock, flags);
 
        /* don't wait for the periodic send (reduces latency) */
-       if (schedule_now)
+       if (schedule_now && ctlr->ctlr_state != JOYCON_CTLR_STATE_REMOVED)
                queue_work(ctlr->rumble_queue, &ctlr->rumble_worker);
 
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+
        return 0;
 }
 
index dc67717..70f602c 100644 (file)
@@ -314,6 +314,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
 #endif
 #if IS_ENABLED(CONFIG_HID_APPLEIR)
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
index a3b151b..fc616db 100644 (file)
@@ -134,6 +134,11 @@ static int steam_recv_report(struct steam_device *steam,
        int ret;
 
        r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+       if (!r) {
+               hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+               return -EINVAL;
+       }
+
        if (hid_report_len(r) < 64)
                return -EINVAL;
 
@@ -165,6 +170,11 @@ static int steam_send_report(struct steam_device *steam,
        int ret;
 
        r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+       if (!r) {
+               hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+               return -EINVAL;
+       }
+
        if (hid_report_len(r) < 64)
                return -EINVAL;
 
index c3e6d69..cf1679b 100644 (file)
@@ -67,12 +67,13 @@ static const struct tm_wheel_info tm_wheels_infos[] = {
        {0x0200, 0x0005, "Thrustmaster T300RS (Missing Attachment)"},
        {0x0206, 0x0005, "Thrustmaster T300RS"},
        {0x0209, 0x0005, "Thrustmaster T300RS (Open Wheel Attachment)"},
+       {0x020a, 0x0005, "Thrustmaster T300RS (Sparco R383 Mod)"},
        {0x0204, 0x0005, "Thrustmaster T300 Ferrari Alcantara Edition"},
        {0x0002, 0x0002, "Thrustmaster T500RS"}
        //{0x0407, 0x0001, "Thrustmaster TMX"}
 };
 
-static const uint8_t tm_wheels_infos_length = 4;
+static const uint8_t tm_wheels_infos_length = 7;
 
 /*
  * This structs contains (in little endian) the response data
index 681614a..197b1e7 100644 (file)
@@ -350,6 +350,8 @@ static int hidraw_release(struct inode * inode, struct file * file)
        down_write(&minors_rwsem);
 
        spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
+       for (int i = list->tail; i < list->head; i++)
+               kfree(list->buffer[i].value);
        list_del(&list->node);
        spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
        kfree(list);
index e600dbf..fc108f1 100644 (file)
@@ -32,6 +32,7 @@
 #define ADL_P_DEVICE_ID                0x51FC
 #define ADL_N_DEVICE_ID                0x54FC
 #define RPL_S_DEVICE_ID                0x7A78
+#define MTL_P_DEVICE_ID                0x7E45
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index 2c67ec1..7120b30 100644 (file)
@@ -43,6 +43,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_P_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index 6a5cc11..35dddc5 100644 (file)
@@ -105,7 +105,7 @@ struct report_list {
  * @multi_packet_cnt:  Count of fragmented packet count
  *
  * This structure is used to store completion flags and per client data like
- * like report description, number of HID devices etc.
+ * report description, number of HID devices etc.
  */
 struct ishtp_cl_data {
        /* completion flags */
index 405e0d5..df0a825 100644 (file)
@@ -626,13 +626,14 @@ static void ishtp_cl_read_complete(struct ishtp_cl_rb *rb)
 }
 
 /**
- * ipc_tx_callback() - IPC tx callback function
+ * ipc_tx_send() - IPC tx send function
  * @prm: Pointer to client device instance
  *
- * Send message over IPC either first time or on callback on previous message
- * completion
+ * Send message over IPC. Message will be split into fragments
+ * if message size is bigger than IPC FIFO size, and all
+ * fragments will be sent one by one.
  */
-static void ipc_tx_callback(void *prm)
+static void ipc_tx_send(void *prm)
 {
        struct ishtp_cl *cl = prm;
        struct ishtp_cl_tx_ring *cl_msg;
@@ -677,32 +678,41 @@ static void ipc_tx_callback(void *prm)
                            list);
        rem = cl_msg->send_buf.size - cl->tx_offs;
 
-       ishtp_hdr.host_addr = cl->host_client_id;
-       ishtp_hdr.fw_addr = cl->fw_client_id;
-       ishtp_hdr.reserved = 0;
-       pmsg = cl_msg->send_buf.data + cl->tx_offs;
+       while (rem > 0) {
+               ishtp_hdr.host_addr = cl->host_client_id;
+               ishtp_hdr.fw_addr = cl->fw_client_id;
+               ishtp_hdr.reserved = 0;
+               pmsg = cl_msg->send_buf.data + cl->tx_offs;
+
+               if (rem <= dev->mtu) {
+                       /* Last fragment or only one packet */
+                       ishtp_hdr.length = rem;
+                       ishtp_hdr.msg_complete = 1;
+                       /* Submit to IPC queue with no callback */
+                       ishtp_write_message(dev, &ishtp_hdr, pmsg);
+                       cl->tx_offs = 0;
+                       cl->sending = 0;
 
-       if (rem <= dev->mtu) {
-               ishtp_hdr.length = rem;
-               ishtp_hdr.msg_complete = 1;
-               cl->sending = 0;
-               list_del_init(&cl_msg->list);   /* Must be before write */
-               spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-               /* Submit to IPC queue with no callback */
-               ishtp_write_message(dev, &ishtp_hdr, pmsg);
-               spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
-               list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
-               ++cl->tx_ring_free_size;
-               spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
-                       tx_free_flags);
-       } else {
-               /* Send IPC fragment */
-               spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-               cl->tx_offs += dev->mtu;
-               ishtp_hdr.length = dev->mtu;
-               ishtp_hdr.msg_complete = 0;
-               ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl);
+                       break;
+               } else {
+                       /* Send ipc fragment */
+                       ishtp_hdr.length = dev->mtu;
+                       ishtp_hdr.msg_complete = 0;
+                       /* All fregments submitted to IPC queue with no callback */
+                       ishtp_write_message(dev, &ishtp_hdr, pmsg);
+                       cl->tx_offs += dev->mtu;
+                       rem = cl_msg->send_buf.size - cl->tx_offs;
+               }
        }
+
+       list_del_init(&cl_msg->list);
+       spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
+
+       spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
+       list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
+       ++cl->tx_ring_free_size;
+       spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
+               tx_free_flags);
 }
 
 /**
@@ -720,7 +730,7 @@ static void ishtp_cl_send_msg_ipc(struct ishtp_device *dev,
                return;
 
        cl->tx_offs = 0;
-       ipc_tx_callback(cl);
+       ipc_tx_send(cl);
        ++cl->send_msg_cnt_ipc;
 }
 
index 660036d..922d83e 100644 (file)
@@ -129,7 +129,7 @@ static void fcopy_send_data(struct work_struct *dummy)
 
        /*
         * The  strings sent from the host are encoded in
-        * in utf16; convert it to utf8 strings.
+        * utf16; convert it to utf8 strings.
         * The host assures us that the utf16 strings will not exceed
         * the max lengths specified. We will however, reserve room
         * for the string terminating character - in the utf16s_utf8s()
index 23c680d..7b9f3fc 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/syscore_ops.h>
 #include <linux/dma-map-ops.h>
+#include <linux/pci.h>
 #include <clocksource/hyperv_timer.h>
 #include "hyperv_vmbus.h"
 
@@ -2262,26 +2263,43 @@ static int vmbus_acpi_remove(struct acpi_device *device)
 
 static void vmbus_reserve_fb(void)
 {
-       int size;
+       resource_size_t start = 0, size;
+       struct pci_dev *pdev;
+
+       if (efi_enabled(EFI_BOOT)) {
+               /* Gen2 VM: get FB base from EFI framebuffer */
+               start = screen_info.lfb_base;
+               size = max_t(__u32, screen_info.lfb_size, 0x800000);
+       } else {
+               /* Gen1 VM: get FB base from PCI */
+               pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
+                                     PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
+               if (!pdev)
+                       return;
+
+               if (pdev->resource[0].flags & IORESOURCE_MEM) {
+                       start = pci_resource_start(pdev, 0);
+                       size = pci_resource_len(pdev, 0);
+               }
+
+               /*
+                * Release the PCI device so hyperv_drm or hyperv_fb driver can
+                * grab it later.
+                */
+               pci_dev_put(pdev);
+       }
+
+       if (!start)
+               return;
+
        /*
         * Make a claim for the frame buffer in the resource tree under the
         * first node, which will be the one below 4GB.  The length seems to
         * be underreported, particularly in a Generation 1 VM.  So start out
         * reserving a larger area and make it smaller until it succeeds.
         */
-
-       if (screen_info.lfb_base) {
-               if (efi_enabled(EFI_BOOT))
-                       size = max_t(__u32, screen_info.lfb_size, 0x800000);
-               else
-                       size = max_t(__u32, screen_info.lfb_size, 0x4000000);
-
-               for (; !fb_mmio && (size >= 0x100000); size >>= 1) {
-                       fb_mmio = __request_region(hyperv_mmio,
-                                                  screen_info.lfb_base, size,
-                                                  fb_mmio_name, 0);
-               }
-       }
+       for (; !fb_mmio && (size >= 0x100000); size >>= 1)
+               fb_mmio = __request_region(hyperv_mmio, start, size, fb_mmio_name, 0);
 }
 
 /**
@@ -2313,7 +2331,7 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
                        bool fb_overlap_ok)
 {
        struct resource *iter, *shadow;
-       resource_size_t range_min, range_max, start;
+       resource_size_t range_min, range_max, start, end;
        const char *dev_n = dev_name(&device_obj->device);
        int retval;
 
@@ -2348,6 +2366,14 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
                range_max = iter->end;
                start = (range_min + align - 1) & ~(align - 1);
                for (; start + size - 1 <= range_max; start += align) {
+                       end = start + size - 1;
+
+                       /* Skip the whole fb_mmio region if not fb_overlap_ok */
+                       if (!fb_overlap_ok && fb_mmio &&
+                           (((start >= fb_mmio->start) && (start <= fb_mmio->end)) ||
+                            ((end >= fb_mmio->start) && (end <= fb_mmio->end))))
+                               continue;
+
                        shadow = __request_region(iter, start, size, NULL,
                                                  IORESOURCE_BUSY);
                        if (!shadow)
@@ -2427,7 +2453,8 @@ static int vmbus_acpi_add(struct acpi_device *device)
         * Some ancestor of the vmbus acpi device (Gen1 or Gen2
         * firmware) is the VMOD that has the mmio ranges. Get that.
         */
-       for (ancestor = device->parent; ancestor; ancestor = ancestor->parent) {
+       for (ancestor = acpi_dev_parent(device); ancestor;
+            ancestor = acpi_dev_parent(ancestor)) {
                result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS,
                                             vmbus_walk_resources, NULL);
 
index d2545a1..44e04c7 100644 (file)
@@ -598,7 +598,7 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource)
                        continue;
 
                /* Create a symlink to domain objects */
-               obj = acpi_bus_get_acpi_device(element->reference.handle);
+               obj = acpi_get_acpi_dev(element->reference.handle);
                resource->domain_devices[i] = obj;
                if (!obj)
                        continue;
index 61a4684..81e6889 100644 (file)
@@ -266,9 +266,7 @@ static const struct ec_sensor_info sensors_family_intel_600[] = {
 #define SENSOR_SET_WATER_BLOCK                                                 \
        (SENSOR_TEMP_WATER_BLOCK_IN | SENSOR_TEMP_WATER_BLOCK_OUT)
 
-
 struct ec_board_info {
-       const char *board_names[MAX_IDENTICAL_BOARD_VARIATIONS];
        unsigned long sensors;
        /*
         * Defines which mutex to use for guarding access to the state and the
@@ -281,152 +279,194 @@ struct ec_board_info {
        enum board_family family;
 };
 
-static const struct ec_board_info board_info[] = {
-       {
-               .board_names = {"PRIME X470-PRO"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
-                       SENSOR_FAN_CPU_OPT |
-                       SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
-               .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
-               .family = family_amd_400_series,
-       },
-       {
-               .board_names = {"PRIME X570-PRO"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ProArt X570-CREATOR WIFI"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT |
-                       SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
-       },
-       {
-               .board_names = {"Pro WS X570-ACE"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET |
-                       SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG CROSSHAIR VIII DARK HERO"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR |
-                       SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
-                       SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW |
-                       SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {
-                       "ROG CROSSHAIR VIII FORMULA",
-                       "ROG CROSSHAIR VIII HERO",
-                       "ROG CROSSHAIR VIII HERO (WI-FI)",
-               },
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR |
-                       SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
-                       SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET |
-                       SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU |
-                       SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {
-                       "ROG MAXIMUS XI HERO",
-                       "ROG MAXIMUS XI HERO (WI-FI)",
-               },
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR |
-                       SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
-                       SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_intel_300_series,
-       },
-       {
-               .board_names = {"ROG CROSSHAIR VIII IMPACT"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
-                       SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
-                       SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX B550-E GAMING"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
-                       SENSOR_FAN_CPU_OPT,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX B550-I GAMING"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
-                       SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU |
-                       SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX X570-E GAMING"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
-                       SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
-                       SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX X570-E GAMING WIFI II"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU |
-                       SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX X570-F GAMING"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
-                       SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX X570-I GAMING"},
-               .sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM |
-                       SENSOR_TEMP_T_SENSOR |
-                       SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET |
-                       SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
-               .family = family_amd_500_series,
-       },
-       {
-               .board_names = {"ROG STRIX Z690-A GAMING WIFI D4"},
-               .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
-               .family = family_intel_600_series,
-       },
-       {
-               .board_names = {"ROG ZENITH II EXTREME"},
-               .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR |
-                       SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
-                       SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS |
-                       SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE |
-                       SENSOR_SET_WATER_BLOCK |
-                       SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 |
-                       SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3,
-               .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0,
-               .family = family_amd_500_series,
-       },
-       {}
+static const struct ec_board_info board_info_prime_x470_pro = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
+               SENSOR_FAN_CPU_OPT |
+               SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
+       .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
+       .family = family_amd_400_series,
+};
+
+static const struct ec_board_info board_info_prime_x570_pro = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
+               SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_pro_art_x570_creator_wifi = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
+               SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT |
+               SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_pro_ws_x570_ace = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
+               SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET |
+               SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_crosshair_viii_dark_hero = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR |
+               SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
+               SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW |
+               SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_crosshair_viii_hero = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR |
+               SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
+               SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET |
+               SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU |
+               SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_maximus_xi_hero = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR |
+               SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
+               SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_intel_300_series,
+};
+
+static const struct ec_board_info board_info_crosshair_viii_impact = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
+               SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
+               SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_b550_e_gaming = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
+               SENSOR_FAN_CPU_OPT,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_b550_i_gaming = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
+               SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU |
+               SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_x570_e_gaming = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
+               SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
+               SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_x570_e_gaming_wifi_ii = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU |
+               SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_x570_f_gaming = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
+               SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_x570_i_gaming = {
+       .sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM |
+               SENSOR_TEMP_T_SENSOR |
+               SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET |
+               SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+       .family = family_amd_500_series,
+};
+
+static const struct ec_board_info board_info_strix_z690_a_gaming_wifi_d4 = {
+       .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
+       .family = family_intel_600_series,
+};
+
+static const struct ec_board_info board_info_zenith_ii_extreme = {
+       .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR |
+               SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
+               SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS |
+               SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE |
+               SENSOR_SET_WATER_BLOCK |
+               SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 |
+               SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3,
+       .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0,
+       .family = family_amd_500_series,
+};
+
+#define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name, board_info)                      \
+       {                                                                      \
+               .matches = {                                                   \
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR,                      \
+                                       "ASUSTeK COMPUTER INC."),              \
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, name),                 \
+               },                                                             \
+               .driver_data = (void *)board_info,                              \
+       }
+
+static const struct dmi_system_id dmi_table[] = {
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO",
+                                       &board_info_prime_x470_pro),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X570-PRO",
+                                       &board_info_prime_x570_pro),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X570-CREATOR WIFI",
+                                       &board_info_pro_art_x570_creator_wifi),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE",
+                                       &board_info_pro_ws_x570_ace),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII DARK HERO",
+                                       &board_info_crosshair_viii_dark_hero),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII FORMULA",
+                                       &board_info_crosshair_viii_hero),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO",
+                                       &board_info_crosshair_viii_hero),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO (WI-FI)",
+                                       &board_info_crosshair_viii_hero),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO",
+                                       &board_info_maximus_xi_hero),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO (WI-FI)",
+                                       &board_info_maximus_xi_hero),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII IMPACT",
+                                       &board_info_crosshair_viii_impact),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-E GAMING",
+                                       &board_info_strix_b550_e_gaming),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-I GAMING",
+                                       &board_info_strix_b550_i_gaming),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING",
+                                       &board_info_strix_x570_e_gaming),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING WIFI II",
+                                       &board_info_strix_x570_e_gaming_wifi_ii),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-F GAMING",
+                                       &board_info_strix_x570_f_gaming),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-I GAMING",
+                                       &board_info_strix_x570_i_gaming),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z690-A GAMING WIFI D4",
+                                       &board_info_strix_z690_a_gaming_wifi_d4),
+       DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME",
+                                       &board_info_zenith_ii_extreme),
+       {},
 };
 
 struct ec_sensor {
@@ -537,12 +577,12 @@ static int find_ec_sensor_index(const struct ec_sensors_data *ec,
        return -ENOENT;
 }
 
-static int __init bank_compare(const void *a, const void *b)
+static int bank_compare(const void *a, const void *b)
 {
        return *((const s8 *)a) - *((const s8 *)b);
 }
 
-static void __init setup_sensor_data(struct ec_sensors_data *ec)
+static void setup_sensor_data(struct ec_sensors_data *ec)
 {
        struct ec_sensor *s = ec->sensors;
        bool bank_found;
@@ -574,7 +614,7 @@ static void __init setup_sensor_data(struct ec_sensors_data *ec)
        sort(ec->banks, ec->nr_banks, 1, bank_compare, NULL);
 }
 
-static void __init fill_ec_registers(struct ec_sensors_data *ec)
+static void fill_ec_registers(struct ec_sensors_data *ec)
 {
        const struct ec_sensor_info *si;
        unsigned int i, j, register_idx = 0;
@@ -589,7 +629,7 @@ static void __init fill_ec_registers(struct ec_sensors_data *ec)
        }
 }
 
-static int __init setup_lock_data(struct device *dev)
+static int setup_lock_data(struct device *dev)
 {
        const char *mutex_path;
        int status;
@@ -812,7 +852,7 @@ static umode_t asus_ec_hwmon_is_visible(const void *drvdata,
        return find_ec_sensor_index(state, type, channel) >= 0 ? S_IRUGO : 0;
 }
 
-static int __init
+static int
 asus_ec_hwmon_add_chan_info(struct hwmon_channel_info *asus_ec_hwmon_chan,
                             struct device *dev, int num,
                             enum hwmon_sensor_types type, u32 config)
@@ -841,27 +881,15 @@ static struct hwmon_chip_info asus_ec_chip_info = {
        .ops = &asus_ec_hwmon_ops,
 };
 
-static const struct ec_board_info * __init get_board_info(void)
+static const struct ec_board_info *get_board_info(void)
 {
-       const char *dmi_board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
-       const char *dmi_board_name = dmi_get_system_info(DMI_BOARD_NAME);
-       const struct ec_board_info *board;
-
-       if (!dmi_board_vendor || !dmi_board_name ||
-           strcasecmp(dmi_board_vendor, "ASUSTeK COMPUTER INC."))
-               return NULL;
-
-       for (board = board_info; board->sensors; board++) {
-               if (match_string(board->board_names,
-                                MAX_IDENTICAL_BOARD_VARIATIONS,
-                                dmi_board_name) >= 0)
-                       return board;
-       }
+       const struct dmi_system_id *dmi_entry;
 
-       return NULL;
+       dmi_entry = dmi_first_match(dmi_table);
+       return dmi_entry ? dmi_entry->driver_data : NULL;
 }
 
-static int __init asus_ec_probe(struct platform_device *pdev)
+static int asus_ec_probe(struct platform_device *pdev)
 {
        const struct hwmon_channel_info **ptr_asus_ec_ci;
        int nr_count[hwmon_max] = { 0 }, nr_types = 0;
@@ -970,29 +998,37 @@ static int __init asus_ec_probe(struct platform_device *pdev)
        return PTR_ERR_OR_ZERO(hwdev);
 }
 
-
-static const struct acpi_device_id acpi_ec_ids[] = {
-       /* Embedded Controller Device */
-       { "PNP0C09", 0 },
-       {}
-};
+MODULE_DEVICE_TABLE(dmi, dmi_table);
 
 static struct platform_driver asus_ec_sensors_platform_driver = {
        .driver = {
                .name   = "asus-ec-sensors",
-               .acpi_match_table = acpi_ec_ids,
        },
+       .probe = asus_ec_probe,
 };
 
-MODULE_DEVICE_TABLE(acpi, acpi_ec_ids);
-/*
- * we use module_platform_driver_probe() rather than module_platform_driver()
- * because the probe function (and its dependants) are marked with __init, which
- * means we can't put it into the .probe member of the platform_driver struct
- * above, and we can't mark the asus_ec_sensors_platform_driver object as __init
- * because the object is referenced from the module exit code.
- */
-module_platform_driver_probe(asus_ec_sensors_platform_driver, asus_ec_probe);
+static struct platform_device *asus_ec_sensors_platform_device;
+
+static int __init asus_ec_init(void)
+{
+       asus_ec_sensors_platform_device =
+               platform_create_bundle(&asus_ec_sensors_platform_driver,
+                                      asus_ec_probe, NULL, 0, NULL, 0);
+
+       if (IS_ERR(asus_ec_sensors_platform_device))
+               return PTR_ERR(asus_ec_sensors_platform_device);
+
+       return 0;
+}
+
+static void __exit asus_ec_exit(void)
+{
+       platform_device_unregister(asus_ec_sensors_platform_device);
+       platform_driver_unregister(&asus_ec_sensors_platform_driver);
+}
+
+module_init(asus_ec_init);
+module_exit(asus_ec_exit);
 
 module_param_named(mutex_path, mutex_path_override, charp, 0);
 MODULE_PARM_DESC(mutex_path,
index befe989..fbf3f5a 100644 (file)
@@ -391,6 +391,9 @@ static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,
        if (!fan_data)
                return -EINVAL;
 
+       if (state >= fan_data->num_speed)
+               return -EINVAL;
+
        set_fan_speed(fan_data, state);
        return 0;
 }
index 26278b0..9259779 100644 (file)
@@ -68,8 +68,9 @@
 
 /* VM Individual Macro Register */
 #define VM_COM_REG_SIZE        0x200
-#define VM_SDIF_DONE(n)        (VM_COM_REG_SIZE + 0x34 + 0x200 * (n))
-#define VM_SDIF_DATA(n)        (VM_COM_REG_SIZE + 0x40 + 0x200 * (n))
+#define VM_SDIF_DONE(vm)       (VM_COM_REG_SIZE + 0x34 + 0x200 * (vm))
+#define VM_SDIF_DATA(vm, ch)   \
+       (VM_COM_REG_SIZE + 0x40 + 0x200 * (vm) + 0x4 * (ch))
 
 /* SDA Slave Register */
 #define IP_CTRL                        0x00
@@ -115,6 +116,7 @@ struct pvt_device {
        u32                     t_num;
        u32                     p_num;
        u32                     v_num;
+       u32                     c_num;
        u32                     ip_freq;
        u8                      *vm_idx;
 };
@@ -178,14 +180,15 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
 {
        struct pvt_device *pvt = dev_get_drvdata(dev);
        struct regmap *v_map = pvt->v_map;
+       u8 vm_idx, ch_idx;
        u32 n, stat;
-       u8 vm_idx;
        int ret;
 
-       if (channel >= pvt->v_num)
+       if (channel >= pvt->v_num * pvt->c_num)
                return -EINVAL;
 
-       vm_idx = pvt->vm_idx[channel];
+       vm_idx = pvt->vm_idx[channel / pvt->c_num];
+       ch_idx = channel % pvt->c_num;
 
        switch (attr) {
        case hwmon_in_input:
@@ -196,13 +199,23 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
                if (ret)
                        return ret;
 
-               ret = regmap_read(v_map, VM_SDIF_DATA(vm_idx), &n);
+               ret = regmap_read(v_map, VM_SDIF_DATA(vm_idx, ch_idx), &n);
                if(ret < 0)
                        return ret;
 
                n &= SAMPLE_DATA_MSK;
-               /* Convert the N bitstream count into voltage */
-               *val = (PVT_N_CONST * n - PVT_R_CONST) >> PVT_CONV_BITS;
+               /*
+                * Convert the N bitstream count into voltage.
+                * To support negative voltage calculation for 64bit machines
+                * n must be cast to long, since n and *val differ both in
+                * signedness and in size.
+                * Division is used instead of right shift, because for signed
+                * numbers, the sign bit is used to fill the vacated bit
+                * positions, and if the number is negative, 1 is used.
+                * BIT(x) may not be used instead of (1 << x) because it's
+                * unsigned.
+                */
+               *val = (PVT_N_CONST * (long)n - PVT_R_CONST) / (1 << PVT_CONV_BITS);
 
                return 0;
        default:
@@ -375,6 +388,19 @@ static int pvt_init(struct pvt_device *pvt)
                if (ret)
                        return ret;
 
+               val = (BIT(pvt->c_num) - 1) | VM_CH_INIT |
+                     IP_POLL << SDIF_ADDR_SFT | SDIF_WRN_W | SDIF_PROG;
+               ret = regmap_write(v_map, SDIF_W, val);
+               if (ret < 0)
+                       return ret;
+
+               ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
+                                              val, !(val & SDIF_BUSY),
+                                              PVT_POLL_DELAY_US,
+                                              PVT_POLL_TIMEOUT_US);
+               if (ret)
+                       return ret;
+
                val = CFG1_VOL_MEAS_MODE | CFG1_PARALLEL_OUT |
                      CFG1_14_BIT | IP_CFG << SDIF_ADDR_SFT |
                      SDIF_WRN_W | SDIF_PROG;
@@ -489,8 +515,8 @@ static int pvt_reset_control_deassert(struct device *dev, struct pvt_device *pvt
 
 static int mr75203_probe(struct platform_device *pdev)
 {
+       u32 ts_num, vm_num, pd_num, ch_num, val, index, i;
        const struct hwmon_channel_info **pvt_info;
-       u32 ts_num, vm_num, pd_num, val, index, i;
        struct device *dev = &pdev->dev;
        u32 *temp_config, *in_config;
        struct device *hwmon_dev;
@@ -531,9 +557,11 @@ static int mr75203_probe(struct platform_device *pdev)
        ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
        pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
        vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
+       ch_num = (val & CH_NUM_MSK) >> CH_NUM_SFT;
        pvt->t_num = ts_num;
        pvt->p_num = pd_num;
        pvt->v_num = vm_num;
+       pvt->c_num = ch_num;
        val = 0;
        if (ts_num)
                val++;
@@ -570,7 +598,7 @@ static int mr75203_probe(struct platform_device *pdev)
        }
 
        if (vm_num) {
-               u32 num = vm_num;
+               u32 total_ch;
 
                ret = pvt_get_regmap(pdev, "vm", pvt);
                if (ret)
@@ -584,30 +612,30 @@ static int mr75203_probe(struct platform_device *pdev)
                ret = device_property_read_u8_array(dev, "intel,vm-map",
                                                    pvt->vm_idx, vm_num);
                if (ret) {
-                       num = 0;
+                       /*
+                        * Incase intel,vm-map property is not defined, we
+                        * assume incremental channel numbers.
+                        */
+                       for (i = 0; i < vm_num; i++)
+                               pvt->vm_idx[i] = i;
                } else {
                        for (i = 0; i < vm_num; i++)
                                if (pvt->vm_idx[i] >= vm_num ||
                                    pvt->vm_idx[i] == 0xff) {
-                                       num = i;
+                                       pvt->v_num = i;
+                                       vm_num = i;
                                        break;
                                }
                }
 
-               /*
-                * Incase intel,vm-map property is not defined, we assume
-                * incremental channel numbers.
-                */
-               for (i = num; i < vm_num; i++)
-                       pvt->vm_idx[i] = i;
-
-               in_config = devm_kcalloc(dev, num + 1,
+               total_ch = ch_num * vm_num;
+               in_config = devm_kcalloc(dev, total_ch + 1,
                                         sizeof(*in_config), GFP_KERNEL);
                if (!in_config)
                        return -ENOMEM;
 
-               memset32(in_config, HWMON_I_INPUT, num);
-               in_config[num] = 0;
+               memset32(in_config, HWMON_I_INPUT, total_ch);
+               in_config[total_ch] = 0;
                pvt_in.config = in_config;
 
                pvt_info[index++] = &pvt_in;
index 5541d26..7ec0493 100644 (file)
@@ -2861,7 +2861,7 @@ static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
                .data = -1,
        };
 
-       if (!data->vout_low[page]) {
+       if (data->vout_low[page] < 0) {
                if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MIN))
                        s.data = _pmbus_read_word_data(client, page, 0xff,
                                                       PMBUS_MFR_VOUT_MIN);
@@ -2887,7 +2887,7 @@ static int pmbus_regulator_get_high_margin(struct i2c_client *client, int page)
                .data = -1,
        };
 
-       if (!data->vout_high[page]) {
+       if (data->vout_high[page] < 0) {
                if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MAX))
                        s.data = _pmbus_read_word_data(client, page, 0xff,
                                                       PMBUS_MFR_VOUT_MAX);
@@ -3016,11 +3016,10 @@ static int pmbus_regulator_register(struct pmbus_data *data)
 
                rdev = devm_regulator_register(dev, &info->reg_desc[i],
                                               &config);
-               if (IS_ERR(rdev)) {
-                       dev_err(dev, "Failed to register %s regulator\n",
-                               info->reg_desc[i].name);
-                       return PTR_ERR(rdev);
-               }
+               if (IS_ERR(rdev))
+                       return dev_err_probe(dev, PTR_ERR(rdev),
+                                            "Failed to register %s regulator\n",
+                                            info->reg_desc[i].name);
        }
 
        return 0;
@@ -3320,6 +3319,7 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
        struct pmbus_data *data;
        size_t groups_num = 0;
        int ret;
+       int i;
        char *name;
 
        if (!info)
@@ -3353,6 +3353,11 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
        data->currpage = -1;
        data->currphase = -1;
 
+       for (i = 0; i < ARRAY_SIZE(data->vout_low); i++) {
+               data->vout_low[i] = -1;
+               data->vout_high[i] = -1;
+       }
+
        ret = pmbus_init_common(client, data, info);
        if (ret < 0)
                return ret;
index 42762e8..f7c59ff 100644 (file)
@@ -493,18 +493,20 @@ static char *tps23861_port_poe_plus_status(struct tps23861_data *data, int port)
 
 static int tps23861_port_resistance(struct tps23861_data *data, int port)
 {
-       u16 regval;
+       unsigned int raw_val;
+       __le16 regval;
 
        regmap_bulk_read(data->regmap,
                         PORT_1_RESISTANCE_LSB + PORT_N_RESISTANCE_LSB_OFFSET * (port - 1),
                         &regval,
                         2);
 
-       switch (FIELD_GET(PORT_RESISTANCE_RSN_MASK, regval)) {
+       raw_val = le16_to_cpu(regval);
+       switch (FIELD_GET(PORT_RESISTANCE_RSN_MASK, raw_val)) {
        case PORT_RESISTANCE_RSN_OTHER:
-               return (FIELD_GET(PORT_RESISTANCE_MASK, regval) * RESISTANCE_LSB) / 10000;
+               return (FIELD_GET(PORT_RESISTANCE_MASK, raw_val) * RESISTANCE_LSB) / 10000;
        case PORT_RESISTANCE_RSN_LOW:
-               return (FIELD_GET(PORT_RESISTANCE_MASK, regval) * RESISTANCE_LSB_LOW) / 10000;
+               return (FIELD_GET(PORT_RESISTANCE_MASK, raw_val) * RESISTANCE_LSB_LOW) / 10000;
        case PORT_RESISTANCE_RSN_SHORT:
        case PORT_RESISTANCE_RSN_OPEN:
        default:
index 84b7e6c..423fe0c 100644 (file)
@@ -244,14 +244,18 @@ static const struct i2c_adapter_quirks amd_i2c_dev_quirks = {
 
 static int i2c_amd_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        int ret;
        struct amd_i2c_dev *i2c_dev;
-       struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
        struct amd_mp2_dev *mp2_dev;
-       const char *uid;
+       u64 uid;
 
-       if (!adev)
-               return -ENODEV;
+       ret = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
+       if (ret)
+               return dev_err_probe(dev, ret, "missing UID/bus id!\n");
+       if (uid >= 2)
+               return dev_err_probe(dev, -EINVAL, "incorrect UID/bus id \"%llu\"!\n", uid);
+       dev_dbg(dev, "bus id is %llu\n", uid);
 
        /* The ACPI namespace doesn't contain information about which MP2 PCI
         * device an AMDI0011 ACPI device is related to, so assume that there's
@@ -266,6 +270,7 @@ static int i2c_amd_probe(struct platform_device *pdev)
        if (!i2c_dev)
                return -ENOMEM;
 
+       i2c_dev->common.bus_id = uid;
        i2c_dev->common.mp2_dev = mp2_dev;
        i2c_dev->pdev = pdev;
        platform_set_drvdata(pdev, i2c_dev);
@@ -276,20 +281,6 @@ static int i2c_amd_probe(struct platform_device *pdev)
        i2c_dev->common.resume = &i2c_amd_resume;
 #endif
 
-       uid = adev->pnp.unique_id;
-       if (!uid) {
-               dev_err(&pdev->dev, "missing UID/bus id!\n");
-               return -EINVAL;
-       } else if (strcmp(uid, "0") == 0) {
-               i2c_dev->common.bus_id = 0;
-       } else if (strcmp(uid, "1") == 0) {
-               i2c_dev->common.bus_id = 1;
-       } else {
-               dev_err(&pdev->dev, "incorrect UID/bus id \"%s\"!\n", uid);
-               return -EINVAL;
-       }
-       dev_dbg(&pdev->dev, "bus id is %u\n", i2c_dev->common.bus_id);
-
        /* Register the adapter */
        amd_mp2_pm_runtime_get(mp2_dev);
 
index 471c47d..c836cf8 100644 (file)
@@ -823,7 +823,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        r = pm_runtime_resume_and_get(dev->dev);
        if (r < 0) {
                dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
-               return r;
+               goto err_pm;
        }
 
        i2c_davinci_init(dev);
@@ -882,6 +882,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 err_unuse_clocks:
        pm_runtime_dont_use_autosuspend(dev->dev);
        pm_runtime_put_sync(dev->dev);
+err_pm:
        pm_runtime_disable(dev->dev);
 
        return r;
index e47fa34..3082183 100644 (file)
@@ -1583,7 +1583,7 @@ static int i2c_imx_remove(struct platform_device *pdev)
        if (i2c_imx->dma)
                i2c_imx_dma_free(i2c_imx);
 
-       if (ret == 0) {
+       if (ret >= 0) {
                /* setup chip registers to defaults */
                imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR);
                imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IFDR);
index 8716032..60908c5 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
  */
 #define MLXBF_I2C_TYU_PLL_OUT_FREQ  (400 * 1000 * 1000)
 /* Reference clock for Bluefield - 156 MHz. */
-#define MLXBF_I2C_PLL_IN_FREQ       (156 * 1000 * 1000)
+#define MLXBF_I2C_PLL_IN_FREQ       156250000ULL
 
 /* Constant used to determine the PLL frequency. */
-#define MLNXBF_I2C_COREPLL_CONST    16384
+#define MLNXBF_I2C_COREPLL_CONST    16384ULL
+
+#define MLXBF_I2C_FREQUENCY_1GHZ  1000000000ULL
 
 /* PLL registers. */
-#define MLXBF_I2C_CORE_PLL_REG0         0x0
 #define MLXBF_I2C_CORE_PLL_REG1         0x4
 #define MLXBF_I2C_CORE_PLL_REG2         0x8
 
 #define MLXBF_I2C_COREPLL_FREQ          MLXBF_I2C_TYU_PLL_OUT_FREQ
 
 /* Core PLL TYU configuration. */
-#define MLXBF_I2C_COREPLL_CORE_F_TYU_MASK   GENMASK(12, 0)
-#define MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK  GENMASK(3, 0)
-#define MLXBF_I2C_COREPLL_CORE_R_TYU_MASK   GENMASK(5, 0)
-
-#define MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT  3
-#define MLXBF_I2C_COREPLL_CORE_OD_TYU_SHIFT 16
-#define MLXBF_I2C_COREPLL_CORE_R_TYU_SHIFT  20
+#define MLXBF_I2C_COREPLL_CORE_F_TYU_MASK   GENMASK(15, 3)
+#define MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK  GENMASK(19, 16)
+#define MLXBF_I2C_COREPLL_CORE_R_TYU_MASK   GENMASK(25, 20)
 
 /* Core PLL YU configuration. */
 #define MLXBF_I2C_COREPLL_CORE_F_YU_MASK    GENMASK(25, 0)
 #define MLXBF_I2C_COREPLL_CORE_OD_YU_MASK   GENMASK(3, 0)
-#define MLXBF_I2C_COREPLL_CORE_R_YU_MASK    GENMASK(5, 0)
+#define MLXBF_I2C_COREPLL_CORE_R_YU_MASK    GENMASK(31, 26)
 
-#define MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT   0
-#define MLXBF_I2C_COREPLL_CORE_OD_YU_SHIFT  1
-#define MLXBF_I2C_COREPLL_CORE_R_YU_SHIFT   26
 
 /* Core PLL frequency. */
 static u64 mlxbf_i2c_corepll_frequency;
@@ -479,8 +474,6 @@ static struct mutex mlxbf_i2c_bus_lock;
 #define MLXBF_I2C_MASK_8    GENMASK(7, 0)
 #define MLXBF_I2C_MASK_16   GENMASK(15, 0)
 
-#define MLXBF_I2C_FREQUENCY_1GHZ  1000000000
-
 /*
  * Function to poll a set of bits at a specific address; it checks whether
  * the bits are equal to zero when eq_zero is set to 'true', and not equal
@@ -669,7 +662,7 @@ static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave,
        /* Clear status bits. */
        writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_STATUS);
        /* Set the cause data. */
-       writel(~0x0, priv->smbus->io + MLXBF_I2C_CAUSE_OR_CLEAR);
+       writel(~0x0, priv->mst_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR);
        /* Zero PEC byte. */
        writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_PEC);
        /* Zero byte count. */
@@ -738,6 +731,9 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
                if (flags & MLXBF_I2C_F_WRITE) {
                        write_en = 1;
                        write_len += operation->length;
+                       if (data_idx + operation->length >
+                                       MLXBF_I2C_MASTER_DATA_DESC_SIZE)
+                               return -ENOBUFS;
                        memcpy(data_desc + data_idx,
                               operation->buffer, operation->length);
                        data_idx += operation->length;
@@ -1407,24 +1403,19 @@ static int mlxbf_i2c_init_master(struct platform_device *pdev,
        return 0;
 }
 
-static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
+static u64 mlxbf_i2c_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
 {
-       u64 core_frequency, pad_frequency;
+       u64 core_frequency;
        u8 core_od, core_r;
        u32 corepll_val;
        u16 core_f;
 
-       pad_frequency = MLXBF_I2C_PLL_IN_FREQ;
-
        corepll_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);
 
        /* Get Core PLL configuration bits. */
-       core_f = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT) &
-                       MLXBF_I2C_COREPLL_CORE_F_TYU_MASK;
-       core_od = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_OD_TYU_SHIFT) &
-                       MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK;
-       core_r = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_R_TYU_SHIFT) &
-                       MLXBF_I2C_COREPLL_CORE_R_TYU_MASK;
+       core_f = FIELD_GET(MLXBF_I2C_COREPLL_CORE_F_TYU_MASK, corepll_val);
+       core_od = FIELD_GET(MLXBF_I2C_COREPLL_CORE_OD_TYU_MASK, corepll_val);
+       core_r = FIELD_GET(MLXBF_I2C_COREPLL_CORE_R_TYU_MASK, corepll_val);
 
        /*
         * Compute PLL output frequency as follow:
@@ -1436,31 +1427,26 @@ static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)
         * Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency
         * and PadFrequency, respectively.
         */
-       core_frequency = pad_frequency * (++core_f);
+       core_frequency = MLXBF_I2C_PLL_IN_FREQ * (++core_f);
        core_frequency /= (++core_r) * (++core_od);
 
        return core_frequency;
 }
 
-static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
+static u64 mlxbf_i2c_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
 {
        u32 corepll_reg1_val, corepll_reg2_val;
-       u64 corepll_frequency, pad_frequency;
+       u64 corepll_frequency;
        u8 core_od, core_r;
        u32 core_f;
 
-       pad_frequency = MLXBF_I2C_PLL_IN_FREQ;
-
        corepll_reg1_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);
        corepll_reg2_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG2);
 
        /* Get Core PLL configuration bits */
-       core_f = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT) &
-                       MLXBF_I2C_COREPLL_CORE_F_YU_MASK;
-       core_r = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_R_YU_SHIFT) &
-                       MLXBF_I2C_COREPLL_CORE_R_YU_MASK;
-       core_od = rol32(corepll_reg2_val,  MLXBF_I2C_COREPLL_CORE_OD_YU_SHIFT) &
-                       MLXBF_I2C_COREPLL_CORE_OD_YU_MASK;
+       core_f = FIELD_GET(MLXBF_I2C_COREPLL_CORE_F_YU_MASK, corepll_reg1_val);
+       core_r = FIELD_GET(MLXBF_I2C_COREPLL_CORE_R_YU_MASK, corepll_reg1_val);
+       core_od = FIELD_GET(MLXBF_I2C_COREPLL_CORE_OD_YU_MASK, corepll_reg2_val);
 
        /*
         * Compute PLL output frequency as follow:
@@ -1472,7 +1458,7 @@ static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)
         * Where PLL_OUT_FREQ and PLL_IN_FREQ refer to CoreFrequency
         * and PadFrequency, respectively.
         */
-       corepll_frequency = (pad_frequency * core_f) / MLNXBF_I2C_COREPLL_CONST;
+       corepll_frequency = (MLXBF_I2C_PLL_IN_FREQ * core_f) / MLNXBF_I2C_COREPLL_CONST;
        corepll_frequency /= (++core_r) * (++core_od);
 
        return corepll_frequency;
@@ -2180,14 +2166,14 @@ static struct mlxbf_i2c_chip_info mlxbf_i2c_chip[] = {
                        [1] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_1],
                        [2] = &mlxbf_i2c_gpio_res[MLXBF_I2C_CHIP_TYPE_1]
                },
-               .calculate_freq = mlxbf_calculate_freq_from_tyu
+               .calculate_freq = mlxbf_i2c_calculate_freq_from_tyu
        },
        [MLXBF_I2C_CHIP_TYPE_2] = {
                .type = MLXBF_I2C_CHIP_TYPE_2,
                .shared_res = {
                        [0] = &mlxbf_i2c_corepll_res[MLXBF_I2C_CHIP_TYPE_2]
                },
-               .calculate_freq = mlxbf_calculate_freq_from_yu
+               .calculate_freq = mlxbf_i2c_calculate_freq_from_yu
        }
 };
 
@@ -2229,35 +2215,27 @@ MODULE_DEVICE_TABLE(acpi, mlxbf_i2c_acpi_ids);
 static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
 {
        const struct acpi_device_id *aid;
-       struct acpi_device *adev;
-       unsigned long bus_id = 0;
-       const char *uid;
+       u64 bus_id;
        int ret;
 
        if (acpi_disabled)
                return -ENOENT;
 
-       adev = ACPI_COMPANION(dev);
-       if (!adev)
-               return -ENXIO;
-
        aid = acpi_match_device(mlxbf_i2c_acpi_ids, dev);
        if (!aid)
                return -ENODEV;
 
        priv->chip = (struct mlxbf_i2c_chip_info *)aid->driver_data;
 
-       uid = acpi_device_uid(adev);
-       if (!uid || !(*uid)) {
+       ret = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &bus_id);
+       if (ret) {
                dev_err(dev, "Cannot retrieve UID\n");
-               return -ENODEV;
+               return ret;
        }
 
-       ret = kstrtoul(uid, 0, &bus_id);
-       if (!ret)
-               priv->bus = bus_id;
+       priv->bus = bus_id;
 
-       return ret;
+       return 0;
 }
 #else
 static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)
index 774507b..313904b 100644 (file)
@@ -243,9 +243,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
                                   int (*deselect)(struct i2c_mux_core *, u32))
 {
        struct i2c_mux_core *muxc;
+       size_t mux_size;
 
-       muxc = devm_kzalloc(dev, struct_size(muxc, adapter, max_adapters)
-                           + sizeof_priv, GFP_KERNEL);
+       mux_size = struct_size(muxc, adapter, max_adapters);
+       muxc = devm_kzalloc(dev, size_add(mux_size, sizeof_priv), GFP_KERNEL);
        if (!muxc)
                return NULL;
        if (sizeof_priv)
index 3e10171..cfeb24d 100644 (file)
@@ -928,6 +928,51 @@ static struct cpuidle_state adl_l_cstates[] __initdata = {
                .enter = NULL }
 };
 
+static struct cpuidle_state adl_n_cstates[] __initdata = {
+       {
+               .name = "C1",
+               .desc = "MWAIT 0x00",
+               .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_UNUSABLE,
+               .exit_latency = 1,
+               .target_residency = 1,
+               .enter = &intel_idle,
+               .enter_s2idle = intel_idle_s2idle, },
+       {
+               .name = "C1E",
+               .desc = "MWAIT 0x01",
+               .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
+               .exit_latency = 2,
+               .target_residency = 4,
+               .enter = &intel_idle,
+               .enter_s2idle = intel_idle_s2idle, },
+       {
+               .name = "C6",
+               .desc = "MWAIT 0x20",
+               .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 195,
+               .target_residency = 585,
+               .enter = &intel_idle,
+               .enter_s2idle = intel_idle_s2idle, },
+       {
+               .name = "C8",
+               .desc = "MWAIT 0x40",
+               .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 260,
+               .target_residency = 1040,
+               .enter = &intel_idle,
+               .enter_s2idle = intel_idle_s2idle, },
+       {
+               .name = "C10",
+               .desc = "MWAIT 0x60",
+               .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 660,
+               .target_residency = 1980,
+               .enter = &intel_idle,
+               .enter_s2idle = intel_idle_s2idle, },
+       {
+               .enter = NULL }
+};
+
 static struct cpuidle_state spr_cstates[] __initdata = {
        {
                .name = "C1",
@@ -1309,6 +1354,10 @@ static const struct idle_cpu idle_cpu_adl_l __initconst = {
        .state_table = adl_l_cstates,
 };
 
+static const struct idle_cpu idle_cpu_adl_n __initconst = {
+       .state_table = adl_n_cstates,
+};
+
 static const struct idle_cpu idle_cpu_spr __initconst = {
        .state_table = spr_cstates,
        .disable_promotion_to_c1e = true,
@@ -1379,6 +1428,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,           &idle_cpu_icx),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,           &idle_cpu_adl),
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,         &idle_cpu_adl_l),
+       X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N,         &idle_cpu_adl_n),
        X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,    &idle_cpu_spr),
        X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,        &idle_cpu_knl),
        X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,        &idle_cpu_knl),
@@ -1507,7 +1557,7 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
                state = &drv->states[drv->state_count++];
 
                snprintf(state->name, CPUIDLE_NAME_LEN, "C%d_ACPI", cstate);
-               strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
+               strscpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
                state->exit_latency = cx->latency;
                /*
                 * For C1-type C-states use the same number for both the exit
@@ -1816,6 +1866,7 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
                break;
        case INTEL_FAM6_ALDERLAKE:
        case INTEL_FAM6_ALDERLAKE_L:
+       case INTEL_FAM6_ALDERLAKE_N:
                adl_idle_state_table_update();
                break;
        }
index 92c68d4..a2f9fda 100644 (file)
@@ -287,10 +287,8 @@ static int ad7292_probe(struct spi_device *spi)
 
                ret = devm_add_action_or_reset(&spi->dev,
                                               ad7292_regulator_disable, st);
-               if (ret) {
-                       regulator_disable(st->reg);
+               if (ret)
                        return ret;
-               }
 
                ret = regulator_get_voltage(st->reg);
                if (ret < 0)
index 1cb4590..890af7d 100644 (file)
@@ -40,8 +40,8 @@
 #define MCP3911_CHANNEL(x)             (MCP3911_REG_CHANNEL0 + x * 3)
 #define MCP3911_OFFCAL(x)              (MCP3911_REG_OFFCAL_CH0 + x * 6)
 
-/* Internal voltage reference in uV */
-#define MCP3911_INT_VREF_UV            1200000
+/* Internal voltage reference in mV */
+#define MCP3911_INT_VREF_MV            1200
 
 #define MCP3911_REG_READ(reg, id)      ((((reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff)
 #define MCP3911_REG_WRITE(reg, id)     ((((reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff)
@@ -113,6 +113,8 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev,
                if (ret)
                        goto out;
 
+               *val = sign_extend32(*val, 23);
+
                ret = IIO_VAL_INT;
                break;
 
@@ -137,11 +139,18 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev,
 
                        *val = ret / 1000;
                } else {
-                       *val = MCP3911_INT_VREF_UV;
+                       *val = MCP3911_INT_VREF_MV;
                }
 
-               *val2 = 24;
-               ret = IIO_VAL_FRACTIONAL_LOG2;
+               /*
+                * For 24bit Conversion
+                * Raw = ((Voltage)/(Vref) * 2^23 * Gain * 1.5
+                * Voltage = Raw * (Vref)/(2^23 * Gain * 1.5)
+                */
+
+               /* val2 = (2^23 * 1.5) */
+               *val2 = 12582912;
+               ret = IIO_VAL_FRACTIONAL;
                break;
        }
 
@@ -208,7 +217,14 @@ static int mcp3911_config(struct mcp3911 *adc)
        u32 configreg;
        int ret;
 
-       device_property_read_u32(dev, "device-addr", &adc->dev_addr);
+       ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr);
+
+       /*
+        * Fallback to "device-addr" due to historical mismatch between
+        * dt-bindings and implementation
+        */
+       if (ret)
+               device_property_read_u32(dev, "device-addr", &adc->dev_addr);
        if (adc->dev_addr > 3) {
                dev_err(&adc->spi->dev,
                        "invalid device address (%i). Must be in range 0-3.\n",
index edbe6a3..001055d 100644 (file)
@@ -505,7 +505,7 @@ static int cm32181_resume(struct device *dev)
                                         cm32181->conf_regs[CM32181_REG_ADDR_CMD]);
 }
 
-DEFINE_SIMPLE_DEV_PM_OPS(cm32181_pm_ops, cm32181_suspend, cm32181_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(cm32181_pm_ops, cm32181_suspend, cm32181_resume);
 
 static const struct of_device_id cm32181_of_match[] = {
        { .compatible = "capella,cm3218" },
index c721b69..0b30db7 100644 (file)
@@ -226,8 +226,10 @@ static int cm3605_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return dev_err_probe(dev, irq, "failed to get irq\n");
+       if (irq < 0) {
+               ret = dev_err_probe(dev, irq, "failed to get irq\n");
+               goto out_disable_aset;
+       }
 
        ret = devm_request_threaded_irq(dev, irq, cm3605_prox_irq,
                                        NULL, 0, "cm3605", indio_dev);
index 46d0667..be317f2 100644 (file)
@@ -1841,8 +1841,8 @@ cma_ib_id_from_event(struct ib_cm_id *cm_id,
                }
 
                if (!validate_net_dev(*net_dev,
-                                (struct sockaddr *)&req->listen_addr_storage,
-                                (struct sockaddr *)&req->src_addr_storage)) {
+                                (struct sockaddr *)&req->src_addr_storage,
+                                (struct sockaddr *)&req->listen_addr_storage)) {
                        id_priv = ERR_PTR(-EHOSTUNREACH);
                        goto err;
                }
index 186ed88..d39e16c 100644 (file)
@@ -462,7 +462,7 @@ retry:
                mutex_unlock(&umem_odp->umem_mutex);
 
 out_put_mm:
-       mmput(owning_mm);
+       mmput_async(owning_mm);
 out_put_task:
        if (owning_process)
                put_task_struct(owning_process);
index f848eed..d249965 100644 (file)
@@ -730,7 +730,6 @@ struct hns_roce_caps {
        u32             num_qps;
        u32             num_pi_qps;
        u32             reserved_qps;
-       int             num_qpc_timer;
        u32             num_srqs;
        u32             max_wqes;
        u32             max_srq_wrs;
index cbdafaa..c780646 100644 (file)
@@ -1977,7 +1977,7 @@ static void set_default_caps(struct hns_roce_dev *hr_dev)
 
        caps->num_mtpts         = HNS_ROCE_V2_MAX_MTPT_NUM;
        caps->num_pds           = HNS_ROCE_V2_MAX_PD_NUM;
-       caps->num_qpc_timer     = HNS_ROCE_V2_MAX_QPC_TIMER_NUM;
+       caps->qpc_timer_bt_num  = HNS_ROCE_V2_MAX_QPC_TIMER_BT_NUM;
        caps->cqc_timer_bt_num  = HNS_ROCE_V2_MAX_CQC_TIMER_BT_NUM;
 
        caps->max_qp_init_rdma  = HNS_ROCE_V2_MAX_QP_INIT_RDMA;
@@ -2273,7 +2273,6 @@ static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev)
        caps->max_rq_sg              = le16_to_cpu(resp_a->max_rq_sg);
        caps->max_rq_sg = roundup_pow_of_two(caps->max_rq_sg);
        caps->max_extend_sg          = le32_to_cpu(resp_a->max_extend_sg);
-       caps->num_qpc_timer          = le16_to_cpu(resp_a->num_qpc_timer);
        caps->max_srq_sges           = le16_to_cpu(resp_a->max_srq_sges);
        caps->max_srq_sges = roundup_pow_of_two(caps->max_srq_sges);
        caps->num_aeq_vectors        = resp_a->num_aeq_vectors;
index f96deba..6479710 100644 (file)
 #include <linux/bitops.h>
 
 #define HNS_ROCE_V2_MAX_QP_NUM                 0x1000
-#define HNS_ROCE_V2_MAX_QPC_TIMER_NUM          0x200
 #define HNS_ROCE_V2_MAX_WQE_NUM                        0x8000
 #define HNS_ROCE_V2_MAX_SRQ_WR                 0x8000
 #define HNS_ROCE_V2_MAX_SRQ_SGE                        64
 #define HNS_ROCE_V2_MAX_CQ_NUM                 0x100000
+#define HNS_ROCE_V2_MAX_QPC_TIMER_BT_NUM       0x100
 #define HNS_ROCE_V2_MAX_CQC_TIMER_BT_NUM       0x100
 #define HNS_ROCE_V2_MAX_SRQ_NUM                        0x100000
 #define HNS_ROCE_V2_MAX_CQE_NUM                        0x400000
@@ -83,7 +83,7 @@
 
 #define HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ         PAGE_SIZE
 #define HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ         PAGE_SIZE
-#define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED                0xFFFFF000
+#define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED                0xFFFF000
 #define HNS_ROCE_V2_MAX_INNER_MTPT_NUM         2
 #define HNS_ROCE_INVALID_LKEY                  0x0
 #define HNS_ROCE_INVALID_SGE_LENGTH            0x80000000
index c8af4eb..4ccb217 100644 (file)
@@ -725,7 +725,7 @@ static int hns_roce_init_hem(struct hns_roce_dev *hr_dev)
                ret = hns_roce_init_hem_table(hr_dev, &hr_dev->qpc_timer_table,
                                              HEM_TYPE_QPC_TIMER,
                                              hr_dev->caps.qpc_timer_entry_sz,
-                                             hr_dev->caps.num_qpc_timer, 1);
+                                             hr_dev->caps.qpc_timer_bt_num, 1);
                if (ret) {
                        dev_err(dev,
                                "Failed to init QPC timer memory, aborting.\n");
index 48d3616..7bee7f6 100644 (file)
@@ -462,11 +462,8 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap,
        hr_qp->rq.max_gs = roundup_pow_of_two(max(1U, cap->max_recv_sge) +
                                              hr_qp->rq.rsv_sge);
 
-       if (hr_dev->caps.max_rq_sg <= HNS_ROCE_SGE_IN_WQE)
-               hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz);
-       else
-               hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz *
-                                           hr_qp->rq.max_gs);
+       hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz *
+                                   hr_qp->rq.max_gs);
 
        hr_qp->rq.wqe_cnt = cnt;
        if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE &&
index daeab5d..a6e5d35 100644 (file)
@@ -497,7 +497,8 @@ int irdma_uk_send(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info,
                              FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data));
                i = 0;
        } else {
-               qp->wqe_ops.iw_set_fragment(wqe, 0, op_info->sg_list,
+               qp->wqe_ops.iw_set_fragment(wqe, 0,
+                                           frag_cnt ? op_info->sg_list : NULL,
                                            qp->swqe_polarity);
                i = 1;
        }
@@ -1005,6 +1006,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
        int ret_code;
        bool move_cq_head = true;
        u8 polarity;
+       u8 op_type;
        bool ext_valid;
        __le64 *ext_cqe;
 
@@ -1187,7 +1189,6 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
                        do {
                                __le64 *sw_wqe;
                                u64 wqe_qword;
-                               u8 op_type;
                                u32 tail;
 
                                tail = qp->sq_ring.tail;
@@ -1204,6 +1205,8 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
                                        break;
                                }
                        } while (1);
+                       if (op_type == IRDMA_OP_TYPE_BIND_MW && info->minor_err == FLUSH_PROT_ERR)
+                               info->minor_err = FLUSH_MW_BIND_ERR;
                        qp->sq_flush_seen = true;
                        if (!IRDMA_RING_MORE_WORK(qp->sq_ring))
                                qp->sq_flush_complete = true;
index fdf4cc8..075defa 100644 (file)
@@ -590,11 +590,14 @@ static int irdma_wait_event(struct irdma_pci_f *rf,
        cqp_error = cqp_request->compl_info.error;
        if (cqp_error) {
                err_code = -EIO;
-               if (cqp_request->compl_info.maj_err_code == 0xFFFF &&
-                   cqp_request->compl_info.min_err_code == 0x8029) {
-                       if (!rf->reset) {
-                               rf->reset = true;
-                               rf->gen_ops.request_reset(rf);
+               if (cqp_request->compl_info.maj_err_code == 0xFFFF) {
+                       if (cqp_request->compl_info.min_err_code == 0x8002)
+                               err_code = -EBUSY;
+                       else if (cqp_request->compl_info.min_err_code == 0x8029) {
+                               if (!rf->reset) {
+                                       rf->reset = true;
+                                       rf->gen_ops.request_reset(rf);
+                               }
                        }
                }
        }
@@ -2598,7 +2601,7 @@ void irdma_generate_flush_completions(struct irdma_qp *iwqp)
                spin_unlock_irqrestore(&iwqp->lock, flags2);
                spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1);
                if (compl_generated)
-                       irdma_comp_handler(iwqp->iwrcq);
+                       irdma_comp_handler(iwqp->iwscq);
        } else {
                spin_unlock_irqrestore(&iwqp->iwscq->lock, flags1);
                mod_delayed_work(iwqp->iwdev->cleanup_wq, &iwqp->dwork_flush,
index 9b07b8a..9b207f5 100644 (file)
@@ -39,15 +39,18 @@ static int irdma_query_device(struct ib_device *ibdev,
        props->max_send_sge = hw_attrs->uk_attrs.max_hw_wq_frags;
        props->max_recv_sge = hw_attrs->uk_attrs.max_hw_wq_frags;
        props->max_cq = rf->max_cq - rf->used_cqs;
-       props->max_cqe = rf->max_cqe;
+       props->max_cqe = rf->max_cqe - 1;
        props->max_mr = rf->max_mr - rf->used_mrs;
        props->max_mw = props->max_mr;
        props->max_pd = rf->max_pd - rf->used_pds;
        props->max_sge_rd = hw_attrs->uk_attrs.max_hw_read_sges;
        props->max_qp_rd_atom = hw_attrs->max_hw_ird;
        props->max_qp_init_rd_atom = hw_attrs->max_hw_ord;
-       if (rdma_protocol_roce(ibdev, 1))
+       if (rdma_protocol_roce(ibdev, 1)) {
+               props->device_cap_flags |= IB_DEVICE_RC_RNR_NAK_GEN;
                props->max_pkeys = IRDMA_PKEY_TBL_SZ;
+       }
+
        props->max_ah = rf->max_ah;
        props->max_mcast_grp = rf->max_mcg;
        props->max_mcast_qp_attach = IRDMA_MAX_MGS_PER_CTX;
@@ -3009,6 +3012,7 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
        struct irdma_pble_alloc *palloc = &iwpbl->pble_alloc;
        struct irdma_cqp_request *cqp_request;
        struct cqp_cmds_info *cqp_info;
+       int status;
 
        if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) {
                if (iwmr->region) {
@@ -3039,8 +3043,11 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
        cqp_info->post_sq = 1;
        cqp_info->in.u.dealloc_stag.dev = &iwdev->rf->sc_dev;
        cqp_info->in.u.dealloc_stag.scratch = (uintptr_t)cqp_request;
-       irdma_handle_cqp_op(iwdev->rf, cqp_request);
+       status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
        irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);
+       if (status)
+               return status;
+
        irdma_free_stag(iwdev, iwmr->stag);
 done:
        if (iwpbl->pbl_allocated)
index 293ed70..b4dc523 100644 (file)
@@ -166,6 +166,12 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
                mdev = dev->mdev;
                mdev_port_num = 1;
        }
+       if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
+               /* set local port to one for Function-Per-Port HCA. */
+               mdev = dev->mdev;
+               mdev_port_num = 1;
+       }
+
        /* Declaring support of extended counters */
        if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
                struct ib_class_port_info cpi = {};
index fc94a1b..883d7c6 100644 (file)
@@ -4336,7 +4336,7 @@ static int mlx5r_probe(struct auxiliary_device *adev,
        dev->mdev = mdev;
        dev->num_ports = num_ports;
 
-       if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_is_roce_init_enabled(mdev))
+       if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_get_roce_state(mdev))
                profile = &raw_eth_profile;
        else
                profile = &pf_profile;
index 2e2ad39..e66bf72 100644 (file)
@@ -708,6 +708,7 @@ struct mlx5_ib_umr_context {
 };
 
 enum {
+       MLX5_UMR_STATE_UNINIT,
        MLX5_UMR_STATE_ACTIVE,
        MLX5_UMR_STATE_RECOVER,
        MLX5_UMR_STATE_ERR,
index e00b94d..d5105b5 100644 (file)
@@ -177,6 +177,7 @@ int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
 
        sema_init(&dev->umrc.sem, MAX_UMR_WR);
        mutex_init(&dev->umrc.lock);
+       dev->umrc.state = MLX5_UMR_STATE_ACTIVE;
 
        return 0;
 
@@ -191,6 +192,8 @@ destroy_pd:
 
 void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev)
 {
+       if (dev->umrc.state == MLX5_UMR_STATE_UNINIT)
+               return;
        ib_destroy_qp(dev->umrc.qp);
        ib_free_cq(dev->umrc.cq);
        ib_dealloc_pd(dev->umrc.pd);
index 1f4e602..7d47b52 100644 (file)
@@ -29,7 +29,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
        dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
 
        if (paddr)
-               return virt_to_page(paddr);
+               return virt_to_page((void *)paddr);
 
        return NULL;
 }
@@ -533,13 +533,23 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
                                        kunmap_local(kaddr);
                                }
                        } else {
-                               u64 va = sge->laddr + sge_off;
+                               /*
+                                * Cast to an uintptr_t to preserve all 64 bits
+                                * in sge->laddr.
+                                */
+                               uintptr_t va = (uintptr_t)(sge->laddr + sge_off);
 
-                               page_array[seg] = virt_to_page(va & PAGE_MASK);
+                               /*
+                                * virt_to_page() takes a (void *) pointer
+                                * so cast to a (void *) meaning it will be 64
+                                * bits on a 64 bit platform and 32 bits on a
+                                * 32 bit platform.
+                                */
+                               page_array[seg] = virt_to_page((void *)(va & PAGE_MASK));
                                if (do_crc)
                                        crypto_shash_update(
                                                c_tx->mpa_crc_hd,
-                                               (void *)(uintptr_t)va,
+                                               (void *)va,
                                                plen);
                        }
 
index baecde4..449904d 100644 (file)
@@ -1004,7 +1004,8 @@ rtrs_clt_get_copy_req(struct rtrs_clt_path *alive_path,
 static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con,
                                   struct rtrs_clt_io_req *req,
                                   struct rtrs_rbuf *rbuf, bool fr_en,
-                                  u32 size, u32 imm, struct ib_send_wr *wr,
+                                  u32 count, u32 size, u32 imm,
+                                  struct ib_send_wr *wr,
                                   struct ib_send_wr *tail)
 {
        struct rtrs_clt_path *clt_path = to_clt_path(con->c.path);
@@ -1024,12 +1025,12 @@ static int rtrs_post_rdma_write_sg(struct rtrs_clt_con *con,
                num_sge = 2;
                ptail = tail;
        } else {
-               for_each_sg(req->sglist, sg, req->sg_cnt, i) {
+               for_each_sg(req->sglist, sg, count, i) {
                        sge[i].addr   = sg_dma_address(sg);
                        sge[i].length = sg_dma_len(sg);
                        sge[i].lkey   = clt_path->s.dev->ib_pd->local_dma_lkey;
                }
-               num_sge = 1 + req->sg_cnt;
+               num_sge = 1 + count;
        }
        sge[i].addr   = req->iu->dma_addr;
        sge[i].length = size;
@@ -1142,7 +1143,7 @@ static int rtrs_clt_write_req(struct rtrs_clt_io_req *req)
         */
        rtrs_clt_update_all_stats(req, WRITE);
 
-       ret = rtrs_post_rdma_write_sg(req->con, req, rbuf, fr_en,
+       ret = rtrs_post_rdma_write_sg(req->con, req, rbuf, fr_en, count,
                                      req->usr_len + sizeof(*msg),
                                      imm, wr, &inv_wr);
        if (ret) {
index 34c03bd..4894e73 100644 (file)
@@ -595,7 +595,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
                struct sg_table *sgt = &srv_mr->sgt;
                struct scatterlist *s;
                struct ib_mr *mr;
-               int nr, chunks;
+               int nr, nr_sgt, chunks;
 
                chunks = chunks_per_mr * mri;
                if (!always_invalidate)
@@ -610,19 +610,19 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
                        sg_set_page(s, srv->chunks[chunks + i],
                                    max_chunk_size, 0);
 
-               nr = ib_dma_map_sg(srv_path->s.dev->ib_dev, sgt->sgl,
+               nr_sgt = ib_dma_map_sg(srv_path->s.dev->ib_dev, sgt->sgl,
                                   sgt->nents, DMA_BIDIRECTIONAL);
-               if (nr < sgt->nents) {
-                       err = nr < 0 ? nr : -EINVAL;
+               if (!nr_sgt) {
+                       err = -EINVAL;
                        goto free_sg;
                }
                mr = ib_alloc_mr(srv_path->s.dev->ib_pd, IB_MR_TYPE_MEM_REG,
-                                sgt->nents);
+                                nr_sgt);
                if (IS_ERR(mr)) {
                        err = PTR_ERR(mr);
                        goto unmap_sg;
                }
-               nr = ib_map_mr_sg(mr, sgt->sgl, sgt->nents,
+               nr = ib_map_mr_sg(mr, sgt->sgl, nr_sgt,
                                  NULL, max_chunk_size);
                if (nr < 0 || nr < sgt->nents) {
                        err = nr < 0 ? nr : -EINVAL;
@@ -641,7 +641,7 @@ static int map_cont_bufs(struct rtrs_srv_path *srv_path)
                        }
                }
                /* Eventually dma addr for each chunk can be cached */
-               for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
+               for_each_sg(sgt->sgl, s, nr_sgt, i)
                        srv_path->dma_addr[chunks + i] = sg_dma_address(s);
 
                ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey));
index 7720ea2..d7f69e5 100644 (file)
@@ -1961,7 +1961,8 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
                if (scmnd) {
                        req = scsi_cmd_priv(scmnd);
                        scmnd = srp_claim_req(ch, req, NULL, scmnd);
-               } else {
+               }
+               if (!scmnd) {
                        shost_printk(KERN_ERR, target->scsi_host,
                                     "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
                                     rsp->tag, ch - target->ch, ch->qp->qp_num);
index b2a68bc..b86de13 100644 (file)
@@ -50,6 +50,7 @@ static struct iforce_device iforce_device[] = {
        { 0x046d, 0xc291, "Logitech WingMan Formula Force",             btn_wheel, abs_wheel, ff_iforce },
        { 0x05ef, 0x020a, "AVB Top Shot Pegasus",                       btn_joystick_avb, abs_avb_pegasus, ff_iforce },
        { 0x05ef, 0x8884, "AVB Mag Turbo Force",                        btn_wheel, abs_wheel, ff_iforce },
+       { 0x05ef, 0x8886, "Boeder Force Feedback Wheel",                btn_wheel, abs_wheel, ff_iforce },
        { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel",   btn_wheel, abs_wheel, ff_iforce }, //?
        { 0x061c, 0xc0a4, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce }, //?
        { 0x061c, 0xc084, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce },
index f95a81b..2380546 100644 (file)
@@ -39,7 +39,7 @@ static void iforce_serio_xmit(struct iforce *iforce)
 
 again:
        if (iforce->xmit.head == iforce->xmit.tail) {
-               clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+               iforce_clear_xmit_and_wake(iforce);
                spin_unlock_irqrestore(&iforce->xmit_lock, flags);
                return;
        }
@@ -64,7 +64,7 @@ again:
        if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
                goto again;
 
-       clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+       iforce_clear_xmit_and_wake(iforce);
 
        spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 }
@@ -169,7 +169,7 @@ static irqreturn_t iforce_serio_irq(struct serio *serio,
                        iforce_serio->cmd_response_len = iforce_serio->len;
 
                        /* Signal that command is done */
-                       wake_up(&iforce->wait);
+                       wake_up_all(&iforce->wait);
                } else if (likely(iforce->type)) {
                        iforce_process_packet(iforce, iforce_serio->id,
                                              iforce_serio->data_in,
index ea58805..cba92bd 100644 (file)
@@ -30,7 +30,7 @@ static void __iforce_usb_xmit(struct iforce *iforce)
        spin_lock_irqsave(&iforce->xmit_lock, flags);
 
        if (iforce->xmit.head == iforce->xmit.tail) {
-               clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+               iforce_clear_xmit_and_wake(iforce);
                spin_unlock_irqrestore(&iforce->xmit_lock, flags);
                return;
        }
@@ -58,9 +58,9 @@ static void __iforce_usb_xmit(struct iforce *iforce)
        XMIT_INC(iforce->xmit.tail, n);
 
        if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) {
-               clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
                dev_warn(&iforce_usb->intf->dev,
                         "usb_submit_urb failed %d\n", n);
+               iforce_clear_xmit_and_wake(iforce);
        }
 
        /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -175,15 +175,15 @@ static void iforce_usb_out(struct urb *urb)
        struct iforce *iforce = &iforce_usb->iforce;
 
        if (urb->status) {
-               clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
                dev_dbg(&iforce_usb->intf->dev, "urb->status %d, exiting\n",
                        urb->status);
+               iforce_clear_xmit_and_wake(iforce);
                return;
        }
 
        __iforce_usb_xmit(iforce);
 
-       wake_up(&iforce->wait);
+       wake_up_all(&iforce->wait);
 }
 
 static int iforce_usb_probe(struct usb_interface *intf,
index 6aa761e..9ccb910 100644 (file)
@@ -119,6 +119,12 @@ static inline int iforce_get_id_packet(struct iforce *iforce, u8 id,
                                         response_data, response_len);
 }
 
+static inline void iforce_clear_xmit_and_wake(struct iforce *iforce)
+{
+       clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+       wake_up_all(&iforce->wait);
+}
+
 /* Public functions */
 /* iforce-main.c */
 int iforce_init_device(struct device *parent, u16 bustype,
index 93446b2..db793a5 100644 (file)
@@ -77,6 +77,7 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev,
                if (ret) {
                        dev_err(&pdev->dev, "Failed to read switch code: %d\n",
                                ret);
+                       fwnode_handle_put(child);
                        return ret;
                }
                iqs62x_keys->switches[i].code = val;
@@ -90,6 +91,8 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev,
                        iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ?
                                                         IQS62X_EVENT_HALL_N_T :
                                                         IQS62X_EVENT_HALL_S_T);
+
+               fwnode_handle_put(child);
        }
 
        return 0;
index 6528676..ad8660b 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 
-#define SNVS_HPVIDR1_REG       0xF8
+#define SNVS_HPVIDR1_REG       0xBF8
 #define SNVS_LPSR_REG          0x4C    /* LP Status Register */
 #define SNVS_LPCR_REG          0x38    /* LP Control Register */
 #define SNVS_HPSR_REG          0x14
index 3fb64db..76873aa 100644 (file)
@@ -98,6 +98,7 @@ static struct platform_driver rk805_pwrkey_driver = {
 };
 module_platform_driver(rk805_pwrkey_driver);
 
+MODULE_ALIAS("platform:rk805-pwrkey");
 MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
 MODULE_DESCRIPTION("RK805 PMIC Power Key driver");
 MODULE_LICENSE("GPL");
index 434d48a..ffad142 100644 (file)
@@ -186,7 +186,6 @@ static const char * const smbus_pnp_ids[] = {
        "LEN2044", /* L470  */
        "LEN2054", /* E480 */
        "LEN2055", /* E580 */
-       "LEN2064", /* T14 Gen 1 AMD / P14s Gen 1 AMD */
        "LEN2068", /* T14 Gen 1 */
        "SYN3052", /* HP EliteBook 840 G4 */
        "SYN3221", /* HP 15-ay000 */
index d016505..21c0ddd 100644 (file)
@@ -95,6 +95,7 @@ static const struct goodix_chip_data gt9x_chip_data = {
 
 static const struct goodix_chip_id goodix_chip_ids[] = {
        { .id = "1151", .data = &gt1x_chip_data },
+       { .id = "1158", .data = &gt1x_chip_data },
        { .id = "5663", .data = &gt1x_chip_data },
        { .id = "5688", .data = &gt1x_chip_data },
        { .id = "917S", .data = &gt1x_chip_data },
@@ -1508,6 +1509,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
 #ifdef CONFIG_OF
 static const struct of_device_id goodix_of_match[] = {
        { .compatible = "goodix,gt1151" },
+       { .compatible = "goodix,gt1158" },
        { .compatible = "goodix,gt5663" },
        { .compatible = "goodix,gt5688" },
        { .compatible = "goodix,gt911" },
index 2745bf1..83f4be0 100644 (file)
@@ -1453,7 +1453,7 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
                                              "ce", GPIOD_OUT_LOW);
        if (IS_ERR(ts->gpio_ce)) {
                error = PTR_ERR(ts->gpio_ce);
-               if (error != EPROBE_DEFER)
+               if (error != -EPROBE_DEFER)
                        dev_err(&client->dev,
                                "Failed to get gpio: %d\n", error);
                return error;
index 65b8e4f..828672a 100644 (file)
@@ -939,7 +939,8 @@ static void build_completion_wait(struct iommu_cmd *cmd,
        memset(cmd, 0, sizeof(*cmd));
        cmd->data[0] = lower_32_bits(paddr) | CMD_COMPL_WAIT_STORE_MASK;
        cmd->data[1] = upper_32_bits(paddr);
-       cmd->data[2] = data;
+       cmd->data[2] = lower_32_bits(data);
+       cmd->data[3] = upper_32_bits(data);
        CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
 }
 
index 696d555..6a1f02c 100644 (file)
@@ -777,6 +777,8 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
        if (dev_state->domain == NULL)
                goto out_free_states;
 
+       /* See iommu_is_default_domain() */
+       dev_state->domain->type = IOMMU_DOMAIN_IDENTITY;
        amd_iommu_domain_direct_map(dev_state->domain);
 
        ret = amd_iommu_domain_enable_v2(dev_state->domain, pasids);
index 7cca030..31bc50e 100644 (file)
@@ -163,38 +163,6 @@ static phys_addr_t root_entry_uctp(struct root_entry *re)
        return re->hi & VTD_PAGE_MASK;
 }
 
-static inline void context_clear_pasid_enable(struct context_entry *context)
-{
-       context->lo &= ~(1ULL << 11);
-}
-
-static inline bool context_pasid_enabled(struct context_entry *context)
-{
-       return !!(context->lo & (1ULL << 11));
-}
-
-static inline void context_set_copied(struct context_entry *context)
-{
-       context->hi |= (1ull << 3);
-}
-
-static inline bool context_copied(struct context_entry *context)
-{
-       return !!(context->hi & (1ULL << 3));
-}
-
-static inline bool __context_present(struct context_entry *context)
-{
-       return (context->lo & 1);
-}
-
-bool context_present(struct context_entry *context)
-{
-       return context_pasid_enabled(context) ?
-            __context_present(context) :
-            __context_present(context) && !context_copied(context);
-}
-
 static inline void context_set_present(struct context_entry *context)
 {
        context->lo |= 1;
@@ -242,6 +210,26 @@ static inline void context_clear_entry(struct context_entry *context)
        context->hi = 0;
 }
 
+static inline bool context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+       if (!iommu->copied_tables)
+               return false;
+
+       return test_bit(((long)bus << 8) | devfn, iommu->copied_tables);
+}
+
+static inline void
+set_context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+       set_bit(((long)bus << 8) | devfn, iommu->copied_tables);
+}
+
+static inline void
+clear_context_copied(struct intel_iommu *iommu, u8 bus, u8 devfn)
+{
+       clear_bit(((long)bus << 8) | devfn, iommu->copied_tables);
+}
+
 /*
  * This domain is a statically identity mapping domain.
  *     1. This domain creats a static 1:1 mapping to all usable memory.
@@ -402,14 +390,36 @@ static inline int domain_pfn_supported(struct dmar_domain *domain,
        return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
 }
 
+/*
+ * Calculate the Supported Adjusted Guest Address Widths of an IOMMU.
+ * Refer to 11.4.2 of the VT-d spec for the encoding of each bit of
+ * the returned SAGAW.
+ */
+static unsigned long __iommu_calculate_sagaw(struct intel_iommu *iommu)
+{
+       unsigned long fl_sagaw, sl_sagaw;
+
+       fl_sagaw = BIT(2) | (cap_5lp_support(iommu->cap) ? BIT(3) : 0);
+       sl_sagaw = cap_sagaw(iommu->cap);
+
+       /* Second level only. */
+       if (!sm_supported(iommu) || !ecap_flts(iommu->ecap))
+               return sl_sagaw;
+
+       /* First level only. */
+       if (!ecap_slts(iommu->ecap))
+               return fl_sagaw;
+
+       return fl_sagaw & sl_sagaw;
+}
+
 static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
 {
        unsigned long sagaw;
        int agaw;
 
-       sagaw = cap_sagaw(iommu->cap);
-       for (agaw = width_to_agaw(max_gaw);
-            agaw >= 0; agaw--) {
+       sagaw = __iommu_calculate_sagaw(iommu);
+       for (agaw = width_to_agaw(max_gaw); agaw >= 0; agaw--) {
                if (test_bit(agaw, &sagaw))
                        break;
        }
@@ -505,8 +515,9 @@ static int domain_update_device_node(struct dmar_domain *domain)
 {
        struct device_domain_info *info;
        int nid = NUMA_NO_NODE;
+       unsigned long flags;
 
-       spin_lock(&domain->lock);
+       spin_lock_irqsave(&domain->lock, flags);
        list_for_each_entry(info, &domain->devices, link) {
                /*
                 * There could possibly be multiple device numa nodes as devices
@@ -518,7 +529,7 @@ static int domain_update_device_node(struct dmar_domain *domain)
                if (nid != NUMA_NO_NODE)
                        break;
        }
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&domain->lock, flags);
 
        return nid;
 }
@@ -578,6 +589,13 @@ struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
        struct context_entry *context;
        u64 *entry;
 
+       /*
+        * Except that the caller requested to allocate a new entry,
+        * returning a copied context entry makes no sense.
+        */
+       if (!alloc && context_copied(iommu, bus, devfn))
+               return NULL;
+
        entry = &root->lo;
        if (sm_supported(iommu)) {
                if (devfn >= 0x80) {
@@ -795,32 +813,11 @@ static void free_context_table(struct intel_iommu *iommu)
 }
 
 #ifdef CONFIG_DMAR_DEBUG
-static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn, u8 bus, u8 devfn)
+static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn,
+                        u8 bus, u8 devfn, struct dma_pte *parent, int level)
 {
-       struct device_domain_info *info;
-       struct dma_pte *parent, *pte;
-       struct dmar_domain *domain;
-       struct pci_dev *pdev;
-       int offset, level;
-
-       pdev = pci_get_domain_bus_and_slot(iommu->segment, bus, devfn);
-       if (!pdev)
-               return;
-
-       info = dev_iommu_priv_get(&pdev->dev);
-       if (!info || !info->domain) {
-               pr_info("device [%02x:%02x.%d] not probed\n",
-                       bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-               return;
-       }
-
-       domain = info->domain;
-       level = agaw_to_level(domain->agaw);
-       parent = domain->pgd;
-       if (!parent) {
-               pr_info("no page table setup\n");
-               return;
-       }
+       struct dma_pte *pte;
+       int offset;
 
        while (1) {
                offset = pfn_level_offset(pfn, level);
@@ -847,9 +844,10 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
        struct pasid_entry *entries, *pte;
        struct context_entry *ctx_entry;
        struct root_entry *rt_entry;
+       int i, dir_index, index, level;
        u8 devfn = source_id & 0xff;
        u8 bus = source_id >> 8;
-       int i, dir_index, index;
+       struct dma_pte *pgtable;
 
        pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr);
 
@@ -877,8 +875,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
                ctx_entry->hi, ctx_entry->lo);
 
        /* legacy mode does not require PASID entries */
-       if (!sm_supported(iommu))
+       if (!sm_supported(iommu)) {
+               level = agaw_to_level(ctx_entry->hi & 7);
+               pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
                goto pgtable_walk;
+       }
 
        /* get the pointer to pasid directory entry */
        dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
@@ -905,8 +906,16 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
        for (i = 0; i < ARRAY_SIZE(pte->val); i++)
                pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]);
 
+       if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) {
+               level = pte->val[2] & BIT_ULL(2) ? 5 : 4;
+               pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK);
+       } else {
+               level = agaw_to_level((pte->val[0] >> 2) & 0x7);
+               pgtable = phys_to_virt(pte->val[0] & VTD_PAGE_MASK);
+       }
+
 pgtable_walk:
-       pgtable_walk(iommu, addr >> VTD_PAGE_SHIFT, bus, devfn);
+       pgtable_walk(iommu, addr >> VTD_PAGE_SHIFT, bus, devfn, pgtable, level);
 }
 #endif
 
@@ -1345,19 +1354,20 @@ iommu_support_dev_iotlb(struct dmar_domain *domain, struct intel_iommu *iommu,
                        u8 bus, u8 devfn)
 {
        struct device_domain_info *info;
+       unsigned long flags;
 
        if (!iommu->qi)
                return NULL;
 
-       spin_lock(&domain->lock);
+       spin_lock_irqsave(&domain->lock, flags);
        list_for_each_entry(info, &domain->devices, link) {
                if (info->iommu == iommu && info->bus == bus &&
                    info->devfn == devfn) {
-                       spin_unlock(&domain->lock);
+                       spin_unlock_irqrestore(&domain->lock, flags);
                        return info->ats_supported ? info : NULL;
                }
        }
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&domain->lock, flags);
 
        return NULL;
 }
@@ -1366,8 +1376,9 @@ static void domain_update_iotlb(struct dmar_domain *domain)
 {
        struct device_domain_info *info;
        bool has_iotlb_device = false;
+       unsigned long flags;
 
-       spin_lock(&domain->lock);
+       spin_lock_irqsave(&domain->lock, flags);
        list_for_each_entry(info, &domain->devices, link) {
                if (info->ats_enabled) {
                        has_iotlb_device = true;
@@ -1375,7 +1386,7 @@ static void domain_update_iotlb(struct dmar_domain *domain)
                }
        }
        domain->has_iotlb_device = has_iotlb_device;
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&domain->lock, flags);
 }
 
 static void iommu_enable_dev_iotlb(struct device_domain_info *info)
@@ -1467,14 +1478,15 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
                                  u64 addr, unsigned mask)
 {
        struct device_domain_info *info;
+       unsigned long flags;
 
        if (!domain->has_iotlb_device)
                return;
 
-       spin_lock(&domain->lock);
+       spin_lock_irqsave(&domain->lock, flags);
        list_for_each_entry(info, &domain->devices, link)
                __iommu_flush_dev_iotlb(info, addr, mask);
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&domain->lock, flags);
 }
 
 static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
@@ -1688,6 +1700,11 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
                iommu->domain_ids = NULL;
        }
 
+       if (iommu->copied_tables) {
+               bitmap_free(iommu->copied_tables);
+               iommu->copied_tables = NULL;
+       }
+
        /* free context mapping */
        free_context_table(iommu);
 
@@ -1913,7 +1930,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
                goto out_unlock;
 
        ret = 0;
-       if (context_present(context))
+       if (context_present(context) && !context_copied(iommu, bus, devfn))
                goto out_unlock;
 
        /*
@@ -1925,7 +1942,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
         * in-flight DMA will exist, and we don't need to worry anymore
         * hereafter.
         */
-       if (context_copied(context)) {
+       if (context_copied(iommu, bus, devfn)) {
                u16 did_old = context_domain_id(context);
 
                if (did_old < cap_ndoms(iommu->cap)) {
@@ -1936,6 +1953,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
                        iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
                                                 DMA_TLB_DSI_FLUSH);
                }
+
+               clear_context_copied(iommu, bus, devfn);
        }
 
        context_clear_entry(context);
@@ -2429,6 +2448,7 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
 {
        struct device_domain_info *info = dev_iommu_priv_get(dev);
        struct intel_iommu *iommu;
+       unsigned long flags;
        u8 bus, devfn;
        int ret;
 
@@ -2440,9 +2460,9 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
        if (ret)
                return ret;
        info->domain = domain;
-       spin_lock(&domain->lock);
+       spin_lock_irqsave(&domain->lock, flags);
        list_add(&info->link, &domain->devices);
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&domain->lock, flags);
 
        /* PASID table is mandatory for a PCI device in scalable mode. */
        if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
@@ -2684,32 +2704,14 @@ static int copy_context_table(struct intel_iommu *iommu,
                /* Now copy the context entry */
                memcpy(&ce, old_ce + idx, sizeof(ce));
 
-               if (!__context_present(&ce))
+               if (!context_present(&ce))
                        continue;
 
                did = context_domain_id(&ce);
                if (did >= 0 && did < cap_ndoms(iommu->cap))
                        set_bit(did, iommu->domain_ids);
 
-               /*
-                * We need a marker for copied context entries. This
-                * marker needs to work for the old format as well as
-                * for extended context entries.
-                *
-                * Bit 67 of the context entry is used. In the old
-                * format this bit is available to software, in the
-                * extended format it is the PGE bit, but PGE is ignored
-                * by HW if PASIDs are disabled (and thus still
-                * available).
-                *
-                * So disable PASIDs first and then mark the entry
-                * copied. This means that we don't copy PASID
-                * translations from the old kernel, but this is fine as
-                * faults there are not fatal.
-                */
-               context_clear_pasid_enable(&ce);
-               context_set_copied(&ce);
-
+               set_context_copied(iommu, bus, devfn);
                new_ce[idx] = ce;
        }
 
@@ -2735,8 +2737,8 @@ static int copy_translation_tables(struct intel_iommu *iommu)
        bool new_ext, ext;
 
        rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
-       ext        = !!(rtaddr_reg & DMA_RTADDR_RTT);
-       new_ext    = !!ecap_ecs(iommu->ecap);
+       ext        = !!(rtaddr_reg & DMA_RTADDR_SMT);
+       new_ext    = !!sm_supported(iommu);
 
        /*
         * The RTT bit can only be changed when translation is disabled,
@@ -2747,6 +2749,10 @@ static int copy_translation_tables(struct intel_iommu *iommu)
        if (new_ext != ext)
                return -EINVAL;
 
+       iommu->copied_tables = bitmap_zalloc(BIT_ULL(16), GFP_KERNEL);
+       if (!iommu->copied_tables)
+               return -ENOMEM;
+
        old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
        if (!old_rt_phys)
                return -EINVAL;
@@ -4080,6 +4086,7 @@ static void dmar_remove_one_dev_info(struct device *dev)
        struct device_domain_info *info = dev_iommu_priv_get(dev);
        struct dmar_domain *domain = info->domain;
        struct intel_iommu *iommu = info->iommu;
+       unsigned long flags;
 
        if (!dev_is_real_dma_subdevice(info->dev)) {
                if (dev_is_pci(info->dev) && sm_supported(iommu))
@@ -4091,9 +4098,9 @@ static void dmar_remove_one_dev_info(struct device *dev)
                intel_pasid_free_table(info->dev);
        }
 
-       spin_lock(&domain->lock);
+       spin_lock_irqsave(&domain->lock, flags);
        list_del(&info->link);
-       spin_unlock(&domain->lock);
+       spin_unlock_irqrestore(&domain->lock, flags);
 
        domain_detach_iommu(domain, iommu);
        info->domain = NULL;
@@ -4412,19 +4419,20 @@ static void domain_set_force_snooping(struct dmar_domain *domain)
 static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domain)
 {
        struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+       unsigned long flags;
 
        if (dmar_domain->force_snooping)
                return true;
 
-       spin_lock(&dmar_domain->lock);
+       spin_lock_irqsave(&dmar_domain->lock, flags);
        if (!domain_support_force_snooping(dmar_domain)) {
-               spin_unlock(&dmar_domain->lock);
+               spin_unlock_irqrestore(&dmar_domain->lock, flags);
                return false;
        }
 
        domain_set_force_snooping(dmar_domain);
        dmar_domain->force_snooping = true;
-       spin_unlock(&dmar_domain->lock);
+       spin_unlock_irqrestore(&dmar_domain->lock, flags);
 
        return true;
 }
index fae45bb..74b0e19 100644 (file)
 #define ecap_dis(e)            (((e) >> 27) & 0x1)
 #define ecap_nest(e)           (((e) >> 26) & 0x1)
 #define ecap_mts(e)            (((e) >> 25) & 0x1)
-#define ecap_ecs(e)            (((e) >> 24) & 0x1)
 #define ecap_iotlb_offset(e)   ((((e) >> 8) & 0x3ff) * 16)
 #define ecap_max_iotlb_offset(e) (ecap_iotlb_offset(e) + 16)
 #define ecap_coherent(e)       ((e) & 0x1)
 #define DMA_GSTS_CFIS (((u32)1) << 23)
 
 /* DMA_RTADDR_REG */
-#define DMA_RTADDR_RTT (((u64)1) << 11)
 #define DMA_RTADDR_SMT (((u64)1) << 10)
 
 /* CCMD_REG */
@@ -579,6 +577,7 @@ struct intel_iommu {
 
 #ifdef CONFIG_INTEL_IOMMU
        unsigned long   *domain_ids; /* bitmap of domains */
+       unsigned long   *copied_tables; /* bitmap of copied tables */
        spinlock_t      lock; /* protect context, domain ids */
        struct root_entry *root_entry; /* virtual address */
 
@@ -701,6 +700,11 @@ static inline int nr_pte_to_next_page(struct dma_pte *pte)
                (struct dma_pte *)ALIGN((unsigned long)pte, VTD_PAGE_SIZE) - pte;
 }
 
+static inline bool context_present(struct context_entry *context)
+{
+       return (context->lo & 1);
+}
+
 extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
 
 extern int dmar_enable_qi(struct intel_iommu *iommu);
@@ -784,7 +788,6 @@ static inline void intel_iommu_debugfs_init(void) {}
 #endif /* CONFIG_INTEL_IOMMU_DEBUGFS */
 
 extern const struct attribute_group *intel_iommu_groups[];
-bool context_present(struct context_entry *context);
 struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
                                         u8 devfn, int alloc);
 
index 780fb70..3a80814 100644 (file)
@@ -3076,6 +3076,24 @@ out:
        return ret;
 }
 
+static bool iommu_is_default_domain(struct iommu_group *group)
+{
+       if (group->domain == group->default_domain)
+               return true;
+
+       /*
+        * If the default domain was set to identity and it is still an identity
+        * domain then we consider this a pass. This happens because of
+        * amd_iommu_init_device() replacing the default idenytity domain with an
+        * identity domain that has a different configuration for AMDGPU.
+        */
+       if (group->default_domain &&
+           group->default_domain->type == IOMMU_DOMAIN_IDENTITY &&
+           group->domain && group->domain->type == IOMMU_DOMAIN_IDENTITY)
+               return true;
+       return false;
+}
+
 /**
  * iommu_device_use_default_domain() - Device driver wants to handle device
  *                                     DMA through the kernel DMA API.
@@ -3094,8 +3112,7 @@ int iommu_device_use_default_domain(struct device *dev)
 
        mutex_lock(&group->mutex);
        if (group->owner_cnt) {
-               if (group->domain != group->default_domain ||
-                   group->owner) {
+               if (group->owner || !iommu_is_default_domain(group)) {
                        ret = -EBUSY;
                        goto unlock_out;
                }
index 41f4eb0..5696314 100644 (file)
@@ -40,7 +40,7 @@ static int of_iommu_xlate(struct device *dev,
         * a proper probe-ordering dependency mechanism in future.
         */
        if (!ops)
-               return -ENODEV;
+               return driver_deferred_probe_check_state(dev);
 
        if (!try_module_get(ops->owner))
                return -ENODEV;
index 08eeafc..8015117 100644 (file)
@@ -1006,7 +1006,18 @@ static int viommu_of_xlate(struct device *dev, struct of_phandle_args *args)
        return iommu_fwspec_add_ids(dev, args->args, 1);
 }
 
+static bool viommu_capable(enum iommu_cap cap)
+{
+       switch (cap) {
+       case IOMMU_CAP_CACHE_COHERENCY:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static struct iommu_ops viommu_ops = {
+       .capable                = viommu_capable,
        .domain_alloc           = viommu_domain_alloc,
        .probe_device           = viommu_probe_device,
        .probe_finalize         = viommu_probe_finalize,
index 66b9fa4..eb5ea5b 100644 (file)
@@ -561,6 +561,11 @@ config IRQ_LOONGARCH_CPU
        select GENERIC_IRQ_CHIP
        select IRQ_DOMAIN
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK
+       select LOONGSON_LIOINTC
+       select LOONGSON_EIOINTC
+       select LOONGSON_PCH_PIC
+       select LOONGSON_PCH_MSI
+       select LOONGSON_PCH_LPC
        help
          Support for the LoongArch CPU Interrupt Controller. For details of
          irq chip hierarchy on LoongArch platforms please read the document
@@ -623,8 +628,9 @@ config LOONGSON_PCH_MSI
 
 config LOONGSON_PCH_LPC
        bool "Loongson PCH LPC Controller"
+       depends on LOONGARCH
        depends on MACH_LOONGSON64
-       default (MACH_LOONGSON64 && LOONGARCH)
+       default MACH_LOONGSON64
        select IRQ_DOMAIN_HIERARCHY
        help
          Support for the Loongson PCH LPC Controller.
index 5ff09de..beead1a 100644 (file)
@@ -1574,13 +1574,15 @@ static int its_select_cpu(struct irq_data *d,
                          const struct cpumask *aff_mask)
 {
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
-       cpumask_var_t tmpmask;
+       static DEFINE_RAW_SPINLOCK(tmpmask_lock);
+       static struct cpumask __tmpmask;
+       struct cpumask *tmpmask;
+       unsigned long flags;
        int cpu, node;
-
-       if (!alloc_cpumask_var(&tmpmask, GFP_ATOMIC))
-               return -ENOMEM;
-
        node = its_dev->its->numa_node;
+       tmpmask = &__tmpmask;
+
+       raw_spin_lock_irqsave(&tmpmask_lock, flags);
 
        if (!irqd_affinity_is_managed(d)) {
                /* First try the NUMA node */
@@ -1634,7 +1636,7 @@ static int its_select_cpu(struct irq_data *d,
                cpu = cpumask_pick_least_loaded(d, tmpmask);
        }
 out:
-       free_cpumask_var(tmpmask);
+       raw_spin_unlock_irqrestore(&tmpmask_lock, flags);
 
        pr_debug("IRQ%d -> %*pbl CPU%d\n", d->irq, cpumask_pr_args(aff_mask), cpu);
        return cpu;
index a73763d..6a3f749 100644 (file)
@@ -716,7 +716,7 @@ static int stm32_exti_h_domain_alloc(struct irq_domain *dm,
 
        irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data);
 
-       if (!host_data->drv_data || !host_data->drv_data->desc_irqs)
+       if (!host_data->drv_data->desc_irqs)
                return -EINVAL;
 
        desc_irq = host_data->drv_data->desc_irqs[hwirq];
index a1bd6d9..909df82 100644 (file)
@@ -354,6 +354,12 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
 
 int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
+       struct vb2_queue *q = &ctx->vb_q;
+
+       if (b->index >= q->num_buffers) {
+               dprintk(1, "[%s] buffer index out of range\n", ctx->name);
+               return -EINVAL;
+       }
        vb2_core_querybuf(&ctx->vb_q, b->index, b);
        dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
        return 0;
@@ -378,8 +384,13 @@ int dvb_vb2_expbuf(struct dvb_vb2_ctx *ctx, struct dmx_exportbuffer *exp)
 
 int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
+       struct vb2_queue *q = &ctx->vb_q;
        int ret;
 
+       if (b->index >= q->num_buffers) {
+               dprintk(1, "[%s] buffer index out of range\n", ctx->name);
+               return -EINVAL;
+       }
        ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
        if (ret) {
                dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
index 95e8c29..d2f5f30 100644 (file)
@@ -228,7 +228,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
 {
        struct mtk_vcodec_dev *dev;
        struct video_device *vfd_enc;
-       struct resource *res;
        phandle rproc_phandle;
        enum mtk_vcodec_fw_type fw_type;
        int ret;
@@ -272,14 +271,12 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
                goto err_res;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get irq resource");
-               ret = -ENOENT;
+       dev->enc_irq = platform_get_irq(pdev, 0);
+       if (dev->enc_irq < 0) {
+               ret = dev->enc_irq;
                goto err_res;
        }
 
-       dev->enc_irq = platform_get_irq(pdev, 0);
        irq_set_status_flags(dev->enc_irq, IRQ_NOAUTOEN);
        ret = devm_request_irq(&pdev->dev, dev->enc_irq,
                               mtk_vcodec_enc_irq_handler,
index 0834d5f..39d2b03 100644 (file)
@@ -1416,42 +1416,37 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
 {
        int ret;
        struct device *dev = ir->dev;
-       char *data;
-
-       data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
-       if (!data) {
-               dev_err(dev, "%s: memory allocation failed!", __func__);
-               return;
-       }
+       char data[USB_CTRL_MSG_SZ];
 
        /*
         * This is a strange one. Windows issues a set address to the device
         * on the receive control pipe and expect a certain value pair back
         */
-       ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
-                             USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
-                             data, USB_CTRL_MSG_SZ, 3000);
+       ret = usb_control_msg_recv(ir->usbdev, 0, USB_REQ_SET_ADDRESS,
+                                  USB_DIR_IN | USB_TYPE_VENDOR,
+                                  0, 0, data, USB_CTRL_MSG_SZ, 3000,
+                                  GFP_KERNEL);
        dev_dbg(dev, "set address - ret = %d", ret);
        dev_dbg(dev, "set address - data[0] = %d, data[1] = %d",
                                                data[0], data[1]);
 
        /* set feature: bit rate 38400 bps */
-       ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-                             USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
-                             0xc04e, 0x0000, NULL, 0, 3000);
+       ret = usb_control_msg_send(ir->usbdev, 0,
+                                  USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+                                  0xc04e, 0x0000, NULL, 0, 3000, GFP_KERNEL);
 
        dev_dbg(dev, "set feature - ret = %d", ret);
 
        /* bRequest 4: set char length to 8 bits */
-       ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-                             4, USB_TYPE_VENDOR,
-                             0x0808, 0x0000, NULL, 0, 3000);
+       ret = usb_control_msg_send(ir->usbdev, 0,
+                                  4, USB_TYPE_VENDOR,
+                                  0x0808, 0x0000, NULL, 0, 3000, GFP_KERNEL);
        dev_dbg(dev, "set char length - retB = %d", ret);
 
        /* bRequest 2: set handshaking to use DTR/DSR */
-       ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-                             2, USB_TYPE_VENDOR,
-                             0x0000, 0x0100, NULL, 0, 3000);
+       ret = usb_control_msg_send(ir->usbdev, 0,
+                                  2, USB_TYPE_VENDOR,
+                                  0x0000, 0x0100, NULL, 0, 3000, GFP_KERNEL);
        dev_dbg(dev, "set handshake  - retC = %d", ret);
 
        /* device resume */
@@ -1459,8 +1454,6 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
 
        /* get hw/sw revision? */
        mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION));
-
-       kfree(data);
 }
 
 static void mceusb_gen2_init(struct mceusb_dev *ir)
index 7835bb0..e012b21 100644 (file)
@@ -511,7 +511,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb)
 
        if (fc_usb->uintf->cur_altsetting->desc.bNumEndpoints < 1)
                return -ENODEV;
-       if (!usb_endpoint_is_isoc_in(&fc_usb->uintf->cur_altsetting->endpoint[1].desc))
+       if (!usb_endpoint_is_isoc_in(&fc_usb->uintf->cur_altsetting->endpoint[0].desc))
                return -ENODEV;
 
        switch (fc_usb->udev->speed) {
index 9c05776..d509a4a 100644 (file)
@@ -2740,7 +2740,7 @@ static const struct usb_device_id uvc_ids[] = {
          .idProduct            = 0x4034,
          .bInterfaceClass      = USB_CLASS_VIDEO,
          .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
+         .bInterfaceProtocol   = UVC_PC_PROTOCOL_15,
          .driver_info          = (kernel_ulong_t)&uvc_ctrl_power_line_limited },
        /* LogiLink Wireless Webcam */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
index 0f3d6b5..55c26e7 100644 (file)
@@ -1040,6 +1040,8 @@ int v4l2_compat_get_array_args(struct file *file, void *mbuf,
 {
        int err = 0;
 
+       memset(mbuf, 0, array_size);
+
        switch (cmd) {
        case VIDIOC_G_FMT32:
        case VIDIOC_S_FMT32:
index c314025..e6fd355 100644 (file)
@@ -2872,9 +2872,9 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = {
        IOCTL_INFO(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO),
        IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)),
        IOCTL_INFO(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0),
-       IOCTL_INFO(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
-       IOCTL_INFO(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL),
-       IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
+       IOCTL_INFO(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL | INFO_FL_ALWAYS_COPY),
+       IOCTL_INFO(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL | INFO_FL_ALWAYS_COPY),
+       IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL | INFO_FL_ALWAYS_COPY),
        IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, v4l_stub_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)),
        IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, v4l_stub_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)),
        IOCTL_INFO(VIDIOC_G_ENC_INDEX, v4l_stub_g_enc_index, v4l_print_enc_idx, 0),
@@ -3367,8 +3367,7 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
                array_buf = kvmalloc(array_size, GFP_KERNEL);
                err = -ENOMEM;
                if (array_buf == NULL)
-                       goto out_array_args;
-               err = -EFAULT;
+                       goto out;
                if (in_compat_syscall())
                        err = v4l2_compat_get_array_args(file, array_buf,
                                                         user_ptr, array_size,
@@ -3377,7 +3376,7 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
                        err = copy_from_user(array_buf, user_ptr, array_size) ?
                                                                -EFAULT : 0;
                if (err)
-                       goto out_array_args;
+                       goto out;
                *kernel_ptr = array_buf;
        }
 
@@ -3395,6 +3394,13 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
                        trace_v4l2_qbuf(video_devdata(file)->minor, parg);
        }
 
+       /*
+        * Some ioctls can return an error, but still have valid
+        * results that must be returned.
+        */
+       if (err < 0 && !always_copy)
+               goto out;
+
        if (has_array_args) {
                *kernel_ptr = (void __force *)user_ptr;
                if (in_compat_syscall()) {
@@ -3409,16 +3415,8 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
                } else if (copy_to_user(user_ptr, array_buf, array_size)) {
                        err = -EFAULT;
                }
-               goto out_array_args;
        }
-       /*
-        * Some ioctls can return an error, but still have valid
-        * results that must be returned.
-        */
-       if (err < 0 && !always_copy)
-               goto out;
 
-out_array_args:
        if (video_put_user((void __user *)arg, parg, cmd, orig_cmd))
                err = -EFAULT;
 out:
index 93ebd17..5d9e348 100644 (file)
@@ -25,7 +25,7 @@
 #define SDSP_DOMAIN_ID (2)
 #define CDSP_DOMAIN_ID (3)
 #define FASTRPC_DEV_MAX                4 /* adsp, mdsp, slpi, cdsp*/
-#define FASTRPC_MAX_SESSIONS   13 /*12 compute, 1 cpz*/
+#define FASTRPC_MAX_SESSIONS   14
 #define FASTRPC_MAX_VMIDS      16
 #define FASTRPC_ALIGN          128
 #define FASTRPC_MAX_FDLIST     16
@@ -1943,7 +1943,12 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
        of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
 
        spin_lock_irqsave(&cctx->lock, flags);
-       sess = &cctx->session[cctx->sesscount];
+       if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
+               dev_err(&pdev->dev, "too many sessions\n");
+               spin_unlock_irqrestore(&cctx->lock, flags);
+               return -ENOSPC;
+       }
+       sess = &cctx->session[cctx->sesscount++];
        sess->used = false;
        sess->valid = true;
        sess->dev = dev;
@@ -1956,13 +1961,12 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
                struct fastrpc_session_ctx *dup_sess;
 
                for (i = 1; i < sessions; i++) {
-                       if (cctx->sesscount++ >= FASTRPC_MAX_SESSIONS)
+                       if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
                                break;
-                       dup_sess = &cctx->session[cctx->sesscount];
+                       dup_sess = &cctx->session[cctx->sesscount++];
                        memcpy(dup_sess, sess, sizeof(*dup_sess));
                }
        }
-       cctx->sesscount++;
        spin_unlock_irqrestore(&cctx->lock, flags);
        rc = dma_set_mask(dev, DMA_BIT_MASK(32));
        if (rc) {
index cee4c0b..3662bf5 100644 (file)
@@ -870,7 +870,8 @@ try_again:
         * the CCS bit is set as well. We deliberately deviate from the spec in
         * regards to this, which allows UHS-I to be supported for SDSC cards.
         */
-       if (!mmc_host_is_spi(host) && rocr && (*rocr & SD_ROCR_S18A)) {
+       if (!mmc_host_is_spi(host) && (ocr & SD_OCR_S18R) &&
+           rocr && (*rocr & SD_ROCR_S18A)) {
                err = mmc_set_uhs_voltage(host, pocr);
                if (err == -EAGAIN) {
                        retries--;
@@ -949,16 +950,17 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 
                /* Erase init depends on CSD and SSR */
                mmc_init_erase(card);
-
-               /*
-                * Fetch switch information from card.
-                */
-               err = mmc_read_switch(card);
-               if (err)
-                       return err;
        }
 
        /*
+        * Fetch switch information from card. Note, sd3_bus_mode can change if
+        * voltage switch outcome changes, so do this always.
+        */
+       err = mmc_read_switch(card);
+       if (err)
+               return err;
+
+       /*
         * For SPI, enable CRC as appropriate.
         * This CRC enable is located AFTER the reading of the
         * card registers because some SDHC cards are not able
@@ -1480,26 +1482,15 @@ retry:
        if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) &&
            mmc_sd_card_using_v18(card) &&
            host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
-               /*
-                * Re-read switch information in case it has changed since
-                * oldcard was initialized.
-                */
-               if (oldcard) {
-                       err = mmc_read_switch(card);
-                       if (err)
-                               goto free_card;
-               }
-               if (mmc_sd_card_using_v18(card)) {
-                       if (mmc_host_set_uhs_voltage(host) ||
-                           mmc_sd_init_uhs_card(card)) {
-                               v18_fixup_failed = true;
-                               mmc_power_cycle(host, ocr);
-                               if (!oldcard)
-                                       mmc_remove_card(card);
-                               goto retry;
-                       }
-                       goto done;
+               if (mmc_host_set_uhs_voltage(host) ||
+                   mmc_sd_init_uhs_card(card)) {
+                       v18_fixup_failed = true;
+                       mmc_power_cycle(host, ocr);
+                       if (!oldcard)
+                               mmc_remove_card(card);
+                       goto retry;
                }
+               goto cont;
        }
 
        /* Initialization sequence for UHS-I cards */
@@ -1534,7 +1525,7 @@ retry:
                        mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
                }
        }
-
+cont:
        if (!oldcard) {
                /* Read/parse the extension registers. */
                err = sd_read_ext_regs(card);
@@ -1566,7 +1557,7 @@ retry:
                err = -EINVAL;
                goto free_card;
        }
-done:
+
        host->card = card;
        return 0;
 
index a5e05ed..9d35453 100644 (file)
@@ -34,7 +34,7 @@ static void mmc_hsq_pump_requests(struct mmc_hsq *hsq)
        spin_lock_irqsave(&hsq->lock, flags);
 
        /* Make sure we are not already running a request now */
-       if (hsq->mrq) {
+       if (hsq->mrq || hsq->recovery_halt) {
                spin_unlock_irqrestore(&hsq->lock, flags);
                return;
        }
index b6eb75f..dfc3ffd 100644 (file)
 #define CLK_DIV_MASK           0x7f
 
 /* REG_BUS_WIDTH */
-#define BUS_WIDTH_8            BIT(2)
-#define BUS_WIDTH_4            BIT(1)
+#define BUS_WIDTH_4_SUPPORT    BIT(3)
+#define BUS_WIDTH_4            BIT(2)
 #define BUS_WIDTH_1            BIT(0)
 
 #define MMC_VDD_360            23
@@ -524,9 +524,6 @@ static void moxart_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        case MMC_BUS_WIDTH_4:
                writel(BUS_WIDTH_4, host->base + REG_BUS_WIDTH);
                break;
-       case MMC_BUS_WIDTH_8:
-               writel(BUS_WIDTH_8, host->base + REG_BUS_WIDTH);
-               break;
        default:
                writel(BUS_WIDTH_1, host->base + REG_BUS_WIDTH);
                break;
@@ -651,16 +648,8 @@ static int moxart_probe(struct platform_device *pdev)
                dmaengine_slave_config(host->dma_chan_rx, &cfg);
        }
 
-       switch ((readl(host->base + REG_BUS_WIDTH) >> 3) & 3) {
-       case 1:
+       if (readl(host->base + REG_BUS_WIDTH) & BUS_WIDTH_4_SUPPORT)
                mmc->caps |= MMC_CAP_4_BIT_DATA;
-               break;
-       case 2:
-               mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-               break;
-       default:
-               break;
-       }
 
        writel(0, host->base + REG_INTERRUPT_MASK);
 
index 7689ffe..2511728 100644 (file)
@@ -3928,7 +3928,7 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
 
        if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) {
                *cmd_error = -EILSEQ;
-               if (!mmc_op_tuning(host->cmd->opcode))
+               if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
                        sdhci_err_stats_inc(host, CMD_CRC);
        } else if (intmask & SDHCI_INT_TIMEOUT) {
                *cmd_error = -ETIMEDOUT;
@@ -3938,7 +3938,7 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
 
        if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) {
                *data_error = -EILSEQ;
-               if (!mmc_op_tuning(host->cmd->opcode))
+               if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
                        sdhci_err_stats_inc(host, DAT_CRC);
        } else if (intmask & SDHCI_INT_DATA_TIMEOUT) {
                *data_error = -ETIMEDOUT;
index 184608b..e58a1e0 100644 (file)
@@ -88,8 +88,9 @@ static const u8 null_mac_addr[ETH_ALEN + 2] __long_aligned = {
 static const u16 ad_ticks_per_sec = 1000 / AD_TIMER_INTERVAL;
 static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
-static const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned =
-       MULTICAST_LACPDU_ADDR;
+const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned = {
+       0x01, 0x80, 0xC2, 0x00, 0x00, 0x02
+};
 
 /* ================= main 802.3ad protocol functions ================== */
 static int ad_lacpdu_send(struct port *port);
index 2f4da2c..86d4230 100644 (file)
@@ -865,12 +865,8 @@ static void bond_hw_addr_flush(struct net_device *bond_dev,
        dev_uc_unsync(slave_dev, bond_dev);
        dev_mc_unsync(slave_dev, bond_dev);
 
-       if (BOND_MODE(bond) == BOND_MODE_8023AD) {
-               /* del lacpdu mc addr from mc list */
-               u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
-
-               dev_mc_del(slave_dev, lacpdu_multicast);
-       }
+       if (BOND_MODE(bond) == BOND_MODE_8023AD)
+               dev_mc_del(slave_dev, lacpdu_mcast_addr);
 }
 
 /*--------------------------- Active slave change ---------------------------*/
@@ -890,7 +886,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
                if (bond->dev->flags & IFF_ALLMULTI)
                        dev_set_allmulti(old_active->dev, -1);
 
-               bond_hw_addr_flush(bond->dev, old_active->dev);
+               if (bond->dev->flags & IFF_UP)
+                       bond_hw_addr_flush(bond->dev, old_active->dev);
        }
 
        if (new_active) {
@@ -901,10 +898,12 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
                if (bond->dev->flags & IFF_ALLMULTI)
                        dev_set_allmulti(new_active->dev, 1);
 
-               netif_addr_lock_bh(bond->dev);
-               dev_uc_sync(new_active->dev, bond->dev);
-               dev_mc_sync(new_active->dev, bond->dev);
-               netif_addr_unlock_bh(bond->dev);
+               if (bond->dev->flags & IFF_UP) {
+                       netif_addr_lock_bh(bond->dev);
+                       dev_uc_sync(new_active->dev, bond->dev);
+                       dev_mc_sync(new_active->dev, bond->dev);
+                       netif_addr_unlock_bh(bond->dev);
+               }
        }
 }
 
@@ -2166,16 +2165,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
                        }
                }
 
-               netif_addr_lock_bh(bond_dev);
-               dev_mc_sync_multiple(slave_dev, bond_dev);
-               dev_uc_sync_multiple(slave_dev, bond_dev);
-               netif_addr_unlock_bh(bond_dev);
-
-               if (BOND_MODE(bond) == BOND_MODE_8023AD) {
-                       /* add lacpdu mc addr to mc list */
-                       u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+               if (bond_dev->flags & IFF_UP) {
+                       netif_addr_lock_bh(bond_dev);
+                       dev_mc_sync_multiple(slave_dev, bond_dev);
+                       dev_uc_sync_multiple(slave_dev, bond_dev);
+                       netif_addr_unlock_bh(bond_dev);
 
-                       dev_mc_add(slave_dev, lacpdu_multicast);
+                       if (BOND_MODE(bond) == BOND_MODE_8023AD)
+                               dev_mc_add(slave_dev, lacpdu_mcast_addr);
                }
        }
 
@@ -2447,7 +2444,8 @@ static int __bond_release_one(struct net_device *bond_dev,
                if (old_flags & IFF_ALLMULTI)
                        dev_set_allmulti(slave_dev, -1);
 
-               bond_hw_addr_flush(bond_dev, slave_dev);
+               if (old_flags & IFF_UP)
+                       bond_hw_addr_flush(bond_dev, slave_dev);
        }
 
        slave_disable_netpoll(slave);
@@ -3167,6 +3165,9 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
 found:
                if (!ipv6_dev_get_saddr(dev_net(dst->dev), dst->dev, &targets[i], 0, &saddr))
                        bond_ns_send(slave, &targets[i], &saddr, tags);
+               else
+                       bond_ns_send(slave, &targets[i], &in6addr_any, tags);
+
                dst_release(dst);
                kfree(tags);
        }
@@ -3198,12 +3199,19 @@ static bool bond_has_this_ip6(struct bonding *bond, struct in6_addr *addr)
        return ret;
 }
 
-static void bond_validate_ns(struct bonding *bond, struct slave *slave,
+static void bond_validate_na(struct bonding *bond, struct slave *slave,
                             struct in6_addr *saddr, struct in6_addr *daddr)
 {
        int i;
 
-       if (ipv6_addr_any(saddr) || !bond_has_this_ip6(bond, daddr)) {
+       /* Ignore NAs that:
+        * 1. Source address is unspecified address.
+        * 2. Dest address is neither all-nodes multicast address nor
+        *    exist on bond interface.
+        */
+       if (ipv6_addr_any(saddr) ||
+           (!ipv6_addr_equal(daddr, &in6addr_linklocal_allnodes) &&
+            !bond_has_this_ip6(bond, daddr))) {
                slave_dbg(bond->dev, slave->dev, "%s: sip %pI6c tip %pI6c not found\n",
                          __func__, saddr, daddr);
                return;
@@ -3246,14 +3254,14 @@ static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond,
         * see bond_arp_rcv().
         */
        if (bond_is_active_slave(slave))
-               bond_validate_ns(bond, slave, saddr, daddr);
+               bond_validate_na(bond, slave, saddr, daddr);
        else if (curr_active_slave &&
                 time_after(slave_last_rx(bond, curr_active_slave),
                            curr_active_slave->last_link_up))
-               bond_validate_ns(bond, slave, saddr, daddr);
+               bond_validate_na(bond, slave, saddr, daddr);
        else if (curr_arp_slave &&
                 bond_time_in_interval(bond, slave_last_tx(curr_arp_slave), 1))
-               bond_validate_ns(bond, slave, saddr, daddr);
+               bond_validate_na(bond, slave, saddr, daddr);
 
 out:
        return RX_HANDLER_ANOTHER;
@@ -4174,6 +4182,12 @@ static int bond_open(struct net_device *bond_dev)
        struct list_head *iter;
        struct slave *slave;
 
+       if (BOND_MODE(bond) == BOND_MODE_ROUNDROBIN && !bond->rr_tx_counter) {
+               bond->rr_tx_counter = alloc_percpu(u32);
+               if (!bond->rr_tx_counter)
+                       return -ENOMEM;
+       }
+
        /* reset slave->backup and slave->inactive */
        if (bond_has_slaves(bond)) {
                bond_for_each_slave(bond, slave, iter) {
@@ -4211,6 +4225,9 @@ static int bond_open(struct net_device *bond_dev)
                /* register to receive LACPDUs */
                bond->recv_probe = bond_3ad_lacpdu_recv;
                bond_3ad_initiate_agg_selection(bond, 1);
+
+               bond_for_each_slave(bond, slave, iter)
+                       dev_mc_add(slave->dev, lacpdu_mcast_addr);
        }
 
        if (bond_mode_can_use_xmit_hash(bond))
@@ -4222,6 +4239,7 @@ static int bond_open(struct net_device *bond_dev)
 static int bond_close(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
+       struct slave *slave;
 
        bond_work_cancel_all(bond);
        bond->send_peer_notif = 0;
@@ -4229,6 +4247,19 @@ static int bond_close(struct net_device *bond_dev)
                bond_alb_deinitialize(bond);
        bond->recv_probe = NULL;
 
+       if (bond_uses_primary(bond)) {
+               rcu_read_lock();
+               slave = rcu_dereference(bond->curr_active_slave);
+               if (slave)
+                       bond_hw_addr_flush(bond_dev, slave->dev);
+               rcu_read_unlock();
+       } else {
+               struct list_head *iter;
+
+               bond_for_each_slave(bond, slave, iter)
+                       bond_hw_addr_flush(bond_dev, slave->dev);
+       }
+
        return 0;
 }
 
@@ -6218,15 +6249,6 @@ static int bond_init(struct net_device *bond_dev)
        if (!bond->wq)
                return -ENOMEM;
 
-       if (BOND_MODE(bond) == BOND_MODE_ROUNDROBIN) {
-               bond->rr_tx_counter = alloc_percpu(u32);
-               if (!bond->rr_tx_counter) {
-                       destroy_workqueue(bond->wq);
-                       bond->wq = NULL;
-                       return -ENOMEM;
-               }
-       }
-
        spin_lock_init(&bond->stats_lock);
        netdev_lockdep_set_classes(bond_dev);
 
index f23a033..029cd81 100644 (file)
@@ -235,9 +235,22 @@ static inline u8 c_can_get_tx_tail(const struct c_can_tx_ring *ring)
        return ring->tail & (ring->obj_num - 1);
 }
 
-static inline u8 c_can_get_tx_free(const struct c_can_tx_ring *ring)
+static inline u8 c_can_get_tx_free(const struct c_can_priv *priv,
+                                  const struct c_can_tx_ring *ring)
 {
-       return ring->obj_num - (ring->head - ring->tail);
+       u8 head = c_can_get_tx_head(ring);
+       u8 tail = c_can_get_tx_tail(ring);
+
+       if (priv->type == BOSCH_D_CAN)
+               return ring->obj_num - (ring->head - ring->tail);
+
+       /* This is not a FIFO. C/D_CAN sends out the buffers
+        * prioritized. The lowest buffer number wins.
+        */
+       if (head < tail)
+               return 0;
+
+       return ring->obj_num - head;
 }
 
 #endif /* C_CAN_H */
index dc81328..d6605db 100644 (file)
@@ -429,7 +429,7 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
 static bool c_can_tx_busy(const struct c_can_priv *priv,
                          const struct c_can_tx_ring *tx_ring)
 {
-       if (c_can_get_tx_free(tx_ring) > 0)
+       if (c_can_get_tx_free(priv, tx_ring) > 0)
                return false;
 
        netif_stop_queue(priv->dev);
@@ -437,7 +437,7 @@ static bool c_can_tx_busy(const struct c_can_priv *priv,
        /* Memory barrier before checking tx_free (head and tail) */
        smp_mb();
 
-       if (c_can_get_tx_free(tx_ring) == 0) {
+       if (c_can_get_tx_free(priv, tx_ring) == 0) {
                netdev_dbg(priv->dev,
                           "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n",
                           tx_ring->head, tx_ring->tail,
@@ -465,7 +465,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
 
        idx = c_can_get_tx_head(tx_ring);
        tx_ring->head++;
-       if (c_can_get_tx_free(tx_ring) == 0)
+       if (c_can_get_tx_free(priv, tx_ring) == 0)
                netif_stop_queue(dev);
 
        if (idx < c_can_get_tx_tail(tx_ring))
@@ -748,7 +748,7 @@ static void c_can_do_tx(struct net_device *dev)
                return;
 
        tx_ring->tail += pkts;
-       if (c_can_get_tx_free(tx_ring)) {
+       if (c_can_get_tx_free(priv, tx_ring)) {
                /* Make sure that anybody stopping the queue after
                 * this sees the new tx_ring->tail.
                 */
@@ -760,8 +760,7 @@ static void c_can_do_tx(struct net_device *dev)
        stats->tx_packets += pkts;
 
        tail = c_can_get_tx_tail(tx_ring);
-
-       if (tail == 0) {
+       if (priv->type == BOSCH_D_CAN && tail == 0) {
                u8 head = c_can_get_tx_head(tx_ring);
 
                /* Start transmission for all cached messages */
index f857968..ccb438e 100644 (file)
@@ -941,11 +941,6 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
        u32 reg_ctrl, reg_id, reg_iflag1;
        int i;
 
-       if (unlikely(drop)) {
-               skb = ERR_PTR(-ENOBUFS);
-               goto mark_as_read;
-       }
-
        mb = flexcan_get_mb(priv, n);
 
        if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) {
@@ -974,6 +969,11 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
                reg_ctrl = priv->read(&mb->can_ctrl);
        }
 
+       if (unlikely(drop)) {
+               skb = ERR_PTR(-ENOBUFS);
+               goto mark_as_read;
+       }
+
        if (reg_ctrl & FLEXCAN_MB_CNT_EDL)
                skb = alloc_canfd_skb(offload->dev, &cfd);
        else
index baf749c..c1ff3c0 100644 (file)
@@ -824,6 +824,7 @@ static int gs_can_open(struct net_device *netdev)
                flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
 
        /* finally start device */
+       dev->can.state = CAN_STATE_ERROR_ACTIVE;
        dm->mode = cpu_to_le32(GS_CAN_MODE_START);
        dm->flags = cpu_to_le32(flags);
        rc = usb_control_msg(interface_to_usbdev(dev->iface),
@@ -835,13 +836,12 @@ static int gs_can_open(struct net_device *netdev)
        if (rc < 0) {
                netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
                kfree(dm);
+               dev->can.state = CAN_STATE_STOPPED;
                return rc;
        }
 
        kfree(dm);
 
-       dev->can.state = CAN_STATE_ERROR_ACTIVE;
-
        parent->active_channels++;
        if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
                netif_start_queue(netdev);
@@ -925,17 +925,21 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
 }
 
 /* blink LED's for finding the this interface */
-static int gs_usb_set_phys_id(struct net_device *dev,
+static int gs_usb_set_phys_id(struct net_device *netdev,
                              enum ethtool_phys_id_state state)
 {
+       const struct gs_can *dev = netdev_priv(netdev);
        int rc = 0;
 
+       if (!(dev->feature & GS_CAN_FEATURE_IDENTIFY))
+               return -EOPNOTSUPP;
+
        switch (state) {
        case ETHTOOL_ID_ACTIVE:
-               rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_ON);
+               rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_ON);
                break;
        case ETHTOOL_ID_INACTIVE:
-               rc = gs_usb_set_identify(dev, GS_CAN_IDENTIFY_OFF);
+               rc = gs_usb_set_identify(netdev, GS_CAN_IDENTIFY_OFF);
                break;
        default:
                break;
@@ -1072,9 +1076,10 @@ static struct gs_can *gs_make_candev(unsigned int channel,
                dev->feature |= GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX |
                        GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO;
 
-       if (le32_to_cpu(dconf->sw_version) > 1)
-               if (feature & GS_CAN_FEATURE_IDENTIFY)
-                       netdev->ethtool_ops = &gs_usb_ethtool_ops;
+       /* GS_CAN_FEATURE_IDENTIFY is only supported for sw_version > 1 */
+       if (!(le32_to_cpu(dconf->sw_version) > 1 &&
+             feature & GS_CAN_FEATURE_IDENTIFY))
+               dev->feature &= ~GS_CAN_FEATURE_IDENTIFY;
 
        kfree(bt_const);
 
index 6bd69a7..872aba6 100644 (file)
@@ -170,6 +170,13 @@ static const struct ksz_dev_ops ksz8_dev_ops = {
        .exit = ksz8_switch_exit,
 };
 
+static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port,
+                                       unsigned int mode,
+                                       phy_interface_t interface,
+                                       struct phy_device *phydev, int speed,
+                                       int duplex, bool tx_pause,
+                                       bool rx_pause);
+
 static const struct ksz_dev_ops ksz9477_dev_ops = {
        .setup = ksz9477_setup,
        .get_port_addr = ksz9477_get_port_addr,
@@ -196,6 +203,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
        .mdb_del = ksz9477_mdb_del,
        .change_mtu = ksz9477_change_mtu,
        .max_mtu = ksz9477_max_mtu,
+       .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
        .config_cpu_port = ksz9477_config_cpu_port,
        .enable_stp_addr = ksz9477_enable_stp_addr,
        .reset = ksz9477_reset_switch,
@@ -230,6 +238,7 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
        .mdb_del = ksz9477_mdb_del,
        .change_mtu = lan937x_change_mtu,
        .max_mtu = ksz9477_max_mtu,
+       .phylink_mac_link_up = ksz9477_phylink_mac_link_up,
        .config_cpu_port = lan937x_config_cpu_port,
        .enable_stp_addr = ksz9477_enable_stp_addr,
        .reset = lan937x_reset_switch,
@@ -1656,13 +1665,13 @@ static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex,
        ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
 }
 
-static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
-                                   unsigned int mode,
-                                   phy_interface_t interface,
-                                   struct phy_device *phydev, int speed,
-                                   int duplex, bool tx_pause, bool rx_pause)
+static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port,
+                                       unsigned int mode,
+                                       phy_interface_t interface,
+                                       struct phy_device *phydev, int speed,
+                                       int duplex, bool tx_pause,
+                                       bool rx_pause)
 {
-       struct ksz_device *dev = ds->priv;
        struct ksz_port *p;
 
        p = &dev->ports[port];
@@ -1676,6 +1685,15 @@ static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
        ksz_port_set_xmii_speed(dev, port, speed);
 
        ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
+}
+
+static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
+                                   unsigned int mode,
+                                   phy_interface_t interface,
+                                   struct phy_device *phydev, int speed,
+                                   int duplex, bool tx_pause, bool rx_pause)
+{
+       struct ksz_device *dev = ds->priv;
 
        if (dev->dev_ops->phylink_mac_link_up)
                dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface,
index daedd2b..5579644 100644 (file)
@@ -244,10 +244,6 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port)
                lan937x_port_cfg(dev, port, REG_PORT_CTRL_0,
                                 PORT_TAIL_TAG_ENABLE, true);
 
-       /* disable frame check length field */
-       lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_0, PORT_CHECK_LENGTH,
-                        false);
-
        /* set back pressure for half duplex */
        lan937x_port_cfg(dev, port, REG_PORT_MAC_CTRL_1, PORT_BACK_PRESSURE,
                         true);
index 8358079..409d5c3 100644 (file)
@@ -506,14 +506,19 @@ static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv)
 static int
 mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
 {
-       struct mt7530_priv *priv = ds->priv;
+       return 0;
+}
+
+static void
+mt7531_pll_setup(struct mt7530_priv *priv)
+{
        u32 top_sig;
        u32 hwstrap;
        u32 xtal;
        u32 val;
 
        if (mt7531_dual_sgmii_supported(priv))
-               return 0;
+               return;
 
        val = mt7530_read(priv, MT7531_CREV);
        top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR);
@@ -592,8 +597,6 @@ mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
        val |= EN_COREPLL;
        mt7530_write(priv, MT7531_PLLGP_EN, val);
        usleep_range(25, 35);
-
-       return 0;
 }
 
 static void
@@ -2326,11 +2329,17 @@ mt7531_setup(struct dsa_switch *ds)
                return -ENODEV;
        }
 
+       /* all MACs must be forced link-down before sw reset */
+       for (i = 0; i < MT7530_NUM_PORTS; i++)
+               mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK);
+
        /* Reset the switch through internal reset */
        mt7530_write(priv, MT7530_SYS_CTRL,
                     SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
                     SYS_CTRL_REG_RST);
 
+       mt7531_pll_setup(priv);
+
        if (mt7531_dual_sgmii_supported(priv)) {
                priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII;
 
@@ -2887,8 +2896,6 @@ mt7531_cpu_port_config(struct dsa_switch *ds, int port)
        case 6:
                interface = PHY_INTERFACE_MODE_2500BASEX;
 
-               mt7531_pad_setup(ds, interface);
-
                priv->p6_interface = interface;
                break;
        default:
index 1cdce8a..f8f19a8 100644 (file)
@@ -22,6 +22,7 @@
 #define VSC9959_NUM_PORTS              6
 
 #define VSC9959_TAS_GCL_ENTRY_MAX      63
+#define VSC9959_TAS_MIN_GATE_LEN_NS    33
 #define VSC9959_VCAP_POLICER_BASE      63
 #define VSC9959_VCAP_POLICER_MAX       383
 #define VSC9959_SWITCH_PCI_BAR         4
@@ -1478,6 +1479,23 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
        mdiobus_free(felix->imdio);
 }
 
+/* The switch considers any frame (regardless of size) as eligible for
+ * transmission if the traffic class gate is open for at least 33 ns.
+ * Overruns are prevented by cropping an interval at the end of the gate time
+ * slot for which egress scheduling is blocked, but we need to still keep 33 ns
+ * available for one packet to be transmitted, otherwise the port tc will hang.
+ * This function returns the size of a gate interval that remains available for
+ * setting the guard band, after reserving the space for one egress frame.
+ */
+static u64 vsc9959_tas_remaining_gate_len_ps(u64 gate_len_ns)
+{
+       /* Gate always open */
+       if (gate_len_ns == U64_MAX)
+               return U64_MAX;
+
+       return (gate_len_ns - VSC9959_TAS_MIN_GATE_LEN_NS) * PSEC_PER_NSEC;
+}
+
 /* Extract shortest continuous gate open intervals in ns for each traffic class
  * of a cyclic tc-taprio schedule. If a gate is always open, the duration is
  * considered U64_MAX. If the gate is always closed, it is considered 0.
@@ -1539,6 +1557,65 @@ static void vsc9959_tas_min_gate_lengths(struct tc_taprio_qopt_offload *taprio,
                        min_gate_len[tc] = 0;
 }
 
+/* ocelot_write_rix is a macro that concatenates QSYS_MAXSDU_CFG_* with _RSZ,
+ * so we need to spell out the register access to each traffic class in helper
+ * functions, to simplify callers
+ */
+static void vsc9959_port_qmaxsdu_set(struct ocelot *ocelot, int port, int tc,
+                                    u32 max_sdu)
+{
+       switch (tc) {
+       case 0:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_0,
+                                port);
+               break;
+       case 1:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_1,
+                                port);
+               break;
+       case 2:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_2,
+                                port);
+               break;
+       case 3:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_3,
+                                port);
+               break;
+       case 4:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_4,
+                                port);
+               break;
+       case 5:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_5,
+                                port);
+               break;
+       case 6:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_6,
+                                port);
+               break;
+       case 7:
+               ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_7,
+                                port);
+               break;
+       }
+}
+
+static u32 vsc9959_port_qmaxsdu_get(struct ocelot *ocelot, int port, int tc)
+{
+       switch (tc) {
+       case 0: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_0, port);
+       case 1: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_1, port);
+       case 2: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_2, port);
+       case 3: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_3, port);
+       case 4: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_4, port);
+       case 5: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_5, port);
+       case 6: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_6, port);
+       case 7: return ocelot_read_rix(ocelot, QSYS_QMAXSDU_CFG_7, port);
+       default:
+               return 0;
+       }
+}
+
 /* Update QSYS_PORT_MAX_SDU to make sure the static guard bands added by the
  * switch (see the ALWAYS_GUARD_BAND_SCH_Q comment) are correct at all MTU
  * values (the default value is 1518). Also, for traffic class windows smaller
@@ -1595,11 +1672,16 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
 
        vsc9959_tas_min_gate_lengths(ocelot_port->taprio, min_gate_len);
 
+       mutex_lock(&ocelot->fwd_domain_lock);
+
        for (tc = 0; tc < OCELOT_NUM_TC; tc++) {
+               u64 remaining_gate_len_ps;
                u32 max_sdu;
 
-               if (min_gate_len[tc] == U64_MAX /* Gate always open */ ||
-                   min_gate_len[tc] * PSEC_PER_NSEC > needed_bit_time_ps) {
+               remaining_gate_len_ps =
+                       vsc9959_tas_remaining_gate_len_ps(min_gate_len[tc]);
+
+               if (remaining_gate_len_ps > needed_bit_time_ps) {
                        /* Setting QMAXSDU_CFG to 0 disables oversized frame
                         * dropping.
                         */
@@ -1612,9 +1694,15 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
                        /* If traffic class doesn't support a full MTU sized
                         * frame, make sure to enable oversize frame dropping
                         * for frames larger than the smallest that would fit.
+                        *
+                        * However, the exact same register, QSYS_QMAXSDU_CFG_*,
+                        * controls not only oversized frame dropping, but also
+                        * per-tc static guard band lengths, so it reduces the
+                        * useful gate interval length. Therefore, be careful
+                        * to calculate a guard band (and therefore max_sdu)
+                        * that still leaves 33 ns available in the time slot.
                         */
-                       max_sdu = div_u64(min_gate_len[tc] * PSEC_PER_NSEC,
-                                         picos_per_byte);
+                       max_sdu = div_u64(remaining_gate_len_ps, picos_per_byte);
                        /* A TC gate may be completely closed, which is a
                         * special case where all packets are oversized.
                         * Any limit smaller than 64 octets accomplishes this
@@ -1637,47 +1725,14 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
                                 max_sdu);
                }
 
-               /* ocelot_write_rix is a macro that concatenates
-                * QSYS_MAXSDU_CFG_* with _RSZ, so we need to spell out
-                * the writes to each traffic class
-                */
-               switch (tc) {
-               case 0:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_0,
-                                        port);
-                       break;
-               case 1:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_1,
-                                        port);
-                       break;
-               case 2:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_2,
-                                        port);
-                       break;
-               case 3:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_3,
-                                        port);
-                       break;
-               case 4:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_4,
-                                        port);
-                       break;
-               case 5:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_5,
-                                        port);
-                       break;
-               case 6:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_6,
-                                        port);
-                       break;
-               case 7:
-                       ocelot_write_rix(ocelot, max_sdu, QSYS_QMAXSDU_CFG_7,
-                                        port);
-                       break;
-               }
+               vsc9959_port_qmaxsdu_set(ocelot, port, tc, max_sdu);
        }
 
        ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port);
+
+       ocelot->ops->cut_through_fwd(ocelot);
+
+       mutex_unlock(&ocelot->fwd_domain_lock);
 }
 
 static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
@@ -1704,13 +1759,13 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
                break;
        }
 
+       mutex_lock(&ocelot->tas_lock);
+
        ocelot_rmw_rix(ocelot,
                       QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
                       QSYS_TAG_CONFIG_LINK_SPEED_M,
                       QSYS_TAG_CONFIG, port);
 
-       mutex_lock(&ocelot->tas_lock);
-
        if (ocelot_port->taprio)
                vsc9959_tas_guard_bands_update(ocelot, port);
 
@@ -2770,7 +2825,7 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot)
 {
        struct felix *felix = ocelot_to_felix(ocelot);
        struct dsa_switch *ds = felix->ds;
-       int port, other_port;
+       int tc, port, other_port;
 
        lockdep_assert_held(&ocelot->fwd_domain_lock);
 
@@ -2814,19 +2869,27 @@ static void vsc9959_cut_through_fwd(struct ocelot *ocelot)
                                min_speed = other_ocelot_port->speed;
                }
 
-               /* Enable cut-through forwarding for all traffic classes. */
-               if (ocelot_port->speed == min_speed)
+               /* Enable cut-through forwarding for all traffic classes that
+                * don't have oversized dropping enabled, since this check is
+                * bypassed in cut-through mode.
+                */
+               if (ocelot_port->speed == min_speed) {
                        val = GENMASK(7, 0);
 
+                       for (tc = 0; tc < OCELOT_NUM_TC; tc++)
+                               if (vsc9959_port_qmaxsdu_get(ocelot, port, tc))
+                                       val &= ~BIT(tc);
+               }
+
 set:
                tmp = ocelot_read_rix(ocelot, ANA_CUT_THRU_CFG, port);
                if (tmp == val)
                        continue;
 
                dev_dbg(ocelot->dev,
-                       "port %d fwd mask 0x%lx speed %d min_speed %d, %s cut-through forwarding\n",
+                       "port %d fwd mask 0x%lx speed %d min_speed %d, %s cut-through forwarding on TC mask 0x%x\n",
                        port, mask, ocelot_port->speed, min_speed,
-                       val ? "enabling" : "disabling");
+                       val ? "enabling" : "disabling", val);
 
                ocelot_write_rix(ocelot, val, ANA_CUT_THRU_CFG, port);
        }
index 1d3e778..c181346 100644 (file)
@@ -1889,9 +1889,9 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
        if (!priv)
                return -ENOMEM;
 
-       priv->info = of_device_get_match_data(priv->dev);
        priv->bus = mdiodev->bus;
        priv->dev = &mdiodev->dev;
+       priv->info = of_device_get_match_data(priv->dev);
 
        priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset",
                                                   GPIOD_ASIS);
index 3887ed3..fa62263 100644 (file)
@@ -109,6 +109,7 @@ static void xrs700x_read_port_counters(struct xrs700x *priv, int port)
 {
        struct xrs700x_port *p = &priv->ports[port];
        struct rtnl_link_stats64 stats;
+       unsigned long flags;
        int i;
 
        memset(&stats, 0, sizeof(stats));
@@ -138,9 +139,9 @@ static void xrs700x_read_port_counters(struct xrs700x *priv, int port)
         */
        stats.rx_packets += stats.multicast;
 
-       u64_stats_update_begin(&p->syncp);
+       flags = u64_stats_update_begin_irqsave(&p->syncp);
        p->stats64 = stats;
-       u64_stats_update_end(&p->syncp);
+       u64_stats_update_end_irqrestore(&p->syncp, flags);
 
        mutex_unlock(&p->mib_mutex);
 }
index 8859586..8a0af37 100644 (file)
@@ -94,11 +94,8 @@ static int aq_ndev_close(struct net_device *ndev)
        int err = 0;
 
        err = aq_nic_stop(aq_nic);
-       if (err < 0)
-               goto err_exit;
        aq_nic_deinit(aq_nic, true);
 
-err_exit:
        return err;
 }
 
index f46eefb..96da0ba 100644 (file)
@@ -659,7 +659,6 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
 
        for (i = 0; i < nr_pkts; i++) {
                struct bnxt_sw_tx_bd *tx_buf;
-               bool compl_deferred = false;
                struct sk_buff *skb;
                int j, last;
 
@@ -668,6 +667,8 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
                skb = tx_buf->skb;
                tx_buf->skb = NULL;
 
+               tx_bytes += skb->len;
+
                if (tx_buf->is_push) {
                        tx_buf->is_push = 0;
                        goto next_tx_int;
@@ -688,8 +689,9 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
                }
                if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
                        if (bp->flags & BNXT_FLAG_CHIP_P5) {
+                               /* PTP worker takes ownership of the skb */
                                if (!bnxt_get_tx_ts_p5(bp, skb))
-                                       compl_deferred = true;
+                                       skb = NULL;
                                else
                                        atomic_inc(&bp->ptp_cfg->tx_avail);
                        }
@@ -698,9 +700,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
 next_tx_int:
                cons = NEXT_TX(cons);
 
-               tx_bytes += skb->len;
-               if (!compl_deferred)
-                       dev_kfree_skb_any(skb);
+               dev_kfree_skb_any(skb);
        }
 
        netdev_tx_completed_queue(txq, nr_pkts, tx_bytes);
index 7f3c087..8e31636 100644 (file)
@@ -317,9 +317,9 @@ void bnxt_ptp_cfg_tstamp_filters(struct bnxt *bp)
 
        if (!(bp->fw_cap & BNXT_FW_CAP_RX_ALL_PKT_TS) && (ptp->tstamp_filters &
            (PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE |
-            PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE))) {
+            PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE))) {
                ptp->tstamp_filters &= ~(PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_ENABLE |
-                                        PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE);
+                                        PORT_MAC_CFG_REQ_FLAGS_ALL_RX_TS_CAPTURE_DISABLE);
                netdev_warn(bp->dev, "Unsupported FW for all RX pkts timestamp filter\n");
        }
 
index db1e9d8..89889d8 100644 (file)
@@ -18076,16 +18076,20 @@ static void tg3_shutdown(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
 
+       tg3_reset_task_cancel(tp);
+
        rtnl_lock();
+
        netif_device_detach(dev);
 
        if (netif_running(dev))
                dev_close(dev);
 
-       if (system_state == SYSTEM_POWER_OFF)
-               tg3_power_down(tp);
+       tg3_power_down(tp);
 
        rtnl_unlock();
+
+       pci_disable_device(pdev);
 }
 
 /**
index 66c7d08..a289754 100644 (file)
@@ -5109,6 +5109,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
        if (!(bp->wol & MACB_WOL_ENABLED)) {
                rtnl_lock();
                phylink_stop(bp->phylink);
+               phy_exit(bp->sgmii_phy);
                rtnl_unlock();
                spin_lock_irqsave(&bp->lock, flags);
                macb_reset_hw(bp);
@@ -5198,6 +5199,9 @@ static int __maybe_unused macb_resume(struct device *dev)
        macb_set_rx_mode(netdev);
        macb_restore_features(bp);
        rtnl_lock();
+       if (!device_may_wakeup(&bp->dev->dev))
+               phy_init(bp->sgmii_phy);
+
        phylink_start(bp->phylink);
        rtnl_unlock();
 
index a7f291c..557c591 100644 (file)
@@ -14,6 +14,7 @@
 #include "cudbg_entity.h"
 #include "cudbg_lib.h"
 #include "cudbg_zlib.h"
+#include "cxgb4_tc_mqprio.h"
 
 static const u32 t6_tp_pio_array[][IREG_NUM_ELEM] = {
        {0x7e40, 0x7e44, 0x020, 28}, /* t6_tp_pio_regs_20_to_3b */
@@ -3458,7 +3459,7 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
                        for (i = 0; i < utxq->ntxq; i++)
                                QDESC_GET_TXQ(&utxq->uldtxq[i].q,
                                              cudbg_uld_txq_to_qtype(j),
-                                             out_unlock);
+                                             out_unlock_uld);
                }
        }
 
@@ -3475,7 +3476,7 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
                        for (i = 0; i < urxq->nrxq; i++)
                                QDESC_GET_RXQ(&urxq->uldrxq[i].rspq,
                                              cudbg_uld_rxq_to_qtype(j),
-                                             out_unlock);
+                                             out_unlock_uld);
                }
 
                /* ULD FLQ */
@@ -3487,7 +3488,7 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
                        for (i = 0; i < urxq->nrxq; i++)
                                QDESC_GET_FLQ(&urxq->uldrxq[i].fl,
                                              cudbg_uld_flq_to_qtype(j),
-                                             out_unlock);
+                                             out_unlock_uld);
                }
 
                /* ULD CIQ */
@@ -3500,29 +3501,34 @@ int cudbg_collect_qdesc(struct cudbg_init *pdbg_init,
                        for (i = 0; i < urxq->nciq; i++)
                                QDESC_GET_RXQ(&urxq->uldrxq[base + i].rspq,
                                              cudbg_uld_ciq_to_qtype(j),
-                                             out_unlock);
+                                             out_unlock_uld);
                }
        }
+       mutex_unlock(&uld_mutex);
+
+       if (!padap->tc_mqprio)
+               goto out;
 
+       mutex_lock(&padap->tc_mqprio->mqprio_mutex);
        /* ETHOFLD TXQ */
        if (s->eohw_txq)
                for (i = 0; i < s->eoqsets; i++)
                        QDESC_GET_TXQ(&s->eohw_txq[i].q,
-                                     CUDBG_QTYPE_ETHOFLD_TXQ, out);
+                                     CUDBG_QTYPE_ETHOFLD_TXQ, out_unlock_mqprio);
 
        /* ETHOFLD RXQ and FLQ */
        if (s->eohw_rxq) {
                for (i = 0; i < s->eoqsets; i++)
                        QDESC_GET_RXQ(&s->eohw_rxq[i].rspq,
-                                     CUDBG_QTYPE_ETHOFLD_RXQ, out);
+                                     CUDBG_QTYPE_ETHOFLD_RXQ, out_unlock_mqprio);
 
                for (i = 0; i < s->eoqsets; i++)
                        QDESC_GET_FLQ(&s->eohw_rxq[i].fl,
-                                     CUDBG_QTYPE_ETHOFLD_FLQ, out);
+                                     CUDBG_QTYPE_ETHOFLD_FLQ, out_unlock_mqprio);
        }
 
-out_unlock:
-       mutex_unlock(&uld_mutex);
+out_unlock_mqprio:
+       mutex_unlock(&padap->tc_mqprio->mqprio_mutex);
 
 out:
        qdesc_info->qdesc_entry_size = sizeof(*qdesc_entry);
@@ -3559,6 +3565,10 @@ out_free:
 #undef QDESC_GET
 
        return rc;
+
+out_unlock_uld:
+       mutex_unlock(&uld_mutex);
+       goto out;
 }
 
 int cudbg_collect_flash(struct cudbg_init *pdbg_init,
index 9e6de2f..6dae768 100644 (file)
@@ -1919,7 +1919,7 @@ static void gmac_get_stats64(struct net_device *netdev,
 
        /* Racing with RX NAPI */
        do {
-               start = u64_stats_fetch_begin(&port->rx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
 
                stats->rx_packets = port->stats.rx_packets;
                stats->rx_bytes = port->stats.rx_bytes;
@@ -1931,11 +1931,11 @@ static void gmac_get_stats64(struct net_device *netdev,
                stats->rx_crc_errors = port->stats.rx_crc_errors;
                stats->rx_frame_errors = port->stats.rx_frame_errors;
 
-       } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
 
        /* Racing with MIB and TX completion interrupts */
        do {
-               start = u64_stats_fetch_begin(&port->ir_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
 
                stats->tx_errors = port->stats.tx_errors;
                stats->tx_packets = port->stats.tx_packets;
@@ -1945,15 +1945,15 @@ static void gmac_get_stats64(struct net_device *netdev,
                stats->rx_missed_errors = port->stats.rx_missed_errors;
                stats->rx_fifo_errors = port->stats.rx_fifo_errors;
 
-       } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
 
        /* Racing with hard_start_xmit */
        do {
-               start = u64_stats_fetch_begin(&port->tx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
 
                stats->tx_dropped = port->stats.tx_dropped;
 
-       } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
 
        stats->rx_dropped += stats->rx_missed_errors;
 }
@@ -2031,18 +2031,18 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
        /* Racing with MIB interrupt */
        do {
                p = values;
-               start = u64_stats_fetch_begin(&port->ir_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
 
                for (i = 0; i < RX_STATS_NUM; i++)
                        *p++ = port->hw_stats[i];
 
-       } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
        values = p;
 
        /* Racing with RX NAPI */
        do {
                p = values;
-               start = u64_stats_fetch_begin(&port->rx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
 
                for (i = 0; i < RX_STATUS_NUM; i++)
                        *p++ = port->rx_stats[i];
@@ -2050,13 +2050,13 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
                        *p++ = port->rx_csum_stats[i];
                *p++ = port->rx_napi_exits;
 
-       } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
        values = p;
 
        /* Racing with TX start_xmit */
        do {
                p = values;
-               start = u64_stats_fetch_begin(&port->tx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
 
                for (i = 0; i < TX_MAX_FRAGS; i++) {
                        *values++ = port->tx_frag_stats[i];
@@ -2065,7 +2065,7 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
                *values++ = port->tx_frags_linearized;
                *values++ = port->tx_hw_csummed;
 
-       } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
 }
 
 static int gmac_get_ksettings(struct net_device *netdev,
index a139f2e..e0e8dfd 100644 (file)
@@ -9,7 +9,6 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o $(common-objs)
-fsl-enetc-vf-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_FSL_ENETC_IERB) += fsl-enetc-ierb.o
 fsl-enetc-ierb-y := enetc_ierb.o
index 4470a4a..9f5b921 100644 (file)
@@ -2432,7 +2432,7 @@ int enetc_close(struct net_device *ndev)
        return 0;
 }
 
-static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
+int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
 {
        struct enetc_ndev_priv *priv = netdev_priv(ndev);
        struct tc_mqprio_qopt *mqprio = type_data;
@@ -2486,25 +2486,6 @@ static int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
        return 0;
 }
 
-int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
-                  void *type_data)
-{
-       switch (type) {
-       case TC_SETUP_QDISC_MQPRIO:
-               return enetc_setup_tc_mqprio(ndev, type_data);
-       case TC_SETUP_QDISC_TAPRIO:
-               return enetc_setup_tc_taprio(ndev, type_data);
-       case TC_SETUP_QDISC_CBS:
-               return enetc_setup_tc_cbs(ndev, type_data);
-       case TC_SETUP_QDISC_ETF:
-               return enetc_setup_tc_txtime(ndev, type_data);
-       case TC_SETUP_BLOCK:
-               return enetc_setup_tc_psfp(ndev, type_data);
-       default:
-               return -EOPNOTSUPP;
-       }
-}
-
 static int enetc_setup_xdp_prog(struct net_device *dev, struct bpf_prog *prog,
                                struct netlink_ext_ack *extack)
 {
@@ -2600,29 +2581,6 @@ static int enetc_set_rss(struct net_device *ndev, int en)
        return 0;
 }
 
-static int enetc_set_psfp(struct net_device *ndev, int en)
-{
-       struct enetc_ndev_priv *priv = netdev_priv(ndev);
-       int err;
-
-       if (en) {
-               err = enetc_psfp_enable(priv);
-               if (err)
-                       return err;
-
-               priv->active_offloads |= ENETC_F_QCI;
-               return 0;
-       }
-
-       err = enetc_psfp_disable(priv);
-       if (err)
-               return err;
-
-       priv->active_offloads &= ~ENETC_F_QCI;
-
-       return 0;
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
        struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -2641,11 +2599,9 @@ static void enetc_enable_txvlan(struct net_device *ndev, bool en)
                enetc_bdr_enable_txvlan(&priv->si->hw, i, en);
 }
 
-int enetc_set_features(struct net_device *ndev,
-                      netdev_features_t features)
+void enetc_set_features(struct net_device *ndev, netdev_features_t features)
 {
        netdev_features_t changed = ndev->features ^ features;
-       int err = 0;
 
        if (changed & NETIF_F_RXHASH)
                enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
@@ -2657,11 +2613,6 @@ int enetc_set_features(struct net_device *ndev,
        if (changed & NETIF_F_HW_VLAN_CTAG_TX)
                enetc_enable_txvlan(ndev,
                                    !!(features & NETIF_F_HW_VLAN_CTAG_TX));
-
-       if (changed & NETIF_F_HW_TC)
-               err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
-
-       return err;
 }
 
 #ifdef CONFIG_FSL_ENETC_PTP_CLOCK
index 29922c2..2cfe694 100644 (file)
@@ -393,11 +393,9 @@ void enetc_start(struct net_device *ndev);
 void enetc_stop(struct net_device *ndev);
 netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev);
 struct net_device_stats *enetc_get_stats(struct net_device *ndev);
-int enetc_set_features(struct net_device *ndev,
-                      netdev_features_t features);
+void enetc_set_features(struct net_device *ndev, netdev_features_t features);
 int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
-int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
-                  void *type_data);
+int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data);
 int enetc_setup_bpf(struct net_device *dev, struct netdev_bpf *xdp);
 int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
                   struct xdp_frame **frames, u32 flags);
@@ -465,6 +463,7 @@ int enetc_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 int enetc_setup_tc_psfp(struct net_device *ndev, void *type_data);
 int enetc_psfp_init(struct enetc_ndev_priv *priv);
 int enetc_psfp_clean(struct enetc_ndev_priv *priv);
+int enetc_set_psfp(struct net_device *ndev, bool en);
 
 static inline void enetc_get_max_cap(struct enetc_ndev_priv *priv)
 {
@@ -540,4 +539,9 @@ static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv)
 {
        return 0;
 }
+
+static inline int enetc_set_psfp(struct net_device *ndev, bool en)
+{
+       return 0;
+}
 #endif
index c4a0e83..bb77502 100644 (file)
@@ -709,6 +709,13 @@ static int enetc_pf_set_features(struct net_device *ndev,
 {
        netdev_features_t changed = ndev->features ^ features;
        struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       int err;
+
+       if (changed & NETIF_F_HW_TC) {
+               err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
+               if (err)
+                       return err;
+       }
 
        if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
                struct enetc_pf *pf = enetc_si_priv(priv->si);
@@ -722,7 +729,28 @@ static int enetc_pf_set_features(struct net_device *ndev,
        if (changed & NETIF_F_LOOPBACK)
                enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
 
-       return enetc_set_features(ndev, features);
+       enetc_set_features(ndev, features);
+
+       return 0;
+}
+
+static int enetc_pf_setup_tc(struct net_device *ndev, enum tc_setup_type type,
+                            void *type_data)
+{
+       switch (type) {
+       case TC_SETUP_QDISC_MQPRIO:
+               return enetc_setup_tc_mqprio(ndev, type_data);
+       case TC_SETUP_QDISC_TAPRIO:
+               return enetc_setup_tc_taprio(ndev, type_data);
+       case TC_SETUP_QDISC_CBS:
+               return enetc_setup_tc_cbs(ndev, type_data);
+       case TC_SETUP_QDISC_ETF:
+               return enetc_setup_tc_txtime(ndev, type_data);
+       case TC_SETUP_BLOCK:
+               return enetc_setup_tc_psfp(ndev, type_data);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 static const struct net_device_ops enetc_ndev_ops = {
@@ -739,7 +767,7 @@ static const struct net_device_ops enetc_ndev_ops = {
        .ndo_set_vf_spoofchk    = enetc_pf_set_vf_spoofchk,
        .ndo_set_features       = enetc_pf_set_features,
        .ndo_eth_ioctl          = enetc_ioctl,
-       .ndo_setup_tc           = enetc_setup_tc,
+       .ndo_setup_tc           = enetc_pf_setup_tc,
        .ndo_bpf                = enetc_setup_bpf,
        .ndo_xdp_xmit           = enetc_xdp_xmit,
 };
index 582a663..f8a2f02 100644 (file)
@@ -1517,6 +1517,29 @@ int enetc_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
        }
 }
 
+int enetc_set_psfp(struct net_device *ndev, bool en)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       int err;
+
+       if (en) {
+               err = enetc_psfp_enable(priv);
+               if (err)
+                       return err;
+
+               priv->active_offloads |= ENETC_F_QCI;
+               return 0;
+       }
+
+       err = enetc_psfp_disable(priv);
+       if (err)
+               return err;
+
+       priv->active_offloads &= ~ENETC_F_QCI;
+
+       return 0;
+}
+
 int enetc_psfp_init(struct enetc_ndev_priv *priv)
 {
        if (epsfp.psfp_sfi_bitmap)
index 1792430..dfcaac3 100644 (file)
@@ -88,7 +88,20 @@ static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)
 static int enetc_vf_set_features(struct net_device *ndev,
                                 netdev_features_t features)
 {
-       return enetc_set_features(ndev, features);
+       enetc_set_features(ndev, features);
+
+       return 0;
+}
+
+static int enetc_vf_setup_tc(struct net_device *ndev, enum tc_setup_type type,
+                            void *type_data)
+{
+       switch (type) {
+       case TC_SETUP_QDISC_MQPRIO:
+               return enetc_setup_tc_mqprio(ndev, type_data);
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
 /* Probing/ Init */
@@ -100,7 +113,7 @@ static const struct net_device_ops enetc_ndev_ops = {
        .ndo_set_mac_address    = enetc_vf_set_mac_addr,
        .ndo_set_features       = enetc_vf_set_features,
        .ndo_eth_ioctl          = enetc_ioctl,
-       .ndo_setup_tc           = enetc_setup_tc,
+       .ndo_setup_tc           = enetc_vf_setup_tc,
 };
 
 static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
index 0cebe4b..a5fed00 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clocksource.h>
 #include <linux/net_tstamp.h>
+#include <linux/pm_qos.h>
 #include <linux/ptp_clock_kernel.h>
 #include <linux/timecounter.h>
 
@@ -498,6 +499,9 @@ struct bufdesc_ex {
 /* i.MX8MQ SoC integration mix wakeup interrupt signal into "int2" interrupt line. */
 #define FEC_QUIRK_WAKEUP_FROM_INT2     (1 << 22)
 
+/* i.MX6Q adds pm_qos support */
+#define FEC_QUIRK_HAS_PMQOS                    BIT(23)
+
 struct bufdesc_prop {
        int qid;
        /* Address of Rx and Tx buffers */
@@ -608,6 +612,7 @@ struct fec_enet_private {
        struct delayed_work time_keep;
        struct regulator *reg_phy;
        struct fec_stop_mode_gpr stop_gpr;
+       struct pm_qos_request pm_qos_req;
 
        unsigned int tx_align;
        unsigned int rx_align;
@@ -634,13 +639,6 @@ struct fec_enet_private {
        int pps_enable;
        unsigned int next_counter;
 
-       struct {
-               struct timespec64 ts_phc;
-               u64 ns_sys;
-               u32 at_corr;
-               u8 at_inc_corr;
-       } ptp_saved_state;
-
        u64 ethtool_stats[];
 };
 
@@ -651,8 +649,5 @@ void fec_ptp_disable_hwts(struct net_device *ndev);
 int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
 int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
 
-void fec_ptp_save_state(struct fec_enet_private *fep);
-int fec_ptp_restore_state(struct fec_enet_private *fep);
-
 /****************************************************************************/
 #endif /* FEC_H */
index b0d60f8..92c55e1 100644 (file)
@@ -111,7 +111,8 @@ static const struct fec_devinfo fec_imx6q_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_ERR006358 |
-                 FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII,
+                 FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII |
+                 FEC_QUIRK_HAS_PMQOS,
 };
 
 static const struct fec_devinfo fec_mvf600_info = {
@@ -285,11 +286,8 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define FEC_MMFR_TA            (2 << 16)
 #define FEC_MMFR_DATA(v)       (v & 0xffff)
 /* FEC ECR bits definition */
-#define FEC_ECR_RESET   BIT(0)
-#define FEC_ECR_ETHEREN BIT(1)
-#define FEC_ECR_MAGICEN BIT(2)
-#define FEC_ECR_SLEEP   BIT(3)
-#define FEC_ECR_EN1588  BIT(4)
+#define FEC_ECR_MAGICEN                (1 << 2)
+#define FEC_ECR_SLEEP          (1 << 3)
 
 #define FEC_MII_TIMEOUT                30000 /* us */
 
@@ -985,9 +983,6 @@ fec_restart(struct net_device *ndev)
        u32 temp_mac[2];
        u32 rcntl = OPT_FRAME_SIZE | 0x04;
        u32 ecntl = 0x2; /* ETHEREN */
-       struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
-
-       fec_ptp_save_state(fep);
 
        /* Whack a reset.  We should wait for this.
         * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
@@ -1141,7 +1136,7 @@ fec_restart(struct net_device *ndev)
        }
 
        if (fep->bufdesc_ex)
-               ecntl |= FEC_ECR_EN1588;
+               ecntl |= (1 << 4);
 
        if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&
            fep->rgmii_txc_dly)
@@ -1162,14 +1157,6 @@ fec_restart(struct net_device *ndev)
        if (fep->bufdesc_ex)
                fec_ptp_start_cyclecounter(ndev);
 
-       /* Restart PPS if needed */
-       if (fep->pps_enable) {
-               /* Clear flag so fec_ptp_enable_pps() doesn't return immediately */
-               fep->pps_enable = 0;
-               fec_ptp_restore_state(fep);
-               fep->ptp_caps.enable(&fep->ptp_caps, &ptp_rq, 1);
-       }
-
        /* Enable interrupts we wish to service */
        if (fep->link)
                writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1220,8 +1207,6 @@ fec_stop(struct net_device *ndev)
        struct fec_enet_private *fep = netdev_priv(ndev);
        u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
        u32 val;
-       struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
-       u32 ecntl = 0;
 
        /* We cannot expect a graceful transmit stop without link !!! */
        if (fep->link) {
@@ -1231,8 +1216,6 @@ fec_stop(struct net_device *ndev)
                        netdev_err(ndev, "Graceful transmit stop did not complete!\n");
        }
 
-       fec_ptp_save_state(fep);
-
        /* Whack a reset.  We should wait for this.
         * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
         * instead of reset MAC itself.
@@ -1252,28 +1235,12 @@ fec_stop(struct net_device *ndev)
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
        writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 
-       if (fep->bufdesc_ex)
-               ecntl |= FEC_ECR_EN1588;
-
        /* We have to keep ENET enabled to have MII interrupt stay working */
        if (fep->quirks & FEC_QUIRK_ENET_MAC &&
                !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
-               ecntl |= FEC_ECR_ETHEREN;
+               writel(2, fep->hwp + FEC_ECNTRL);
                writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
        }
-
-       writel(ecntl, fep->hwp + FEC_ECNTRL);
-
-       if (fep->bufdesc_ex)
-               fec_ptp_start_cyclecounter(ndev);
-
-       /* Restart PPS if needed */
-       if (fep->pps_enable) {
-               /* Clear flag so fec_ptp_enable_pps() doesn't return immediately */
-               fep->pps_enable = 0;
-               fec_ptp_restore_state(fep);
-               fep->ptp_caps.enable(&fep->ptp_caps, &ptp_rq, 1);
-       }
 }
 
 
@@ -3244,6 +3211,9 @@ fec_enet_open(struct net_device *ndev)
        if (fep->quirks & FEC_QUIRK_ERR006687)
                imx6q_cpuidle_fec_irqs_used();
 
+       if (fep->quirks & FEC_QUIRK_HAS_PMQOS)
+               cpu_latency_qos_add_request(&fep->pm_qos_req, 0);
+
        napi_enable(&fep->napi);
        phy_start(ndev->phydev);
        netif_tx_start_all_queues(ndev);
@@ -3285,6 +3255,9 @@ fec_enet_close(struct net_device *ndev)
        fec_enet_update_ethtool_stats(ndev);
 
        fec_enet_clk_enable(ndev, false);
+       if (fep->quirks & FEC_QUIRK_HAS_PMQOS)
+               cpu_latency_qos_remove_request(&fep->pm_qos_req);
+
        pinctrl_pm_select_sleep_state(&fep->pdev->dev);
        pm_runtime_mark_last_busy(&fep->pdev->dev);
        pm_runtime_put_autosuspend(&fep->pdev->dev);
index c74d04f..3dc3c0b 100644 (file)
@@ -633,36 +633,7 @@ void fec_ptp_stop(struct platform_device *pdev)
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct fec_enet_private *fep = netdev_priv(ndev);
 
-       if (fep->pps_enable)
-               fec_ptp_enable_pps(fep, 0);
-
        cancel_delayed_work_sync(&fep->time_keep);
        if (fep->ptp_clock)
                ptp_clock_unregister(fep->ptp_clock);
 }
-
-void fec_ptp_save_state(struct fec_enet_private *fep)
-{
-       u32 atime_inc_corr;
-
-       fec_ptp_gettime(&fep->ptp_caps, &fep->ptp_saved_state.ts_phc);
-       fep->ptp_saved_state.ns_sys = ktime_get_ns();
-
-       fep->ptp_saved_state.at_corr = readl(fep->hwp + FEC_ATIME_CORR);
-       atime_inc_corr = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_CORR_MASK;
-       fep->ptp_saved_state.at_inc_corr = (u8)(atime_inc_corr >> FEC_T_INC_CORR_OFFSET);
-}
-
-int fec_ptp_restore_state(struct fec_enet_private *fep)
-{
-       u32 atime_inc = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
-       u64 ns_sys;
-
-       writel(fep->ptp_saved_state.at_corr, fep->hwp + FEC_ATIME_CORR);
-       atime_inc |= ((u32)fep->ptp_saved_state.at_inc_corr) << FEC_T_INC_CORR_OFFSET;
-       writel(atime_inc, fep->hwp + FEC_ATIME_INC);
-
-       ns_sys = ktime_get_ns() - fep->ptp_saved_state.ns_sys;
-       timespec64_add_ns(&fep->ptp_saved_state.ts_phc, ns_sys);
-       return fec_ptp_settime(&fep->ptp_caps, &fep->ptp_saved_state.ts_phc);
-}
index 53b7e95..671f511 100644 (file)
@@ -206,9 +206,9 @@ struct funeth_rxq {
 
 #define FUN_QSTAT_READ(q, seq, stats_copy) \
        do { \
-               seq = u64_stats_fetch_begin(&(q)->syncp); \
+               seq = u64_stats_fetch_begin_irq(&(q)->syncp); \
                stats_copy = (q)->stats; \
-       } while (u64_stats_fetch_retry(&(q)->syncp, (seq)))
+       } while (u64_stats_fetch_retry_irq(&(q)->syncp, (seq)))
 
 #define FUN_INT_NAME_LEN (IFNAMSIZ + 16)
 
index 50b3849..7b9a2d9 100644 (file)
@@ -177,14 +177,14 @@ gve_get_ethtool_stats(struct net_device *netdev,
                                struct gve_rx_ring *rx = &priv->rx[ring];
 
                                start =
-                                 u64_stats_fetch_begin(&priv->rx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
                                tmp_rx_pkts = rx->rpackets;
                                tmp_rx_bytes = rx->rbytes;
                                tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
                                tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
                                tmp_rx_desc_err_dropped_pkt =
                                        rx->rx_desc_err_dropped_pkt;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
                                                       start));
                        rx_pkts += tmp_rx_pkts;
                        rx_bytes += tmp_rx_bytes;
@@ -198,10 +198,10 @@ gve_get_ethtool_stats(struct net_device *netdev,
                if (priv->tx) {
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->tx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
                                tmp_tx_pkts = priv->tx[ring].pkt_done;
                                tmp_tx_bytes = priv->tx[ring].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
                                                       start));
                        tx_pkts += tmp_tx_pkts;
                        tx_bytes += tmp_tx_bytes;
@@ -259,13 +259,13 @@ gve_get_ethtool_stats(struct net_device *netdev,
                        data[i++] = rx->fill_cnt - rx->cnt;
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->rx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
                                tmp_rx_bytes = rx->rbytes;
                                tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
                                tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
                                tmp_rx_desc_err_dropped_pkt =
                                        rx->rx_desc_err_dropped_pkt;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
                                                       start));
                        data[i++] = tmp_rx_bytes;
                        data[i++] = rx->rx_cont_packet_cnt;
@@ -331,9 +331,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
                        }
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->tx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
                                tmp_tx_bytes = tx->bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
                                                       start));
                        data[i++] = tmp_tx_bytes;
                        data[i++] = tx->wake_queue;
index 6cafee5..044db3e 100644 (file)
@@ -51,10 +51,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->rx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
                                packets = priv->rx[ring].rpackets;
                                bytes = priv->rx[ring].rbytes;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
                                                       start));
                        s->rx_packets += packets;
                        s->rx_bytes += bytes;
@@ -64,10 +64,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->tx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
                                packets = priv->tx[ring].pkt_done;
                                bytes = priv->tx[ring].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
                                                       start));
                        s->tx_packets += packets;
                        s->tx_bytes += bytes;
@@ -1274,9 +1274,9 @@ void gve_handle_report_stats(struct gve_priv *priv)
                        }
 
                        do {
-                               start = u64_stats_fetch_begin(&priv->tx[idx].statss);
+                               start = u64_stats_fetch_begin_irq(&priv->tx[idx].statss);
                                tx_bytes = priv->tx[idx].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[idx].statss, start));
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[idx].statss, start));
                        stats[stats_idx++] = (struct stats) {
                                .stat_name = cpu_to_be32(TX_WAKE_CNT),
                                .value = cpu_to_be64(priv->tx[idx].wake_queue),
index 8c93962..2e6461b 100644 (file)
@@ -157,7 +157,7 @@ static int gve_alloc_page_dqo(struct gve_priv *priv,
        int err;
 
        err = gve_alloc_page(priv, &priv->pdev->dev, &buf_state->page_info.page,
-                            &buf_state->addr, DMA_FROM_DEVICE, GFP_KERNEL);
+                            &buf_state->addr, DMA_FROM_DEVICE, GFP_ATOMIC);
        if (err)
                return err;
 
index a866bea..e5828a6 100644 (file)
@@ -74,14 +74,14 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
        unsigned int start;
 
        do {
-               start = u64_stats_fetch_begin(&rxq_stats->syncp);
+               start = u64_stats_fetch_begin_irq(&rxq_stats->syncp);
                stats->pkts = rxq_stats->pkts;
                stats->bytes = rxq_stats->bytes;
                stats->errors = rxq_stats->csum_errors +
                                rxq_stats->other_errors;
                stats->csum_errors = rxq_stats->csum_errors;
                stats->other_errors = rxq_stats->other_errors;
-       } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&rxq_stats->syncp, start));
 }
 
 /**
index 5051cdf..3b6c7b5 100644 (file)
@@ -99,14 +99,14 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
        unsigned int start;
 
        do {
-               start = u64_stats_fetch_begin(&txq_stats->syncp);
+               start = u64_stats_fetch_begin_irq(&txq_stats->syncp);
                stats->pkts    = txq_stats->pkts;
                stats->bytes   = txq_stats->bytes;
                stats->tx_busy = txq_stats->tx_busy;
                stats->tx_wake = txq_stats->tx_wake;
                stats->tx_dropped = txq_stats->tx_dropped;
                stats->big_frags_pkts = txq_stats->big_frags_pkts;
-       } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&txq_stats->syncp, start));
 }
 
 /**
index ea2bb01..10d7a98 100644 (file)
@@ -177,6 +177,10 @@ void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset)
                        "Cannot locate client instance close routine\n");
                return;
        }
+       if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
+               dev_dbg(&pf->pdev->dev, "Client is not open, abort close\n");
+               return;
+       }
        cdev->client->ops->close(&cdev->lan_info, cdev->client, reset);
        clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
        i40e_client_release_qvlist(&cdev->lan_info);
@@ -429,7 +433,6 @@ void i40e_client_subtask(struct i40e_pf *pf)
                                /* Remove failed client instance */
                                clear_bit(__I40E_CLIENT_INSTANCE_OPENED,
                                          &cdev->state);
-                               i40e_client_del_instance(pf);
                                return;
                        }
                }
index 9f1d5de..e3d9804 100644 (file)
@@ -5909,6 +5909,26 @@ static int i40e_get_link_speed(struct i40e_vsi *vsi)
 }
 
 /**
+ * i40e_bw_bytes_to_mbits - Convert max_tx_rate from bytes to mbits
+ * @vsi: Pointer to vsi structure
+ * @max_tx_rate: max TX rate in bytes to be converted into Mbits
+ *
+ * Helper function to convert units before send to set BW limit
+ **/
+static u64 i40e_bw_bytes_to_mbits(struct i40e_vsi *vsi, u64 max_tx_rate)
+{
+       if (max_tx_rate < I40E_BW_MBPS_DIVISOR) {
+               dev_warn(&vsi->back->pdev->dev,
+                        "Setting max tx rate to minimum usable value of 50Mbps.\n");
+               max_tx_rate = I40E_BW_CREDIT_DIVISOR;
+       } else {
+               do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
+       }
+
+       return max_tx_rate;
+}
+
+/**
  * i40e_set_bw_limit - setup BW limit for Tx traffic based on max_tx_rate
  * @vsi: VSI to be configured
  * @seid: seid of the channel/VSI
@@ -5930,10 +5950,10 @@ int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate)
                        max_tx_rate, seid);
                return -EINVAL;
        }
-       if (max_tx_rate && max_tx_rate < 50) {
+       if (max_tx_rate && max_tx_rate < I40E_BW_CREDIT_DIVISOR) {
                dev_warn(&pf->pdev->dev,
                         "Setting max tx rate to minimum usable value of 50Mbps.\n");
-               max_tx_rate = 50;
+               max_tx_rate = I40E_BW_CREDIT_DIVISOR;
        }
 
        /* Tx rate credits are in values of 50Mbps, 0 is disabled */
@@ -6659,6 +6679,9 @@ static int i40e_configure_queue_channels(struct i40e_vsi *vsi)
                        vsi->tc_seid_map[i] = ch->seid;
                }
        }
+
+       /* reset to reconfigure TX queue contexts */
+       i40e_do_reset(vsi->back, I40E_PF_RESET_FLAG, true);
        return ret;
 
 err_free:
@@ -8221,9 +8244,9 @@ config_tc:
 
        if (i40e_is_tc_mqprio_enabled(pf)) {
                if (vsi->mqprio_qopt.max_rate[0]) {
-                       u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
+                       u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
+                                                 vsi->mqprio_qopt.max_rate[0]);
 
-                       do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
                        ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
                        if (!ret) {
                                u64 credits = max_tx_rate;
@@ -10968,10 +10991,10 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
        }
 
        if (vsi->mqprio_qopt.max_rate[0]) {
-               u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
+               u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
+                                                 vsi->mqprio_qopt.max_rate[0]);
                u64 credits = 0;
 
-               do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
                ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
                if (ret)
                        goto end_unlock;
index d422616..69e67eb 100644 (file)
@@ -3688,7 +3688,8 @@ u16 i40e_lan_select_queue(struct net_device *netdev,
        u8 prio;
 
        /* is DCB enabled at all? */
-       if (vsi->tc_config.numtc == 1)
+       if (vsi->tc_config.numtc == 1 ||
+           i40e_is_tc_mqprio_enabled(vsi->back))
                return netdev_pick_tx(netdev, skb, sb_dev);
 
        prio = skb->priority;
index 4f184c5..7e9f6a6 100644 (file)
@@ -2039,6 +2039,25 @@ static void i40e_del_qch(struct i40e_vf *vf)
 }
 
 /**
+ * i40e_vc_get_max_frame_size
+ * @vf: pointer to the VF
+ *
+ * Max frame size is determined based on the current port's max frame size and
+ * whether a port VLAN is configured on this VF. The VF is not aware whether
+ * it's in a port VLAN so the PF needs to account for this in max frame size
+ * checks and sending the max frame size to the VF.
+ **/
+static u16 i40e_vc_get_max_frame_size(struct i40e_vf *vf)
+{
+       u16 max_frame_size = vf->pf->hw.phy.link_info.max_frame_size;
+
+       if (vf->port_vlan_id)
+               max_frame_size -= VLAN_HLEN;
+
+       return max_frame_size;
+}
+
+/**
  * i40e_vc_get_vf_resources_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -2139,6 +2158,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
        vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf;
        vfres->rss_key_size = I40E_HKEY_ARRAY_SIZE;
        vfres->rss_lut_size = I40E_VF_HLUT_ARRAY_SIZE;
+       vfres->max_mtu = i40e_vc_get_max_frame_size(vf);
 
        if (vf->lan_vsi_idx) {
                vfres->vsi_res[0].vsi_id = vf->lan_vsi_id;
index f39440a..0c89f16 100644 (file)
@@ -1077,7 +1077,6 @@ static int iavf_set_mac(struct net_device *netdev, void *p)
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        struct sockaddr *addr = p;
-       bool handle_mac = iavf_is_mac_set_handled(netdev, addr->sa_data);
        int ret;
 
        if (!is_valid_ether_addr(addr->sa_data))
@@ -1094,10 +1093,9 @@ static int iavf_set_mac(struct net_device *netdev, void *p)
                return 0;
        }
 
-       if (handle_mac)
-               goto done;
-
-       ret = wait_event_interruptible_timeout(adapter->vc_waitqueue, false, msecs_to_jiffies(2500));
+       ret = wait_event_interruptible_timeout(adapter->vc_waitqueue,
+                                              iavf_is_mac_set_handled(netdev, addr->sa_data),
+                                              msecs_to_jiffies(2500));
 
        /* If ret < 0 then it means wait was interrupted.
         * If ret == 0 then it means we got a timeout.
@@ -1111,7 +1109,6 @@ static int iavf_set_mac(struct net_device *netdev, void *p)
        if (!ret)
                return -EAGAIN;
 
-done:
        if (!ether_addr_equal(netdev->dev_addr, addr->sa_data))
                return -EACCES;
 
@@ -2877,6 +2874,11 @@ static void iavf_reset_task(struct work_struct *work)
        int i = 0, err;
        bool running;
 
+       /* Detach interface to avoid subsequent NDO callbacks */
+       rtnl_lock();
+       netif_device_detach(netdev);
+       rtnl_unlock();
+
        /* When device is being removed it doesn't make sense to run the reset
         * task, just return in such a case.
         */
@@ -2884,7 +2886,7 @@ static void iavf_reset_task(struct work_struct *work)
                if (adapter->state != __IAVF_REMOVE)
                        queue_work(iavf_wq, &adapter->reset_task);
 
-               return;
+               goto reset_finish;
        }
 
        while (!mutex_trylock(&adapter->client_lock))
@@ -2954,7 +2956,6 @@ continue_reset:
 
        if (running) {
                netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
                adapter->link_up = false;
                iavf_napi_disable_all(adapter);
        }
@@ -3084,7 +3085,7 @@ continue_reset:
        mutex_unlock(&adapter->client_lock);
        mutex_unlock(&adapter->crit_lock);
 
-       return;
+       goto reset_finish;
 reset_err:
        if (running) {
                set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
@@ -3095,6 +3096,10 @@ reset_err:
        mutex_unlock(&adapter->client_lock);
        mutex_unlock(&adapter->crit_lock);
        dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
+reset_finish:
+       rtnl_lock();
+       netif_device_attach(netdev);
+       rtnl_unlock();
 }
 
 /**
index 06d1879..18b6a70 100644 (file)
@@ -114,8 +114,11 @@ u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
 {
        u32 head, tail;
 
+       /* underlying hardware might not allow access and/or always return
+        * 0 for the head/tail registers so just use the cached values
+        */
        head = ring->next_to_clean;
-       tail = readl(ring->tail);
+       tail = ring->next_to_use;
 
        if (head != tail)
                return (head < tail) ?
@@ -1390,7 +1393,7 @@ static struct sk_buff *iavf_build_skb(struct iavf_ring *rx_ring,
 #endif
        struct sk_buff *skb;
 
-       if (!rx_buffer)
+       if (!rx_buffer || !size)
                return NULL;
        /* prefetch first cache line of first page */
        va = page_address(rx_buffer->page) + rx_buffer->page_offset;
@@ -1548,7 +1551,7 @@ static int iavf_clean_rx_irq(struct iavf_ring *rx_ring, int budget)
                /* exit if we failed to retrieve a buffer */
                if (!skb) {
                        rx_ring->rx_stats.alloc_buff_failed++;
-                       if (rx_buffer)
+                       if (rx_buffer && size)
                                rx_buffer->pagecnt_bias++;
                        break;
                }
index 15ee85d..5a9e656 100644 (file)
@@ -269,11 +269,14 @@ int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter)
 void iavf_configure_queues(struct iavf_adapter *adapter)
 {
        struct virtchnl_vsi_queue_config_info *vqci;
-       struct virtchnl_queue_pair_info *vqpi;
+       int i, max_frame = adapter->vf_res->max_mtu;
        int pairs = adapter->num_active_queues;
-       int i, max_frame = IAVF_MAX_RXBUFFER;
+       struct virtchnl_queue_pair_info *vqpi;
        size_t len;
 
+       if (max_frame > IAVF_MAX_RXBUFFER || !max_frame)
+               max_frame = IAVF_MAX_RXBUFFER;
+
        if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
                /* bail because we already have a command pending */
                dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
index 136d791..1e32438 100644 (file)
@@ -7,18 +7,6 @@
 #include "ice_dcb_lib.h"
 #include "ice_sriov.h"
 
-static bool ice_alloc_rx_buf_zc(struct ice_rx_ring *rx_ring)
-{
-       rx_ring->xdp_buf = kcalloc(rx_ring->count, sizeof(*rx_ring->xdp_buf), GFP_KERNEL);
-       return !!rx_ring->xdp_buf;
-}
-
-static bool ice_alloc_rx_buf(struct ice_rx_ring *rx_ring)
-{
-       rx_ring->rx_buf = kcalloc(rx_ring->count, sizeof(*rx_ring->rx_buf), GFP_KERNEL);
-       return !!rx_ring->rx_buf;
-}
-
 /**
  * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI
  * @qs_cfg: gathered variables needed for PF->VSI queues assignment
@@ -519,11 +507,8 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
                        xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
                                         ring->q_index, ring->q_vector->napi.napi_id);
 
-               kfree(ring->rx_buf);
                ring->xsk_pool = ice_xsk_pool(ring);
                if (ring->xsk_pool) {
-                       if (!ice_alloc_rx_buf_zc(ring))
-                               return -ENOMEM;
                        xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
 
                        ring->rx_buf_len =
@@ -538,8 +523,6 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
                        dev_info(dev, "Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n",
                                 ring->q_index);
                } else {
-                       if (!ice_alloc_rx_buf(ring))
-                               return -ENOMEM;
                        if (!xdp_rxq_info_is_reg(&ring->xdp_rxq))
                                /* coverity[check_return] */
                                xdp_rxq_info_reg(&ring->xdp_rxq,
index 0c4ec92..58d483e 100644 (file)
@@ -914,7 +914,7 @@ static void ice_set_dflt_vsi_ctx(struct ice_hw *hw, struct ice_vsi_ctx *ctxt)
  */
 static int ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
 {
-       u16 offset = 0, qmap = 0, tx_count = 0, pow = 0;
+       u16 offset = 0, qmap = 0, tx_count = 0, rx_count = 0, pow = 0;
        u16 num_txq_per_tc, num_rxq_per_tc;
        u16 qcount_tx = vsi->alloc_txq;
        u16 qcount_rx = vsi->alloc_rxq;
@@ -981,23 +981,25 @@ static int ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
         * at least 1)
         */
        if (offset)
-               vsi->num_rxq = offset;
+               rx_count = offset;
        else
-               vsi->num_rxq = num_rxq_per_tc;
+               rx_count = num_rxq_per_tc;
 
-       if (vsi->num_rxq > vsi->alloc_rxq) {
+       if (rx_count > vsi->alloc_rxq) {
                dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Rx queues (%u), than were allocated (%u)!\n",
-                       vsi->num_rxq, vsi->alloc_rxq);
+                       rx_count, vsi->alloc_rxq);
                return -EINVAL;
        }
 
-       vsi->num_txq = tx_count;
-       if (vsi->num_txq > vsi->alloc_txq) {
+       if (tx_count > vsi->alloc_txq) {
                dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Tx queues (%u), than were allocated (%u)!\n",
-                       vsi->num_txq, vsi->alloc_txq);
+                       tx_count, vsi->alloc_txq);
                return -EINVAL;
        }
 
+       vsi->num_txq = tx_count;
+       vsi->num_rxq = rx_count;
+
        if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
                dev_dbg(ice_pf_to_dev(vsi->back), "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n");
                /* since there is a chance that num_rxq could have been changed
@@ -3490,6 +3492,7 @@ ice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt,
        u16 pow, offset = 0, qcount_tx = 0, qcount_rx = 0, qmap;
        u16 tc0_offset = vsi->mqprio_qopt.qopt.offset[0];
        int tc0_qcount = vsi->mqprio_qopt.qopt.count[0];
+       u16 new_txq, new_rxq;
        u8 netdev_tc = 0;
        int i;
 
@@ -3530,21 +3533,24 @@ ice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt,
                }
        }
 
-       /* Set actual Tx/Rx queue pairs */
-       vsi->num_txq = offset + qcount_tx;
-       if (vsi->num_txq > vsi->alloc_txq) {
+       new_txq = offset + qcount_tx;
+       if (new_txq > vsi->alloc_txq) {
                dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Tx queues (%u), than were allocated (%u)!\n",
-                       vsi->num_txq, vsi->alloc_txq);
+                       new_txq, vsi->alloc_txq);
                return -EINVAL;
        }
 
-       vsi->num_rxq = offset + qcount_rx;
-       if (vsi->num_rxq > vsi->alloc_rxq) {
+       new_rxq = offset + qcount_rx;
+       if (new_rxq > vsi->alloc_rxq) {
                dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Rx queues (%u), than were allocated (%u)!\n",
-                       vsi->num_rxq, vsi->alloc_rxq);
+                       new_rxq, vsi->alloc_rxq);
                return -EINVAL;
        }
 
+       /* Set actual Tx/Rx queue pairs */
+       vsi->num_txq = new_txq;
+       vsi->num_rxq = new_rxq;
+
        /* Setup queue TC[0].qmap for given VSI context */
        ctxt->info.tc_mapping[0] = cpu_to_le16(qmap);
        ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
@@ -3576,6 +3582,7 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
 {
        u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
        struct ice_pf *pf = vsi->back;
+       struct ice_tc_cfg old_tc_cfg;
        struct ice_vsi_ctx *ctx;
        struct device *dev;
        int i, ret = 0;
@@ -3600,6 +3607,7 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
                        max_txqs[i] = vsi->num_txq;
        }
 
+       memcpy(&old_tc_cfg, &vsi->tc_cfg, sizeof(old_tc_cfg));
        vsi->tc_cfg.ena_tc = ena_tc;
        vsi->tc_cfg.numtc = num_tc;
 
@@ -3616,8 +3624,10 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
        else
                ret = ice_vsi_setup_q_map(vsi, ctx);
 
-       if (ret)
+       if (ret) {
+               memcpy(&vsi->tc_cfg, &old_tc_cfg, sizeof(vsi->tc_cfg));
                goto out;
+       }
 
        /* must to indicate which section of VSI context are being modified */
        ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
index 173fe6c..e109cb9 100644 (file)
@@ -2399,8 +2399,6 @@ int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset)
                return -EBUSY;
        }
 
-       ice_unplug_aux_dev(pf);
-
        switch (reset) {
        case ICE_RESET_PFR:
                set_bit(ICE_PFR_REQ, pf->state);
@@ -2898,10 +2896,18 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
                        if (xdp_ring_err)
                                NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Tx resources failed");
                }
+               /* reallocate Rx queues that are used for zero-copy */
+               xdp_ring_err = ice_realloc_zc_buf(vsi, true);
+               if (xdp_ring_err)
+                       NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Rx resources failed");
        } else if (ice_is_xdp_ena_vsi(vsi) && !prog) {
                xdp_ring_err = ice_destroy_xdp_rings(vsi);
                if (xdp_ring_err)
                        NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed");
+               /* reallocate Rx queues that were used for zero-copy */
+               xdp_ring_err = ice_realloc_zc_buf(vsi, false);
+               if (xdp_ring_err)
+                       NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed");
        } else {
                /* safe to call even when prog == vsi->xdp_prog as
                 * dev_xdp_install in net/core/dev.c incremented prog's
@@ -3905,7 +3911,7 @@ static int ice_init_pf(struct ice_pf *pf)
 
        pf->avail_rxqs = bitmap_zalloc(pf->max_pf_rxqs, GFP_KERNEL);
        if (!pf->avail_rxqs) {
-               devm_kfree(ice_pf_to_dev(pf), pf->avail_txqs);
+               bitmap_free(pf->avail_txqs);
                pf->avail_txqs = NULL;
                return -ENOMEM;
        }
@@ -6643,7 +6649,7 @@ static void ice_napi_disable_all(struct ice_vsi *vsi)
  */
 int ice_down(struct ice_vsi *vsi)
 {
-       int i, tx_err, rx_err, link_err = 0, vlan_err = 0;
+       int i, tx_err, rx_err, vlan_err = 0;
 
        WARN_ON(!test_bit(ICE_VSI_DOWN, vsi->state));
 
@@ -6677,20 +6683,13 @@ int ice_down(struct ice_vsi *vsi)
 
        ice_napi_disable_all(vsi);
 
-       if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
-               link_err = ice_force_phys_link_state(vsi, false);
-               if (link_err)
-                       netdev_err(vsi->netdev, "Failed to set physical link down, VSI %d error %d\n",
-                                  vsi->vsi_num, link_err);
-       }
-
        ice_for_each_txq(vsi, i)
                ice_clean_tx_ring(vsi->tx_rings[i]);
 
        ice_for_each_rxq(vsi, i)
                ice_clean_rx_ring(vsi->rx_rings[i]);
 
-       if (tx_err || rx_err || link_err || vlan_err) {
+       if (tx_err || rx_err || vlan_err) {
                netdev_err(vsi->netdev, "Failed to close VSI 0x%04X on switch 0x%04X\n",
                           vsi->vsi_num, vsi->vsw->sw_id);
                return -EIO;
@@ -6852,6 +6851,8 @@ int ice_vsi_open(struct ice_vsi *vsi)
        if (err)
                goto err_setup_rx;
 
+       ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
+
        if (vsi->type == ICE_VSI_PF) {
                /* Notify the stack of the actual queue counts. */
                err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
@@ -8884,6 +8885,16 @@ int ice_stop(struct net_device *netdev)
                return -EBUSY;
        }
 
+       if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
+               int link_err = ice_force_phys_link_state(vsi, false);
+
+               if (link_err) {
+                       netdev_err(vsi->netdev, "Failed to set physical link down, VSI %d error %d\n",
+                                  vsi->vsi_num, link_err);
+                       return -EIO;
+               }
+       }
+
        ice_vsi_close(vsi);
 
        return 0;
index 836dce8..dd2285d 100644 (file)
@@ -610,7 +610,7 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
        if (test_bit(ICE_VSI_DOWN, vsi->state))
                return -ENETDOWN;
 
-       if (!ice_is_xdp_ena_vsi(vsi) || queue_index >= vsi->num_xdp_txq)
+       if (!ice_is_xdp_ena_vsi(vsi))
                return -ENXIO;
 
        if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
@@ -621,6 +621,9 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
                xdp_ring = vsi->xdp_rings[queue_index];
                spin_lock(&xdp_ring->tx_lock);
        } else {
+               /* Generally, should not happen */
+               if (unlikely(queue_index >= vsi->num_xdp_txq))
+                       return -ENXIO;
                xdp_ring = vsi->xdp_rings[queue_index];
        }
 
@@ -1464,7 +1467,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget)
                bool wd;
 
                if (tx_ring->xsk_pool)
-                       wd = ice_xmit_zc(tx_ring, ICE_DESC_UNUSED(tx_ring), budget);
+                       wd = ice_xmit_zc(tx_ring);
                else if (ice_ring_is_xdp(tx_ring))
                        wd = true;
                else
index e48e292..056c904 100644 (file)
@@ -192,6 +192,7 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
        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);
@@ -317,6 +318,62 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
 }
 
 /**
+ * ice_realloc_rx_xdp_bufs - reallocate for either XSK or normal buffer
+ * @rx_ring: Rx ring
+ * @pool_present: is pool for XSK present
+ *
+ * Try allocating memory and return ENOMEM, if failed to allocate.
+ * If allocation was successful, substitute buffer with allocated one.
+ * Returns 0 on success, negative on failure
+ */
+static int
+ice_realloc_rx_xdp_bufs(struct ice_rx_ring *rx_ring, bool pool_present)
+{
+       size_t elem_size = pool_present ? sizeof(*rx_ring->xdp_buf) :
+                                         sizeof(*rx_ring->rx_buf);
+       void *sw_ring = kcalloc(rx_ring->count, elem_size, GFP_KERNEL);
+
+       if (!sw_ring)
+               return -ENOMEM;
+
+       if (pool_present) {
+               kfree(rx_ring->rx_buf);
+               rx_ring->rx_buf = NULL;
+               rx_ring->xdp_buf = sw_ring;
+       } else {
+               kfree(rx_ring->xdp_buf);
+               rx_ring->xdp_buf = NULL;
+               rx_ring->rx_buf = sw_ring;
+       }
+
+       return 0;
+}
+
+/**
+ * ice_realloc_zc_buf - reallocate XDP ZC queue pairs
+ * @vsi: Current VSI
+ * @zc: is zero copy set
+ *
+ * Reallocate buffer for rx_rings that might be used by XSK.
+ * XDP requires more memory, than rx_buf provides.
+ * Returns 0 on success, negative on failure
+ */
+int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc)
+{
+       struct ice_rx_ring *rx_ring;
+       unsigned long q;
+
+       for_each_set_bit(q, vsi->af_xdp_zc_qps,
+                        max_t(int, vsi->alloc_txq, vsi->alloc_rxq)) {
+               rx_ring = vsi->rx_rings[q];
+               if (ice_realloc_rx_xdp_bufs(rx_ring, zc))
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/**
  * ice_xsk_pool_setup - enable/disable a buffer pool region depending on its state
  * @vsi: Current VSI
  * @pool: buffer pool to enable/associate to a ring, NULL to disable
@@ -335,21 +392,20 @@ int ice_xsk_pool_setup(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
                goto failure;
        }
 
-       if (!is_power_of_2(vsi->rx_rings[qid]->count) ||
-           !is_power_of_2(vsi->tx_rings[qid]->count)) {
-               netdev_err(vsi->netdev, "Please align ring sizes to power of 2\n");
-               pool_failure = -EINVAL;
-               goto failure;
-       }
-
        if_running = netif_running(vsi->netdev) && ice_is_xdp_ena_vsi(vsi);
 
        if (if_running) {
+               struct ice_rx_ring *rx_ring = vsi->rx_rings[qid];
+
                ret = ice_qp_dis(vsi, qid);
                if (ret) {
                        netdev_err(vsi->netdev, "ice_qp_dis error = %d\n", ret);
                        goto xsk_pool_if_up;
                }
+
+               ret = ice_realloc_rx_xdp_bufs(rx_ring, pool_present);
+               if (ret)
+                       goto xsk_pool_if_up;
        }
 
        pool_failure = pool_present ? ice_xsk_pool_enable(vsi, pool, qid) :
@@ -471,11 +527,10 @@ exit:
 bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count)
 {
        u16 rx_thresh = ICE_RING_QUARTER(rx_ring);
-       u16 batched, leftover, i, tail_bumps;
+       u16 leftover, i, tail_bumps;
 
-       batched = ALIGN_DOWN(count, rx_thresh);
-       tail_bumps = batched / rx_thresh;
-       leftover = count & (rx_thresh - 1);
+       tail_bumps = count / rx_thresh;
+       leftover = count - (tail_bumps * rx_thresh);
 
        for (i = 0; i < tail_bumps; i++)
                if (!__ice_alloc_rx_bufs_zc(rx_ring, rx_thresh))
@@ -725,69 +780,57 @@ ice_clean_xdp_tx_buf(struct ice_tx_ring *xdp_ring, struct ice_tx_buf *tx_buf)
 }
 
 /**
- * ice_clean_xdp_irq_zc - Reclaim resources after transmit completes on XDP ring
- * @xdp_ring: XDP ring to clean
- * @napi_budget: amount of descriptors that NAPI allows us to clean
- *
- * Returns count of cleaned descriptors
+ * ice_clean_xdp_irq_zc - produce AF_XDP descriptors to CQ
+ * @xdp_ring: XDP Tx ring
  */
-static u16 ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring, int napi_budget)
+static void ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring)
 {
-       u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
-       int budget = napi_budget / tx_thresh;
-       u16 next_dd = xdp_ring->next_dd;
-       u16 ntc, cleared_dds = 0;
-
-       do {
-               struct ice_tx_desc *next_dd_desc;
-               u16 desc_cnt = xdp_ring->count;
-               struct ice_tx_buf *tx_buf;
-               u32 xsk_frames;
-               u16 i;
-
-               next_dd_desc = ICE_TX_DESC(xdp_ring, next_dd);
-               if (!(next_dd_desc->cmd_type_offset_bsz &
-                   cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE)))
-                       break;
+       u16 ntc = xdp_ring->next_to_clean;
+       struct ice_tx_desc *tx_desc;
+       u16 cnt = xdp_ring->count;
+       struct ice_tx_buf *tx_buf;
+       u16 xsk_frames = 0;
+       u16 last_rs;
+       int i;
 
-               cleared_dds++;
-               xsk_frames = 0;
-               if (likely(!xdp_ring->xdp_tx_active)) {
-                       xsk_frames = tx_thresh;
-                       goto skip;
-               }
+       last_rs = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : cnt - 1;
+       tx_desc = ICE_TX_DESC(xdp_ring, last_rs);
+       if ((tx_desc->cmd_type_offset_bsz &
+           cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE))) {
+               if (last_rs >= ntc)
+                       xsk_frames = last_rs - ntc + 1;
+               else
+                       xsk_frames = last_rs + cnt - ntc + 1;
+       }
 
-               ntc = xdp_ring->next_to_clean;
+       if (!xsk_frames)
+               return;
 
-               for (i = 0; i < tx_thresh; i++) {
-                       tx_buf = &xdp_ring->tx_buf[ntc];
+       if (likely(!xdp_ring->xdp_tx_active))
+               goto skip;
 
-                       if (tx_buf->raw_buf) {
-                               ice_clean_xdp_tx_buf(xdp_ring, tx_buf);
-                               tx_buf->raw_buf = NULL;
-                       } else {
-                               xsk_frames++;
-                       }
+       ntc = xdp_ring->next_to_clean;
+       for (i = 0; i < xsk_frames; i++) {
+               tx_buf = &xdp_ring->tx_buf[ntc];
 
-                       ntc++;
-                       if (ntc >= xdp_ring->count)
-                               ntc = 0;
+               if (tx_buf->raw_buf) {
+                       ice_clean_xdp_tx_buf(xdp_ring, tx_buf);
+                       tx_buf->raw_buf = NULL;
+               } else {
+                       xsk_frames++;
                }
+
+               ntc++;
+               if (ntc >= xdp_ring->count)
+                       ntc = 0;
+       }
 skip:
-               xdp_ring->next_to_clean += tx_thresh;
-               if (xdp_ring->next_to_clean >= desc_cnt)
-                       xdp_ring->next_to_clean -= desc_cnt;
-               if (xsk_frames)
-                       xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames);
-               next_dd_desc->cmd_type_offset_bsz = 0;
-               next_dd = next_dd + tx_thresh;
-               if (next_dd >= desc_cnt)
-                       next_dd = tx_thresh - 1;
-       } while (--budget);
-
-       xdp_ring->next_dd = next_dd;
-
-       return cleared_dds * tx_thresh;
+       tx_desc->cmd_type_offset_bsz = 0;
+       xdp_ring->next_to_clean += xsk_frames;
+       if (xdp_ring->next_to_clean >= cnt)
+               xdp_ring->next_to_clean -= cnt;
+       if (xsk_frames)
+               xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames);
 }
 
 /**
@@ -822,7 +865,6 @@ static void ice_xmit_pkt(struct ice_tx_ring *xdp_ring, struct xdp_desc *desc,
 static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *descs,
                               unsigned int *total_bytes)
 {
-       u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
        u16 ntu = xdp_ring->next_to_use;
        struct ice_tx_desc *tx_desc;
        u32 i;
@@ -842,13 +884,6 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de
        }
 
        xdp_ring->next_to_use = ntu;
-
-       if (xdp_ring->next_to_use > xdp_ring->next_rs) {
-               tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
-               tx_desc->cmd_type_offset_bsz |=
-                       cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
-               xdp_ring->next_rs += tx_thresh;
-       }
 }
 
 /**
@@ -861,7 +896,6 @@ static void ice_xmit_pkt_batch(struct ice_tx_ring *xdp_ring, struct xdp_desc *de
 static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, struct xdp_desc *descs,
                                u32 nb_pkts, unsigned int *total_bytes)
 {
-       u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
        u32 batched, leftover, i;
 
        batched = ALIGN_DOWN(nb_pkts, PKTS_PER_BATCH);
@@ -870,54 +904,54 @@ static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, struct xdp_desc *d
                ice_xmit_pkt_batch(xdp_ring, &descs[i], total_bytes);
        for (; i < batched + leftover; i++)
                ice_xmit_pkt(xdp_ring, &descs[i], total_bytes);
+}
 
-       if (xdp_ring->next_to_use > xdp_ring->next_rs) {
-               struct ice_tx_desc *tx_desc;
+/**
+ * ice_set_rs_bit - set RS bit on last produced descriptor (one behind current NTU)
+ * @xdp_ring: XDP ring to produce the HW Tx descriptors on
+ */
+static void ice_set_rs_bit(struct ice_tx_ring *xdp_ring)
+{
+       u16 ntu = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : xdp_ring->count - 1;
+       struct ice_tx_desc *tx_desc;
 
-               tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
-               tx_desc->cmd_type_offset_bsz |=
-                       cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
-               xdp_ring->next_rs += tx_thresh;
-       }
+       tx_desc = ICE_TX_DESC(xdp_ring, ntu);
+       tx_desc->cmd_type_offset_bsz |=
+               cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
 }
 
 /**
  * ice_xmit_zc - take entries from XSK Tx ring and place them onto HW Tx ring
  * @xdp_ring: XDP ring to produce the HW Tx descriptors on
- * @budget: number of free descriptors on HW Tx ring that can be used
- * @napi_budget: amount of descriptors that NAPI allows us to clean
  *
  * Returns true if there is no more work that needs to be done, false otherwise
  */
-bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, u32 budget, int napi_budget)
+bool ice_xmit_zc(struct ice_tx_ring *xdp_ring)
 {
        struct xdp_desc *descs = xdp_ring->xsk_pool->tx_descs;
-       u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
        u32 nb_pkts, nb_processed = 0;
        unsigned int total_bytes = 0;
+       int budget;
+
+       ice_clean_xdp_irq_zc(xdp_ring);
 
-       if (budget < tx_thresh)
-               budget += ice_clean_xdp_irq_zc(xdp_ring, napi_budget);
+       budget = ICE_DESC_UNUSED(xdp_ring);
+       budget = min_t(u16, budget, ICE_RING_QUARTER(xdp_ring));
 
        nb_pkts = xsk_tx_peek_release_desc_batch(xdp_ring->xsk_pool, budget);
        if (!nb_pkts)
                return true;
 
        if (xdp_ring->next_to_use + nb_pkts >= xdp_ring->count) {
-               struct ice_tx_desc *tx_desc;
-
                nb_processed = xdp_ring->count - xdp_ring->next_to_use;
                ice_fill_tx_hw_ring(xdp_ring, descs, nb_processed, &total_bytes);
-               tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
-               tx_desc->cmd_type_offset_bsz |=
-                       cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
-               xdp_ring->next_rs = tx_thresh - 1;
                xdp_ring->next_to_use = 0;
        }
 
        ice_fill_tx_hw_ring(xdp_ring, &descs[nb_processed], nb_pkts - nb_processed,
                            &total_bytes);
 
+       ice_set_rs_bit(xdp_ring);
        ice_xdp_ring_update_tail(xdp_ring);
        ice_update_tx_ring_stats(xdp_ring, nb_pkts, total_bytes);
 
@@ -995,14 +1029,16 @@ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi)
  */
 void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring)
 {
-       u16 count_mask = rx_ring->count - 1;
        u16 ntc = rx_ring->next_to_clean;
        u16 ntu = rx_ring->next_to_use;
 
-       for ( ; ntc != ntu; ntc = (ntc + 1) & count_mask) {
+       while (ntc != ntu) {
                struct xdp_buff *xdp = *ice_xdp_buf(rx_ring, ntc);
 
                xsk_buff_free(xdp);
+               ntc++;
+               if (ntc >= rx_ring->count)
+                       ntc = 0;
        }
 }
 
index 21faec8..6fa181f 100644 (file)
@@ -26,12 +26,10 @@ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count);
 bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi);
 void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring);
 void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring);
-bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, u32 budget, int napi_budget);
+bool ice_xmit_zc(struct ice_tx_ring *xdp_ring);
+int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc);
 #else
-static inline bool
-ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring,
-           u32 __always_unused budget,
-           int __always_unused napi_budget)
+static inline bool ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring)
 {
        return false;
 }
@@ -72,5 +70,12 @@ ice_xsk_wakeup(struct net_device __always_unused *netdev,
 
 static inline void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring) { }
 static inline void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring) { }
+
+static inline int
+ice_realloc_zc_buf(struct ice_vsi __always_unused *vsi,
+                  bool __always_unused zc)
+{
+       return 0;
+}
 #endif /* CONFIG_XDP_SOCKETS */
 #endif /* !_ICE_XSK_H_ */
index ede3e53..a895862 100644 (file)
@@ -368,6 +368,7 @@ static int prestera_port_sfp_bind(struct prestera_port *port)
        if (!sw->np)
                return 0;
 
+       of_node_get(sw->np);
        ports = of_find_node_by_name(sw->np, "ports");
 
        for_each_child_of_node(ports, node) {
@@ -417,6 +418,7 @@ static int prestera_port_sfp_bind(struct prestera_port *port)
        }
 
 out:
+       of_node_put(node);
        of_node_put(ports);
        return err;
 }
index f538a74..59470d9 100644 (file)
@@ -872,6 +872,7 @@ static void prestera_pci_remove(struct pci_dev *pdev)
 static const struct pci_device_id prestera_pci_devices[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC804) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xC80C) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0xCC1E) },
        { }
 };
 MODULE_DEVICE_TABLE(pci, prestera_pci_devices);
index 5ace460..b344632 100644 (file)
@@ -1458,7 +1458,7 @@ static void mtk_update_rx_cpu_idx(struct mtk_eth *eth)
 
 static bool mtk_page_pool_enabled(struct mtk_eth *eth)
 {
-       return !eth->hwlro;
+       return MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2);
 }
 
 static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth,
index ecf85e9..0f9668a 100644 (file)
 #define MTK_RXD5_PPE_CPU_REASON        GENMASK(22, 18)
 #define MTK_RXD5_SRC_PORT      GENMASK(29, 26)
 
-#define RX_DMA_GET_SPORT(x)    (((x) >> 19) & 0xf)
-#define RX_DMA_GET_SPORT_V2(x) (((x) >> 26) & 0x7)
+#define RX_DMA_GET_SPORT(x)    (((x) >> 19) & 0x7)
+#define RX_DMA_GET_SPORT_V2(x) (((x) >> 26) & 0xf)
 
 /* PDMA V2 descriptor rxd3 */
 #define RX_DMA_VTAG_V2         BIT(0)
index dab8f3f..cfe804b 100644 (file)
@@ -412,7 +412,7 @@ __mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
        if (entry->hash != 0xffff) {
                ppe->foe_table[entry->hash].ib1 &= ~MTK_FOE_IB1_STATE;
                ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE,
-                                                             MTK_FOE_STATE_BIND);
+                                                             MTK_FOE_STATE_UNBIND);
                dma_wmb();
        }
        entry->hash = 0xffff;
index 1f5cf1c..69ffce0 100644 (file)
@@ -293,6 +293,9 @@ mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
        if (!ppe)
                return;
 
+       if (hash > MTK_PPE_HASH_MASK)
+               return;
+
        now = (u16)jiffies;
        diff = now - ppe->foe_check_time[hash];
        if (diff < HZ / 10)
index c085b03..89b2d9c 100644 (file)
@@ -494,6 +494,24 @@ static int max_uc_list_get_devlink_param(struct mlx5_core_dev *dev)
        return err;
 }
 
+bool mlx5_is_roce_on(struct mlx5_core_dev *dev)
+{
+       struct devlink *devlink = priv_to_devlink(dev);
+       union devlink_param_value val;
+       int err;
+
+       err = devlink_param_driverinit_value_get(devlink,
+                                                DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
+                                                &val);
+
+       if (!err)
+               return val.vbool;
+
+       mlx5_core_dbg(dev, "Failed to get param. err = %d\n", err);
+       return MLX5_CAP_GEN(dev, roce);
+}
+EXPORT_SYMBOL(mlx5_is_roce_on);
+
 static int handle_hca_cap_2(struct mlx5_core_dev *dev, void *set_ctx)
 {
        void *set_hca_cap;
@@ -597,7 +615,8 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
                         MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix));
 
        if (MLX5_CAP_GEN(dev, roce_rw_supported))
-               MLX5_SET(cmd_hca_cap, set_hca_cap, roce, mlx5_is_roce_init_enabled(dev));
+               MLX5_SET(cmd_hca_cap, set_hca_cap, roce,
+                        mlx5_is_roce_on(dev));
 
        max_uc_list = max_uc_list_get_devlink_param(dev);
        if (max_uc_list > 0)
@@ -623,7 +642,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
  */
 static bool is_roce_fw_disabled(struct mlx5_core_dev *dev)
 {
-       return (MLX5_CAP_GEN(dev, roce_rw_supported) && !mlx5_is_roce_init_enabled(dev)) ||
+       return (MLX5_CAP_GEN(dev, roce_rw_supported) && !mlx5_is_roce_on(dev)) ||
                (!MLX5_CAP_GEN(dev, roce_rw_supported) && !MLX5_CAP_GEN(dev, roce));
 }
 
index 5fdf9b7..5a1027b 100644 (file)
@@ -75,6 +75,7 @@ struct mlxbf_gige {
        struct net_device *netdev;
        struct platform_device *pdev;
        void __iomem *mdio_io;
+       void __iomem *clk_io;
        struct mii_bus *mdiobus;
        spinlock_t lock;      /* for packet processing indices */
        u16 rx_q_entries;
@@ -137,7 +138,8 @@ enum mlxbf_gige_res {
        MLXBF_GIGE_RES_MDIO9,
        MLXBF_GIGE_RES_GPIO0,
        MLXBF_GIGE_RES_LLU,
-       MLXBF_GIGE_RES_PLU
+       MLXBF_GIGE_RES_PLU,
+       MLXBF_GIGE_RES_CLK
 };
 
 /* Version of register data returned by mlxbf_gige_get_regs() */
index 2e6c1b7..aa780b1 100644 (file)
 #include <linux/property.h>
 
 #include "mlxbf_gige.h"
+#include "mlxbf_gige_regs.h"
 
 #define MLXBF_GIGE_MDIO_GW_OFFSET      0x0
 #define MLXBF_GIGE_MDIO_CFG_OFFSET     0x4
 
+#define MLXBF_GIGE_MDIO_FREQ_REFERENCE 156250000ULL
+#define MLXBF_GIGE_MDIO_COREPLL_CONST  16384ULL
+#define MLXBF_GIGE_MDC_CLK_NS          400
+#define MLXBF_GIGE_MDIO_PLL_I1CLK_REG1 0x4
+#define MLXBF_GIGE_MDIO_PLL_I1CLK_REG2 0x8
+#define MLXBF_GIGE_MDIO_CORE_F_SHIFT   0
+#define MLXBF_GIGE_MDIO_CORE_F_MASK    GENMASK(25, 0)
+#define MLXBF_GIGE_MDIO_CORE_R_SHIFT   26
+#define MLXBF_GIGE_MDIO_CORE_R_MASK    GENMASK(31, 26)
+#define MLXBF_GIGE_MDIO_CORE_OD_SHIFT  0
+#define MLXBF_GIGE_MDIO_CORE_OD_MASK   GENMASK(3, 0)
+
 /* Support clause 22 */
 #define MLXBF_GIGE_MDIO_CL22_ST1       0x1
 #define MLXBF_GIGE_MDIO_CL22_WRITE     0x1
 #define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK          GENMASK(23, 16)
 #define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK         GENMASK(31, 24)
 
+#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
+
+#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30
+#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c
+
+static struct resource corepll_params[] = {
+       [MLXBF_GIGE_VERSION_BF2] = {
+               .start = MLXBF_GIGE_BF2_COREPLL_ADDR,
+               .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1,
+               .name = "COREPLL_RES"
+       },
+};
+
+/* Returns core clock i1clk in Hz */
+static u64 calculate_i1clk(struct mlxbf_gige *priv)
+{
+       u8 core_od, core_r;
+       u64 freq_output;
+       u32 reg1, reg2;
+       u32 core_f;
+
+       reg1 = readl(priv->clk_io + MLXBF_GIGE_MDIO_PLL_I1CLK_REG1);
+       reg2 = readl(priv->clk_io + MLXBF_GIGE_MDIO_PLL_I1CLK_REG2);
+
+       core_f = (reg1 & MLXBF_GIGE_MDIO_CORE_F_MASK) >>
+               MLXBF_GIGE_MDIO_CORE_F_SHIFT;
+       core_r = (reg1 & MLXBF_GIGE_MDIO_CORE_R_MASK) >>
+               MLXBF_GIGE_MDIO_CORE_R_SHIFT;
+       core_od = (reg2 & MLXBF_GIGE_MDIO_CORE_OD_MASK) >>
+               MLXBF_GIGE_MDIO_CORE_OD_SHIFT;
+
+       /* Compute PLL output frequency as follow:
+        *
+        *                                     CORE_F / 16384
+        * freq_output = freq_reference * ----------------------------
+        *                              (CORE_R + 1) * (CORE_OD + 1)
+        */
+       freq_output = div_u64((MLXBF_GIGE_MDIO_FREQ_REFERENCE * core_f),
+                             MLXBF_GIGE_MDIO_COREPLL_CONST);
+       freq_output = div_u64(freq_output, (core_r + 1) * (core_od + 1));
+
+       return freq_output;
+}
+
 /* Formula for encoding the MDIO period. The encoded value is
  * passed to the MDIO config register.
  *
- * mdc_clk = 2*(val + 1)*i1clk
+ * mdc_clk = 2*(val + 1)*(core clock in sec)
  *
- * 400 ns = 2*(val + 1)*(((1/430)*1000) ns)
+ * i1clk is in Hz:
+ * 400 ns = 2*(val + 1)*(1/i1clk)
  *
- * val = (((400 * 430 / 1000) / 2) - 1)
+ * val = (((400/10^9) / (1/i1clk) / 2) - 1)
+ * val = (400/2 * i1clk)/10^9 - 1
  */
-#define MLXBF_GIGE_I1CLK_MHZ           430
-#define MLXBF_GIGE_MDC_CLK_NS          400
+static u8 mdio_period_map(struct mlxbf_gige *priv)
+{
+       u8 mdio_period;
+       u64 i1clk;
 
-#define MLXBF_GIGE_MDIO_PERIOD (((MLXBF_GIGE_MDC_CLK_NS * MLXBF_GIGE_I1CLK_MHZ / 1000) / 2) - 1)
+       i1clk = calculate_i1clk(priv);
 
-#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, \
-                                           MLXBF_GIGE_MDIO_PERIOD) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
+       mdio_period = div_u64((MLXBF_GIGE_MDC_CLK_NS >> 1) * i1clk, 1000000000) - 1;
+
+       return mdio_period;
+}
 
 static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add,
                                      int phy_reg, u32 opcode)
@@ -117,6 +179,9 @@ static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg)
        /* Only return ad bits of the gw register */
        ret &= MLXBF_GIGE_MDIO_GW_AD_MASK;
 
+       /* The MDIO lock is set on read. To release it, clear gw register */
+       writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
+
        return ret;
 }
 
@@ -124,9 +189,9 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
                                 int phy_reg, u16 val)
 {
        struct mlxbf_gige *priv = bus->priv;
+       u32 temp;
        u32 cmd;
        int ret;
-       u32 temp;
 
        if (phy_reg & MII_ADDR_C45)
                return -EOPNOTSUPP;
@@ -141,21 +206,50 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
                                        temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK),
                                        5, 1000000);
 
+       /* The MDIO lock is set on read. To release it, clear gw register */
+       writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
+
        return ret;
 }
 
+static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv)
+{
+       u8 mdio_period;
+       u32 val;
+
+       mdio_period = mdio_period_map(priv);
+
+       val = MLXBF_GIGE_MDIO_CFG_VAL;
+       val |= FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period);
+       writel(val, priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
+}
+
 int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
 {
        struct device *dev = &pdev->dev;
+       struct resource *res;
        int ret;
 
        priv->mdio_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MDIO9);
        if (IS_ERR(priv->mdio_io))
                return PTR_ERR(priv->mdio_io);
 
-       /* Configure mdio parameters */
-       writel(MLXBF_GIGE_MDIO_CFG_VAL,
-              priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
+       /* clk resource shared with other drivers so cannot use
+        * devm_platform_ioremap_resource
+        */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK);
+       if (!res) {
+               /* For backward compatibility with older ACPI tables, also keep
+                * CLK resource internal to the driver.
+                */
+               res = &corepll_params[MLXBF_GIGE_VERSION_BF2];
+       }
+
+       priv->clk_io = devm_ioremap(dev, res->start, resource_size(res));
+       if (!priv->clk_io)
+               return -ENOMEM;
+
+       mlxbf_gige_mdio_cfg(priv);
 
        priv->mdiobus = devm_mdiobus_alloc(dev);
        if (!priv->mdiobus) {
index 5fb33c9..7be3a79 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __MLXBF_GIGE_REGS_H__
 #define __MLXBF_GIGE_REGS_H__
 
+#define MLXBF_GIGE_VERSION                            0x0000
+#define MLXBF_GIGE_VERSION_BF2                        0x0
 #define MLXBF_GIGE_STATUS                             0x0010
 #define MLXBF_GIGE_STATUS_READY                       BIT(0)
 #define MLXBF_GIGE_INT_STATUS                         0x0028
index 39904da..b3472fb 100644 (file)
@@ -423,7 +423,8 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
 
        parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
        ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
-                           0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0);
+                           0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0,
+                           0);
 
        rt = ip_route_output_key(tun->net, &fl4);
        if (IS_ERR(rt))
index 6dea7f8..51f8a08 100644 (file)
@@ -425,7 +425,8 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
        lan966x_ifh_get_src_port(skb->data, &src_port);
        lan966x_ifh_get_timestamp(skb->data, &timestamp);
 
-       WARN_ON(src_port >= lan966x->num_phys_ports);
+       if (WARN_ON(src_port >= lan966x->num_phys_ports))
+               goto free_skb;
 
        skb->dev = lan966x->ports[src_port]->dev;
        skb_pull(skb, IFH_LEN * sizeof(u32));
@@ -449,6 +450,8 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
 
        return skb;
 
+free_skb:
+       kfree_skb(skb);
 unmap_page:
        dma_unmap_page(lan966x->dev, (dma_addr_t)db->dataptr,
                       FDMA_DCB_STATUS_BLOCKL(db->status),
index 304f84a..21844be 100644 (file)
@@ -113,6 +113,8 @@ static void sparx5_xtr_grp(struct sparx5 *sparx5, u8 grp, bool byte_swap)
                        /* This assumes STATUS_WORD_POS == 1, Status
                         * just after last data
                         */
+                       if (!byte_swap)
+                               val = ntohl((__force __be32)val);
                        byte_cnt -= (4 - XTR_VALID_BYTES(val));
                        eof_flag = true;
                        break;
index 5f92401..a6f99b4 100644 (file)
@@ -397,6 +397,11 @@ static void mana_gd_process_eq_events(void *arg)
                        break;
                }
 
+               /* Per GDMA spec, rmb is necessary after checking owner_bits, before
+                * reading eqe.
+                */
+               rmb();
+
                mana_gd_process_eqe(eq);
 
                eq->head++;
@@ -1134,6 +1139,11 @@ static int mana_gd_read_cqe(struct gdma_queue *cq, struct gdma_comp *comp)
        if (WARN_ON_ONCE(owner_bits != new_bits))
                return -1;
 
+       /* Per GDMA spec, rmb is necessary after checking owner_bits, before
+        * reading completion info
+        */
+       rmb();
+
        comp->wq_num = cqe->cqe_info.wq_num;
        comp->is_sq = cqe->cqe_info.is_sq;
        memcpy(comp->cqe_data, cqe->cqe_data, GDMA_COMP_DATA_SIZE);
@@ -1465,10 +1475,6 @@ static void mana_gd_shutdown(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-#ifndef PCI_VENDOR_ID_MICROSOFT
-#define PCI_VENDOR_ID_MICROSOFT 0x1414
-#endif
-
 static const struct pci_device_id mana_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MICROSOFT, MANA_PF_DEVICE_ID) },
        { PCI_DEVICE(PCI_VENDOR_ID_MICROSOFT, MANA_VF_DEVICE_ID) },
index 306026e..8f8005b 100644 (file)
@@ -290,6 +290,13 @@ static int ocelot_port_num_untagged_vlans(struct ocelot *ocelot, int port)
                if (!(vlan->portmask & BIT(port)))
                        continue;
 
+               /* Ignore the VLAN added by ocelot_add_vlan_unaware_pvid(),
+                * because this is never active in hardware at the same time as
+                * the bridge VLANs, which only matter in VLAN-aware mode.
+                */
+               if (vlan->vid >= OCELOT_RSV_VLAN_RANGE_START)
+                       continue;
+
                if (vlan->untagged & BIT(port))
                        num_untagged++;
        }
index 4e5df9f..7b92026 100644 (file)
@@ -127,10 +127,11 @@ static int nfp_policer_validate(const struct flow_action *action,
                return -EOPNOTSUPP;
        }
 
-       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+       if (act->police.notexceed.act_id != FLOW_ACTION_CONTINUE &&
+           act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
            act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
                NL_SET_ERR_MSG_MOD(extack,
-                                  "Offload not supported when conform action is not pipe or ok");
+                                  "Offload not supported when conform action is not continue, pipe or ok");
                return -EOPNOTSUPP;
        }
 
index cf4d6f1..349a2b1 100644 (file)
@@ -1630,21 +1630,21 @@ static void nfp_net_stat64(struct net_device *netdev,
                unsigned int start;
 
                do {
-                       start = u64_stats_fetch_begin(&r_vec->rx_sync);
+                       start = u64_stats_fetch_begin_irq(&r_vec->rx_sync);
                        data[0] = r_vec->rx_pkts;
                        data[1] = r_vec->rx_bytes;
                        data[2] = r_vec->rx_drops;
-               } while (u64_stats_fetch_retry(&r_vec->rx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&r_vec->rx_sync, start));
                stats->rx_packets += data[0];
                stats->rx_bytes += data[1];
                stats->rx_dropped += data[2];
 
                do {
-                       start = u64_stats_fetch_begin(&r_vec->tx_sync);
+                       start = u64_stats_fetch_begin_irq(&r_vec->tx_sync);
                        data[0] = r_vec->tx_pkts;
                        data[1] = r_vec->tx_bytes;
                        data[2] = r_vec->tx_errors;
-               } while (u64_stats_fetch_retry(&r_vec->tx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&r_vec->tx_sync, start));
                stats->tx_packets += data[0];
                stats->tx_bytes += data[1];
                stats->tx_errors += data[2];
index eeb1455..b1b1b64 100644 (file)
@@ -649,7 +649,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
                unsigned int start;
 
                do {
-                       start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync);
+                       start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].rx_sync);
                        data[0] = nn->r_vecs[i].rx_pkts;
                        tmp[0] = nn->r_vecs[i].hw_csum_rx_ok;
                        tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok;
@@ -657,10 +657,10 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
                        tmp[3] = nn->r_vecs[i].hw_csum_rx_error;
                        tmp[4] = nn->r_vecs[i].rx_replace_buf_alloc_fail;
                        tmp[5] = nn->r_vecs[i].hw_tls_rx;
-               } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].rx_sync, start));
 
                do {
-                       start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync);
+                       start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].tx_sync);
                        data[1] = nn->r_vecs[i].tx_pkts;
                        data[2] = nn->r_vecs[i].tx_busy;
                        tmp[6] = nn->r_vecs[i].hw_csum_tx;
@@ -670,7 +670,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
                        tmp[10] = nn->r_vecs[i].hw_tls_tx;
                        tmp[11] = nn->r_vecs[i].tls_tx_fallback;
                        tmp[12] = nn->r_vecs[i].tls_tx_no_fallback;
-               } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].tx_sync, start));
 
                data += NN_RVEC_PER_Q_STATS;
 
index edd3000..4cc3879 100644 (file)
@@ -507,6 +507,7 @@ int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsigned int idx, bool state)
        if (nfp_nsp_get_abi_ver_minor(nsp) < 32) {
                nfp_err(nfp_nsp_cpp(nsp),
                        "set id mode operation not supported, please update flash\n");
+               nfp_eth_config_cleanup_end(nsp);
                return -EOPNOTSUPP;
        }
 
index b357ac4..7e32b04 100644 (file)
@@ -1449,6 +1449,8 @@ 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;
index 67ade78..7fd8828 100644 (file)
@@ -2029,6 +2029,8 @@ 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;
index bc70c6a..58cf7cc 100644 (file)
@@ -1273,7 +1273,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
        bool removing;
        int err = 0;
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (!entry)
                return -ENOMEM;
 
index ee734b6..d1e1aa1 100644 (file)
@@ -4213,7 +4213,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
        .ev_test_generate = efx_ef10_ev_test_generate,
        .filter_table_probe = efx_ef10_filter_table_probe,
        .filter_table_restore = efx_mcdi_filter_table_restore,
-       .filter_table_remove = efx_mcdi_filter_table_remove,
+       .filter_table_remove = efx_ef10_filter_table_remove,
        .filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
        .filter_insert = efx_mcdi_filter_insert,
        .filter_remove_safe = efx_mcdi_filter_remove_safe,
index 032b8c0..5b4d661 100644 (file)
@@ -319,7 +319,7 @@ int efx_probe_interrupts(struct efx_nic *efx)
                efx->n_channels = 1 + (efx_separate_tx_channels ? 1 : 0);
                efx->n_rx_channels = 1;
                efx->n_tx_channels = 1;
-               efx->tx_channel_offset = 1;
+               efx->tx_channel_offset = efx_separate_tx_channels ? 1 : 0;
                efx->n_xdp_channels = 0;
                efx->xdp_channel_offset = efx->n_channels;
                efx->legacy_irq = efx->pci_dev->irq;
index 017212a..f54ebd0 100644 (file)
@@ -320,7 +320,7 @@ int efx_siena_probe_interrupts(struct efx_nic *efx)
                efx->n_channels = 1 + (efx_siena_separate_tx_channels ? 1 : 0);
                efx->n_rx_channels = 1;
                efx->n_tx_channels = 1;
-               efx->tx_channel_offset = 1;
+               efx->tx_channel_offset = efx_siena_separate_tx_channels ? 1 : 0;
                efx->n_xdp_channels = 0;
                efx->xdp_channel_offset = efx->n_channels;
                efx->legacy_irq = efx->pci_dev->irq;
index e166dcb..91e8759 100644 (file)
@@ -336,7 +336,7 @@ netdev_tx_t efx_siena_hard_start_xmit(struct sk_buff *skb,
                 * previous packets out.
                 */
                if (!netdev_xmit_more())
-                       efx_tx_send_pending(tx_queue->channel);
+                       efx_tx_send_pending(efx_get_tx_channel(efx, index));
                return NETDEV_TX_OK;
        }
 
index d124740..c5f88f7 100644 (file)
@@ -549,7 +549,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
                 * previous packets out.
                 */
                if (!netdev_xmit_more())
-                       efx_tx_send_pending(tx_queue->channel);
+                       efx_tx_send_pending(efx_get_tx_channel(efx, index));
                return NETDEV_TX_OK;
        }
 
index 3bf2021..3829c28 100644 (file)
@@ -1037,6 +1037,8 @@ 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);
@@ -2587,6 +2589,8 @@ static int smsc911x_suspend(struct device *dev)
        if (netif_running(ndev)) {
                netif_stop_queue(ndev);
                netif_device_detach(ndev);
+               if (!device_may_wakeup(dev))
+                       phy_stop(ndev->phydev);
        }
 
        /* enable wake on LAN, energy detection and the external PME
@@ -2628,6 +2632,8 @@ static int smsc911x_resume(struct device *dev)
        if (netif_running(ndev)) {
                netif_device_attach(ndev);
                netif_start_queue(ndev);
+               if (!device_may_wakeup(dev))
+                       phy_start(ndev->phydev);
        }
 
        return 0;
index 4f2b82a..9af25be 100644 (file)
@@ -1136,8 +1136,6 @@ static void intel_eth_pci_remove(struct pci_dev *pdev)
 
        clk_disable_unprepare(priv->plat->stmmac_clk);
        clk_unregister_fixed_rate(priv->plat->stmmac_clk);
-
-       pcim_iounmap_regions(pdev, BIT(0));
 }
 
 static int __maybe_unused intel_eth_pci_suspend(struct device *dev)
index 592d29a..9083159 100644 (file)
@@ -3801,6 +3801,15 @@ static int __stmmac_open(struct net_device *dev,
 
        stmmac_reset_queues_param(priv);
 
+       if (priv->plat->serdes_powerup) {
+               ret = priv->plat->serdes_powerup(dev, priv->plat->bsp_priv);
+               if (ret < 0) {
+                       netdev_err(priv->dev, "%s: Serdes powerup failed\n",
+                                  __func__);
+                       goto init_error;
+               }
+       }
+
        ret = stmmac_hw_setup(dev, true);
        if (ret < 0) {
                netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
@@ -3904,6 +3913,10 @@ static int stmmac_release(struct net_device *dev)
        /* Disable the MAC Rx/Tx */
        stmmac_mac_set(priv, priv->ioaddr, false);
 
+       /* Powerdown Serdes if there is */
+       if (priv->plat->serdes_powerdown)
+               priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv);
+
        netif_carrier_off(dev);
 
        stmmac_release_ptp(priv);
@@ -7293,14 +7306,6 @@ int stmmac_dvr_probe(struct device *device,
                goto error_netdev_register;
        }
 
-       if (priv->plat->serdes_powerup) {
-               ret = priv->plat->serdes_powerup(ndev,
-                                                priv->plat->bsp_priv);
-
-               if (ret < 0)
-                       goto error_serdes_powerup;
-       }
-
 #ifdef CONFIG_DEBUG_FS
        stmmac_init_fs(ndev);
 #endif
@@ -7315,8 +7320,6 @@ int stmmac_dvr_probe(struct device *device,
 
        return ret;
 
-error_serdes_powerup:
-       unregister_netdev(ndev);
 error_netdev_register:
        phylink_destroy(priv->phylink);
 error_xpcs_setup:
index 8594ee8..88aa0d3 100644 (file)
@@ -2020,9 +2020,9 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
 
                        skb_reserve(copy_skb, 2);
                        skb_put(copy_skb, len);
-                       dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
+                       dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len + 2, DMA_FROM_DEVICE);
                        skb_copy_from_linear_data(skb, copy_skb->data, len);
-                       dma_sync_single_for_device(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
+                       dma_sync_single_for_device(hp->dma_dev, dma_addr, len + 2, DMA_FROM_DEVICE);
                        /* Reuse original ring buffer. */
                        hme_write_rxd(hp, this,
                                      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
index 74e845f..aa8f828 100644 (file)
@@ -213,6 +213,7 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                pci_iounmap(pdev, rrpriv->regs);
        if (pdev)
                pci_release_regions(pdev);
+       pci_disable_device(pdev);
  out2:
        free_netdev(dev);
  out3:
index 6afdf16..5cf218c 100644 (file)
@@ -1310,10 +1310,11 @@ static void adf7242_remove(struct spi_device *spi)
 
        debugfs_remove_recursive(lp->debugfs_root);
 
+       ieee802154_unregister_hw(lp->hw);
+
        cancel_delayed_work_sync(&lp->work);
        destroy_workqueue(lp->wqueue);
 
-       ieee802154_unregister_hw(lp->hw);
        mutex_destroy(&lp->bmux);
        ieee802154_free_hw(lp->hw);
 }
index 42c0b45..450b16a 100644 (file)
@@ -2293,7 +2293,7 @@ static int ca8210_set_csma_params(
  * @retries:  Number of retries
  *
  * Sets the number of times to retry a transmission if no acknowledgment was
- * was received from the other end when one was requested.
+ * received from the other end when one was requested.
  *
  * Return: 0 or linux error code
  */
index 1e1f40f..c69b87d 100644 (file)
@@ -504,6 +504,7 @@ cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
                goto err_tx;
 
        if (status & CC2520_STATUS_TX_UNDERFLOW) {
+               rc = -EINVAL;
                dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
                goto err_tx;
        }
index ec010cf..6f874f9 100644 (file)
@@ -308,12 +308,12 @@ init_modem_driver_req(struct ipa_qmi *ipa_qmi)
        mem = ipa_mem_find(ipa, IPA_MEM_V4_ROUTE);
        req.v4_route_tbl_info_valid = 1;
        req.v4_route_tbl_info.start = ipa->mem_offset + mem->offset;
-       req.v4_route_tbl_info.count = mem->size / sizeof(__le64);
+       req.v4_route_tbl_info.end = IPA_ROUTE_MODEM_COUNT - 1;
 
        mem = ipa_mem_find(ipa, IPA_MEM_V6_ROUTE);
        req.v6_route_tbl_info_valid = 1;
        req.v6_route_tbl_info.start = ipa->mem_offset + mem->offset;
-       req.v6_route_tbl_info.count = mem->size / sizeof(__le64);
+       req.v6_route_tbl_info.end = IPA_ROUTE_MODEM_COUNT - 1;
 
        mem = ipa_mem_find(ipa, IPA_MEM_V4_FILTER);
        req.v4_filter_tbl_start_valid = 1;
@@ -352,7 +352,7 @@ init_modem_driver_req(struct ipa_qmi *ipa_qmi)
                req.v4_hash_route_tbl_info_valid = 1;
                req.v4_hash_route_tbl_info.start =
                                ipa->mem_offset + mem->offset;
-               req.v4_hash_route_tbl_info.count = mem->size / sizeof(__le64);
+               req.v4_hash_route_tbl_info.end = IPA_ROUTE_MODEM_COUNT - 1;
        }
 
        mem = ipa_mem_find(ipa, IPA_MEM_V6_ROUTE_HASHED);
@@ -360,7 +360,7 @@ init_modem_driver_req(struct ipa_qmi *ipa_qmi)
                req.v6_hash_route_tbl_info_valid = 1;
                req.v6_hash_route_tbl_info.start =
                        ipa->mem_offset + mem->offset;
-               req.v6_hash_route_tbl_info.count = mem->size / sizeof(__le64);
+               req.v6_hash_route_tbl_info.end = IPA_ROUTE_MODEM_COUNT - 1;
        }
 
        mem = ipa_mem_find(ipa, IPA_MEM_V4_FILTER_HASHED);
index 6838e80..75d3fc0 100644 (file)
@@ -311,7 +311,7 @@ struct qmi_elem_info ipa_init_modem_driver_req_ei[] = {
                .tlv_type       = 0x12,
                .offset         = offsetof(struct ipa_init_modem_driver_req,
                                           v4_route_tbl_info),
-               .ei_array       = ipa_mem_array_ei,
+               .ei_array       = ipa_mem_bounds_ei,
        },
        {
                .data_type      = QMI_OPT_FLAG,
@@ -332,7 +332,7 @@ struct qmi_elem_info ipa_init_modem_driver_req_ei[] = {
                .tlv_type       = 0x13,
                .offset         = offsetof(struct ipa_init_modem_driver_req,
                                           v6_route_tbl_info),
-               .ei_array       = ipa_mem_array_ei,
+               .ei_array       = ipa_mem_bounds_ei,
        },
        {
                .data_type      = QMI_OPT_FLAG,
@@ -496,7 +496,7 @@ struct qmi_elem_info ipa_init_modem_driver_req_ei[] = {
                .tlv_type       = 0x1b,
                .offset         = offsetof(struct ipa_init_modem_driver_req,
                                           v4_hash_route_tbl_info),
-               .ei_array       = ipa_mem_array_ei,
+               .ei_array       = ipa_mem_bounds_ei,
        },
        {
                .data_type      = QMI_OPT_FLAG,
@@ -517,7 +517,7 @@ struct qmi_elem_info ipa_init_modem_driver_req_ei[] = {
                .tlv_type       = 0x1c,
                .offset         = offsetof(struct ipa_init_modem_driver_req,
                                           v6_hash_route_tbl_info),
-               .ei_array       = ipa_mem_array_ei,
+               .ei_array       = ipa_mem_bounds_ei,
        },
        {
                .data_type      = QMI_OPT_FLAG,
index 495e85a..9651aa5 100644 (file)
@@ -86,9 +86,11 @@ enum ipa_platform_type {
        IPA_QMI_PLATFORM_TYPE_MSM_QNX_V01       = 0x5,  /* QNX MSM */
 };
 
-/* This defines the start and end offset of a range of memory.  Both
- * fields are offsets relative to the start of IPA shared memory.
- * The end value is the last addressable byte *within* the range.
+/* This defines the start and end offset of a range of memory.  The start
+ * value is a byte offset relative to the start of IPA shared memory.  The
+ * end value is the last addressable unit *within* the range.  Typically
+ * the end value is in units of bytes, however it can also be a maximum
+ * array index value.
  */
 struct ipa_mem_bounds {
        u32 start;
@@ -129,18 +131,19 @@ struct ipa_init_modem_driver_req {
        u8                      hdr_tbl_info_valid;
        struct ipa_mem_bounds   hdr_tbl_info;
 
-       /* Routing table information.  These define the location and size of
-        * non-hashable IPv4 and IPv6 filter tables.  The start values are
-        * offsets relative to the start of IPA shared memory.
+       /* Routing table information.  These define the location and maximum
+        * *index* (not byte) for the modem portion of non-hashable IPv4 and
+        * IPv6 routing tables.  The start values are byte offsets relative
+        * to the start of IPA shared memory.
         */
        u8                      v4_route_tbl_info_valid;
-       struct ipa_mem_array    v4_route_tbl_info;
+       struct ipa_mem_bounds   v4_route_tbl_info;
        u8                      v6_route_tbl_info_valid;
-       struct ipa_mem_array    v6_route_tbl_info;
+       struct ipa_mem_bounds   v6_route_tbl_info;
 
        /* Filter table information.  These define the location of the
         * non-hashable IPv4 and IPv6 filter tables.  The start values are
-        * offsets relative to the start of IPA shared memory.
+        * byte offsets relative to the start of IPA shared memory.
         */
        u8                      v4_filter_tbl_start_valid;
        u32                     v4_filter_tbl_start;
@@ -181,18 +184,20 @@ struct ipa_init_modem_driver_req {
        u8                      zip_tbl_info_valid;
        struct ipa_mem_bounds   zip_tbl_info;
 
-       /* Routing table information.  These define the location and size
-        * of hashable IPv4 and IPv6 filter tables.  The start values are
-        * offsets relative to the start of IPA shared memory.
+       /* Routing table information.  These define the location and maximum
+        * *index* (not byte) for the modem portion of hashable IPv4 and IPv6
+        * routing tables (if supported by hardware).  The start values are
+        * byte offsets relative to the start of IPA shared memory.
         */
        u8                      v4_hash_route_tbl_info_valid;
-       struct ipa_mem_array    v4_hash_route_tbl_info;
+       struct ipa_mem_bounds   v4_hash_route_tbl_info;
        u8                      v6_hash_route_tbl_info_valid;
-       struct ipa_mem_array    v6_hash_route_tbl_info;
+       struct ipa_mem_bounds   v6_hash_route_tbl_info;
 
        /* Filter table information.  These define the location and size
-        * of hashable IPv4 and IPv6 filter tables.  The start values are
-        * offsets relative to the start of IPA shared memory.
+        * of hashable IPv4 and IPv6 filter tables (if supported by hardware).
+        * The start values are byte offsets relative to the start of IPA
+        * shared memory.
         */
        u8                      v4_hash_filter_tbl_start_valid;
        u32                     v4_hash_filter_tbl_start;
index 2f5a58b..69efe67 100644 (file)
 
 /* Assignment of route table entries to the modem and AP */
 #define IPA_ROUTE_MODEM_MIN            0
-#define IPA_ROUTE_MODEM_COUNT          8
-
 #define IPA_ROUTE_AP_MIN               IPA_ROUTE_MODEM_COUNT
 #define IPA_ROUTE_AP_COUNT \
                (IPA_ROUTE_COUNT_MAX - IPA_ROUTE_MODEM_COUNT)
index b6a9a0d..1538e2e 100644 (file)
@@ -13,6 +13,9 @@ struct ipa;
 /* The maximum number of filter table entries (IPv4, IPv6; hashed or not) */
 #define IPA_FILTER_COUNT_MAX   14
 
+/* The number of route table entries allotted to the modem */
+#define IPA_ROUTE_MODEM_COUNT  8
+
 /* The maximum number of route table entries (IPv4, IPv6; hashed or not) */
 #define IPA_ROUTE_COUNT_MAX    15
 
index dfeb5b3..bb1c298 100644 (file)
@@ -495,7 +495,6 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
 
 static int ipvlan_process_outbound(struct sk_buff *skb)
 {
-       struct ethhdr *ethh = eth_hdr(skb);
        int ret = NET_XMIT_DROP;
 
        /* The ipvlan is a pseudo-L2 device, so the packets that we receive
@@ -505,6 +504,8 @@ static int ipvlan_process_outbound(struct sk_buff *skb)
        if (skb_mac_header_was_set(skb)) {
                /* In this mode we dont care about
                 * multicast and broadcast traffic */
+               struct ethhdr *ethh = eth_hdr(skb);
+
                if (is_multicast_ether_addr(ethh->h_dest)) {
                        pr_debug_ratelimited(
                                "Dropped {multi|broad}cast of type=[%x]\n",
@@ -589,7 +590,7 @@ out:
 static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 {
        const struct ipvl_dev *ipvlan = netdev_priv(dev);
-       struct ethhdr *eth = eth_hdr(skb);
+       struct ethhdr *eth = skb_eth_hdr(skb);
        struct ipvl_addr *addr;
        void *lyr3h;
        int addr_type;
@@ -619,6 +620,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
                return dev_forward_skb(ipvlan->phy_dev, skb);
 
        } else if (is_multicast_ether_addr(eth->h_dest)) {
+               skb_reset_mac_header(skb);
                ipvlan_skb_crossing_ns(skb, NULL);
                ipvlan_multicast_enqueue(ipvlan->port, skb, true);
                return NET_XMIT_SUCCESS;
index 3e79c2c..1c1584f 100644 (file)
@@ -47,7 +47,9 @@ int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
         * just fall back to poll mode
         */
        if (rc == -EPROBE_DEFER)
-               rc = -ENODEV;
+               rc = driver_deferred_probe_check_state(&phy->mdio.dev);
+       if (rc == -EPROBE_DEFER)
+               return rc;
 
        if (rc > 0) {
                phy->irq = rc;
index 9e3c815..796e9c7 100644 (file)
@@ -231,6 +231,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        return 0;
 
 unregister:
+       of_node_put(child);
        mdiobus_unregister(mdio);
        return rc;
 }
index 605a38e..0e58aa7 100644 (file)
@@ -433,11 +433,11 @@ int nsim_dev_hwstats_init(struct nsim_dev *nsim_dev)
                goto err_remove_hwstats_recursive;
        }
 
-       debugfs_create_file("enable_ifindex", 0600, hwstats->l3_ddir, hwstats,
+       debugfs_create_file("enable_ifindex", 0200, hwstats->l3_ddir, hwstats,
                            &nsim_dev_hwstats_l3_enable_fops.fops);
-       debugfs_create_file("disable_ifindex", 0600, hwstats->l3_ddir, hwstats,
+       debugfs_create_file("disable_ifindex", 0200, hwstats->l3_ddir, hwstats,
                            &nsim_dev_hwstats_l3_disable_fops.fops);
-       debugfs_create_file("fail_next_enable", 0600, hwstats->l3_ddir, hwstats,
+       debugfs_create_file("fail_next_enable", 0200, hwstats->l3_ddir, hwstats,
                            &nsim_dev_hwstats_l3_fail_fops.fops);
 
        INIT_DELAYED_WORK(&hwstats->traffic_dw,
index e470e33..9a1a5b2 100644 (file)
@@ -67,10 +67,10 @@ nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
        unsigned int start;
 
        do {
-               start = u64_stats_fetch_begin(&ns->syncp);
+               start = u64_stats_fetch_begin_irq(&ns->syncp);
                stats->tx_bytes = ns->tx_bytes;
                stats->tx_packets = ns->tx_packets;
-       } while (u64_stats_fetch_retry(&ns->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&ns->syncp, start));
 }
 
 static int
index 8b7a46d..7111e2e 100644 (file)
@@ -91,6 +91,9 @@
 #define VEND1_GLOBAL_FW_ID_MAJOR               GENMASK(15, 8)
 #define VEND1_GLOBAL_FW_ID_MINOR               GENMASK(7, 0)
 
+#define VEND1_GLOBAL_GEN_STAT2                 0xc831
+#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG      BIT(15)
+
 #define VEND1_GLOBAL_RSVD_STAT1                        0xc885
 #define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID    GENMASK(7, 4)
 #define VEND1_GLOBAL_RSVD_STAT1_PROV_ID                GENMASK(3, 0)
 #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2     BIT(1)
 #define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3     BIT(0)
 
+/* Sleep and timeout for checking if the Processor-Intensive
+ * MDIO operation is finished
+ */
+#define AQR107_OP_IN_PROG_SLEEP                1000
+#define AQR107_OP_IN_PROG_TIMEOUT      100000
+
 struct aqr107_hw_stat {
        const char *name;
        int reg;
@@ -597,16 +606,52 @@ static void aqr107_link_change_notify(struct phy_device *phydev)
                phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n");
 }
 
+static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
+{
+       int val, err;
+
+       /* The datasheet notes to wait at least 1ms after issuing a
+        * processor intensive operation before checking.
+        * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
+        * because that just determines the maximum time slept, not the minimum.
+        */
+       usleep_range(1000, 5000);
+
+       err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+                                       VEND1_GLOBAL_GEN_STAT2, val,
+                                       !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
+                                       AQR107_OP_IN_PROG_SLEEP,
+                                       AQR107_OP_IN_PROG_TIMEOUT, false);
+       if (err) {
+               phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
+               return err;
+       }
+
+       return 0;
+}
+
 static int aqr107_suspend(struct phy_device *phydev)
 {
-       return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
-                               MDIO_CTRL1_LPOWER);
+       int err;
+
+       err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
+                              MDIO_CTRL1_LPOWER);
+       if (err)
+               return err;
+
+       return aqr107_wait_processor_intensive_op(phydev);
 }
 
 static int aqr107_resume(struct phy_device *phydev)
 {
-       return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
-                                 MDIO_CTRL1_LPOWER);
+       int err;
+
+       err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1,
+                                MDIO_CTRL1_LPOWER);
+       if (err)
+               return err;
+
+       return aqr107_wait_processor_intensive_op(phydev);
 }
 
 static int aqr107_probe(struct phy_device *phydev)
index 73f7962..c49062a 100644 (file)
@@ -243,13 +243,7 @@ static irqreturn_t meson_gxl_handle_interrupt(struct phy_device *phydev)
            irq_status == INTSRC_ENERGY_DETECT)
                return IRQ_HANDLED;
 
-       /* Give PHY some time before MAC starts sending data. This works
-        * around an issue where network doesn't come up properly.
-        */
-       if (!(irq_status & INTSRC_LINK_DOWN))
-               phy_queue_state_machine(phydev, msecs_to_jiffies(100));
-       else
-               phy_trigger_machine(phydev);
+       phy_trigger_machine(phydev);
 
        return IRQ_HANDLED;
 }
index e78d0bf..38234d7 100644 (file)
@@ -2679,16 +2679,19 @@ static int lan8804_config_init(struct phy_device *phydev)
 static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev)
 {
        int irq_status, tsu_irq_status;
+       int ret = IRQ_NONE;
 
        irq_status = phy_read(phydev, LAN8814_INTS);
-       if (irq_status > 0 && (irq_status & LAN8814_INT_LINK))
-               phy_trigger_machine(phydev);
-
        if (irq_status < 0) {
                phy_error(phydev);
                return IRQ_NONE;
        }
 
+       if (irq_status & LAN8814_INT_LINK) {
+               phy_trigger_machine(phydev);
+               ret = IRQ_HANDLED;
+       }
+
        while (1) {
                tsu_irq_status = lanphy_read_page_reg(phydev, 4,
                                                      LAN8814_INTR_STS_REG);
@@ -2697,12 +2700,15 @@ static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev)
                    (tsu_irq_status & (LAN8814_INTR_STS_REG_1588_TSU0_ |
                                       LAN8814_INTR_STS_REG_1588_TSU1_ |
                                       LAN8814_INTR_STS_REG_1588_TSU2_ |
-                                      LAN8814_INTR_STS_REG_1588_TSU3_)))
+                                      LAN8814_INTR_STS_REG_1588_TSU3_))) {
                        lan8814_handle_ptp_interrupt(phydev);
-               else
+                       ret = IRQ_HANDLED;
+               } else {
                        break;
+               }
        }
-       return IRQ_HANDLED;
+
+       return ret;
 }
 
 static int lan8814_ack_interrupt(struct phy_device *phydev)
@@ -2873,12 +2879,18 @@ static int lan8814_config_init(struct phy_device *phydev)
        return 0;
 }
 
+/* It is expected that there will not be any 'lan8814_take_coma_mode'
+ * function called in suspend. Because the GPIO line can be shared, so if one of
+ * the phys goes back in coma mode, then all the other PHYs will go, which is
+ * wrong.
+ */
 static int lan8814_release_coma_mode(struct phy_device *phydev)
 {
        struct gpio_desc *gpiod;
 
        gpiod = devm_gpiod_get_optional(&phydev->mdio.dev, "coma-mode",
-                                       GPIOD_OUT_HIGH_OPEN_DRAIN);
+                                       GPIOD_OUT_HIGH_OPEN_DRAIN |
+                                       GPIOD_FLAGS_BIT_NONEXCLUSIVE);
        if (IS_ERR(gpiod))
                return PTR_ERR(gpiod);
 
index d4c93d5..8569a54 100644 (file)
 
 /* Interrupt Source Register */
 #define LAN87XX_INTERRUPT_SOURCE                (0x18)
+#define LAN87XX_INTERRUPT_SOURCE_2              (0x08)
 
 /* Interrupt Mask Register */
 #define LAN87XX_INTERRUPT_MASK                  (0x19)
 #define LAN87XX_MASK_LINK_UP                    (0x0004)
 #define LAN87XX_MASK_LINK_DOWN                  (0x0002)
 
+#define LAN87XX_INTERRUPT_MASK_2                (0x09)
+#define LAN87XX_MASK_COMM_RDY                  BIT(10)
+
 /* MISC Control 1 Register */
 #define LAN87XX_CTRL_1                          (0x11)
 #define LAN87XX_MASK_RGMII_TXC_DLY_EN           (0x4000)
@@ -424,17 +428,55 @@ static int lan87xx_phy_config_intr(struct phy_device *phydev)
        int rc, val = 0;
 
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
-               /* unmask all source and clear them before enable */
-               rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, 0x7FFF);
+               /* clear all interrupt */
+               rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
+               if (rc < 0)
+                       return rc;
+
                rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
-               val = LAN87XX_MASK_LINK_UP | LAN87XX_MASK_LINK_DOWN;
+               if (rc < 0)
+                       return rc;
+
+               rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+                                PHYACC_ATTR_BANK_MISC,
+                                LAN87XX_INTERRUPT_MASK_2, val);
+               if (rc < 0)
+                       return rc;
+
+               rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+                                PHYACC_ATTR_BANK_MISC,
+                                LAN87XX_INTERRUPT_SOURCE_2, 0);
+               if (rc < 0)
+                       return rc;
+
+               /* enable link down and comm ready interrupt */
+               val = LAN87XX_MASK_LINK_DOWN;
                rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
+               if (rc < 0)
+                       return rc;
+
+               val = LAN87XX_MASK_COMM_RDY;
+               rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+                                PHYACC_ATTR_BANK_MISC,
+                                LAN87XX_INTERRUPT_MASK_2, val);
        } else {
                rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
-               if (rc)
+               if (rc < 0)
                        return rc;
 
                rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
+               if (rc < 0)
+                       return rc;
+
+               rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
+                                PHYACC_ATTR_BANK_MISC,
+                                LAN87XX_INTERRUPT_MASK_2, val);
+               if (rc < 0)
+                       return rc;
+
+               rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+                                PHYACC_ATTR_BANK_MISC,
+                                LAN87XX_INTERRUPT_SOURCE_2, 0);
        }
 
        return rc < 0 ? rc : 0;
@@ -444,6 +486,14 @@ static irqreturn_t lan87xx_handle_interrupt(struct phy_device *phydev)
 {
        int irq_status;
 
+       irq_status  = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+                                 PHYACC_ATTR_BANK_MISC,
+                                 LAN87XX_INTERRUPT_SOURCE_2, 0);
+       if (irq_status < 0) {
+               phy_error(phydev);
+               return IRQ_NONE;
+       }
+
        irq_status = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
        if (irq_status < 0) {
                phy_error(phydev);
index 12ff276..4df8c33 100644 (file)
@@ -316,11 +316,13 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
 
        phydev->suspended_by_mdio_bus = 0;
 
-       /* If we manged to get here with the PHY state machine in a state neither
-        * PHY_HALTED nor PHY_READY this is an indication that something went wrong
-        * and we should most likely be using MAC managed PM and we are not.
+       /* If we managed to get here with the PHY state machine in a state
+        * neither PHY_HALTED, PHY_READY nor PHY_UP, this is an indication
+        * that something went wrong and we should most likely be using
+        * MAC managed PM, but we are not.
         */
-       WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY);
+       WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY &&
+               phydev->state != PHY_UP);
 
        ret = phy_init_hw(phydev);
        if (ret < 0)
index aac133a..154a3c0 100644 (file)
@@ -1275,10 +1275,12 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
                }
        }
 
-       netif_addr_lock_bh(dev);
-       dev_uc_sync_multiple(port_dev, dev);
-       dev_mc_sync_multiple(port_dev, dev);
-       netif_addr_unlock_bh(dev);
+       if (dev->flags & IFF_UP) {
+               netif_addr_lock_bh(dev);
+               dev_uc_sync_multiple(port_dev, dev);
+               dev_mc_sync_multiple(port_dev, dev);
+               netif_addr_unlock_bh(dev);
+       }
 
        port->index = -1;
        list_add_tail_rcu(&port->list, &team->port_list);
@@ -1349,8 +1351,10 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
        netdev_rx_handler_unregister(port_dev);
        team_port_disable_netpoll(port);
        vlan_vids_del_by_dev(port_dev, dev);
-       dev_uc_unsync(port_dev, dev);
-       dev_mc_unsync(port_dev, dev);
+       if (dev->flags & IFF_UP) {
+               dev_uc_unsync(port_dev, dev);
+               dev_mc_unsync(port_dev, dev);
+       }
        dev_close(port_dev);
        team_port_leave(team, port);
 
@@ -1700,6 +1704,14 @@ static int team_open(struct net_device *dev)
 
 static int team_close(struct net_device *dev)
 {
+       struct team *team = netdev_priv(dev);
+       struct team_port *port;
+
+       list_for_each_entry(port, &team->port_list, list) {
+               dev_uc_unsync(port->dev, dev);
+               dev_mc_unsync(port->dev, dev);
+       }
+
        return 0;
 }
 
index 259b2b8..db736b9 100644 (file)
@@ -2828,7 +2828,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                rcu_assign_pointer(tfile->tun, tun);
        }
 
-       netif_carrier_on(tun->dev);
+       if (ifr->ifr_flags & IFF_NO_CARRIER)
+               netif_carrier_off(tun->dev);
+       else
+               netif_carrier_on(tun->dev);
 
        /* Make sure persistent devices do not get stuck in
         * xoff state.
@@ -3056,8 +3059,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                 * This is needed because we never checked for invalid flags on
                 * TUNSETIFF.
                 */
-               return put_user(IFF_TUN | IFF_TAP | TUN_FEATURES,
-                               (unsigned int __user*)argp);
+               return put_user(IFF_TUN | IFF_TAP | IFF_NO_CARRIER |
+                               TUN_FEATURES, (unsigned int __user*)argp);
        } else if (cmd == TUNSETQUEUE) {
                return tun_set_queue(file, &ifr);
        } else if (cmd == SIOCGSKNS) {
index 2de09ad..e11f709 100644 (file)
@@ -777,6 +777,13 @@ static const struct usb_device_id  products[] = {
 },
 #endif
 
+/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* ThinkPad USB-C Dock (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
index 709e3c5..26c34a7 100644 (file)
@@ -1087,6 +1087,7 @@ static const struct usb_device_id products[] = {
        {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)},   /* Quectel EG12/EM12 */
        {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)},   /* Quectel EM160R-GL */
        {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)},   /* Quectel RM500Q-GL */
+       {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)},   /* Quectel RM520N */
 
        /* 3. Combined interface devices matching on interface number */
        {QMI_FIXED_INTF(0x0408, 0xea42, 4)},    /* Yota / Megafon M100-1 */
@@ -1401,6 +1402,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81b3, 8)},    /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
        {QMI_FIXED_INTF(0x413c, 0x81b6, 8)},    /* Dell Wireless 5811e */
        {QMI_FIXED_INTF(0x413c, 0x81b6, 10)},   /* Dell Wireless 5811e */
+       {QMI_FIXED_INTF(0x413c, 0x81c2, 8)},    /* Dell Wireless 5811e */
        {QMI_FIXED_INTF(0x413c, 0x81cc, 8)},    /* Dell Wireless 5816e */
        {QMI_FIXED_INTF(0x413c, 0x81d7, 0)},    /* Dell Wireless 5821e */
        {QMI_FIXED_INTF(0x413c, 0x81d7, 1)},    /* Dell Wireless 5821e preproduction config */
index d142ac8..688905e 100644 (file)
@@ -770,6 +770,7 @@ enum rtl8152_flags {
        RX_EPROTO,
 };
 
+#define DEVICE_ID_THINKPAD_ONELINK_PLUS_DOCK           0x3054
 #define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2      0x3082
 #define DEVICE_ID_THINKPAD_USB_C_DONGLE                        0x720c
 #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2             0xa387
@@ -9581,6 +9582,7 @@ static bool rtl8152_supports_lenovo_macpassthru(struct usb_device *udev)
 
        if (vendor_id == VENDOR_ID_LENOVO) {
                switch (product_id) {
+               case DEVICE_ID_THINKPAD_ONELINK_PLUS_DOCK:
                case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2:
                case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
                case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3:
@@ -9828,6 +9830,7 @@ static const struct usb_device_id rtl8152_table[] = {
        REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927),
        REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f),
+       REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3054),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3069),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3082),
index aaa89b4..e368b07 100644 (file)
@@ -1598,6 +1598,7 @@ void usbnet_disconnect (struct usb_interface *intf)
        struct usbnet           *dev;
        struct usb_device       *xdev;
        struct net_device       *net;
+       struct urb              *urb;
 
        dev = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
@@ -1614,7 +1615,11 @@ void usbnet_disconnect (struct usb_interface *intf)
        net = dev->net;
        unregister_netdev (net);
 
-       usb_scuttle_anchored_urbs(&dev->deferred);
+       while ((urb = usb_get_from_anchor(&dev->deferred))) {
+               dev_kfree_skb(urb->context);
+               kfree(urb->sg);
+               usb_free_urb(urb);
+       }
 
        if (dev->driver_info->unbind)
                dev->driver_info->unbind(dev, intf);
index d0f3b6d..5c804bc 100644 (file)
@@ -436,14 +436,13 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs)
        if (attrs[WGPEER_A_ENDPOINT]) {
                struct sockaddr *addr = nla_data(attrs[WGPEER_A_ENDPOINT]);
                size_t len = nla_len(attrs[WGPEER_A_ENDPOINT]);
+               struct endpoint endpoint = { { { 0 } } };
 
-               if ((len == sizeof(struct sockaddr_in) &&
-                    addr->sa_family == AF_INET) ||
-                   (len == sizeof(struct sockaddr_in6) &&
-                    addr->sa_family == AF_INET6)) {
-                       struct endpoint endpoint = { { { 0 } } };
-
-                       memcpy(&endpoint.addr, addr, len);
+               if (len == sizeof(struct sockaddr_in) && addr->sa_family == AF_INET) {
+                       endpoint.addr4 = *(struct sockaddr_in *)addr;
+                       wg_socket_set_peer_endpoint(peer, &endpoint);
+               } else if (len == sizeof(struct sockaddr_in6) && addr->sa_family == AF_INET6) {
+                       endpoint.addr6 = *(struct sockaddr_in6 *)addr;
                        wg_socket_set_peer_endpoint(peer, &endpoint);
                }
        }
index ba87d29..d4bb40a 100644 (file)
@@ -6,29 +6,28 @@
 #ifdef DEBUG
 
 #include <linux/jiffies.h>
-#include <linux/hrtimer.h>
 
 static const struct {
        bool result;
-       u64 nsec_to_sleep_before;
+       unsigned int msec_to_sleep_before;
 } expected_results[] __initconst = {
        [0 ... PACKETS_BURSTABLE - 1] = { true, 0 },
        [PACKETS_BURSTABLE] = { false, 0 },
-       [PACKETS_BURSTABLE + 1] = { true, NSEC_PER_SEC / PACKETS_PER_SECOND },
+       [PACKETS_BURSTABLE + 1] = { true, MSEC_PER_SEC / PACKETS_PER_SECOND },
        [PACKETS_BURSTABLE + 2] = { false, 0 },
-       [PACKETS_BURSTABLE + 3] = { true, (NSEC_PER_SEC / PACKETS_PER_SECOND) * 2 },
+       [PACKETS_BURSTABLE + 3] = { true, (MSEC_PER_SEC / PACKETS_PER_SECOND) * 2 },
        [PACKETS_BURSTABLE + 4] = { true, 0 },
        [PACKETS_BURSTABLE + 5] = { false, 0 }
 };
 
 static __init unsigned int maximum_jiffies_at_index(int index)
 {
-       u64 total_nsecs = 2 * NSEC_PER_SEC / PACKETS_PER_SECOND / 3;
+       unsigned int total_msecs = 2 * MSEC_PER_SEC / PACKETS_PER_SECOND / 3;
        int i;
 
        for (i = 0; i <= index; ++i)
-               total_nsecs += expected_results[i].nsec_to_sleep_before;
-       return nsecs_to_jiffies(total_nsecs);
+               total_msecs += expected_results[i].msec_to_sleep_before;
+       return msecs_to_jiffies(total_msecs);
 }
 
 static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4,
@@ -43,12 +42,8 @@ static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4,
        loop_start_time = jiffies;
 
        for (i = 0; i < ARRAY_SIZE(expected_results); ++i) {
-               if (expected_results[i].nsec_to_sleep_before) {
-                       ktime_t timeout = ktime_add(ktime_add_ns(ktime_get_coarse_boottime(), TICK_NSEC * 4 / 3),
-                                                   ns_to_ktime(expected_results[i].nsec_to_sleep_before));
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_hrtimeout_range_clock(&timeout, 0, HRTIMER_MODE_ABS, CLOCK_BOOTTIME);
-               }
+               if (expected_results[i].msec_to_sleep_before)
+                       msleep(expected_results[i].msec_to_sleep_before);
 
                if (time_is_before_jiffies(loop_start_time +
                                           maximum_jiffies_at_index(i)))
@@ -132,7 +127,7 @@ bool __init wg_ratelimiter_selftest(void)
        if (IS_ENABLED(CONFIG_KASAN) || IS_ENABLED(CONFIG_UBSAN))
                return true;
 
-       BUILD_BUG_ON(NSEC_PER_SEC % PACKETS_PER_SECOND != 0);
+       BUILD_BUG_ON(MSEC_PER_SEC % PACKETS_PER_SECOND != 0);
 
        if (wg_ratelimiter_init())
                goto out;
@@ -172,7 +167,7 @@ bool __init wg_ratelimiter_selftest(void)
        ++test;
 #endif
 
-       for (trials = TRIALS_BEFORE_GIVING_UP;;) {
+       for (trials = TRIALS_BEFORE_GIVING_UP; IS_ENABLED(DEBUG_RATELIMITER_TIMINGS);) {
                int test_count = 0, ret;
 
                ret = timings_test(skb4, hdr4, skb6, hdr6, &test_count);
index c62f299..d8a5dbf 100644 (file)
@@ -2403,7 +2403,7 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta,
                /* Repeat initial/next rate.
                 * For legacy IL_NUMBER_TRY == 1, this loop will not execute.
                 * For HT IL_HT_NUMBER_TRY == 3, this executes twice. */
-               while (repeat_rate > 0) {
+               while (repeat_rate > 0 && idx < (LINK_QUAL_MAX_RETRY_NUM - 1)) {
                        if (is_legacy(tbl_type.lq_type)) {
                                if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
                                        ant_toggle_cnt++;
@@ -2422,8 +2422,6 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta,
                            cpu_to_le32(new_rate);
                        repeat_rate--;
                        idx++;
-                       if (idx >= LINK_QUAL_MAX_RETRY_NUM)
-                               goto out;
                }
 
                il4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
@@ -2468,7 +2466,6 @@ il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta,
                repeat_rate--;
        }
 
-out:
        lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
        lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
 
index a647a40..b20409f 100644 (file)
@@ -140,6 +140,7 @@ config IWLMEI
        depends on INTEL_MEI
        depends on PM
        depends on CFG80211
+       depends on BROKEN
        help
          Enables the iwlmei kernel module.
 
index 5eb28f8..11536f1 100644 (file)
@@ -1833,8 +1833,8 @@ static void iwl_mvm_parse_ppe(struct iwl_mvm *mvm,
        * If nss < MAX: we can set zeros in other streams
        */
        if (nss > MAX_HE_SUPP_NSS) {
-               IWL_INFO(mvm, "Got NSS = %d - trimming to %d\n", nss,
-                        MAX_HE_SUPP_NSS);
+               IWL_DEBUG_INFO(mvm, "Got NSS = %d - trimming to %d\n", nss,
+                              MAX_HE_SUPP_NSS);
                nss = MAX_HE_SUPP_NSS;
        }
 
index 6e55f15..1f301a5 100644 (file)
@@ -5060,6 +5060,10 @@ static int hwsim_virtio_handle_cmd(struct sk_buff *skb)
 
        nlh = nlmsg_hdr(skb);
        gnlh = nlmsg_data(nlh);
+
+       if (skb->len < nlh->nlmsg_len)
+               return -EINVAL;
+
        err = genlmsg_parse(nlh, &hwsim_genl_family, tb, HWSIM_ATTR_MAX,
                            hwsim_genl_policy, NULL);
        if (err) {
@@ -5102,7 +5106,8 @@ static void hwsim_virtio_rx_work(struct work_struct *work)
        spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
 
        skb->data = skb->head;
-       skb_set_tail_pointer(skb, len);
+       skb_reset_tail_pointer(skb);
+       skb_put(skb, len);
        hwsim_virtio_handle_cmd(skb);
 
        spin_lock_irqsave(&hwsim_virtio_lock, flags);
index 253cbc1..6de13d6 100644 (file)
@@ -267,7 +267,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
        }
        vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
        vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
-       vht_cap->vht_mcs.tx_highest |=
+       if (ieee80211_hw_check(phy->hw, SUPPORTS_VHT_EXT_NSS_BW))
+               vht_cap->vht_mcs.tx_highest |=
                                cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
 }
 
index ad6c7d6..d6aae60 100644 (file)
@@ -1088,7 +1088,7 @@ u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid)
        offset %= 32;
 
        val = mt76_rr(dev, addr);
-       val >>= (tid % 32);
+       val >>= offset;
 
        if (offset > 20) {
                addr += 4;
index e180067..576a014 100644 (file)
@@ -261,7 +261,7 @@ int mt7921e_mac_reset(struct mt7921_dev *dev)
 
        err = mt7921e_driver_own(dev);
        if (err)
-               return err;
+               goto out;
 
        err = mt7921_run_firmware(dev);
        if (err)
index 43c085c..bb1a315 100644 (file)
@@ -245,6 +245,7 @@ struct wilc {
        u8 *rx_buffer;
        u32 rx_buffer_offset;
        u8 *tx_buffer;
+       u32 *vmm_table;
 
        struct txq_handle txq[NQUEUES];
        int txq_entries;
index 600cc57..7390f94 100644 (file)
@@ -28,6 +28,7 @@ struct wilc_sdio {
        u32 block_size;
        bool isinit;
        int has_thrpt_enh3;
+       u8 *cmd53_buf;
 };
 
 struct sdio_cmd52 {
@@ -47,6 +48,7 @@ struct sdio_cmd53 {
        u32 count:              9;
        u8 *buffer;
        u32 block_size;
+       bool use_global_buf;
 };
 
 static const struct wilc_hif_func wilc_hif_sdio;
@@ -91,6 +93,8 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
 {
        struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
        int size, ret;
+       struct wilc_sdio *sdio_priv = wilc->bus_data;
+       u8 *buf = cmd->buffer;
 
        sdio_claim_host(func);
 
@@ -101,12 +105,23 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
        else
                size = cmd->count;
 
+       if (cmd->use_global_buf) {
+               if (size > sizeof(u32))
+                       return -EINVAL;
+
+               buf = sdio_priv->cmd53_buf;
+       }
+
        if (cmd->read_write) {  /* write */
-               ret = sdio_memcpy_toio(func, cmd->address,
-                                      (void *)cmd->buffer, size);
+               if (cmd->use_global_buf)
+                       memcpy(buf, cmd->buffer, size);
+
+               ret = sdio_memcpy_toio(func, cmd->address, buf, size);
        } else {        /* read */
-               ret = sdio_memcpy_fromio(func, (void *)cmd->buffer,
-                                        cmd->address,  size);
+               ret = sdio_memcpy_fromio(func, buf, cmd->address, size);
+
+               if (cmd->use_global_buf)
+                       memcpy(cmd->buffer, buf, size);
        }
 
        sdio_release_host(func);
@@ -128,6 +143,12 @@ static int wilc_sdio_probe(struct sdio_func *func,
        if (!sdio_priv)
                return -ENOMEM;
 
+       sdio_priv->cmd53_buf = kzalloc(sizeof(u32), GFP_KERNEL);
+       if (!sdio_priv->cmd53_buf) {
+               ret = -ENOMEM;
+               goto free;
+       }
+
        ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
                                 &wilc_hif_sdio);
        if (ret)
@@ -161,6 +182,7 @@ dispose_irq:
        irq_dispose_mapping(wilc->dev_irq_num);
        wilc_netdev_cleanup(wilc);
 free:
+       kfree(sdio_priv->cmd53_buf);
        kfree(sdio_priv);
        return ret;
 }
@@ -172,6 +194,7 @@ static void wilc_sdio_remove(struct sdio_func *func)
 
        clk_disable_unprepare(wilc->rtc_clk);
        wilc_netdev_cleanup(wilc);
+       kfree(sdio_priv->cmd53_buf);
        kfree(sdio_priv);
 }
 
@@ -375,8 +398,9 @@ static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
                cmd.address = WILC_SDIO_FBR_DATA_REG;
                cmd.block_mode = 0;
                cmd.increment = 1;
-               cmd.count = 4;
+               cmd.count = sizeof(u32);
                cmd.buffer = (u8 *)&data;
+               cmd.use_global_buf = true;
                cmd.block_size = sdio_priv->block_size;
                ret = wilc_sdio_cmd53(wilc, &cmd);
                if (ret)
@@ -414,6 +438,7 @@ static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
        nblk = size / block_size;
        nleft = size % block_size;
 
+       cmd.use_global_buf = false;
        if (nblk > 0) {
                cmd.block_mode = 1;
                cmd.increment = 1;
@@ -492,8 +517,9 @@ static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
                cmd.address = WILC_SDIO_FBR_DATA_REG;
                cmd.block_mode = 0;
                cmd.increment = 1;
-               cmd.count = 4;
+               cmd.count = sizeof(u32);
                cmd.buffer = (u8 *)data;
+               cmd.use_global_buf = true;
 
                cmd.block_size = sdio_priv->block_size;
                ret = wilc_sdio_cmd53(wilc, &cmd);
@@ -535,6 +561,7 @@ static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
        nblk = size / block_size;
        nleft = size % block_size;
 
+       cmd.use_global_buf = false;
        if (nblk > 0) {
                cmd.block_mode = 1;
                cmd.increment = 1;
index 947d9a0..58bbf50 100644 (file)
@@ -714,7 +714,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
        int ret = 0;
        int counter;
        int timeout;
-       u32 vmm_table[WILC_VMM_TBL_SIZE];
+       u32 *vmm_table = wilc->vmm_table;
        u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};
        const struct wilc_hif_func *func;
        int srcu_idx;
@@ -1252,6 +1252,8 @@ void wilc_wlan_cleanup(struct net_device *dev)
        while ((rqe = wilc_wlan_rxq_remove(wilc)))
                kfree(rqe);
 
+       kfree(wilc->vmm_table);
+       wilc->vmm_table = NULL;
        kfree(wilc->rx_buffer);
        wilc->rx_buffer = NULL;
        kfree(wilc->tx_buffer);
@@ -1489,6 +1491,14 @@ int wilc_wlan_init(struct net_device *dev)
                        goto fail;
        }
 
+       if (!wilc->vmm_table)
+               wilc->vmm_table = kzalloc(WILC_VMM_TBL_SIZE, GFP_KERNEL);
+
+       if (!wilc->vmm_table) {
+               ret = -ENOBUFS;
+               goto fail;
+       }
+
        if (!wilc->tx_buffer)
                wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL);
 
@@ -1513,7 +1523,8 @@ int wilc_wlan_init(struct net_device *dev)
        return 0;
 
 fail:
-
+       kfree(wilc->vmm_table);
+       wilc->vmm_table = NULL;
        kfree(wilc->rx_buffer);
        wilc->rx_buffer = NULL;
        kfree(wilc->tx_buffer);
index 990360d..e85b3c5 100644 (file)
@@ -256,7 +256,6 @@ static void backend_disconnect(struct backend_info *be)
                unsigned int queue_index;
 
                xen_unregister_watchers(vif);
-               xenbus_rm(XBT_NIL, be->dev->nodename, "hotplug-status");
 #ifdef CONFIG_DEBUG_FS
                xenvif_debugfs_delif(vif);
 #endif /* CONFIG_DEBUG_FS */
@@ -984,6 +983,7 @@ static int netback_remove(struct xenbus_device *dev)
        struct backend_info *be = dev_get_drvdata(&dev->dev);
 
        unregister_hotplug_status_watch(be);
+       xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
        if (be->vif) {
                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
                backend_disconnect(be);
index bf4f5c0..bbe5099 100644 (file)
@@ -1712,8 +1712,6 @@ static struct device *create_namespace_pmem(struct nd_region *nd_region,
        res->flags = IORESOURCE_MEM;
 
        for (i = 0; i < nd_region->ndr_mappings; i++) {
-               uuid_t uuid;
-
                nsl_get_uuid(ndd, nd_label, &uuid);
                if (has_uuid_at_pos(nd_region, &uuid, cookie, i))
                        continue;
index 7e88cd2..96e6e9a 100644 (file)
@@ -45,7 +45,7 @@ static struct nd_region *to_region(struct pmem_device *pmem)
        return to_nd_region(to_dev(pmem)->parent);
 }
 
-static phys_addr_t to_phys(struct pmem_device *pmem, phys_addr_t offset)
+static phys_addr_t pmem_to_phys(struct pmem_device *pmem, phys_addr_t offset)
 {
        return pmem->phys_addr + offset;
 }
@@ -63,7 +63,7 @@ static phys_addr_t to_offset(struct pmem_device *pmem, sector_t sector)
 static void pmem_mkpage_present(struct pmem_device *pmem, phys_addr_t offset,
                unsigned int len)
 {
-       phys_addr_t phys = to_phys(pmem, offset);
+       phys_addr_t phys = pmem_to_phys(pmem, offset);
        unsigned long pfn_start, pfn_end, pfn;
 
        /* only pmem in the linear map supports HWPoison */
@@ -97,7 +97,7 @@ static void pmem_clear_bb(struct pmem_device *pmem, sector_t sector, long blks)
 static long __pmem_clear_poison(struct pmem_device *pmem,
                phys_addr_t offset, unsigned int len)
 {
-       phys_addr_t phys = to_phys(pmem, offset);
+       phys_addr_t phys = pmem_to_phys(pmem, offset);
        long cleared = nvdimm_clear_poison(to_dev(pmem), phys, len);
 
        if (cleared > 0) {
index af367b2..8d5a7ae 100644 (file)
@@ -2162,14 +2162,14 @@ static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
 
 static int nvme_pr_clear(struct block_device *bdev, u64 key)
 {
-       u32 cdw10 = 1 | (key ? 1 << 3 : 0);
+       u32 cdw10 = 1 | (key ? 0 : 1 << 3);
 
-       return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_register);
+       return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
 }
 
 static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
 {
-       u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 1 << 3 : 0);
+       u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 0 : 1 << 3);
 
        return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
 }
@@ -4703,6 +4703,8 @@ static void nvme_fw_act_work(struct work_struct *work)
        nvme_start_queues(ctrl);
        /* read FW slot information to clear the AER */
        nvme_get_fw_slot_info(ctrl);
+
+       queue_work(nvme_wq, &ctrl->async_event_work);
 }
 
 static u32 nvme_aer_type(u32 result)
@@ -4715,9 +4717,10 @@ static u32 nvme_aer_subtype(u32 result)
        return (result & 0xff00) >> 8;
 }
 
-static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
+static bool nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
 {
        u32 aer_notice_type = nvme_aer_subtype(result);
+       bool requeue = true;
 
        trace_nvme_async_event(ctrl, aer_notice_type);
 
@@ -4734,6 +4737,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
                 */
                if (nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) {
                        nvme_auth_stop(ctrl);
+                       requeue = false;
                        queue_work(nvme_wq, &ctrl->fw_act_work);
                }
                break;
@@ -4750,6 +4754,7 @@ static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
        default:
                dev_warn(ctrl->device, "async event result %08x\n", result);
        }
+       return requeue;
 }
 
 static void nvme_handle_aer_persistent_error(struct nvme_ctrl *ctrl)
@@ -4765,13 +4770,14 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
        u32 result = le32_to_cpu(res->u32);
        u32 aer_type = nvme_aer_type(result);
        u32 aer_subtype = nvme_aer_subtype(result);
+       bool requeue = true;
 
        if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS)
                return;
 
        switch (aer_type) {
        case NVME_AER_NOTICE:
-               nvme_handle_aen_notice(ctrl, result);
+               requeue = nvme_handle_aen_notice(ctrl, result);
                break;
        case NVME_AER_ERROR:
                /*
@@ -4792,7 +4798,9 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
        default:
                break;
        }
-       queue_work(nvme_wq, &ctrl->async_event_work);
+
+       if (requeue)
+               queue_work(nvme_wq, &ctrl->async_event_work);
 }
 EXPORT_SYMBOL_GPL(nvme_complete_async_event);
 
index 3a1c37f..67d3335 100644 (file)
@@ -3470,6 +3470,10 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_DEVICE(0x1987, 0x5016),   /* Phison E16 */
                .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN |
                                NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1987, 0x5019),  /* phison E19 */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x1987, 0x5021),   /* Phison E21 */
+               .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x1b4b, 0x1092),   /* Lexar 256 GB SSD */
                .driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
@@ -3517,6 +3521,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
        { PCI_DEVICE(0xc0a9, 0x540a),   /* Crucial P2 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1d97, 0x2263), /* Lexar NM610 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061),
                .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065),
index 044da18..d5871fd 100644 (file)
@@ -121,7 +121,6 @@ struct nvme_tcp_queue {
        struct mutex            send_mutex;
        struct llist_head       req_list;
        struct list_head        send_list;
-       bool                    more_requests;
 
        /* recv state */
        void                    *pdu;
@@ -320,7 +319,7 @@ static inline void nvme_tcp_send_all(struct nvme_tcp_queue *queue)
 static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
 {
        return !list_empty(&queue->send_list) ||
-               !llist_empty(&queue->req_list) || queue->more_requests;
+               !llist_empty(&queue->req_list);
 }
 
 static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
@@ -339,9 +338,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
         */
        if (queue->io_cpu == raw_smp_processor_id() &&
            sync && empty && mutex_trylock(&queue->send_mutex)) {
-               queue->more_requests = !last;
                nvme_tcp_send_all(queue);
-               queue->more_requests = false;
                mutex_unlock(&queue->send_mutex);
        }
 
@@ -1229,7 +1226,7 @@ static void nvme_tcp_io_work(struct work_struct *w)
                else if (unlikely(result < 0))
                        return;
 
-               if (!pending)
+               if (!pending || !queue->rd_enabled)
                        return;
 
        } while (!time_after(jiffies, deadline)); /* quota is exhausted */
index cf690df..c4113b4 100644 (file)
@@ -196,6 +196,7 @@ int nvmet_setup_auth(struct nvmet_ctrl *ctrl)
        if (IS_ERR(ctrl->ctrl_key)) {
                ret = PTR_ERR(ctrl->ctrl_key);
                ctrl->ctrl_key = NULL;
+               goto out_free_hash;
        }
        pr_debug("%s: using ctrl hash %s key %*ph\n", __func__,
                 ctrl->ctrl_key->hash > 0 ?
index a134579..7f4083c 100644 (file)
@@ -735,6 +735,8 @@ static void nvmet_set_error(struct nvmet_req *req, u16 status)
 
 static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 {
+       struct nvmet_ns *ns = req->ns;
+
        if (!req->sq->sqhd_disabled)
                nvmet_update_sq_head(req);
        req->cqe->sq_id = cpu_to_le16(req->sq->qid);
@@ -745,9 +747,9 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 
        trace_nvmet_req_complete(req);
 
-       if (req->ns)
-               nvmet_put_namespace(req->ns);
        req->ops->queue_response(req);
+       if (ns)
+               nvmet_put_namespace(ns);
 }
 
 void nvmet_req_complete(struct nvmet_req *req, u16 status)
index dc3b4dc..a3694a3 100644 (file)
@@ -1506,6 +1506,9 @@ static void nvmet_tcp_state_change(struct sock *sk)
                goto done;
 
        switch (sk->sk_state) {
+       case TCP_FIN_WAIT2:
+       case TCP_LAST_ACK:
+               break;
        case TCP_FIN_WAIT1:
        case TCP_CLOSE_WAIT:
        case TCP_CLOSE:
index c7ef69f..835bfda 100644 (file)
@@ -100,6 +100,7 @@ void nvmet_execute_identify_cns_cs_ns(struct nvmet_req *req)
        struct nvme_id_ns_zns *id_zns;
        u64 zsze;
        u16 status;
+       u32 mar, mor;
 
        if (le32_to_cpu(req->cmd->identify.nsid) == NVME_NSID_ALL) {
                req->error_loc = offsetof(struct nvme_identify, nsid);
@@ -130,8 +131,20 @@ void nvmet_execute_identify_cns_cs_ns(struct nvmet_req *req)
        zsze = (bdev_zone_sectors(req->ns->bdev) << 9) >>
                                        req->ns->blksize_shift;
        id_zns->lbafe[0].zsze = cpu_to_le64(zsze);
-       id_zns->mor = cpu_to_le32(bdev_max_open_zones(req->ns->bdev));
-       id_zns->mar = cpu_to_le32(bdev_max_active_zones(req->ns->bdev));
+
+       mor = bdev_max_open_zones(req->ns->bdev);
+       if (!mor)
+               mor = U32_MAX;
+       else
+               mor--;
+       id_zns->mor = cpu_to_le32(mor);
+
+       mar = bdev_max_active_zones(req->ns->bdev);
+       if (!mar)
+               mar = U32_MAX;
+       else
+               mar--;
+       id_zns->mar = cpu_to_le32(mar);
 
 done:
        status = nvmet_copy_to_sgl(req, 0, id_zns, sizeof(*id_zns));
index 7bc9292..1c573e7 100644 (file)
@@ -314,7 +314,7 @@ static int unflatten_dt_nodes(const void *blob,
        for (offset = 0;
             offset >= 0 && depth >= initial_depth;
             offset = fdt_next_node(blob, offset, &depth)) {
-               if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
+               if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH - 1))
                        continue;
 
                if (!IS_ENABLED(CONFIG_OF_KOBJ) &&
index 77d1ba3..e87567d 100644 (file)
@@ -873,7 +873,7 @@ int dev_pm_opp_config_clks_simple(struct device *dev,
                }
        }
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_config_clks_simple);
 
index f223afe..a663860 100644 (file)
@@ -1546,6 +1546,7 @@ static int __init ccio_probe(struct parisc_device *dev)
        }
        ccio_ioc_init(ioc);
        if (ccio_init_resources(ioc)) {
+               iounmap(ioc->ioc_regs);
                kfree(ioc);
                return -ENOMEM;
        }
index 3a8c986..bdef7a8 100644 (file)
@@ -221,16 +221,7 @@ static size_t irt_num_entry;
 
 static struct irt_entry *iosapic_alloc_irt(int num_entries)
 {
-       unsigned long a;
-
-       /* The IRT needs to be 8-byte aligned for the PDC call. 
-        * Normally kmalloc would guarantee larger alignment, but
-        * if CONFIG_DEBUG_SLAB is enabled, then we can get only
-        * 4-byte alignment on 32-bit kernels
-        */
-       a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
-       a = (a + 7UL) & ~7UL;
-       return (struct irt_entry *)a;
+       return kcalloc(num_entries, sizeof(struct irt_entry), GFP_KERNEL);
 }
 
 /**
index 1925ddc..731c5d8 100644 (file)
@@ -523,7 +523,7 @@ static int aspeed_peci_probe(struct platform_device *pdev)
                return PTR_ERR(priv->base);
 
        priv->irq = platform_get_irq(pdev, 0);
-       if (!priv->irq)
+       if (priv->irq < 0)
                return priv->irq;
 
        ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler,
index 68eb61c..de4a7b3 100644 (file)
@@ -188,8 +188,6 @@ static void adev_release(struct device *dev)
 {
        struct auxiliary_device *adev = to_auxiliary_dev(dev);
 
-       auxiliary_device_uninit(adev);
-
        kfree(adev->name);
        kfree(adev);
 }
@@ -234,6 +232,7 @@ static void unregister_adev(void *_adev)
        struct auxiliary_device *adev = _adev;
 
        auxiliary_device_delete(adev);
+       auxiliary_device_uninit(adev);
 }
 
 static int devm_adev_add(struct device *dev, int idx)
index 80d8309..b80a9b7 100644 (file)
@@ -36,7 +36,7 @@
 #define CMN_CI_CHILD_COUNT             GENMASK_ULL(15, 0)
 #define CMN_CI_CHILD_PTR_OFFSET                GENMASK_ULL(31, 16)
 
-#define CMN_CHILD_NODE_ADDR            GENMASK(27, 0)
+#define CMN_CHILD_NODE_ADDR            GENMASK(29, 0)
 #define CMN_CHILD_NODE_EXTERNAL                BIT(31)
 
 #define CMN_MAX_DIMENSION              12
index a36698a..4a15c86 100644 (file)
@@ -639,6 +639,7 @@ static int dsu_pmu_dt_get_cpus(struct device *dev, cpumask_t *mask)
 static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask)
 {
 #ifdef CONFIG_ACPI
+       struct acpi_device *parent_adev = acpi_dev_parent(ACPI_COMPANION(dev));
        int cpu;
 
        /*
@@ -653,8 +654,7 @@ static int dsu_pmu_acpi_get_cpus(struct device *dev, cpumask_t *mask)
                        continue;
 
                acpi_dev = ACPI_COMPANION(cpu_dev);
-               if (acpi_dev &&
-                       acpi_dev->parent == ACPI_COMPANION(dev)->parent)
+               if (acpi_dev && acpi_dev_parent(acpi_dev) == parent_adev)
                        cpumask_set_cpu(cpu, mask);
        }
 #endif
index 513de1f..933b96e 100644 (file)
@@ -117,7 +117,7 @@ static int pmu_parse_irqs(struct arm_pmu *pmu)
 
        if (num_irqs == 1) {
                int irq = platform_get_irq(pdev, 0);
-               if (irq && irq_is_percpu_devid(irq))
+               if ((irq > 0) && irq_is_percpu_devid(irq))
                        return pmu_parse_percpu_irq(pmu, irq);
        }
 
index 30234c2..aaca6db 100644 (file)
@@ -840,16 +840,16 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev->parent);
        struct platform_device *sdev = to_platform_device(dev);
-       struct acpi_device *adev = ACPI_COMPANION(dev);
        struct l2cache_pmu *l2cache_pmu = data;
        struct cluster_pmu *cluster;
-       unsigned long fw_cluster_id;
+       u64 fw_cluster_id;
        int err;
        int irq;
 
-       if (!adev || kstrtoul(adev->pnp.unique_id, 10, &fw_cluster_id) < 0) {
+       err = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &fw_cluster_id);
+       if (err) {
                dev_err(&pdev->dev, "unable to read ACPI uid\n");
-               return -ENODEV;
+               return err;
        }
 
        cluster = devm_kzalloc(&pdev->dev, sizeof(*cluster), GFP_KERNEL);
@@ -879,7 +879,7 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data)
        }
 
        dev_info(&pdev->dev,
-               "Registered L2 cache PMU cluster %ld\n", fw_cluster_id);
+                "Registered L2 cache PMU cluster %lld\n", fw_cluster_id);
 
        spin_lock_init(&cluster->pmu_lock);
 
index 1ff2ff6..346311a 100644 (file)
@@ -742,7 +742,8 @@ static int qcom_l3_cache_pmu_probe(struct platform_device *pdev)
 
        l3pmu = devm_kzalloc(&pdev->dev, sizeof(*l3pmu), GFP_KERNEL);
        name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "l3cache_%s_%s",
-                     acpi_dev->parent->pnp.unique_id, acpi_dev->pnp.unique_id);
+                     acpi_dev_parent(acpi_dev)->pnp.unique_id,
+                     acpi_dev->pnp.unique_id);
        if (!l3pmu || !name)
                return -ENOMEM;
 
index 6f6681b..8de4ca2 100644 (file)
@@ -473,7 +473,7 @@ static int pmu_sbi_get_ctrinfo(int nctr)
        if (!pmu_ctr_list)
                return -ENOMEM;
 
-       for (i = 0; i <= nctr; i++) {
+       for (i = 0; i < nctr; i++) {
                ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_GET_INFO, i, 0, 0, 0, 0, 0);
                if (ret.error)
                        /* The logical counter ids are not expected to be contiguous */
index a4d7d9b..67712c7 100644 (file)
@@ -274,7 +274,6 @@ struct mvebu_a3700_comphy_lane {
        int submode;
        bool invert_tx;
        bool invert_rx;
-       bool needs_reset;
 };
 
 struct gbe_phy_init_data_fix {
@@ -1097,40 +1096,12 @@ mvebu_a3700_comphy_pcie_power_off(struct mvebu_a3700_comphy_lane *lane)
                            0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT);
 }
 
-static int mvebu_a3700_comphy_reset(struct phy *phy)
+static void mvebu_a3700_comphy_usb3_power_off(struct mvebu_a3700_comphy_lane *lane)
 {
-       struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
-       u16 mask, data;
-
-       dev_dbg(lane->dev, "resetting lane %d\n", lane->id);
-
-       /* COMPHY reset for internal logic */
-       comphy_lane_reg_set(lane, COMPHY_SFT_RESET,
-                           SFT_RST_NO_REG, SFT_RST_NO_REG);
-
-       /* COMPHY register reset (cleared automatically) */
-       comphy_lane_reg_set(lane, COMPHY_SFT_RESET, SFT_RST, SFT_RST);
-
-       /* PIPE soft and register reset */
-       data = PIPE_SOFT_RESET | PIPE_REG_RESET;
-       mask = data;
-       comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask);
-
-       /* Release PIPE register reset */
-       comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL,
-                           0x0, PIPE_REG_RESET);
-
-       /* Reset SB configuration register (only for lanes 0 and 1) */
-       if (lane->id == 0 || lane->id == 1) {
-               u32 mask, data;
-
-               data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT |
-                      PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT;
-               mask = data | PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT;
-               comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
-       }
-
-       return 0;
+       /*
+        * The USB3 MAC sets the USB3 PHY to low state, so we do not
+        * need to power off USB3 PHY again.
+        */
 }
 
 static bool mvebu_a3700_comphy_check_mode(int lane,
@@ -1171,10 +1142,6 @@ static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode,
            (lane->mode != mode || lane->submode != submode))
                return -EBUSY;
 
-       /* If changing mode, ensure reset is called */
-       if (lane->mode != PHY_MODE_INVALID && lane->mode != mode)
-               lane->needs_reset = true;
-
        /* Just remember the mode, ->power_on() will do the real setup */
        lane->mode = mode;
        lane->submode = submode;
@@ -1185,7 +1152,6 @@ static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode,
 static int mvebu_a3700_comphy_power_on(struct phy *phy)
 {
        struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
-       int ret;
 
        if (!mvebu_a3700_comphy_check_mode(lane->id, lane->mode,
                                           lane->submode)) {
@@ -1193,14 +1159,6 @@ static int mvebu_a3700_comphy_power_on(struct phy *phy)
                return -EINVAL;
        }
 
-       if (lane->needs_reset) {
-               ret = mvebu_a3700_comphy_reset(phy);
-               if (ret)
-                       return ret;
-
-               lane->needs_reset = false;
-       }
-
        switch (lane->mode) {
        case PHY_MODE_USB_HOST_SS:
                dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id);
@@ -1224,38 +1182,28 @@ static int mvebu_a3700_comphy_power_off(struct phy *phy)
 {
        struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
 
-       switch (lane->mode) {
-       case PHY_MODE_USB_HOST_SS:
-               /*
-                * The USB3 MAC sets the USB3 PHY to low state, so we do not
-                * need to power off USB3 PHY again.
-                */
-               break;
-
-       case PHY_MODE_SATA:
-               mvebu_a3700_comphy_sata_power_off(lane);
-               break;
-
-       case PHY_MODE_ETHERNET:
+       switch (lane->id) {
+       case 0:
+               mvebu_a3700_comphy_usb3_power_off(lane);
                mvebu_a3700_comphy_ethernet_power_off(lane);
-               break;
-
-       case PHY_MODE_PCIE:
+               return 0;
+       case 1:
                mvebu_a3700_comphy_pcie_power_off(lane);
-               break;
-
+               mvebu_a3700_comphy_ethernet_power_off(lane);
+               return 0;
+       case 2:
+               mvebu_a3700_comphy_usb3_power_off(lane);
+               mvebu_a3700_comphy_sata_power_off(lane);
+               return 0;
        default:
                dev_err(lane->dev, "invalid COMPHY mode\n");
                return -EINVAL;
        }
-
-       return 0;
 }
 
 static const struct phy_ops mvebu_a3700_comphy_ops = {
        .power_on       = mvebu_a3700_comphy_power_on,
        .power_off      = mvebu_a3700_comphy_power_off,
-       .reset          = mvebu_a3700_comphy_reset,
        .set_mode       = mvebu_a3700_comphy_set_mode,
        .owner          = THIS_MODULE,
 };
@@ -1393,8 +1341,7 @@ static int mvebu_a3700_comphy_probe(struct platform_device *pdev)
                 * To avoid relying on the bootloader/firmware configuration,
                 * power off all comphys.
                 */
-               mvebu_a3700_comphy_reset(phy);
-               lane->needs_reset = false;
+               mvebu_a3700_comphy_power_off(phy);
        }
 
        provider = devm_of_phy_provider_register(&pdev->dev,
index c5fd154..c7df8c5 100644 (file)
@@ -331,6 +331,7 @@ struct ocelot_pinctrl {
        const struct ocelot_pincfg_data *pincfg_data;
        struct ocelot_pmx_func func[FUNC_MAX];
        u8 stride;
+       struct workqueue_struct *wq;
 };
 
 struct ocelot_match_data {
@@ -338,6 +339,11 @@ struct ocelot_match_data {
        struct ocelot_pincfg_data pincfg_data;
 };
 
+struct ocelot_irq_work {
+       struct work_struct irq_work;
+       struct irq_desc *irq_desc;
+};
+
 #define LUTON_P(p, f0, f1)                                             \
 static struct ocelot_pin_caps luton_pin_##p = {                                \
        .pin = p,                                                       \
@@ -1813,6 +1819,75 @@ static void ocelot_irq_mask(struct irq_data *data)
        gpiochip_disable_irq(chip, gpio);
 }
 
+static void ocelot_irq_work(struct work_struct *work)
+{
+       struct ocelot_irq_work *w = container_of(work, struct ocelot_irq_work, irq_work);
+       struct irq_chip *parent_chip = irq_desc_get_chip(w->irq_desc);
+       struct gpio_chip *chip = irq_desc_get_chip_data(w->irq_desc);
+       struct irq_data *data = irq_desc_get_irq_data(w->irq_desc);
+       unsigned int gpio = irqd_to_hwirq(data);
+
+       local_irq_disable();
+       chained_irq_enter(parent_chip, w->irq_desc);
+       generic_handle_domain_irq(chip->irq.domain, gpio);
+       chained_irq_exit(parent_chip, w->irq_desc);
+       local_irq_enable();
+
+       kfree(w);
+}
+
+static void ocelot_irq_unmask_level(struct irq_data *data)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct ocelot_pinctrl *info = gpiochip_get_data(chip);
+       struct irq_desc *desc = irq_data_to_desc(data);
+       unsigned int gpio = irqd_to_hwirq(data);
+       unsigned int bit = BIT(gpio % 32);
+       bool ack = false, active = false;
+       u8 trigger_level;
+       int val;
+
+       trigger_level = irqd_get_trigger_type(data);
+
+       /* Check if the interrupt line is still active. */
+       regmap_read(info->map, REG(OCELOT_GPIO_IN, info, gpio), &val);
+       if ((!(val & bit) && trigger_level == IRQ_TYPE_LEVEL_LOW) ||
+             (val & bit && trigger_level == IRQ_TYPE_LEVEL_HIGH))
+               active = true;
+
+       /*
+        * Check if the interrupt controller has seen any changes in the
+        * interrupt line.
+        */
+       regmap_read(info->map, REG(OCELOT_GPIO_INTR, info, gpio), &val);
+       if (val & bit)
+               ack = true;
+
+       /* Enable the interrupt now */
+       gpiochip_enable_irq(chip, gpio);
+       regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
+                          bit, bit);
+
+       /*
+        * In case the interrupt line is still active and the interrupt
+        * controller has not seen any changes in the interrupt line, then it
+        * means that there happen another interrupt while the line was active.
+        * So we missed that one, so we need to kick the interrupt again
+        * handler.
+        */
+       if (active && !ack) {
+               struct ocelot_irq_work *work;
+
+               work = kmalloc(sizeof(*work), GFP_ATOMIC);
+               if (!work)
+                       return;
+
+               work->irq_desc = desc;
+               INIT_WORK(&work->irq_work, ocelot_irq_work);
+               queue_work(info->wq, &work->irq_work);
+       }
+}
+
 static void ocelot_irq_unmask(struct irq_data *data)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
@@ -1836,13 +1911,12 @@ static void ocelot_irq_ack(struct irq_data *data)
 
 static int ocelot_irq_set_type(struct irq_data *data, unsigned int type);
 
-static struct irq_chip ocelot_eoi_irqchip = {
+static struct irq_chip ocelot_level_irqchip = {
        .name           = "gpio",
        .irq_mask       = ocelot_irq_mask,
-       .irq_eoi        = ocelot_irq_ack,
-       .irq_unmask     = ocelot_irq_unmask,
-       .flags          = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
-                         IRQCHIP_IMMUTABLE,
+       .irq_ack        = ocelot_irq_ack,
+       .irq_unmask     = ocelot_irq_unmask_level,
+       .flags          = IRQCHIP_IMMUTABLE,
        .irq_set_type   = ocelot_irq_set_type,
        GPIOCHIP_IRQ_RESOURCE_HELPERS
 };
@@ -1859,14 +1933,9 @@ static struct irq_chip ocelot_irqchip = {
 
 static int ocelot_irq_set_type(struct irq_data *data, unsigned int type)
 {
-       type &= IRQ_TYPE_SENSE_MASK;
-
-       if (!(type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_HIGH)))
-               return -EINVAL;
-
-       if (type & IRQ_TYPE_LEVEL_HIGH)
-               irq_set_chip_handler_name_locked(data, &ocelot_eoi_irqchip,
-                                                handle_fasteoi_irq, NULL);
+       if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+               irq_set_chip_handler_name_locked(data, &ocelot_level_irqchip,
+                                                handle_level_irq, NULL);
        if (type & IRQ_TYPE_EDGE_BOTH)
                irq_set_chip_handler_name_locked(data, &ocelot_irqchip,
                                                 handle_edge_irq, NULL);
@@ -1996,6 +2065,10 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
        if (!info->desc)
                return -ENOMEM;
 
+       info->wq = alloc_ordered_workqueue("ocelot_ordered", 0);
+       if (!info->wq)
+               return -ENOMEM;
+
        info->pincfg_data = &data->pincfg_data;
 
        reset = devm_reset_control_get_optional_shared(dev, "switch");
@@ -2018,7 +2091,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
                dev_err(dev, "Failed to create regmap\n");
                return PTR_ERR(info->map);
        }
-       dev_set_drvdata(dev, info->map);
+       dev_set_drvdata(dev, info);
        info->dev = dev;
 
        /* Pinconf registers */
@@ -2043,6 +2116,15 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev)
        return 0;
 }
 
+static int ocelot_pinctrl_remove(struct platform_device *pdev)
+{
+       struct ocelot_pinctrl *info = platform_get_drvdata(pdev);
+
+       destroy_workqueue(info->wq);
+
+       return 0;
+}
+
 static struct platform_driver ocelot_pinctrl_driver = {
        .driver = {
                .name = "pinctrl-ocelot",
@@ -2050,6 +2132,7 @@ static struct platform_driver ocelot_pinctrl_driver = {
                .suppress_bind_attrs = true,
        },
        .probe = ocelot_pinctrl_probe,
+       .remove = ocelot_pinctrl_remove,
 };
 module_platform_driver(ocelot_pinctrl_driver);
 MODULE_LICENSE("Dual MIT/GPL");
index 6bec7f1..704a99d 100644 (file)
@@ -530,10 +530,10 @@ DECLARE_MSM_GPIO_PINS(187);
 DECLARE_MSM_GPIO_PINS(188);
 DECLARE_MSM_GPIO_PINS(189);
 
-static const unsigned int sdc2_clk_pins[] = { 190 };
-static const unsigned int sdc2_cmd_pins[] = { 191 };
-static const unsigned int sdc2_data_pins[] = { 192 };
-static const unsigned int ufs_reset_pins[] = { 193 };
+static const unsigned int ufs_reset_pins[] = { 190 };
+static const unsigned int sdc2_clk_pins[] = { 191 };
+static const unsigned int sdc2_cmd_pins[] = { 192 };
+static const unsigned int sdc2_data_pins[] = { 193 };
 
 enum sc8180x_functions {
        msm_mux_adsp_ext,
@@ -1582,7 +1582,7 @@ static const int sc8180x_acpi_reserved_gpios[] = {
 static const struct msm_gpio_wakeirq_map sc8180x_pdc_map[] = {
        { 3, 31 }, { 5, 32 }, { 8, 33 }, { 9, 34 }, { 10, 100 }, { 12, 104 },
        { 24, 37 }, { 26, 38 }, { 27, 41 }, { 28, 42 }, { 30, 39 }, { 36, 43 },
-       { 37, 43 }, { 38, 45 }, { 39, 118 }, { 39, 125 }, { 41, 47 },
+       { 37, 44 }, { 38, 45 }, { 39, 118 }, { 39, 125 }, { 41, 47 },
        { 42, 48 }, { 46, 50 }, { 47, 49 }, { 48, 51 }, { 49, 53 }, { 50, 52 },
        { 51, 116 }, { 51, 123 }, { 53, 54 }, { 54, 55 }, { 55, 56 },
        { 56, 57 }, { 58, 58 }, { 60, 60 }, { 68, 62 }, { 70, 63 }, { 76, 86 },
index afc1f5d..b82ad13 100644 (file)
@@ -99,7 +99,7 @@ MODULE_DEVICE_TABLE(of, a100_r_pinctrl_match);
 static struct platform_driver a100_r_pinctrl_driver = {
        .probe  = a100_r_pinctrl_probe,
        .driver = {
-               .name           = "sun50iw10p1-r-pinctrl",
+               .name           = "sun50i-a100-r-pinctrl",
                .of_match_table = a100_r_pinctrl_match,
        },
 };
index 55834cc..1e071df 100644 (file)
@@ -460,8 +460,6 @@ static int mlxreg_lc_power_on_off(struct mlxreg_lc *mlxreg_lc, u8 action)
        u32 regval;
        int err;
 
-       mutex_lock(&mlxreg_lc->lock);
-
        err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, &regval);
        if (err)
                goto regmap_read_fail;
@@ -474,7 +472,6 @@ static int mlxreg_lc_power_on_off(struct mlxreg_lc *mlxreg_lc, u8 action)
        err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_pwr, regval);
 
 regmap_read_fail:
-       mutex_unlock(&mlxreg_lc->lock);
        return err;
 }
 
@@ -491,8 +488,6 @@ static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)
         * line card which is already has been enabled. Disabling does not affect the disabled line
         * card.
         */
-       mutex_lock(&mlxreg_lc->lock);
-
        err = regmap_read(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, &regval);
        if (err)
                goto regmap_read_fail;
@@ -505,7 +500,6 @@ static int mlxreg_lc_enable_disable(struct mlxreg_lc *mlxreg_lc, bool action)
        err = regmap_write(mlxreg_lc->par_regmap, mlxreg_lc->data->reg_ena, regval);
 
 regmap_read_fail:
-       mutex_unlock(&mlxreg_lc->lock);
        return err;
 }
 
@@ -538,6 +532,15 @@ mlxreg_lc_sn4800_c16_config_init(struct mlxreg_lc *mlxreg_lc, void *regmap,
 static void
 mlxreg_lc_state_update(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
 {
+       if (action)
+               mlxreg_lc->state |= state;
+       else
+               mlxreg_lc->state &= ~state;
+}
+
+static void
+mlxreg_lc_state_update_locked(struct mlxreg_lc *mlxreg_lc, enum mlxreg_lc_state state, u8 action)
+{
        mutex_lock(&mlxreg_lc->lock);
 
        if (action)
@@ -560,8 +563,11 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
        dev_info(mlxreg_lc->dev, "linecard#%d state %d event kind %d action %d\n",
                 mlxreg_lc->data->slot, mlxreg_lc->state, kind, action);
 
-       if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED))
+       mutex_lock(&mlxreg_lc->lock);
+       if (!(mlxreg_lc->state & MLXREG_LC_INITIALIZED)) {
+               mutex_unlock(&mlxreg_lc->lock);
                return 0;
+       }
 
        switch (kind) {
        case MLXREG_HOTPLUG_LC_SYNCED:
@@ -574,7 +580,7 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
                if (!(mlxreg_lc->state & MLXREG_LC_POWERED) && action) {
                        err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
                        if (err)
-                               return err;
+                               goto mlxreg_lc_power_on_off_fail;
                }
                /* In case line card is configured - enable it. */
                if (mlxreg_lc->state & MLXREG_LC_CONFIGURED && action)
@@ -588,12 +594,13 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
                                /* In case line card is configured - enable it. */
                                if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
                                        err = mlxreg_lc_enable_disable(mlxreg_lc, 1);
+                               mutex_unlock(&mlxreg_lc->lock);
                                return err;
                        }
                        err = mlxreg_lc_create_static_devices(mlxreg_lc, mlxreg_lc->main_devs,
                                                              mlxreg_lc->main_devs_num);
                        if (err)
-                               return err;
+                               goto mlxreg_lc_create_static_devices_fail;
 
                        /* In case line card is already in ready state - enable it. */
                        if (mlxreg_lc->state & MLXREG_LC_CONFIGURED)
@@ -620,6 +627,10 @@ static int mlxreg_lc_event_handler(void *handle, enum mlxreg_hotplug_kind kind,
                break;
        }
 
+mlxreg_lc_power_on_off_fail:
+mlxreg_lc_create_static_devices_fail:
+       mutex_unlock(&mlxreg_lc->lock);
+
        return err;
 }
 
@@ -665,7 +676,7 @@ static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
                if (err)
                        goto mlxreg_lc_create_static_devices_failed;
 
-               mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_POWERED, 1);
+               mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_POWERED, 1);
        }
 
        /* Verify if line card is synchronized. */
@@ -676,7 +687,7 @@ static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
        /* Power on line card if necessary. */
        if (regval & mlxreg_lc->data->mask) {
                mlxreg_lc->state |= MLXREG_LC_SYNCED;
-               mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_SYNCED, 1);
+               mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_SYNCED, 1);
                if (mlxreg_lc->state & ~MLXREG_LC_POWERED) {
                        err = mlxreg_lc_power_on_off(mlxreg_lc, 1);
                        if (err)
@@ -684,7 +695,7 @@ static int mlxreg_lc_completion_notify(void *handle, struct i2c_adapter *parent,
                }
        }
 
-       mlxreg_lc_state_update(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);
+       mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 1);
 
        return 0;
 
@@ -814,10 +825,9 @@ static int mlxreg_lc_probe(struct platform_device *pdev)
 
        mutex_init(&mlxreg_lc->lock);
        /* Set event notification callback. */
-       if (data->notifier) {
-               data->notifier->user_handler = mlxreg_lc_event_handler;
-               data->notifier->handle = mlxreg_lc;
-       }
+       data->notifier->user_handler = mlxreg_lc_event_handler;
+       data->notifier->handle = mlxreg_lc;
+
        data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
        if (!data->hpdev.adapter) {
                dev_err(&pdev->dev, "Failed to get adapter for bus %d\n",
@@ -863,7 +873,6 @@ static int mlxreg_lc_probe(struct platform_device *pdev)
        if (err) {
                dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n",
                        data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
-               err = PTR_ERR(regmap);
                goto regcache_sync_fail;
        }
 
@@ -878,16 +887,14 @@ static int mlxreg_lc_probe(struct platform_device *pdev)
        if (err)
                goto mlxreg_lc_config_init_fail;
 
-       return err;
+       return 0;
 
 mlxreg_lc_config_init_fail:
 regcache_sync_fail:
 regmap_write_fail:
 devm_regmap_init_i2c_fail:
-       if (data->hpdev.client) {
-               i2c_unregister_device(data->hpdev.client);
-               data->hpdev.client = NULL;
-       }
+       i2c_unregister_device(data->hpdev.client);
+       data->hpdev.client = NULL;
 i2c_new_device_fail:
        i2c_put_adapter(data->hpdev.adapter);
        data->hpdev.adapter = NULL;
@@ -905,6 +912,8 @@ static int mlxreg_lc_remove(struct platform_device *pdev)
        struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
        struct mlxreg_lc *mlxreg_lc = platform_get_drvdata(pdev);
 
+       mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_INITIALIZED, 0);
+
        /*
         * Probing and removing are invoked by hotplug events raised upon line card insertion and
         * removing. If probing procedure fails all data is cleared. However, hotplug event still
index d5655f6..5859110 100644 (file)
@@ -86,38 +86,38 @@ static const struct software_node ssam_node_bas_dtx = {
        .parent = &ssam_node_root,
 };
 
-/* HID keyboard (TID1). */
-static const struct software_node ssam_node_hid_tid1_keyboard = {
+/* HID keyboard (SAM, TID=1). */
+static const struct software_node ssam_node_hid_sam_keyboard = {
        .name = "ssam:01:15:01:01:00",
        .parent = &ssam_node_root,
 };
 
-/* HID pen stash (TID1; pen taken / stashed away evens). */
-static const struct software_node ssam_node_hid_tid1_penstash = {
+/* HID pen stash (SAM, TID=1; pen taken / stashed away evens). */
+static const struct software_node ssam_node_hid_sam_penstash = {
        .name = "ssam:01:15:01:02:00",
        .parent = &ssam_node_root,
 };
 
-/* HID touchpad (TID1). */
-static const struct software_node ssam_node_hid_tid1_touchpad = {
+/* HID touchpad (SAM, TID=1). */
+static const struct software_node ssam_node_hid_sam_touchpad = {
        .name = "ssam:01:15:01:03:00",
        .parent = &ssam_node_root,
 };
 
-/* HID device instance 6 (TID1, unknown HID device). */
-static const struct software_node ssam_node_hid_tid1_iid6 = {
+/* HID device instance 6 (SAM, TID=1, HID sensor collection). */
+static const struct software_node ssam_node_hid_sam_sensors = {
        .name = "ssam:01:15:01:06:00",
        .parent = &ssam_node_root,
 };
 
-/* HID device instance 7 (TID1, unknown HID device). */
-static const struct software_node ssam_node_hid_tid1_iid7 = {
+/* HID device instance 7 (SAM, TID=1, UCM UCSI HID client). */
+static const struct software_node ssam_node_hid_sam_ucm_ucsi = {
        .name = "ssam:01:15:01:07:00",
        .parent = &ssam_node_root,
 };
 
-/* HID system controls (TID1). */
-static const struct software_node ssam_node_hid_tid1_sysctrl = {
+/* HID system controls (SAM, TID=1). */
+static const struct software_node ssam_node_hid_sam_sysctrl = {
        .name = "ssam:01:15:01:08:00",
        .parent = &ssam_node_root,
 };
@@ -182,8 +182,8 @@ static const struct software_node ssam_node_hid_kip_touchpad = {
        .parent = &ssam_node_hub_kip,
 };
 
-/* HID device instance 5 (KIP hub, unknown HID device). */
-static const struct software_node ssam_node_hid_kip_iid5 = {
+/* HID device instance 5 (KIP hub, type-cover firmware update). */
+static const struct software_node ssam_node_hid_kip_fwupd = {
        .name = "ssam:01:15:02:05:00",
        .parent = &ssam_node_hub_kip,
 };
@@ -241,12 +241,12 @@ static const struct software_node *ssam_node_group_sls[] = {
        &ssam_node_bat_main,
        &ssam_node_tmp_pprof,
        &ssam_node_pos_tablet_switch,
-       &ssam_node_hid_tid1_keyboard,
-       &ssam_node_hid_tid1_penstash,
-       &ssam_node_hid_tid1_touchpad,
-       &ssam_node_hid_tid1_iid6,
-       &ssam_node_hid_tid1_iid7,
-       &ssam_node_hid_tid1_sysctrl,
+       &ssam_node_hid_sam_keyboard,
+       &ssam_node_hid_sam_penstash,
+       &ssam_node_hid_sam_touchpad,
+       &ssam_node_hid_sam_sensors,
+       &ssam_node_hid_sam_ucm_ucsi,
+       &ssam_node_hid_sam_sysctrl,
        NULL,
 };
 
@@ -278,7 +278,9 @@ static const struct software_node *ssam_node_group_sp8[] = {
        &ssam_node_hid_kip_keyboard,
        &ssam_node_hid_kip_penstash,
        &ssam_node_hid_kip_touchpad,
-       &ssam_node_hid_kip_iid5,
+       &ssam_node_hid_kip_fwupd,
+       &ssam_node_hid_sam_sensors,
+       &ssam_node_hid_sam_ucm_ucsi,
        NULL,
 };
 
@@ -325,6 +327,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
        /* Surface Laptop Go 1 */
        { "MSHW0118", (unsigned long)ssam_node_group_slg1 },
 
+       /* Surface Laptop Go 2 */
+       { "MSHW0290", (unsigned long)ssam_node_group_slg1 },
+
        /* Surface Laptop Studio */
        { "MSHW0123", (unsigned long)ssam_node_group_sls },
 
index e0230ea..f1259d8 100644 (file)
@@ -99,6 +99,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = {
        {KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
        {KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
        {KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
+       {KE_KEY, 0x27, {KEY_HELP} },
        {KE_KEY, 0x29, {KEY_PROG3} },    /* P_Key for TM8372 */
        {KE_IGNORE, 0x41, {KEY_MUTE} },
        {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
@@ -112,7 +113,13 @@ static const struct key_entry acer_wmi_keymap[] __initconst = {
        {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
        {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
        {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
-       {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
+       /*
+        * 0x61 is KEY_SWITCHVIDEOMODE. Usually this is a duplicate input event
+        * with the "Video Bus" input device events. But sometimes it is not
+        * a dup. Map it to KEY_UNKNOWN instead of using KE_IGNORE so that
+        * udev/hwdb can override it on systems where it is not a dup.
+        */
+       {KE_KEY, 0x61, {KEY_UNKNOWN} },
        {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
        {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
        {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */
index 89b604e..eec7d0e 100644 (file)
@@ -107,7 +107,7 @@ module_param(fnlock_default, bool, 0444);
 #define WMI_EVENT_MASK                 0xFFFF
 
 #define FAN_CURVE_POINTS               8
-#define FAN_CURVE_BUF_LEN              (FAN_CURVE_POINTS * 2)
+#define FAN_CURVE_BUF_LEN              32
 #define FAN_CURVE_DEV_CPU              0x00
 #define FAN_CURVE_DEV_GPU              0x01
 /* Mask to determine if setting temperature or percentage */
@@ -1118,7 +1118,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
        }
 
        if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MICMUTE_LED)) {
-               asus->micmute_led.name = "asus::micmute";
+               asus->micmute_led.name = "platform::micmute";
                asus->micmute_led.max_brightness = 1;
                asus->micmute_led.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
                asus->micmute_led.brightness_set_blocking = micmute_led_set;
@@ -2233,8 +2233,10 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev)
        curves = &asus->custom_fan_curves[fan_idx];
        err = asus_wmi_evaluate_method_buf(asus->dsts_id, fan_dev, mode, buf,
                                           FAN_CURVE_BUF_LEN);
-       if (err)
+       if (err) {
+               pr_warn("%s (0x%08x) failed: %d\n", __func__, fan_dev, err);
                return err;
+       }
 
        fan_curve_copy_from_buf(curves, buf);
        curves->device_id = fan_dev;
@@ -2252,9 +2254,6 @@ static int fan_curve_check_present(struct asus_wmi *asus, bool *available,
 
        err = fan_curve_get_factory_default(asus, fan_dev);
        if (err) {
-               pr_debug("fan_curve_get_factory_default(0x%08x) failed: %d\n",
-                        fan_dev, err);
-               /* Don't cause probe to fail on devices without fan-curves */
                return 0;
        }
 
index 77cf058..9db2bb0 100644 (file)
@@ -62,7 +62,7 @@ int skl_int3472_get_sensor_adev_and_name(struct device *dev,
        struct acpi_device *sensor;
        int ret = 0;
 
-       sensor = acpi_dev_get_first_consumer_dev(adev);
+       sensor = acpi_dev_get_next_consumer_dev(adev, NULL);
        if (!sensor) {
                dev_err(dev, "INT3472 seems to have no dependents.\n");
                return -ENODEV;
index 22f61b4..49fc379 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Author: Dan Scally <djrscally@gmail.com> */
 
+#include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/kernel.h>
 #include <linux/mfd/core.h>
@@ -95,20 +96,65 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev)
        return DESIGNED_FOR_WINDOWS;
 }
 
+/*
+ * Return the size of the flexible array member, because we'll need that later
+ * on to pass .pdata_size to cells.
+ */
+static int
+skl_int3472_fill_clk_pdata(struct device *dev, struct tps68470_clk_platform_data **clk_pdata)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       struct acpi_device *consumer;
+       unsigned int n_consumers = 0;
+       const char *sensor_name;
+       unsigned int i = 0;
+
+       for_each_acpi_consumer_dev(adev, consumer)
+               n_consumers++;
+
+       if (!n_consumers) {
+               dev_err(dev, "INT3472 seems to have no dependents\n");
+               return -ENODEV;
+       }
+
+       *clk_pdata = devm_kzalloc(dev, struct_size(*clk_pdata, consumers, n_consumers),
+                                 GFP_KERNEL);
+       if (!*clk_pdata)
+               return -ENOMEM;
+
+       (*clk_pdata)->n_consumers = n_consumers;
+       i = 0;
+
+       for_each_acpi_consumer_dev(adev, consumer) {
+               sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
+                                            acpi_dev_name(consumer));
+               if (!sensor_name)
+                       return -ENOMEM;
+
+               (*clk_pdata)->consumers[i].consumer_dev_name = sensor_name;
+               i++;
+       }
+
+       acpi_dev_put(consumer);
+
+       return n_consumers;
+}
+
 static int skl_int3472_tps68470_probe(struct i2c_client *client)
 {
        struct acpi_device *adev = ACPI_COMPANION(&client->dev);
        const struct int3472_tps68470_board_data *board_data;
-       struct tps68470_clk_platform_data clk_pdata = {};
+       struct tps68470_clk_platform_data *clk_pdata;
        struct mfd_cell *cells;
        struct regmap *regmap;
+       int n_consumers;
        int device_type;
        int ret;
+       int i;
 
-       ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL,
-                                                  &clk_pdata.consumer_dev_name);
-       if (ret)
-               return ret;
+       n_consumers = skl_int3472_fill_clk_pdata(&client->dev, &clk_pdata);
+       if (n_consumers < 0)
+               return n_consumers;
 
        regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config);
        if (IS_ERR(regmap)) {
@@ -142,22 +188,25 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client)
                 * the clk + regulators must be ready when this happens.
                 */
                cells[0].name = "tps68470-clk";
-               cells[0].platform_data = &clk_pdata;
-               cells[0].pdata_size = sizeof(clk_pdata);
+               cells[0].platform_data = clk_pdata;
+               cells[0].pdata_size = struct_size(clk_pdata, consumers, n_consumers);
                cells[1].name = "tps68470-regulator";
                cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata;
                cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data);
                cells[2].name = "tps68470-gpio";
 
-               gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table);
+               for (i = 0; i < board_data->n_gpiod_lookups; i++)
+                       gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
 
                ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
                                           cells, TPS68470_WIN_MFD_CELL_COUNT,
                                           NULL, 0, NULL);
                kfree(cells);
 
-               if (ret)
-                       gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
+               if (ret) {
+                       for (i = 0; i < board_data->n_gpiod_lookups; i++)
+                               gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
+               }
 
                break;
        case DESIGNED_FOR_CHROMEOS:
@@ -181,10 +230,13 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client)
 static int skl_int3472_tps68470_remove(struct i2c_client *client)
 {
        const struct int3472_tps68470_board_data *board_data;
+       int i;
 
        board_data = int3472_tps68470_get_board_data(dev_name(&client->dev));
-       if (board_data)
-               gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table);
+       if (board_data) {
+               for (i = 0; i < board_data->n_gpiod_lookups; i++)
+                       gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
+       }
 
        return 0;
 }
index cfd33eb..35915e7 100644 (file)
@@ -16,8 +16,9 @@ struct tps68470_regulator_platform_data;
 
 struct int3472_tps68470_board_data {
        const char *dev_name;
-       struct gpiod_lookup_table *tps68470_gpio_lookup_table;
        const struct tps68470_regulator_platform_data *tps68470_regulator_pdata;
+       unsigned int n_gpiod_lookups;
+       struct gpiod_lookup_table *tps68470_gpio_lookup_tables[];
 };
 
 const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name);
index 525f09a..309eab9 100644 (file)
@@ -30,6 +30,15 @@ static struct regulator_consumer_supply int347a_vcm_consumer_supplies[] = {
 static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = {
        REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"),
        REGULATOR_SUPPLY("vsio", "i2c-INT347A:00-VCM"),
+       REGULATOR_SUPPLY("vddd", "i2c-INT347E:00"),
+};
+
+static struct regulator_consumer_supply int347a_aux1_consumer_supplies[] = {
+       REGULATOR_SUPPLY("vdda", "i2c-INT347E:00"),
+};
+
+static struct regulator_consumer_supply int347a_aux2_consumer_supplies[] = {
+       REGULATOR_SUPPLY("vdddo", "i2c-INT347E:00"),
 };
 
 static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = {
@@ -86,6 +95,28 @@ static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data =
        .consumer_supplies = int347a_vsio_consumer_supplies,
 };
 
+static const struct regulator_init_data surface_go_tps68470_aux1_reg_init_data = {
+       .constraints = {
+               .min_uV = 2815200,
+               .max_uV = 2815200,
+               .apply_uV = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_aux1_consumer_supplies),
+       .consumer_supplies = int347a_aux1_consumer_supplies,
+};
+
+static const struct regulator_init_data surface_go_tps68470_aux2_reg_init_data = {
+       .constraints = {
+               .min_uV = 1800600,
+               .max_uV = 1800600,
+               .apply_uV = 1,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(int347a_aux2_consumer_supplies),
+       .consumer_supplies = int347a_aux2_consumer_supplies,
+};
+
 static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = {
        .reg_init_data = {
                [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data,
@@ -93,10 +124,12 @@ static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata =
                [TPS68470_VCM]  = &surface_go_tps68470_vcm_reg_init_data,
                [TPS68470_VIO] = &surface_go_tps68470_vio_reg_init_data,
                [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data,
+               [TPS68470_AUX1] = &surface_go_tps68470_aux1_reg_init_data,
+               [TPS68470_AUX2] = &surface_go_tps68470_aux2_reg_init_data,
        },
 };
 
-static struct gpiod_lookup_table surface_go_tps68470_gpios = {
+static struct gpiod_lookup_table surface_go_int347a_gpios = {
        .dev_id = "i2c-INT347A:00",
        .table = {
                GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW),
@@ -105,16 +138,31 @@ static struct gpiod_lookup_table surface_go_tps68470_gpios = {
        }
 };
 
+static struct gpiod_lookup_table surface_go_int347e_gpios = {
+       .dev_id = "i2c-INT347E:00",
+       .table = {
+               GPIO_LOOKUP("tps68470-gpio", 5, "enable", GPIO_ACTIVE_HIGH),
+               { }
+       }
+};
+
 static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = {
        .dev_name = "i2c-INT3472:05",
-       .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
        .tps68470_regulator_pdata = &surface_go_tps68470_pdata,
+       .n_gpiod_lookups = 2,
+       .tps68470_gpio_lookup_tables = {
+               &surface_go_int347a_gpios,
+               &surface_go_int347e_gpios,
+       },
 };
 
 static const struct int3472_tps68470_board_data surface_go3_tps68470_board_data = {
        .dev_name = "i2c-INT3472:01",
-       .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios,
        .tps68470_regulator_pdata = &surface_go_tps68470_pdata,
+       .n_gpiod_lookups = 1,
+       .tps68470_gpio_lookup_tables = {
+               &surface_go_int347a_gpios
+       },
 };
 
 static const struct dmi_system_id int3472_tps68470_board_data_table[] = {
index fb2e141..384d096 100644 (file)
@@ -42,10 +42,24 @@ static int p2sb_get_devfn(unsigned int *devfn)
        return 0;
 }
 
+/* Copy resource from the first BAR of the device in question */
 static int p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem)
 {
-       /* Copy resource from the first BAR of the device in question */
-       *mem = pdev->resource[0];
+       struct resource *bar0 = &pdev->resource[0];
+
+       /* Make sure we have no dangling pointers in the output */
+       memset(mem, 0, sizeof(*mem));
+
+       /*
+        * We copy only selected fields from the original resource.
+        * Because a PCI device will be removed soon, we may not use
+        * any allocated data, hence we may not copy any pointers.
+        */
+       mem->start = bar0->start;
+       mem->end = bar0->end;
+       mem->flags = bar0->flags;
+       mem->desc = bar0->desc;
+
        return 0;
 }
 
index 154317e..5c757c7 100644 (file)
@@ -232,7 +232,7 @@ static void pmc_power_off(void)
        pm1_cnt_port = acpi_base_addr + PM1_CNT;
 
        pm1_cnt_value = inl(pm1_cnt_port);
-       pm1_cnt_value &= SLEEP_TYPE_MASK;
+       pm1_cnt_value &= ~SLEEP_TYPE_MASK;
        pm1_cnt_value |= SLEEP_TYPE_S5;
        pm1_cnt_value |= SLEEP_ENABLE;
 
index 22d4e86..2dbb9fc 100644 (file)
@@ -10592,10 +10592,9 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
        /* Ensure initial values are correct */
        dytc_profile_refresh();
 
-       /* Set AMT correctly now we know current profile */
-       if ((dytc_capabilities & BIT(DYTC_FC_PSC)) &&
-           (dytc_capabilities & BIT(DYTC_FC_AMT)))
-           dytc_control_amt(dytc_current_profile == PLATFORM_PROFILE_BALANCED);
+       /* Workaround for https://bugzilla.kernel.org/show_bug.cgi?id=216347 */
+       if (dytc_capabilities & BIT(DYTC_FC_PSC))
+               dytc_profile_set(NULL, PLATFORM_PROFILE_BALANCED);
 
        return 0;
 }
index 4803759..4acd6fa 100644 (file)
@@ -663,9 +663,23 @@ static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = {
        },
 };
 
+static int __init chuwi_hi8_init(void)
+{
+       /*
+        * Avoid the acpi_unregister_gsi() call in x86_acpi_irq_helper_get()
+        * breaking the touchscreen + logging various errors when the Windows
+        * BIOS is used.
+        */
+       if (acpi_dev_present("MSSL0001", NULL, 1))
+               return -ENODEV;
+
+       return 0;
+}
+
 static const struct x86_dev_info chuwi_hi8_info __initconst = {
        .i2c_client_info = chuwi_hi8_i2c_clients,
        .i2c_client_count = ARRAY_SIZE(chuwi_hi8_i2c_clients),
+       .init = chuwi_hi8_init,
 };
 
 #define CZC_EC_EXTRA_PORT      0x68
index 2ce739f..f330200 100644 (file)
@@ -153,7 +153,6 @@ extern int  pnpbios_dont_use_current_config;
 extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node);
 extern int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node);
 extern int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node);
-extern void pnpid32_to_pnpid(u32 id, char *str);
 
 extern void pnpbios_print_status(const char * module, u16 status);
 extern void pnpbios_calls_init(union pnp_bios_install_struct * header);
index 21d624f..26d00b1 100644 (file)
@@ -994,6 +994,9 @@ static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
                y = value & 0x1f;
                value = (1 << y) * (4 + f) * rp->time_unit / 4;
        } else {
+               if (value < rp->time_unit)
+                       return 0;
+
                do_div(value, rp->time_unit);
                y = ilog2(value);
                f = div64_u64(4 * (value - (1 << y)), 1 << y);
@@ -1035,7 +1038,6 @@ static const struct rapl_defaults rapl_defaults_spr_server = {
        .check_unit = rapl_check_unit_core,
        .set_floor_freq = set_floor_freq_default,
        .compute_time_window = rapl_compute_time_window_core,
-       .dram_domain_energy_unit = 15300,
        .psys_domain_energy_unit = 1000000000,
        .spr_psys_bits = true,
 };
@@ -1110,6 +1112,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N,         &rapl_defaults_core),
        X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE,          &rapl_defaults_core),
        X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P,        &rapl_defaults_core),
+       X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S,        &rapl_defaults_core),
        X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,    &rapl_defaults_spr_server),
        X86_MATCH_INTEL_FAM6_MODEL(LAKEFIELD,           &rapl_defaults_core),
 
index d8373cb..d3e8dc3 100644 (file)
@@ -2733,13 +2733,18 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
  */
 static int _regulator_handle_consumer_enable(struct regulator *regulator)
 {
+       int ret;
        struct regulator_dev *rdev = regulator->rdev;
 
        lockdep_assert_held_once(&rdev->mutex.base);
 
        regulator->enable_count++;
-       if (regulator->uA_load && regulator->enable_count == 1)
-               return drms_uA_update(rdev);
+       if (regulator->uA_load && regulator->enable_count == 1) {
+               ret = drms_uA_update(rdev);
+               if (ret)
+                       regulator->enable_count--;
+               return ret;
+       }
 
        return 0;
 }
index 6b61702..d899d6e 100644 (file)
@@ -766,7 +766,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
                ((pfuze_chip->chip_id == PFUZE3000) ? "3000" : "3001"))));
 
        memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators,
-               sizeof(pfuze_chip->regulator_descs));
+               regulator_num * sizeof(struct pfuze_regulator));
 
        ret = pfuze_parse_regulators_dt(pfuze_chip);
        if (ret)
index 185a333..d240872 100644 (file)
@@ -329,6 +329,7 @@ static int imx8mp_reset_set(struct reset_controller_dev *rcdev,
                break;
 
        case IMX8MP_RESET_PCIE_CTRL_APPS_EN:
+       case IMX8MP_RESET_PCIEPHY_PERST:
                value = assert ? 0 : bit;
                break;
        }
index 00b612a..f3528dd 100644 (file)
@@ -33,11 +33,8 @@ static struct regmap_config sparx5_reset_regmap_config = {
        .reg_stride     = 4,
 };
 
-static int sparx5_switch_reset(struct reset_controller_dev *rcdev,
-                              unsigned long id)
+static int sparx5_switch_reset(struct mchp_reset_context *ctx)
 {
-       struct mchp_reset_context *ctx =
-               container_of(rcdev, struct mchp_reset_context, rcdev);
        u32 val;
 
        /* Make sure the core is PROTECTED from reset */
@@ -54,8 +51,14 @@ static int sparx5_switch_reset(struct reset_controller_dev *rcdev,
                                        1, 100);
 }
 
+static int sparx5_reset_noop(struct reset_controller_dev *rcdev,
+                            unsigned long id)
+{
+       return 0;
+}
+
 static const struct reset_control_ops sparx5_reset_ops = {
-       .reset = sparx5_switch_reset,
+       .reset = sparx5_reset_noop,
 };
 
 static int mchp_sparx5_map_syscon(struct platform_device *pdev, char *name,
@@ -122,6 +125,11 @@ static int mchp_sparx5_reset_probe(struct platform_device *pdev)
        ctx->rcdev.of_node = dn;
        ctx->props = device_get_match_data(&pdev->dev);
 
+       /* Issue the reset very early, our actual reset callback is a noop. */
+       err = sparx5_switch_reset(ctx);
+       if (err)
+               return err;
+
        return devm_reset_controller_register(&pdev->dev, &ctx->rcdev);
 }
 
@@ -163,6 +171,10 @@ static int __init mchp_sparx5_reset_init(void)
        return platform_driver_register(&mchp_sparx5_reset_driver);
 }
 
+/*
+ * Because this is a global reset, keep this postcore_initcall() to issue the
+ * reset as early as possible during the kernel startup.
+ */
 postcore_initcall(mchp_sparx5_reset_init);
 
 MODULE_DESCRIPTION("Microchip Sparx5 switch reset driver");
index 24c55ef..f233350 100644 (file)
@@ -291,7 +291,7 @@ static void npcm_usb_reset_npcm8xx(struct npcm_rc_data *rc)
        iprst2 |= ipsrst2_bits;
        iprst3 |= (ipsrst3_bits | NPCM_IPSRST3_USBPHY1 |
                   NPCM_IPSRST3_USBPHY2);
-       iprst2 |= ipsrst4_bits;
+       iprst4 |= ipsrst4_bits;
 
        writel(iprst1, rc->base + NPCM_IPSRST1);
        writel(iprst2, rc->base + NPCM_IPSRST2);
index dc78a52..b6b938a 100644 (file)
@@ -675,12 +675,12 @@ int dasd_alias_remove_device(struct dasd_device *device)
 struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
 {
        struct dasd_eckd_private *alias_priv, *private = base_device->private;
-       struct alias_pav_group *group = private->pavgroup;
        struct alias_lcu *lcu = private->lcu;
        struct dasd_device *alias_device;
+       struct alias_pav_group *group;
        unsigned long flags;
 
-       if (!group || !lcu)
+       if (!lcu)
                return NULL;
        if (lcu->pav == NO_PAV ||
            lcu->flags & (NEED_UAC_UPDATE | UPDATE_PENDING))
@@ -697,6 +697,11 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
        }
 
        spin_lock_irqsave(&lcu->lock, flags);
+       group = private->pavgroup;
+       if (!group) {
+               spin_unlock_irqrestore(&lcu->lock, flags);
+               return NULL;
+       }
        alias_device = group->next;
        if (!alias_device) {
                if (list_empty(&group->aliaslist)) {
index 6c8c41f..ee82207 100644 (file)
@@ -984,6 +984,11 @@ static ssize_t assign_adapter_store(struct device *dev,
                goto done;
        }
 
+       if (test_bit_inv(apid, matrix_mdev->matrix.apm)) {
+               ret = count;
+               goto done;
+       }
+
        set_bit_inv(apid, matrix_mdev->matrix.apm);
 
        ret = vfio_ap_mdev_validate_masks(matrix_mdev);
@@ -1109,6 +1114,11 @@ static ssize_t unassign_adapter_store(struct device *dev,
                goto done;
        }
 
+       if (!test_bit_inv(apid, matrix_mdev->matrix.apm)) {
+               ret = count;
+               goto done;
+       }
+
        clear_bit_inv((unsigned long)apid, matrix_mdev->matrix.apm);
        vfio_ap_mdev_hot_unplug_adapter(matrix_mdev, apid);
        ret = count;
@@ -1183,6 +1193,11 @@ static ssize_t assign_domain_store(struct device *dev,
                goto done;
        }
 
+       if (test_bit_inv(apqi, matrix_mdev->matrix.aqm)) {
+               ret = count;
+               goto done;
+       }
+
        set_bit_inv(apqi, matrix_mdev->matrix.aqm);
 
        ret = vfio_ap_mdev_validate_masks(matrix_mdev);
@@ -1286,6 +1301,11 @@ static ssize_t unassign_domain_store(struct device *dev,
                goto done;
        }
 
+       if (!test_bit_inv(apqi, matrix_mdev->matrix.aqm)) {
+               ret = count;
+               goto done;
+       }
+
        clear_bit_inv((unsigned long)apqi, matrix_mdev->matrix.aqm);
        vfio_ap_mdev_hot_unplug_domain(matrix_mdev, apqi);
        ret = count;
@@ -1329,6 +1349,11 @@ static ssize_t assign_control_domain_store(struct device *dev,
                goto done;
        }
 
+       if (test_bit_inv(id, matrix_mdev->matrix.adm)) {
+               ret = count;
+               goto done;
+       }
+
        /* Set the bit in the ADM (bitmask) corresponding to the AP control
         * domain number (id). The bits in the mask, from most significant to
         * least significant, correspond to IDs 0 up to the one less than the
@@ -1378,6 +1403,11 @@ static ssize_t unassign_control_domain_store(struct device *dev,
                goto done;
        }
 
+       if (!test_bit_inv(domid, matrix_mdev->matrix.adm)) {
+               ret = count;
+               goto done;
+       }
+
        clear_bit_inv(domid, matrix_mdev->matrix.adm);
 
        if (test_bit_inv(domid, matrix_mdev->shadow_apcb.adm)) {
index 0738238..9857dba 100644 (file)
@@ -182,6 +182,15 @@ void scsi_remove_host(struct Scsi_Host *shost)
        mutex_unlock(&shost->scan_mutex);
        scsi_proc_host_rm(shost);
 
+       /*
+        * New SCSI devices cannot be attached anymore because of the SCSI host
+        * state so drop the tag set refcnt. Wait until the tag set refcnt drops
+        * to zero because .exit_cmd_priv implementations may need the host
+        * pointer.
+        */
+       kref_put(&shost->tagset_refcnt, scsi_mq_free_tags);
+       wait_for_completion(&shost->tagset_freed);
+
        spin_lock_irqsave(shost->host_lock, flags);
        if (scsi_host_set_state(shost, SHOST_DEL))
                BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
@@ -190,15 +199,6 @@ void scsi_remove_host(struct Scsi_Host *shost)
        transport_unregister_device(&shost->shost_gendev);
        device_unregister(&shost->shost_dev);
        device_del(&shost->shost_gendev);
-
-       /*
-        * After scsi_remove_host() has returned the scsi LLD module can be
-        * unloaded and/or the host resources can be released. Hence wait until
-        * the dependent SCSI targets and devices are gone before returning.
-        */
-       wait_event(shost->targets_wq, atomic_read(&shost->target_count) == 0);
-
-       scsi_mq_destroy_tags(shost);
 }
 EXPORT_SYMBOL(scsi_remove_host);
 
@@ -254,6 +254,9 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
        if (error)
                goto fail;
 
+       kref_init(&shost->tagset_refcnt);
+       init_completion(&shost->tagset_freed);
+
        /*
         * Increase usage count temporarily here so that calling
         * scsi_autopm_put_host() will trigger runtime idle if there is
@@ -309,8 +312,8 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
        return error;
 
        /*
-        * Any resources associated with the SCSI host in this function except
-        * the tag set will be freed by scsi_host_dev_release().
+        * Any host allocation in this function will be freed in
+        * scsi_host_dev_release().
         */
  out_del_dev:
        device_del(&shost->shost_dev);
@@ -326,7 +329,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
        pm_runtime_disable(&shost->shost_gendev);
        pm_runtime_set_suspended(&shost->shost_gendev);
        pm_runtime_put_noidle(&shost->shost_gendev);
-       scsi_mq_destroy_tags(shost);
+       kref_put(&shost->tagset_refcnt, scsi_mq_free_tags);
  fail:
        return error;
 }
@@ -406,7 +409,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        INIT_LIST_HEAD(&shost->starved_list);
        init_waitqueue_head(&shost->host_wait);
        mutex_init(&shost->scan_mutex);
-       init_waitqueue_head(&shost->targets_wq);
 
        index = ida_alloc(&host_index_ida, GFP_KERNEL);
        if (index < 0) {
index 9c82e5d..a36fa1c 100644 (file)
@@ -872,7 +872,8 @@ int sas_change_queue_depth(struct scsi_device *sdev, int depth)
        struct domain_device *dev = sdev_to_domain_dev(sdev);
 
        if (dev_is_sata(dev))
-               return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
+               return ata_change_queue_depth(dev->sata_dev.ap,
+                                             sas_to_ata_dev(dev), sdev, depth);
 
        if (!sdev->tagged_supported)
                depth = 1;
index c69c5a0..55a1ad6 100644 (file)
@@ -8053,7 +8053,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        /* Allocate device driver memory */
        rc = lpfc_mem_alloc(phba, SGL_ALIGN_SZ);
        if (rc)
-               return -ENOMEM;
+               goto out_destroy_workqueue;
 
        /* IF Type 2 ports get initialized now. */
        if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
@@ -8481,6 +8481,9 @@ out_free_bsmbx:
        lpfc_destroy_bootstrap_mbox(phba);
 out_free_mem:
        lpfc_mem_free(phba);
+out_destroy_workqueue:
+       destroy_workqueue(phba->wq);
+       phba->wq = NULL;
        return rc;
 }
 
index 084c0f9..938a5e4 100644 (file)
@@ -4272,7 +4272,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
                    lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
                    lpfc_cmd->result == IOERR_RPI_SUSPENDED ||
                    lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
-                       cmd->result = DID_REQUEUE << 16;
+                       cmd->result = DID_TRANSPORT_DISRUPTED << 16;
                        break;
                }
                if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
@@ -4562,7 +4562,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                            lpfc_cmd->result == IOERR_NO_RESOURCES ||
                            lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
                            lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) {
-                               cmd->result = DID_REQUEUE << 16;
+                               cmd->result = DID_TRANSPORT_DISRUPTED << 16;
                                break;
                        }
                        if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
index 565339a..331e896 100644 (file)
@@ -2993,7 +2993,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
 
        if (ioc->is_mcpu_endpoint ||
            sizeof(dma_addr_t) == 4 || ioc->use_32bit_dma ||
-           dma_get_required_mask(&pdev->dev) <= 32)
+           dma_get_required_mask(&pdev->dev) <= DMA_BIT_MASK(32))
                ioc->dma_mask = 32;
        /* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
        else if (ioc->hba_mpi_version_belonged > MPI2_VERSION)
index def37a7..bd6a5f1 100644 (file)
@@ -3670,6 +3670,7 @@ static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc)
                fw_event = list_first_entry(&ioc->fw_event_list,
                                struct fw_event_work, list);
                list_del_init(&fw_event->list);
+               fw_event_work_put(fw_event);
        }
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 
@@ -3751,7 +3752,6 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
                if (cancel_work_sync(&fw_event->work))
                        fw_event_work_put(fw_event);
 
-               fw_event_work_put(fw_event);
        }
        ioc->fw_events_cleanup = 0;
 }
index 3d6b137..bbc4d58 100644 (file)
@@ -3686,11 +3686,6 @@ err2:
 err1:
        scsi_host_put(lport->host);
 err0:
-       if (qedf) {
-               QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, "Probe done.\n");
-
-               clear_bit(QEDF_PROBING, &qedf->flags);
-       }
        return rc;
 }
 
index 62666df..4acff4e 100644 (file)
@@ -2151,8 +2151,10 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
 
        abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag(sess,
                                le32_to_cpu(abts->exchange_addr_to_abort));
-       if (!abort_cmd)
+       if (!abort_cmd) {
+               mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
                return -EIO;
+       }
        mcmd->unpacked_lun = abort_cmd->se_cmd.orig_fe_lun;
 
        if (abort_cmd->qpair) {
index 086ec5b..c59eac7 100644 (file)
@@ -586,13 +586,10 @@ EXPORT_SYMBOL(scsi_device_get);
  */
 void scsi_device_put(struct scsi_device *sdev)
 {
-       /*
-        * Decreasing the module reference count before the device reference
-        * count is safe since scsi_remove_host() only returns after all
-        * devices have been removed.
-        */
-       module_put(sdev->host->hostt->module);
+       struct module *mod = sdev->host->hostt->module;
+
        put_device(&sdev->sdev_gendev);
+       module_put(mod);
 }
 EXPORT_SYMBOL(scsi_device_put);
 
index ef08029..96e7e3e 100644 (file)
@@ -1983,9 +1983,13 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
        return blk_mq_alloc_tag_set(tag_set);
 }
 
-void scsi_mq_destroy_tags(struct Scsi_Host *shost)
+void scsi_mq_free_tags(struct kref *kref)
 {
+       struct Scsi_Host *shost = container_of(kref, typeof(*shost),
+                                              tagset_refcnt);
+
        blk_mq_free_tag_set(&shost->tag_set);
+       complete(&shost->tagset_freed);
 }
 
 /**
index 429663b..f385b3f 100644 (file)
@@ -94,7 +94,7 @@ extern void scsi_run_host_queues(struct Scsi_Host *shost);
 extern void scsi_requeue_run_queue(struct work_struct *work);
 extern void scsi_start_queue(struct scsi_device *sdev);
 extern int scsi_mq_setup_tags(struct Scsi_Host *shost);
-extern void scsi_mq_destroy_tags(struct Scsi_Host *shost);
+extern void scsi_mq_free_tags(struct kref *kref);
 extern void scsi_exit_queue(void);
 extern void scsi_evt_thread(struct work_struct *work);
 
index ac60597..5d27f51 100644 (file)
@@ -340,6 +340,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
                kfree(sdev);
                goto out;
        }
+       kref_get(&sdev->host->tagset_refcnt);
        sdev->request_queue = q;
        q->queuedata = sdev;
        __scsi_init_queue(sdev->host, q);
@@ -406,14 +407,9 @@ static void scsi_target_destroy(struct scsi_target *starget)
 static void scsi_target_dev_release(struct device *dev)
 {
        struct device *parent = dev->parent;
-       struct Scsi_Host *shost = dev_to_shost(parent);
        struct scsi_target *starget = to_scsi_target(dev);
 
        kfree(starget);
-
-       if (atomic_dec_return(&shost->target_count) == 0)
-               wake_up(&shost->targets_wq);
-
        put_device(parent);
 }
 
@@ -526,10 +522,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        starget->state = STARGET_CREATED;
        starget->scsi_level = SCSI_2;
        starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED;
-       init_waitqueue_head(&starget->sdev_wq);
-
-       atomic_inc(&shost->target_count);
-
  retry:
        spin_lock_irqsave(shost->host_lock, flags);
 
index 9dad2fd..5d61f58 100644 (file)
@@ -443,15 +443,18 @@ static void scsi_device_cls_release(struct device *class_dev)
 
 static void scsi_device_dev_release_usercontext(struct work_struct *work)
 {
-       struct scsi_device *sdev = container_of(work, struct scsi_device,
-                                               ew.work);
-       struct scsi_target *starget = sdev->sdev_target;
+       struct scsi_device *sdev;
        struct device *parent;
        struct list_head *this, *tmp;
        struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
        struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
        struct scsi_vpd *vpd_pgb0 = NULL, *vpd_pgb1 = NULL, *vpd_pgb2 = NULL;
        unsigned long flags;
+       struct module *mod;
+
+       sdev = container_of(work, struct scsi_device, ew.work);
+
+       mod = sdev->host->hostt->module;
 
        scsi_dh_release_device(sdev);
 
@@ -513,16 +516,19 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
        kfree(sdev->inquiry);
        kfree(sdev);
 
-       if (starget && atomic_dec_return(&starget->sdev_count) == 0)
-               wake_up(&starget->sdev_wq);
-
        if (parent)
                put_device(parent);
+       module_put(mod);
 }
 
 static void scsi_device_dev_release(struct device *dev)
 {
        struct scsi_device *sdp = to_scsi_device(dev);
+
+       /* Set module pointer as NULL in case of module unloading */
+       if (!try_module_get(sdp->host->hostt->module))
+               sdp->host->hostt->module = NULL;
+
        execute_in_process_context(scsi_device_dev_release_usercontext,
                                   &sdp->ew);
 }
@@ -1470,6 +1476,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
        mutex_unlock(&sdev->state_mutex);
 
        blk_mq_destroy_queue(sdev->request_queue);
+       kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags);
        cancel_work_sync(&sdev->requeue_work);
 
        if (sdev->host->hostt->slave_destroy)
@@ -1529,14 +1536,6 @@ static void __scsi_remove_target(struct scsi_target *starget)
                goto restart;
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
-
-       /*
-        * After scsi_remove_target() returns its caller can remove resources
-        * associated with @starget, e.g. an rport or session. Wait until all
-        * devices associated with @starget have been removed to prevent that
-        * a SCSI error handling callback function triggers a use-after-free.
-        */
-       wait_event(starget->sdev_wq, atomic_read(&starget->sdev_count) == 0);
 }
 
 /**
@@ -1647,9 +1646,6 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
        list_add_tail(&sdev->same_target_siblings, &starget->devices);
        list_add_tail(&sdev->siblings, &shost->__devices);
        spin_unlock_irqrestore(shost->host_lock, flags);
-
-       atomic_inc(&starget->sdev_count);
-
        /*
         * device can now only be removed via __scsi_remove_device() so hold
         * the target.  Target will be held in CREATED state until something
index 1467bbd..e1d7b45 100644 (file)
@@ -288,7 +288,6 @@ 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:
-       of_node_put(np);
        return ret;
 }
 
index d6b30d5..775da69 100644 (file)
@@ -684,13 +684,14 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
        const struct of_device_id *of_id = NULL;
        struct device_node *dn;
        void __iomem *base;
-       int ret, i;
+       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");
-               return PTR_ERR(base);
+               ret = PTR_ERR(base);
+               goto aon_err;
        }
        ctrl.aon_ctrl_base = base;
 
@@ -700,8 +701,10 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
                /* 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);
@@ -711,7 +714,8 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
                                     (const void **)&ddr_phy_data);
        if (IS_ERR(base)) {
                pr_err("error mapping DDR PHY\n");
-               return PTR_ERR(base);
+               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;
@@ -731,17 +735,20 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
        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);
-                       return PTR_ERR(base);
+                       ret = PTR_ERR(base);
+                       goto ddr_shimphy_err;
                }
                ctrl.memcs[i].ddr_shimphy_base = base;
                ctrl.num_memc++;
@@ -752,14 +759,18 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
        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);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto brcmstb_memc_err;
                }
 
                of_id = of_match_node(brcmstb_memc_of_match, dn);
                if (!of_id) {
                        iounmap(base);
-                       return -EINVAL;
+                       of_node_put(dn);
+                       ret = -EINVAL;
+                       goto brcmstb_memc_err;
                }
 
                ddr_seq_data = of_id->data;
@@ -779,21 +790,24 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
        dn = of_find_matching_node(NULL, sram_dt_ids);
        if (!dn) {
                pr_err("SRAM not found\n");
-               return -EINVAL;
+               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");
-               return ret;
+               goto brcmstb_memc_err;
        }
 
        ctrl.pdev = pdev;
 
        ctrl.s3_params = kmalloc(sizeof(*ctrl.s3_params), GFP_KERNEL);
-       if (!ctrl.s3_params)
-               return -ENOMEM;
+       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);
@@ -813,7 +827,21 @@ static int brcmstb_pm_probe(struct platform_device *pdev)
 
 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;
index 07d52ca..fcec6ed 100644 (file)
@@ -24,6 +24,7 @@ config FSL_MC_DPIO
         tristate "QorIQ DPAA2 DPIO driver"
         depends on FSL_MC_BUS
         select SOC_BUS
+        select FSL_GUTS
         select DIMLIB
         help
          Driver for the DPAA2 DPIO object.  A DPIO provides queue and
index 6383a4e..88aee59 100644 (file)
@@ -335,6 +335,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
                }
        }
 
+       reset_control_assert(domain->reset);
+
        /* Enable reset clocks for all devices in the domain */
        ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
        if (ret) {
@@ -342,7 +344,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
                goto out_regulator_disable;
        }
 
-       reset_control_assert(domain->reset);
+       /* delays for reset to propagate */
+       udelay(5);
 
        if (domain->bits.pxx) {
                /* request the domain to power up */
index dff7529..972f289 100644 (file)
@@ -243,7 +243,6 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
                        ret = PTR_ERR(domain->power_dev);
                        goto cleanup_pds;
                }
-               dev_set_name(domain->power_dev, "%s", data->name);
 
                domain->genpd.name = data->name;
                domain->genpd.power_on = imx8m_blk_ctrl_power_on;
index a8f3876..09754cd 100644 (file)
@@ -78,8 +78,8 @@ static struct sunxi_sram_desc sun4i_a10_sram_d = {
 
 static struct sunxi_sram_desc sun50i_a64_sram_c = {
        .data   = SUNXI_SRAM_DATA("C", 0x4, 24, 1,
-                                 SUNXI_SRAM_MAP(0, 1, "cpu"),
-                                 SUNXI_SRAM_MAP(1, 0, "de2")),
+                                 SUNXI_SRAM_MAP(1, 0, "cpu"),
+                                 SUNXI_SRAM_MAP(0, 1, "de2")),
 };
 
 static const struct of_device_id sunxi_sram_dt_ids[] = {
@@ -254,6 +254,7 @@ int sunxi_sram_claim(struct device *dev)
        writel(val | ((device << sram_data->offset) & mask),
               base + sram_data->reg);
 
+       sram_desc->claimed = true;
        spin_unlock(&sram_lock);
 
        return 0;
@@ -329,11 +330,11 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
        .writeable_reg  = sunxi_sram_regmap_accessible_reg,
 };
 
-static int sunxi_sram_probe(struct platform_device *pdev)
+static int __init sunxi_sram_probe(struct platform_device *pdev)
 {
-       struct dentry *d;
        struct regmap *emac_clock;
        const struct sunxi_sramc_variant *variant;
+       struct device *dev = &pdev->dev;
 
        sram_dev = &pdev->dev;
 
@@ -345,13 +346,6 @@ static int sunxi_sram_probe(struct platform_device *pdev)
        if (IS_ERR(base))
                return PTR_ERR(base);
 
-       of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
-
-       d = debugfs_create_file("sram", S_IRUGO, NULL, NULL,
-                               &sunxi_sram_fops);
-       if (!d)
-               return -ENOMEM;
-
        if (variant->num_emac_clocks > 0) {
                emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
                                                   &sunxi_sram_emac_clock_regmap);
@@ -360,6 +354,10 @@ static int sunxi_sram_probe(struct platform_device *pdev)
                        return PTR_ERR(emac_clock);
        }
 
+       of_platform_populate(dev->of_node, NULL, NULL, dev);
+
+       debugfs_create_file("sram", 0444, NULL, NULL, &sunxi_sram_fops);
+
        return 0;
 }
 
@@ -409,9 +407,8 @@ static struct platform_driver sunxi_sram_driver = {
                .name           = "sunxi-sram",
                .of_match_table = sunxi_sram_dt_match,
        },
-       .probe  = sunxi_sram_probe,
 };
-module_platform_driver(sunxi_sram_driver);
+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");
index 9df970e..3a992a6 100644 (file)
@@ -169,7 +169,7 @@ struct qcom_swrm_ctrl {
        u8 wcmd_id;
        struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS];
        struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS];
-       enum sdw_slave_status status[SDW_MAX_DEVICES];
+       enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
        int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val);
        int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val);
        u32 slave_status;
@@ -420,7 +420,7 @@ static int qcom_swrm_get_alert_slave_dev_num(struct qcom_swrm_ctrl *ctrl)
 
        ctrl->reg_read(ctrl, SWRM_MCP_SLV_STATUS, &val);
 
-       for (dev_num = 0; dev_num < SDW_MAX_DEVICES; dev_num++) {
+       for (dev_num = 0; dev_num <= SDW_MAX_DEVICES; dev_num++) {
                status = (val >> (dev_num * SWRM_MCP_SLV_STATUS_SZ));
 
                if ((status & SWRM_MCP_SLV_STATUS_MASK) == SDW_SLAVE_ALERT) {
@@ -440,7 +440,7 @@ static void qcom_swrm_get_device_status(struct qcom_swrm_ctrl *ctrl)
        ctrl->reg_read(ctrl, SWRM_MCP_SLV_STATUS, &val);
        ctrl->slave_status = val;
 
-       for (i = 0; i < SDW_MAX_DEVICES; i++) {
+       for (i = 0; i <= SDW_MAX_DEVICES; i++) {
                u32 s;
 
                s = (val >> (i * 2));
@@ -1356,10 +1356,6 @@ static int qcom_swrm_probe(struct platform_device *pdev)
        ctrl->bus.compute_params = &qcom_swrm_compute_params;
        ctrl->bus.clk_stop_timeout = 300;
 
-       ctrl->audio_cgcr = devm_reset_control_get_exclusive(dev, "swr_audio_cgcr");
-       if (IS_ERR(ctrl->audio_cgcr))
-               dev_err(dev, "Failed to get audio_cgcr reset required for soundwire-v1.6.0\n");
-
        ret = qcom_swrm_get_port_config(ctrl);
        if (ret)
                goto err_clk;
index 267342d..2dcbe16 100644 (file)
@@ -116,6 +116,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi,
 {
        /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
 
+       u8 rxbit = bits - 1;
        u32 oldbit = !(word & 1);
        /* clock starts at inactive polarity */
        for (; likely(bits); bits--) {
@@ -135,7 +136,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi,
                /* sample LSB (from slave) on leading edge */
                word >>= 1;
                if ((flags & SPI_MASTER_NO_RX) == 0)
-                       word |= getmiso(spi) << (bits - 1);
+                       word |= getmiso(spi) << rxbit;
                setsck(spi, cpol);
        }
        return word;
@@ -148,6 +149,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi,
 {
        /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
 
+       u8 rxbit = bits - 1;
        u32 oldbit = !(word & 1);
        /* clock starts at inactive polarity */
        for (; likely(bits); bits--) {
@@ -168,7 +170,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi,
                /* sample LSB (from slave) on trailing edge */
                word >>= 1;
                if ((flags & SPI_MASTER_NO_RX) == 0)
-                       word |= getmiso(spi) << (bits - 1);
+                       word |= getmiso(spi) << rxbit;
        }
        return word;
 }
index 72b1a5a..e12ab5b 100644 (file)
@@ -39,6 +39,7 @@
 #define CQSPI_DISABLE_DAC_MODE         BIT(1)
 #define CQSPI_SUPPORT_EXTERNAL_DMA     BIT(2)
 #define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
+#define CQSPI_SLOW_SRAM                BIT(4)
 
 /* Capabilities */
 #define CQSPI_SUPPORTS_OCTAL           BIT(0)
@@ -87,6 +88,7 @@ struct cqspi_st {
        bool                    use_dma_read;
        u32                     pd_dev_id;
        bool                    wr_completion;
+       bool                    slow_sram;
 };
 
 struct cqspi_driver_platdata {
@@ -333,7 +335,10 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
                }
        }
 
-       irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
+       else if (!cqspi->slow_sram)
+               irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
+       else
+               irq_status &= CQSPI_REG_IRQ_WATERMARK | CQSPI_IRQ_MASK_WR;
 
        if (irq_status)
                complete(&cqspi->transfer_complete);
@@ -673,7 +678,18 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
        /* Clear all interrupts. */
        writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
 
-       writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
+       /*
+        * On SoCFPGA platform reading the SRAM is slow due to
+        * hardware limitation and causing read interrupt storm to CPU,
+        * so enabling only watermark interrupt to disable all read
+        * interrupts later as we want to run "bytes to read" loop with
+        * all the read interrupts disabled for max performance.
+        */
+
+       if (!cqspi->slow_sram)
+               writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
+       else
+               writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
 
        reinit_completion(&cqspi->transfer_complete);
        writel(CQSPI_REG_INDIRECTRD_START_MASK,
@@ -684,6 +700,13 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
                                                 msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
                        ret = -ETIMEDOUT;
 
+               /*
+                * Disable all read interrupts until
+                * we are out of "bytes to read"
+                */
+               if (cqspi->slow_sram)
+                       writel(0x0, reg_base + CQSPI_REG_IRQMASK);
+
                bytes_to_read = cqspi_get_rd_sram_level(cqspi);
 
                if (ret && bytes_to_read == 0) {
@@ -715,8 +738,11 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
                        bytes_to_read = cqspi_get_rd_sram_level(cqspi);
                }
 
-               if (remaining > 0)
+               if (remaining > 0) {
                        reinit_completion(&cqspi->transfer_complete);
+                       if (cqspi->slow_sram)
+                               writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
+               }
        }
 
        /* Check indirect done status */
@@ -1667,6 +1693,8 @@ static int cqspi_probe(struct platform_device *pdev)
                        cqspi->use_dma_read = true;
                if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION)
                        cqspi->wr_completion = false;
+               if (ddata->quirks & CQSPI_SLOW_SRAM)
+                       cqspi->slow_sram = true;
 
                if (of_device_is_compatible(pdev->dev.of_node,
                                            "xlnx,versal-ospi-1.0"))
@@ -1779,7 +1807,9 @@ static const struct cqspi_driver_platdata intel_lgm_qspi = {
 };
 
 static const struct cqspi_driver_platdata socfpga_qspi = {
-       .quirks = CQSPI_DISABLE_DAC_MODE | CQSPI_NO_SUPPORT_WR_COMPLETION,
+       .quirks = CQSPI_DISABLE_DAC_MODE
+                       | CQSPI_NO_SUPPORT_WR_COMPLETION
+                       | CQSPI_SLOW_SRAM,
 };
 
 static const struct cqspi_driver_platdata versal_ospi = {
index f5d32ec..0709e98 100644 (file)
@@ -161,6 +161,7 @@ static int spi_mux_probe(struct spi_device *spi)
        ctlr->num_chipselect = mux_control_states(priv->mux);
        ctlr->bus_num = -1;
        ctlr->dev.of_node = spi->dev.of_node;
+       ctlr->must_async = true;
 
        ret = devm_spi_register_controller(&spi->dev, ctlr);
        if (ret)
index 838d12e..c8e079d 100644 (file)
@@ -1441,31 +1441,6 @@ static const struct of_device_id pxa2xx_spi_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
 
-#ifdef CONFIG_ACPI
-
-static int pxa2xx_spi_get_port_id(struct device *dev)
-{
-       struct acpi_device *adev;
-       unsigned int devid;
-       int port_id = -1;
-
-       adev = ACPI_COMPANION(dev);
-       if (adev && adev->pnp.unique_id &&
-           !kstrtouint(adev->pnp.unique_id, 0, &devid))
-               port_id = devid;
-       return port_id;
-}
-
-#else /* !CONFIG_ACPI */
-
-static int pxa2xx_spi_get_port_id(struct device *dev)
-{
-       return -1;
-}
-
-#endif /* CONFIG_ACPI */
-
-
 #ifdef CONFIG_PCI
 
 static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
@@ -1479,13 +1454,16 @@ static struct pxa2xx_spi_controller *
 pxa2xx_spi_init_pdata(struct platform_device *pdev)
 {
        struct pxa2xx_spi_controller *pdata;
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
        struct ssp_device *ssp;
        struct resource *res;
-       struct device *parent = pdev->dev.parent;
        struct pci_dev *pcidev = dev_is_pci(parent) ? to_pci_dev(parent) : NULL;
        const struct pci_device_id *pcidev_id = NULL;
        enum pxa_ssp_type type;
        const void *match;
+       int status;
+       u64 uid;
 
        if (pcidev)
                pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, pcidev);
@@ -1529,7 +1507,12 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
 
        ssp->type = type;
        ssp->dev = &pdev->dev;
-       ssp->port_id = pxa2xx_spi_get_port_id(&pdev->dev);
+
+       status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
+       if (status)
+               ssp->port_id = -1;
+       else
+               ssp->port_id = uid;
 
        pdata->is_slave = device_property_read_bool(&pdev->dev, "spi-slave");
        pdata->num_chipselect = 1;
index 83da886..30e82f9 100644 (file)
@@ -1727,8 +1727,7 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
        spin_unlock_irqrestore(&ctlr->queue_lock, flags);
 
        ret = __spi_pump_transfer_message(ctlr, msg, was_busy);
-       if (!ret)
-               kthread_queue_work(ctlr->kworker, &ctlr->pump_messages);
+       kthread_queue_work(ctlr->kworker, &ctlr->pump_messages);
 
        ctlr->cur_msg = NULL;
        ctlr->fallback = false;
@@ -4033,7 +4032,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
         * guard against reentrancy from a different context. The io_mutex
         * will catch those cases.
         */
-       if (READ_ONCE(ctlr->queue_empty)) {
+       if (READ_ONCE(ctlr->queue_empty) && !ctlr->must_async) {
                message->actual_length = 0;
                message->status = -EINPROGRESS;
 
@@ -4375,7 +4374,7 @@ static int acpi_spi_notify(struct notifier_block *nb, unsigned long value,
 
        switch (value) {
        case ACPI_RECONFIG_DEVICE_ADD:
-               ctlr = acpi_spi_find_controller_by_adev(adev->parent);
+               ctlr = acpi_spi_find_controller_by_adev(acpi_dev_parent(adev));
                if (!ctlr)
                        break;
 
index 4af5a83..4fc167b 100644 (file)
@@ -1162,8 +1162,8 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
 
        schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000));
 
-       writel(0xffffffff, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
-       writel(0xffffffff, rkvdec->regs + RKVDEC_REG_H264_ERR_E);
+       writel(0, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
+       writel(0, rkvdec->regs + RKVDEC_REG_H264_ERR_E);
        writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
        writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
 
index cac9553..aa100b5 100644 (file)
@@ -18,6 +18,7 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
 MODULE_AUTHOR("Realtek Semiconductor Corp.");
 MODULE_VERSION(DRIVERVERSION);
+MODULE_FIRMWARE("rtlwifi/rtl8188eufw.bin");
 
 #define CONFIG_BR_EXT_BRNAME "br0"
 #define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */
index cc2b44f..9147d17 100644 (file)
@@ -28,6 +28,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
        /*=== Realtek demoboard ===*/
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
+       {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill USB-N150 Nano */
        /*=== Customer ID ===*/
        /****** 8188EUS ********/
        {USB_DEVICE(0x07B8, 0x8179)}, /* Abocom - Abocom */
index 2326aae..bb7db96 100644 (file)
@@ -117,34 +117,6 @@ static void r871x_internal_cmd_hdl(struct _adapter *padapter, u8 *pbuf)
        kfree(pdrvcmd->pbuf);
 }
 
-static u8 read_macreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
-       void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj      *pcmd);
-       struct cmd_obj *pcmd  = (struct cmd_obj *)pbuf;
-
-       /*  invoke cmd->callback function */
-       pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
-       if (!pcmd_callback)
-               r8712_free_cmd_obj(pcmd);
-       else
-               pcmd_callback(padapter, pcmd);
-       return H2C_SUCCESS;
-}
-
-static u8 write_macreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
-       void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj      *pcmd);
-       struct cmd_obj *pcmd  = (struct cmd_obj *)pbuf;
-
-       /*  invoke cmd->callback function */
-       pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
-       if (!pcmd_callback)
-               r8712_free_cmd_obj(pcmd);
-       else
-               pcmd_callback(padapter, pcmd);
-       return H2C_SUCCESS;
-}
-
 static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf)
 {
        struct cmd_obj *pcmd  = (struct cmd_obj *)pbuf;
@@ -213,14 +185,6 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter,
        pcmd_r = NULL;
 
        switch (pcmd->cmdcode) {
-       case GEN_CMD_CODE(_Read_MACREG):
-               read_macreg_hdl(padapter, (u8 *)pcmd);
-               pcmd_r = pcmd;
-               break;
-       case GEN_CMD_CODE(_Write_MACREG):
-               write_macreg_hdl(padapter, (u8 *)pcmd);
-               pcmd_r = pcmd;
-               break;
        case GEN_CMD_CODE(_Read_BBREG):
                read_bbreg_hdl(padapter, (u8 *)pcmd);
                break;
index 1175f3a..27295bd 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/tee_drv.h>
+#include <linux/uaccess.h>
 #include <linux/uio.h>
 #include "tee_private.h"
 
index e76a6c1..f12d0a3 100644 (file)
@@ -29,8 +29,7 @@ config USB4_DEBUGFS_WRITE
 
 config USB4_KUNIT_TEST
        bool "KUnit tests" if !KUNIT_ALL_TESTS
-       depends on (USB4=m || KUNIT=y)
-       depends on KUNIT
+       depends on USB4 && KUNIT=y
        default KUNIT_ALL_TESTS
 
 config USB4_DMA_TEST
index b1f0dc8..7a8adf5 100644 (file)
@@ -42,7 +42,7 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
         */
        dev = acpi_get_first_physical_node(adev);
        while (!dev) {
-               adev = adev->parent;
+               adev = acpi_dev_parent(adev);
                if (!adev)
                        break;
                dev = acpi_get_first_physical_node(adev);
index e5ede5d..0c661a7 100644 (file)
@@ -407,7 +407,7 @@ static void tb_ctl_rx_submit(struct ctl_pkg *pkg)
 
 static int tb_async_error(const struct ctl_pkg *pkg)
 {
-       const struct cfg_error_pkg *error = (const struct cfg_error_pkg *)pkg;
+       const struct cfg_error_pkg *error = pkg->buffer;
 
        if (pkg->frame.eof != TB_CFG_PKG_ERROR)
                return false;
index ae38f0d..572b589 100644 (file)
@@ -2529,6 +2529,7 @@ struct tb *icm_probe(struct tb_nhi *nhi)
                tb->cm_ops = &icm_icl_ops;
                break;
 
+       case PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_2C_NHI:
        case PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_4C_NHI:
                icm->is_supported = icm_tgl_is_supported;
                icm->get_mode = icm_ar_get_mode;
index f09da5b..01190d9 100644 (file)
@@ -55,6 +55,7 @@ extern const struct tb_nhi_ops icl_nhi_ops;
  * need for the PCI quirk anymore as we will use ICM also on Apple
  * hardware.
  */
+#define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_2C_NHI         0x1134
 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_4C_NHI         0x1137
 #define PCI_DEVICE_ID_INTEL_WIN_RIDGE_2C_NHI            0x157d
 #define PCI_DEVICE_ID_INTEL_WIN_RIDGE_2C_BRIDGE         0x157e
index 244f8cd..77d7f07 100644 (file)
@@ -2413,6 +2413,7 @@ int tb_switch_configure(struct tb_switch *sw)
                 * additional capabilities.
                 */
                sw->config.cmuv = USB4_VERSION_1_0;
+               sw->config.plug_events_delay = 0xa;
 
                /* Enumerate the switch */
                ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH,
@@ -3786,14 +3787,18 @@ int tb_switch_pcie_l1_enable(struct tb_switch *sw)
  */
 int tb_switch_xhci_connect(struct tb_switch *sw)
 {
-       bool usb_port1, usb_port3, xhci_port1, xhci_port3;
        struct tb_port *port1, *port3;
        int ret;
 
+       if (sw->generation != 3)
+               return 0;
+
        port1 = &sw->ports[1];
        port3 = &sw->ports[3];
 
        if (tb_switch_is_alpine_ridge(sw)) {
+               bool usb_port1, usb_port3, xhci_port1, xhci_port3;
+
                usb_port1 = tb_lc_is_usb_plugged(port1);
                usb_port3 = tb_lc_is_usb_plugged(port3);
                xhci_port1 = tb_lc_is_xhci_connected(port1);
index caa5c14..01c112e 100644 (file)
@@ -248,7 +248,7 @@ struct gsm_mux {
        bool constipated;               /* Asked by remote to shut up */
        bool has_devices;               /* Devices were registered */
 
-       spinlock_t tx_lock;
+       struct mutex tx_mutex;
        unsigned int tx_bytes;          /* TX data outstanding */
 #define TX_THRESH_HI           8192
 #define TX_THRESH_LO           2048
@@ -256,7 +256,7 @@ struct gsm_mux {
        struct list_head tx_data_list;  /* Pending data packets */
 
        /* Control messages */
-       struct timer_list kick_timer;   /* Kick TX queuing on timeout */
+       struct delayed_work kick_timeout;       /* Kick TX queuing on timeout */
        struct timer_list t2_timer;     /* Retransmit timer for commands */
        int cretries;                   /* Command retry counter */
        struct gsm_control *pending_cmd;/* Our current pending command */
@@ -680,7 +680,6 @@ static int gsm_send(struct gsm_mux *gsm, int addr, int cr, int control)
        struct gsm_msg *msg;
        u8 *dp;
        int ocr;
-       unsigned long flags;
 
        msg = gsm_data_alloc(gsm, addr, 0, control);
        if (!msg)
@@ -702,10 +701,10 @@ static int gsm_send(struct gsm_mux *gsm, int addr, int cr, int control)
 
        gsm_print_packet("Q->", addr, cr, control, NULL, 0);
 
-       spin_lock_irqsave(&gsm->tx_lock, flags);
+       mutex_lock(&gsm->tx_mutex);
        list_add_tail(&msg->list, &gsm->tx_ctrl_list);
        gsm->tx_bytes += msg->len;
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
+       mutex_unlock(&gsm->tx_mutex);
        gsmld_write_trigger(gsm);
 
        return 0;
@@ -730,7 +729,7 @@ static void gsm_dlci_clear_queues(struct gsm_mux *gsm, struct gsm_dlci *dlci)
        spin_unlock_irqrestore(&dlci->lock, flags);
 
        /* Clear data packets in MUX write queue */
-       spin_lock_irqsave(&gsm->tx_lock, flags);
+       mutex_lock(&gsm->tx_mutex);
        list_for_each_entry_safe(msg, nmsg, &gsm->tx_data_list, list) {
                if (msg->addr != addr)
                        continue;
@@ -738,7 +737,7 @@ static void gsm_dlci_clear_queues(struct gsm_mux *gsm, struct gsm_dlci *dlci)
                list_del(&msg->list);
                kfree(msg);
        }
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
+       mutex_unlock(&gsm->tx_mutex);
 }
 
 /**
@@ -1009,7 +1008,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
        gsm->tx_bytes += msg->len;
 
        gsmld_write_trigger(gsm);
-       mod_timer(&gsm->kick_timer, jiffies + 10 * gsm->t1 * HZ / 100);
+       schedule_delayed_work(&gsm->kick_timeout, 10 * gsm->t1 * HZ / 100);
 }
 
 /**
@@ -1024,10 +1023,9 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
 
 static void gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
 {
-       unsigned long flags;
-       spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
+       mutex_lock(&dlci->gsm->tx_mutex);
        __gsm_data_queue(dlci, msg);
-       spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
+       mutex_unlock(&dlci->gsm->tx_mutex);
 }
 
 /**
@@ -1039,7 +1037,7 @@ static void gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
  *     is data. Keep to the MRU of the mux. This path handles the usual tty
  *     interface which is a byte stream with optional modem data.
  *
- *     Caller must hold the tx_lock of the mux.
+ *     Caller must hold the tx_mutex of the mux.
  */
 
 static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
@@ -1099,7 +1097,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
  *     is data. Keep to the MRU of the mux. This path handles framed data
  *     queued as skbuffs to the DLCI.
  *
- *     Caller must hold the tx_lock of the mux.
+ *     Caller must hold the tx_mutex of the mux.
  */
 
 static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
@@ -1115,7 +1113,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
        if (dlci->adaption == 4)
                overhead = 1;
 
-       /* dlci->skb is locked by tx_lock */
+       /* dlci->skb is locked by tx_mutex */
        if (dlci->skb == NULL) {
                dlci->skb = skb_dequeue_tail(&dlci->skb_list);
                if (dlci->skb == NULL)
@@ -1169,7 +1167,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
  *     Push an empty frame in to the transmit queue to update the modem status
  *     bits and to transmit an optional break.
  *
- *     Caller must hold the tx_lock of the mux.
+ *     Caller must hold the tx_mutex of the mux.
  */
 
 static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci,
@@ -1283,13 +1281,12 @@ static int gsm_dlci_data_sweep(struct gsm_mux *gsm)
 
 static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
 {
-       unsigned long flags;
        int sweep;
 
        if (dlci->constipated)
                return;
 
-       spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
+       mutex_lock(&dlci->gsm->tx_mutex);
        /* If we have nothing running then we need to fire up */
        sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO);
        if (dlci->gsm->tx_bytes == 0) {
@@ -1300,7 +1297,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
        }
        if (sweep)
                gsm_dlci_data_sweep(dlci->gsm);
-       spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
+       mutex_unlock(&dlci->gsm->tx_mutex);
 }
 
 /*
@@ -1984,24 +1981,23 @@ static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len)
 }
 
 /**
- *     gsm_kick_timer  -       transmit if possible
- *     @t: timer contained in our gsm object
+ *     gsm_kick_timeout        -       transmit if possible
+ *     @work: work contained in our gsm object
  *
  *     Transmit data from DLCIs if the queue is empty. We can't rely on
  *     a tty wakeup except when we filled the pipe so we need to fire off
  *     new data ourselves in other cases.
  */
-static void gsm_kick_timer(struct timer_list *t)
+static void gsm_kick_timeout(struct work_struct *work)
 {
-       struct gsm_mux *gsm = from_timer(gsm, t, kick_timer);
-       unsigned long flags;
+       struct gsm_mux *gsm = container_of(work, struct gsm_mux, kick_timeout.work);
        int sent = 0;
 
-       spin_lock_irqsave(&gsm->tx_lock, flags);
+       mutex_lock(&gsm->tx_mutex);
        /* If we have nothing running then we need to fire up */
        if (gsm->tx_bytes < TX_THRESH_LO)
                sent = gsm_dlci_data_sweep(gsm);
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
+       mutex_unlock(&gsm->tx_mutex);
 
        if (sent && debug & 4)
                pr_info("%s TX queue stalled\n", __func__);
@@ -2458,7 +2454,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
        }
 
        /* Finish outstanding timers, making sure they are done */
-       del_timer_sync(&gsm->kick_timer);
+       cancel_delayed_work_sync(&gsm->kick_timeout);
        del_timer_sync(&gsm->t2_timer);
 
        /* Finish writing to ldisc */
@@ -2501,13 +2497,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
        if (dlci == NULL)
                return -ENOMEM;
 
-       timer_setup(&gsm->kick_timer, gsm_kick_timer, 0);
-       timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
-       INIT_WORK(&gsm->tx_work, gsmld_write_task);
-       init_waitqueue_head(&gsm->event);
-       spin_lock_init(&gsm->control_lock);
-       spin_lock_init(&gsm->tx_lock);
-
        if (gsm->encoding == 0)
                gsm->receive = gsm0_receive;
        else
@@ -2538,6 +2527,7 @@ static void gsm_free_mux(struct gsm_mux *gsm)
                        break;
                }
        }
+       mutex_destroy(&gsm->tx_mutex);
        mutex_destroy(&gsm->mutex);
        kfree(gsm->txframe);
        kfree(gsm->buf);
@@ -2609,9 +2599,15 @@ static struct gsm_mux *gsm_alloc_mux(void)
        }
        spin_lock_init(&gsm->lock);
        mutex_init(&gsm->mutex);
+       mutex_init(&gsm->tx_mutex);
        kref_init(&gsm->ref);
        INIT_LIST_HEAD(&gsm->tx_ctrl_list);
        INIT_LIST_HEAD(&gsm->tx_data_list);
+       INIT_DELAYED_WORK(&gsm->kick_timeout, gsm_kick_timeout);
+       timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
+       INIT_WORK(&gsm->tx_work, gsmld_write_task);
+       init_waitqueue_head(&gsm->event);
+       spin_lock_init(&gsm->control_lock);
 
        gsm->t1 = T1;
        gsm->t2 = T2;
@@ -2636,6 +2632,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
        }
        spin_unlock(&gsm_mux_lock);
        if (i == MAX_MUX) {
+               mutex_destroy(&gsm->tx_mutex);
                mutex_destroy(&gsm->mutex);
                kfree(gsm->txframe);
                kfree(gsm->buf);
@@ -2791,17 +2788,16 @@ static void gsmld_write_trigger(struct gsm_mux *gsm)
 static void gsmld_write_task(struct work_struct *work)
 {
        struct gsm_mux *gsm = container_of(work, struct gsm_mux, tx_work);
-       unsigned long flags;
        int i, ret;
 
        /* All outstanding control channel and control messages and one data
         * frame is sent.
         */
        ret = -ENODEV;
-       spin_lock_irqsave(&gsm->tx_lock, flags);
+       mutex_lock(&gsm->tx_mutex);
        if (gsm->tty)
                ret = gsm_data_kick(gsm);
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
+       mutex_unlock(&gsm->tx_mutex);
 
        if (ret >= 0)
                for (i = 0; i < NUM_DLCI; i++)
@@ -2858,7 +2854,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                        flags = *fp++;
                switch (flags) {
                case TTY_NORMAL:
-                       gsm->receive(gsm, *cp);
+                       if (gsm->receive)
+                               gsm->receive(gsm, *cp);
                        break;
                case TTY_OVERRUN:
                case TTY_BREAK:
@@ -2946,10 +2943,6 @@ static int gsmld_open(struct tty_struct *tty)
 
        gsmld_attach_gsm(tty, gsm);
 
-       timer_setup(&gsm->kick_timer, gsm_kick_timer, 0);
-       timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
-       INIT_WORK(&gsm->tx_work, gsmld_write_task);
-
        return 0;
 }
 
@@ -3012,7 +3005,6 @@ static ssize_t gsmld_write(struct tty_struct *tty, struct file *file,
                           const unsigned char *buf, size_t nr)
 {
        struct gsm_mux *gsm = tty->disc_data;
-       unsigned long flags;
        int space;
        int ret;
 
@@ -3020,13 +3012,13 @@ static ssize_t gsmld_write(struct tty_struct *tty, struct file *file,
                return -ENODEV;
 
        ret = -ENOBUFS;
-       spin_lock_irqsave(&gsm->tx_lock, flags);
+       mutex_lock(&gsm->tx_mutex);
        space = tty_write_room(tty);
        if (space >= nr)
                ret = tty->ops->write(tty, buf, nr);
        else
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
+       mutex_unlock(&gsm->tx_mutex);
 
        return ret;
 }
@@ -3323,14 +3315,13 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
 static void gsm_modem_upd_via_data(struct gsm_dlci *dlci, u8 brk)
 {
        struct gsm_mux *gsm = dlci->gsm;
-       unsigned long flags;
 
        if (dlci->state != DLCI_OPEN || dlci->adaption != 2)
                return;
 
-       spin_lock_irqsave(&gsm->tx_lock, flags);
+       mutex_lock(&gsm->tx_mutex);
        gsm_dlci_modem_output(gsm, dlci, brk);
-       spin_unlock_irqrestore(&gsm->tx_lock, flags);
+       mutex_unlock(&gsm->tx_mutex);
 }
 
 /**
index 0dcecbb..f7fbef8 100644 (file)
@@ -1334,6 +1334,7 @@ static int omap8250_probe(struct platform_device *pdev)
        up.port.throttle = omap_8250_throttle;
        up.port.unthrottle = omap_8250_unthrottle;
        up.port.rs485_config = serial8250_em485_config;
+       up.port.rs485_supported = serial8250_em485_supported;
        up.rs485_start_tx = serial8250_em485_start_tx;
        up.rs485_stop_tx = serial8250_em485_stop_tx;
        up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
index 30ba9ee..7450d38 100644 (file)
@@ -294,9 +294,6 @@ static int atmel_config_rs485(struct uart_port *port, struct ktermios *termios,
 
        mode = atmel_uart_readl(port, ATMEL_US_MR);
 
-       /* Resetting serial mode to RS232 (0x0) */
-       mode &= ~ATMEL_US_USMODE;
-
        if (rs485conf->flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
                if (rs485conf->flags & SER_RS485_RX_DURING_TX)
@@ -306,6 +303,7 @@ static int atmel_config_rs485(struct uart_port *port, struct ktermios *termios,
 
                atmel_uart_writel(port, ATMEL_US_TTGR,
                                  rs485conf->delay_rts_after_send);
+               mode &= ~ATMEL_US_USMODE;
                mode |= ATMEL_US_USMODE_RS485;
        } else {
                dev_dbg(port->dev, "Setting UART to RS232\n");
index f6c33cd..fbc4b07 100644 (file)
@@ -1394,9 +1394,9 @@ static int lpuart_config_rs485(struct uart_port *port, struct ktermios *termios,
                 * Note: UART is assumed to be active high.
                 */
                if (rs485->flags & SER_RS485_RTS_ON_SEND)
-                       modem &= ~UARTMODEM_TXRTSPOL;
-               else if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
                        modem |= UARTMODEM_TXRTSPOL;
+               else if (rs485->flags & SER_RS485_RTS_AFTER_SEND)
+                       modem &= ~UARTMODEM_TXRTSPOL;
        }
 
        writeb(modem, sport->port.membase + UARTMODEM);
@@ -2191,6 +2191,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
        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);
 
        /* disable transmit and receive */
@@ -2723,14 +2724,15 @@ static int lpuart_probe(struct platform_device *pdev)
                lpuart_reg.cons = LPUART_CONSOLE;
                handler = lpuart_int;
        }
-       ret = uart_add_one_port(&lpuart_reg, &sport->port);
-       if (ret)
-               goto failed_attach_port;
 
        ret = lpuart_global_reset(sport);
        if (ret)
                goto failed_reset;
 
+       ret = uart_add_one_port(&lpuart_reg, &sport->port);
+       if (ret)
+               goto failed_attach_port;
+
        ret = uart_get_rs485_mode(&sport->port);
        if (ret)
                goto failed_get_rs485;
@@ -2746,9 +2748,9 @@ static int lpuart_probe(struct platform_device *pdev)
 
 failed_irq_request:
 failed_get_rs485:
-failed_reset:
        uart_remove_one_port(&lpuart_reg, &sport->port);
 failed_attach_port:
+failed_reset:
        lpuart_disable_clks(sport);
        return ret;
 }
index ad4f356..a5748e4 100644 (file)
@@ -525,7 +525,7 @@ static void tegra_uart_tx_dma_complete(void *args)
        count = tup->tx_bytes_requested - state.residue;
        async_tx_ack(tup->tx_dma_desc);
        spin_lock_irqsave(&tup->uport.lock, flags);
-       xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+       uart_xmit_advance(&tup->uport, count);
        tup->tx_in_progress = 0;
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&tup->uport);
@@ -613,7 +613,6 @@ static unsigned int tegra_uart_tx_empty(struct uart_port *u)
 static void tegra_uart_stop_tx(struct uart_port *u)
 {
        struct tegra_uart_port *tup = to_tegra_uport(u);
-       struct circ_buf *xmit = &tup->uport.state->xmit;
        struct dma_tx_state state;
        unsigned int count;
 
@@ -624,7 +623,7 @@ static void tegra_uart_stop_tx(struct uart_port *u)
        dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
        count = tup->tx_bytes_requested - state.residue;
        async_tx_ack(tup->tx_dma_desc);
-       xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+       uart_xmit_advance(&tup->uport, count);
        tup->tx_in_progress = 0;
 }
 
index 5c3a075..4b1d4fe 100644 (file)
@@ -945,7 +945,7 @@ static int sifive_serial_probe(struct platform_device *pdev)
                return PTR_ERR(base);
        }
 
-       clk = devm_clk_get(&pdev->dev, NULL);
+       clk = devm_clk_get_enabled(&pdev->dev, NULL);
        if (IS_ERR(clk)) {
                dev_err(&pdev->dev, "unable to find controller clock\n");
                return PTR_ERR(clk);
index 4877c54..889b701 100644 (file)
@@ -101,7 +101,7 @@ static void tegra_tcu_uart_start_tx(struct uart_port *port)
                        break;
 
                tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count);
-               xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+               uart_xmit_advance(port, count);
        }
 
        uart_write_wakeup(port);
index 9fdecc7..5e287de 100644 (file)
@@ -470,7 +470,6 @@ static void lookahead_bufs(struct tty_port *port, struct tty_buffer *head)
 
        while (head) {
                struct tty_buffer *next;
-               unsigned char *p, *f = NULL;
                unsigned int count;
 
                /*
@@ -489,11 +488,16 @@ static void lookahead_bufs(struct tty_port *port, struct tty_buffer *head)
                        continue;
                }
 
-               p = char_buf_ptr(head, head->lookahead);
-               if (~head->flags & TTYB_NORMAL)
-                       f = flag_buf_ptr(head, head->lookahead);
+               if (port->client_ops->lookahead_buf) {
+                       unsigned char *p, *f = NULL;
+
+                       p = char_buf_ptr(head, head->lookahead);
+                       if (~head->flags & TTYB_NORMAL)
+                               f = flag_buf_ptr(head, head->lookahead);
+
+                       port->client_ops->lookahead_buf(port, p, f, count);
+               }
 
-               port->client_ops->lookahead_buf(port, p, f, count);
                head->lookahead += count;
        }
 }
index ae9c926..0b669c8 100644 (file)
@@ -4662,9 +4662,11 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
        console_lock();
        if (vc->vc_mode != KD_TEXT)
                rc = -EINVAL;
-       else if (vc->vc_sw->con_font_set)
+       else if (vc->vc_sw->con_font_set) {
+               if (vc_is_sel(vc))
+                       clear_selection();
                rc = vc->vc_sw->con_font_set(vc, &font, op->flags);
-       else
+       else
                rc = -ENOSYS;
        console_unlock();
        kfree(font.data);
@@ -4691,9 +4693,11 @@ static int con_font_default(struct vc_data *vc, struct console_font_op *op)
                console_unlock();
                return -EINVAL;
        }
-       if (vc->vc_sw->con_font_default)
+       if (vc->vc_sw->con_font_default) {
+               if (vc_is_sel(vc))
+                       clear_selection();
                rc = vc->vc_sw->con_font_default(vc, &font, s);
-       else
+       else
                rc = -ENOSYS;
        console_unlock();
        if (!rc) {
index d21b699..5adcb34 100644 (file)
@@ -1530,7 +1530,8 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
                                                TRB_LEN(le32_to_cpu(trb->length));
 
                                if (priv_req->num_of_trb > 1 &&
-                                       le32_to_cpu(trb->control) & TRB_SMM)
+                                       le32_to_cpu(trb->control) & TRB_SMM &&
+                                       le32_to_cpu(trb->control) & TRB_CHAIN)
                                        transfer_end = true;
 
                                cdns3_ep_inc_deq(priv_ep);
@@ -1690,6 +1691,7 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep)
                                ep_cfg &= ~EP_CFG_ENABLE;
                                writel(ep_cfg, &priv_dev->regs->ep_cfg);
                                priv_ep->flags &= ~EP_QUIRK_ISO_OUT_EN;
+                               priv_ep->flags |= EP_UPDATE_EP_TRBADDR;
                        }
                        cdns3_transfer_completed(priv_dev, priv_ep);
                } else if (!(priv_ep->flags & EP_STALLED) &&
index 483bcb1..cc637c4 100644 (file)
@@ -1810,6 +1810,9 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */
        .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */
        },
+       { USB_DEVICE(0x0c26, 0x0020), /* Icom ICF3400 Serie */
+       .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
+       },
        { USB_DEVICE(0x0ca6, 0xa050), /* Castles VEGA3000 */
        .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
        },
index 2633acd..bbab424 100644 (file)
@@ -6038,6 +6038,11 @@ re_enumerate:
  * the reset is over (using their post_reset method).
  *
  * Return: The same as for usb_reset_and_verify_device().
+ * However, if a reset is already in progress (for instance, if a
+ * driver doesn't have pre_reset() or post_reset() callbacks, and while
+ * being unbound or re-bound during the ongoing reset its disconnect()
+ * or probe() routine tries to perform a second, nested reset), the
+ * routine returns -EINPROGRESS.
  *
  * Note:
  * The caller must own the device lock.  For example, it's safe to use
@@ -6071,6 +6076,10 @@ int usb_reset_device(struct usb_device *udev)
                return -EISDIR;
        }
 
+       if (udev->reset_in_progress)
+               return -EINPROGRESS;
+       udev->reset_in_progress = 1;
+
        port_dev = hub->ports[udev->portnum - 1];
 
        /*
@@ -6135,6 +6144,7 @@ int usb_reset_device(struct usb_device *udev)
 
        usb_autosuspend_device(udev);
        memalloc_noio_restore(noio_flag);
+       udev->reset_in_progress = 0;
        return ret;
 }
 EXPORT_SYMBOL_GPL(usb_reset_device);
index c8ba87d..fd0ccf6 100644 (file)
@@ -154,9 +154,9 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
        } else if (hsotg->plat && hsotg->plat->phy_init) {
                ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
        } else {
-               ret = phy_power_on(hsotg->phy);
+               ret = phy_init(hsotg->phy);
                if (ret == 0)
-                       ret = phy_init(hsotg->phy);
+                       ret = phy_power_on(hsotg->phy);
        }
 
        return ret;
@@ -188,9 +188,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
        } else if (hsotg->plat && hsotg->plat->phy_exit) {
                ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
        } else {
-               ret = phy_exit(hsotg->phy);
+               ret = phy_power_off(hsotg->phy);
                if (ret == 0)
-                       ret = phy_power_off(hsotg->phy);
+                       ret = phy_exit(hsotg->phy);
        }
        if (ret)
                return ret;
index c5c238a..d0237b3 100644 (file)
@@ -833,15 +833,16 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 {
        dwc3_event_buffers_cleanup(dwc);
 
+       usb_phy_set_suspend(dwc->usb2_phy, 1);
+       usb_phy_set_suspend(dwc->usb3_phy, 1);
+       phy_power_off(dwc->usb2_generic_phy);
+       phy_power_off(dwc->usb3_generic_phy);
+
        usb_phy_shutdown(dwc->usb2_phy);
        usb_phy_shutdown(dwc->usb3_phy);
        phy_exit(dwc->usb2_generic_phy);
        phy_exit(dwc->usb3_generic_phy);
 
-       usb_phy_set_suspend(dwc->usb2_phy, 1);
-       usb_phy_set_suspend(dwc->usb3_phy, 1);
-       phy_power_off(dwc->usb2_generic_phy);
-       phy_power_off(dwc->usb3_generic_phy);
        dwc3_clk_disable(dwc);
        reset_control_assert(dwc->reset);
 }
@@ -1751,12 +1752,6 @@ static int dwc3_probe(struct platform_device *pdev)
 
        dwc3_get_properties(dwc);
 
-       if (!dwc->sysdev_is_parent) {
-               ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
-               if (ret)
-                       return ret;
-       }
-
        dwc->reset = devm_reset_control_array_get_optional_shared(dev);
        if (IS_ERR(dwc->reset))
                return PTR_ERR(dwc->reset);
@@ -1821,7 +1816,13 @@ static int dwc3_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dwc);
        dwc3_cache_hwparams(dwc);
-       device_init_wakeup(&pdev->dev, of_property_read_bool(dev->of_node, "wakeup-source"));
+
+       if (!dwc->sysdev_is_parent &&
+           DWC3_GHWPARAMS0_AWIDTH(dwc->hwparams.hwparams0) == 64) {
+               ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
+               if (ret)
+                       goto disable_clks;
+       }
 
        spin_lock_init(&dwc->lock);
        mutex_init(&dwc->mutex);
@@ -1879,16 +1880,16 @@ err5:
        dwc3_debugfs_exit(dwc);
        dwc3_event_buffers_cleanup(dwc);
 
-       usb_phy_shutdown(dwc->usb2_phy);
-       usb_phy_shutdown(dwc->usb3_phy);
-       phy_exit(dwc->usb2_generic_phy);
-       phy_exit(dwc->usb3_generic_phy);
-
        usb_phy_set_suspend(dwc->usb2_phy, 1);
        usb_phy_set_suspend(dwc->usb3_phy, 1);
        phy_power_off(dwc->usb2_generic_phy);
        phy_power_off(dwc->usb3_generic_phy);
 
+       usb_phy_shutdown(dwc->usb2_phy);
+       usb_phy_shutdown(dwc->usb3_phy);
+       phy_exit(dwc->usb2_generic_phy);
+       phy_exit(dwc->usb3_generic_phy);
+
        dwc3_ulpi_exit(dwc);
 
 err4:
@@ -1983,7 +1984,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
                dwc3_core_exit(dwc);
                break;
        case DWC3_GCTL_PRTCAP_HOST:
-               if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) {
+               if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) {
                        dwc3_core_exit(dwc);
                        break;
                }
@@ -2044,7 +2045,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
                spin_unlock_irqrestore(&dwc->lock, flags);
                break;
        case DWC3_GCTL_PRTCAP_HOST:
-               if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) {
+               if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) {
                        ret = dwc3_core_init_for_resume(dwc);
                        if (ret)
                                return ret;
index 6b01804..4ee4ca0 100644 (file)
@@ -44,6 +44,7 @@
 #define PCI_DEVICE_ID_INTEL_ADLP               0x51ee
 #define PCI_DEVICE_ID_INTEL_ADLM               0x54ee
 #define PCI_DEVICE_ID_INTEL_ADLS               0x7ae1
+#define PCI_DEVICE_ID_INTEL_RPL                        0x460e
 #define PCI_DEVICE_ID_INTEL_RPLS               0x7a61
 #define PCI_DEVICE_ID_INTEL_MTLP               0x7ec1
 #define PCI_DEVICE_ID_INTEL_MTL                        0x7e7e
@@ -456,6 +457,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS),
          (kernel_ulong_t) &dwc3_pci_intel_swnode, },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL),
+         (kernel_ulong_t) &dwc3_pci_intel_swnode, },
+
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS),
          (kernel_ulong_t) &dwc3_pci_intel_swnode, },
 
index c5e482f..d3f3937 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
-#include <linux/pm_domain.h>
 #include <linux/usb/of.h>
 #include <linux/reset.h>
 #include <linux/iopoll.h>
@@ -299,11 +298,24 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
        icc_put(qcom->icc_path_apps);
 }
 
+/* Only usable in contexts where the role can not change. */
+static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom)
+{
+       struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
+
+       return dwc->xhci;
+}
+
 static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom)
 {
        struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
-       struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci);
        struct usb_device *udev;
+       struct usb_hcd __maybe_unused *hcd;
+
+       /*
+        * FIXME: Fix this layering violation.
+        */
+       hcd = platform_get_drvdata(dwc->xhci);
 
        /*
         * It is possible to query the speed of all children of
@@ -311,8 +323,11 @@ static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom)
         * currently supports only 1 port per controller. So
         * this is sufficient.
         */
+#ifdef CONFIG_USB
        udev = usb_hub_find_child(hcd->self.root_hub, 1);
-
+#else
+       udev = NULL;
+#endif
        if (!udev)
                return USB_SPEED_UNKNOWN;
 
@@ -387,7 +402,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
        dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0);
 }
 
-static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
+static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
 {
        u32 val;
        int i, ret;
@@ -406,7 +421,11 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
        if (ret)
                dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
 
-       if (device_may_wakeup(qcom->dev)) {
+       /*
+        * The role is stable during suspend as role switching is done from a
+        * freezable workqueue.
+        */
+       if (dwc3_qcom_is_host(qcom) && wakeup) {
                qcom->usb2_speed = dwc3_qcom_read_usb2_speed(qcom);
                dwc3_qcom_enable_interrupts(qcom);
        }
@@ -416,7 +435,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
        return 0;
 }
 
-static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
+static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup)
 {
        int ret;
        int i;
@@ -424,7 +443,7 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
        if (!qcom->is_suspended)
                return 0;
 
-       if (device_may_wakeup(qcom->dev))
+       if (dwc3_qcom_is_host(qcom) && wakeup)
                dwc3_qcom_disable_interrupts(qcom);
 
        for (i = 0; i < qcom->num_clocks; i++) {
@@ -458,7 +477,11 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data)
        if (qcom->pm_suspended)
                return IRQ_HANDLED;
 
-       if (dwc->xhci)
+       /*
+        * This is safe as role switching is done from a freezable workqueue
+        * and the wakeup interrupts are disabled as part of resume.
+        */
+       if (dwc3_qcom_is_host(qcom))
                pm_runtime_resume(&dwc->xhci->dev);
 
        return IRQ_HANDLED;
@@ -757,13 +780,13 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
 
 static int dwc3_qcom_probe(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
-       struct device *dev = &pdev->dev;
-       struct dwc3_qcom *qcom;
-       struct resource *res, *parent_res = NULL;
-       int ret, i;
-       bool ignore_pipe_clk;
-       struct generic_pm_domain *genpd;
+       struct device_node      *np = pdev->dev.of_node;
+       struct device           *dev = &pdev->dev;
+       struct dwc3_qcom        *qcom;
+       struct resource         *res, *parent_res = NULL;
+       int                     ret, i;
+       bool                    ignore_pipe_clk;
+       bool                    wakeup_source;
 
        qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
        if (!qcom)
@@ -772,8 +795,6 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, qcom);
        qcom->dev = &pdev->dev;
 
-       genpd = pd_to_genpd(qcom->dev->pm_domain);
-
        if (has_acpi_companion(dev)) {
                qcom->acpi_pdata = acpi_device_get_match_data(dev);
                if (!qcom->acpi_pdata) {
@@ -881,16 +902,9 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
        if (ret)
                goto interconnect_exit;
 
-       if (device_can_wakeup(&qcom->dwc3->dev)) {
-               /*
-                * Setting GENPD_FLAG_ALWAYS_ON flag takes care of keeping
-                * genpd on in both runtime suspend and system suspend cases.
-                */
-               genpd->flags |= GENPD_FLAG_ALWAYS_ON;
-               device_init_wakeup(&pdev->dev, true);
-       } else {
-               genpd->flags |= GENPD_FLAG_RPM_ALWAYS_ON;
-       }
+       wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source");
+       device_init_wakeup(&pdev->dev, wakeup_source);
+       device_init_wakeup(&qcom->dwc3->dev, wakeup_source);
 
        qcom->is_suspended = false;
        pm_runtime_set_active(dev);
@@ -944,39 +958,45 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
 static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
 {
        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
-       int ret = 0;
+       bool wakeup = device_may_wakeup(dev);
+       int ret;
 
-       ret = dwc3_qcom_suspend(qcom);
-       if (!ret)
-               qcom->pm_suspended = true;
+       ret = dwc3_qcom_suspend(qcom, wakeup);
+       if (ret)
+               return ret;
 
-       return ret;
+       qcom->pm_suspended = true;
+
+       return 0;
 }
 
 static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
 {
        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
+       bool wakeup = device_may_wakeup(dev);
        int ret;
 
-       ret = dwc3_qcom_resume(qcom);
-       if (!ret)
-               qcom->pm_suspended = false;
+       ret = dwc3_qcom_resume(qcom, wakeup);
+       if (ret)
+               return ret;
 
-       return ret;
+       qcom->pm_suspended = false;
+
+       return 0;
 }
 
 static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
 {
        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 
-       return dwc3_qcom_suspend(qcom);
+       return dwc3_qcom_suspend(qcom, true);
 }
 
 static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
 {
        struct dwc3_qcom *qcom = dev_get_drvdata(dev);
 
-       return dwc3_qcom_resume(qcom);
+       return dwc3_qcom_resume(qcom, true);
 }
 
 static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
index 166b5bd..6c14a79 100644 (file)
@@ -251,7 +251,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
        /* Manage SoftReset */
        reset_control_deassert(dwc3_data->rstc_rst);
 
-       child = of_get_child_by_name(node, "dwc3");
+       child = of_get_child_by_name(node, "usb");
        if (!child) {
                dev_err(&pdev->dev, "failed to find dwc3 core node\n");
                ret = -ENODEV;
index aeeec75..eca945f 100644 (file)
@@ -2539,9 +2539,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 
        is_on = !!is_on;
 
-       if (dwc->pullups_connected == is_on)
-               return 0;
-
        dwc->softconnect = is_on;
 
        /*
@@ -2566,6 +2563,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
                return 0;
        }
 
+       if (dwc->pullups_connected == is_on) {
+               pm_runtime_put(dwc->dev);
+               return 0;
+       }
+
        if (!is_on) {
                ret = dwc3_gadget_soft_disconnect(dwc);
        } else {
index f56c30c..a7154fe 100644 (file)
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
+#include "../host/xhci-plat.h"
 #include "core.h"
 
+static const struct xhci_plat_priv dwc3_xhci_plat_priv = {
+       .quirks = XHCI_SKIP_PHY_INIT,
+};
+
 static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
                                        int irq, char *name)
 {
@@ -92,6 +97,11 @@ int dwc3_host_init(struct dwc3 *dwc)
                goto err;
        }
 
+       ret = platform_device_add_data(xhci, &dwc3_xhci_plat_priv,
+                                       sizeof(dwc3_xhci_plat_priv));
+       if (ret)
+               goto err;
+
        memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
 
        if (dwc->usb3_lpm_capable)
@@ -135,4 +145,5 @@ err:
 void dwc3_host_exit(struct dwc3 *dwc)
 {
        platform_device_unregister(dwc->xhci);
+       dwc->xhci = NULL;
 }
index 1905a8d..08726e4 100644 (file)
@@ -291,6 +291,12 @@ static struct usb_endpoint_descriptor ss_ep_int_desc = {
        .bInterval = 4,
 };
 
+static struct usb_ss_ep_comp_descriptor ss_ep_int_desc_comp = {
+       .bLength = sizeof(ss_ep_int_desc_comp),
+       .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+       .wBytesPerInterval = cpu_to_le16(6),
+};
+
 /* Audio Streaming OUT Interface - Alt0 */
 static struct usb_interface_descriptor std_as_out_if0_desc = {
        .bLength = sizeof std_as_out_if0_desc,
@@ -604,7 +610,8 @@ static struct usb_descriptor_header *ss_audio_desc[] = {
        (struct usb_descriptor_header *)&in_feature_unit_desc,
        (struct usb_descriptor_header *)&io_out_ot_desc,
 
-  (struct usb_descriptor_header *)&ss_ep_int_desc,
+       (struct usb_descriptor_header *)&ss_ep_int_desc,
+       (struct usb_descriptor_header *)&ss_ep_int_desc_comp,
 
        (struct usb_descriptor_header *)&std_as_out_if0_desc,
        (struct usb_descriptor_header *)&std_as_out_if1_desc,
@@ -800,6 +807,7 @@ static void setup_headers(struct f_uac2_opts *opts,
        struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL;
        struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL;
        struct usb_ss_ep_comp_descriptor *epin_fback_desc_comp = NULL;
+       struct usb_ss_ep_comp_descriptor *ep_int_desc_comp = NULL;
        struct usb_endpoint_descriptor *epout_desc;
        struct usb_endpoint_descriptor *epin_desc;
        struct usb_endpoint_descriptor *epin_fback_desc;
@@ -827,6 +835,7 @@ static void setup_headers(struct f_uac2_opts *opts,
                epin_fback_desc = &ss_epin_fback_desc;
                epin_fback_desc_comp = &ss_epin_fback_desc_comp;
                ep_int_desc = &ss_ep_int_desc;
+               ep_int_desc_comp = &ss_ep_int_desc_comp;
        }
 
        i = 0;
@@ -855,8 +864,11 @@ static void setup_headers(struct f_uac2_opts *opts,
        if (EPOUT_EN(opts))
                headers[i++] = USBDHDR(&io_out_ot_desc);
 
-       if (FUOUT_EN(opts) || FUIN_EN(opts))
+       if (FUOUT_EN(opts) || FUIN_EN(opts)) {
                headers[i++] = USBDHDR(ep_int_desc);
+               if (ep_int_desc_comp)
+                       headers[i++] = USBDHDR(ep_int_desc_comp);
+       }
 
        if (EPOUT_EN(opts)) {
                headers[i++] = USBDHDR(&std_as_out_if0_desc);
index 03035db..208c6a9 100644 (file)
@@ -294,8 +294,10 @@ EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
 void store_cdrom_address(u8 *dest, int msf, u32 addr)
 {
        if (msf) {
-               /* Convert to Minutes-Seconds-Frames */
-               addr >>= 2;             /* Convert to 2048-byte frames */
+               /*
+                * Convert to Minutes-Seconds-Frames.
+                * Sector size is already set to 2048 bytes.
+                */
                addr += 2*75;           /* Lead-in occupies 2 seconds */
                dest[3] = addr % 75;    /* Frames */
                addr /= 75;
index cafcf26..c63c0c2 100644 (file)
@@ -736,7 +736,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
        ret = gadget->ops->pullup(gadget, 0);
        if (!ret) {
                gadget->connected = 0;
-               gadget->udc->driver->disconnect(gadget);
+               mutex_lock(&udc_lock);
+               if (gadget->udc->driver)
+                       gadget->udc->driver->disconnect(gadget);
+               mutex_unlock(&udc_lock);
        }
 
 out:
@@ -1489,7 +1492,6 @@ static int gadget_bind_driver(struct device *dev)
 
        usb_gadget_udc_set_speed(udc, driver->max_speed);
 
-       mutex_lock(&udc_lock);
        ret = driver->bind(udc->gadget, driver);
        if (ret)
                goto err_bind;
@@ -1499,7 +1501,6 @@ static int gadget_bind_driver(struct device *dev)
                goto err_start;
        usb_gadget_enable_async_callbacks(udc);
        usb_udc_connect_control(udc);
-       mutex_unlock(&udc_lock);
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
        return 0;
@@ -1512,6 +1513,7 @@ static int gadget_bind_driver(struct device *dev)
                dev_err(&udc->dev, "failed to start %s: %d\n",
                        driver->function, ret);
 
+       mutex_lock(&udc_lock);
        udc->driver = NULL;
        driver->is_bound = false;
        mutex_unlock(&udc_lock);
@@ -1529,7 +1531,6 @@ static void gadget_unbind_driver(struct device *dev)
 
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
-       mutex_lock(&udc_lock);
        usb_gadget_disconnect(gadget);
        usb_gadget_disable_async_callbacks(udc);
        if (gadget->irq)
@@ -1537,6 +1538,7 @@ static void gadget_unbind_driver(struct device *dev)
        udc->driver->unbind(gadget);
        usb_gadget_udc_stop(udc);
 
+       mutex_lock(&udc_lock);
        driver->is_bound = false;
        udc->driver = NULL;
        mutex_unlock(&udc_lock);
@@ -1612,7 +1614,7 @@ static ssize_t soft_connect_store(struct device *dev,
        struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
        ssize_t                 ret;
 
-       mutex_lock(&udc_lock);
+       device_lock(&udc->gadget->dev);
        if (!udc->driver) {
                dev_err(dev, "soft-connect without a gadget driver\n");
                ret = -EOPNOTSUPP;
@@ -1633,7 +1635,7 @@ static ssize_t soft_connect_store(struct device *dev,
 
        ret = n;
 out:
-       mutex_unlock(&udc_lock);
+       device_unlock(&udc->gadget->dev);
        return ret;
 }
 static DEVICE_ATTR_WO(soft_connect);
@@ -1652,11 +1654,15 @@ static ssize_t function_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
-       struct usb_gadget_driver *drv = udc->driver;
+       struct usb_gadget_driver *drv;
+       int                     rc = 0;
 
-       if (!drv || !drv->function)
-               return 0;
-       return scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
+       mutex_lock(&udc_lock);
+       drv = udc->driver;
+       if (drv && drv->function)
+               rc = scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
+       mutex_unlock(&udc_lock);
+       return rc;
 }
 static DEVICE_ATTR_RO(function);
 
index 0fdc014..4619d5e 100644 (file)
@@ -652,7 +652,7 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
  * It will release and re-aquire the lock while calling ACPI
  * method.
  */
-void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
+static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
                                u16 index, bool on, unsigned long *flags)
        __must_hold(&xhci->lock)
 {
@@ -1648,6 +1648,17 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 
        status = bus_state->resuming_ports;
 
+       /*
+        * SS devices are only visible to roothub after link training completes.
+        * Keep polling roothubs for a grace period after xHC start
+        */
+       if (xhci->run_graceperiod) {
+               if (time_before(jiffies, xhci->run_graceperiod))
+                       status = 1;
+               else
+                       xhci->run_graceperiod = 0;
+       }
+
        mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC;
 
        /* For each port, did anything change?  If so, set that bit in buf. */
index 06a6b19..579899e 100644 (file)
@@ -425,7 +425,6 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
 
 static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
 {
-       u32 extra_cs_count;
        u32 start_ss, last_ss;
        u32 start_cs, last_cs;
 
@@ -461,18 +460,12 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
                if (last_cs > 7)
                        return -ESCH_CS_OVERFLOW;
 
-               if (sch_ep->ep_type == ISOC_IN_EP)
-                       extra_cs_count = (last_cs == 7) ? 1 : 2;
-               else /*  ep_type : INTR IN / INTR OUT */
-                       extra_cs_count = 1;
-
-               cs_count += extra_cs_count;
                if (cs_count > 7)
                        cs_count = 7; /* HW limit */
 
                sch_ep->cs_count = cs_count;
-               /* one for ss, the other for idle */
-               sch_ep->num_budget_microframes = cs_count + 2;
+               /* ss, idle are ignored */
+               sch_ep->num_budget_microframes = cs_count;
 
                /*
                 * if interval=1, maxp >752, num_budge_micoframe is larger
@@ -771,8 +764,8 @@ int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev,
        if (ret)
                return ret;
 
-       if (ep->hcpriv)
-               drop_ep_quirk(hcd, udev, ep);
+       /* needn't check @ep->hcpriv, xhci_endpoint_disable set it NULL */
+       drop_ep_quirk(hcd, udev, ep);
 
        return 0;
 }
index 0448558..a8641b6 100644 (file)
@@ -398,12 +398,17 @@ static int xhci_plat_remove(struct platform_device *dev)
        pm_runtime_get_sync(&dev->dev);
        xhci->xhc_state |= XHCI_STATE_REMOVING;
 
-       usb_remove_hcd(shared_hcd);
-       xhci->shared_hcd = NULL;
+       if (shared_hcd) {
+               usb_remove_hcd(shared_hcd);
+               xhci->shared_hcd = NULL;
+       }
+
        usb_phy_shutdown(hcd->usb_phy);
 
        usb_remove_hcd(hcd);
-       usb_put_hcd(shared_hcd);
+
+       if (shared_hcd)
+               usb_put_hcd(shared_hcd);
 
        clk_disable_unprepare(clk);
        clk_disable_unprepare(reg_clk);
index 65858f6..3864928 100644 (file)
@@ -151,9 +151,11 @@ int xhci_start(struct xhci_hcd *xhci)
                xhci_err(xhci, "Host took too long to start, "
                                "waited %u microseconds.\n",
                                XHCI_MAX_HALT_USEC);
-       if (!ret)
+       if (!ret) {
                /* clear state flags. Including dying, halted or removing */
                xhci->xhc_state = 0;
+               xhci->run_graceperiod = jiffies + msecs_to_jiffies(500);
+       }
 
        return ret;
 }
@@ -791,8 +793,6 @@ static void xhci_stop(struct usb_hcd *hcd)
 void xhci_shutdown(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       unsigned long flags;
-       int i;
 
        if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
                usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
@@ -808,21 +808,12 @@ void xhci_shutdown(struct usb_hcd *hcd)
                del_timer_sync(&xhci->shared_hcd->rh_timer);
        }
 
-       spin_lock_irqsave(&xhci->lock, flags);
+       spin_lock_irq(&xhci->lock);
        xhci_halt(xhci);
-
-       /* Power off USB2 ports*/
-       for (i = 0; i < xhci->usb2_rhub.num_ports; i++)
-               xhci_set_port_power(xhci, xhci->main_hcd, i, false, &flags);
-
-       /* Power off USB3 ports*/
-       for (i = 0; i < xhci->usb3_rhub.num_ports; i++)
-               xhci_set_port_power(xhci, xhci->shared_hcd, i, false, &flags);
-
        /* Workaround for spurious wakeups at shutdown with HSW */
        if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
                xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
-       spin_unlock_irqrestore(&xhci->lock, flags);
+       spin_unlock_irq(&xhci->lock);
 
        xhci_cleanup_msix(xhci);
 
index 1960b47..7caa0db 100644 (file)
@@ -1826,7 +1826,7 @@ struct xhci_hcd {
 
        /* Host controller watchdog timer structures */
        unsigned int            xhc_state;
-
+       unsigned long           run_graceperiod;
        u32                     command;
        struct s3_save          s3;
 /* Host controller is dying - not responding to commands. "I'm not dead yet!"
@@ -2196,8 +2196,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
 int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
 int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
 struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
-void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index,
-                        bool on, unsigned long *flags);
 
 void xhci_hc_died(struct xhci_hcd *xhci);
 
index d1df153..d63c639 100644 (file)
@@ -71,10 +71,7 @@ static int onboard_hub_power_off(struct onboard_hub *hub)
 {
        int err;
 
-       if (hub->reset_gpio) {
-               gpiod_set_value_cansleep(hub->reset_gpio, 1);
-               fsleep(hub->pdata->reset_us);
-       }
+       gpiod_set_value_cansleep(hub->reset_gpio, 1);
 
        err = regulator_disable(hub->vdd);
        if (err) {
index f906dfd..6c8f776 100644 (file)
@@ -86,7 +86,7 @@ config USB_MUSB_TUSB6010
        tristate "TUSB6010"
        depends on HAS_IOMEM
        depends on ARCH_OMAP2PLUS || COMPILE_TEST
-       depends on NOP_USB_XCEIV = USB_MUSB_HDRC # both built-in or both modules
+       depends on NOP_USB_XCEIV!=m || USB_MUSB_HDRC=m
 
 config USB_MUSB_OMAP2PLUS
        tristate "OMAP2430 and onwards"
index 2798fca..af01a46 100644 (file)
@@ -97,7 +97,10 @@ struct ch341_private {
        u8 mcr;
        u8 msr;
        u8 lcr;
+
        unsigned long quirks;
+       u8 version;
+
        unsigned long break_end;
 };
 
@@ -250,8 +253,12 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
        /*
         * CH341A buffers data until a full endpoint-size packet (32 bytes)
         * has been received unless bit 7 is set.
+        *
+        * At least one device with version 0x27 appears to have this bit
+        * inverted.
         */
-       val |= BIT(7);
+       if (priv->version > 0x27)
+               val |= BIT(7);
 
        r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
                              CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER,
@@ -265,6 +272,9 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
         * (stop bits, parity and word length). Version 0x30 and above use
         * CH341_REG_LCR only and CH341_REG_LCR2 is always set to zero.
         */
+       if (priv->version < 0x30)
+               return 0;
+
        r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
                              CH341_REG_LCR2 << 8 | CH341_REG_LCR, lcr);
        if (r)
@@ -308,7 +318,9 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
        r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size);
        if (r)
                return r;
-       dev_dbg(&dev->dev, "Chip version: 0x%02x\n", buffer[0]);
+
+       priv->version = buffer[0];
+       dev_dbg(&dev->dev, "Chip version: 0x%02x\n", priv->version);
 
        r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0);
        if (r < 0)
index c374620..a34957c 100644 (file)
@@ -130,6 +130,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x83AA) }, /* Mark-10 Digital Force Gauge */
        { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
        { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
+       { USB_DEVICE(0x10C4, 0x8414) }, /* Decagon USB Cable Adapter */
        { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
        { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
        { USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */
index d5a3986..52d59be 100644 (file)
@@ -1045,6 +1045,8 @@ static const struct usb_device_id id_table_combined[] = {
        /* IDS GmbH devices */
        { USB_DEVICE(IDS_VID, IDS_SI31A_PID) },
        { USB_DEVICE(IDS_VID, IDS_CM31A_PID) },
+       /* Omron devices */
+       { USB_DEVICE(OMRON_VID, OMRON_CS1W_CIF31_PID) },
        /* U-Blox devices */
        { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) },
        { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) },
index 4e92c16..31c8cca 100644 (file)
 #define INFINEON_TRIBOARD_TC2X7_PID    0x0043 /* DAS JTAG TriBoard TC2X7 V1.0 */
 
 /*
+ * Omron corporation (https://www.omron.com)
+ */
+ #define OMRON_VID                     0x0590
+ #define OMRON_CS1W_CIF31_PID          0x00b2
+
+/*
  * Acton Research Corp.
  */
 #define ACTON_VID              0x0647  /* Vendor ID */
index de59fa9..697683e 100644 (file)
@@ -253,8 +253,10 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_BG96                   0x0296
 #define QUECTEL_PRODUCT_EP06                   0x0306
 #define QUECTEL_PRODUCT_EM05G                  0x030a
+#define QUECTEL_PRODUCT_EM060K                 0x030b
 #define QUECTEL_PRODUCT_EM12                   0x0512
 #define QUECTEL_PRODUCT_RM500Q                 0x0800
+#define QUECTEL_PRODUCT_RM520N                 0x0801
 #define QUECTEL_PRODUCT_EC200S_CN              0x6002
 #define QUECTEL_PRODUCT_EC200T                 0x6026
 #define QUECTEL_PRODUCT_RM500K                 0x7001
@@ -438,6 +440,8 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_MV31_2_RMNET         0x00b9
 #define CINTERION_PRODUCT_MV32_WA              0x00f1
 #define CINTERION_PRODUCT_MV32_WB              0x00f2
+#define CINTERION_PRODUCT_MV32_WA_RMNET                0x00f3
+#define CINTERION_PRODUCT_MV32_WB_RMNET                0x00f4
 
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID                     0x0b3c
@@ -573,6 +577,10 @@ static void option_instat_callback(struct urb *urb);
 #define WETELECOM_PRODUCT_6802                 0x6802
 #define WETELECOM_PRODUCT_WMD300               0x6803
 
+/* OPPO products */
+#define OPPO_VENDOR_ID                         0x22d9
+#define OPPO_PRODUCT_R11                       0x276c
+
 
 /* Device flags */
 
@@ -1131,6 +1139,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
          .driver_info = NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, 0x0203, 0xff), /* BG95-M3 */
+         .driver_info = ZLP },
        { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
          .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
@@ -1138,6 +1148,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
        { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
          .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
@@ -1149,6 +1162,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
          .driver_info = ZLP },
+       { 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, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
@@ -1993,8 +2009,12 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(0)},
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
          .driver_info = RSVD(3)},
+       { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA_RMNET, 0xff),
+         .driver_info = RSVD(0) },
        { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
          .driver_info = RSVD(3)},
+       { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB_RMNET, 0xff),
+         .driver_info = RSVD(0) },
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100),
          .driver_info = RSVD(4) },
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120),
@@ -2155,6 +2175,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) },                   /* GosunCn GM500 RNDIS */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) },                   /* GosunCn GM500 MBIM */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) },                   /* GosunCn GM500 ECM/NCM */
+       { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 1a05e3d..4993227 100644 (file)
@@ -2294,6 +2294,13 @@ UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
 
+/* Reported by Witold Lipieta <witold.lipieta@thaumatec.com> */
+UNUSUAL_DEV( 0x1fc9, 0x0117, 0x0100, 0x0100,
+               "NXP Semiconductors",
+               "PN7462AU",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_RESIDUE ),
+
 /* Supplied with some Castlewood ORB removable drives */
 UNUSUAL_DEV(  0x2027, 0xa001, 0x0000, 0x9999,
                "Double-H Technology",
index 4051c8c..251778d 100644 (file)
@@ -52,6 +52,13 @@ UNUSUAL_DEV(0x059f, 0x1061, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME),
 
+/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */
+UNUSUAL_DEV(0x090c, 0x2000, 0x0000, 0x9999,
+               "Hiksemi",
+               "External HDD",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_UAS),
+
 /*
  * Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI
  * commands in UAS mode.  Observed with the 1.28 firmware; are there others?
@@ -62,6 +69,13 @@ UNUSUAL_DEV(0x0984, 0x0301, 0x0128, 0x0128,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_IGNORE_UAS),
 
+/* Reported-by: Tom Hu <huxiaoying@kylinos.cn> */
+UNUSUAL_DEV(0x0b05, 0x1932, 0x0000, 0x9999,
+               "ASUS",
+               "External HDD",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_UAS),
+
 /* Reported-by: David Webb <djw@noc.ac.uk> */
 UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
                "Seagate",
@@ -69,6 +83,13 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_REPORT_LUNS),
 
+/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */
+UNUSUAL_DEV(0x0bda, 0x9210, 0x0000, 0x9999,
+               "Hiksemi",
+               "External HDD",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_UAS),
+
 /* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
 UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
                "Initio Corporation",
@@ -111,6 +132,13 @@ UNUSUAL_DEV(0x154b, 0xf00d, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_ATA_1X),
 
+/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */
+UNUSUAL_DEV(0x17ef, 0x3899, 0x0000, 0x9999,
+               "Thinkplus",
+               "External HDD",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_UAS),
+
 /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
 UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999,
                "VIA",
index 5defdfe..831e704 100644 (file)
@@ -56,6 +56,7 @@ config TYPEC_ANX7411
        tristate "Analogix ANX7411 Type-C DRP Port controller driver"
        depends on I2C
        depends on USB_ROLE_SWITCH
+       depends on POWER_SUPPLY
        help
          Say Y or M here if your system has Analogix ANX7411 Type-C DRP Port
          controller driver.
index c1d8c23..de66a29 100644 (file)
@@ -99,8 +99,8 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
        case DP_STATUS_CON_UFP_D:
        case DP_STATUS_CON_BOTH: /* NOTE: First acting as DP source */
                conf |= DP_CONF_UFP_U_AS_UFP_D;
-               pin_assign = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo) &
-                            DP_CAP_UFP_D_PIN_ASSIGN(dp->port->vdo);
+               pin_assign = DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo) &
+                                DP_CAP_PIN_ASSIGN_DFP_D(dp->port->vdo);
                break;
        default:
                break;
index ebc29ec..bd5e5dd 100644 (file)
@@ -2346,6 +2346,7 @@ static void __exit typec_exit(void)
        ida_destroy(&typec_index_ida);
        bus_unregister(&typec_bus);
        class_unregister(&typec_mux_class);
+       class_unregister(&retimer_class);
 }
 module_exit(typec_exit);
 
index 47b733f..e1f4df7 100644 (file)
@@ -569,13 +569,6 @@ err_unregister_switch:
        return ret;
 }
 
-static int is_memory(struct acpi_resource *res, void *data)
-{
-       struct resource r;
-
-       return !acpi_dev_resource_memory(res, &r);
-}
-
 /* IOM ACPI IDs and IOM_PORT_STATUS_OFFSET */
 static const struct acpi_device_id iom_acpi_ids[] = {
        /* TigerLake */
@@ -583,6 +576,9 @@ static const struct acpi_device_id iom_acpi_ids[] = {
 
        /* AlderLake */
        { "INTC1079", 0x160, },
+
+       /* Meteor Lake */
+       { "INTC107A", 0x160, },
        {}
 };
 
@@ -606,7 +602,7 @@ static int pmc_usb_probe_iom(struct pmc_usb *pmc)
                return -ENODEV;
 
        INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list, is_memory, NULL);
+       ret = acpi_dev_get_memory_resources(adev, &resource_list);
        if (ret < 0)
                return ret;
 
index ea5a917..904c7b4 100644 (file)
@@ -6320,6 +6320,13 @@ static int tcpm_psy_set_prop(struct power_supply *psy,
        struct tcpm_port *port = power_supply_get_drvdata(psy);
        int ret;
 
+       /*
+        * All the properties below are related to USB PD. The check needs to be
+        * property specific when a non-pd related property is added.
+        */
+       if (!port->pd_supported)
+               return -EOPNOTSUPP;
+
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
                ret = tcpm_psy_set_online(port, val);
index 1aea464..6364f0d 100644 (file)
@@ -588,8 +588,6 @@ static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner,
                                num_pdos * sizeof(u32));
        if (ret < 0 && ret != -ETIMEDOUT)
                dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret);
-       if (ret == 0 && offset == 0)
-               dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n");
 
        return ret;
 }
@@ -1200,32 +1198,6 @@ out_unlock:
        return ret;
 }
 
-static void ucsi_unregister_connectors(struct ucsi *ucsi)
-{
-       struct ucsi_connector *con;
-       int i;
-
-       if (!ucsi->connector)
-               return;
-
-       for (i = 0; i < ucsi->cap.num_connectors; i++) {
-               con = &ucsi->connector[i];
-
-               if (!con->wq)
-                       break;
-
-               cancel_work_sync(&con->work);
-               ucsi_unregister_partner(con);
-               ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
-               ucsi_unregister_port_psy(con);
-               destroy_workqueue(con->wq);
-               typec_unregister_port(con->port);
-       }
-
-       kfree(ucsi->connector);
-       ucsi->connector = NULL;
-}
-
 /**
  * ucsi_init - Initialize UCSI interface
  * @ucsi: UCSI to be initialized
@@ -1234,6 +1206,7 @@ static void ucsi_unregister_connectors(struct ucsi *ucsi)
  */
 static int ucsi_init(struct ucsi *ucsi)
 {
+       struct ucsi_connector *con;
        u64 command;
        int ret;
        int i;
@@ -1264,7 +1237,7 @@ static int ucsi_init(struct ucsi *ucsi)
        }
 
        /* Allocate the connectors. Released in ucsi_unregister() */
-       ucsi->connector = kcalloc(ucsi->cap.num_connectors,
+       ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
                                  sizeof(*ucsi->connector), GFP_KERNEL);
        if (!ucsi->connector) {
                ret = -ENOMEM;
@@ -1288,7 +1261,15 @@ static int ucsi_init(struct ucsi *ucsi)
        return 0;
 
 err_unregister:
-       ucsi_unregister_connectors(ucsi);
+       for (con = ucsi->connector; con->port; con++) {
+               ucsi_unregister_partner(con);
+               ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
+               ucsi_unregister_port_psy(con);
+               if (con->wq)
+                       destroy_workqueue(con->wq);
+               typec_unregister_port(con->port);
+               con->port = NULL;
+       }
 
 err_reset:
        memset(&ucsi->cap, 0, sizeof(ucsi->cap));
@@ -1402,6 +1383,7 @@ EXPORT_SYMBOL_GPL(ucsi_register);
 void ucsi_unregister(struct ucsi *ucsi)
 {
        u64 cmd = UCSI_SET_NOTIFICATION_ENABLE;
+       int i;
 
        /* Make sure that we are not in the middle of driver initialization */
        cancel_delayed_work_sync(&ucsi->work);
@@ -1409,7 +1391,18 @@ void ucsi_unregister(struct ucsi *ucsi)
        /* Disable notifications */
        ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
 
-       ucsi_unregister_connectors(ucsi);
+       for (i = 0; i < ucsi->cap.num_connectors; i++) {
+               cancel_work_sync(&ucsi->connector[i].work);
+               ucsi_unregister_partner(&ucsi->connector[i]);
+               ucsi_unregister_altmodes(&ucsi->connector[i],
+                                        UCSI_RECIPIENT_CON);
+               ucsi_unregister_port_psy(&ucsi->connector[i]);
+               if (ucsi->connector[i].wq)
+                       destroy_workqueue(ucsi->connector[i].wq);
+               typec_unregister_port(ucsi->connector[i].port);
+       }
+
+       kfree(ucsi->connector);
 }
 EXPORT_SYMBOL_GPL(ucsi_unregister);
 
index 75a703b..3e4486b 100644 (file)
@@ -323,7 +323,7 @@ u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid)
        u32 q_pair_id;
 
        ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
-       q_pair_id = qid / hw->nr_vring;
+       q_pair_id = qid / 2;
        avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2];
        last_avail_idx = vp_ioread16(avail_idx_addr);
 
@@ -337,7 +337,7 @@ int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num)
        u32 q_pair_id;
 
        ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg;
-       q_pair_id = qid / hw->nr_vring;
+       q_pair_id = qid / 2;
        avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2];
        hw->vring[qid].last_avail_idx = num;
        vp_iowrite16(num, avail_idx_addr);
index ed100a3..9091336 100644 (file)
@@ -1320,6 +1320,8 @@ static void teardown_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *
 
 static int create_rqt(struct mlx5_vdpa_net *ndev)
 {
+       int rqt_table_size = roundup_pow_of_two(ndev->rqt_size);
+       int act_sz = roundup_pow_of_two(ndev->cur_num_vqs / 2);
        __be32 *list;
        void *rqtc;
        int inlen;
@@ -1327,7 +1329,7 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
        int i, j;
        int err;
 
-       inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + ndev->rqt_size * MLX5_ST_SZ_BYTES(rq_num);
+       inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + rqt_table_size * MLX5_ST_SZ_BYTES(rq_num);
        in = kzalloc(inlen, GFP_KERNEL);
        if (!in)
                return -ENOMEM;
@@ -1336,12 +1338,12 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
        rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
 
        MLX5_SET(rqtc, rqtc, list_q_type, MLX5_RQTC_LIST_Q_TYPE_VIRTIO_NET_Q);
-       MLX5_SET(rqtc, rqtc, rqt_max_size, ndev->rqt_size);
+       MLX5_SET(rqtc, rqtc, rqt_max_size, rqt_table_size);
        list = MLX5_ADDR_OF(rqtc, rqtc, rq_num[0]);
-       for (i = 0, j = 0; i < ndev->rqt_size; i++, j += 2)
+       for (i = 0, j = 0; i < act_sz; i++, j += 2)
                list[i] = cpu_to_be32(ndev->vqs[j % ndev->cur_num_vqs].virtq_id);
 
-       MLX5_SET(rqtc, rqtc, rqt_actual_size, ndev->rqt_size);
+       MLX5_SET(rqtc, rqtc, rqt_actual_size, act_sz);
        err = mlx5_vdpa_create_rqt(&ndev->mvdev, in, inlen, &ndev->res.rqtn);
        kfree(in);
        if (err)
@@ -1354,6 +1356,7 @@ static int create_rqt(struct mlx5_vdpa_net *ndev)
 
 static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
 {
+       int act_sz = roundup_pow_of_two(num / 2);
        __be32 *list;
        void *rqtc;
        int inlen;
@@ -1361,7 +1364,7 @@ static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
        int i, j;
        int err;
 
-       inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + ndev->rqt_size * MLX5_ST_SZ_BYTES(rq_num);
+       inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + act_sz * MLX5_ST_SZ_BYTES(rq_num);
        in = kzalloc(inlen, GFP_KERNEL);
        if (!in)
                return -ENOMEM;
@@ -1372,10 +1375,10 @@ static int modify_rqt(struct mlx5_vdpa_net *ndev, int num)
        MLX5_SET(rqtc, rqtc, list_q_type, MLX5_RQTC_LIST_Q_TYPE_VIRTIO_NET_Q);
 
        list = MLX5_ADDR_OF(rqtc, rqtc, rq_num[0]);
-       for (i = 0, j = 0; i < ndev->rqt_size; i++, j += 2)
+       for (i = 0, j = 0; i < act_sz; i++, j = j + 2)
                list[i] = cpu_to_be32(ndev->vqs[j % num].virtq_id);
 
-       MLX5_SET(rqtc, rqtc, rqt_actual_size, ndev->rqt_size);
+       MLX5_SET(rqtc, rqtc, rqt_actual_size, act_sz);
        err = mlx5_vdpa_modify_rqt(&ndev->mvdev, in, inlen, ndev->res.rqtn);
        kfree(in);
        if (err)
index 41c0b29..35dceee 100644 (file)
@@ -673,10 +673,15 @@ static void vduse_vdpa_get_config(struct vdpa_device *vdpa, unsigned int offset,
 {
        struct vduse_dev *dev = vdpa_to_vduse(vdpa);
 
-       if (offset > dev->config_size ||
-           len > dev->config_size - offset)
+       /* Initialize the buffer in case of partial copy. */
+       memset(buf, 0, len);
+
+       if (offset > dev->config_size)
                return;
 
+       if (len > dev->config_size - offset)
+               len = dev->config_size - offset;
+
        memcpy(buf, dev->config + offset, len);
 }
 
index e163aa9..0cbdcd1 100644 (file)
@@ -151,7 +151,10 @@ int vfio_pci_zdev_open_device(struct vfio_pci_core_device *vdev)
        if (!vdev->vdev.kvm)
                return 0;
 
-       return kvm_s390_pci_register_kvm(zdev, vdev->vdev.kvm);
+       if (zpci_kvm_hook.kvm_register)
+               return zpci_kvm_hook.kvm_register(zdev, vdev->vdev.kvm);
+
+       return -ENOENT;
 }
 
 void vfio_pci_zdev_close_device(struct vfio_pci_core_device *vdev)
@@ -161,5 +164,6 @@ void vfio_pci_zdev_close_device(struct vfio_pci_core_device *vdev)
        if (!zdev || !vdev->vdev.kvm)
                return;
 
-       kvm_s390_pci_unregister_kvm(zdev);
+       if (zpci_kvm_hook.kvm_unregister)
+               zpci_kvm_hook.kvm_unregister(zdev);
 }
index db516c9..8706482 100644 (file)
@@ -558,6 +558,18 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
        ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM,
                                    pages, NULL, NULL);
        if (ret > 0) {
+               int i;
+
+               /*
+                * The zero page is always resident, we don't need to pin it
+                * and it falls into our invalid/reserved test so we don't
+                * unpin in put_pfn().  Unpin all zero pages in the batch here.
+                */
+               for (i = 0 ; i < ret; i++) {
+                       if (unlikely(is_zero_pfn(page_to_pfn(pages[i]))))
+                               unpin_user_page(pages[i]);
+               }
+
                *pfn = page_to_pfn(pages[0]);
                goto done;
        }
index 886c564..b58b445 100644 (file)
 #define SYNTHVID_DEPTH_WIN8 32
 #define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
 
-#define PCI_VENDOR_ID_MICROSOFT 0x1414
-#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
-
-
 enum pipe_msg_type {
        PIPE_MSG_INVALID,
        PIPE_MSG_DATA,
index ce91add..dc4d25c 100644 (file)
@@ -17,7 +17,7 @@ config NITRO_ENCLAVES
 
 config NITRO_ENCLAVES_MISC_DEV_TEST
        bool "Tests for the misc device functionality of the Nitro Enclaves" if !KUNIT_ALL_TESTS
-       depends on NITRO_ENCLAVES && KUNIT
+       depends on NITRO_ENCLAVES && KUNIT=y
        default KUNIT_ALL_TESTS
        help
          Enable KUnit tests for the misc device functionality of the Nitro
index 738029d..e1ec725 100644 (file)
@@ -1047,6 +1047,9 @@ int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args)
        size_t size;
        int i, ret;
 
+       if (args->nr_pages < 0 || args->nr_pages > (INT_MAX >> PAGE_SHIFT))
+               return -ENOMEM;
+
        size = args->nr_pages << PAGE_SHIFT;
        if (args->coherent)
                args->vaddr = dma_alloc_coherent(args->dev, size,
index d5f3f76..d4b2519 100644 (file)
@@ -382,9 +382,10 @@ int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr,
        unsigned long ring_size = nr_pages * XEN_PAGE_SIZE;
        grant_ref_t gref_head;
        unsigned int i;
+       void *addr;
        int ret;
 
-       *vaddr = alloc_pages_exact(ring_size, gfp | __GFP_ZERO);
+       addr = *vaddr = alloc_pages_exact(ring_size, gfp | __GFP_ZERO);
        if (!*vaddr) {
                ret = -ENOMEM;
                goto err;
@@ -401,13 +402,15 @@ int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr,
                unsigned long gfn;
 
                if (is_vmalloc_addr(*vaddr))
-                       gfn = pfn_to_gfn(vmalloc_to_pfn(vaddr[i]));
+                       gfn = pfn_to_gfn(vmalloc_to_pfn(addr));
                else
-                       gfn = virt_to_gfn(vaddr[i]);
+                       gfn = virt_to_gfn(addr);
 
                grefs[i] = gnttab_claim_grant_reference(&gref_head);
                gnttab_grant_foreign_access_ref(grefs[i], dev->otherend_id,
                                                gfn, 0);
+
+               addr += XEN_PAGE_SIZE;
        }
 
        return 0;
index c4210a3..bbcc5af 100644 (file)
@@ -76,7 +76,7 @@ void afs_lock_op_done(struct afs_call *call)
        if (call->error == 0) {
                spin_lock(&vnode->lock);
                trace_afs_flock_ev(vnode, NULL, afs_flock_timestamp, 0);
-               vnode->locked_at = call->reply_time;
+               vnode->locked_at = call->issue_time;
                afs_schedule_lock_extension(vnode);
                spin_unlock(&vnode->lock);
        }
index 4943413..7d37f63 100644 (file)
@@ -131,7 +131,7 @@ bad:
 
 static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
 {
-       return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry;
+       return ktime_divns(call->issue_time, NSEC_PER_SEC) + expiry;
 }
 
 static void xdr_decode_AFSCallBack(const __be32 **_bp,
index 64ad554..723d162 100644 (file)
@@ -137,7 +137,6 @@ struct afs_call {
        bool                    need_attention; /* T if RxRPC poked us */
        bool                    async;          /* T if asynchronous */
        bool                    upgrade;        /* T to request service upgrade */
-       bool                    have_reply_time; /* T if have got reply_time */
        bool                    intr;           /* T if interruptible */
        bool                    unmarshalling_error; /* T if an unmarshalling error occurred */
        u16                     service_id;     /* Actual service ID (after upgrade) */
@@ -151,7 +150,7 @@ struct afs_call {
                } __attribute__((packed));
                __be64          tmp64;
        };
-       ktime_t                 reply_time;     /* Time of first reply packet */
+       ktime_t                 issue_time;     /* Time of issue of operation */
 };
 
 struct afs_call_type {
index 933e67f..805328c 100644 (file)
@@ -69,6 +69,7 @@ int afs_abort_to_error(u32 abort_code)
                /* Unified AFS error table */
        case UAEPERM:                   return -EPERM;
        case UAENOENT:                  return -ENOENT;
+       case UAEAGAIN:                  return -EAGAIN;
        case UAEACCES:                  return -EACCES;
        case UAEBUSY:                   return -EBUSY;
        case UAEEXIST:                  return -EEXIST;
index d5c4785..eccc3cd 100644 (file)
@@ -351,6 +351,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
        if (call->max_lifespan)
                rxrpc_kernel_set_max_life(call->net->socket, rxcall,
                                          call->max_lifespan);
+       call->issue_time = ktime_get_real();
 
        /* send the request */
        iov[0].iov_base = call->request;
@@ -501,12 +502,6 @@ static void afs_deliver_to_call(struct afs_call *call)
                        return;
                }
 
-               if (!call->have_reply_time &&
-                   rxrpc_kernel_get_reply_time(call->net->socket,
-                                               call->rxcall,
-                                               &call->reply_time))
-                       call->have_reply_time = true;
-
                ret = call->type->deliver(call);
                state = READ_ONCE(call->state);
                if (ret == 0 && call->unmarshalling_error)
index fdc7d67..11571cc 100644 (file)
@@ -232,8 +232,7 @@ static void xdr_decode_YFSCallBack(const __be32 **_bp,
        struct afs_callback *cb = &scb->callback;
        ktime_t cb_expiry;
 
-       cb_expiry = call->reply_time;
-       cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100);
+       cb_expiry = ktime_add(call->issue_time, xdr_to_u64(x->expiration_time) * 100);
        cb->expires_at  = ktime_divns(cb_expiry, NSEC_PER_SEC);
        scb->have_cb    = true;
        *_bp += xdr_size(x);
index 9ef162d..df8c99c 100644 (file)
@@ -1088,8 +1088,6 @@ struct btrfs_fs_info {
 
        spinlock_t zone_active_bgs_lock;
        struct list_head zone_active_bgs;
-       /* Waiters when BTRFS_FS_NEED_ZONE_FINISH is set */
-       wait_queue_head_t zone_finish_wait;
 
        /* Updates are not protected by any lock */
        struct btrfs_commit_stats commit_stats;
index 820b1f1..2633137 100644 (file)
@@ -3068,7 +3068,6 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
        init_waitqueue_head(&fs_info->transaction_blocked_wait);
        init_waitqueue_head(&fs_info->async_submit_wait);
        init_waitqueue_head(&fs_info->delayed_iputs_wait);
-       init_waitqueue_head(&fs_info->zone_finish_wait);
 
        /* Usable values until the real ones are cached from the superblock */
        fs_info->nodesize = 4096;
@@ -4476,6 +4475,17 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        set_bit(BTRFS_FS_CLOSING_START, &fs_info->flags);
 
        /*
+        * If we had UNFINISHED_DROPS we could still be processing them, so
+        * clear that bit and wake up relocation so it can stop.
+        * We must do this before stopping the block group reclaim task, because
+        * at btrfs_relocate_block_group() we wait for this bit, and after the
+        * wait we stop with -EINTR if btrfs_fs_closing() returns non-zero - we
+        * have just set BTRFS_FS_CLOSING_START, so btrfs_fs_closing() will
+        * return 1.
+        */
+       btrfs_wake_unfinished_drop(fs_info);
+
+       /*
         * We may have the reclaim task running and relocating a data block group,
         * in which case it may create delayed iputs. So stop it before we park
         * the cleaner kthread otherwise we can get new delayed iputs after
@@ -4493,12 +4503,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
         */
        kthread_park(fs_info->cleaner_kthread);
 
-       /*
-        * If we had UNFINISHED_DROPS we could still be processing them, so
-        * clear that bit and wake up relocation so it can stop.
-        */
-       btrfs_wake_unfinished_drop(fs_info);
-
        /* wait for the qgroup rescan worker to stop */
        btrfs_qgroup_wait_for_completion(fs_info, false);
 
@@ -4521,6 +4525,31 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        /* clear out the rbtree of defraggable inodes */
        btrfs_cleanup_defrag_inodes(fs_info);
 
+       /*
+        * After we parked the cleaner kthread, ordered extents may have
+        * completed and created new delayed iputs. If one of the async reclaim
+        * tasks is running and in the RUN_DELAYED_IPUTS flush state, then we
+        * can hang forever trying to stop it, because if a delayed iput is
+        * added after it ran btrfs_run_delayed_iputs() and before it called
+        * btrfs_wait_on_delayed_iputs(), it will hang forever since there is
+        * no one else to run iputs.
+        *
+        * So wait for all ongoing ordered extents to complete and then run
+        * delayed iputs. This works because once we reach this point no one
+        * can either create new ordered extents nor create delayed iputs
+        * through some other means.
+        *
+        * Also note that btrfs_wait_ordered_roots() is not safe here, because
+        * it waits for BTRFS_ORDERED_COMPLETE to be set on an ordered extent,
+        * but the delayed iput for the respective inode is made only when doing
+        * the final btrfs_put_ordered_extent() (which must happen at
+        * btrfs_finish_ordered_io() when we are unmounting).
+        */
+       btrfs_flush_workqueue(fs_info->endio_write_workers);
+       /* Ordered extents for free space inodes. */
+       btrfs_flush_workqueue(fs_info->endio_freespace_worker);
+       btrfs_run_delayed_iputs(fs_info);
+
        cancel_work_sync(&fs_info->async_reclaim_work);
        cancel_work_sync(&fs_info->async_data_reclaim_work);
        cancel_work_sync(&fs_info->preempt_reclaim_work);
index ad25089..1372210 100644 (file)
@@ -1644,10 +1644,9 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
                        done_offset = end;
 
                if (done_offset == start) {
-                       struct btrfs_fs_info *info = inode->root->fs_info;
-
-                       wait_var_event(&info->zone_finish_wait,
-                                      !test_bit(BTRFS_FS_NEED_ZONE_FINISH, &info->flags));
+                       wait_on_bit_io(&inode->root->fs_info->flags,
+                                      BTRFS_FS_NEED_ZONE_FINISH,
+                                      TASK_UNINTERRUPTIBLE);
                        continue;
                }
 
index d0cbeb7..435559b 100644 (file)
@@ -199,7 +199,7 @@ static u64 calc_chunk_size(const struct btrfs_fs_info *fs_info, u64 flags)
        ASSERT(flags & BTRFS_BLOCK_GROUP_TYPE_MASK);
 
        if (flags & BTRFS_BLOCK_GROUP_DATA)
-               return SZ_1G;
+               return BTRFS_MAX_DATA_CHUNK_SIZE;
        else if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
                return SZ_32M;
 
index 064ab2a..f63ff91 100644 (file)
@@ -5267,6 +5267,9 @@ static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
                                       ctl->stripe_size);
        }
 
+       /* Stripe size should not go beyond 1G. */
+       ctl->stripe_size = min_t(u64, ctl->stripe_size, SZ_1G);
+
        /* Align to BTRFS_STRIPE_LEN */
        ctl->stripe_size = round_down(ctl->stripe_size, BTRFS_STRIPE_LEN);
        ctl->chunk_size = ctl->stripe_size * data_stripes;
index b150b07..73c6929 100644 (file)
@@ -421,10 +421,19 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
         * since btrfs adds the pages one by one to a bio, and btrfs cannot
         * increase the metadata reservation even if it increases the number of
         * extents, it is safe to stick with the limit.
+        *
+        * With the zoned emulation, we can have non-zoned device on the zoned
+        * mode. In this case, we don't have a valid max zone append size. So,
+        * use max_segments * PAGE_SIZE as the pseudo max_zone_append_size.
         */
-       zone_info->max_zone_append_size =
-               min_t(u64, (u64)bdev_max_zone_append_sectors(bdev) << SECTOR_SHIFT,
-                     (u64)bdev_max_segments(bdev) << PAGE_SHIFT);
+       if (bdev_is_zoned(bdev)) {
+               zone_info->max_zone_append_size = min_t(u64,
+                       (u64)bdev_max_zone_append_sectors(bdev) << SECTOR_SHIFT,
+                       (u64)bdev_max_segments(bdev) << PAGE_SHIFT);
+       } else {
+               zone_info->max_zone_append_size =
+                       (u64)bdev_max_segments(bdev) << PAGE_SHIFT;
+       }
        if (!IS_ALIGNED(nr_sectors, zone_sectors))
                zone_info->nr_zones++;
 
@@ -1178,7 +1187,7 @@ int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size)
  * offset.
  */
 static int calculate_alloc_pointer(struct btrfs_block_group *cache,
-                                  u64 *offset_ret)
+                                  u64 *offset_ret, bool new)
 {
        struct btrfs_fs_info *fs_info = cache->fs_info;
        struct btrfs_root *root;
@@ -1188,6 +1197,21 @@ static int calculate_alloc_pointer(struct btrfs_block_group *cache,
        int ret;
        u64 length;
 
+       /*
+        * Avoid  tree lookups for a new block group, there's no use for it.
+        * It must always be 0.
+        *
+        * Also, we have a lock chain of extent buffer lock -> chunk mutex.
+        * For new a block group, this function is called from
+        * btrfs_make_block_group() which is already taking the chunk mutex.
+        * Thus, we cannot call calculate_alloc_pointer() which takes extent
+        * buffer locks to avoid deadlock.
+        */
+       if (new) {
+               *offset_ret = 0;
+               return 0;
+       }
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -1323,6 +1347,13 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
                else
                        num_conventional++;
 
+               /*
+                * Consider a zone as active if we can allow any number of
+                * active zones.
+                */
+               if (!device->zone_info->max_active_zones)
+                       __set_bit(i, active);
+
                if (!is_sequential) {
                        alloc_offsets[i] = WP_CONVENTIONAL;
                        continue;
@@ -1389,45 +1420,23 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
                        __set_bit(i, active);
                        break;
                }
-
-               /*
-                * Consider a zone as active if we can allow any number of
-                * active zones.
-                */
-               if (!device->zone_info->max_active_zones)
-                       __set_bit(i, active);
        }
 
        if (num_sequential > 0)
                cache->seq_zone = true;
 
        if (num_conventional > 0) {
-               /*
-                * Avoid calling calculate_alloc_pointer() for new BG. It
-                * is no use for new BG. It must be always 0.
-                *
-                * Also, we have a lock chain of extent buffer lock ->
-                * chunk mutex.  For new BG, this function is called from
-                * btrfs_make_block_group() which is already taking the
-                * chunk mutex. Thus, we cannot call
-                * calculate_alloc_pointer() which takes extent buffer
-                * locks to avoid deadlock.
-                */
-
                /* Zone capacity is always zone size in emulation */
                cache->zone_capacity = cache->length;
-               if (new) {
-                       cache->alloc_offset = 0;
-                       goto out;
-               }
-               ret = calculate_alloc_pointer(cache, &last_alloc);
-               if (ret || map->num_stripes == num_conventional) {
-                       if (!ret)
-                               cache->alloc_offset = last_alloc;
-                       else
-                               btrfs_err(fs_info,
+               ret = calculate_alloc_pointer(cache, &last_alloc, new);
+               if (ret) {
+                       btrfs_err(fs_info,
                        "zoned: failed to determine allocation offset of bg %llu",
-                                         cache->start);
+                                 cache->start);
+                       goto out;
+               } else if (map->num_stripes == num_conventional) {
+                       cache->alloc_offset = last_alloc;
+                       cache->zone_is_active = 1;
                        goto out;
                }
        }
@@ -1495,13 +1504,6 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
                goto out;
        }
 
-       if (cache->zone_is_active) {
-               btrfs_get_block_group(cache);
-               spin_lock(&fs_info->zone_active_bgs_lock);
-               list_add_tail(&cache->active_bg_list, &fs_info->zone_active_bgs);
-               spin_unlock(&fs_info->zone_active_bgs_lock);
-       }
-
 out:
        if (cache->alloc_offset > fs_info->zone_size) {
                btrfs_err(fs_info,
@@ -1526,10 +1528,16 @@ out:
                ret = -EIO;
        }
 
-       if (!ret)
+       if (!ret) {
                cache->meta_write_pointer = cache->alloc_offset + cache->start;
-
-       if (ret) {
+               if (cache->zone_is_active) {
+                       btrfs_get_block_group(cache);
+                       spin_lock(&fs_info->zone_active_bgs_lock);
+                       list_add_tail(&cache->active_bg_list,
+                                     &fs_info->zone_active_bgs);
+                       spin_unlock(&fs_info->zone_active_bgs_lock);
+               }
+       } else {
                kfree(cache->physical_map);
                cache->physical_map = NULL;
        }
@@ -1910,10 +1918,44 @@ out_unlock:
        return ret;
 }
 
+static void wait_eb_writebacks(struct btrfs_block_group *block_group)
+{
+       struct btrfs_fs_info *fs_info = block_group->fs_info;
+       const u64 end = block_group->start + block_group->length;
+       struct radix_tree_iter iter;
+       struct extent_buffer *eb;
+       void __rcu **slot;
+
+       rcu_read_lock();
+       radix_tree_for_each_slot(slot, &fs_info->buffer_radix, &iter,
+                                block_group->start >> fs_info->sectorsize_bits) {
+               eb = radix_tree_deref_slot(slot);
+               if (!eb)
+                       continue;
+               if (radix_tree_deref_retry(eb)) {
+                       slot = radix_tree_iter_retry(&iter);
+                       continue;
+               }
+
+               if (eb->start < block_group->start)
+                       continue;
+               if (eb->start >= end)
+                       break;
+
+               slot = radix_tree_iter_resume(slot, &iter);
+               rcu_read_unlock();
+               wait_on_extent_buffer_writeback(eb);
+               rcu_read_lock();
+       }
+       rcu_read_unlock();
+}
+
 static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_written)
 {
        struct btrfs_fs_info *fs_info = block_group->fs_info;
        struct map_lookup *map;
+       const bool is_metadata = (block_group->flags &
+                       (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM));
        int ret = 0;
        int i;
 
@@ -1924,8 +1966,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
        }
 
        /* Check if we have unwritten allocated space */
-       if ((block_group->flags &
-            (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM)) &&
+       if (is_metadata &&
            block_group->start + block_group->alloc_offset > block_group->meta_write_pointer) {
                spin_unlock(&block_group->lock);
                return -EAGAIN;
@@ -1950,6 +1991,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
                /* No need to wait for NOCOW writers. Zoned mode does not allow that */
                btrfs_wait_ordered_roots(fs_info, U64_MAX, block_group->start,
                                         block_group->length);
+               /* Wait for extent buffers to be written. */
+               if (is_metadata)
+                       wait_eb_writebacks(block_group);
 
                spin_lock(&block_group->lock);
 
@@ -2007,8 +2051,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
        /* For active_bg_list */
        btrfs_put_block_group(block_group);
 
-       clear_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
-       wake_up_all(&fs_info->zone_finish_wait);
+       clear_and_wake_up_bit(BTRFS_FS_NEED_ZONE_FINISH, &fs_info->flags);
 
        return 0;
 }
index 6cba2c6..2ad58c4 100644 (file)
@@ -111,6 +111,7 @@ struct cachefiles_cache {
        char                            *tag;           /* cache binding tag */
        refcount_t                      unbind_pincount;/* refcount to do daemon unbind */
        struct xarray                   reqs;           /* xarray of pending on-demand requests */
+       unsigned long                   req_id_next;
        struct xarray                   ondemand_ids;   /* xarray for ondemand_id allocation */
        u32                             ondemand_id_next;
 };
index 1fee702..0254ed3 100644 (file)
@@ -158,9 +158,13 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
 
        /* fail OPEN request if daemon reports an error */
        if (size < 0) {
-               if (!IS_ERR_VALUE(size))
-                       size = -EINVAL;
-               req->error = size;
+               if (!IS_ERR_VALUE(size)) {
+                       req->error = -EINVAL;
+                       ret = -EINVAL;
+               } else {
+                       req->error = size;
+                       ret = 0;
+               }
                goto out;
        }
 
@@ -238,14 +242,19 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
        unsigned long id = 0;
        size_t n;
        int ret = 0;
-       XA_STATE(xas, &cache->reqs, 0);
+       XA_STATE(xas, &cache->reqs, cache->req_id_next);
 
        /*
-        * Search for a request that has not ever been processed, to prevent
-        * requests from being processed repeatedly.
+        * Cyclically search for a request that has not ever been processed,
+        * to prevent requests from being processed repeatedly, and make
+        * request distribution fair.
         */
        xa_lock(&cache->reqs);
        req = xas_find_marked(&xas, UINT_MAX, CACHEFILES_REQ_NEW);
+       if (!req && cache->req_id_next > 0) {
+               xas_set(&xas, 0);
+               req = xas_find_marked(&xas, cache->req_id_next - 1, CACHEFILES_REQ_NEW);
+       }
        if (!req) {
                xa_unlock(&cache->reqs);
                return 0;
@@ -260,6 +269,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
        }
 
        xas_clear_mark(&xas, CACHEFILES_REQ_NEW);
+       cache->req_id_next = xas.xa_index + 1;
        xa_unlock(&cache->reqs);
 
        id = xas.xa_index;
index f54d8bf..8042d72 100644 (file)
@@ -1248,6 +1248,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
        lock_two_nondirectories(target_inode, src_inode);
 
        cifs_dbg(FYI, "about to flush pages\n");
+
+       rc = filemap_write_and_wait_range(src_inode->i_mapping, off,
+                                         off + len - 1);
+       if (rc)
+               goto out;
+
        /* should we flush first and last page first */
        truncate_inode_pages(&target_inode->i_data, 0);
 
index 81f4c15..5b4a7a3 100644 (file)
@@ -153,6 +153,6 @@ extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
 /* when changing internal version - update following two lines at same time */
-#define SMB3_PRODUCT_BUILD 38
-#define CIFS_VERSION   "2.38"
+#define SMB3_PRODUCT_BUILD 39
+#define CIFS_VERSION   "2.39"
 #endif                         /* _CIFSFS_H */
index a0a06b6..7ae6f2c 100644 (file)
@@ -702,9 +702,6 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
        int length = 0;
        int total_read;
 
-       smb_msg->msg_control = NULL;
-       smb_msg->msg_controllen = 0;
-
        for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
                try_to_freeze();
 
@@ -760,7 +757,7 @@ int
 cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
                      unsigned int to_read)
 {
-       struct msghdr smb_msg;
+       struct msghdr smb_msg = {};
        struct kvec iov = {.iov_base = buf, .iov_len = to_read};
        iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
 
@@ -770,15 +767,13 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
 ssize_t
 cifs_discard_from_socket(struct TCP_Server_Info *server, size_t to_read)
 {
-       struct msghdr smb_msg;
+       struct msghdr smb_msg = {};
 
        /*
         *  iov_iter_discard already sets smb_msg.type and count and iov_offset
         *  and cifs_readv_from_socket sets msg_control and msg_controllen
         *  so little to initialize in struct msghdr
         */
-       smb_msg.msg_name = NULL;
-       smb_msg.msg_namelen = 0;
        iov_iter_discard(&smb_msg.msg_iter, READ, to_read);
 
        return cifs_readv_from_socket(server, &smb_msg);
@@ -788,7 +783,7 @@ int
 cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
        unsigned int page_offset, unsigned int to_read)
 {
-       struct msghdr smb_msg;
+       struct msghdr smb_msg = {};
        struct bio_vec bv = {
                .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
        iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
@@ -2350,7 +2345,9 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        ses = tcon->ses;
        cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
        spin_lock(&cifs_tcp_ses_lock);
+       spin_lock(&tcon->tc_lock);
        if (--tcon->tc_count > 0) {
+               spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
                return;
        }
@@ -2359,6 +2356,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        WARN_ON(tcon->tc_count < 0);
 
        list_del_init(&tcon->tcon_list);
+       spin_unlock(&tcon->tc_lock);
        spin_unlock(&cifs_tcp_ses_lock);
 
        /* cancel polling of interfaces */
index fa738ad..6f38b13 100644 (file)
@@ -3575,6 +3575,9 @@ static ssize_t __cifs_writev(
 
 ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from)
 {
+       struct file *file = iocb->ki_filp;
+
+       cifs_revalidate_mapping(file->f_inode);
        return __cifs_writev(iocb, from, true);
 }
 
index 4810bd6..421be43 100644 (file)
@@ -1600,17 +1600,8 @@ smb2_copychunk_range(const unsigned int xid,
        int chunks_copied = 0;
        bool chunk_sizes_updated = false;
        ssize_t bytes_written, total_bytes_written = 0;
-       struct inode *inode;
 
        pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
-
-       /*
-        * We need to flush all unwritten data before we can send the
-        * copychunk ioctl to the server.
-        */
-       inode = d_inode(trgtfile->dentry);
-       filemap_write_and_wait(inode->i_mapping);
-
        if (pcchunk == NULL)
                return -ENOMEM;
 
@@ -3678,39 +3669,50 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
 {
        int rc;
        unsigned int xid;
-       struct inode *inode;
+       struct inode *inode = file_inode(file);
        struct cifsFileInfo *cfile = file->private_data;
-       struct cifsInodeInfo *cifsi;
+       struct cifsInodeInfo *cifsi = CIFS_I(inode);
        __le64 eof;
+       loff_t old_eof;
 
        xid = get_xid();
 
-       inode = d_inode(cfile->dentry);
-       cifsi = CIFS_I(inode);
+       inode_lock(inode);
 
-       if (off >= i_size_read(inode) ||
-           off + len >= i_size_read(inode)) {
+       old_eof = i_size_read(inode);
+       if ((off >= old_eof) ||
+           off + len >= old_eof) {
                rc = -EINVAL;
                goto out;
        }
 
+       filemap_invalidate_lock(inode->i_mapping);
+       rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
+       if (rc < 0)
+               goto out_2;
+
+       truncate_pagecache_range(inode, off, old_eof);
+
        rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
-                                 i_size_read(inode) - off - len, off);
+                                 old_eof - off - len, off);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
-       eof = cpu_to_le64(i_size_read(inode) - len);
+       eof = cpu_to_le64(old_eof - len);
        rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
                          cfile->fid.volatile_fid, cfile->pid, &eof);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
        rc = 0;
 
        cifsi->server_eof = i_size_read(inode) - len;
        truncate_setsize(inode, cifsi->server_eof);
        fscache_resize_cookie(cifs_inode_cookie(inode), cifsi->server_eof);
+out_2:
+       filemap_invalidate_unlock(inode->i_mapping);
  out:
+       inode_unlock(inode);
        free_xid(xid);
        return rc;
 }
@@ -3721,34 +3723,47 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
        int rc;
        unsigned int xid;
        struct cifsFileInfo *cfile = file->private_data;
+       struct inode *inode = file_inode(file);
        __le64 eof;
-       __u64  count;
+       __u64  count, old_eof;
 
        xid = get_xid();
 
-       if (off >= i_size_read(file->f_inode)) {
+       inode_lock(inode);
+
+       old_eof = i_size_read(inode);
+       if (off >= old_eof) {
                rc = -EINVAL;
                goto out;
        }
 
-       count = i_size_read(file->f_inode) - off;
-       eof = cpu_to_le64(i_size_read(file->f_inode) + len);
+       count = old_eof - off;
+       eof = cpu_to_le64(old_eof + len);
+
+       filemap_invalidate_lock(inode->i_mapping);
+       rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof + len - 1);
+       if (rc < 0)
+               goto out_2;
+       truncate_pagecache_range(inode, off, old_eof);
 
        rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
                          cfile->fid.volatile_fid, cfile->pid, &eof);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
        rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
-       rc = smb3_zero_range(file, tcon, off, len, 1);
+       rc = smb3_zero_data(file, tcon, off, len, xid);
        if (rc < 0)
-               goto out;
+               goto out_2;
 
        rc = 0;
+out_2:
+       filemap_invalidate_unlock(inode->i_mapping);
  out:
+       inode_unlock(inode);
        free_xid(xid);
        return rc;
 }
index 128e44e..6352ab3 100644 (file)
@@ -965,16 +965,17 @@ SMB2_negotiate(const unsigned int xid,
        } else if (rc != 0)
                goto neg_exit;
 
+       rc = -EIO;
        if (strcmp(server->vals->version_string,
                   SMB3ANY_VERSION_STRING) == 0) {
                if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
                        cifs_server_dbg(VFS,
                                "SMB2 dialect returned but not requested\n");
-                       return -EIO;
+                       goto neg_exit;
                } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
                        cifs_server_dbg(VFS,
                                "SMB2.1 dialect returned but not requested\n");
-                       return -EIO;
+                       goto neg_exit;
                } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) {
                        /* ops set to 3.0 by default for default so update */
                        server->ops = &smb311_operations;
@@ -985,7 +986,7 @@ SMB2_negotiate(const unsigned int xid,
                if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) {
                        cifs_server_dbg(VFS,
                                "SMB2 dialect returned but not requested\n");
-                       return -EIO;
+                       goto neg_exit;
                } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) {
                        /* ops set to 3.0 by default for default so update */
                        server->ops = &smb21_operations;
@@ -999,7 +1000,7 @@ SMB2_negotiate(const unsigned int xid,
                /* if requested single dialect ensure returned dialect matched */
                cifs_server_dbg(VFS, "Invalid 0x%x dialect returned: not requested\n",
                                le16_to_cpu(rsp->DialectRevision));
-               return -EIO;
+               goto neg_exit;
        }
 
        cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
@@ -1017,9 +1018,10 @@ SMB2_negotiate(const unsigned int xid,
        else {
                cifs_server_dbg(VFS, "Invalid dialect returned by server 0x%x\n",
                                le16_to_cpu(rsp->DialectRevision));
-               rc = -EIO;
                goto neg_exit;
        }
+
+       rc = 0;
        server->dialect = le16_to_cpu(rsp->DialectRevision);
 
        /*
index c2fe035..9a2753e 100644 (file)
@@ -194,10 +194,6 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
 
        *sent = 0;
 
-       smb_msg->msg_name = (struct sockaddr *) &server->dstaddr;
-       smb_msg->msg_namelen = sizeof(struct sockaddr);
-       smb_msg->msg_control = NULL;
-       smb_msg->msg_controllen = 0;
        if (server->noblocksnd)
                smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
        else
@@ -309,7 +305,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
        sigset_t mask, oldmask;
        size_t total_len = 0, sent, size;
        struct socket *ssocket = server->ssocket;
-       struct msghdr smb_msg;
+       struct msghdr smb_msg = {};
        __be32 rfc1002_marker;
 
        if (cifs_rdma_enabled(server)) {
index 9f4aae2..1ab4f5b 100644 (file)
@@ -832,6 +832,38 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
        }
 }
 
+static int dump_emit_page(struct coredump_params *cprm, struct page *page)
+{
+       struct bio_vec bvec = {
+               .bv_page        = page,
+               .bv_offset      = 0,
+               .bv_len         = PAGE_SIZE,
+       };
+       struct iov_iter iter;
+       struct file *file = cprm->file;
+       loff_t pos = file->f_pos;
+       ssize_t n;
+
+       if (cprm->to_skip) {
+               if (!__dump_skip(cprm, cprm->to_skip))
+                       return 0;
+               cprm->to_skip = 0;
+       }
+       if (cprm->written + PAGE_SIZE > cprm->limit)
+               return 0;
+       if (dump_interrupted())
+               return 0;
+       iov_iter_bvec(&iter, WRITE, &bvec, 1, PAGE_SIZE);
+       n = __kernel_write_iter(cprm->file, &iter, &pos);
+       if (n != PAGE_SIZE)
+               return 0;
+       file->f_pos = pos;
+       cprm->written += PAGE_SIZE;
+       cprm->pos += PAGE_SIZE;
+
+       return 1;
+}
+
 int dump_emit(struct coredump_params *cprm, const void *addr, int nr)
 {
        if (cprm->to_skip) {
@@ -863,7 +895,6 @@ int dump_user_range(struct coredump_params *cprm, unsigned long start,
 
        for (addr = start; addr < start + len; addr += PAGE_SIZE) {
                struct page *page;
-               int stop;
 
                /*
                 * To avoid having to allocate page tables for virtual address
@@ -874,10 +905,7 @@ int dump_user_range(struct coredump_params *cprm, unsigned long start,
                 */
                page = get_dump_page(addr);
                if (page) {
-                       void *kaddr = kmap_local_page(page);
-
-                       stop = !dump_emit(cprm, kaddr, PAGE_SIZE);
-                       kunmap_local(kaddr);
+                       int stop = !dump_emit_page(cprm, page);
                        put_page(page);
                        if (stop)
                                return 0;
index c440dce..1c68678 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1445,6 +1445,9 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
        loff_t done = 0;
        int ret;
 
+       if (!iomi.len)
+               return 0;
+
        if (iov_iter_rw(iter) == WRITE) {
                lockdep_assert_held_write(&iomi.inode->i_rwsem);
                iomi.flags |= IOMAP_WRITE;
index 3dcf0b8..232cfdf 100644 (file)
@@ -745,6 +745,28 @@ void debugfs_remove(struct dentry *dentry)
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
 /**
+ * debugfs_lookup_and_remove - lookup a directory or file and recursively remove it
+ * @name: a pointer to a string containing the name of the item to look up.
+ * @parent: a pointer to the parent dentry of the item.
+ *
+ * This is the equlivant of doing something like
+ * debugfs_remove(debugfs_lookup(..)) but with the proper reference counting
+ * handled for the directory being looked up.
+ */
+void debugfs_lookup_and_remove(const char *name, struct dentry *parent)
+{
+       struct dentry *dentry;
+
+       dentry = debugfs_lookup(name, parent);
+       if (!dentry)
+               return;
+
+       debugfs_remove(dentry);
+       dput(dentry);
+}
+EXPORT_SYMBOL_GPL(debugfs_lookup_and_remove);
+
+/**
  * debugfs_rename - rename a file/directory in the debugfs filesystem
  * @old_dir: a pointer to the parent dentry for the renamed object. This
  *          should be a directory dentry.
index 8e01d89..b5fd9d7 100644 (file)
@@ -222,8 +222,10 @@ static int erofs_fscache_meta_read_folio(struct file *data, struct folio *folio)
 
        rreq = erofs_fscache_alloc_request(folio_mapping(folio),
                                folio_pos(folio), folio_size(folio));
-       if (IS_ERR(rreq))
+       if (IS_ERR(rreq)) {
+               ret = PTR_ERR(rreq);
                goto out;
+       }
 
        return erofs_fscache_read_folios_async(mdev.m_fscache->cookie,
                                rreq, mdev.m_pa);
@@ -301,8 +303,10 @@ static int erofs_fscache_read_folio(struct file *file, struct folio *folio)
 
        rreq = erofs_fscache_alloc_request(folio_mapping(folio),
                                folio_pos(folio), folio_size(folio));
-       if (IS_ERR(rreq))
+       if (IS_ERR(rreq)) {
+               ret = PTR_ERR(rreq);
                goto out_unlock;
+       }
 
        pstart = mdev.m_pa + (pos - map.m_la);
        return erofs_fscache_read_folios_async(mdev.m_fscache->cookie,
index cfee49d..a01cc82 100644 (file)
@@ -195,7 +195,6 @@ struct erofs_workgroup {
        atomic_t refcount;
 };
 
-#if defined(CONFIG_SMP)
 static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
                                                 int val)
 {
@@ -224,34 +223,6 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
        return atomic_cond_read_relaxed(&grp->refcount,
                                        VAL != EROFS_LOCKED_MAGIC);
 }
-#else
-static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp,
-                                                int val)
-{
-       preempt_disable();
-       /* no need to spin on UP platforms, let's just disable preemption. */
-       if (val != atomic_read(&grp->refcount)) {
-               preempt_enable();
-               return false;
-       }
-       return true;
-}
-
-static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp,
-                                           int orig_val)
-{
-       preempt_enable();
-}
-
-static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
-{
-       int v = atomic_read(&grp->refcount);
-
-       /* workgroup is never freezed on uniprocessor systems */
-       DBG_BUGON(v == EROFS_LOCKED_MAGIC);
-       return v;
-}
-#endif /* !CONFIG_SMP */
 #endif /* !CONFIG_EROFS_FS_ZIP */
 
 /* we strictly follow PAGE_SIZE and no buffer head yet */
index 572f0b8..d58549c 100644 (file)
@@ -141,7 +141,7 @@ struct z_erofs_maprecorder {
        u8  type, headtype;
        u16 clusterofs;
        u16 delta[2];
-       erofs_blk_t pblk, compressedlcs;
+       erofs_blk_t pblk, compressedblks;
        erofs_off_t nextpackoff;
 };
 
@@ -192,7 +192,7 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
                                DBG_BUGON(1);
                                return -EFSCORRUPTED;
                        }
-                       m->compressedlcs = m->delta[0] &
+                       m->compressedblks = m->delta[0] &
                                ~Z_EROFS_VLE_DI_D0_CBLKCNT;
                        m->delta[0] = 1;
                }
@@ -293,7 +293,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
                                DBG_BUGON(1);
                                return -EFSCORRUPTED;
                        }
-                       m->compressedlcs = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
+                       m->compressedblks = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
                        m->delta[0] = 1;
                        return 0;
                } else if (i + 1 != (int)vcnt) {
@@ -497,7 +497,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
                return 0;
        }
        lcn = m->lcn + 1;
-       if (m->compressedlcs)
+       if (m->compressedblks)
                goto out;
 
        err = z_erofs_load_cluster_from_disk(m, lcn, false);
@@ -506,7 +506,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
 
        /*
         * If the 1st NONHEAD lcluster has already been handled initially w/o
-        * valid compressedlcs, which means at least it mustn't be CBLKCNT, or
+        * valid compressedblks, which means at least it mustn't be CBLKCNT, or
         * an internal implemenatation error is detected.
         *
         * The following code can also handle it properly anyway, but let's
@@ -523,12 +523,12 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
                 * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
                 * rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
                 */
-               m->compressedlcs = 1;
+               m->compressedblks = 1 << (lclusterbits - LOG_BLOCK_SIZE);
                break;
        case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
                if (m->delta[0] != 1)
                        goto err_bonus_cblkcnt;
-               if (m->compressedlcs)
+               if (m->compressedblks)
                        break;
                fallthrough;
        default:
@@ -539,7 +539,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
                return -EFSCORRUPTED;
        }
 out:
-       map->m_plen = (u64)m->compressedlcs << lclusterbits;
+       map->m_plen = (u64)m->compressedblks << LOG_BLOCK_SIZE;
        return 0;
 err_bonus_cblkcnt:
        erofs_err(m->inode->i_sb,
index 9a5ca7b..d046dbb 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -65,7 +65,6 @@
 #include <linux/io_uring.h>
 #include <linux/syscall_user_dispatch.h>
 #include <linux/coredump.h>
-#include <linux/time_namespace.h>
 
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
@@ -979,12 +978,10 @@ static int exec_mmap(struct mm_struct *mm)
 {
        struct task_struct *tsk;
        struct mm_struct *old_mm, *active_mm;
-       bool vfork;
        int ret;
 
        /* Notify parent that we're no longer interested in the old VM */
        tsk = current;
-       vfork = !!tsk->vfork_done;
        old_mm = current->mm;
        exec_mm_release(tsk, old_mm);
        if (old_mm)
@@ -1029,10 +1026,6 @@ static int exec_mmap(struct mm_struct *mm)
        tsk->mm->vmacache_seqnum = 0;
        vmacache_flush(tsk);
        task_unlock(tsk);
-
-       if (vfork)
-               timens_on_fork(tsk->nsproxy, tsk);
-
        if (old_mm) {
                mmap_read_unlock(old_mm);
                BUG_ON(active_mm != old_mm);
index ee0b7cf..41ae4cc 100644 (file)
@@ -270,8 +270,7 @@ int exfat_zeroed_cluster(struct inode *dir, unsigned int clu)
        struct super_block *sb = dir->i_sb;
        struct exfat_sb_info *sbi = EXFAT_SB(sb);
        struct buffer_head *bh;
-       sector_t blknr, last_blknr;
-       int i;
+       sector_t blknr, last_blknr, i;
 
        blknr = exfat_cluster_to_sector(sbi, clu);
        last_blknr = blknr + sbi->sect_per_clus;
index 9bca556..3bf9a69 100644 (file)
@@ -167,8 +167,6 @@ enum SHIFT_DIRECTION {
 #define EXT4_MB_CR0_OPTIMIZED          0x8000
 /* Avg fragment size rb tree lookup succeeded at least once for cr = 1 */
 #define EXT4_MB_CR1_OPTIMIZED          0x00010000
-/* Perform linear traversal for one group */
-#define EXT4_MB_SEARCH_NEXT_LINEAR     0x00020000
 struct ext4_allocation_request {
        /* target inode for block we're allocating */
        struct inode *inode;
@@ -1600,8 +1598,8 @@ struct ext4_sb_info {
        struct list_head s_discard_list;
        struct work_struct s_discard_work;
        atomic_t s_retry_alloc_pending;
-       struct rb_root s_mb_avg_fragment_size_root;
-       rwlock_t s_mb_rb_lock;
+       struct list_head *s_mb_avg_fragment_size;
+       rwlock_t *s_mb_avg_fragment_size_locks;
        struct list_head *s_mb_largest_free_orders;
        rwlock_t *s_mb_largest_free_orders_locks;
 
@@ -3413,6 +3411,8 @@ struct ext4_group_info {
        ext4_grpblk_t   bb_first_free;  /* first free block */
        ext4_grpblk_t   bb_free;        /* total free blocks */
        ext4_grpblk_t   bb_fragments;   /* nr of freespace fragments */
+       int             bb_avg_fragment_size_order;     /* order of average
+                                                          fragment in BG */
        ext4_grpblk_t   bb_largest_free_order;/* order of largest frag in BG */
        ext4_group_t    bb_group;       /* Group number */
        struct          list_head bb_prealloc_list;
@@ -3420,7 +3420,7 @@ struct ext4_group_info {
        void            *bb_bitmap;
 #endif
        struct rw_semaphore alloc_sem;
-       struct rb_node  bb_avg_fragment_size_rb;
+       struct list_head bb_avg_fragment_size_node;
        struct list_head bb_largest_free_order_node;
        ext4_grpblk_t   bb_counters[];  /* Nr of free power-of-two-block
                                         * regions, index is order.
index c148bb9..5235974 100644 (file)
@@ -460,6 +460,10 @@ static int __ext4_ext_check(const char *function, unsigned int line,
                error_msg = "invalid eh_entries";
                goto corrupted;
        }
+       if (unlikely((eh->eh_entries == 0) && (depth > 0))) {
+               error_msg = "eh_entries is 0 but eh_depth is > 0";
+               goto corrupted;
+       }
        if (!ext4_valid_extent_entries(inode, eh, lblk, &pblk, depth)) {
                error_msg = "invalid extent entries";
                goto corrupted;
index f73e5eb..208b87c 100644 (file)
@@ -510,7 +510,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
                goto fallback;
        }
 
-       max_dirs = ndirs / ngroups + inodes_per_group / 16;
+       max_dirs = ndirs / ngroups + inodes_per_group*flex_size / 16;
        min_inodes = avefreei - inodes_per_group*flex_size / 4;
        if (min_inodes < 1)
                min_inodes = 1;
index bd8f8b5..9dad930 100644 (file)
  *    number of buddy bitmap orders possible) number of lists. Group-infos are
  *    placed in appropriate lists.
  *
- * 2) Average fragment size rb tree (sbi->s_mb_avg_fragment_size_root)
+ * 2) Average fragment size lists (sbi->s_mb_avg_fragment_size)
  *
- *    Locking: sbi->s_mb_rb_lock (rwlock)
+ *    Locking: sbi->s_mb_avg_fragment_size_locks(array of rw locks)
  *
- *    This is a red black tree consisting of group infos and the tree is sorted
- *    by average fragment sizes (which is calculated as ext4_group_info->bb_free
- *    / ext4_group_info->bb_fragments).
+ *    This is an array of lists where in the i-th list there are groups with
+ *    average fragment size >= 2^i and < 2^(i+1). The average fragment size
+ *    is computed as ext4_group_info->bb_free / ext4_group_info->bb_fragments.
+ *    Note that we don't bother with a special list for completely empty groups
+ *    so we only have MB_NUM_ORDERS(sb) lists.
  *
  * When "mb_optimize_scan" mount option is set, mballoc consults the above data
  * structures to decide the order in which groups are to be traversed for
  *
  * At CR = 1, we only consider groups where average fragment size > request
  * size. So, we lookup a group which has average fragment size just above or
- * equal to request size using our rb tree (data structure 2) in O(log N) time.
+ * equal to request size using our average fragment size group lists (data
+ * structure 2) in O(1) time.
  *
  * If "mb_optimize_scan" mount option is not set, mballoc traverses groups in
  * linear order which requires O(N) search time for each CR 0 and CR 1 phase.
@@ -802,65 +805,51 @@ static void ext4_mb_mark_free_simple(struct super_block *sb,
        }
 }
 
-static void ext4_mb_rb_insert(struct rb_root *root, struct rb_node *new,
-                       int (*cmp)(struct rb_node *, struct rb_node *))
+static int mb_avg_fragment_size_order(struct super_block *sb, ext4_grpblk_t len)
 {
-       struct rb_node **iter = &root->rb_node, *parent = NULL;
+       int order;
 
-       while (*iter) {
-               parent = *iter;
-               if (cmp(new, *iter) > 0)
-                       iter = &((*iter)->rb_left);
-               else
-                       iter = &((*iter)->rb_right);
-       }
-
-       rb_link_node(new, parent, iter);
-       rb_insert_color(new, root);
-}
-
-static int
-ext4_mb_avg_fragment_size_cmp(struct rb_node *rb1, struct rb_node *rb2)
-{
-       struct ext4_group_info *grp1 = rb_entry(rb1,
-                                               struct ext4_group_info,
-                                               bb_avg_fragment_size_rb);
-       struct ext4_group_info *grp2 = rb_entry(rb2,
-                                               struct ext4_group_info,
-                                               bb_avg_fragment_size_rb);
-       int num_frags_1, num_frags_2;
-
-       num_frags_1 = grp1->bb_fragments ?
-               grp1->bb_free / grp1->bb_fragments : 0;
-       num_frags_2 = grp2->bb_fragments ?
-               grp2->bb_free / grp2->bb_fragments : 0;
-
-       return (num_frags_2 - num_frags_1);
+       /*
+        * We don't bother with a special lists groups with only 1 block free
+        * extents and for completely empty groups.
+        */
+       order = fls(len) - 2;
+       if (order < 0)
+               return 0;
+       if (order == MB_NUM_ORDERS(sb))
+               order--;
+       return order;
 }
 
-/*
- * Reinsert grpinfo into the avg_fragment_size tree with new average
- * fragment size.
- */
+/* Move group to appropriate avg_fragment_size list */
 static void
 mb_update_avg_fragment_size(struct super_block *sb, struct ext4_group_info *grp)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int new_order;
 
        if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_free == 0)
                return;
 
-       write_lock(&sbi->s_mb_rb_lock);
-       if (!RB_EMPTY_NODE(&grp->bb_avg_fragment_size_rb)) {
-               rb_erase(&grp->bb_avg_fragment_size_rb,
-                               &sbi->s_mb_avg_fragment_size_root);
-               RB_CLEAR_NODE(&grp->bb_avg_fragment_size_rb);
-       }
+       new_order = mb_avg_fragment_size_order(sb,
+                                       grp->bb_free / grp->bb_fragments);
+       if (new_order == grp->bb_avg_fragment_size_order)
+               return;
 
-       ext4_mb_rb_insert(&sbi->s_mb_avg_fragment_size_root,
-               &grp->bb_avg_fragment_size_rb,
-               ext4_mb_avg_fragment_size_cmp);
-       write_unlock(&sbi->s_mb_rb_lock);
+       if (grp->bb_avg_fragment_size_order != -1) {
+               write_lock(&sbi->s_mb_avg_fragment_size_locks[
+                                       grp->bb_avg_fragment_size_order]);
+               list_del(&grp->bb_avg_fragment_size_node);
+               write_unlock(&sbi->s_mb_avg_fragment_size_locks[
+                                       grp->bb_avg_fragment_size_order]);
+       }
+       grp->bb_avg_fragment_size_order = new_order;
+       write_lock(&sbi->s_mb_avg_fragment_size_locks[
+                                       grp->bb_avg_fragment_size_order]);
+       list_add_tail(&grp->bb_avg_fragment_size_node,
+               &sbi->s_mb_avg_fragment_size[grp->bb_avg_fragment_size_order]);
+       write_unlock(&sbi->s_mb_avg_fragment_size_locks[
+                                       grp->bb_avg_fragment_size_order]);
 }
 
 /*
@@ -909,86 +898,55 @@ static void ext4_mb_choose_next_group_cr0(struct ext4_allocation_context *ac,
                *new_cr = 1;
        } else {
                *group = grp->bb_group;
-               ac->ac_last_optimal_group = *group;
                ac->ac_flags |= EXT4_MB_CR0_OPTIMIZED;
        }
 }
 
 /*
- * Choose next group by traversing average fragment size tree. Updates *new_cr
- * if cr lvel needs an update. Sets EXT4_MB_SEARCH_NEXT_LINEAR to indicate that
- * the linear search should continue for one iteration since there's lock
- * contention on the rb tree lock.
+ * Choose next group by traversing average fragment size list of suitable
+ * order. Updates *new_cr if cr level needs an update.
  */
 static void ext4_mb_choose_next_group_cr1(struct ext4_allocation_context *ac,
                int *new_cr, ext4_group_t *group, ext4_group_t ngroups)
 {
        struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
-       int avg_fragment_size, best_so_far;
-       struct rb_node *node, *found;
-       struct ext4_group_info *grp;
-
-       /*
-        * If there is contention on the lock, instead of waiting for the lock
-        * to become available, just continue searching lineraly. We'll resume
-        * our rb tree search later starting at ac->ac_last_optimal_group.
-        */
-       if (!read_trylock(&sbi->s_mb_rb_lock)) {
-               ac->ac_flags |= EXT4_MB_SEARCH_NEXT_LINEAR;
-               return;
-       }
+       struct ext4_group_info *grp = NULL, *iter;
+       int i;
 
        if (unlikely(ac->ac_flags & EXT4_MB_CR1_OPTIMIZED)) {
                if (sbi->s_mb_stats)
                        atomic_inc(&sbi->s_bal_cr1_bad_suggestions);
-               /* We have found something at CR 1 in the past */
-               grp = ext4_get_group_info(ac->ac_sb, ac->ac_last_optimal_group);
-               for (found = rb_next(&grp->bb_avg_fragment_size_rb); found != NULL;
-                    found = rb_next(found)) {
-                       grp = rb_entry(found, struct ext4_group_info,
-                                      bb_avg_fragment_size_rb);
+       }
+
+       for (i = mb_avg_fragment_size_order(ac->ac_sb, ac->ac_g_ex.fe_len);
+            i < MB_NUM_ORDERS(ac->ac_sb); i++) {
+               if (list_empty(&sbi->s_mb_avg_fragment_size[i]))
+                       continue;
+               read_lock(&sbi->s_mb_avg_fragment_size_locks[i]);
+               if (list_empty(&sbi->s_mb_avg_fragment_size[i])) {
+                       read_unlock(&sbi->s_mb_avg_fragment_size_locks[i]);
+                       continue;
+               }
+               list_for_each_entry(iter, &sbi->s_mb_avg_fragment_size[i],
+                                   bb_avg_fragment_size_node) {
                        if (sbi->s_mb_stats)
                                atomic64_inc(&sbi->s_bal_cX_groups_considered[1]);
-                       if (likely(ext4_mb_good_group(ac, grp->bb_group, 1)))
+                       if (likely(ext4_mb_good_group(ac, iter->bb_group, 1))) {
+                               grp = iter;
                                break;
-               }
-               goto done;
-       }
-
-       node = sbi->s_mb_avg_fragment_size_root.rb_node;
-       best_so_far = 0;
-       found = NULL;
-
-       while (node) {
-               grp = rb_entry(node, struct ext4_group_info,
-                              bb_avg_fragment_size_rb);
-               avg_fragment_size = 0;
-               if (ext4_mb_good_group(ac, grp->bb_group, 1)) {
-                       avg_fragment_size = grp->bb_fragments ?
-                               grp->bb_free / grp->bb_fragments : 0;
-                       if (!best_so_far || avg_fragment_size < best_so_far) {
-                               best_so_far = avg_fragment_size;
-                               found = node;
                        }
                }
-               if (avg_fragment_size > ac->ac_g_ex.fe_len)
-                       node = node->rb_right;
-               else
-                       node = node->rb_left;
+               read_unlock(&sbi->s_mb_avg_fragment_size_locks[i]);
+               if (grp)
+                       break;
        }
 
-done:
-       if (found) {
-               grp = rb_entry(found, struct ext4_group_info,
-                              bb_avg_fragment_size_rb);
+       if (grp) {
                *group = grp->bb_group;
                ac->ac_flags |= EXT4_MB_CR1_OPTIMIZED;
        } else {
                *new_cr = 2;
        }
-
-       read_unlock(&sbi->s_mb_rb_lock);
-       ac->ac_last_optimal_group = *group;
 }
 
 static inline int should_optimize_scan(struct ext4_allocation_context *ac)
@@ -1017,11 +975,6 @@ next_linear_group(struct ext4_allocation_context *ac, int group, int ngroups)
                goto inc_and_return;
        }
 
-       if (ac->ac_flags & EXT4_MB_SEARCH_NEXT_LINEAR) {
-               ac->ac_flags &= ~EXT4_MB_SEARCH_NEXT_LINEAR;
-               goto inc_and_return;
-       }
-
        return group;
 inc_and_return:
        /*
@@ -1049,8 +1002,10 @@ static void ext4_mb_choose_next_group(struct ext4_allocation_context *ac,
 {
        *new_cr = ac->ac_criteria;
 
-       if (!should_optimize_scan(ac) || ac->ac_groups_linear_remaining)
+       if (!should_optimize_scan(ac) || ac->ac_groups_linear_remaining) {
+               *group = next_linear_group(ac, *group, ngroups);
                return;
+       }
 
        if (*new_cr == 0) {
                ext4_mb_choose_next_group_cr0(ac, new_cr, group, ngroups);
@@ -1075,23 +1030,25 @@ mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        int i;
 
-       if (test_opt2(sb, MB_OPTIMIZE_SCAN) && grp->bb_largest_free_order >= 0) {
+       for (i = MB_NUM_ORDERS(sb) - 1; i >= 0; i--)
+               if (grp->bb_counters[i] > 0)
+                       break;
+       /* No need to move between order lists? */
+       if (!test_opt2(sb, MB_OPTIMIZE_SCAN) ||
+           i == grp->bb_largest_free_order) {
+               grp->bb_largest_free_order = i;
+               return;
+       }
+
+       if (grp->bb_largest_free_order >= 0) {
                write_lock(&sbi->s_mb_largest_free_orders_locks[
                                              grp->bb_largest_free_order]);
                list_del_init(&grp->bb_largest_free_order_node);
                write_unlock(&sbi->s_mb_largest_free_orders_locks[
                                              grp->bb_largest_free_order]);
        }
-       grp->bb_largest_free_order = -1; /* uninit */
-
-       for (i = MB_NUM_ORDERS(sb) - 1; i >= 0; i--) {
-               if (grp->bb_counters[i] > 0) {
-                       grp->bb_largest_free_order = i;
-                       break;
-               }
-       }
-       if (test_opt2(sb, MB_OPTIMIZE_SCAN) &&
-           grp->bb_largest_free_order >= 0 && grp->bb_free) {
+       grp->bb_largest_free_order = i;
+       if (grp->bb_largest_free_order >= 0 && grp->bb_free) {
                write_lock(&sbi->s_mb_largest_free_orders_locks[
                                              grp->bb_largest_free_order]);
                list_add_tail(&grp->bb_largest_free_order_node,
@@ -1148,13 +1105,13 @@ void ext4_mb_generate_buddy(struct super_block *sb,
                                        EXT4_GROUP_INFO_BBITMAP_CORRUPT);
        }
        mb_set_largest_free_order(sb, grp);
+       mb_update_avg_fragment_size(sb, grp);
 
        clear_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state));
 
        period = get_cycles() - period;
        atomic_inc(&sbi->s_mb_buddies_generated);
        atomic64_add(period, &sbi->s_mb_generation_time);
-       mb_update_avg_fragment_size(sb, grp);
 }
 
 /* The buddy information is attached the buddy cache inode
@@ -2636,7 +2593,7 @@ static noinline_for_stack int
 ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
 {
        ext4_group_t prefetch_grp = 0, ngroups, group, i;
-       int cr = -1;
+       int cr = -1, new_cr;
        int err = 0, first_err = 0;
        unsigned int nr = 0, prefetch_ios = 0;
        struct ext4_sb_info *sbi;
@@ -2707,17 +2664,14 @@ repeat:
                 * from the goal value specified
                 */
                group = ac->ac_g_ex.fe_group;
-               ac->ac_last_optimal_group = group;
                ac->ac_groups_linear_remaining = sbi->s_mb_max_linear_groups;
                prefetch_grp = group;
 
-               for (i = 0; i < ngroups; group = next_linear_group(ac, group, ngroups),
-                            i++) {
-                       int ret = 0, new_cr;
+               for (i = 0, new_cr = cr; i < ngroups; i++,
+                    ext4_mb_choose_next_group(ac, &new_cr, &group, ngroups)) {
+                       int ret = 0;
 
                        cond_resched();
-
-                       ext4_mb_choose_next_group(ac, &new_cr, &group, ngroups);
                        if (new_cr != cr) {
                                cr = new_cr;
                                goto repeat;
@@ -2991,9 +2945,7 @@ __acquires(&EXT4_SB(sb)->s_mb_rb_lock)
        struct super_block *sb = pde_data(file_inode(seq->file));
        unsigned long position;
 
-       read_lock(&EXT4_SB(sb)->s_mb_rb_lock);
-
-       if (*pos < 0 || *pos >= MB_NUM_ORDERS(sb) + 1)
+       if (*pos < 0 || *pos >= 2*MB_NUM_ORDERS(sb))
                return NULL;
        position = *pos + 1;
        return (void *) ((unsigned long) position);
@@ -3005,7 +2957,7 @@ static void *ext4_mb_seq_structs_summary_next(struct seq_file *seq, void *v, lof
        unsigned long position;
 
        ++*pos;
-       if (*pos < 0 || *pos >= MB_NUM_ORDERS(sb) + 1)
+       if (*pos < 0 || *pos >= 2*MB_NUM_ORDERS(sb))
                return NULL;
        position = *pos + 1;
        return (void *) ((unsigned long) position);
@@ -3017,29 +2969,22 @@ static int ext4_mb_seq_structs_summary_show(struct seq_file *seq, void *v)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned long position = ((unsigned long) v);
        struct ext4_group_info *grp;
-       struct rb_node *n;
-       unsigned int count, min, max;
+       unsigned int count;
 
        position--;
        if (position >= MB_NUM_ORDERS(sb)) {
-               seq_puts(seq, "fragment_size_tree:\n");
-               n = rb_first(&sbi->s_mb_avg_fragment_size_root);
-               if (!n) {
-                       seq_puts(seq, "\ttree_min: 0\n\ttree_max: 0\n\ttree_nodes: 0\n");
-                       return 0;
-               }
-               grp = rb_entry(n, struct ext4_group_info, bb_avg_fragment_size_rb);
-               min = grp->bb_fragments ? grp->bb_free / grp->bb_fragments : 0;
-               count = 1;
-               while (rb_next(n)) {
-                       count++;
-                       n = rb_next(n);
-               }
-               grp = rb_entry(n, struct ext4_group_info, bb_avg_fragment_size_rb);
-               max = grp->bb_fragments ? grp->bb_free / grp->bb_fragments : 0;
+               position -= MB_NUM_ORDERS(sb);
+               if (position == 0)
+                       seq_puts(seq, "avg_fragment_size_lists:\n");
 
-               seq_printf(seq, "\ttree_min: %u\n\ttree_max: %u\n\ttree_nodes: %u\n",
-                          min, max, count);
+               count = 0;
+               read_lock(&sbi->s_mb_avg_fragment_size_locks[position]);
+               list_for_each_entry(grp, &sbi->s_mb_avg_fragment_size[position],
+                                   bb_avg_fragment_size_node)
+                       count++;
+               read_unlock(&sbi->s_mb_avg_fragment_size_locks[position]);
+               seq_printf(seq, "\tlist_order_%u_groups: %u\n",
+                                       (unsigned int)position, count);
                return 0;
        }
 
@@ -3049,9 +2994,11 @@ static int ext4_mb_seq_structs_summary_show(struct seq_file *seq, void *v)
                seq_puts(seq, "max_free_order_lists:\n");
        }
        count = 0;
+       read_lock(&sbi->s_mb_largest_free_orders_locks[position]);
        list_for_each_entry(grp, &sbi->s_mb_largest_free_orders[position],
                            bb_largest_free_order_node)
                count++;
+       read_unlock(&sbi->s_mb_largest_free_orders_locks[position]);
        seq_printf(seq, "\tlist_order_%u_groups: %u\n",
                   (unsigned int)position, count);
 
@@ -3059,11 +3006,7 @@ static int ext4_mb_seq_structs_summary_show(struct seq_file *seq, void *v)
 }
 
 static void ext4_mb_seq_structs_summary_stop(struct seq_file *seq, void *v)
-__releases(&EXT4_SB(sb)->s_mb_rb_lock)
 {
-       struct super_block *sb = pde_data(file_inode(seq->file));
-
-       read_unlock(&EXT4_SB(sb)->s_mb_rb_lock);
 }
 
 const struct seq_operations ext4_mb_seq_structs_summary_ops = {
@@ -3176,8 +3119,9 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
        init_rwsem(&meta_group_info[i]->alloc_sem);
        meta_group_info[i]->bb_free_root = RB_ROOT;
        INIT_LIST_HEAD(&meta_group_info[i]->bb_largest_free_order_node);
-       RB_CLEAR_NODE(&meta_group_info[i]->bb_avg_fragment_size_rb);
+       INIT_LIST_HEAD(&meta_group_info[i]->bb_avg_fragment_size_node);
        meta_group_info[i]->bb_largest_free_order = -1;  /* uninit */
+       meta_group_info[i]->bb_avg_fragment_size_order = -1;  /* uninit */
        meta_group_info[i]->bb_group = group;
 
        mb_group_bb_bitmap_alloc(sb, meta_group_info[i], group);
@@ -3426,7 +3370,24 @@ int ext4_mb_init(struct super_block *sb)
                i++;
        } while (i < MB_NUM_ORDERS(sb));
 
-       sbi->s_mb_avg_fragment_size_root = RB_ROOT;
+       sbi->s_mb_avg_fragment_size =
+               kmalloc_array(MB_NUM_ORDERS(sb), sizeof(struct list_head),
+                       GFP_KERNEL);
+       if (!sbi->s_mb_avg_fragment_size) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       sbi->s_mb_avg_fragment_size_locks =
+               kmalloc_array(MB_NUM_ORDERS(sb), sizeof(rwlock_t),
+                       GFP_KERNEL);
+       if (!sbi->s_mb_avg_fragment_size_locks) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       for (i = 0; i < MB_NUM_ORDERS(sb); i++) {
+               INIT_LIST_HEAD(&sbi->s_mb_avg_fragment_size[i]);
+               rwlock_init(&sbi->s_mb_avg_fragment_size_locks[i]);
+       }
        sbi->s_mb_largest_free_orders =
                kmalloc_array(MB_NUM_ORDERS(sb), sizeof(struct list_head),
                        GFP_KERNEL);
@@ -3445,7 +3406,6 @@ int ext4_mb_init(struct super_block *sb)
                INIT_LIST_HEAD(&sbi->s_mb_largest_free_orders[i]);
                rwlock_init(&sbi->s_mb_largest_free_orders_locks[i]);
        }
-       rwlock_init(&sbi->s_mb_rb_lock);
 
        spin_lock_init(&sbi->s_md_lock);
        sbi->s_mb_free_pending = 0;
@@ -3516,6 +3476,8 @@ out_free_locality_groups:
        free_percpu(sbi->s_locality_groups);
        sbi->s_locality_groups = NULL;
 out:
+       kfree(sbi->s_mb_avg_fragment_size);
+       kfree(sbi->s_mb_avg_fragment_size_locks);
        kfree(sbi->s_mb_largest_free_orders);
        kfree(sbi->s_mb_largest_free_orders_locks);
        kfree(sbi->s_mb_offsets);
@@ -3582,6 +3544,8 @@ int ext4_mb_release(struct super_block *sb)
                kvfree(group_info);
                rcu_read_unlock();
        }
+       kfree(sbi->s_mb_avg_fragment_size);
+       kfree(sbi->s_mb_avg_fragment_size_locks);
        kfree(sbi->s_mb_largest_free_orders);
        kfree(sbi->s_mb_largest_free_orders_locks);
        kfree(sbi->s_mb_offsets);
@@ -5193,6 +5157,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
        struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
        int bsbits = ac->ac_sb->s_blocksize_bits;
        loff_t size, isize;
+       bool inode_pa_eligible, group_pa_eligible;
 
        if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
                return;
@@ -5200,25 +5165,27 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
        if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY))
                return;
 
+       group_pa_eligible = sbi->s_mb_group_prealloc > 0;
+       inode_pa_eligible = true;
        size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len);
        isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
                >> bsbits;
 
+       /* No point in using inode preallocation for closed files */
        if ((size == isize) && !ext4_fs_is_busy(sbi) &&
-           !inode_is_open_for_write(ac->ac_inode)) {
-               ac->ac_flags |= EXT4_MB_HINT_NOPREALLOC;
-               return;
-       }
+           !inode_is_open_for_write(ac->ac_inode))
+               inode_pa_eligible = false;
 
-       if (sbi->s_mb_group_prealloc <= 0) {
-               ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
-               return;
-       }
-
-       /* don't use group allocation for large files */
        size = max(size, isize);
-       if (size > sbi->s_mb_stream_request) {
-               ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
+       /* Don't use group allocation for large files */
+       if (size > sbi->s_mb_stream_request)
+               group_pa_eligible = false;
+
+       if (!group_pa_eligible) {
+               if (inode_pa_eligible)
+                       ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
+               else
+                       ac->ac_flags |= EXT4_MB_HINT_NOPREALLOC;
                return;
        }
 
@@ -5565,6 +5532,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
        ext4_fsblk_t block = 0;
        unsigned int inquota = 0;
        unsigned int reserv_clstrs = 0;
+       int retries = 0;
        u64 seq;
 
        might_sleep();
@@ -5667,7 +5635,8 @@ repeat:
                        ar->len = ac->ac_b_ex.fe_len;
                }
        } else {
-               if (ext4_mb_discard_preallocations_should_retry(sb, ac, &seq))
+               if (++retries < 3 &&
+                   ext4_mb_discard_preallocations_should_retry(sb, ac, &seq))
                        goto repeat;
                /*
                 * If block allocation fails then the pa allocated above
index 39da92c..dcda2a9 100644 (file)
@@ -178,7 +178,6 @@ struct ext4_allocation_context {
        /* copy of the best found extent taken before preallocation efforts */
        struct ext4_free_extent ac_f_ex;
 
-       ext4_group_t ac_last_optimal_group;
        __u32 ac_groups_considered;
        __u32 ac_flags;         /* allocation hints */
        __u16 ac_groups_scanned;
index 87e96b9..3e206d3 100644 (file)
@@ -16,6 +16,7 @@ struct shrink_control;
 struct fs_context;
 struct user_namespace;
 struct pipe_inode_info;
+struct iov_iter;
 
 /*
  * block/bdev.c
@@ -221,3 +222,5 @@ ssize_t do_getxattr(struct user_namespace *mnt_userns,
 int setxattr_copy(const char __user *name, struct xattr_ctx *ctx);
 int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                struct xattr_ctx *ctx);
+
+ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos);
index 27c720d..898dd95 100644 (file)
@@ -606,6 +606,31 @@ static inline gfp_t nfs_io_gfp_mask(void)
        return GFP_KERNEL;
 }
 
+/*
+ * Special version of should_remove_suid() that ignores capabilities.
+ */
+static inline int nfs_should_remove_suid(const struct inode *inode)
+{
+       umode_t mode = inode->i_mode;
+       int kill = 0;
+
+       /* suid always must be killed */
+       if (unlikely(mode & S_ISUID))
+               kill = ATTR_KILL_SUID;
+
+       /*
+        * sgid without any exec bits is just a mandatory locking mark; leave
+        * it alone.  If some exec bits are set, it's a real sgid; kill it.
+        */
+       if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
+               kill |= ATTR_KILL_SGID;
+
+       if (unlikely(kill && S_ISREG(mode)))
+               return kill;
+
+       return 0;
+}
+
 /* unlink.c */
 extern struct rpc_task *
 nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
index 068c45b..6dab9e4 100644 (file)
@@ -78,10 +78,15 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
 
        status = nfs4_call_sync(server->client, server, msg,
                                &args.seq_args, &res.seq_res, 0);
-       if (status == 0)
+       if (status == 0) {
+               if (nfs_should_remove_suid(inode)) {
+                       spin_lock(&inode->i_lock);
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
+                       spin_unlock(&inode->i_lock);
+               }
                status = nfs_post_op_update_inode_force_wcc(inode,
                                                            res.falloc_fattr);
-
+       }
        if (msg->rpc_proc == &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE])
                trace_nfs4_fallocate(inode, &args, status);
        else
index 82944e1..ee66ffd 100644 (file)
@@ -1051,22 +1051,31 @@ static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
        if (ctx->bsize)
                sb->s_blocksize = nfs_block_size(ctx->bsize, &sb->s_blocksize_bits);
 
-       if (server->nfs_client->rpc_ops->version != 2) {
-               /* The VFS shouldn't apply the umask to mode bits. We will do
-                * so ourselves when necessary.
+       switch (server->nfs_client->rpc_ops->version) {
+       case 2:
+               sb->s_time_gran = 1000;
+               sb->s_time_min = 0;
+               sb->s_time_max = U32_MAX;
+               break;
+       case 3:
+               /*
+                * The VFS shouldn't apply the umask to mode bits.
+                * We will do so ourselves when necessary.
                 */
                sb->s_flags |= SB_POSIXACL;
                sb->s_time_gran = 1;
-               sb->s_export_op = &nfs_export_ops;
-       } else
-               sb->s_time_gran = 1000;
-
-       if (server->nfs_client->rpc_ops->version != 4) {
                sb->s_time_min = 0;
                sb->s_time_max = U32_MAX;
-       } else {
+               sb->s_export_op = &nfs_export_ops;
+               break;
+       case 4:
+               sb->s_flags |= SB_POSIXACL;
+               sb->s_time_gran = 1;
                sb->s_time_min = S64_MIN;
                sb->s_time_max = S64_MAX;
+               if (server->caps & NFS_CAP_ATOMIC_OPEN_V1)
+                       sb->s_export_op = &nfs_export_ops;
+               break;
        }
 
        sb->s_magic = NFS_SUPER_MAGIC;
index 1843fa2..f41d24b 100644 (file)
@@ -1496,31 +1496,6 @@ void nfs_commit_prepare(struct rpc_task *task, void *calldata)
        NFS_PROTO(data->inode)->commit_rpc_prepare(task, data);
 }
 
-/*
- * Special version of should_remove_suid() that ignores capabilities.
- */
-static int nfs_should_remove_suid(const struct inode *inode)
-{
-       umode_t mode = inode->i_mode;
-       int kill = 0;
-
-       /* suid always must be killed */
-       if (unlikely(mode & S_ISUID))
-               kill = ATTR_KILL_SUID;
-
-       /*
-        * sgid without any exec bits is just a mandatory locking mark; leave
-        * it alone.  If some exec bits are set, it's a real sgid; kill it.
-        */
-       if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
-               kill |= ATTR_KILL_SGID;
-
-       if (unlikely(kill && S_ISREG(mode)))
-               return kill;
-
-       return 0;
-}
-
 static void nfs_writeback_check_extend(struct nfs_pgio_header *hdr,
                struct nfs_fattr *fattr)
 {
index 9f486b7..fc17b0a 100644 (file)
@@ -300,6 +300,10 @@ commit_metadata(struct svc_fh *fhp)
 static void
 nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap)
 {
+       /* Ignore mode updates on symlinks */
+       if (S_ISLNK(inode->i_mode))
+               iap->ia_valid &= ~ATTR_MODE;
+
        /* sanitize the mode change */
        if (iap->ia_valid & ATTR_MODE) {
                iap->ia_mode &= S_IALLUGO;
@@ -353,7 +357,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
        int             accmode = NFSD_MAY_SATTR;
        umode_t         ftype = 0;
        __be32          err;
-       int             host_err;
+       int             host_err = 0;
        bool            get_write_count;
        bool            size_change = (iap->ia_valid & ATTR_SIZE);
 
@@ -391,13 +395,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
        dentry = fhp->fh_dentry;
        inode = d_inode(dentry);
 
-       /* Ignore any mode updates on symlinks */
-       if (S_ISLNK(inode->i_mode))
-               iap->ia_valid &= ~ATTR_MODE;
-
-       if (!iap->ia_valid)
-               return 0;
-
        nfsd_sanitize_attrs(inode, iap);
 
        if (check_guard && guardtime != inode->i_ctime.tv_sec)
@@ -448,8 +445,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
                        goto out_unlock;
        }
 
-       iap->ia_valid |= ATTR_CTIME;
-       host_err = notify_change(&init_user_ns, dentry, iap, NULL);
+       if (iap->ia_valid) {
+               iap->ia_valid |= ATTR_CTIME;
+               host_err = notify_change(&init_user_ns, dentry, iap, NULL);
+       }
 
 out_unlock:
        if (attr->na_seclabel && attr->na_seclabel->len)
@@ -846,10 +845,14 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
                  struct splice_desc *sd)
 {
        struct svc_rqst *rqstp = sd->u.data;
-
-       svc_rqst_replace_page(rqstp, buf->page);
-       if (rqstp->rq_res.page_len == 0)
-               rqstp->rq_res.page_base = buf->offset;
+       struct page *page = buf->page;  // may be a compound one
+       unsigned offset = buf->offset;
+
+       page += offset / PAGE_SIZE;
+       for (int i = sd->len; i > 0; i -= PAGE_SIZE)
+               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;
        return sd->len;
 }
index 5ae8de0..001f4e0 100644 (file)
@@ -2092,7 +2092,8 @@ get_ctx_vol_failed:
        // TODO: Initialize security.
        /* Get the extended system files' directory inode. */
        vol->extend_ino = ntfs_iget(sb, FILE_Extend);
-       if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino)) {
+       if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino) ||
+           !S_ISDIR(vol->extend_ino->i_mode)) {
                if (!IS_ERR(vol->extend_ino))
                        iput(vol->extend_ino);
                ntfs_error(sb, "Failed to load $Extend.");
index 8a813fa..cf7e5c3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -716,6 +716,8 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
        fs_userns = i_user_ns(inode);
 
 retry_deleg:
+       newattrs.ia_vfsuid = INVALID_VFSUID;
+       newattrs.ia_vfsgid = INVALID_VFSGID;
        newattrs.ia_valid =  ATTR_CTIME;
        if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
                return -EINVAL;
index b2fd3c2..0c034ea 100644 (file)
 #include <linux/crypto.h>
 #include <linux/string.h>
 #include <linux/timer.h>
-#include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/jiffies.h>
 #include <linux/workqueue.h>
 
-#include <crypto/acompress.h>
-
 #include "internal.h"
 
 /*
@@ -93,8 +90,7 @@ module_param(compress, charp, 0444);
 MODULE_PARM_DESC(compress, "compression to use");
 
 /* Compression parameters */
-static struct crypto_acomp *tfm;
-static struct acomp_req *creq;
+static struct crypto_comp *tfm;
 
 struct pstore_zbackend {
        int (*zbufsize)(size_t size);
@@ -272,21 +268,12 @@ static const struct pstore_zbackend zbackends[] = {
 static int pstore_compress(const void *in, void *out,
                           unsigned int inlen, unsigned int outlen)
 {
-       struct scatterlist src, dst;
        int ret;
 
        if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS))
                return -EINVAL;
 
-       sg_init_table(&src, 1);
-       sg_set_buf(&src, in, inlen);
-
-       sg_init_table(&dst, 1);
-       sg_set_buf(&dst, out, outlen);
-
-       acomp_request_set_params(creq, &src, &dst, inlen, outlen);
-
-       ret = crypto_acomp_compress(creq);
+       ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
        if (ret) {
                pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
                return ret;
@@ -297,7 +284,7 @@ static int pstore_compress(const void *in, void *out,
 
 static void allocate_buf_for_compression(void)
 {
-       struct crypto_acomp *acomp;
+       struct crypto_comp *ctx;
        int size;
        char *buf;
 
@@ -309,7 +296,7 @@ static void allocate_buf_for_compression(void)
        if (!psinfo || tfm)
                return;
 
-       if (!crypto_has_acomp(zbackend->name, 0, CRYPTO_ALG_ASYNC)) {
+       if (!crypto_has_comp(zbackend->name, 0, 0)) {
                pr_err("Unknown compression: %s\n", zbackend->name);
                return;
        }
@@ -328,24 +315,16 @@ static void allocate_buf_for_compression(void)
                return;
        }
 
-       acomp = crypto_alloc_acomp(zbackend->name, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR_OR_NULL(acomp)) {
+       ctx = crypto_alloc_comp(zbackend->name, 0, 0);
+       if (IS_ERR_OR_NULL(ctx)) {
                kfree(buf);
                pr_err("crypto_alloc_comp('%s') failed: %ld\n", zbackend->name,
-                      PTR_ERR(acomp));
-               return;
-       }
-
-       creq = acomp_request_alloc(acomp);
-       if (!creq) {
-               crypto_free_acomp(acomp);
-               kfree(buf);
-               pr_err("acomp_request_alloc('%s') failed\n", zbackend->name);
+                      PTR_ERR(ctx));
                return;
        }
 
        /* A non-NULL big_oops_buf indicates compression is available. */
-       tfm = acomp;
+       tfm = ctx;
        big_oops_buf_sz = size;
        big_oops_buf = buf;
 
@@ -355,8 +334,7 @@ static void allocate_buf_for_compression(void)
 static void free_buf_for_compression(void)
 {
        if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) {
-               acomp_request_free(creq);
-               crypto_free_acomp(tfm);
+               crypto_free_comp(tfm);
                tfm = NULL;
        }
        kfree(big_oops_buf);
@@ -693,8 +671,6 @@ static void decompress_record(struct pstore_record *record)
        int ret;
        int unzipped_len;
        char *unzipped, *workspace;
-       struct acomp_req *dreq;
-       struct scatterlist src, dst;
 
        if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed)
                return;
@@ -718,30 +694,16 @@ static void decompress_record(struct pstore_record *record)
        if (!workspace)
                return;
 
-       dreq = acomp_request_alloc(tfm);
-       if (!dreq) {
-               kfree(workspace);
-               return;
-       }
-
-       sg_init_table(&src, 1);
-       sg_set_buf(&src, record->buf, record->size);
-
-       sg_init_table(&dst, 1);
-       sg_set_buf(&dst, workspace, unzipped_len);
-
-       acomp_request_set_params(dreq, &src, &dst, record->size, unzipped_len);
-
        /* After decompression "unzipped_len" is almost certainly smaller. */
-       ret = crypto_acomp_decompress(dreq);
+       ret = crypto_comp_decompress(tfm, record->buf, record->size,
+                                         workspace, &unzipped_len);
        if (ret) {
-               pr_err("crypto_acomp_decompress failed, ret = %d!\n", ret);
+               pr_err("crypto_comp_decompress failed, ret = %d!\n", ret);
                kfree(workspace);
                return;
        }
 
        /* Append ECC notice to decompressed buffer. */
-       unzipped_len = dreq->dlen;
        memcpy(workspace + unzipped_len, record->buf + record->size,
               record->ecc_notice_size);
 
@@ -749,7 +711,6 @@ static void decompress_record(struct pstore_record *record)
        unzipped = kmemdup(workspace, unzipped_len + record->ecc_notice_size,
                           GFP_KERNEL);
        kfree(workspace);
-       acomp_request_free(dreq);
        if (!unzipped)
                return;
 
index 1a261dc..328ce8c 100644 (file)
@@ -496,14 +496,9 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t
 }
 
 /* caller is responsible for file_start_write/file_end_write */
-ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
+ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos)
 {
-       struct kvec iov = {
-               .iov_base       = (void *)buf,
-               .iov_len        = min_t(size_t, count, MAX_RW_COUNT),
-       };
        struct kiocb kiocb;
-       struct iov_iter iter;
        ssize_t ret;
 
        if (WARN_ON_ONCE(!(file->f_mode & FMODE_WRITE)))
@@ -519,8 +514,7 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
 
        init_sync_kiocb(&kiocb, file);
        kiocb.ki_pos = pos ? *pos : 0;
-       iov_iter_kvec(&iter, WRITE, &iov, 1, iov.iov_len);
-       ret = file->f_op->write_iter(&kiocb, &iter);
+       ret = file->f_op->write_iter(&kiocb, from);
        if (ret > 0) {
                if (pos)
                        *pos = kiocb.ki_pos;
@@ -530,6 +524,18 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
        inc_syscw(current);
        return ret;
 }
+
+/* caller is responsible for file_start_write/file_end_write */
+ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
+{
+       struct kvec iov = {
+               .iov_base       = (void *)buf,
+               .iov_len        = min_t(size_t, count, MAX_RW_COUNT),
+       };
+       struct iov_iter iter;
+       iov_iter_kvec(&iter, WRITE, &iov, 1, iov.iov_len);
+       return __kernel_write_iter(file, &iter, pos);
+}
 /*
  * This "EXPORT_SYMBOL_GPL()" is more of a "EXPORT_SYMBOL_DONTUSE()",
  * but autofs is one of the few internal kernel users that actually
index 81d26ab..da85b39 100644 (file)
@@ -141,6 +141,8 @@ struct tracefs_mount_opts {
        kuid_t uid;
        kgid_t gid;
        umode_t mode;
+       /* Opt_* bitfield. */
+       unsigned int opts;
 };
 
 enum {
@@ -241,6 +243,7 @@ static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts)
        kgid_t gid;
        char *p;
 
+       opts->opts = 0;
        opts->mode = TRACEFS_DEFAULT_MODE;
 
        while ((p = strsep(&data, ",")) != NULL) {
@@ -275,24 +278,36 @@ static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts)
                 * but traditionally tracefs has ignored all mount options
                 */
                }
+
+               opts->opts |= BIT(token);
        }
 
        return 0;
 }
 
-static int tracefs_apply_options(struct super_block *sb)
+static int tracefs_apply_options(struct super_block *sb, bool remount)
 {
        struct tracefs_fs_info *fsi = sb->s_fs_info;
        struct inode *inode = d_inode(sb->s_root);
        struct tracefs_mount_opts *opts = &fsi->mount_opts;
 
-       inode->i_mode &= ~S_IALLUGO;
-       inode->i_mode |= opts->mode;
+       /*
+        * On remount, only reset mode/uid/gid if they were provided as mount
+        * options.
+        */
+
+       if (!remount || opts->opts & BIT(Opt_mode)) {
+               inode->i_mode &= ~S_IALLUGO;
+               inode->i_mode |= opts->mode;
+       }
 
-       inode->i_uid = opts->uid;
+       if (!remount || opts->opts & BIT(Opt_uid))
+               inode->i_uid = opts->uid;
 
-       /* Set all the group ids to the mount option */
-       set_gid(sb->s_root, opts->gid);
+       if (!remount || opts->opts & BIT(Opt_gid)) {
+               /* Set all the group ids to the mount option */
+               set_gid(sb->s_root, opts->gid);
+       }
 
        return 0;
 }
@@ -307,7 +322,7 @@ static int tracefs_remount(struct super_block *sb, int *flags, char *data)
        if (err)
                goto fail;
 
-       tracefs_apply_options(sb);
+       tracefs_apply_options(sb, true);
 
 fail:
        return err;
@@ -359,7 +374,7 @@ static int trace_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_op = &tracefs_super_operations;
 
-       tracefs_apply_options(sb);
+       tracefs_apply_options(sb, false);
 
        return 0;
 
index 69d9c83..5b1f9a2 100644 (file)
@@ -175,13 +175,13 @@ xfs_dax_notify_failure(
        u64                     ddev_start;
        u64                     ddev_end;
 
-       if (!(mp->m_sb.sb_flags & SB_BORN)) {
+       if (!(mp->m_super->s_flags & SB_BORN)) {
                xfs_warn(mp, "filesystem is not ready for notify_failure()!");
                return -EIO;
        }
 
        if (mp->m_rtdev_targp && mp->m_rtdev_targp->bt_daxdev == dax_dev) {
-               xfs_warn(mp,
+               xfs_debug(mp,
                         "notify_failure() not supported on realtime device!");
                return -EOPNOTSUPP;
        }
@@ -194,7 +194,7 @@ xfs_dax_notify_failure(
        }
 
        if (!xfs_has_rmapbt(mp)) {
-               xfs_warn(mp, "notify_failure() needs rmapbt enabled!");
+               xfs_debug(mp, "notify_failure() needs rmapbt enabled!");
                return -EOPNOTSUPP;
        }
 
index e7d2737..c09d729 100644 (file)
@@ -365,7 +365,6 @@ struct acpi_device {
        int device_type;
        acpi_handle handle;             /* no handle for fixed hardware */
        struct fwnode_handle fwnode;
-       struct acpi_device *parent;
        struct list_head wakeup_list;
        struct list_head del_list;
        struct acpi_device_status status;
@@ -458,6 +457,14 @@ static inline void *acpi_driver_data(struct acpi_device *d)
 #define to_acpi_device(d)      container_of(d, struct acpi_device, dev)
 #define to_acpi_driver(d)      container_of(d, struct acpi_driver, drv)
 
+static inline struct acpi_device *acpi_dev_parent(struct acpi_device *adev)
+{
+       if (adev->dev.parent)
+               return to_acpi_device(adev->dev.parent);
+
+       return NULL;
+}
+
 static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)
 {
        *((u32 *)&adev->status) = sta;
@@ -512,7 +519,6 @@ extern int unregister_acpi_notifier(struct notifier_block *);
  * External Functions
  */
 
-struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
                                       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
@@ -613,8 +619,7 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
 int acpi_iommu_fwspec_init(struct device *dev, u32 id,
                           struct fwnode_handle *fwnode,
                           const struct iommu_ops *ops);
-int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
-                      u64 *size);
+int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map);
 int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
                           const u32 *input_id);
 static inline int acpi_dma_configure(struct device *dev,
@@ -733,10 +738,24 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
 }
 
 bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
+int acpi_dev_uid_to_integer(struct acpi_device *adev, u64 *integer);
 
 void acpi_dev_clear_dependencies(struct acpi_device *supplier);
 bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
-struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier);
+struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
+                                                  struct acpi_device *start);
+
+/**
+ * for_each_acpi_consumer_dev - iterate over the consumer ACPI devices for a
+ *                             given supplier
+ * @supplier: Pointer to the supplier's ACPI device
+ * @consumer: Pointer to &struct acpi_device to hold the consumer, initially NULL
+ */
+#define for_each_acpi_consumer_dev(supplier, consumer)                 \
+       for (consumer = acpi_dev_get_next_consumer_dev(supplier, NULL); \
+            consumer;                                                  \
+            consumer = acpi_dev_get_next_consumer_dev(supplier, consumer))
+
 struct acpi_device *
 acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
 struct acpi_device *
@@ -767,9 +786,10 @@ static inline void acpi_dev_put(struct acpi_device *adev)
                put_device(&adev->dev);
 }
 
-struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);
+struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle);
+struct acpi_device *acpi_get_acpi_dev(acpi_handle handle);
 
-static inline void acpi_bus_put_acpi_device(struct acpi_device *adev)
+static inline void acpi_put_acpi_dev(struct acpi_device *adev)
 {
        acpi_dev_put(adev);
 }
index f73d357..c561444 100644 (file)
@@ -140,6 +140,7 @@ extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
 extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
 extern int cppc_set_enable(int cpu, bool enable);
 extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
+extern bool cppc_perf_ctrs_in_pcc(void);
 extern bool acpi_cpc_valid(void);
 extern bool cppc_allow_fast_switch(void);
 extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data);
@@ -173,6 +174,10 @@ static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
 {
        return -ENOTSUPP;
 }
+static inline bool cppc_perf_ctrs_in_pcc(void)
+{
+       return false;
+}
 static inline bool acpi_cpc_valid(void)
 {
        return false;
index d3e2d81..2a67aed 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef __ASM_GENERIC_SOFTIRQ_STACK_H
 #define __ASM_GENERIC_SOFTIRQ_STACK_H
 
-#if defined(CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK) && !defined(CONFIG_PREEMPT_RT)
+#ifdef CONFIG_SOFTIRQ_ON_OWN_STACK
 void do_softirq_own_stack(void);
 #else
 static inline void do_softirq_own_stack(void)
index 7515a46..7c90b1a 100644 (file)
  */
 #ifdef CONFIG_CFI_CLANG
 #define TEXT_CFI_JT                                                    \
-               . = ALIGN(PMD_SIZE);                                    \
+               ALIGN_FUNCTION();                                       \
                __cfi_jt_start = .;                                     \
                *(.text..L.cfi.jumptable .text..L.cfi.jumptable.*)      \
-               . = ALIGN(PMD_SIZE);                                    \
                __cfi_jt_end = .;
 #else
 #define TEXT_CFI_JT
index a1705d6..7df7876 100644 (file)
@@ -319,8 +319,8 @@ enum drm_panel_orientation {
  *             EDID's detailed monitor range
  */
 struct drm_monitor_range_info {
-       u8 min_vfreq;
-       u8 max_vfreq;
+       u16 min_vfreq;
+       u16 max_vfreq;
 };
 
 /**
index 2181977..1ed61e2 100644 (file)
@@ -92,6 +92,11 @@ struct detailed_data_string {
        u8 str[13];
 } __attribute__((packed));
 
+#define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) /* 1.4 */
+#define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) /* 1.4 */
+#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) /* 1.4 */
+#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) /* 1.4 */
+
 #define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG   0x00
 #define DRM_EDID_RANGE_LIMITS_ONLY_FLAG     0x01
 #define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02
index c958855..840a2c3 100644 (file)
@@ -826,7 +826,7 @@ do {                                                                               \
 
 #define KUNIT_EXPECT_LE_MSG(test, left, right, fmt, ...)                      \
        KUNIT_BINARY_INT_ASSERTION(test,                                       \
-                                  KUNIT_ASSERTION,                            \
+                                  KUNIT_EXPECTATION,                          \
                                   left, <=, right,                            \
                                   fmt,                                        \
                                    ##__VA_ARGS__)
@@ -1116,7 +1116,7 @@ do {                                                                             \
 
 #define KUNIT_ASSERT_LT_MSG(test, left, right, fmt, ...)                      \
        KUNIT_BINARY_INT_ASSERTION(test,                                       \
-                                  KUNIT_EXPECTATION,                          \
+                                  KUNIT_ASSERTION,                            \
                                   left, <, right,                             \
                                   fmt,                                        \
                                    ##__VA_ARGS__)
@@ -1157,7 +1157,7 @@ do {                                                                             \
 
 #define KUNIT_ASSERT_GT_MSG(test, left, right, fmt, ...)                      \
        KUNIT_BINARY_INT_ASSERTION(test,                                       \
-                                  KUNIT_EXPECTATION,                          \
+                                  KUNIT_ASSERTION,                            \
                                   left, >, right,                             \
                                   fmt,                                        \
                                    ##__VA_ARGS__)
index 6f64b2f..2f9193b 100644 (file)
@@ -279,14 +279,17 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { }
 
 void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
 
+#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
+void acpi_arch_dma_setup(struct device *dev);
+#else
+static inline void acpi_arch_dma_setup(struct device *dev) { }
+#endif
+
 #ifdef CONFIG_ARM64
 void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
-void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size);
 #else
 static inline void
 acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
-static inline void
-acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) { }
 #endif
 
 int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
@@ -506,6 +509,7 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
                           void *preproc_data);
 int acpi_dev_get_dma_resources(struct acpi_device *adev,
                               struct list_head *list);
+int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list);
 int acpi_dev_filter_resource_type(struct acpi_resource *ares,
                                  unsigned long types);
 
@@ -798,6 +802,11 @@ acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *u
        return false;
 }
 
+static inline int acpi_dev_uid_to_integer(struct acpi_device *adev, u64 *integer)
+{
+       return -ENODEV;
+}
+
 static inline struct acpi_device *
 acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
 {
@@ -977,8 +986,7 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
        return DEV_DMA_NOT_SUPPORTED;
 }
 
-static inline int acpi_dma_get_range(struct device *dev, u64 *dma_addr,
-                                    u64 *offset, u64 *size)
+static inline int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
 {
        return -ENODEV;
 }
index e94cdf2..5001e14 100644 (file)
@@ -67,6 +67,7 @@ struct amba_device {
        struct clk              *pclk;
        struct device_dma_parameters dma_parms;
        unsigned int            periphid;
+       struct mutex            periphid_lock;
        unsigned int            cid;
        struct amba_cs_uci_id   uci;
        unsigned int            irq[AMBA_NR_IRQS];
index 089c9ad..df518c4 100644 (file)
@@ -138,6 +138,17 @@ BUFFER_FNS(Defer_Completion, defer_completion)
 static __always_inline void set_buffer_uptodate(struct buffer_head *bh)
 {
        /*
+        * If somebody else already set this uptodate, they will
+        * have done the memory barrier, and a reader will thus
+        * see *some* valid buffer state.
+        *
+        * Any other serialization (with IO errors or whatever that
+        * might clear the bit) has to come from other state (eg BH_Lock).
+        */
+       if (test_bit(BH_Uptodate, &bh->b_state))
+               return;
+
+       /*
         * make it consistent with folio_mark_uptodate
         * pairs with smp_load_acquire in buffer_uptodate
         */
index 01ce94b..7713d7b 100644 (file)
@@ -240,6 +240,12 @@ static inline void *offset_to_ptr(const int *off)
 #define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
 
 /*
+ * Whether 'type' is a signed type or an unsigned type. Supports scalar types,
+ * bool and also pointer types.
+ */
+#define is_signed_type(type) (((type)(-1)) < (__force type)1)
+
+/*
  * This is needed in functions which generate the stack canary, see
  * arch/x86/kernel/smpboot.c::start_secondary() for an example.
  */
index bd04786..e8ad12b 100644 (file)
@@ -1127,9 +1127,10 @@ cpumap_print_list_to_buf(char *buf, const struct cpumask *mask,
  * cover a worst-case of every other cpu being on one of two nodes for a
  * very large NR_CPUS.
  *
- *  Use PAGE_SIZE as a minimum for smaller configurations.
+ *  Use PAGE_SIZE as a minimum for smaller configurations while avoiding
+ *  unsigned comparison to -1.
  */
-#define CPUMAP_FILE_MAX_BYTES  ((((NR_CPUS * 9)/32 - 1) > PAGE_SIZE) \
+#define CPUMAP_FILE_MAX_BYTES  (((NR_CPUS * 9)/32 > PAGE_SIZE) \
                                        ? (NR_CPUS * 9)/32 - 1 : PAGE_SIZE)
 #define CPULIST_FILE_MAX_BYTES  (((NR_CPUS * 7)/2 > PAGE_SIZE) ? (NR_CPUS * 7)/2 : PAGE_SIZE)
 
index c869f1e..f606746 100644 (file)
@@ -91,6 +91,8 @@ struct dentry *debugfs_create_automount(const char *name,
 void debugfs_remove(struct dentry *dentry);
 #define debugfs_remove_recursive debugfs_remove
 
+void debugfs_lookup_and_remove(const char *name, struct dentry *parent);
+
 const struct file_operations *debugfs_real_fops(const struct file *filp);
 
 int debugfs_file_get(struct dentry *dentry);
@@ -225,6 +227,10 @@ static inline void debugfs_remove(struct dentry *dentry)
 static inline void debugfs_remove_recursive(struct dentry *dentry)
 { }
 
+static inline void debugfs_lookup_and_remove(const char *name,
+                                            struct dentry *parent)
+{ }
+
 const struct file_operations *debugfs_real_fops(const struct file *filp);
 
 static inline int debugfs_file_get(struct dentry *dentry)
index 7acaabd..2114d65 100644 (file)
@@ -242,6 +242,7 @@ driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev)
 
 extern int driver_deferred_probe_timeout;
 void driver_deferred_probe_add(struct device *dev);
+int driver_deferred_probe_check_state(struct device *dev);
 void driver_init(void);
 
 /**
index 25a3090..0ee20b7 100644 (file)
@@ -139,7 +139,6 @@ int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
                void *cpu_addr, dma_addr_t dma_addr, size_t size,
                unsigned long attrs);
 bool dma_can_mmap(struct device *dev);
-int dma_supported(struct device *dev, u64 mask);
 bool dma_pci_p2pdma_supported(struct device *dev);
 int dma_set_mask(struct device *dev, u64 mask);
 int dma_set_coherent_mask(struct device *dev, u64 mask);
@@ -248,10 +247,6 @@ static inline bool dma_can_mmap(struct device *dev)
 {
        return false;
 }
-static inline int dma_supported(struct device *dev, u64 mask)
-{
-       return 0;
-}
 static inline bool dma_pci_p2pdma_supported(struct device *dev)
 {
        return false;
index 720874e..36e5dd8 100644 (file)
@@ -258,7 +258,7 @@ struct fscache_cookie *fscache_acquire_cookie(struct fscache_volume *volume,
 
 /**
  * fscache_use_cookie - Request usage of cookie attached to an object
- * @object: Object description
+ * @cookie: The cookie representing the cache object
  * @will_modify: If cache is expected to be modified locally
  *
  * Request usage of the cookie attached to an object.  The caller should tell
@@ -274,7 +274,7 @@ static inline void fscache_use_cookie(struct fscache_cookie *cookie,
 
 /**
  * fscache_unuse_cookie - Cease usage of cookie attached to an object
- * @object: Object description
+ * @cookie: The cookie representing the cache object
  * @aux_data: Updated auxiliary data (or NULL)
  * @object_size: Revised size of the object (or NULL)
  *
index 6f1dee7..9be8704 100644 (file)
@@ -180,7 +180,7 @@ switch (val) {                                              \
 
 #define HP_SDC_CMD_SET_IM      0x40    /* 010xxxxx == set irq mask */
 
-/* The documents provided do not explicitly state that all registers betwee
+/* The documents provided do not explicitly state that all registers between
  * 0x01 and 0x1f inclusive can be read by sending their register index as a 
  * command, but this is implied and appears to be the case.
  */
index 55e6f4a..b6e6d5b 100644 (file)
@@ -310,9 +310,11 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2)
 struct ieee80211_hdr {
        __le16 frame_control;
        __le16 duration_id;
-       u8 addr1[ETH_ALEN];
-       u8 addr2[ETH_ALEN];
-       u8 addr3[ETH_ALEN];
+       struct_group(addrs,
+               u8 addr1[ETH_ALEN];
+               u8 addr2[ETH_ALEN];
+               u8 addr3[ETH_ALEN];
+       );
        __le16 seq_ctrl;
        u8 addr4[ETH_ALEN];
 } __packed __aligned(2);
index 698032e..20765d1 100644 (file)
@@ -1136,8 +1136,8 @@ extern int ata_scsi_slave_config(struct scsi_device *sdev);
 extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
                                       int queue_depth);
-extern int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
-                                   int queue_depth);
+extern int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
+                                 struct scsi_device *sdev, int queue_depth);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
 extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
index 8064481..60fff13 100644 (file)
@@ -407,4 +407,5 @@ LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
 #ifdef CONFIG_IO_URING
 LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
 LSM_HOOK(int, 0, uring_sqpoll, void)
+LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd)
 #endif /* CONFIG_IO_URING */
index 84a0d7e..3aa6030 100644 (file)
  *      Check whether the current task is allowed to spawn a io_uring polling
  *      thread (IORING_SETUP_SQPOLL).
  *
+ * @uring_cmd:
+ *      Check whether the file_operations uring_cmd is allowed to run.
+ *
  */
 union security_list_options {
        #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
index 6257867..567f123 100644 (file)
@@ -1788,42 +1788,6 @@ static inline void count_objcg_event(struct obj_cgroup *objcg,
        rcu_read_unlock();
 }
 
-/**
- * get_mem_cgroup_from_obj - get a memcg associated with passed kernel object.
- * @p: pointer to object from which memcg should be extracted. It can be NULL.
- *
- * Retrieves the memory group into which the memory of the pointed kernel
- * object is accounted. If memcg is found, its reference is taken.
- * If a passed kernel object is uncharged, or if proper memcg cannot be found,
- * as well as if mem_cgroup is disabled, NULL is returned.
- *
- * Return: valid memcg pointer with taken reference or NULL.
- */
-static inline struct mem_cgroup *get_mem_cgroup_from_obj(void *p)
-{
-       struct mem_cgroup *memcg;
-
-       rcu_read_lock();
-       do {
-               memcg = mem_cgroup_from_obj(p);
-       } while (memcg && !css_tryget(&memcg->css));
-       rcu_read_unlock();
-       return memcg;
-}
-
-/**
- * mem_cgroup_or_root - always returns a pointer to a valid memory cgroup.
- * @memcg: pointer to a valid memory cgroup or NULL.
- *
- * If passed argument is not NULL, returns it without any additional checks
- * and changes. Otherwise, root_mem_cgroup is returned.
- *
- * NOTE: root_mem_cgroup can be NULL during early boot.
- */
-static inline struct mem_cgroup *mem_cgroup_or_root(struct mem_cgroup *memcg)
-{
-       return memcg ? memcg : root_mem_cgroup;
-}
 #else
 static inline bool mem_cgroup_kmem_disabled(void)
 {
@@ -1880,15 +1844,6 @@ static inline void count_objcg_event(struct obj_cgroup *objcg,
 {
 }
 
-static inline struct mem_cgroup *get_mem_cgroup_from_obj(void *p)
-{
-       return NULL;
-}
-
-static inline struct mem_cgroup *mem_cgroup_or_root(struct mem_cgroup *memcg)
-{
-       return NULL;
-}
 #endif /* CONFIG_MEMCG_KMEM */
 
 #if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_ZSWAP)
index 1901049..c3b4cc8 100644 (file)
@@ -139,6 +139,11 @@ struct dev_pagemap {
        };
 };
 
+static inline bool pgmap_has_memory_failure(struct dev_pagemap *pgmap)
+{
+       return pgmap->ops && pgmap->ops->memory_failure;
+}
+
 static inline struct vmem_altmap *pgmap_altmap(struct dev_pagemap *pgmap)
 {
        if (pgmap->flags & PGMAP_ALTMAP_VALID)
index 7b7ce60..c32de98 100644 (file)
@@ -1280,16 +1280,17 @@ enum {
        MLX5_TRIGGERED_CMD_COMP = (u64)1 << 32,
 };
 
-static inline bool mlx5_is_roce_init_enabled(struct mlx5_core_dev *dev)
+bool mlx5_is_roce_on(struct mlx5_core_dev *dev);
+
+static inline bool mlx5_get_roce_state(struct mlx5_core_dev *dev)
 {
-       struct devlink *devlink = priv_to_devlink(dev);
-       union devlink_param_value val;
-       int err;
-
-       err = devlink_param_driverinit_value_get(devlink,
-                                                DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
-                                                &val);
-       return err ? MLX5_CAP_GEN(dev, roce) : val.vbool;
+       if (MLX5_CAP_GEN(dev, roce_rw_supported))
+               return MLX5_CAP_GEN(dev, roce);
+
+       /* If RoCE cap is read-only in FW, get RoCE state from devlink
+        * in order to support RoCE enable/disable feature
+        */
+       return mlx5_is_roce_on(dev);
 }
 
 #endif /* MLX5_DRIVER_H */
index 1d7992a..1a803e4 100644 (file)
@@ -101,8 +101,9 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 }
 
 static inline int of_dma_configure_id(struct device *dev,
-                                  struct device_node *np,
-                                  bool force_dma)
+                                     struct device_node *np,
+                                     bool force_dma,
+                                     const u32 *id)
 {
        return 0;
 }
index f1221d1..0eb3b19 100644 (file)
@@ -30,7 +30,6 @@
  * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
  * credit to Christian Biere.
  */
-#define is_signed_type(type)       (((type)(-1)) < (type)1)
 #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
 #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
 #define type_min(T) ((T)((T)-type_max(T)-(T)1))
index 6feade6..15b49e6 100644 (file)
 #define PCI_DEVICE_ID_ICE_1712         0x1712
 #define PCI_DEVICE_ID_VT1724           0x1724
 
+#define PCI_VENDOR_ID_MICROSOFT                0x1414
+#define PCI_DEVICE_ID_HYPERV_VIDEO     0x5353
+
 #define PCI_VENDOR_ID_OXSEMI           0x1415
 #define PCI_DEVICE_ID_OXSEMI_12PCI840  0x8403
 #define PCI_DEVICE_ID_OXSEMI_PCIe840           0xC000
index 126d082..e605a2c 100644 (file)
@@ -27,9 +27,14 @@ struct tps68470_regulator_platform_data {
        const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS];
 };
 
-struct tps68470_clk_platform_data {
+struct tps68470_clk_consumer {
        const char *consumer_dev_name;
        const char *consumer_con_id;
 };
 
+struct tps68470_clk_platform_data {
+       unsigned int n_consumers;
+       struct tps68470_clk_consumer consumers[];
+};
+
 #endif
index 3edfb6d..dd81f51 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef PMC_ATOM_H
 #define PMC_ATOM_H
 
+#include <linux/bits.h>
+
 /* ValleyView Power Control Unit PCI Device ID */
 #define        PCI_DEVICE_ID_VLV_PMC   0x0F1C
 /* CherryTrail Power Control Unit PCI Device ID */
 #define        ACPI_MMIO_REG_LEN       0x100
 
 #define        PM1_CNT                 0x4
-#define        SLEEP_TYPE_MASK         0xFFFFECFF
+#define        SLEEP_TYPE_MASK         GENMASK(12, 10)
 #define        SLEEP_TYPE_S5           0x1C00
-#define        SLEEP_ENABLE            0x2000
+#define        SLEEP_ENABLE            BIT(13)
 
 extern int pmc_atom_read(int offset, u32 *value);
 
index f527f27..08605ce 100644 (file)
@@ -42,7 +42,31 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func);
 void rcu_barrier_tasks(void);
 void rcu_barrier_tasks_rude(void);
 void synchronize_rcu(void);
+
+struct rcu_gp_oldstate;
 unsigned long get_completed_synchronize_rcu(void);
+void get_completed_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp);
+
+// Maximum number of unsigned long values corresponding to
+// not-yet-completed RCU grace periods.
+#define NUM_ACTIVE_RCU_POLL_OLDSTATE 2
+
+/**
+ * same_state_synchronize_rcu - Are two old-state values identical?
+ * @oldstate1: First old-state value.
+ * @oldstate2: Second old-state value.
+ *
+ * The two old-state values must have been obtained from either
+ * get_state_synchronize_rcu(), start_poll_synchronize_rcu(), or
+ * get_completed_synchronize_rcu().  Returns @true if the two values are
+ * identical and @false otherwise.  This allows structures whose lifetimes
+ * are tracked by old-state values to push these values to a list header,
+ * allowing those structures to be slightly smaller.
+ */
+static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned long oldstate2)
+{
+       return oldstate1 == oldstate2;
+}
 
 #ifdef CONFIG_PREEMPT_RCU
 
@@ -496,13 +520,21 @@ do {                                                                            \
  * against NULL.  Although rcu_access_pointer() may also be used in cases
  * where update-side locks prevent the value of the pointer from changing,
  * you should instead use rcu_dereference_protected() for this use case.
+ * Within an RCU read-side critical section, there is little reason to
+ * use rcu_access_pointer().
+ *
+ * It is usually best to test the rcu_access_pointer() return value
+ * directly in order to avoid accidental dereferences being introduced
+ * by later inattentive changes.  In other words, assigning the
+ * rcu_access_pointer() return value to a local variable results in an
+ * accident waiting to happen.
  *
  * It is also permissible to use rcu_access_pointer() when read-side
- * access to the pointer was removed at least one grace period ago, as
- * is the case in the context of the RCU callback that is freeing up
- * the data, or after a synchronize_rcu() returns.  This can be useful
- * when tearing down multi-linked structures after a grace period
- * has elapsed.
+ * access to the pointer was removed at least one grace period ago, as is
+ * the case in the context of the RCU callback that is freeing up the data,
+ * or after a synchronize_rcu() returns.  This can be useful when tearing
+ * down multi-linked structures after a grace period has elapsed.  However,
+ * rcu_dereference_protected() is normally preferred for this use case.
  */
 #define rcu_access_pointer(p) __rcu_access_pointer((p), __UNIQUE_ID(rcu), __rcu)
 
index 62815c0..768196a 100644 (file)
 
 #include <asm/param.h> /* for HZ */
 
+struct rcu_gp_oldstate {
+       unsigned long rgos_norm;
+};
+
+// Maximum number of rcu_gp_oldstate values corresponding to
+// not-yet-completed RCU grace periods.
+#define NUM_ACTIVE_RCU_POLL_FULL_OLDSTATE 2
+
+/*
+ * Are the two oldstate values the same?  See the Tree RCU version for
+ * docbook header.
+ */
+static inline bool same_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp1,
+                                                  struct rcu_gp_oldstate *rgosp2)
+{
+       return rgosp1->rgos_norm == rgosp2->rgos_norm;
+}
+
 unsigned long get_state_synchronize_rcu(void);
+
+static inline void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       rgosp->rgos_norm = get_state_synchronize_rcu();
+}
+
 unsigned long start_poll_synchronize_rcu(void);
+
+static inline void start_poll_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       rgosp->rgos_norm = start_poll_synchronize_rcu();
+}
+
 bool poll_state_synchronize_rcu(unsigned long oldstate);
 
+static inline bool poll_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       return poll_state_synchronize_rcu(rgosp->rgos_norm);
+}
+
 static inline void cond_synchronize_rcu(unsigned long oldstate)
 {
        might_sleep();
 }
 
+static inline void cond_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       cond_synchronize_rcu(rgosp->rgos_norm);
+}
+
 static inline unsigned long start_poll_synchronize_rcu_expedited(void)
 {
        return start_poll_synchronize_rcu();
 }
 
+static inline void start_poll_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp)
+{
+       rgosp->rgos_norm = start_poll_synchronize_rcu_expedited();
+}
+
 static inline void cond_synchronize_rcu_expedited(unsigned long oldstate)
 {
        cond_synchronize_rcu(oldstate);
 }
 
+static inline void cond_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp)
+{
+       cond_synchronize_rcu_expedited(rgosp->rgos_norm);
+}
+
 extern void rcu_barrier(void);
 
 static inline void synchronize_rcu_expedited(void)
index 47eaa4c..5efb514 100644 (file)
@@ -40,12 +40,52 @@ bool rcu_eqs_special_set(int cpu);
 void rcu_momentary_dyntick_idle(void);
 void kfree_rcu_scheduler_running(void);
 bool rcu_gp_might_be_stalled(void);
+
+struct rcu_gp_oldstate {
+       unsigned long rgos_norm;
+       unsigned long rgos_exp;
+};
+
+// Maximum number of rcu_gp_oldstate values corresponding to
+// not-yet-completed RCU grace periods.
+#define NUM_ACTIVE_RCU_POLL_FULL_OLDSTATE 4
+
+/**
+ * same_state_synchronize_rcu_full - Are two old-state values identical?
+ * @rgosp1: First old-state value.
+ * @rgosp2: Second old-state value.
+ *
+ * The two old-state values must have been obtained from either
+ * get_state_synchronize_rcu_full(), start_poll_synchronize_rcu_full(),
+ * or get_completed_synchronize_rcu_full().  Returns @true if the two
+ * values are identical and @false otherwise.  This allows structures
+ * whose lifetimes are tracked by old-state values to push these values
+ * to a list header, allowing those structures to be slightly smaller.
+ *
+ * Note that equality is judged on a bitwise basis, so that an
+ * @rcu_gp_oldstate structure with an already-completed state in one field
+ * will compare not-equal to a structure with an already-completed state
+ * in the other field.  After all, the @rcu_gp_oldstate structure is opaque
+ * so how did such a situation come to pass in the first place?
+ */
+static inline bool same_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp1,
+                                                  struct rcu_gp_oldstate *rgosp2)
+{
+       return rgosp1->rgos_norm == rgosp2->rgos_norm && rgosp1->rgos_exp == rgosp2->rgos_exp;
+}
+
 unsigned long start_poll_synchronize_rcu_expedited(void);
+void start_poll_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp);
 void cond_synchronize_rcu_expedited(unsigned long oldstate);
+void cond_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp);
 unsigned long get_state_synchronize_rcu(void);
+void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp);
 unsigned long start_poll_synchronize_rcu(void);
+void start_poll_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp);
 bool poll_state_synchronize_rcu(unsigned long oldstate);
+bool poll_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp);
 void cond_synchronize_rcu(unsigned long oldstate);
+void cond_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp);
 
 bool rcu_is_idle_cpu(int cpu);
 
index bf80adc..b89b4b8 100644 (file)
@@ -41,12 +41,15 @@ struct anon_vma {
        atomic_t refcount;
 
        /*
-        * Count of child anon_vmas and VMAs which points to this anon_vma.
+        * Count of child anon_vmas. Equals to the count of all anon_vmas that
+        * have ->parent pointing to this one, including itself.
         *
         * This counter is used for making decision about reusing anon_vma
         * instead of forking new one. See comments in function anon_vma_clone.
         */
-       unsigned degree;
+       unsigned long num_children;
+       /* Count of VMAs whose ->anon_vma pointer points to this object. */
+       unsigned long num_active_vmas;
 
        struct anon_vma *parent;        /* Parent of this anon_vma */
 
index a193884..4f765bc 100644 (file)
@@ -84,7 +84,7 @@ struct scmi_protocol_handle;
 struct scmi_clk_proto_ops {
        int (*count_get)(const struct scmi_protocol_handle *ph);
 
-       const struct scmi_clock_info *(*info_get)
+       const struct scmi_clock_info __must_check *(*info_get)
                (const struct scmi_protocol_handle *ph, u32 clk_id);
        int (*rate_get)(const struct scmi_protocol_handle *ph, u32 clk_id,
                        u64 *rate);
@@ -466,7 +466,7 @@ enum scmi_sensor_class {
  */
 struct scmi_sensor_proto_ops {
        int (*count_get)(const struct scmi_protocol_handle *ph);
-       const struct scmi_sensor_info *(*info_get)
+       const struct scmi_sensor_info __must_check *(*info_get)
                (const struct scmi_protocol_handle *ph, u32 sensor_id);
        int (*trip_point_config)(const struct scmi_protocol_handle *ph,
                                 u32 sensor_id, u8 trip_id, u64 trip_value);
index 1bc362c..7bd0c49 100644 (file)
@@ -2060,6 +2060,7 @@ static inline int security_perf_event_write(struct perf_event *event)
 #ifdef CONFIG_SECURITY
 extern int security_uring_override_creds(const struct cred *new);
 extern int security_uring_sqpoll(void);
+extern int security_uring_cmd(struct io_uring_cmd *ioucmd);
 #else
 static inline int security_uring_override_creds(const struct cred *new)
 {
@@ -2069,6 +2070,10 @@ static inline int security_uring_sqpoll(void)
 {
        return 0;
 }
+static inline int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       return 0;
+}
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_IO_URING */
 
index aef3145..1eaea9f 100644 (file)
@@ -141,6 +141,14 @@ struct gpio_desc;
  *     Locking: none.
  *     Interrupts: caller dependent.
  *
+ * @start_rx: ``void ()(struct uart_port *port)``
+ *
+ *     Start receiving characters.
+ *
+ *     Locking: @port->lock taken.
+ *     Interrupts: locally disabled.
+ *     This call must not sleep
+ *
  * @stop_rx: ``void ()(struct uart_port *port)``
  *
  *     Stop receiving characters; the @port is in the process of being closed.
@@ -616,6 +624,23 @@ struct uart_state {
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS           256
 
+/**
+ * uart_xmit_advance - Advance xmit buffer and account Tx'ed chars
+ * @up: uart_port structure describing the port
+ * @chars: number of characters sent
+ *
+ * This function advances the tail of circular xmit buffer by the number of
+ * @chars transmitted and handles accounting of transmitted bytes (into
+ * @up's icount.tx).
+ */
+static inline void uart_xmit_advance(struct uart_port *up, unsigned int chars)
+{
+       struct circ_buf *xmit = &up->state->xmit;
+
+       xmit->tail = (xmit->tail + chars) & (UART_XMIT_SIZE - 1);
+       up->icount.tx += chars;
+}
+
 struct module;
 struct tty_driver;
 
index ca8afa3..18e163a 100644 (file)
@@ -2444,6 +2444,27 @@ static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
        skb_shinfo(skb)->nr_frags = i + 1;
 }
 
+/**
+ * skb_fill_page_desc_noacc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * Variant of skb_fill_page_desc() which does not deal with
+ * pfmemalloc, if page is not owned by us.
+ */
+static inline void skb_fill_page_desc_noacc(struct sk_buff *skb, int i,
+                                           struct page *page, int off,
+                                           int size)
+{
+       struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+       __skb_fill_page_desc_noacc(shinfo, i, page, off, size);
+       shinfo->nr_frags = i + 1;
+}
+
 void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
                     int size, unsigned int truesize);
 
index e6c73d5..f089ee1 100644 (file)
@@ -469,6 +469,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
  *     SPI_TRANS_FAIL_NO_START.
  * @queue_empty: signal green light for opportunistically skipping the queue
  *     for spi_sync transfers.
+ * @must_async: disable all fast paths in the core
  *
  * Each SPI controller can communicate with one or more @spi_device
  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
@@ -690,6 +691,7 @@ struct spi_controller {
 
        /* Flag for enabling opportunistic skipping of the queue in spi_sync */
        bool                    queue_empty;
+       bool                    must_async;
 };
 
 static inline void *spi_controller_get_devdata(struct spi_controller *ctlr)
index 6cfaa0a..5aa5e0f 100644 (file)
 
 struct srcu_struct {
        short srcu_lock_nesting[2];     /* srcu_read_lock() nesting depth. */
-       unsigned short srcu_idx;        /* Current reader array element in bit 0x2. */
-       unsigned short srcu_idx_max;    /* Furthest future srcu_idx request. */
        u8 srcu_gp_running;             /* GP workqueue running? */
        u8 srcu_gp_waiting;             /* GP waiting for readers? */
+       unsigned long srcu_idx;         /* Current reader array element in bit 0x2. */
+       unsigned long srcu_idx_max;     /* Furthest future srcu_idx request. */
        struct swait_queue_head srcu_wq;
                                        /* Last srcu_read_unlock() wakes GP. */
        struct rcu_head *srcu_cb_head;  /* Pending callbacks: Head. */
@@ -82,10 +82,12 @@ static inline void srcu_torture_stats_print(struct srcu_struct *ssp,
        int idx;
 
        idx = ((data_race(READ_ONCE(ssp->srcu_idx)) + 1) & 0x2) >> 1;
-       pr_alert("%s%s Tiny SRCU per-CPU(idx=%d): (%hd,%hd)\n",
+       pr_alert("%s%s Tiny SRCU per-CPU(idx=%d): (%hd,%hd) gp: %lu->%lu\n",
                 tt, tf, idx,
                 data_race(READ_ONCE(ssp->srcu_lock_nesting[!idx])),
-                data_race(READ_ONCE(ssp->srcu_lock_nesting[idx])));
+                data_race(READ_ONCE(ssp->srcu_lock_nesting[idx])),
+                data_race(READ_ONCE(ssp->srcu_idx)),
+                data_race(READ_ONCE(ssp->srcu_idx_max)));
 }
 
 #endif
index 70f2921..23a253d 100644 (file)
@@ -75,7 +75,7 @@ extern struct suspend_stats suspend_stats;
 
 static inline void dpm_save_failed_dev(const char *name)
 {
-       strlcpy(suspend_stats.failed_devs[suspend_stats.last_failed_dev],
+       strscpy(suspend_stats.failed_devs[suspend_stats.last_failed_dev],
                name,
                sizeof(suspend_stats.failed_devs[0]));
        suspend_stats.last_failed_dev++;
index b18759a..8401dec 100644 (file)
@@ -814,8 +814,6 @@ extern int trace_add_event_call(struct trace_event_call *call);
 extern int trace_remove_event_call(struct trace_event_call *call);
 extern int trace_event_get_offsets(struct trace_event_call *call);
 
-#define is_signed_type(type)   (((type)(-1)) < (type)1)
-
 int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
 int trace_set_clr_event(const char *system, const char *event, int set);
 int trace_array_set_clr_event(struct trace_array *tr, const char *system,
index 254a265..e96da41 100644 (file)
@@ -70,6 +70,7 @@ struct udp_sock {
         * For encapsulation sockets.
         */
        int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
+       void (*encap_err_rcv)(struct sock *sk, struct sk_buff *skb, unsigned int udp_offset);
        int (*encap_err_lookup)(struct sock *sk, struct sk_buff *skb);
        void (*encap_destroy)(struct sock *sk);
 
index f7a9914..9ff1ad4 100644 (file)
@@ -575,6 +575,7 @@ struct usb3_lpm_parameters {
  * @devaddr: device address, XHCI: assigned by HW, others: same as devnum
  * @can_submit: URBs may be submitted
  * @persist_enabled:  USB_PERSIST enabled for this device
+ * @reset_in_progress: the device is being reset
  * @have_langid: whether string_langid is valid
  * @authorized: policy has said we can use it;
  *     (user space) policy determines if we authorize this device to be
@@ -662,6 +663,7 @@ struct usb_device {
 
        unsigned can_submit:1;
        unsigned persist_enabled:1;
+       unsigned reset_in_progress:1;
        unsigned have_langid:1;
        unsigned authorized:1;
        unsigned authenticated:1;
index cfb916c..8d09c2f 100644 (file)
@@ -73,6 +73,11 @@ enum {
 #define DP_CAP_USB                     BIT(7)
 #define DP_CAP_DFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(15, 8)) >> 8)
 #define DP_CAP_UFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(23, 16)) >> 16)
+/* Get pin assignment taking plug & receptacle into consideration */
+#define DP_CAP_PIN_ASSIGN_UFP_D(_cap_) ((_cap_ & DP_CAP_RECEPTACLE) ? \
+                       DP_CAP_UFP_D_PIN_ASSIGN(_cap_) : DP_CAP_DFP_D_PIN_ASSIGN(_cap_))
+#define DP_CAP_PIN_ASSIGN_DFP_D(_cap_) ((_cap_ & DP_CAP_RECEPTACLE) ? \
+                       DP_CAP_DFP_D_PIN_ASSIGN(_cap_) : DP_CAP_UFP_D_PIN_ASSIGN(_cap_))
 
 /* DisplayPort Status Update VDO bits */
 #define DP_STATUS_CONNECTION(_status_) ((_status_) & 3)
index cee5f83..b69ca69 100644 (file)
@@ -66,8 +66,6 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
 void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
 bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
-bool rxrpc_kernel_get_reply_time(struct socket *, struct rxrpc_call *,
-                                ktime_t *);
 bool rxrpc_kernel_call_is_complete(struct rxrpc_call *);
 void rxrpc_kernel_set_max_life(struct socket *, struct rxrpc_call *,
                               unsigned long);
index 0520e21..9949870 100644 (file)
@@ -124,8 +124,6 @@ struct hci_dev_info {
        __u16 acl_pkts;
        __u16 sco_mtu;
        __u16 sco_pkts;
-       __u16 iso_mtu;
-       __u16 iso_pkts;
 
        struct hci_dev_stats stat;
 };
index be2992e..a016f27 100644 (file)
@@ -15,8 +15,6 @@
 #define PKT_TYPE_LACPDU         cpu_to_be16(ETH_P_SLOW)
 #define AD_TIMER_INTERVAL       100 /*msec*/
 
-#define MULTICAST_LACPDU_ADDR    {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
-
 #define AD_LACP_SLOW 0
 #define AD_LACP_FAST 1
 
index afd606d..e999f85 100644 (file)
@@ -786,6 +786,9 @@ extern struct rtnl_link_ops bond_link_ops;
 /* exported from bond_sysfs_slave.c */
 extern const struct sysfs_ops slave_sysfs_ops;
 
+/* exported from bond_3ad.c */
+extern const u8 lacpdu_mcast_addr[];
+
 static inline netdev_tx_t bond_tx_drop(struct net_device *dev, struct sk_buff *skb)
 {
        dev_core_stats_tx_dropped_inc(dev);
index fae9b40..c1cbcdb 100644 (file)
@@ -3,6 +3,73 @@
 #ifndef _LINUX_DROPREASON_H
 #define _LINUX_DROPREASON_H
 
+#define DEFINE_DROP_REASON(FN, FNe)    \
+       FN(NOT_SPECIFIED)               \
+       FN(NO_SOCKET)                   \
+       FN(PKT_TOO_SMALL)               \
+       FN(TCP_CSUM)                    \
+       FN(SOCKET_FILTER)               \
+       FN(UDP_CSUM)                    \
+       FN(NETFILTER_DROP)              \
+       FN(OTHERHOST)                   \
+       FN(IP_CSUM)                     \
+       FN(IP_INHDR)                    \
+       FN(IP_RPFILTER)                 \
+       FN(UNICAST_IN_L2_MULTICAST)     \
+       FN(XFRM_POLICY)                 \
+       FN(IP_NOPROTO)                  \
+       FN(SOCKET_RCVBUFF)              \
+       FN(PROTO_MEM)                   \
+       FN(TCP_MD5NOTFOUND)             \
+       FN(TCP_MD5UNEXPECTED)           \
+       FN(TCP_MD5FAILURE)              \
+       FN(SOCKET_BACKLOG)              \
+       FN(TCP_FLAGS)                   \
+       FN(TCP_ZEROWINDOW)              \
+       FN(TCP_OLD_DATA)                \
+       FN(TCP_OVERWINDOW)              \
+       FN(TCP_OFOMERGE)                \
+       FN(TCP_RFC7323_PAWS)            \
+       FN(TCP_INVALID_SEQUENCE)        \
+       FN(TCP_RESET)                   \
+       FN(TCP_INVALID_SYN)             \
+       FN(TCP_CLOSE)                   \
+       FN(TCP_FASTOPEN)                \
+       FN(TCP_OLD_ACK)                 \
+       FN(TCP_TOO_OLD_ACK)             \
+       FN(TCP_ACK_UNSENT_DATA)         \
+       FN(TCP_OFO_QUEUE_PRUNE)         \
+       FN(TCP_OFO_DROP)                \
+       FN(IP_OUTNOROUTES)              \
+       FN(BPF_CGROUP_EGRESS)           \
+       FN(IPV6DISABLED)                \
+       FN(NEIGH_CREATEFAIL)            \
+       FN(NEIGH_FAILED)                \
+       FN(NEIGH_QUEUEFULL)             \
+       FN(NEIGH_DEAD)                  \
+       FN(TC_EGRESS)                   \
+       FN(QDISC_DROP)                  \
+       FN(CPU_BACKLOG)                 \
+       FN(XDP)                         \
+       FN(TC_INGRESS)                  \
+       FN(UNHANDLED_PROTO)             \
+       FN(SKB_CSUM)                    \
+       FN(SKB_GSO_SEG)                 \
+       FN(SKB_UCOPY_FAULT)             \
+       FN(DEV_HDR)                     \
+       FN(DEV_READY)                   \
+       FN(FULL_RING)                   \
+       FN(NOMEM)                       \
+       FN(HDR_TRUNC)                   \
+       FN(TAP_FILTER)                  \
+       FN(TAP_TXFILTER)                \
+       FN(ICMP_CSUM)                   \
+       FN(INVALID_PROTO)               \
+       FN(IP_INADDRERRORS)             \
+       FN(IP_INNOROUTES)               \
+       FN(PKT_TOO_BIG)                 \
+       FNe(MAX)
+
 /**
  * enum skb_drop_reason - the reasons of skb drops
  *
index d0d188c..a8994f3 100644 (file)
 #ifndef IEEE802154_NETDEVICE_H
 #define IEEE802154_NETDEVICE_H
 
+#define IEEE802154_REQUIRED_SIZE(struct_type, member) \
+       (offsetof(typeof(struct_type), member) + \
+       sizeof(((typeof(struct_type) *)(NULL))->member))
+
+#define IEEE802154_ADDR_OFFSET \
+       offsetof(typeof(struct sockaddr_ieee802154), addr)
+
+#define IEEE802154_MIN_NAMELEN (IEEE802154_ADDR_OFFSET + \
+       IEEE802154_REQUIRED_SIZE(struct ieee802154_addr_sa, addr_type))
+
+#define IEEE802154_NAMELEN_SHORT (IEEE802154_ADDR_OFFSET + \
+       IEEE802154_REQUIRED_SIZE(struct ieee802154_addr_sa, short_addr))
+
+#define IEEE802154_NAMELEN_LONG (IEEE802154_ADDR_OFFSET + \
+       IEEE802154_REQUIRED_SIZE(struct ieee802154_addr_sa, hwaddr))
+
 #include <net/af_ieee802154.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
@@ -165,6 +181,27 @@ static inline void ieee802154_devaddr_to_raw(void *raw, __le64 addr)
        memcpy(raw, &temp, IEEE802154_ADDR_LEN);
 }
 
+static inline int
+ieee802154_sockaddr_check_size(struct sockaddr_ieee802154 *daddr, int len)
+{
+       struct ieee802154_addr_sa *sa;
+
+       sa = &daddr->addr;
+       if (len < IEEE802154_MIN_NAMELEN)
+               return -EINVAL;
+       switch (sa->addr_type) {
+       case IEEE802154_ADDR_SHORT:
+               if (len < IEEE802154_NAMELEN_SHORT)
+                       return -EINVAL;
+               break;
+       case IEEE802154_ADDR_LONG:
+               if (len < IEEE802154_NAMELEN_LONG)
+                       return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
 static inline void ieee802154_addr_from_sa(struct ieee802154_addr *a,
                                           const struct ieee802154_addr_sa *sa)
 {
index 63fac94..ced80e2 100644 (file)
@@ -246,7 +246,8 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
                                       __be32 daddr, __be32 saddr,
                                       __be32 key, __u8 tos,
                                       struct net *net, int oif,
-                                      __u32 mark, __u32 tun_inner_hash)
+                                      __u32 mark, __u32 tun_inner_hash,
+                                      __u8 flow_flags)
 {
        memset(fl4, 0, sizeof(*fl4));
 
@@ -263,6 +264,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
        fl4->fl4_gre_key = key;
        fl4->flowi4_mark = mark;
        fl4->flowi4_multipath_hash = tun_inner_hash;
+       fl4->flowi4_flags = flow_flags;
 }
 
 int ip_tunnel_init(struct net_device *dev);
index a32be8a..6a2019a 100644 (file)
@@ -53,8 +53,6 @@ struct nf_conntrack_net {
        /* only used when new connection is allocated: */
        atomic_t count;
        unsigned int expect_count;
-       u8 sysctl_auto_assign_helper;
-       bool auto_assign_helper_warned;
 
        /* only used from work queues, configuration plane, and so on: */
        unsigned int users4;
index c396a38..e1290c1 100644 (file)
@@ -101,7 +101,6 @@ struct netns_ct {
        u8                      sysctl_log_invalid; /* Log invalid packets */
        u8                      sysctl_events;
        u8                      sysctl_acct;
-       u8                      sysctl_auto_assign_helper;
        u8                      sysctl_tstamp;
        u8                      sysctl_checksum;
 
index c7320ef..6320a76 100644 (file)
@@ -179,6 +179,8 @@ struct netns_ipv4 {
        unsigned int sysctl_tcp_fastopen_blackhole_timeout;
        atomic_t tfo_active_disable_times;
        unsigned long tfo_active_disable_stamp;
+       u32 tcp_challenge_timestamp;
+       u32 tcp_challenge_count;
 
        int sysctl_udp_wmem_min;
        int sysctl_udp_rmem_min;
index afc7ce7..72394f4 100644 (file)
@@ -67,6 +67,9 @@ static inline int udp_sock_create(struct net *net,
 typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb);
 typedef int (*udp_tunnel_encap_err_lookup_t)(struct sock *sk,
                                             struct sk_buff *skb);
+typedef void (*udp_tunnel_encap_err_rcv_t)(struct sock *sk,
+                                          struct sk_buff *skb,
+                                          unsigned int udp_offset);
 typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk);
 typedef struct sk_buff *(*udp_tunnel_gro_receive_t)(struct sock *sk,
                                                    struct list_head *head,
@@ -80,6 +83,7 @@ struct udp_tunnel_sock_cfg {
        __u8  encap_type;
        udp_tunnel_encap_rcv_t encap_rcv;
        udp_tunnel_encap_err_lookup_t encap_err_lookup;
+       udp_tunnel_encap_err_rcv_t encap_err_rcv;
        udp_tunnel_encap_destroy_t encap_destroy;
        udp_tunnel_gro_receive_t gro_receive;
        udp_tunnel_gro_complete_t gro_complete;
index 3113471..2493bd6 100644 (file)
@@ -309,8 +309,6 @@ struct scsi_target {
        struct list_head        devices;
        struct device           dev;
        struct kref             reap_ref; /* last put renders target invisible */
-       atomic_t                sdev_count;
-       wait_queue_head_t       sdev_wq;
        unsigned int            channel;
        unsigned int            id; /* target id ... replace
                                     * scsi_device.id eventually */
index aa7b749..9b0a028 100644 (file)
@@ -557,6 +557,8 @@ struct Scsi_Host {
        struct scsi_host_template *hostt;
        struct scsi_transport_template *transportt;
 
+       struct kref             tagset_refcnt;
+       struct completion       tagset_freed;
        /* Area to keep a shared tag map */
        struct blk_mq_tag_set   tag_set;
 
@@ -690,9 +692,6 @@ struct Scsi_Host {
        /* ldm bits */
        struct device           shost_gendev, shost_dev;
 
-       atomic_t                target_count;
-       wait_queue_head_t       targets_wq;
-
        /*
         * Points to the transport data (if any) which is allocated
         * separately
index 9e17247..6ce3bd2 100644 (file)
 #define                DDR3PHY_DSGCR_ODTPDD_ODT0       (1 << 20)       /* ODT[0] Power Down Driver */
 
 #define DDR3PHY_ZQ0SR0                         (0x188)         /* ZQ status register 0 */
+#define DDR3PHY_ZQ0SR0_PDO_OFF                 (0)             /* Pull-down output impedance select offset */
+#define DDR3PHY_ZQ0SR0_PUO_OFF                 (5)             /* Pull-up output impedance select offset */
+#define DDR3PHY_ZQ0SR0_PDODT_OFF               (10)            /* Pull-down on-die termination impedance select offset */
+#define DDR3PHY_ZQ0SRO_PUODT_OFF               (15)            /* Pull-up on-die termination impedance select offset */
+
+#define        DDR3PHY_DX0DLLCR                        (0x1CC)         /* DDR3PHY DATX8 DLL Control Register */
+#define        DDR3PHY_DX1DLLCR                        (0x20C)         /* DDR3PHY DATX8 DLL Control Register */
+#define                DDR3PHY_DXDLLCR_DLLDIS          (1 << 31)       /* DLL Disable */
 
 /* UDDRC */
 #define UDDRC_STAT                             (0x04)          /* UDDRC Operating Mode Status Register */
index 65016a7..f160d68 100644 (file)
@@ -27,9 +27,9 @@ TRACE_EVENT(scmi_fc_call,
                __entry->val2 = val2;
        ),
 
-       TP_printk("[0x%02X]:[0x%02X]:[%08X]:%u:%u",
-                 __entry->protocol_id, __entry->msg_id,
-                 __entry->res_id, __entry->val1, __entry->val2)
+       TP_printk("pt=%02X msg_id=%02X res_id:%u vals=%u:%u",
+               __entry->protocol_id, __entry->msg_id,
+               __entry->res_id, __entry->val1, __entry->val2)
 );
 
 TRACE_EVENT(scmi_xfer_begin,
@@ -53,9 +53,9 @@ TRACE_EVENT(scmi_xfer_begin,
                __entry->poll = poll;
        ),
 
-       TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u poll=%u",
-               __entry->transfer_id, __entry->msg_id, __entry->protocol_id,
-               __entry->seq, __entry->poll)
+       TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X poll=%u",
+               __entry->protocol_id, __entry->msg_id, __entry->seq,
+               __entry->transfer_id, __entry->poll)
 );
 
 TRACE_EVENT(scmi_xfer_response_wait,
@@ -81,9 +81,9 @@ TRACE_EVENT(scmi_xfer_response_wait,
                __entry->poll = poll;
        ),
 
-       TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u tmo_ms=%u poll=%u",
-               __entry->transfer_id, __entry->msg_id, __entry->protocol_id,
-               __entry->seq, __entry->timeout, __entry->poll)
+       TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X tmo_ms=%u poll=%u",
+               __entry->protocol_id, __entry->msg_id, __entry->seq,
+               __entry->transfer_id, __entry->timeout, __entry->poll)
 );
 
 TRACE_EVENT(scmi_xfer_end,
@@ -107,9 +107,9 @@ TRACE_EVENT(scmi_xfer_end,
                __entry->status = status;
        ),
 
-       TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u status=%d",
-               __entry->transfer_id, __entry->msg_id, __entry->protocol_id,
-               __entry->seq, __entry->status)
+       TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X s=%d",
+               __entry->protocol_id, __entry->msg_id, __entry->seq,
+               __entry->transfer_id, __entry->status)
 );
 
 TRACE_EVENT(scmi_rx_done,
@@ -133,9 +133,9 @@ TRACE_EVENT(scmi_rx_done,
                __entry->msg_type = msg_type;
        ),
 
-       TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u msg_type=%u",
-               __entry->transfer_id, __entry->msg_id, __entry->protocol_id,
-               __entry->seq, __entry->msg_type)
+       TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X msg_type=%u",
+               __entry->protocol_id, __entry->msg_id, __entry->seq,
+               __entry->transfer_id, __entry->msg_type)
 );
 
 TRACE_EVENT(scmi_msg_dump,
index 45264e4..50a974f 100644 (file)
@@ -9,6 +9,15 @@
 #include <linux/netdevice.h>
 #include <linux/tracepoint.h>
 
+#undef FN
+#define FN(reason)     TRACE_DEFINE_ENUM(SKB_DROP_REASON_##reason);
+DEFINE_DROP_REASON(FN, FN)
+
+#undef FN
+#undef FNe
+#define FN(reason)     { SKB_DROP_REASON_##reason, #reason },
+#define FNe(reason)    { SKB_DROP_REASON_##reason, #reason }
+
 /*
  * Tracepoint for free an sk_buff:
  */
@@ -35,9 +44,13 @@ TRACE_EVENT(kfree_skb,
 
        TP_printk("skbaddr=%p protocol=%u location=%p reason: %s",
                  __entry->skbaddr, __entry->protocol, __entry->location,
-                 drop_reasons[__entry->reason])
+                 __print_symbolic(__entry->reason,
+                                  DEFINE_DROP_REASON(FN, FNe)))
 );
 
+#undef FN
+#undef FNe
+
 TRACE_EVENT(consume_skb,
 
        TP_PROTO(struct sk_buff *skb),
index 7bf9ba1..59a217c 100644 (file)
@@ -79,7 +79,7 @@ struct bpf_insn {
 /* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
 struct bpf_lpm_trie_key {
        __u32   prefixlen;      /* up to 32 for AF_INET, 128 for AF_INET6 */
-       __u8    data[]; /* Arbitrary size */
+       __u8    data[0];        /* Arbitrary size */
 };
 
 struct bpf_cgroup_storage_key {
index 2ec07de..b6d7b86 100644 (file)
@@ -67,6 +67,8 @@
 #define IFF_TAP                0x0002
 #define IFF_NAPI       0x0010
 #define IFF_NAPI_FRAGS 0x0020
+/* Used in TUNSETIFF to bring up tun/tap without carrier */
+#define IFF_NO_CARRIER 0x0040
 #define IFF_NO_PI      0x1000
 /* This flag has no real effect */
 #define IFF_ONE_QUEUE  0x2000
index 9e0b5c8..6b83177 100644 (file)
@@ -71,8 +71,8 @@ struct io_uring_sqe {
                __s32   splice_fd_in;
                __u32   file_index;
                struct {
-                       __u16   notification_idx;
                        __u16   addr_len;
+                       __u16   __pad3[1];
                };
        };
        union {
@@ -178,8 +178,7 @@ enum io_uring_op {
        IORING_OP_FALLOCATE,
        IORING_OP_OPENAT,
        IORING_OP_CLOSE,
-       IORING_OP_RSRC_UPDATE,
-       IORING_OP_FILES_UPDATE = IORING_OP_RSRC_UPDATE,
+       IORING_OP_FILES_UPDATE,
        IORING_OP_STATX,
        IORING_OP_READ,
        IORING_OP_WRITE,
@@ -206,7 +205,7 @@ enum io_uring_op {
        IORING_OP_GETXATTR,
        IORING_OP_SOCKET,
        IORING_OP_URING_CMD,
-       IORING_OP_SENDZC_NOTIF,
+       IORING_OP_SEND_ZC,
 
        /* this goes last, obviously */
        IORING_OP_LAST,
@@ -228,7 +227,6 @@ enum io_uring_op {
 #define IORING_TIMEOUT_ETIME_SUCCESS   (1U << 5)
 #define IORING_TIMEOUT_CLOCK_MASK      (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
 #define IORING_TIMEOUT_UPDATE_MASK     (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
-
 /*
  * sqe->splice_flags
  * extends splice(2) flags
@@ -281,29 +279,16 @@ enum io_uring_op {
  *
  * IORING_RECVSEND_FIXED_BUF   Use registered buffers, the index is stored in
  *                             the buf_index field.
- *
- * IORING_RECVSEND_NOTIF_FLUSH Flush a notification after a successful
- *                             successful. Only for zerocopy sends.
  */
 #define IORING_RECVSEND_POLL_FIRST     (1U << 0)
 #define IORING_RECV_MULTISHOT          (1U << 1)
 #define IORING_RECVSEND_FIXED_BUF      (1U << 2)
-#define IORING_RECVSEND_NOTIF_FLUSH    (1U << 3)
 
 /*
  * accept flags stored in sqe->ioprio
  */
 #define IORING_ACCEPT_MULTISHOT        (1U << 0)
 
-
-/*
- * IORING_OP_RSRC_UPDATE flags
- */
-enum {
-       IORING_RSRC_UPDATE_FILES,
-       IORING_RSRC_UPDATE_NOTIF,
-};
-
 /*
  * IORING_OP_MSG_RING command types, stored in sqe->addr
  */
@@ -341,10 +326,13 @@ struct io_uring_cqe {
  * IORING_CQE_F_BUFFER If set, the upper 16 bits are the buffer ID
  * IORING_CQE_F_MORE   If set, parent SQE will generate more CQE entries
  * IORING_CQE_F_SOCK_NONEMPTY  If set, more data to read after socket recv
+ * IORING_CQE_F_NOTIF  Set for notification CQEs. Can be used to distinct
+ *                     them from sends.
  */
 #define IORING_CQE_F_BUFFER            (1U << 0)
 #define IORING_CQE_F_MORE              (1U << 1)
 #define IORING_CQE_F_SOCK_NONEMPTY     (1U << 2)
+#define IORING_CQE_F_NOTIF             (1U << 3)
 
 enum {
        IORING_CQE_BUFFER_SHIFT         = 16,
@@ -485,10 +473,6 @@ enum {
        /* register a range of fixed file slots for automatic slot allocation */
        IORING_REGISTER_FILE_ALLOC_RANGE        = 25,
 
-       /* zerocopy notification API */
-       IORING_REGISTER_NOTIFIERS               = 26,
-       IORING_UNREGISTER_NOTIFIERS             = 27,
-
        /* this goes last */
        IORING_REGISTER_LAST
 };
index 29ced55..6cb842e 100644 (file)
@@ -56,7 +56,7 @@
 #define VIRTIO_NET_F_MQ        22      /* Device supports Receive Flow
                                         * Steering */
 #define VIRTIO_NET_F_CTRL_MAC_ADDR 23  /* Set MAC address */
-#define VIRTIO_NET_F_NOTF_COAL 53      /* Guest can handle notifications coalescing */
+#define VIRTIO_NET_F_NOTF_COAL 53      /* Device supports notifications coalescing */
 #define VIRTIO_NET_F_HASH_REPORT  57   /* Supports hash report */
 #define VIRTIO_NET_F_RSS         60    /* Supports RSS RX steering */
 #define VIRTIO_NET_F_RSC_EXT     61    /* extended coalescing info */
@@ -364,24 +364,24 @@ struct virtio_net_hash_config {
  */
 #define VIRTIO_NET_CTRL_NOTF_COAL              6
 /*
- * Set the tx-usecs/tx-max-packets patameters.
- * tx-usecs - Maximum number of usecs to delay a TX notification.
- * tx-max-packets - Maximum number of packets to send before a TX notification.
+ * Set the tx-usecs/tx-max-packets parameters.
  */
 struct virtio_net_ctrl_coal_tx {
+       /* Maximum number of packets to send before a TX notification */
        __le32 tx_max_packets;
+       /* Maximum number of usecs to delay a TX notification */
        __le32 tx_usecs;
 };
 
 #define VIRTIO_NET_CTRL_NOTF_COAL_TX_SET               0
 
 /*
- * Set the rx-usecs/rx-max-packets patameters.
- * rx-usecs - Maximum number of usecs to delay a RX notification.
- * rx-max-frames - Maximum number of packets to receive before a RX notification.
+ * Set the rx-usecs/rx-max-packets parameters.
  */
 struct virtio_net_ctrl_coal_rx {
+       /* Maximum number of packets to receive before a RX notification */
        __le32 rx_max_packets;
+       /* Maximum number of usecs to delay a RX notification */
        __le32 rx_usecs;
 };
 
index 7761627..242d896 100644 (file)
@@ -1728,6 +1728,7 @@ static void io_queue_async(struct io_kiocb *req, int ret)
 
        switch (io_arm_poll_handler(req, 0)) {
        case IO_APOLL_READY:
+               io_kbuf_recycle(req, 0);
                io_req_task_queue(req);
                break;
        case IO_APOLL_ABORTED:
@@ -2640,7 +2641,6 @@ static __cold void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
                io_unregister_personality(ctx, index);
        if (ctx->rings)
                io_poll_remove_all(ctx, NULL, true);
-       io_notif_unregister(ctx);
        mutex_unlock(&ctx->uring_lock);
 
        /* failed during ring init, it couldn't have issued any requests */
@@ -2648,6 +2648,9 @@ static __cold void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
                io_kill_timeouts(ctx, NULL, true);
                /* if we failed setting up the ctx, we might not have any rings */
                io_iopoll_try_reap_events(ctx);
+               /* drop cached put refs after potentially doing completions */
+               if (current->io_uring)
+                       io_uring_drop_tctx_refs(current);
        }
 
        INIT_WORK(&ctx->exit_work, io_ring_exit_work);
@@ -3354,6 +3357,10 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
                goto err;
        }
 
+       if (ctx->flags & IORING_SETUP_SINGLE_ISSUER
+           && !(ctx->flags & IORING_SETUP_R_DISABLED))
+               ctx->submitter_task = get_task_struct(current);
+
        file = io_uring_get_file(ctx);
        if (IS_ERR(file)) {
                ret = PTR_ERR(file);
@@ -3545,6 +3552,9 @@ static int io_register_enable_rings(struct io_ring_ctx *ctx)
        if (!(ctx->flags & IORING_SETUP_R_DISABLED))
                return -EBADFD;
 
+       if (ctx->flags & IORING_SETUP_SINGLE_ISSUER && !ctx->submitter_task)
+               ctx->submitter_task = get_task_struct(current);
+
        if (ctx->restrictions.registered)
                ctx->restricted = 1;
 
@@ -3839,15 +3849,6 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
                        break;
                ret = io_register_file_alloc_range(ctx, arg);
                break;
-       case IORING_REGISTER_NOTIFIERS:
-               ret = io_notif_register(ctx, arg, nr_args);
-               break;
-       case IORING_UNREGISTER_NOTIFIERS:
-               ret = -EINVAL;
-               if (arg || nr_args)
-                       break;
-               ret = io_notif_unregister(ctx);
-               break;
        default:
                ret = -EINVAL;
                break;
@@ -3933,8 +3934,8 @@ static int __init io_uring_init(void)
        BUILD_BUG_SQE_ELEM(42, __u16,  personality);
        BUILD_BUG_SQE_ELEM(44, __s32,  splice_fd_in);
        BUILD_BUG_SQE_ELEM(44, __u32,  file_index);
-       BUILD_BUG_SQE_ELEM(44, __u16,  notification_idx);
-       BUILD_BUG_SQE_ELEM(46, __u16,  addr_len);
+       BUILD_BUG_SQE_ELEM(44, __u16,  addr_len);
+       BUILD_BUG_SQE_ELEM(46, __u16,  __pad3[0]);
        BUILD_BUG_SQE_ELEM(48, __u64,  addr3);
        BUILD_BUG_SQE_ELEM_SIZE(48, 0, cmd);
        BUILD_BUG_SQE_ELEM(56, __u64,  __pad2);
index d6af208..746fbf3 100644 (file)
@@ -91,9 +91,13 @@ static inline void io_kbuf_recycle(struct io_kiocb *req, unsigned issue_flags)
         * buffer data. However if that buffer is recycled the original request
         * data stored in addr is lost. Therefore forbid recycling for now.
         */
-       if (req->opcode == IORING_OP_READV)
+       if (req->opcode == IORING_OP_READV) {
+               if ((req->flags & REQ_F_BUFFER_RING) && req->buf_list) {
+                       req->buf_list->head++;
+                       req->buf_list = NULL;
+               }
                return;
-
+       }
        if (req->flags & REQ_F_BUFFER_SELECTED)
                io_kbuf_recycle_legacy(req, issue_flags);
        if (req->flags & REQ_F_BUFFER_RING)
index 976c4ba..4a7e5d0 100644 (file)
@@ -165,7 +165,8 @@ done:
                req_set_fail(req);
        io_req_set_res(req, ret, 0);
        /* put file to avoid an attempt to IOPOLL the req */
-       io_put_file(req->file);
+       if (!(req->flags & REQ_F_FIXED_FILE))
+               io_put_file(req->file);
        req->file = NULL;
        return IOU_OK;
 }
index 0af8a02..60e392f 100644 (file)
@@ -65,12 +65,12 @@ struct io_sendzc {
        struct file                     *file;
        void __user                     *buf;
        size_t                          len;
-       u16                             slot_idx;
        unsigned                        msg_flags;
        unsigned                        flags;
        unsigned                        addr_len;
        void __user                     *addr;
        size_t                          done_io;
+       struct io_kiocb                 *notif;
 };
 
 #define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED)
@@ -879,18 +879,39 @@ out_free:
        return ret;
 }
 
+void io_sendzc_cleanup(struct io_kiocb *req)
+{
+       struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
+
+       zc->notif->flags |= REQ_F_CQE_SKIP;
+       io_notif_flush(zc->notif);
+       zc->notif = NULL;
+}
+
 int io_sendzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
        struct io_ring_ctx *ctx = req->ctx;
+       struct io_kiocb *notif;
 
-       if (READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3))
+       if (READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3) ||
+           READ_ONCE(sqe->__pad3[0]))
+               return -EINVAL;
+       /* we don't support IOSQE_CQE_SKIP_SUCCESS just yet */
+       if (req->flags & REQ_F_CQE_SKIP)
                return -EINVAL;
 
        zc->flags = READ_ONCE(sqe->ioprio);
        if (zc->flags & ~(IORING_RECVSEND_POLL_FIRST |
-                         IORING_RECVSEND_FIXED_BUF | IORING_RECVSEND_NOTIF_FLUSH))
+                         IORING_RECVSEND_FIXED_BUF))
                return -EINVAL;
+       notif = zc->notif = io_alloc_notif(ctx);
+       if (!notif)
+               return -ENOMEM;
+       notif->cqe.user_data = req->cqe.user_data;
+       notif->cqe.res = 0;
+       notif->cqe.flags = IORING_CQE_F_NOTIF;
+       req->flags |= REQ_F_NEED_CLEANUP;
        if (zc->flags & IORING_RECVSEND_FIXED_BUF) {
                unsigned idx = READ_ONCE(sqe->buf_index);
 
@@ -898,13 +919,12 @@ int io_sendzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                        return -EFAULT;
                idx = array_index_nospec(idx, ctx->nr_user_bufs);
                req->imu = READ_ONCE(ctx->user_bufs[idx]);
-               io_req_set_rsrc_node(req, ctx, 0);
+               io_req_set_rsrc_node(notif, ctx, 0);
        }
 
        zc->buf = u64_to_user_ptr(READ_ONCE(sqe->addr));
        zc->len = READ_ONCE(sqe->len);
        zc->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
-       zc->slot_idx = READ_ONCE(sqe->notification_idx);
        if (zc->msg_flags & MSG_DONTWAIT)
                req->flags |= REQ_F_NOWAIT;
 
@@ -956,7 +976,7 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
        shinfo->nr_frags = frag;
        from->bvec += bi.bi_idx;
        from->nr_segs -= bi.bi_idx;
-       from->count = bi.bi_size;
+       from->count -= copied;
        from->iov_offset = bi.bi_bvec_done;
 
        skb->data_len += copied;
@@ -976,33 +996,17 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
 int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct sockaddr_storage __address, *addr = NULL;
-       struct io_ring_ctx *ctx = req->ctx;
        struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
-       struct io_notif_slot *notif_slot;
-       struct io_kiocb *notif;
        struct msghdr msg;
        struct iovec iov;
        struct socket *sock;
-       unsigned msg_flags;
+       unsigned msg_flags, cflags;
        int ret, min_ret = 0;
 
-       if (!(req->flags & REQ_F_POLLED) &&
-           (zc->flags & IORING_RECVSEND_POLL_FIRST))
-               return -EAGAIN;
-
-       if (issue_flags & IO_URING_F_UNLOCKED)
-               return -EAGAIN;
        sock = sock_from_file(req->file);
        if (unlikely(!sock))
                return -ENOTSOCK;
 
-       notif_slot = io_get_notif_slot(ctx, zc->slot_idx);
-       if (!notif_slot)
-               return -EINVAL;
-       notif = io_get_notif(ctx, notif_slot);
-       if (!notif)
-               return -ENOMEM;
-
        msg.msg_name = NULL;
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
@@ -1023,6 +1027,10 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                msg.msg_namelen = zc->addr_len;
        }
 
+       if (!(req->flags & REQ_F_POLLED) &&
+           (zc->flags & IORING_RECVSEND_POLL_FIRST))
+               return io_setup_async_addr(req, addr, issue_flags);
+
        if (zc->flags & IORING_RECVSEND_FIXED_BUF) {
                ret = io_import_fixed(WRITE, &msg.msg_iter, req->imu,
                                        (u64)(uintptr_t)zc->buf, zc->len);
@@ -1033,7 +1041,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                                          &msg.msg_iter);
                if (unlikely(ret))
                        return ret;
-               ret = io_notif_account_mem(notif, zc->len);
+               ret = io_notif_account_mem(zc->notif, zc->len);
                if (unlikely(ret))
                        return ret;
        }
@@ -1045,7 +1053,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                min_ret = iov_iter_count(&msg.msg_iter);
 
        msg.msg_flags = msg_flags;
-       msg.msg_ubuf = &io_notif_to_data(notif)->uarg;
+       msg.msg_ubuf = &io_notif_to_data(zc->notif)->uarg;
        msg.sg_from_iter = io_sg_from_iter;
        ret = sock_sendmsg(sock, &msg);
 
@@ -1060,18 +1068,22 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                        req->flags |= REQ_F_PARTIAL_IO;
                        return io_setup_async_addr(req, addr, issue_flags);
                }
+               if (ret < 0 && !zc->done_io)
+                       zc->notif->flags |= REQ_F_CQE_SKIP;
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
                req_set_fail(req);
-       } else if (zc->flags & IORING_RECVSEND_NOTIF_FLUSH) {
-               io_notif_slot_flush_submit(notif_slot, 0);
        }
 
        if (ret >= 0)
                ret += zc->done_io;
        else if (zc->done_io)
                ret = zc->done_io;
-       io_req_set_res(req, ret, 0);
+
+       io_notif_flush(zc->notif);
+       req->flags &= ~REQ_F_NEED_CLEANUP;
+       cflags = ret >= 0 ? IORING_CQE_F_MORE : 0;
+       io_req_set_res(req, ret, cflags);
        return IOU_OK;
 }
 
index f91f56c..d744a0a 100644 (file)
@@ -55,6 +55,7 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags);
 
 int io_sendzc(struct io_kiocb *req, unsigned int issue_flags);
 int io_sendzc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+void io_sendzc_cleanup(struct io_kiocb *req);
 
 void io_netmsg_cache_free(struct io_cache_entry *entry);
 #else
index 96f076b..e37c656 100644 (file)
@@ -21,14 +21,6 @@ static void __io_notif_complete_tw(struct io_kiocb *notif, bool *locked)
        io_req_task_complete(notif, locked);
 }
 
-static inline void io_notif_complete(struct io_kiocb *notif)
-       __must_hold(&notif->ctx->uring_lock)
-{
-       bool locked = true;
-
-       __io_notif_complete_tw(notif, &locked);
-}
-
 static void io_uring_tx_zerocopy_callback(struct sk_buff *skb,
                                          struct ubuf_info *uarg,
                                          bool success)
@@ -42,8 +34,7 @@ static void io_uring_tx_zerocopy_callback(struct sk_buff *skb,
        }
 }
 
-struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx,
-                               struct io_notif_slot *slot)
+struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx)
        __must_hold(&ctx->uring_lock)
 {
        struct io_kiocb *notif;
@@ -59,101 +50,23 @@ struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx,
        io_get_task_refs(1);
        notif->rsrc_node = NULL;
        io_req_set_rsrc_node(notif, ctx, 0);
-       notif->cqe.user_data = slot->tag;
-       notif->cqe.flags = slot->seq++;
-       notif->cqe.res = 0;
 
        nd = io_notif_to_data(notif);
        nd->account_pages = 0;
        nd->uarg.flags = SKBFL_ZEROCOPY_FRAG | SKBFL_DONT_ORPHAN;
        nd->uarg.callback = io_uring_tx_zerocopy_callback;
-       /* master ref owned by io_notif_slot, will be dropped on flush */
        refcount_set(&nd->uarg.refcnt, 1);
        return notif;
 }
 
-void io_notif_slot_flush(struct io_notif_slot *slot)
+void io_notif_flush(struct io_kiocb *notif)
        __must_hold(&slot->notif->ctx->uring_lock)
 {
-       struct io_kiocb *notif = slot->notif;
        struct io_notif_data *nd = io_notif_to_data(notif);
 
-       slot->notif = NULL;
-
        /* drop slot's master ref */
        if (refcount_dec_and_test(&nd->uarg.refcnt)) {
                notif->io_task_work.func = __io_notif_complete_tw;
                io_req_task_work_add(notif);
        }
 }
-
-__cold int io_notif_unregister(struct io_ring_ctx *ctx)
-       __must_hold(&ctx->uring_lock)
-{
-       int i;
-
-       if (!ctx->notif_slots)
-               return -ENXIO;
-
-       for (i = 0; i < ctx->nr_notif_slots; i++) {
-               struct io_notif_slot *slot = &ctx->notif_slots[i];
-               struct io_kiocb *notif = slot->notif;
-               struct io_notif_data *nd;
-
-               if (!notif)
-                       continue;
-               nd = io_notif_to_data(notif);
-               slot->notif = NULL;
-               if (!refcount_dec_and_test(&nd->uarg.refcnt))
-                       continue;
-               notif->io_task_work.func = __io_notif_complete_tw;
-               io_req_task_work_add(notif);
-       }
-
-       kvfree(ctx->notif_slots);
-       ctx->notif_slots = NULL;
-       ctx->nr_notif_slots = 0;
-       return 0;
-}
-
-__cold int io_notif_register(struct io_ring_ctx *ctx,
-                            void __user *arg, unsigned int size)
-       __must_hold(&ctx->uring_lock)
-{
-       struct io_uring_notification_slot __user *slots;
-       struct io_uring_notification_slot slot;
-       struct io_uring_notification_register reg;
-       unsigned i;
-
-       if (ctx->nr_notif_slots)
-               return -EBUSY;
-       if (size != sizeof(reg))
-               return -EINVAL;
-       if (copy_from_user(&reg, arg, sizeof(reg)))
-               return -EFAULT;
-       if (!reg.nr_slots || reg.nr_slots > IORING_MAX_NOTIF_SLOTS)
-               return -EINVAL;
-       if (reg.resv || reg.resv2 || reg.resv3)
-               return -EINVAL;
-
-       slots = u64_to_user_ptr(reg.data);
-       ctx->notif_slots = kvcalloc(reg.nr_slots, sizeof(ctx->notif_slots[0]),
-                               GFP_KERNEL_ACCOUNT);
-       if (!ctx->notif_slots)
-               return -ENOMEM;
-
-       for (i = 0; i < reg.nr_slots; i++, ctx->nr_notif_slots++) {
-               struct io_notif_slot *notif_slot = &ctx->notif_slots[i];
-
-               if (copy_from_user(&slot, &slots[i], sizeof(slot))) {
-                       io_notif_unregister(ctx);
-                       return -EFAULT;
-               }
-               if (slot.resv[0] | slot.resv[1] | slot.resv[2]) {
-                       io_notif_unregister(ctx);
-                       return -EINVAL;
-               }
-               notif_slot->tag = slot.tag;
-       }
-       return 0;
-}
index 80f6445..5b4d710 100644 (file)
@@ -8,7 +8,6 @@
 #include "rsrc.h"
 
 #define IO_NOTIF_SPLICE_BATCH  32
-#define IORING_MAX_NOTIF_SLOTS (1U << 15)
 
 struct io_notif_data {
        struct file             *file;
@@ -16,63 +15,14 @@ struct io_notif_data {
        unsigned long           account_pages;
 };
 
-struct io_notif_slot {
-       /*
-        * Current/active notifier. A slot holds only one active notifier at a
-        * time and keeps one reference to it. Flush releases the reference and
-        * lazily replaces it with a new notifier.
-        */
-       struct io_kiocb         *notif;
-
-       /*
-        * Default ->user_data for this slot notifiers CQEs
-        */
-       u64                     tag;
-       /*
-        * Notifiers of a slot live in generations, we create a new notifier
-        * only after flushing the previous one. Track the sequential number
-        * for all notifiers and copy it into notifiers's cqe->cflags
-        */
-       u32                     seq;
-};
-
-int io_notif_register(struct io_ring_ctx *ctx,
-                     void __user *arg, unsigned int size);
-int io_notif_unregister(struct io_ring_ctx *ctx);
-
-void io_notif_slot_flush(struct io_notif_slot *slot);
-struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx,
-                               struct io_notif_slot *slot);
+void io_notif_flush(struct io_kiocb *notif);
+struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx);
 
 static inline struct io_notif_data *io_notif_to_data(struct io_kiocb *notif)
 {
        return io_kiocb_to_cmd(notif, struct io_notif_data);
 }
 
-static inline struct io_kiocb *io_get_notif(struct io_ring_ctx *ctx,
-                                           struct io_notif_slot *slot)
-{
-       if (!slot->notif)
-               slot->notif = io_alloc_notif(ctx, slot);
-       return slot->notif;
-}
-
-static inline struct io_notif_slot *io_get_notif_slot(struct io_ring_ctx *ctx,
-                                                     unsigned idx)
-       __must_hold(&ctx->uring_lock)
-{
-       if (idx >= ctx->nr_notif_slots)
-               return NULL;
-       idx = array_index_nospec(idx, ctx->nr_notif_slots);
-       return &ctx->notif_slots[idx];
-}
-
-static inline void io_notif_slot_flush_submit(struct io_notif_slot *slot,
-                                             unsigned int issue_flags)
-{
-       io_notif_slot_flush(slot);
-}
-
 static inline int io_notif_account_mem(struct io_kiocb *notif, unsigned len)
 {
        struct io_ring_ctx *ctx = notif->ctx;
index 4141012..c4dddd0 100644 (file)
@@ -246,13 +246,12 @@ const struct io_op_def io_op_defs[] = {
                .prep                   = io_close_prep,
                .issue                  = io_close,
        },
-       [IORING_OP_RSRC_UPDATE] = {
+       [IORING_OP_FILES_UPDATE] = {
                .audit_skip             = 1,
                .iopoll                 = 1,
-               .name                   = "RSRC_UPDATE",
-               .prep                   = io_rsrc_update_prep,
-               .issue                  = io_rsrc_update,
-               .ioprio                 = 1,
+               .name                   = "FILES_UPDATE",
+               .prep                   = io_files_update_prep,
+               .issue                  = io_files_update,
        },
        [IORING_OP_STATX] = {
                .audit_skip             = 1,
@@ -471,8 +470,8 @@ const struct io_op_def io_op_defs[] = {
                .issue                  = io_uring_cmd,
                .prep_async             = io_uring_cmd_prep_async,
        },
-       [IORING_OP_SENDZC_NOTIF] = {
-               .name                   = "SENDZC_NOTIF",
+       [IORING_OP_SEND_ZC] = {
+               .name                   = "SEND_ZC",
                .needs_file             = 1,
                .unbound_nonreg_file    = 1,
                .pollout                = 1,
@@ -484,6 +483,7 @@ const struct io_op_def io_op_defs[] = {
                .prep                   = io_sendzc_prep,
                .issue                  = io_sendzc,
                .prep_async             = io_sendzc_prep_async,
+               .cleanup                = io_sendzc_cleanup,
 #else
                .prep                   = io_eopnotsupp_prep,
 #endif
index d5bad0b..0d9f49c 100644 (file)
@@ -857,7 +857,7 @@ int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (sqe->buf_index || sqe->off || sqe->addr)
                return -EINVAL;
        flags = READ_ONCE(sqe->len);
-       if (flags & ~(IORING_POLL_ADD_MULTI|IORING_POLL_ADD_LEVEL))
+       if (flags & ~IORING_POLL_ADD_MULTI)
                return -EINVAL;
        if ((flags & IORING_POLL_ADD_MULTI) && (req->flags & REQ_F_CQE_SKIP))
                return -EINVAL;
index 71359a4..cf32721 100644 (file)
 #include "io_uring.h"
 #include "openclose.h"
 #include "rsrc.h"
-#include "notif.h"
 
 struct io_rsrc_update {
        struct file                     *file;
        u64                             arg;
        u32                             nr_args;
        u32                             offset;
-       int                             type;
 };
 
 static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
@@ -655,7 +653,7 @@ __cold int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
        return -EINVAL;
 }
 
-int io_rsrc_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_rsrc_update *up = io_kiocb_to_cmd(req, struct io_rsrc_update);
 
@@ -669,7 +667,6 @@ int io_rsrc_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (!up->nr_args)
                return -EINVAL;
        up->arg = READ_ONCE(sqe->addr);
-       up->type = READ_ONCE(sqe->ioprio);
        return 0;
 }
 
@@ -712,7 +709,7 @@ static int io_files_update_with_index_alloc(struct io_kiocb *req,
        return ret;
 }
 
-static int io_files_update(struct io_kiocb *req, unsigned int issue_flags)
+int io_files_update(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_rsrc_update *up = io_kiocb_to_cmd(req, struct io_rsrc_update);
        struct io_ring_ctx *ctx = req->ctx;
@@ -741,54 +738,6 @@ static int io_files_update(struct io_kiocb *req, unsigned int issue_flags)
        return IOU_OK;
 }
 
-static int io_notif_update(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_rsrc_update *up = io_kiocb_to_cmd(req, struct io_rsrc_update);
-       struct io_ring_ctx *ctx = req->ctx;
-       unsigned len = up->nr_args;
-       unsigned idx_end, idx = up->offset;
-       int ret = 0;
-
-       io_ring_submit_lock(ctx, issue_flags);
-       if (unlikely(check_add_overflow(idx, len, &idx_end))) {
-               ret = -EOVERFLOW;
-               goto out;
-       }
-       if (unlikely(idx_end > ctx->nr_notif_slots)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       for (; idx < idx_end; idx++) {
-               struct io_notif_slot *slot = &ctx->notif_slots[idx];
-
-               if (!slot->notif)
-                       continue;
-               if (up->arg)
-                       slot->tag = up->arg;
-               io_notif_slot_flush_submit(slot, issue_flags);
-       }
-out:
-       io_ring_submit_unlock(ctx, issue_flags);
-       if (ret < 0)
-               req_set_fail(req);
-       io_req_set_res(req, ret, 0);
-       return IOU_OK;
-}
-
-int io_rsrc_update(struct io_kiocb *req, unsigned int issue_flags)
-{
-       struct io_rsrc_update *up = io_kiocb_to_cmd(req, struct io_rsrc_update);
-
-       switch (up->type) {
-       case IORING_RSRC_UPDATE_FILES:
-               return io_files_update(req, issue_flags);
-       case IORING_RSRC_UPDATE_NOTIF:
-               return io_notif_update(req, issue_flags);
-       }
-       return -EINVAL;
-}
-
 int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
                          struct io_rsrc_node *node, void *rsrc)
 {
index f3a9a17..9bce156 100644 (file)
@@ -167,8 +167,8 @@ static inline u64 *io_get_tag_slot(struct io_rsrc_data *data, unsigned int idx)
        return &data->tags[table_idx][off];
 }
 
-int io_rsrc_update(struct io_kiocb *req, unsigned int issue_flags);
-int io_rsrc_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
+int io_files_update(struct io_kiocb *req, unsigned int issue_flags);
+int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
 
 int __io_account_mem(struct user_struct *user, unsigned long nr_pages);
 
index 1babd77..76ebcfe 100644 (file)
@@ -206,6 +206,20 @@ static bool __io_complete_rw_common(struct io_kiocb *req, long res)
        return false;
 }
 
+static inline int io_fixup_rw_res(struct io_kiocb *req, long res)
+{
+       struct io_async_rw *io = req->async_data;
+
+       /* add previously done IO, if any */
+       if (req_has_async_data(req) && io->bytes_done > 0) {
+               if (res < 0)
+                       res = io->bytes_done;
+               else
+                       res += io->bytes_done;
+       }
+       return res;
+}
+
 static void io_complete_rw(struct kiocb *kiocb, long res)
 {
        struct io_rw *rw = container_of(kiocb, struct io_rw, kiocb);
@@ -213,7 +227,7 @@ static void io_complete_rw(struct kiocb *kiocb, long res)
 
        if (__io_complete_rw_common(req, res))
                return;
-       io_req_set_res(req, res, 0);
+       io_req_set_res(req, io_fixup_rw_res(req, res), 0);
        req->io_task_work.func = io_req_task_complete;
        io_req_task_work_add(req);
 }
@@ -240,22 +254,14 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res)
 static int kiocb_done(struct io_kiocb *req, ssize_t ret,
                       unsigned int issue_flags)
 {
-       struct io_async_rw *io = req->async_data;
        struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
-
-       /* add previously done IO, if any */
-       if (req_has_async_data(req) && io->bytes_done > 0) {
-               if (ret < 0)
-                       ret = io->bytes_done;
-               else
-                       ret += io->bytes_done;
-       }
+       unsigned final_ret = io_fixup_rw_res(req, ret);
 
        if (req->flags & REQ_F_CUR_POS)
                req->file->f_pos = rw->kiocb.ki_pos;
        if (ret >= 0 && (rw->kiocb.ki_complete == io_complete_rw)) {
                if (!__io_complete_rw_common(req, ret)) {
-                       io_req_set_res(req, req->cqe.res,
+                       io_req_set_res(req, final_ret,
                                       io_put_kbuf(req, issue_flags));
                        return IOU_OK;
                }
@@ -268,7 +274,7 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret,
                if (io_resubmit_prep(req))
                        io_req_task_queue_reissue(req);
                else
-                       io_req_task_queue_fail(req, ret);
+                       io_req_task_queue_fail(req, final_ret);
        }
        return IOU_ISSUE_SKIP_COMPLETE;
 }
index b9989ae..e78b6f9 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/io_uring.h>
+#include <linux/security.h>
 
 #include <uapi/linux/io_uring.h>
 
@@ -88,6 +89,10 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
        if (!req->file->f_op->uring_cmd)
                return -EOPNOTSUPP;
 
+       ret = security_uring_cmd(ioucmd);
+       if (ret)
+               return ret;
+
        if (ctx->flags & IORING_SETUP_SQE128)
                issue_flags |= IO_URING_F_SQE128;
        if (ctx->flags & IORING_SETUP_CQE32)
index 59b7eb6..4a400cd 100644 (file)
@@ -921,8 +921,10 @@ static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog,
                                pos++;
                        }
                }
+
+               /* no link or prog match, skip the cgroup of this layer */
+               continue;
 found:
-               BUG_ON(!cg);
                progs = rcu_dereference_protected(
                                desc->bpf.effective[atype],
                                lockdep_is_held(&cgroup_mutex));
index c1e10d0..3d9eb3a 100644 (file)
@@ -971,7 +971,7 @@ pure_initcall(bpf_jit_charge_init);
 
 int bpf_jit_charge_modmem(u32 size)
 {
-       if (atomic_long_add_return(size, &bpf_jit_current) > bpf_jit_limit) {
+       if (atomic_long_add_return(size, &bpf_jit_current) > READ_ONCE(bpf_jit_limit)) {
                if (!bpf_capable()) {
                        atomic_long_sub(size, &bpf_jit_current);
                        return -EPERM;
index a4d40d9..2776062 100644 (file)
@@ -5197,7 +5197,7 @@ syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
        switch (func_id) {
        case BPF_FUNC_sys_bpf:
-               return &bpf_sys_bpf_proto;
+               return !perfmon_capable() ? NULL : &bpf_sys_bpf_proto;
        case BPF_FUNC_btf_find_by_name_kind:
                return &bpf_btf_find_by_name_kind_proto;
        case BPF_FUNC_sys_close:
index 096fdac..3eadb14 100644 (file)
@@ -6066,6 +6066,9 @@ skip_type_check:
                        return -EACCES;
                }
                meta->mem_size = reg->var_off.value;
+               err = mark_chain_precision(env, regno);
+               if (err)
+                       return err;
                break;
        case ARG_PTR_TO_INT:
        case ARG_PTR_TO_LONG:
@@ -7030,8 +7033,7 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
        struct bpf_insn_aux_data *aux = &env->insn_aux_data[insn_idx];
        struct bpf_reg_state *regs = cur_regs(env), *reg;
        struct bpf_map *map = meta->map_ptr;
-       struct tnum range;
-       u64 val;
+       u64 val, max;
        int err;
 
        if (func_id != BPF_FUNC_tail_call)
@@ -7041,10 +7043,11 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
                return -EINVAL;
        }
 
-       range = tnum_range(0, map->max_entries - 1);
        reg = &regs[BPF_REG_3];
+       val = reg->var_off.value;
+       max = map->max_entries;
 
-       if (!register_is_const(reg) || !tnum_in(range, reg->var_off)) {
+       if (!(register_is_const(reg) && val < max)) {
                bpf_map_key_store(aux, BPF_MAP_KEY_POISON);
                return 0;
        }
@@ -7052,8 +7055,6 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
        err = mark_chain_precision(env, BPF_REG_3);
        if (err)
                return err;
-
-       val = reg->var_off.value;
        if (bpf_map_key_unseen(aux))
                bpf_map_key_store(aux, val);
        else if (!bpf_map_key_poisoned(aux) &&
index e4bb5d5..5f2090d 100644 (file)
@@ -6049,6 +6049,9 @@ struct cgroup *cgroup_get_from_id(u64 id)
        if (!kn)
                goto out;
 
+       if (kernfs_type(kn) != KERNFS_DIR)
+               goto put;
+
        rcu_read_lock();
 
        cgrp = rcu_dereference(*(void __rcu __force **)&kn->priv);
@@ -6056,7 +6059,7 @@ struct cgroup *cgroup_get_from_id(u64 id)
                cgrp = NULL;
 
        rcu_read_unlock();
-
+put:
        kernfs_put(kn);
 out:
        return cgrp;
index 2caafd1..18c93c2 100644 (file)
@@ -350,11 +350,10 @@ static struct dma_debug_entry *bucket_find_contain(struct hash_bucket **bucket,
                                                   unsigned long *flags)
 {
 
-       unsigned int max_range = dma_get_max_seg_size(ref->dev);
        struct dma_debug_entry *entry, index = *ref;
-       unsigned int range = 0;
+       int limit = min(HASH_SIZE, (index.dev_addr >> HASH_FN_SHIFT) + 1);
 
-       while (range <= max_range) {
+       for (int i = 0; i < limit; i++) {
                entry = __hash_bucket_find(*bucket, ref, containing_match);
 
                if (entry)
@@ -364,7 +363,6 @@ static struct dma_debug_entry *bucket_find_contain(struct hash_bucket **bucket,
                 * Nothing found, go back a hash bucket
                 */
                put_hash_bucket(*bucket, *flags);
-               range          += (1 << HASH_FN_SHIFT);
                index.dev_addr -= (1 << HASH_FN_SHIFT);
                *bucket = get_hash_bucket(&index, flags);
        }
index 49cbf3e..27f2723 100644 (file)
@@ -707,7 +707,7 @@ int dma_mmap_noncontiguous(struct device *dev, struct vm_area_struct *vma,
 }
 EXPORT_SYMBOL_GPL(dma_mmap_noncontiguous);
 
-int dma_supported(struct device *dev, u64 mask)
+static int dma_supported(struct device *dev, u64 mask)
 {
        const struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -721,7 +721,6 @@ int dma_supported(struct device *dev, u64 mask)
                return 1;
        return ops->dma_supported(dev, mask);
 }
-EXPORT_SYMBOL(dma_supported);
 
 bool dma_pci_p2pdma_supported(struct device *dev)
 {
index c5a9190..0ef6b12 100644 (file)
@@ -326,9 +326,6 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
                swiotlb_adjust_nareas(num_possible_cpus());
 
        nslabs = default_nslabs;
-       if (nslabs < IO_TLB_MIN_SLABS)
-               panic("%s: nslabs = %lu too small\n", __func__, nslabs);
-
        /*
         * By default allocate the bounce buffer memory from low memory, but
         * allow to pick a location everywhere for hypervisors with guest
@@ -341,8 +338,7 @@ retry:
        else
                tlb = memblock_alloc_low(bytes, PAGE_SIZE);
        if (!tlb) {
-               pr_warn("%s: Failed to allocate %zu bytes tlb structure\n",
-                       __func__, bytes);
+               pr_warn("%s: failed to allocate tlb structure\n", __func__);
                return;
        }
 
@@ -579,7 +575,10 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
        }
 }
 
-#define slot_addr(start, idx)  ((start) + ((idx) << IO_TLB_SHIFT))
+static inline phys_addr_t slot_addr(phys_addr_t start, phys_addr_t idx)
+{
+       return start + (idx << IO_TLB_SHIFT);
+}
 
 /*
  * Carefully handle integer overflow which can occur when boundary_mask == ~0UL.
@@ -765,7 +764,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
        /*
         * When dir == DMA_FROM_DEVICE we could omit the copy from the orig
         * to the tlb buffer, if we knew for sure the device will
-        * overwirte the entire current content. But we don't. Thus
+        * overwrite the entire current content. But we don't. Thus
         * unconditional bounce may prevent leaking swiotlb content (i.e.
         * kernel memory) to user-space.
         */
index 2621fd2..ff4bffc 100644 (file)
@@ -6893,9 +6893,16 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 {
        struct perf_event *leader = event->group_leader, *sub;
        u64 read_format = event->attr.read_format;
+       unsigned long flags;
        u64 values[6];
        int n = 0;
 
+       /*
+        * Disabling interrupts avoids all counter scheduling
+        * (context switches, timer based rotation and IPIs).
+        */
+       local_irq_save(flags);
+
        values[n++] = 1 + leader->nr_siblings;
 
        if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
@@ -6931,6 +6938,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 
                __output_copy(handle, values, n * sizeof(u64));
        }
+
+       local_irq_restore(flags);
 }
 
 #define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\
index 90c85b1..2b6bd51 100644 (file)
@@ -1225,6 +1225,7 @@ void mmput_async(struct mm_struct *mm)
                schedule_work(&mm->async_put_work);
        }
 }
+EXPORT_SYMBOL_GPL(mmput_async);
 #endif
 
 /**
@@ -2046,11 +2047,8 @@ static __latent_entropy struct task_struct *copy_process(
        /*
         * If the new process will be in a different time namespace
         * do not allow it to share VM or a thread group with the forking task.
-        *
-        * On vfork, the child process enters the target time namespace only
-        * after exec.
         */
-       if ((clone_flags & (CLONE_VM | CLONE_VFORK)) == CLONE_VM) {
+       if (clone_flags & (CLONE_THREAD | CLONE_VM)) {
                if (nsp->time_ns != nsp->time_ns_for_children)
                        return ERR_PTR(-EINVAL);
        }
index 08350e3..ca9d834 100644 (file)
@@ -1562,6 +1562,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
        /* Ensure it is not in reserved area nor out of text */
        if (!(core_kernel_text((unsigned long) p->addr) ||
            is_module_text_address((unsigned long) p->addr)) ||
+           in_gate_area_no_mm((unsigned long) p->addr) ||
            within_kprobe_blacklist((unsigned long) p->addr) ||
            jump_label_text_reserved(p->addr, p->addr) ||
            static_call_text_reserved(p->addr, p->addr) ||
index b4cbb40..eec72ca 100644 (file)
@@ -179,8 +179,7 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
        if (IS_ERR(new_ns))
                return  PTR_ERR(new_ns);
 
-       if ((flags & CLONE_VM) == 0)
-               timens_on_fork(new_ns, tsk);
+       timens_on_fork(new_ns, tsk);
 
        tsk->nsproxy = new_ns;
        return 0;
index d8e1b27..503c2aa 100644 (file)
@@ -84,10 +84,15 @@ torture_param(int, fwd_progress_holdoff, 60, "Time between forward-progress test
 torture_param(bool, fwd_progress_need_resched, 1, "Hide cond_resched() behind need_resched()");
 torture_param(bool, gp_cond, false, "Use conditional/async GP wait primitives");
 torture_param(bool, gp_cond_exp, false, "Use conditional/async expedited GP wait primitives");
+torture_param(bool, gp_cond_full, false, "Use conditional/async full-state GP wait primitives");
+torture_param(bool, gp_cond_exp_full, false,
+                   "Use conditional/async full-stateexpedited GP wait primitives");
 torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
 torture_param(bool, gp_normal, false, "Use normal (non-expedited) GP wait primitives");
 torture_param(bool, gp_poll, false, "Use polling GP wait primitives");
 torture_param(bool, gp_poll_exp, false, "Use polling expedited GP wait primitives");
+torture_param(bool, gp_poll_full, false, "Use polling full-state GP wait primitives");
+torture_param(bool, gp_poll_exp_full, false, "Use polling full-state expedited GP wait primitives");
 torture_param(bool, gp_sync, false, "Use synchronous GP wait primitives");
 torture_param(int, irqreader, 1, "Allow RCU readers from irq handlers");
 torture_param(int, leakpointer, 0, "Leak pointer dereferences from readers");
@@ -194,16 +199,24 @@ static int rcu_torture_writer_state;
 #define RTWS_DEF_FREE          3
 #define RTWS_EXP_SYNC          4
 #define RTWS_COND_GET          5
-#define RTWS_COND_GET_EXP      6
-#define RTWS_COND_SYNC         7
-#define RTWS_COND_SYNC_EXP     8
-#define RTWS_POLL_GET          9
-#define RTWS_POLL_GET_EXP      10
-#define RTWS_POLL_WAIT         11
-#define RTWS_POLL_WAIT_EXP     12
-#define RTWS_SYNC              13
-#define RTWS_STUTTER           14
-#define RTWS_STOPPING          15
+#define RTWS_COND_GET_FULL     6
+#define RTWS_COND_GET_EXP      7
+#define RTWS_COND_GET_EXP_FULL 8
+#define RTWS_COND_SYNC         9
+#define RTWS_COND_SYNC_FULL    10
+#define RTWS_COND_SYNC_EXP     11
+#define RTWS_COND_SYNC_EXP_FULL        12
+#define RTWS_POLL_GET          13
+#define RTWS_POLL_GET_FULL     14
+#define RTWS_POLL_GET_EXP      15
+#define RTWS_POLL_GET_EXP_FULL 16
+#define RTWS_POLL_WAIT         17
+#define RTWS_POLL_WAIT_FULL    18
+#define RTWS_POLL_WAIT_EXP     19
+#define RTWS_POLL_WAIT_EXP_FULL        20
+#define RTWS_SYNC              21
+#define RTWS_STUTTER           22
+#define RTWS_STOPPING          23
 static const char * const rcu_torture_writer_state_names[] = {
        "RTWS_FIXED_DELAY",
        "RTWS_DELAY",
@@ -211,13 +224,21 @@ static const char * const rcu_torture_writer_state_names[] = {
        "RTWS_DEF_FREE",
        "RTWS_EXP_SYNC",
        "RTWS_COND_GET",
+       "RTWS_COND_GET_FULL",
        "RTWS_COND_GET_EXP",
+       "RTWS_COND_GET_EXP_FULL",
        "RTWS_COND_SYNC",
+       "RTWS_COND_SYNC_FULL",
        "RTWS_COND_SYNC_EXP",
+       "RTWS_COND_SYNC_EXP_FULL",
        "RTWS_POLL_GET",
+       "RTWS_POLL_GET_FULL",
        "RTWS_POLL_GET_EXP",
+       "RTWS_POLL_GET_EXP_FULL",
        "RTWS_POLL_WAIT",
+       "RTWS_POLL_WAIT_FULL",
        "RTWS_POLL_WAIT_EXP",
+       "RTWS_POLL_WAIT_EXP_FULL",
        "RTWS_SYNC",
        "RTWS_STUTTER",
        "RTWS_STOPPING",
@@ -332,13 +353,21 @@ struct rcu_torture_ops {
        void (*exp_sync)(void);
        unsigned long (*get_gp_state_exp)(void);
        unsigned long (*start_gp_poll_exp)(void);
+       void (*start_gp_poll_exp_full)(struct rcu_gp_oldstate *rgosp);
        bool (*poll_gp_state_exp)(unsigned long oldstate);
        void (*cond_sync_exp)(unsigned long oldstate);
+       void (*cond_sync_exp_full)(struct rcu_gp_oldstate *rgosp);
        unsigned long (*get_gp_state)(void);
+       void (*get_gp_state_full)(struct rcu_gp_oldstate *rgosp);
        unsigned long (*get_gp_completed)(void);
+       void (*get_gp_completed_full)(struct rcu_gp_oldstate *rgosp);
        unsigned long (*start_gp_poll)(void);
+       void (*start_gp_poll_full)(struct rcu_gp_oldstate *rgosp);
        bool (*poll_gp_state)(unsigned long oldstate);
+       bool (*poll_gp_state_full)(struct rcu_gp_oldstate *rgosp);
+       bool (*poll_need_2gp)(bool poll, bool poll_full);
        void (*cond_sync)(unsigned long oldstate);
+       void (*cond_sync_full)(struct rcu_gp_oldstate *rgosp);
        call_rcu_func_t call;
        void (*cb_barrier)(void);
        void (*fqs)(void);
@@ -489,6 +518,11 @@ static void rcu_sync_torture_init(void)
        INIT_LIST_HEAD(&rcu_torture_removed);
 }
 
+static bool rcu_poll_need_2gp(bool poll, bool poll_full)
+{
+       return poll;
+}
+
 static struct rcu_torture_ops rcu_ops = {
        .ttype                  = RCU_FLAVOR,
        .init                   = rcu_sync_torture_init,
@@ -502,12 +536,19 @@ static struct rcu_torture_ops rcu_ops = {
        .sync                   = synchronize_rcu,
        .exp_sync               = synchronize_rcu_expedited,
        .get_gp_state           = get_state_synchronize_rcu,
+       .get_gp_state_full      = get_state_synchronize_rcu_full,
        .get_gp_completed       = get_completed_synchronize_rcu,
+       .get_gp_completed_full  = get_completed_synchronize_rcu_full,
        .start_gp_poll          = start_poll_synchronize_rcu,
+       .start_gp_poll_full     = start_poll_synchronize_rcu_full,
        .poll_gp_state          = poll_state_synchronize_rcu,
+       .poll_gp_state_full     = poll_state_synchronize_rcu_full,
+       .poll_need_2gp          = rcu_poll_need_2gp,
        .cond_sync              = cond_synchronize_rcu,
+       .cond_sync_full         = cond_synchronize_rcu_full,
        .get_gp_state_exp       = get_state_synchronize_rcu,
        .start_gp_poll_exp      = start_poll_synchronize_rcu_expedited,
+       .start_gp_poll_exp_full = start_poll_synchronize_rcu_expedited_full,
        .poll_gp_state_exp      = poll_state_synchronize_rcu,
        .cond_sync_exp          = cond_synchronize_rcu_expedited,
        .call                   = call_rcu,
@@ -709,6 +750,9 @@ static struct rcu_torture_ops srcud_ops = {
        .deferred_free  = srcu_torture_deferred_free,
        .sync           = srcu_torture_synchronize,
        .exp_sync       = srcu_torture_synchronize_expedited,
+       .get_gp_state   = srcu_torture_get_gp_state,
+       .start_gp_poll  = srcu_torture_start_gp_poll,
+       .poll_gp_state  = srcu_torture_poll_gp_state,
        .call           = srcu_torture_call,
        .cb_barrier     = srcu_torture_barrier,
        .stats          = srcu_torture_stats,
@@ -1148,15 +1192,35 @@ static int nsynctypes;
  */
 static void rcu_torture_write_types(void)
 {
-       bool gp_cond1 = gp_cond, gp_cond_exp1 = gp_cond_exp, gp_exp1 = gp_exp;
-       bool gp_poll_exp1 = gp_poll_exp, gp_normal1 = gp_normal, gp_poll1 = gp_poll;
-       bool gp_sync1 = gp_sync;
+       bool gp_cond1 = gp_cond, gp_cond_exp1 = gp_cond_exp, gp_cond_full1 = gp_cond_full;
+       bool gp_cond_exp_full1 = gp_cond_exp_full, gp_exp1 = gp_exp, gp_poll_exp1 = gp_poll_exp;
+       bool gp_poll_exp_full1 = gp_poll_exp_full, gp_normal1 = gp_normal, gp_poll1 = gp_poll;
+       bool gp_poll_full1 = gp_poll_full, gp_sync1 = gp_sync;
 
        /* Initialize synctype[] array.  If none set, take default. */
-       if (!gp_cond1 && !gp_cond_exp1 && !gp_exp1 && !gp_poll_exp &&
-           !gp_normal1 && !gp_poll1 && !gp_sync1)
-               gp_cond1 = gp_cond_exp1 = gp_exp1 = gp_poll_exp1 =
-                          gp_normal1 = gp_poll1 = gp_sync1 = true;
+       if (!gp_cond1 &&
+           !gp_cond_exp1 &&
+           !gp_cond_full1 &&
+           !gp_cond_exp_full1 &&
+           !gp_exp1 &&
+           !gp_poll_exp1 &&
+           !gp_poll_exp_full1 &&
+           !gp_normal1 &&
+           !gp_poll1 &&
+           !gp_poll_full1 &&
+           !gp_sync1) {
+               gp_cond1 = true;
+               gp_cond_exp1 = true;
+               gp_cond_full1 = true;
+               gp_cond_exp_full1 = true;
+               gp_exp1 = true;
+               gp_poll_exp1 = true;
+               gp_poll_exp_full1 = true;
+               gp_normal1 = true;
+               gp_poll1 = true;
+               gp_poll_full1 = true;
+               gp_sync1 = true;
+       }
        if (gp_cond1 && cur_ops->get_gp_state && cur_ops->cond_sync) {
                synctype[nsynctypes++] = RTWS_COND_GET;
                pr_info("%s: Testing conditional GPs.\n", __func__);
@@ -1169,6 +1233,19 @@ static void rcu_torture_write_types(void)
        } else if (gp_cond_exp && (!cur_ops->get_gp_state_exp || !cur_ops->cond_sync_exp)) {
                pr_alert("%s: gp_cond_exp without primitives.\n", __func__);
        }
+       if (gp_cond_full1 && cur_ops->get_gp_state && cur_ops->cond_sync_full) {
+               synctype[nsynctypes++] = RTWS_COND_GET_FULL;
+               pr_info("%s: Testing conditional full-state GPs.\n", __func__);
+       } else if (gp_cond_full && (!cur_ops->get_gp_state || !cur_ops->cond_sync_full)) {
+               pr_alert("%s: gp_cond_full without primitives.\n", __func__);
+       }
+       if (gp_cond_exp_full1 && cur_ops->get_gp_state_exp && cur_ops->cond_sync_exp_full) {
+               synctype[nsynctypes++] = RTWS_COND_GET_EXP_FULL;
+               pr_info("%s: Testing conditional full-state expedited GPs.\n", __func__);
+       } else if (gp_cond_exp_full &&
+                  (!cur_ops->get_gp_state_exp || !cur_ops->cond_sync_exp_full)) {
+               pr_alert("%s: gp_cond_exp_full without primitives.\n", __func__);
+       }
        if (gp_exp1 && cur_ops->exp_sync) {
                synctype[nsynctypes++] = RTWS_EXP_SYNC;
                pr_info("%s: Testing expedited GPs.\n", __func__);
@@ -1187,12 +1264,25 @@ static void rcu_torture_write_types(void)
        } else if (gp_poll && (!cur_ops->start_gp_poll || !cur_ops->poll_gp_state)) {
                pr_alert("%s: gp_poll without primitives.\n", __func__);
        }
+       if (gp_poll_full1 && cur_ops->start_gp_poll_full && cur_ops->poll_gp_state_full) {
+               synctype[nsynctypes++] = RTWS_POLL_GET_FULL;
+               pr_info("%s: Testing polling full-state GPs.\n", __func__);
+       } else if (gp_poll_full && (!cur_ops->start_gp_poll_full || !cur_ops->poll_gp_state_full)) {
+               pr_alert("%s: gp_poll_full without primitives.\n", __func__);
+       }
        if (gp_poll_exp1 && cur_ops->start_gp_poll_exp && cur_ops->poll_gp_state_exp) {
                synctype[nsynctypes++] = RTWS_POLL_GET_EXP;
                pr_info("%s: Testing polling expedited GPs.\n", __func__);
        } else if (gp_poll_exp && (!cur_ops->start_gp_poll_exp || !cur_ops->poll_gp_state_exp)) {
                pr_alert("%s: gp_poll_exp without primitives.\n", __func__);
        }
+       if (gp_poll_exp_full1 && cur_ops->start_gp_poll_exp_full && cur_ops->poll_gp_state_full) {
+               synctype[nsynctypes++] = RTWS_POLL_GET_EXP_FULL;
+               pr_info("%s: Testing polling full-state expedited GPs.\n", __func__);
+       } else if (gp_poll_exp_full &&
+                  (!cur_ops->start_gp_poll_exp_full || !cur_ops->poll_gp_state_full)) {
+               pr_alert("%s: gp_poll_exp_full without primitives.\n", __func__);
+       }
        if (gp_sync1 && cur_ops->sync) {
                synctype[nsynctypes++] = RTWS_SYNC;
                pr_info("%s: Testing normal GPs.\n", __func__);
@@ -1202,6 +1292,40 @@ static void rcu_torture_write_types(void)
 }
 
 /*
+ * Do the specified rcu_torture_writer() synchronous grace period,
+ * while also testing out the polled APIs.  Note well that the single-CPU
+ * grace-period optimizations must be accounted for.
+ */
+static void do_rtws_sync(struct torture_random_state *trsp, void (*sync)(void))
+{
+       unsigned long cookie;
+       struct rcu_gp_oldstate cookie_full;
+       bool dopoll;
+       bool dopoll_full;
+       unsigned long r = torture_random(trsp);
+
+       dopoll = cur_ops->get_gp_state && cur_ops->poll_gp_state && !(r & 0x300);
+       dopoll_full = cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full && !(r & 0xc00);
+       if (dopoll || dopoll_full)
+               cpus_read_lock();
+       if (dopoll)
+               cookie = cur_ops->get_gp_state();
+       if (dopoll_full)
+               cur_ops->get_gp_state_full(&cookie_full);
+       if (cur_ops->poll_need_2gp && cur_ops->poll_need_2gp(dopoll, dopoll_full))
+               sync();
+       sync();
+       WARN_ONCE(dopoll && !cur_ops->poll_gp_state(cookie),
+                 "%s: Cookie check 3 failed %pS() online %*pbl.",
+                 __func__, sync, cpumask_pr_args(cpu_online_mask));
+       WARN_ONCE(dopoll_full && !cur_ops->poll_gp_state_full(&cookie_full),
+                 "%s: Cookie check 4 failed %pS() online %*pbl",
+                 __func__, sync, cpumask_pr_args(cpu_online_mask));
+       if (dopoll || dopoll_full)
+               cpus_read_unlock();
+}
+
+/*
  * RCU torture writer kthread.  Repeatedly substitutes a new structure
  * for that pointed to by rcu_torture_current, freeing the old structure
  * after a series of grace periods (the "pipeline").
@@ -1212,8 +1336,10 @@ rcu_torture_writer(void *arg)
        bool boot_ended;
        bool can_expedite = !rcu_gp_is_expedited() && !rcu_gp_is_normal();
        unsigned long cookie;
+       struct rcu_gp_oldstate cookie_full;
        int expediting = 0;
        unsigned long gp_snap;
+       struct rcu_gp_oldstate gp_snap_full;
        int i;
        int idx;
        int oldnice = task_nice(current);
@@ -1261,11 +1387,12 @@ rcu_torture_writer(void *arg)
                        atomic_inc(&rcu_torture_wcount[i]);
                        WRITE_ONCE(old_rp->rtort_pipe_count,
                                   old_rp->rtort_pipe_count + 1);
+
+                       // Make sure readers block polled grace periods.
                        if (cur_ops->get_gp_state && cur_ops->poll_gp_state) {
                                idx = cur_ops->readlock();
                                cookie = cur_ops->get_gp_state();
-                               WARN_ONCE(rcu_torture_writer_state != RTWS_DEF_FREE &&
-                                         cur_ops->poll_gp_state(cookie),
+                               WARN_ONCE(cur_ops->poll_gp_state(cookie),
                                          "%s: Cookie check 1 failed %s(%d) %lu->%lu\n",
                                          __func__,
                                          rcu_torture_writer_state_getname(),
@@ -1277,6 +1404,21 @@ rcu_torture_writer(void *arg)
                                }
                                cur_ops->readunlock(idx);
                        }
+                       if (cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full) {
+                               idx = cur_ops->readlock();
+                               cur_ops->get_gp_state_full(&cookie_full);
+                               WARN_ONCE(cur_ops->poll_gp_state_full(&cookie_full),
+                                         "%s: Cookie check 5 failed %s(%d) online %*pbl\n",
+                                         __func__,
+                                         rcu_torture_writer_state_getname(),
+                                         rcu_torture_writer_state,
+                                         cpumask_pr_args(cpu_online_mask));
+                               if (cur_ops->get_gp_completed_full) {
+                                       cur_ops->get_gp_completed_full(&cookie_full);
+                                       WARN_ON_ONCE(!cur_ops->poll_gp_state_full(&cookie_full));
+                               }
+                               cur_ops->readunlock(idx);
+                       }
                        switch (synctype[torture_random(&rand) % nsynctypes]) {
                        case RTWS_DEF_FREE:
                                rcu_torture_writer_state = RTWS_DEF_FREE;
@@ -1284,12 +1426,7 @@ rcu_torture_writer(void *arg)
                                break;
                        case RTWS_EXP_SYNC:
                                rcu_torture_writer_state = RTWS_EXP_SYNC;
-                               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-                                       cookie = cur_ops->get_gp_state();
-                               cur_ops->exp_sync();
-                               cur_ops->exp_sync();
-                               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-                                       WARN_ON_ONCE(!cur_ops->poll_gp_state(cookie));
+                               do_rtws_sync(&rand, cur_ops->exp_sync);
                                rcu_torture_pipe_update(old_rp);
                                break;
                        case RTWS_COND_GET:
@@ -1308,6 +1445,22 @@ rcu_torture_writer(void *arg)
                                cur_ops->cond_sync_exp(gp_snap);
                                rcu_torture_pipe_update(old_rp);
                                break;
+                       case RTWS_COND_GET_FULL:
+                               rcu_torture_writer_state = RTWS_COND_GET_FULL;
+                               cur_ops->get_gp_state_full(&gp_snap_full);
+                               torture_hrtimeout_jiffies(torture_random(&rand) % 16, &rand);
+                               rcu_torture_writer_state = RTWS_COND_SYNC_FULL;
+                               cur_ops->cond_sync_full(&gp_snap_full);
+                               rcu_torture_pipe_update(old_rp);
+                               break;
+                       case RTWS_COND_GET_EXP_FULL:
+                               rcu_torture_writer_state = RTWS_COND_GET_EXP_FULL;
+                               cur_ops->get_gp_state_full(&gp_snap_full);
+                               torture_hrtimeout_jiffies(torture_random(&rand) % 16, &rand);
+                               rcu_torture_writer_state = RTWS_COND_SYNC_EXP_FULL;
+                               cur_ops->cond_sync_exp_full(&gp_snap_full);
+                               rcu_torture_pipe_update(old_rp);
+                               break;
                        case RTWS_POLL_GET:
                                rcu_torture_writer_state = RTWS_POLL_GET;
                                gp_snap = cur_ops->start_gp_poll();
@@ -1317,6 +1470,15 @@ rcu_torture_writer(void *arg)
                                                                  &rand);
                                rcu_torture_pipe_update(old_rp);
                                break;
+                       case RTWS_POLL_GET_FULL:
+                               rcu_torture_writer_state = RTWS_POLL_GET_FULL;
+                               cur_ops->start_gp_poll_full(&gp_snap_full);
+                               rcu_torture_writer_state = RTWS_POLL_WAIT_FULL;
+                               while (!cur_ops->poll_gp_state_full(&gp_snap_full))
+                                       torture_hrtimeout_jiffies(torture_random(&rand) % 16,
+                                                                 &rand);
+                               rcu_torture_pipe_update(old_rp);
+                               break;
                        case RTWS_POLL_GET_EXP:
                                rcu_torture_writer_state = RTWS_POLL_GET_EXP;
                                gp_snap = cur_ops->start_gp_poll_exp();
@@ -1326,14 +1488,18 @@ rcu_torture_writer(void *arg)
                                                                  &rand);
                                rcu_torture_pipe_update(old_rp);
                                break;
+                       case RTWS_POLL_GET_EXP_FULL:
+                               rcu_torture_writer_state = RTWS_POLL_GET_EXP_FULL;
+                               cur_ops->start_gp_poll_exp_full(&gp_snap_full);
+                               rcu_torture_writer_state = RTWS_POLL_WAIT_EXP_FULL;
+                               while (!cur_ops->poll_gp_state_full(&gp_snap_full))
+                                       torture_hrtimeout_jiffies(torture_random(&rand) % 16,
+                                                                 &rand);
+                               rcu_torture_pipe_update(old_rp);
+                               break;
                        case RTWS_SYNC:
                                rcu_torture_writer_state = RTWS_SYNC;
-                               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-                                       cookie = cur_ops->get_gp_state();
-                               cur_ops->sync();
-                               cur_ops->sync();
-                               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-                                       WARN_ON_ONCE(!cur_ops->poll_gp_state(cookie));
+                               do_rtws_sync(&rand, cur_ops->sync);
                                rcu_torture_pipe_update(old_rp);
                                break;
                        default:
@@ -1400,6 +1566,7 @@ static int
 rcu_torture_fakewriter(void *arg)
 {
        unsigned long gp_snap;
+       struct rcu_gp_oldstate gp_snap_full;
        DEFINE_TORTURE_RANDOM(rand);
 
        VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task started");
@@ -1438,6 +1605,16 @@ rcu_torture_fakewriter(void *arg)
                                torture_hrtimeout_jiffies(torture_random(&rand) % 16, &rand);
                                cur_ops->cond_sync_exp(gp_snap);
                                break;
+                       case RTWS_COND_GET_FULL:
+                               cur_ops->get_gp_state_full(&gp_snap_full);
+                               torture_hrtimeout_jiffies(torture_random(&rand) % 16, &rand);
+                               cur_ops->cond_sync_full(&gp_snap_full);
+                               break;
+                       case RTWS_COND_GET_EXP_FULL:
+                               cur_ops->get_gp_state_full(&gp_snap_full);
+                               torture_hrtimeout_jiffies(torture_random(&rand) % 16, &rand);
+                               cur_ops->cond_sync_exp_full(&gp_snap_full);
+                               break;
                        case RTWS_POLL_GET:
                                gp_snap = cur_ops->start_gp_poll();
                                while (!cur_ops->poll_gp_state(gp_snap)) {
@@ -1445,6 +1622,13 @@ rcu_torture_fakewriter(void *arg)
                                                                  &rand);
                                }
                                break;
+                       case RTWS_POLL_GET_FULL:
+                               cur_ops->start_gp_poll_full(&gp_snap_full);
+                               while (!cur_ops->poll_gp_state_full(&gp_snap_full)) {
+                                       torture_hrtimeout_jiffies(torture_random(&rand) % 16,
+                                                                 &rand);
+                               }
+                               break;
                        case RTWS_POLL_GET_EXP:
                                gp_snap = cur_ops->start_gp_poll_exp();
                                while (!cur_ops->poll_gp_state_exp(gp_snap)) {
@@ -1452,6 +1636,13 @@ rcu_torture_fakewriter(void *arg)
                                                                  &rand);
                                }
                                break;
+                       case RTWS_POLL_GET_EXP_FULL:
+                               cur_ops->start_gp_poll_exp_full(&gp_snap_full);
+                               while (!cur_ops->poll_gp_state_full(&gp_snap_full)) {
+                                       torture_hrtimeout_jiffies(torture_random(&rand) % 16,
+                                                                 &rand);
+                               }
+                               break;
                        case RTWS_SYNC:
                                cur_ops->sync();
                                break;
@@ -1715,7 +1906,9 @@ rcutorture_loop_extend(int *readstate, struct torture_random_state *trsp,
  */
 static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
 {
+       bool checkpolling = !(torture_random(trsp) & 0xfff);
        unsigned long cookie;
+       struct rcu_gp_oldstate cookie_full;
        int i;
        unsigned long started;
        unsigned long completed;
@@ -1731,8 +1924,12 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
        WARN_ON_ONCE(!rcu_is_watching());
        newstate = rcutorture_extend_mask(readstate, trsp);
        rcutorture_one_extend(&readstate, newstate, trsp, rtrsp++);
-       if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-               cookie = cur_ops->get_gp_state();
+       if (checkpolling) {
+               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
+                       cookie = cur_ops->get_gp_state();
+               if (cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full)
+                       cur_ops->get_gp_state_full(&cookie_full);
+       }
        started = cur_ops->get_gp_seq();
        ts = rcu_trace_clock_local();
        p = rcu_dereference_check(rcu_torture_current,
@@ -1766,13 +1963,22 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp, long myid)
        }
        __this_cpu_inc(rcu_torture_batch[completed]);
        preempt_enable();
-       if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
-               WARN_ONCE(cur_ops->poll_gp_state(cookie),
-                         "%s: Cookie check 2 failed %s(%d) %lu->%lu\n",
-                         __func__,
-                         rcu_torture_writer_state_getname(),
-                         rcu_torture_writer_state,
-                         cookie, cur_ops->get_gp_state());
+       if (checkpolling) {
+               if (cur_ops->get_gp_state && cur_ops->poll_gp_state)
+                       WARN_ONCE(cur_ops->poll_gp_state(cookie),
+                                 "%s: Cookie check 2 failed %s(%d) %lu->%lu\n",
+                                 __func__,
+                                 rcu_torture_writer_state_getname(),
+                                 rcu_torture_writer_state,
+                                 cookie, cur_ops->get_gp_state());
+               if (cur_ops->get_gp_state_full && cur_ops->poll_gp_state_full)
+                       WARN_ONCE(cur_ops->poll_gp_state_full(&cookie_full),
+                                 "%s: Cookie check 6 failed %s(%d) online %*pbl\n",
+                                 __func__,
+                                 rcu_torture_writer_state_getname(),
+                                 rcu_torture_writer_state,
+                                 cpumask_pr_args(cpu_online_mask));
+       }
        rcutorture_one_extend(&readstate, 0, trsp, rtrsp);
        WARN_ON_ONCE(readstate);
        // This next splat is expected behavior if leakpointer, especially
@@ -2600,12 +2806,12 @@ static int rcutorture_oom_notify(struct notifier_block *self,
        for (i = 0; i < fwd_progress; i++)
                ncbs += rcu_torture_fwd_prog_cbfree(&rfp[i]);
        pr_info("%s: Freed %lu RCU callbacks.\n", __func__, ncbs);
-       rcu_barrier();
+       cur_ops->cb_barrier();
        ncbs = 0;
        for (i = 0; i < fwd_progress; i++)
                ncbs += rcu_torture_fwd_prog_cbfree(&rfp[i]);
        pr_info("%s: Freed %lu RCU callbacks.\n", __func__, ncbs);
-       rcu_barrier();
+       cur_ops->cb_barrier();
        ncbs = 0;
        for (i = 0; i < fwd_progress; i++)
                ncbs += rcu_torture_fwd_prog_cbfree(&rfp[i]);
index 92c002d..33adafd 100644 (file)
@@ -117,7 +117,7 @@ void srcu_drive_gp(struct work_struct *wp)
        struct srcu_struct *ssp;
 
        ssp = container_of(wp, struct srcu_struct, srcu_work);
-       if (ssp->srcu_gp_running || USHORT_CMP_GE(ssp->srcu_idx, READ_ONCE(ssp->srcu_idx_max)))
+       if (ssp->srcu_gp_running || ULONG_CMP_GE(ssp->srcu_idx, READ_ONCE(ssp->srcu_idx_max)))
                return; /* Already running or nothing to do. */
 
        /* Remove recently arrived callbacks and wait for readers. */
@@ -150,17 +150,17 @@ void srcu_drive_gp(struct work_struct *wp)
         * straighten that out.
         */
        WRITE_ONCE(ssp->srcu_gp_running, false);
-       if (USHORT_CMP_LT(ssp->srcu_idx, READ_ONCE(ssp->srcu_idx_max)))
+       if (ULONG_CMP_LT(ssp->srcu_idx, READ_ONCE(ssp->srcu_idx_max)))
                schedule_work(&ssp->srcu_work);
 }
 EXPORT_SYMBOL_GPL(srcu_drive_gp);
 
 static void srcu_gp_start_if_needed(struct srcu_struct *ssp)
 {
-       unsigned short cookie;
+       unsigned long cookie;
 
        cookie = get_state_synchronize_srcu(ssp);
-       if (USHORT_CMP_GE(READ_ONCE(ssp->srcu_idx_max), cookie))
+       if (ULONG_CMP_GE(READ_ONCE(ssp->srcu_idx_max), cookie))
                return;
        WRITE_ONCE(ssp->srcu_idx_max, cookie);
        if (!READ_ONCE(ssp->srcu_gp_running)) {
@@ -215,7 +215,7 @@ unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp)
        barrier();
        ret = (READ_ONCE(ssp->srcu_idx) + 3) & ~0x1;
        barrier();
-       return ret & USHRT_MAX;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(get_state_synchronize_srcu);
 
@@ -240,10 +240,10 @@ EXPORT_SYMBOL_GPL(start_poll_synchronize_srcu);
  */
 bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
 {
-       bool ret = USHORT_CMP_GE(READ_ONCE(ssp->srcu_idx), cookie);
+       unsigned long cur_s = READ_ONCE(ssp->srcu_idx);
 
        barrier();
-       return ret;
+       return ULONG_CMP_GE(cur_s, cookie) || ULONG_CMP_LT(cur_s, cookie - 3);
 }
 EXPORT_SYMBOL_GPL(poll_state_synchronize_srcu);
 
index 83c7e66..f5bf6fb 100644 (file)
@@ -560,7 +560,7 @@ static int __noreturn rcu_tasks_kthread(void *arg)
 static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
 {
        /* Complain if the scheduler has not started.  */
-       RCU_LOCKDEP_WARN(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
+       WARN_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
                         "synchronize_rcu_tasks called too soon");
 
        // If the grace-period kthread is running, use it.
@@ -1500,6 +1500,7 @@ static void rcu_tasks_trace_pregp_step(struct list_head *hop)
                if (rcu_tasks_trace_pertask_prep(t, true))
                        trc_add_holdout(t, hop);
                rcu_read_unlock();
+               cond_resched_tasks_rcu_qs();
        }
 
        // Only after all running tasks have been accounted for is it
@@ -1520,6 +1521,7 @@ static void rcu_tasks_trace_pregp_step(struct list_head *hop)
                        raw_spin_lock_irqsave_rcu_node(rtpcp, flags);
                }
                raw_spin_unlock_irqrestore_rcu_node(rtpcp, flags);
+               cond_resched_tasks_rcu_qs();
        }
 
        // Re-enable CPU hotplug now that the holdout list is populated.
@@ -1619,6 +1621,7 @@ static void check_all_holdout_tasks_trace(struct list_head *hop,
                        trc_del_holdout(t);
                else if (needreport)
                        show_stalled_task_trace(t, firstreport);
+               cond_resched_tasks_rcu_qs();
        }
 
        // Re-enable CPU hotplug now that the holdout list scan has completed.
index f0561ee..a33a8d4 100644 (file)
@@ -158,6 +158,10 @@ void synchronize_rcu(void)
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
+static void tiny_rcu_leak_callback(struct rcu_head *rhp)
+{
+}
+
 /*
  * Post an RCU callback to be invoked after the end of an RCU grace
  * period.  But since we have but one CPU, that would be after any
@@ -165,9 +169,20 @@ EXPORT_SYMBOL_GPL(synchronize_rcu);
  */
 void call_rcu(struct rcu_head *head, rcu_callback_t func)
 {
+       static atomic_t doublefrees;
        unsigned long flags;
 
-       debug_rcu_head_queue(head);
+       if (debug_rcu_head_queue(head)) {
+               if (atomic_inc_return(&doublefrees) < 4) {
+                       pr_err("%s(): Double-freed CB %p->%pS()!!!  ", __func__, head, head->func);
+                       mem_dump_obj(head);
+               }
+
+               if (!__is_kvfree_rcu_offset((unsigned long)head->func))
+                       WRITE_ONCE(head->func, tiny_rcu_leak_callback);
+               return;
+       }
+
        head->func = func;
        head->next = NULL;
 
@@ -184,6 +199,16 @@ void call_rcu(struct rcu_head *head, rcu_callback_t func)
 EXPORT_SYMBOL_GPL(call_rcu);
 
 /*
+ * Store a grace-period-counter "cookie".  For more information,
+ * see the Tree RCU header comment.
+ */
+void get_completed_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       rgosp->rgos_norm = RCU_GET_STATE_COMPLETED;
+}
+EXPORT_SYMBOL_GPL(get_completed_synchronize_rcu_full);
+
+/*
  * Return a grace-period-counter "cookie".  For more information,
  * see the Tree RCU header comment.
  */
index 79aea7d..6bb8e72 100644 (file)
@@ -76,6 +76,7 @@
 /* Data structures. */
 
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, rcu_data) = {
+       .gpwrap = true,
 #ifdef CONFIG_RCU_NOCB_CPU
        .cblist.flags = SEGCBLIST_RCU_CORE,
 #endif
@@ -1755,6 +1756,8 @@ static noinline void rcu_gp_cleanup(void)
                        dump_blkd_tasks(rnp, 10);
                WARN_ON_ONCE(rnp->qsmask);
                WRITE_ONCE(rnp->gp_seq, new_gp_seq);
+               if (!rnp->parent)
+                       smp_mb(); // Order against failing poll_state_synchronize_rcu_full().
                rdp = this_cpu_ptr(&rcu_data);
                if (rnp == rdp->mynode)
                        needgp = __note_gp_changes(rnp, rdp) || needgp;
@@ -2341,8 +2344,8 @@ void rcu_sched_clock_irq(int user)
        rcu_flavor_sched_clock_irq(user);
        if (rcu_pending(user))
                invoke_rcu_core();
-       if (user)
-               rcu_tasks_classic_qs(current, false);
+       if (user || rcu_is_cpu_rrupt_from_idle())
+               rcu_note_voluntary_context_switch(current);
        lockdep_assert_irqs_disabled();
 
        trace_rcu_utilization(TPS("End scheduler-tick"));
@@ -2832,7 +2835,7 @@ EXPORT_SYMBOL_GPL(call_rcu);
 
 
 /* Maximum number of jiffies to wait before draining a batch. */
-#define KFREE_DRAIN_JIFFIES (HZ / 50)
+#define KFREE_DRAIN_JIFFIES (5 * HZ)
 #define KFREE_N_BATCHES 2
 #define FREE_N_CHANNELS 2
 
@@ -3093,6 +3096,21 @@ need_offload_krc(struct kfree_rcu_cpu *krcp)
        return !!krcp->head;
 }
 
+static void
+schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
+{
+       long delay, delay_left;
+
+       delay = READ_ONCE(krcp->count) >= KVFREE_BULK_MAX_ENTR ? 1:KFREE_DRAIN_JIFFIES;
+       if (delayed_work_pending(&krcp->monitor_work)) {
+               delay_left = krcp->monitor_work.timer.expires - jiffies;
+               if (delay < delay_left)
+                       mod_delayed_work(system_wq, &krcp->monitor_work, delay);
+               return;
+       }
+       queue_delayed_work(system_wq, &krcp->monitor_work, delay);
+}
+
 /*
  * This function is invoked after the KFREE_DRAIN_JIFFIES timeout.
  */
@@ -3150,7 +3168,7 @@ static void kfree_rcu_monitor(struct work_struct *work)
        // work to repeat an attempt. Because previous batches are
        // still in progress.
        if (need_offload_krc(krcp))
-               schedule_delayed_work(&krcp->monitor_work, KFREE_DRAIN_JIFFIES);
+               schedule_delayed_monitor_work(krcp);
 
        raw_spin_unlock_irqrestore(&krcp->lock, flags);
 }
@@ -3183,15 +3201,16 @@ static void fill_page_cache_func(struct work_struct *work)
                bnode = (struct kvfree_rcu_bulk_data *)
                        __get_free_page(GFP_KERNEL | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
 
-               if (bnode) {
-                       raw_spin_lock_irqsave(&krcp->lock, flags);
-                       pushed = put_cached_bnode(krcp, bnode);
-                       raw_spin_unlock_irqrestore(&krcp->lock, flags);
+               if (!bnode)
+                       break;
 
-                       if (!pushed) {
-                               free_page((unsigned long) bnode);
-                               break;
-                       }
+               raw_spin_lock_irqsave(&krcp->lock, flags);
+               pushed = put_cached_bnode(krcp, bnode);
+               raw_spin_unlock_irqrestore(&krcp->lock, flags);
+
+               if (!pushed) {
+                       free_page((unsigned long) bnode);
+                       break;
                }
        }
 
@@ -3338,7 +3357,7 @@ void kvfree_call_rcu(struct rcu_head *head, rcu_callback_t func)
 
        // Set timer to drain after KFREE_DRAIN_JIFFIES.
        if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING)
-               schedule_delayed_work(&krcp->monitor_work, KFREE_DRAIN_JIFFIES);
+               schedule_delayed_monitor_work(krcp);
 
 unlock_return:
        krc_this_cpu_unlock(krcp, flags);
@@ -3371,7 +3390,7 @@ kfree_rcu_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
                atomic_set(&krcp->backoff_page_cache_fill, 1);
        }
 
-       return count;
+       return count == 0 ? SHRINK_EMPTY : count;
 }
 
 static unsigned long
@@ -3414,49 +3433,27 @@ void __init kfree_rcu_scheduler_running(void)
 
                raw_spin_lock_irqsave(&krcp->lock, flags);
                if (need_offload_krc(krcp))
-                       schedule_delayed_work_on(cpu, &krcp->monitor_work, KFREE_DRAIN_JIFFIES);
+                       schedule_delayed_monitor_work(krcp);
                raw_spin_unlock_irqrestore(&krcp->lock, flags);
        }
 }
 
 /*
  * During early boot, any blocking grace-period wait automatically
- * implies a grace period.  Later on, this is never the case for PREEMPTION.
+ * implies a grace period.
  *
- * However, because a context switch is a grace period for !PREEMPTION, any
- * blocking grace-period wait automatically implies a grace period if
- * there is only one CPU online at any point time during execution of
- * either synchronize_rcu() or synchronize_rcu_expedited().  It is OK to
- * occasionally incorrectly indicate that there are multiple CPUs online
- * when there was in fact only one the whole time, as this just adds some
- * overhead: RCU still operates correctly.
+ * Later on, this could in theory be the case for kernels built with
+ * CONFIG_SMP=y && CONFIG_PREEMPTION=y running on a single CPU, but this
+ * is not a common case.  Furthermore, this optimization would cause
+ * the rcu_gp_oldstate structure to expand by 50%, so this potential
+ * grace-period optimization is ignored once the scheduler is running.
  */
 static int rcu_blocking_is_gp(void)
 {
-       int ret;
-
-       // Invoking preempt_model_*() too early gets a splat.
-       if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE ||
-           preempt_model_full() || preempt_model_rt())
-               return rcu_scheduler_active == RCU_SCHEDULER_INACTIVE;
+       if (rcu_scheduler_active != RCU_SCHEDULER_INACTIVE)
+               return false;
        might_sleep();  /* Check for RCU read-side critical section. */
-       preempt_disable();
-       /*
-        * If the rcu_state.n_online_cpus counter is equal to one,
-        * there is only one CPU, and that CPU sees all prior accesses
-        * made by any CPU that was online at the time of its access.
-        * Furthermore, if this counter is equal to one, its value cannot
-        * change until after the preempt_enable() below.
-        *
-        * Furthermore, if rcu_state.n_online_cpus is equal to one here,
-        * all later CPUs (both this one and any that come online later
-        * on) are guaranteed to see all accesses prior to this point
-        * in the code, without the need for additional memory barriers.
-        * Those memory barriers are provided by CPU-hotplug code.
-        */
-       ret = READ_ONCE(rcu_state.n_online_cpus) <= 1;
-       preempt_enable();
-       return ret;
+       return true;
 }
 
 /**
@@ -3499,30 +3496,59 @@ static int rcu_blocking_is_gp(void)
  */
 void synchronize_rcu(void)
 {
+       unsigned long flags;
+       struct rcu_node *rnp;
+
        RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) ||
                         lock_is_held(&rcu_lock_map) ||
                         lock_is_held(&rcu_sched_lock_map),
                         "Illegal synchronize_rcu() in RCU read-side critical section");
-       if (rcu_blocking_is_gp()) {
-               // Note well that this code runs with !PREEMPT && !SMP.
-               // In addition, all code that advances grace periods runs at
-               // process level.  Therefore, this normal GP overlaps with
-               // other normal GPs only by being fully nested within them,
-               // which allows reuse of ->gp_seq_polled_snap.
-               rcu_poll_gp_seq_start_unlocked(&rcu_state.gp_seq_polled_snap);
-               rcu_poll_gp_seq_end_unlocked(&rcu_state.gp_seq_polled_snap);
-               if (rcu_init_invoked())
-                       cond_resched_tasks_rcu_qs();
-               return;  // Context allows vacuous grace periods.
+       if (!rcu_blocking_is_gp()) {
+               if (rcu_gp_is_expedited())
+                       synchronize_rcu_expedited();
+               else
+                       wait_rcu_gp(call_rcu);
+               return;
        }
-       if (rcu_gp_is_expedited())
-               synchronize_rcu_expedited();
-       else
-               wait_rcu_gp(call_rcu);
+
+       // Context allows vacuous grace periods.
+       // Note well that this code runs with !PREEMPT && !SMP.
+       // In addition, all code that advances grace periods runs at
+       // process level.  Therefore, this normal GP overlaps with other
+       // normal GPs only by being fully nested within them, which allows
+       // reuse of ->gp_seq_polled_snap.
+       rcu_poll_gp_seq_start_unlocked(&rcu_state.gp_seq_polled_snap);
+       rcu_poll_gp_seq_end_unlocked(&rcu_state.gp_seq_polled_snap);
+
+       // Update the normal grace-period counters to record
+       // this grace period, but only those used by the boot CPU.
+       // The rcu_scheduler_starting() will take care of the rest of
+       // these counters.
+       local_irq_save(flags);
+       WARN_ON_ONCE(num_online_cpus() > 1);
+       rcu_state.gp_seq += (1 << RCU_SEQ_CTR_SHIFT);
+       for (rnp = this_cpu_ptr(&rcu_data)->mynode; rnp; rnp = rnp->parent)
+               rnp->gp_seq_needed = rnp->gp_seq = rcu_state.gp_seq;
+       local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
 /**
+ * get_completed_synchronize_rcu_full - Return a full pre-completed polled state cookie
+ * @rgosp: Place to put state cookie
+ *
+ * Stores into @rgosp a value that will always be treated by functions
+ * like poll_state_synchronize_rcu_full() as a cookie whose grace period
+ * has already completed.
+ */
+void get_completed_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       rgosp->rgos_norm = RCU_GET_STATE_COMPLETED;
+       rgosp->rgos_exp = RCU_GET_STATE_COMPLETED;
+}
+EXPORT_SYMBOL_GPL(get_completed_synchronize_rcu_full);
+
+/**
  * get_state_synchronize_rcu - Snapshot current RCU state
  *
  * Returns a cookie that is used by a later call to cond_synchronize_rcu()
@@ -3541,21 +3567,42 @@ unsigned long get_state_synchronize_rcu(void)
 EXPORT_SYMBOL_GPL(get_state_synchronize_rcu);
 
 /**
- * start_poll_synchronize_rcu - Snapshot and start RCU grace period
+ * get_state_synchronize_rcu_full - Snapshot RCU state, both normal and expedited
+ * @rgosp: location to place combined normal/expedited grace-period state
  *
- * Returns a cookie that is used by a later call to cond_synchronize_rcu()
- * or poll_state_synchronize_rcu() to determine whether or not a full
- * grace period has elapsed in the meantime.  If the needed grace period
- * is not already slated to start, notifies RCU core of the need for that
- * grace period.
+ * Places the normal and expedited grace-period states in @rgosp.  This
+ * state value can be passed to a later call to cond_synchronize_rcu_full()
+ * or poll_state_synchronize_rcu_full() to determine whether or not a
+ * grace period (whether normal or expedited) has elapsed in the meantime.
+ * The rcu_gp_oldstate structure takes up twice the memory of an unsigned
+ * long, but is guaranteed to see all grace periods.  In contrast, the
+ * combined state occupies less memory, but can sometimes fail to take
+ * grace periods into account.
  *
- * Interrupts must be enabled for the case where it is necessary to awaken
- * the grace-period kthread.
+ * This does not guarantee that the needed grace period will actually
+ * start.
  */
-unsigned long start_poll_synchronize_rcu(void)
+void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       struct rcu_node *rnp = rcu_get_root();
+
+       /*
+        * Any prior manipulation of RCU-protected data must happen
+        * before the loads from ->gp_seq and ->expedited_sequence.
+        */
+       smp_mb();  /* ^^^ */
+       rgosp->rgos_norm = rcu_seq_snap(&rnp->gp_seq);
+       rgosp->rgos_exp = rcu_seq_snap(&rcu_state.expedited_sequence);
+}
+EXPORT_SYMBOL_GPL(get_state_synchronize_rcu_full);
+
+/*
+ * Helper function for start_poll_synchronize_rcu() and
+ * start_poll_synchronize_rcu_full().
+ */
+static void start_poll_synchronize_rcu_common(void)
 {
        unsigned long flags;
-       unsigned long gp_seq = get_state_synchronize_rcu();
        bool needwake;
        struct rcu_data *rdp;
        struct rcu_node *rnp;
@@ -3575,17 +3622,57 @@ unsigned long start_poll_synchronize_rcu(void)
        raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        if (needwake)
                rcu_gp_kthread_wake();
+}
+
+/**
+ * start_poll_synchronize_rcu - Snapshot and start RCU grace period
+ *
+ * Returns a cookie that is used by a later call to cond_synchronize_rcu()
+ * or poll_state_synchronize_rcu() to determine whether or not a full
+ * grace period has elapsed in the meantime.  If the needed grace period
+ * is not already slated to start, notifies RCU core of the need for that
+ * grace period.
+ *
+ * Interrupts must be enabled for the case where it is necessary to awaken
+ * the grace-period kthread.
+ */
+unsigned long start_poll_synchronize_rcu(void)
+{
+       unsigned long gp_seq = get_state_synchronize_rcu();
+
+       start_poll_synchronize_rcu_common();
        return gp_seq;
 }
 EXPORT_SYMBOL_GPL(start_poll_synchronize_rcu);
 
 /**
- * poll_state_synchronize_rcu - Conditionally wait for an RCU grace period
+ * start_poll_synchronize_rcu_full - Take a full snapshot and start RCU grace period
+ * @rgosp: value from get_state_synchronize_rcu_full() or start_poll_synchronize_rcu_full()
  *
+ * Places the normal and expedited grace-period states in *@rgos.  This
+ * state value can be passed to a later call to cond_synchronize_rcu_full()
+ * or poll_state_synchronize_rcu_full() to determine whether or not a
+ * grace period (whether normal or expedited) has elapsed in the meantime.
+ * If the needed grace period is not already slated to start, notifies
+ * RCU core of the need for that grace period.
+ *
+ * Interrupts must be enabled for the case where it is necessary to awaken
+ * the grace-period kthread.
+ */
+void start_poll_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       get_state_synchronize_rcu_full(rgosp);
+
+       start_poll_synchronize_rcu_common();
+}
+EXPORT_SYMBOL_GPL(start_poll_synchronize_rcu_full);
+
+/**
+ * poll_state_synchronize_rcu - Has the specified RCU grace period completed?
  * @oldstate: value from get_state_synchronize_rcu() or start_poll_synchronize_rcu()
  *
  * If a full RCU grace period has elapsed since the earlier call from
- * which oldstate was obtained, return @true, otherwise return @false.
+ * which @oldstate was obtained, return @true, otherwise return @false.
  * If @false is returned, it is the caller's responsibility to invoke this
  * function later on until it does return @true.  Alternatively, the caller
  * can explicitly wait for a grace period, for example, by passing @oldstate
@@ -3594,10 +3681,11 @@ EXPORT_SYMBOL_GPL(start_poll_synchronize_rcu);
  * Yes, this function does not take counter wrap into account.
  * But counter wrap is harmless.  If the counter wraps, we have waited for
  * more than a billion grace periods (and way more on a 64-bit system!).
- * Those needing to keep oldstate values for very long time periods
- * (many hours even on 32-bit systems) should check them occasionally
- * and either refresh them or set a flag indicating that the grace period
- * has completed.
+ * Those needing to keep old state values for very long time periods
+ * (many hours even on 32-bit systems) should check them occasionally and
+ * either refresh them or set a flag indicating that the grace period has
+ * completed.  Alternatively, they can use get_completed_synchronize_rcu()
+ * to get a guaranteed-completed grace-period state.
  *
  * This function provides the same memory-ordering guarantees that
  * would be provided by a synchronize_rcu() that was invoked at the call
@@ -3616,8 +3704,56 @@ bool poll_state_synchronize_rcu(unsigned long oldstate)
 EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu);
 
 /**
- * cond_synchronize_rcu - Conditionally wait for an RCU grace period
+ * poll_state_synchronize_rcu_full - Has the specified RCU grace period completed?
+ * @rgosp: value from get_state_synchronize_rcu_full() or start_poll_synchronize_rcu_full()
  *
+ * If a full RCU grace period has elapsed since the earlier call from
+ * which *rgosp was obtained, return @true, otherwise return @false.
+ * If @false is returned, it is the caller's responsibility to invoke this
+ * function later on until it does return @true.  Alternatively, the caller
+ * can explicitly wait for a grace period, for example, by passing @rgosp
+ * to cond_synchronize_rcu() or by directly invoking synchronize_rcu().
+ *
+ * Yes, this function does not take counter wrap into account.
+ * But counter wrap is harmless.  If the counter wraps, we have waited
+ * for more than a billion grace periods (and way more on a 64-bit
+ * system!).  Those needing to keep rcu_gp_oldstate values for very
+ * long time periods (many hours even on 32-bit systems) should check
+ * them occasionally and either refresh them or set a flag indicating
+ * that the grace period has completed.  Alternatively, they can use
+ * get_completed_synchronize_rcu_full() to get a guaranteed-completed
+ * grace-period state.
+ *
+ * This function provides the same memory-ordering guarantees that would
+ * be provided by a synchronize_rcu() that was invoked at the call to
+ * the function that provided @rgosp, and that returned at the end of this
+ * function.  And this guarantee requires that the root rcu_node structure's
+ * ->gp_seq field be checked instead of that of the rcu_state structure.
+ * The problem is that the just-ending grace-period's callbacks can be
+ * invoked between the time that the root rcu_node structure's ->gp_seq
+ * field is updated and the time that the rcu_state structure's ->gp_seq
+ * field is updated.  Therefore, if a single synchronize_rcu() is to
+ * cause a subsequent poll_state_synchronize_rcu_full() to return @true,
+ * then the root rcu_node structure is the one that needs to be polled.
+ */
+bool poll_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       struct rcu_node *rnp = rcu_get_root();
+
+       smp_mb(); // Order against root rcu_node structure grace-period cleanup.
+       if (rgosp->rgos_norm == RCU_GET_STATE_COMPLETED ||
+           rcu_seq_done_exact(&rnp->gp_seq, rgosp->rgos_norm) ||
+           rgosp->rgos_exp == RCU_GET_STATE_COMPLETED ||
+           rcu_seq_done_exact(&rcu_state.expedited_sequence, rgosp->rgos_exp)) {
+               smp_mb(); /* Ensure GP ends before subsequent accesses. */
+               return true;
+       }
+       return false;
+}
+EXPORT_SYMBOL_GPL(poll_state_synchronize_rcu_full);
+
+/**
+ * cond_synchronize_rcu - Conditionally wait for an RCU grace period
  * @oldstate: value from get_state_synchronize_rcu(), start_poll_synchronize_rcu(), or start_poll_synchronize_rcu_expedited()
  *
  * If a full RCU grace period has elapsed since the earlier call to
@@ -3641,6 +3777,33 @@ void cond_synchronize_rcu(unsigned long oldstate)
 }
 EXPORT_SYMBOL_GPL(cond_synchronize_rcu);
 
+/**
+ * cond_synchronize_rcu_full - Conditionally wait for an RCU grace period
+ * @rgosp: value from get_state_synchronize_rcu_full(), start_poll_synchronize_rcu_full(), or start_poll_synchronize_rcu_expedited_full()
+ *
+ * If a full RCU grace period has elapsed since the call to
+ * get_state_synchronize_rcu_full(), start_poll_synchronize_rcu_full(),
+ * or start_poll_synchronize_rcu_expedited_full() from which @rgosp was
+ * obtained, just return.  Otherwise, invoke synchronize_rcu() to wait
+ * for a full grace period.
+ *
+ * Yes, this function does not take counter wrap into account.
+ * But counter wrap is harmless.  If the counter wraps, we have waited for
+ * more than 2 billion grace periods (and way more on a 64-bit system!),
+ * so waiting for a couple of additional grace periods should be just fine.
+ *
+ * This function provides the same memory-ordering guarantees that
+ * would be provided by a synchronize_rcu() that was invoked at the call
+ * to the function that provided @rgosp and that returned at the end of
+ * this function.
+ */
+void cond_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)
+{
+       if (!poll_state_synchronize_rcu_full(rgosp))
+               synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(cond_synchronize_rcu_full);
+
 /*
  * Check to see if there is any immediate RCU-related work to be done by
  * the current CPU, returning 1 if so and zero otherwise.  The checks are
@@ -4312,9 +4475,20 @@ early_initcall(rcu_spawn_gp_kthread);
  */
 void rcu_scheduler_starting(void)
 {
+       unsigned long flags;
+       struct rcu_node *rnp;
+
        WARN_ON(num_online_cpus() != 1);
        WARN_ON(nr_context_switches() > 0);
        rcu_test_sync_prims();
+
+       // Fix up the ->gp_seq counters.
+       local_irq_save(flags);
+       rcu_for_each_node_breadth_first(rnp)
+               rnp->gp_seq_needed = rnp->gp_seq = rcu_state.gp_seq;
+       local_irq_restore(flags);
+
+       // Switch out of early boot mode.
        rcu_scheduler_active = RCU_SCHEDULER_INIT;
        rcu_test_sync_prims();
 }
index be66758..18e9b4c 100644 (file)
@@ -828,11 +828,13 @@ static void rcu_exp_handler(void *unused)
 {
        struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
        struct rcu_node *rnp = rdp->mynode;
+       bool preempt_bh_enabled = !(preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK));
 
        if (!(READ_ONCE(rnp->expmask) & rdp->grpmask) ||
            __this_cpu_read(rcu_data.cpu_no_qs.b.exp))
                return;
-       if (rcu_is_cpu_rrupt_from_idle()) {
+       if (rcu_is_cpu_rrupt_from_idle() ||
+           (IS_ENABLED(CONFIG_PREEMPT_COUNT) && preempt_bh_enabled)) {
                rcu_report_exp_rdp(this_cpu_ptr(&rcu_data));
                return;
        }
@@ -906,6 +908,7 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp)
 void synchronize_rcu_expedited(void)
 {
        bool boottime = (rcu_scheduler_active == RCU_SCHEDULER_INIT);
+       unsigned long flags;
        struct rcu_exp_work rew;
        struct rcu_node *rnp;
        unsigned long s;
@@ -924,8 +927,11 @@ void synchronize_rcu_expedited(void)
                // them, which allows reuse of ->gp_seq_polled_exp_snap.
                rcu_poll_gp_seq_start_unlocked(&rcu_state.gp_seq_polled_exp_snap);
                rcu_poll_gp_seq_end_unlocked(&rcu_state.gp_seq_polled_exp_snap);
-               if (rcu_init_invoked())
-                       cond_resched();
+
+               local_irq_save(flags);
+               WARN_ON_ONCE(num_online_cpus() > 1);
+               rcu_state.expedited_sequence += (1 << RCU_SEQ_CTR_SHIFT);
+               local_irq_restore(flags);
                return;  // Context allows vacuous grace periods.
        }
 
@@ -1028,6 +1034,24 @@ unsigned long start_poll_synchronize_rcu_expedited(void)
 EXPORT_SYMBOL_GPL(start_poll_synchronize_rcu_expedited);
 
 /**
+ * start_poll_synchronize_rcu_expedited_full - Take a full snapshot and start expedited grace period
+ * @rgosp: Place to put snapshot of grace-period state
+ *
+ * Places the normal and expedited grace-period states in rgosp.  This
+ * state value can be passed to a later call to cond_synchronize_rcu_full()
+ * or poll_state_synchronize_rcu_full() to determine whether or not a
+ * grace period (whether normal or expedited) has elapsed in the meantime.
+ * If the needed expedited grace period is not already slated to start,
+ * initiates that grace period.
+ */
+void start_poll_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp)
+{
+       get_state_synchronize_rcu_full(rgosp);
+       (void)start_poll_synchronize_rcu_expedited();
+}
+EXPORT_SYMBOL_GPL(start_poll_synchronize_rcu_expedited_full);
+
+/**
  * cond_synchronize_rcu_expedited - Conditionally wait for an expedited RCU grace period
  *
  * @oldstate: value from get_state_synchronize_rcu(), start_poll_synchronize_rcu(), or start_poll_synchronize_rcu_expedited()
@@ -1053,3 +1077,30 @@ void cond_synchronize_rcu_expedited(unsigned long oldstate)
                synchronize_rcu_expedited();
 }
 EXPORT_SYMBOL_GPL(cond_synchronize_rcu_expedited);
+
+/**
+ * cond_synchronize_rcu_expedited_full - Conditionally wait for an expedited RCU grace period
+ * @rgosp: value from get_state_synchronize_rcu_full(), start_poll_synchronize_rcu_full(), or start_poll_synchronize_rcu_expedited_full()
+ *
+ * If a full RCU grace period has elapsed since the call to
+ * get_state_synchronize_rcu_full(), start_poll_synchronize_rcu_full(),
+ * or start_poll_synchronize_rcu_expedited_full() from which @rgosp was
+ * obtained, just return.  Otherwise, invoke synchronize_rcu_expedited()
+ * to wait for a full grace period.
+ *
+ * Yes, this function does not take counter wrap into account.
+ * But counter wrap is harmless.  If the counter wraps, we have waited for
+ * more than 2 billion grace periods (and way more on a 64-bit system!),
+ * so waiting for a couple of additional grace periods should be just fine.
+ *
+ * This function provides the same memory-ordering guarantees that
+ * would be provided by a synchronize_rcu() that was invoked at the call
+ * to the function that provided @rgosp and that returned at the end of
+ * this function.
+ */
+void cond_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp)
+{
+       if (!poll_state_synchronize_rcu_full(rgosp))
+               synchronize_rcu_expedited();
+}
+EXPORT_SYMBOL_GPL(cond_synchronize_rcu_expedited_full);
index a8f574d..0a5f0ef 100644 (file)
@@ -1111,7 +1111,7 @@ int rcu_nocb_cpu_deoffload(int cpu)
                        if (!ret)
                                cpumask_clear_cpu(cpu, rcu_nocb_mask);
                } else {
-                       pr_info("NOCB: Can't CB-deoffload an offline CPU\n");
+                       pr_info("NOCB: Cannot CB-deoffload offline CPU %d\n", rdp->cpu);
                        ret = -EINVAL;
                }
        }
@@ -1196,7 +1196,7 @@ int rcu_nocb_cpu_offload(int cpu)
                        if (!ret)
                                cpumask_set_cpu(cpu, rcu_nocb_mask);
                } else {
-                       pr_info("NOCB: Can't CB-offload an offline CPU\n");
+                       pr_info("NOCB: Cannot CB-offload offline CPU %d\n", rdp->cpu);
                        ret = -EINVAL;
                }
        }
@@ -1452,8 +1452,8 @@ static void show_rcu_nocb_gp_state(struct rcu_data *rdp)
                (long)rdp->nocb_gp_seq,
                rnp->grplo, rnp->grphi, READ_ONCE(rdp->nocb_gp_loops),
                rdp->nocb_gp_kthread ? task_state_to_char(rdp->nocb_gp_kthread) : '.',
-               rdp->nocb_cb_kthread ? (int)task_cpu(rdp->nocb_gp_kthread) : -1,
-               show_rcu_should_be_on_cpu(rdp->nocb_cb_kthread));
+               rdp->nocb_gp_kthread ? (int)task_cpu(rdp->nocb_gp_kthread) : -1,
+               show_rcu_should_be_on_cpu(rdp->nocb_gp_kthread));
 }
 
 /* Dump out nocb kthread state for the specified rcu_data structure. */
@@ -1497,7 +1497,7 @@ static void show_rcu_nocb_state(struct rcu_data *rdp)
                ".B"[!!rcu_cblist_n_cbs(&rdp->nocb_bypass)],
                rcu_segcblist_n_cbs(&rdp->cblist),
                rdp->nocb_cb_kthread ? task_state_to_char(rdp->nocb_cb_kthread) : '.',
-               rdp->nocb_cb_kthread ? (int)task_cpu(rdp->nocb_gp_kthread) : -1,
+               rdp->nocb_cb_kthread ? (int)task_cpu(rdp->nocb_cb_kthread) : -1,
                show_rcu_should_be_on_cpu(rdp->nocb_cb_kthread));
 
        /* It is OK for GP kthreads to have GP state. */
index 438ecae..e3142ee 100644 (file)
@@ -641,7 +641,8 @@ static void rcu_read_unlock_special(struct task_struct *t)
 
                expboost = (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_tasks)) ||
                           (rdp->grpmask & READ_ONCE(rnp->expmask)) ||
-                          IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) ||
+                          (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) &&
+                          ((rdp->grpmask & READ_ONCE(rnp->qsmask)) || t->rcu_blocked_node)) ||
                           (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled &&
                            t->rcu_blocked_node);
                // Need to defer quiescent state until everything is enabled.
@@ -718,9 +719,6 @@ static void rcu_flavor_sched_clock_irq(int user)
        struct task_struct *t = current;
 
        lockdep_assert_irqs_disabled();
-       if (user || rcu_is_cpu_rrupt_from_idle()) {
-               rcu_note_voluntary_context_switch(current);
-       }
        if (rcu_preempt_depth() > 0 ||
            (preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK))) {
                /* No QS, force context switch if deferred. */
@@ -824,6 +822,7 @@ void rcu_read_unlock_strict(void)
        if (irqs_disabled() || preempt_count() || !rcu_state.gp_kthread)
                return;
        rdp = this_cpu_ptr(&rcu_data);
+       rdp->cpu_no_qs.b.norm = false;
        rcu_report_qs_rdp(rdp);
        udelay(rcu_unlock_delay);
 }
@@ -869,7 +868,7 @@ void rcu_all_qs(void)
 
        if (!raw_cpu_read(rcu_data.rcu_urgent_qs))
                return;
-       preempt_disable();
+       preempt_disable();  // For CONFIG_PREEMPT_COUNT=y kernels
        /* Load rcu_urgent_qs before other flags. */
        if (!smp_load_acquire(this_cpu_ptr(&rcu_data.rcu_urgent_qs))) {
                preempt_enable();
@@ -931,10 +930,13 @@ static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t)
        return false;
 }
 
-// Except that we do need to respond to a request by an expedited grace
-// period for a quiescent state from this CPU.  Note that requests from
-// tasks are handled when removing the task from the blocked-tasks list
-// below.
+// Except that we do need to respond to a request by an expedited
+// grace period for a quiescent state from this CPU.  Note that in
+// non-preemptible kernels, there can be no context switches within RCU
+// read-side critical sections, which in turn means that the leaf rcu_node
+// structure's blocked-tasks list is always empty.  is therefore no need to
+// actually check it.  Instead, a quiescent state from this CPU suffices,
+// and this function is only called from such a quiescent state.
 notrace void rcu_preempt_deferred_qs(struct task_struct *t)
 {
        struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
@@ -972,7 +974,6 @@ static void rcu_flavor_sched_clock_irq(int user)
                 * neither access nor modify, at least not while the
                 * corresponding CPU is online.
                 */
-
                rcu_qs();
        }
 }
@@ -1238,8 +1239,11 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
                    cpu != outgoingcpu)
                        cpumask_set_cpu(cpu, cm);
        cpumask_and(cm, cm, housekeeping_cpumask(HK_TYPE_RCU));
-       if (cpumask_empty(cm))
+       if (cpumask_empty(cm)) {
                cpumask_copy(cm, housekeeping_cpumask(HK_TYPE_RCU));
+               if (outgoingcpu >= 0)
+                       cpumask_clear_cpu(outgoingcpu, cm);
+       }
        set_cpus_allowed_ptr(t, cm);
        mutex_unlock(&rnp->boost_kthread_mutex);
        free_cpumask_var(cm);
index c3fbbcc..5653560 100644 (file)
@@ -368,7 +368,7 @@ static void rcu_dump_cpu_stacks(void)
                        if (rnp->qsmask & leaf_node_cpu_bit(rnp, cpu)) {
                                if (cpu_is_offline(cpu))
                                        pr_err("Offline CPU %d blocking current GP.\n", cpu);
-                               else if (!trigger_single_cpu_backtrace(cpu))
+                               else
                                        dump_cpu_task(cpu);
                        }
                raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
@@ -511,8 +511,7 @@ static void rcu_check_gp_kthread_starvation(void)
                                        pr_err("RCU GP kthread last ran on offline CPU %d.\n", cpu);
                                } else  {
                                        pr_err("Stack dump where RCU GP kthread last ran:\n");
-                                       if (!trigger_single_cpu_backtrace(cpu))
-                                               dump_cpu_task(cpu);
+                                       dump_cpu_task(cpu);
                                }
                        }
                        wake_up_process(gpk);
index ee28253..60fdc0f 100644 (file)
@@ -73,6 +73,7 @@
 
 #include <uapi/linux/sched/types.h>
 
+#include <asm/irq_regs.h>
 #include <asm/switch_to.h>
 #include <asm/tlb.h>
 
@@ -11183,6 +11184,19 @@ struct cgroup_subsys cpu_cgrp_subsys = {
 
 void dump_cpu_task(int cpu)
 {
+       if (cpu == smp_processor_id() && in_hardirq()) {
+               struct pt_regs *regs;
+
+               regs = get_irq_regs();
+               if (regs) {
+                       show_regs(regs);
+                       return;
+               }
+       }
+
+       if (trigger_single_cpu_backtrace(cpu))
+               return;
+
        pr_info("Task dump for CPU %d:\n", cpu);
        sched_show_task(cpu_curr(cpu));
 }
index 1207c78..9161d11 100644 (file)
@@ -25,6 +25,9 @@ struct sugov_policy {
        unsigned int            next_freq;
        unsigned int            cached_raw_freq;
 
+       /* max CPU capacity, which is equal for all CPUs in freq. domain */
+       unsigned long           max;
+
        /* The next fields are only needed if fast switch cannot be used: */
        struct                  irq_work irq_work;
        struct                  kthread_work work;
@@ -48,7 +51,6 @@ struct sugov_cpu {
 
        unsigned long           util;
        unsigned long           bw_dl;
-       unsigned long           max;
 
        /* The field below is for single-CPU policies only: */
 #ifdef CONFIG_NO_HZ_COMMON
@@ -158,7 +160,6 @@ static void sugov_get_util(struct sugov_cpu *sg_cpu)
 {
        struct rq *rq = cpu_rq(sg_cpu->cpu);
 
-       sg_cpu->max = arch_scale_cpu_capacity(sg_cpu->cpu);
        sg_cpu->bw_dl = cpu_bw_dl(rq);
        sg_cpu->util = effective_cpu_util(sg_cpu->cpu, cpu_util_cfs(sg_cpu->cpu),
                                          FREQUENCY_UTIL, NULL);
@@ -253,6 +254,7 @@ static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
  */
 static void sugov_iowait_apply(struct sugov_cpu *sg_cpu, u64 time)
 {
+       struct sugov_policy *sg_policy = sg_cpu->sg_policy;
        unsigned long boost;
 
        /* No boost currently required */
@@ -280,7 +282,8 @@ static void sugov_iowait_apply(struct sugov_cpu *sg_cpu, u64 time)
         * sg_cpu->util is already in capacity scale; convert iowait_boost
         * into the same scale so we can compare.
         */
-       boost = (sg_cpu->iowait_boost * sg_cpu->max) >> SCHED_CAPACITY_SHIFT;
+       boost = sg_cpu->iowait_boost * sg_policy->max;
+       boost >>= SCHED_CAPACITY_SHIFT;
        boost = uclamp_rq_util_with(cpu_rq(sg_cpu->cpu), boost, NULL);
        if (sg_cpu->util < boost)
                sg_cpu->util = boost;
@@ -337,7 +340,7 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
        if (!sugov_update_single_common(sg_cpu, time, flags))
                return;
 
-       next_f = get_next_freq(sg_policy, sg_cpu->util, sg_cpu->max);
+       next_f = get_next_freq(sg_policy, sg_cpu->util, sg_policy->max);
        /*
         * Do not reduce the frequency if the CPU has not been idle
         * recently, as the reduction is likely to be premature then.
@@ -373,6 +376,7 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
                                     unsigned int flags)
 {
        struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
+       struct sugov_policy *sg_policy = sg_cpu->sg_policy;
        unsigned long prev_util = sg_cpu->util;
 
        /*
@@ -399,7 +403,8 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
                sg_cpu->util = prev_util;
 
        cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
-                                  map_util_perf(sg_cpu->util), sg_cpu->max);
+                                  map_util_perf(sg_cpu->util),
+                                  sg_policy->max);
 
        sg_cpu->sg_policy->last_freq_update_time = time;
 }
@@ -408,25 +413,19 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
 {
        struct sugov_policy *sg_policy = sg_cpu->sg_policy;
        struct cpufreq_policy *policy = sg_policy->policy;
-       unsigned long util = 0, max = 1;
+       unsigned long util = 0;
        unsigned int j;
 
        for_each_cpu(j, policy->cpus) {
                struct sugov_cpu *j_sg_cpu = &per_cpu(sugov_cpu, j);
-               unsigned long j_util, j_max;
 
                sugov_get_util(j_sg_cpu);
                sugov_iowait_apply(j_sg_cpu, time);
-               j_util = j_sg_cpu->util;
-               j_max = j_sg_cpu->max;
 
-               if (j_util * max > j_max * util) {
-                       util = j_util;
-                       max = j_max;
-               }
+               util = max(j_sg_cpu->util, util);
        }
 
-       return get_next_freq(sg_policy, util, max);
+       return get_next_freq(sg_policy, util, sg_policy->max);
 }
 
 static void
@@ -752,7 +751,7 @@ static int sugov_start(struct cpufreq_policy *policy)
 {
        struct sugov_policy *sg_policy = policy->governor_data;
        void (*uu)(struct update_util_data *data, u64 time, unsigned int flags);
-       unsigned int cpu;
+       unsigned int cpu = cpumask_first(policy->cpus);
 
        sg_policy->freq_update_delay_ns = sg_policy->tunables->rate_limit_us * NSEC_PER_USEC;
        sg_policy->last_freq_update_time        = 0;
@@ -760,6 +759,7 @@ static int sugov_start(struct cpufreq_policy *policy)
        sg_policy->work_in_progress             = false;
        sg_policy->limits_changed               = false;
        sg_policy->cached_raw_freq              = 0;
+       sg_policy->max                          = arch_scale_cpu_capacity(cpu);
 
        sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
 
index bb3d63b..667876d 100644 (file)
@@ -416,7 +416,7 @@ void update_sched_domain_debugfs(void)
                char buf[32];
 
                snprintf(buf, sizeof(buf), "cpu%d", cpu);
-               debugfs_remove(debugfs_lookup(buf, sd_dentry));
+               debugfs_lookup_and_remove(buf, sd_dentry);
                d_cpu = debugfs_create_dir(buf, sd_dentry);
 
                i = 0;
index 650810a..e8cdc02 100644 (file)
@@ -370,8 +370,7 @@ static bool csd_lock_wait_toolong(struct __call_single_data *csd, u64 ts0, u64 *
        if (cpu >= 0) {
                if (static_branch_unlikely(&csdlock_debug_extended))
                        csd_lock_print_extended(csd, cpu);
-               if (!trigger_single_cpu_backtrace(cpu))
-                       dump_cpu_task(cpu);
+               dump_cpu_task(cpu);
                if (!cpu_cur_csd) {
                        pr_alert("csd: Re-sending CSD lock (#%d) IPI from CPU#%02d to CPU#%02d\n", *bug_id, raw_smp_processor_id(), cpu);
                        arch_send_call_function_single_ipi(cpu);
index c1c47e2..dacc37b 100644 (file)
@@ -27,7 +27,7 @@ struct automaton_wip {
        bool final_states[state_max_wip];
 };
 
-struct automaton_wip automaton_wip = {
+static struct automaton_wip automaton_wip = {
        .state_names = {
                "preemptive",
                "non_preemptive"
index d1afe55..118e576 100644 (file)
@@ -27,7 +27,7 @@ struct automaton_wwnr {
        bool final_states[state_max_wwnr];
 };
 
-struct automaton_wwnr automaton_wwnr = {
+static struct automaton_wwnr automaton_wwnr = {
        .state_names = {
                "not_running",
                "running"
index b698d05..d65f6c2 100644 (file)
@@ -24,13 +24,13 @@ static struct rv_reactor rv_panic = {
        .react = rv_panic_reaction
 };
 
-static int register_react_panic(void)
+static int __init register_react_panic(void)
 {
        rv_register_reactor(&rv_panic);
        return 0;
 }
 
-static void unregister_react_panic(void)
+static void __exit unregister_react_panic(void)
 {
        rv_unregister_reactor(&rv_panic);
 }
index 31899f9..4b6b710 100644 (file)
@@ -23,13 +23,13 @@ static struct rv_reactor rv_printk = {
        .react = rv_printk_reaction
 };
 
-static int register_react_printk(void)
+static int __init register_react_printk(void)
 {
        rv_register_reactor(&rv_printk);
        return 0;
 }
 
-static void unregister_react_printk(void)
+static void __exit unregister_react_printk(void)
 {
        rv_unregister_reactor(&rv_printk);
 }
index cb866c3..918730d 100644 (file)
@@ -142,7 +142,8 @@ static bool check_user_trigger(struct trace_event_file *file)
 {
        struct event_trigger_data *data;
 
-       list_for_each_entry_rcu(data, &file->triggers, list) {
+       list_for_each_entry_rcu(data, &file->triggers, list,
+                               lockdep_is_held(&event_mutex)) {
                if (data->flags & EVENT_TRIGGER_FL_PROBE)
                        continue;
                return true;
index 95b58bd..1e130da 100644 (file)
@@ -95,14 +95,14 @@ __visible void trace_hardirqs_on_caller(unsigned long caller_addr)
        }
 
        lockdep_hardirqs_on_prepare();
-       lockdep_hardirqs_on(CALLER_ADDR0);
+       lockdep_hardirqs_on(caller_addr);
 }
 EXPORT_SYMBOL(trace_hardirqs_on_caller);
 NOKPROBE_SYMBOL(trace_hardirqs_on_caller);
 
 __visible void trace_hardirqs_off_caller(unsigned long caller_addr)
 {
-       lockdep_hardirqs_off(CALLER_ADDR0);
+       lockdep_hardirqs_off(caller_addr);
 
        if (!this_cpu_read(tracing_irq_cpu)) {
                this_cpu_write(tracing_irq_cpu, 1);
index 64ea283..ef42c1a 100644 (file)
@@ -571,7 +571,8 @@ static void for_each_tracepoint_range(
 bool trace_module_has_bad_taint(struct module *mod)
 {
        return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP) |
-                              (1 << TAINT_UNSIGNED_MODULE));
+                              (1 << TAINT_UNSIGNED_MODULE) |
+                              (1 << TAINT_TEST));
 }
 
 static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);
@@ -647,7 +648,7 @@ static int tracepoint_module_coming(struct module *mod)
        /*
         * We skip modules that taint the kernel, especially those with different
         * module headers (for forced load), to make sure we don't cause a crash.
-        * Staging, out-of-tree, and unsigned GPL modules are fine.
+        * Staging, out-of-tree, unsigned GPL, and test modules are fine.
         */
        if (trace_module_has_bad_taint(mod))
                return 0;
index aeea973..39060a5 100644 (file)
@@ -3066,10 +3066,8 @@ static bool __flush_work(struct work_struct *work, bool from_cancel)
        if (WARN_ON(!work->func))
                return false;
 
-       if (!from_cancel) {
-               lock_map_acquire(&work->lockdep_map);
-               lock_map_release(&work->lockdep_map);
-       }
+       lock_map_acquire(&work->lockdep_map);
+       lock_map_release(&work->lockdep_map);
 
        if (start_flush_work(work, &barr, from_cancel)) {
                wait_for_completion(&barr.done);
index bcbe60d..d3e5f36 100644 (file)
@@ -264,8 +264,10 @@ config DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
 config DEBUG_INFO_DWARF4
        bool "Generate DWARF Version 4 debuginfo"
        select DEBUG_INFO
+       depends on !CC_IS_CLANG || (CC_IS_CLANG && (AS_IS_LLVM || (AS_IS_GNU && AS_VERSION >= 23502)))
        help
-         Generate DWARF v4 debug info. This requires gcc 4.5+ and gdb 7.0+.
+         Generate DWARF v4 debug info. This requires gcc 4.5+, binutils 2.35.2
+         if using clang without clang's integrated assembler, and gdb 7.0+.
 
          If you have consumers of DWARF debug info that are not ready for
          newer revisions of DWARF, you may wish to choose this or have your
index 9ff549f..47816af 100644 (file)
@@ -33,7 +33,6 @@ config CRYPTO_ARCH_HAVE_LIB_CHACHA
 
 config CRYPTO_LIB_CHACHA_GENERIC
        tristate
-       select XOR_BLOCKS
        help
          This symbol can be depended upon by arch implementations of the
          ChaCha library interface that require the generic code as a
index cfdf631..4e51466 100644 (file)
@@ -884,6 +884,7 @@ static int dbgfs_rm_context(char *name)
        struct dentry *root, *dir, **new_dirs;
        struct damon_ctx **new_ctxs;
        int i, j;
+       int ret = 0;
 
        if (damon_nr_running_ctxs())
                return -EBUSY;
@@ -898,14 +899,16 @@ static int dbgfs_rm_context(char *name)
 
        new_dirs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_dirs),
                        GFP_KERNEL);
-       if (!new_dirs)
-               return -ENOMEM;
+       if (!new_dirs) {
+               ret = -ENOMEM;
+               goto out_dput;
+       }
 
        new_ctxs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_ctxs),
                        GFP_KERNEL);
        if (!new_ctxs) {
-               kfree(new_dirs);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto out_new_dirs;
        }
 
        for (i = 0, j = 0; i < dbgfs_nr_ctxs; i++) {
@@ -925,7 +928,13 @@ static int dbgfs_rm_context(char *name)
        dbgfs_ctxs = new_ctxs;
        dbgfs_nr_ctxs--;
 
-       return 0;
+       goto out_dput;
+
+out_new_dirs:
+       kfree(new_dirs);
+out_dput:
+       dput(dir);
+       return ret;
 }
 
 static ssize_t dbgfs_rm_context_write(struct file *file,
index 7488e27..bdef968 100644 (file)
@@ -2182,12 +2182,12 @@ static int damon_sysfs_add_target(struct damon_sysfs_target *sys_target,
 
        if (!t)
                return -ENOMEM;
+       damon_add_target(ctx, t);
        if (damon_target_has_pid(ctx)) {
                t->pid = find_get_pid(sys_target->pid);
                if (!t->pid)
                        goto destroy_targets_out;
        }
-       damon_add_target(ctx, t);
        err = damon_sysfs_set_regions(t, sys_target->regions);
        if (err)
                goto destroy_targets_out;
index 1a97610..279e55b 100644 (file)
@@ -125,6 +125,9 @@ void frontswap_init(unsigned type, unsigned long *map)
         * p->frontswap set to something valid to work properly.
         */
        frontswap_map_set(sis, map);
+
+       if (!frontswap_enabled())
+               return;
        frontswap_ops->init(type);
 }
 
index 5abdaf4..00926ab 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2345,8 +2345,28 @@ static void __maybe_unused undo_dev_pagemap(int *nr, int nr_start,
 }
 
 #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL
-static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
-                        unsigned int flags, struct page **pages, int *nr)
+/*
+ * Fast-gup relies on pte change detection to avoid concurrent pgtable
+ * operations.
+ *
+ * To pin the page, fast-gup needs to do below in order:
+ * (1) pin the page (by prefetching pte), then (2) check pte not changed.
+ *
+ * For the rest of pgtable operations where pgtable updates can be racy
+ * with fast-gup, we need to do (1) clear pte, then (2) check whether page
+ * is pinned.
+ *
+ * Above will work for all pte-level operations, including THP split.
+ *
+ * For THP collapse, it's a bit more complicated because fast-gup may be
+ * walking a pgtable page that is being freed (pte is still valid but pmd
+ * can be cleared already).  To avoid race in such condition, we need to
+ * also check pmd here to make sure pmd doesn't change (corresponds to
+ * pmdp_collapse_flush() in the THP collapse code path).
+ */
+static int gup_pte_range(pmd_t pmd, pmd_t *pmdp, unsigned long addr,
+                        unsigned long end, unsigned int flags,
+                        struct page **pages, int *nr)
 {
        struct dev_pagemap *pgmap = NULL;
        int nr_start = *nr, ret = 0;
@@ -2392,7 +2412,8 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
                        goto pte_unmap;
                }
 
-               if (unlikely(pte_val(pte) != pte_val(*ptep))) {
+               if (unlikely(pmd_val(pmd) != pmd_val(*pmdp)) ||
+                   unlikely(pte_val(pte) != pte_val(*ptep))) {
                        gup_put_folio(folio, 1, flags);
                        goto pte_unmap;
                }
@@ -2439,8 +2460,9 @@ pte_unmap:
  * get_user_pages_fast_only implementation that can pin pages. Thus it's still
  * useful to have gup_huge_pmd even if we can't operate on ptes.
  */
-static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
-                        unsigned int flags, struct page **pages, int *nr)
+static int gup_pte_range(pmd_t pmd, pmd_t *pmdp, unsigned long addr,
+                        unsigned long end, unsigned int flags,
+                        struct page **pages, int *nr)
 {
        return 0;
 }
@@ -2764,7 +2786,7 @@ static int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr, unsigned lo
                        if (!gup_huge_pd(__hugepd(pmd_val(pmd)), addr,
                                         PMD_SHIFT, next, flags, pages, nr))
                                return 0;
-               } else if (!gup_pte_range(pmd, addr, next, flags, pages, nr))
+               } else if (!gup_pte_range(pmd, pmdp, addr, next, flags, pages, nr))
                        return 0;
        } while (pmdp++, addr = next, addr != end);
 
index e9414ee..f42bb51 100644 (file)
@@ -2894,11 +2894,9 @@ static void split_huge_pages_all(void)
                max_zone_pfn = zone_end_pfn(zone);
                for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
                        int nr_pages;
-                       if (!pfn_valid(pfn))
-                               continue;
 
-                       page = pfn_to_page(pfn);
-                       if (!get_page_unless_zero(page))
+                       page = pfn_to_online_page(pfn);
+                       if (!page || !get_page_unless_zero(page))
                                continue;
 
                        if (zone != page_zone(page))
index e070b85..0bdfc7e 100644 (file)
@@ -3420,6 +3420,7 @@ static int demote_free_huge_page(struct hstate *h, struct page *page)
 {
        int i, nid = page_to_nid(page);
        struct hstate *target_hstate;
+       struct page *subpage;
        int rc = 0;
 
        target_hstate = size_to_hstate(PAGE_SIZE << h->demote_order);
@@ -3453,15 +3454,16 @@ static int demote_free_huge_page(struct hstate *h, struct page *page)
        mutex_lock(&target_hstate->resize_lock);
        for (i = 0; i < pages_per_huge_page(h);
                                i += pages_per_huge_page(target_hstate)) {
+               subpage = nth_page(page, i);
                if (hstate_is_gigantic(target_hstate))
-                       prep_compound_gigantic_page_for_demote(page + i,
+                       prep_compound_gigantic_page_for_demote(subpage,
                                                        target_hstate->order);
                else
-                       prep_compound_page(page + i, target_hstate->order);
-               set_page_private(page + i, 0);
-               set_page_refcounted(page + i);
-               prep_new_huge_page(target_hstate, page + i, nid);
-               put_page(page + i);
+                       prep_compound_page(subpage, target_hstate->order);
+               set_page_private(subpage, 0);
+               set_page_refcounted(subpage);
+               prep_new_huge_page(target_hstate, subpage, nid);
+               put_page(subpage);
        }
        mutex_unlock(&target_hstate->resize_lock);
 
index 01f7178..70b7ac6 100644 (file)
@@ -1083,10 +1083,12 @@ static void collapse_huge_page(struct mm_struct *mm,
 
        pmd_ptl = pmd_lock(mm, pmd); /* probably unnecessary */
        /*
-        * After this gup_fast can't run anymore. This also removes
-        * any huge TLB entry from the CPU so we won't allow
-        * huge and small TLB entries for the same virtual address
-        * to avoid the risk of CPU bugs in that area.
+        * This removes any huge TLB entry from the CPU so we won't allow
+        * huge and small TLB entries for the same virtual address to
+        * avoid the risk of CPU bugs in that area.
+        *
+        * Parallel fast GUP is fine since fast GUP will back off when
+        * it detects PMD is changed.
         */
        _pmd = pmdp_collapse_flush(vma, address, pmd);
        spin_unlock(pmd_ptl);
index 5f0f094..9ff5165 100644 (file)
@@ -451,8 +451,11 @@ regular_page:
                        continue;
                }
 
-               /* Do not interfere with other mappings of this page */
-               if (page_mapcount(page) != 1)
+               /*
+                * Do not interfere with other mappings of this page and
+                * non-LRU page.
+                */
+               if (!PageLRU(page) || page_mapcount(page) != 1)
                        continue;
 
                VM_BUG_ON_PAGE(PageTransCompound(page), page);
index 1443980..e7ac570 100644 (file)
@@ -345,13 +345,17 @@ static unsigned long dev_pagemap_mapping_shift(struct vm_area_struct *vma,
  * not much we can do. We just print a message and ignore otherwise.
  */
 
+#define FSDAX_INVALID_PGOFF ULONG_MAX
+
 /*
  * Schedule a process for later kill.
  * Uses GFP_ATOMIC allocations to avoid potential recursions in the VM.
  *
- * Notice: @fsdax_pgoff is used only when @p is a fsdax page.
- *   In other cases, such as anonymous and file-backend page, the address to be
- *   killed can be caculated by @p itself.
+ * Note: @fsdax_pgoff is used only when @p is a fsdax page and a
+ * filesystem with a memory failure handler has claimed the
+ * memory_failure event. In all other cases, page->index and
+ * page->mapping are sufficient for mapping the page back to its
+ * corresponding user virtual address.
  */
 static void add_to_kill(struct task_struct *tsk, struct page *p,
                        pgoff_t fsdax_pgoff, struct vm_area_struct *vma,
@@ -367,11 +371,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
 
        tk->addr = page_address_in_vma(p, vma);
        if (is_zone_device_page(p)) {
-               /*
-                * Since page->mapping is not used for fsdax, we need
-                * calculate the address based on the vma.
-                */
-               if (p->pgmap->type == MEMORY_DEVICE_FS_DAX)
+               if (fsdax_pgoff != FSDAX_INVALID_PGOFF)
                        tk->addr = vma_pgoff_address(fsdax_pgoff, 1, vma);
                tk->size_shift = dev_pagemap_mapping_shift(vma, tk->addr);
        } else
@@ -523,7 +523,8 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
                        if (!page_mapped_in_vma(page, vma))
                                continue;
                        if (vma->vm_mm == t->mm)
-                               add_to_kill(t, page, 0, vma, to_kill);
+                               add_to_kill(t, page, FSDAX_INVALID_PGOFF, vma,
+                                           to_kill);
                }
        }
        read_unlock(&tasklist_lock);
@@ -559,7 +560,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill,
                         * to be informed of all such data corruptions.
                         */
                        if (vma->vm_mm == t->mm)
-                               add_to_kill(t, page, 0, vma, to_kill);
+                               add_to_kill(t, page, FSDAX_INVALID_PGOFF, vma,
+                                           to_kill);
                }
        }
        read_unlock(&tasklist_lock);
@@ -743,6 +745,9 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn,
        };
        priv.tk.tsk = p;
 
+       if (!p->mm)
+               return -EFAULT;
+
        mmap_read_lock(p->mm);
        ret = walk_page_range(p->mm, 0, TASK_SIZE, &hwp_walk_ops,
                              (void *)&priv);
@@ -1928,7 +1933,7 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
         * Call driver's implementation to handle the memory failure, otherwise
         * fall back to generic handler.
         */
-       if (pgmap->ops->memory_failure) {
+       if (pgmap_has_memory_failure(pgmap)) {
                rc = pgmap->ops->memory_failure(pgmap, pfn, 1, flags);
                /*
                 * Fall back to generic handler too if operation is not
index 4ba73f5..a788144 100644 (file)
@@ -4386,14 +4386,20 @@ vm_fault_t finish_fault(struct vm_fault *vmf)
 
        vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd,
                                      vmf->address, &vmf->ptl);
-       ret = 0;
+
        /* Re-check under ptl */
-       if (likely(!vmf_pte_changed(vmf)))
+       if (likely(!vmf_pte_changed(vmf))) {
                do_set_pte(vmf, page, vmf->address);
-       else
+
+               /* no need to invalidate: a not-present page won't be cached */
+               update_mmu_cache(vma, vmf->address, vmf->pte);
+
+               ret = 0;
+       } else {
+               update_mmu_tlb(vma, vmf->address, vmf->pte);
                ret = VM_FAULT_NOPAGE;
+       }
 
-       update_mmu_tlb(vma, vmf->address, vmf->pte);
        pte_unmap_unlock(vmf->pte, vmf->ptl);
        return ret;
 }
index 27fb37d..dbf6c7a 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/export.h>
 #include <linux/memremap.h>
 #include <linux/migrate.h>
+#include <linux/mm.h>
 #include <linux/mm_inline.h>
 #include <linux/mmu_notifier.h>
 #include <linux/oom.h>
@@ -193,10 +194,10 @@ again:
                        bool anon_exclusive;
                        pte_t swp_pte;
 
+                       flush_cache_page(vma, addr, pte_pfn(*ptep));
                        anon_exclusive = PageAnon(page) && PageAnonExclusive(page);
                        if (anon_exclusive) {
-                               flush_cache_page(vma, addr, pte_pfn(*ptep));
-                               ptep_clear_flush(vma, addr, ptep);
+                               pte = ptep_clear_flush(vma, addr, ptep);
 
                                if (page_try_share_anon_rmap(page)) {
                                        set_pte_at(mm, addr, ptep, pte);
@@ -206,11 +207,15 @@ again:
                                        goto next;
                                }
                        } else {
-                               ptep_get_and_clear(mm, addr, ptep);
+                               pte = ptep_get_and_clear(mm, addr, ptep);
                        }
 
                        migrate->cpages++;
 
+                       /* Set the dirty flag on the folio now the pte is gone. */
+                       if (pte_dirty(pte))
+                               folio_mark_dirty(page_folio(page));
+
                        /* Setup special migration page table entry */
                        if (mpfn & MIGRATE_PFN_WRITE)
                                entry = make_writable_migration_entry(
@@ -254,13 +259,14 @@ next:
                migrate->dst[migrate->npages] = 0;
                migrate->src[migrate->npages++] = mpfn;
        }
-       arch_leave_lazy_mmu_mode();
-       pte_unmap_unlock(ptep - 1, ptl);
 
        /* Only flush the TLB if we actually modified any entries */
        if (unmapped)
                flush_tlb_range(walk->vma, start, end);
 
+       arch_leave_lazy_mmu_mode();
+       pte_unmap_unlock(ptep - 1, ptl);
+
        return 0;
 }
 
index e5486d4..d04211f 100644 (file)
@@ -4708,6 +4708,30 @@ void fs_reclaim_release(gfp_t gfp_mask)
 EXPORT_SYMBOL_GPL(fs_reclaim_release);
 #endif
 
+/*
+ * Zonelists may change due to hotplug during allocation. Detect when zonelists
+ * have been rebuilt so allocation retries. Reader side does not lock and
+ * retries the allocation if zonelist changes. Writer side is protected by the
+ * embedded spin_lock.
+ */
+static DEFINE_SEQLOCK(zonelist_update_seq);
+
+static unsigned int zonelist_iter_begin(void)
+{
+       if (IS_ENABLED(CONFIG_MEMORY_HOTREMOVE))
+               return read_seqbegin(&zonelist_update_seq);
+
+       return 0;
+}
+
+static unsigned int check_retry_zonelist(unsigned int seq)
+{
+       if (IS_ENABLED(CONFIG_MEMORY_HOTREMOVE))
+               return read_seqretry(&zonelist_update_seq, seq);
+
+       return seq;
+}
+
 /* Perform direct synchronous page reclaim */
 static unsigned long
 __perform_reclaim(gfp_t gfp_mask, unsigned int order,
@@ -5001,6 +5025,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        int compaction_retries;
        int no_progress_loops;
        unsigned int cpuset_mems_cookie;
+       unsigned int zonelist_iter_cookie;
        int reserve_flags;
 
        /*
@@ -5011,11 +5036,12 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
                                (__GFP_ATOMIC|__GFP_DIRECT_RECLAIM)))
                gfp_mask &= ~__GFP_ATOMIC;
 
-retry_cpuset:
+restart:
        compaction_retries = 0;
        no_progress_loops = 0;
        compact_priority = DEF_COMPACT_PRIORITY;
        cpuset_mems_cookie = read_mems_allowed_begin();
+       zonelist_iter_cookie = zonelist_iter_begin();
 
        /*
         * The fast path uses conservative alloc_flags to succeed only until
@@ -5187,9 +5213,13 @@ retry:
                goto retry;
 
 
-       /* Deal with possible cpuset update races before we start OOM killing */
-       if (check_retry_cpuset(cpuset_mems_cookie, ac))
-               goto retry_cpuset;
+       /*
+        * Deal with possible cpuset update races or zonelist updates to avoid
+        * a unnecessary OOM kill.
+        */
+       if (check_retry_cpuset(cpuset_mems_cookie, ac) ||
+           check_retry_zonelist(zonelist_iter_cookie))
+               goto restart;
 
        /* Reclaim has failed us, start killing things */
        page = __alloc_pages_may_oom(gfp_mask, order, ac, &did_some_progress);
@@ -5209,9 +5239,13 @@ retry:
        }
 
 nopage:
-       /* Deal with possible cpuset update races before we fail */
-       if (check_retry_cpuset(cpuset_mems_cookie, ac))
-               goto retry_cpuset;
+       /*
+        * Deal with possible cpuset update races or zonelist updates to avoid
+        * a unnecessary OOM kill.
+        */
+       if (check_retry_cpuset(cpuset_mems_cookie, ac) ||
+           check_retry_zonelist(zonelist_iter_cookie))
+               goto restart;
 
        /*
         * Make sure that __GFP_NOFAIL request doesn't leak out and make sure
@@ -5706,6 +5740,18 @@ refill:
                /* reset page count bias and offset to start of new frag */
                nc->pagecnt_bias = PAGE_FRAG_CACHE_MAX_SIZE + 1;
                offset = size - fragsz;
+               if (unlikely(offset < 0)) {
+                       /*
+                        * The caller is trying to allocate a fragment
+                        * with fragsz > PAGE_SIZE but the cache isn't big
+                        * enough to satisfy the request, this may
+                        * happen in low memory conditions.
+                        * We don't release the cache page because
+                        * it could make memory pressure worse
+                        * so we simply return NULL here.
+                        */
+                       return NULL;
+               }
        }
 
        nc->pagecnt_bias--;
@@ -6514,9 +6560,8 @@ static void __build_all_zonelists(void *data)
        int nid;
        int __maybe_unused cpu;
        pg_data_t *self = data;
-       static DEFINE_SPINLOCK(lock);
 
-       spin_lock(&lock);
+       write_seqlock(&zonelist_update_seq);
 
 #ifdef CONFIG_NUMA
        memset(node_load, 0, sizeof(node_load));
@@ -6553,7 +6598,7 @@ static void __build_all_zonelists(void *data)
 #endif
        }
 
-       spin_unlock(&lock);
+       write_sequnlock(&zonelist_update_seq);
 }
 
 static noinline void __init
index 9d73dc3..eb3a68c 100644 (file)
@@ -288,6 +288,7 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
  * @isolate_before:    isolate the pageblock before the boundary_pfn
  * @skip_isolation:    the flag to skip the pageblock isolation in second
  *                     isolate_single_pageblock()
+ * @migratetype:       migrate type to set in error recovery.
  *
  * Free and in-use pages can be as big as MAX_ORDER-1 and contain more than one
  * pageblock. When not all pageblocks within a page are isolated at the same
@@ -302,9 +303,9 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
  * the in-use page then splitting the free page.
  */
 static int isolate_single_pageblock(unsigned long boundary_pfn, int flags,
-                       gfp_t gfp_flags, bool isolate_before, bool skip_isolation)
+                       gfp_t gfp_flags, bool isolate_before, bool skip_isolation,
+                       int migratetype)
 {
-       unsigned char saved_mt;
        unsigned long start_pfn;
        unsigned long isolate_pageblock;
        unsigned long pfn;
@@ -328,13 +329,13 @@ static int isolate_single_pageblock(unsigned long boundary_pfn, int flags,
        start_pfn  = max(ALIGN_DOWN(isolate_pageblock, MAX_ORDER_NR_PAGES),
                                      zone->zone_start_pfn);
 
-       saved_mt = get_pageblock_migratetype(pfn_to_page(isolate_pageblock));
+       if (skip_isolation) {
+               int mt = get_pageblock_migratetype(pfn_to_page(isolate_pageblock));
 
-       if (skip_isolation)
-               VM_BUG_ON(!is_migrate_isolate(saved_mt));
-       else {
-               ret = set_migratetype_isolate(pfn_to_page(isolate_pageblock), saved_mt, flags,
-                               isolate_pageblock, isolate_pageblock + pageblock_nr_pages);
+               VM_BUG_ON(!is_migrate_isolate(mt));
+       } else {
+               ret = set_migratetype_isolate(pfn_to_page(isolate_pageblock), migratetype,
+                               flags, isolate_pageblock, isolate_pageblock + pageblock_nr_pages);
 
                if (ret)
                        return ret;
@@ -475,7 +476,7 @@ static int isolate_single_pageblock(unsigned long boundary_pfn, int flags,
 failed:
        /* restore the original migratetype */
        if (!skip_isolation)
-               unset_migratetype_isolate(pfn_to_page(isolate_pageblock), saved_mt);
+               unset_migratetype_isolate(pfn_to_page(isolate_pageblock), migratetype);
        return -EBUSY;
 }
 
@@ -537,7 +538,8 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
        bool skip_isolation = false;
 
        /* isolate [isolate_start, isolate_start + pageblock_nr_pages) pageblock */
-       ret = isolate_single_pageblock(isolate_start, flags, gfp_flags, false, skip_isolation);
+       ret = isolate_single_pageblock(isolate_start, flags, gfp_flags, false,
+                       skip_isolation, migratetype);
        if (ret)
                return ret;
 
@@ -545,7 +547,8 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
                skip_isolation = true;
 
        /* isolate [isolate_end - pageblock_nr_pages, isolate_end) pageblock */
-       ret = isolate_single_pageblock(isolate_end, flags, gfp_flags, true, skip_isolation);
+       ret = isolate_single_pageblock(isolate_end, flags, gfp_flags, true,
+                       skip_isolation, migratetype);
        if (ret) {
                unset_migratetype_isolate(pfn_to_page(isolate_start), migratetype);
                return ret;
index 9b3db11..fa7a3d2 100644 (file)
@@ -110,7 +110,7 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
        do {
 again:
                next = pmd_addr_end(addr, end);
-               if (pmd_none(*pmd) || (!walk->vma && !walk->no_vma)) {
+               if (pmd_none(*pmd)) {
                        if (ops->pte_hole)
                                err = ops->pte_hole(addr, next, depth, walk);
                        if (err)
@@ -171,7 +171,7 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
        do {
  again:
                next = pud_addr_end(addr, end);
-               if (pud_none(*pud) || (!walk->vma && !walk->no_vma)) {
+               if (pud_none(*pud)) {
                        if (ops->pte_hole)
                                err = ops->pte_hole(addr, next, depth, walk);
                        if (err)
@@ -366,19 +366,19 @@ static int __walk_page_range(unsigned long start, unsigned long end,
        struct vm_area_struct *vma = walk->vma;
        const struct mm_walk_ops *ops = walk->ops;
 
-       if (vma && ops->pre_vma) {
+       if (ops->pre_vma) {
                err = ops->pre_vma(start, end, walk);
                if (err)
                        return err;
        }
 
-       if (vma && is_vm_hugetlb_page(vma)) {
+       if (is_vm_hugetlb_page(vma)) {
                if (ops->hugetlb_entry)
                        err = walk_hugetlb_range(start, end, walk);
        } else
                err = walk_pgd_range(start, end, walk);
 
-       if (vma && ops->post_vma)
+       if (ops->post_vma)
                ops->post_vma(walk);
 
        return err;
@@ -450,9 +450,13 @@ int walk_page_range(struct mm_struct *mm, unsigned long start,
                if (!vma) { /* after the last vma */
                        walk.vma = NULL;
                        next = end;
+                       if (ops->pte_hole)
+                               err = ops->pte_hole(start, next, -1, &walk);
                } else if (start < vma->vm_start) { /* outside vma */
                        walk.vma = NULL;
                        next = min(end, vma->vm_start);
+                       if (ops->pte_hole)
+                               err = ops->pte_hole(start, next, -1, &walk);
                } else { /* inside vma */
                        walk.vma = vma;
                        next = min(end, vma->vm_end);
@@ -470,9 +474,8 @@ int walk_page_range(struct mm_struct *mm, unsigned long start,
                        }
                        if (err < 0)
                                break;
-               }
-               if (walk.vma || walk.ops->pte_hole)
                        err = __walk_page_range(start, next, &walk);
+               }
                if (err)
                        break;
        } while (start = next, start < end);
@@ -501,9 +504,9 @@ int walk_page_range_novma(struct mm_struct *mm, unsigned long start,
        if (start >= end || !walk.mm)
                return -EINVAL;
 
-       mmap_assert_locked(walk.mm);
+       mmap_assert_write_locked(walk.mm);
 
-       return __walk_page_range(start, end, &walk);
+       return walk_pgd_range(start, end, &walk);
 }
 
 int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops,
index eea3d28..8adab45 100644 (file)
@@ -152,13 +152,13 @@ void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
 {
        const struct ptdump_range *range = st->range;
 
-       mmap_read_lock(mm);
+       mmap_write_lock(mm);
        while (range->start != range->end) {
                walk_page_range_novma(mm, range->start, range->end,
                                      &ptdump_ops, pgd, st);
                range++;
        }
-       mmap_read_unlock(mm);
+       mmap_write_unlock(mm);
 
        /* Flush out the last page */
        st->note_page(st, 0, -1, 0);
index edc06c5..93d5a6f 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -93,7 +93,8 @@ static inline struct anon_vma *anon_vma_alloc(void)
        anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
        if (anon_vma) {
                atomic_set(&anon_vma->refcount, 1);
-               anon_vma->degree = 1;   /* Reference for first vma */
+               anon_vma->num_children = 0;
+               anon_vma->num_active_vmas = 0;
                anon_vma->parent = anon_vma;
                /*
                 * Initialise the anon_vma root to point to itself. If called
@@ -201,6 +202,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
                anon_vma = anon_vma_alloc();
                if (unlikely(!anon_vma))
                        goto out_enomem_free_avc;
+               anon_vma->num_children++; /* self-parent link for new root */
                allocated = anon_vma;
        }
 
@@ -210,8 +212,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
        if (likely(!vma->anon_vma)) {
                vma->anon_vma = anon_vma;
                anon_vma_chain_link(vma, avc, anon_vma);
-               /* vma reference or self-parent link for new root */
-               anon_vma->degree++;
+               anon_vma->num_active_vmas++;
                allocated = NULL;
                avc = NULL;
        }
@@ -296,19 +297,19 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
                anon_vma_chain_link(dst, avc, anon_vma);
 
                /*
-                * Reuse existing anon_vma if its degree lower than two,
-                * that means it has no vma and only one anon_vma child.
+                * Reuse existing anon_vma if it has no vma and only one
+                * anon_vma child.
                 *
-                * Do not choose parent anon_vma, otherwise first child
-                * will always reuse it. Root anon_vma is never reused:
+                * Root anon_vma is never reused:
                 * it has self-parent reference and at least one child.
                 */
                if (!dst->anon_vma && src->anon_vma &&
-                   anon_vma != src->anon_vma && anon_vma->degree < 2)
+                   anon_vma->num_children < 2 &&
+                   anon_vma->num_active_vmas == 0)
                        dst->anon_vma = anon_vma;
        }
        if (dst->anon_vma)
-               dst->anon_vma->degree++;
+               dst->anon_vma->num_active_vmas++;
        unlock_anon_vma_root(root);
        return 0;
 
@@ -358,6 +359,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        anon_vma = anon_vma_alloc();
        if (!anon_vma)
                goto out_error;
+       anon_vma->num_active_vmas++;
        avc = anon_vma_chain_alloc(GFP_KERNEL);
        if (!avc)
                goto out_error_free_anon_vma;
@@ -378,7 +380,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        vma->anon_vma = anon_vma;
        anon_vma_lock_write(anon_vma);
        anon_vma_chain_link(vma, avc, anon_vma);
-       anon_vma->parent->degree++;
+       anon_vma->parent->num_children++;
        anon_vma_unlock_write(anon_vma);
 
        return 0;
@@ -410,7 +412,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
                 * to free them outside the lock.
                 */
                if (RB_EMPTY_ROOT(&anon_vma->rb_root.rb_root)) {
-                       anon_vma->parent->degree--;
+                       anon_vma->parent->num_children--;
                        continue;
                }
 
@@ -418,7 +420,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
                anon_vma_chain_free(avc);
        }
        if (vma->anon_vma) {
-               vma->anon_vma->degree--;
+               vma->anon_vma->num_active_vmas--;
 
                /*
                 * vma would still be needed after unlink, and anon_vma will be prepared
@@ -436,7 +438,8 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
        list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
                struct anon_vma *anon_vma = avc->anon_vma;
 
-               VM_WARN_ON(anon_vma->degree);
+               VM_WARN_ON(anon_vma->num_children);
+               VM_WARN_ON(anon_vma->num_active_vmas);
                put_anon_vma(anon_vma);
 
                list_del(&avc->same_vma);
index e3e9590..3f71540 100644 (file)
@@ -285,7 +285,7 @@ static int secretmem_init(void)
 
        secretmem_mnt = kern_mount(&secretmem_fs);
        if (IS_ERR(secretmem_mnt))
-               ret = PTR_ERR(secretmem_mnt);
+               return PTR_ERR(secretmem_mnt);
 
        /* prevent secretmem mappings from ever getting PROT_EXEC */
        secretmem_mnt->mnt_flags |= MNT_NOEXEC;
index 1799664..ccc0257 100644 (file)
@@ -392,6 +392,28 @@ kmem_cache_create(const char *name, unsigned int size, unsigned int align,
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
+#ifdef SLAB_SUPPORTS_SYSFS
+/*
+ * For a given kmem_cache, kmem_cache_destroy() should only be called
+ * once or there will be a use-after-free problem. The actual deletion
+ * and release of the kobject does not need slab_mutex or cpu_hotplug_lock
+ * protection. So they are now done without holding those locks.
+ *
+ * Note that there will be a slight delay in the deletion of sysfs files
+ * if kmem_cache_release() is called indrectly from a work function.
+ */
+static void kmem_cache_release(struct kmem_cache *s)
+{
+       sysfs_slab_unlink(s);
+       sysfs_slab_release(s);
+}
+#else
+static void kmem_cache_release(struct kmem_cache *s)
+{
+       slab_kmem_cache_release(s);
+}
+#endif
+
 static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work)
 {
        LIST_HEAD(to_destroy);
@@ -418,11 +440,7 @@ static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work)
        list_for_each_entry_safe(s, s2, &to_destroy, list) {
                debugfs_slab_release(s);
                kfence_shutdown_cache(s);
-#ifdef SLAB_SUPPORTS_SYSFS
-               sysfs_slab_release(s);
-#else
-               slab_kmem_cache_release(s);
-#endif
+               kmem_cache_release(s);
        }
 }
 
@@ -437,20 +455,11 @@ static int shutdown_cache(struct kmem_cache *s)
        list_del(&s->list);
 
        if (s->flags & SLAB_TYPESAFE_BY_RCU) {
-#ifdef SLAB_SUPPORTS_SYSFS
-               sysfs_slab_unlink(s);
-#endif
                list_add_tail(&s->list, &slab_caches_to_rcu_destroy);
                schedule_work(&slab_caches_to_rcu_destroy_work);
        } else {
                kfence_shutdown_cache(s);
                debugfs_slab_release(s);
-#ifdef SLAB_SUPPORTS_SYSFS
-               sysfs_slab_unlink(s);
-               sysfs_slab_release(s);
-#else
-               slab_kmem_cache_release(s);
-#endif
        }
 
        return 0;
@@ -465,14 +474,19 @@ void slab_kmem_cache_release(struct kmem_cache *s)
 
 void kmem_cache_destroy(struct kmem_cache *s)
 {
+       int refcnt;
+       bool rcu_set;
+
        if (unlikely(!s) || !kasan_check_byte(s))
                return;
 
        cpus_read_lock();
        mutex_lock(&slab_mutex);
 
-       s->refcount--;
-       if (s->refcount)
+       rcu_set = s->flags & SLAB_TYPESAFE_BY_RCU;
+
+       refcnt = --s->refcount;
+       if (refcnt)
                goto out_unlock;
 
        WARN(shutdown_cache(s),
@@ -481,6 +495,8 @@ void kmem_cache_destroy(struct kmem_cache *s)
 out_unlock:
        mutex_unlock(&slab_mutex);
        cpus_read_unlock();
+       if (!refcnt && !rcu_set)
+               kmem_cache_release(s);
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
index 862dbd9..4b98dff 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -310,6 +310,11 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si)
  */
 static nodemask_t slab_nodes;
 
+/*
+ * Workqueue used for flush_cpu_slab().
+ */
+static struct workqueue_struct *flushwq;
+
 /********************************************************************
  *                     Core slab cache functions
  *******************************************************************/
@@ -2730,7 +2735,7 @@ static void flush_all_cpus_locked(struct kmem_cache *s)
                INIT_WORK(&sfw->work, flush_cpu_slab);
                sfw->skip = false;
                sfw->s = s;
-               schedule_work_on(cpu, &sfw->work);
+               queue_work_on(cpu, flushwq, &sfw->work);
        }
 
        for_each_online_cpu(cpu) {
@@ -4858,6 +4863,8 @@ void __init kmem_cache_init(void)
 
 void __init kmem_cache_init_late(void)
 {
+       flushwq = alloc_workqueue("slub_flushwq", WQ_MEM_RECLAIM, 0);
+       WARN_ON(!flushwq);
 }
 
 struct kmem_cache *
@@ -4926,6 +4933,8 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller)
        /* Honor the call site pointer we received. */
        trace_kmalloc(caller, ret, s, size, s->size, gfpflags);
 
+       ret = kasan_kmalloc(s, ret, size, gfpflags);
+
        return ret;
 }
 EXPORT_SYMBOL(__kmalloc_track_caller);
@@ -4957,6 +4966,8 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
        /* Honor the call site pointer we received. */
        trace_kmalloc_node(caller, ret, s, size, s->size, gfpflags, node);
 
+       ret = kasan_kmalloc(s, ret, size, gfpflags);
+
        return ret;
 }
 EXPORT_SYMBOL(__kmalloc_node_track_caller);
@@ -5890,7 +5901,8 @@ static char *create_unique_id(struct kmem_cache *s)
        char *name = kmalloc(ID_STR_LENGTH, GFP_KERNEL);
        char *p = name;
 
-       BUG_ON(!name);
+       if (!name)
+               return ERR_PTR(-ENOMEM);
 
        *p++ = ':';
        /*
@@ -5948,6 +5960,8 @@ static int sysfs_slab_add(struct kmem_cache *s)
                 * for the symlinks.
                 */
                name = create_unique_id(s);
+               if (IS_ERR(name))
+                       return PTR_ERR(name);
        }
 
        s->kobj.kset = kset;
index e166051..41afa6d 100644 (file)
@@ -151,7 +151,7 @@ void __delete_from_swap_cache(struct folio *folio,
 
        for (i = 0; i < nr; i++) {
                void *entry = xas_store(&xas, shadow);
-               VM_BUG_ON_FOLIO(entry != folio, folio);
+               VM_BUG_ON_PAGE(entry != folio, entry);
                set_page_private(folio_page(folio, i), 0);
                xas_next(&xas);
        }
index c9439c6..346e401 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -619,6 +619,10 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
        if (ret || size <= PAGE_SIZE)
                return ret;
 
+       /* non-sleeping allocations are not supported by vmalloc */
+       if (!gfpflags_allow_blocking(flags))
+               return NULL;
+
        /* Don't even allow crazy sizes */
        if (unlikely(size > INT_MAX)) {
                WARN_ON_ONCE(!(flags & __GFP_NOWARN));
index b2b1431..382dbe9 100644 (file)
@@ -2550,8 +2550,8 @@ static void shrink_active_list(unsigned long nr_to_scan,
                }
 
                if (unlikely(buffer_heads_over_limit)) {
-                       if (folio_get_private(folio) && folio_trylock(folio)) {
-                               if (folio_get_private(folio))
+                       if (folio_test_private(folio) && folio_trylock(folio)) {
+                               if (folio_test_private(folio))
                                        filemap_release_folio(folio, 0);
                                folio_unlock(folio);
                        }
index b8f8da7..41c1ad3 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/atomic.h>
 #include <linux/byteorder/generic.h>
 #include <linux/container_of.h>
+#include <linux/errno.h>
 #include <linux/gfp.h>
 #include <linux/if.h>
 #include <linux/if_arp.h>
@@ -700,6 +701,9 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
        int max_header_len = batadv_max_header_len();
        int ret;
 
+       if (hard_iface->net_dev->mtu < ETH_MIN_MTU + max_header_len)
+               return -EINVAL;
+
        if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
                goto out;
 
index 485c814..6643c9c 100644 (file)
@@ -4179,6 +4179,17 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
                }
        }
 
+       if (i == ARRAY_SIZE(hci_cc_table)) {
+               /* Unknown opcode, assume byte 0 contains the status, so
+                * that e.g. __hci_cmd_sync() properly returns errors
+                * for vendor specific commands send by HCI drivers.
+                * If a vendor doesn't actually follow this convention we may
+                * need to introduce a vendor CC table in order to properly set
+                * the status.
+                */
+               *status = skb->data[0];
+       }
+
        handle_cmd_cnt_and_timer(hdev, ev->ncmd);
 
        hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
@@ -5790,7 +5801,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
         */
        hci_dev_clear_flag(hdev, HCI_LE_ADV);
 
-       conn = hci_lookup_le_connect(hdev);
+       conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
        if (!conn) {
                /* In case of error status and there is no connection pending
                 * just unlock as there is nothing to cleanup.
index e6d804b..fbd5613 100644 (file)
@@ -3018,12 +3018,6 @@ static const struct hci_init_stage amp_init2[] = {
 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
 static int hci_read_buffer_size_sync(struct hci_dev *hdev)
 {
-       /* Use Read LE Buffer Size V2 if supported */
-       if (hdev->commands[41] & 0x20)
-               return __hci_cmd_sync_status(hdev,
-                                            HCI_OP_LE_READ_BUFFER_SIZE_V2,
-                                            0, NULL, HCI_CMD_TIMEOUT);
-
        return __hci_cmd_sync_status(hdev, HCI_OP_READ_BUFFER_SIZE,
                                     0, NULL, HCI_CMD_TIMEOUT);
 }
@@ -3237,6 +3231,12 @@ static const struct hci_init_stage hci_init2[] = {
 /* Read LE Buffer Size */
 static int hci_le_read_buffer_size_sync(struct hci_dev *hdev)
 {
+       /* Use Read LE Buffer Size V2 if supported */
+       if (hdev->commands[41] & 0x20)
+               return __hci_cmd_sync_status(hdev,
+                                            HCI_OP_LE_READ_BUFFER_SIZE_V2,
+                                            0, NULL, HCI_CMD_TIMEOUT);
+
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_READ_BUFFER_SIZE,
                                     0, NULL, HCI_CMD_TIMEOUT);
 }
@@ -4773,9 +4773,11 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason)
                /* Cleanup hci_conn object if it cannot be cancelled as it
                 * likelly means the controller and host stack are out of sync.
                 */
-               if (err)
+               if (err) {
+                       hci_dev_lock(hdev);
                        hci_conn_failed(conn, err);
-
+                       hci_dev_unlock(hdev);
+               }
                return err;
        case BT_CONNECT2:
                return hci_reject_conn_sync(hdev, conn, reason);
@@ -5288,17 +5290,21 @@ int hci_suspend_sync(struct hci_dev *hdev)
        /* Prevent disconnects from causing scanning to be re-enabled */
        hci_pause_scan_sync(hdev);
 
-       /* Soft disconnect everything (power off) */
-       err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
-       if (err) {
-               /* Set state to BT_RUNNING so resume doesn't notify */
-               hdev->suspend_state = BT_RUNNING;
-               hci_resume_sync(hdev);
-               return err;
-       }
+       if (hci_conn_count(hdev)) {
+               /* Soft disconnect everything (power off) */
+               err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
+               if (err) {
+                       /* Set state to BT_RUNNING so resume doesn't notify */
+                       hdev->suspend_state = BT_RUNNING;
+                       hci_resume_sync(hdev);
+                       return err;
+               }
 
-       /* Update event mask so only the allowed event can wakeup the host */
-       hci_set_event_mask_sync(hdev);
+               /* Update event mask so only the allowed event can wakeup the
+                * host.
+                */
+               hci_set_event_mask_sync(hdev);
+       }
 
        /* Only configure accept list if disconnect succeeded and wake
         * isn't being prevented.
index 5940744..cc20e70 100644 (file)
@@ -83,14 +83,14 @@ static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo
                ci->product = session->input->id.product;
                ci->version = session->input->id.version;
                if (session->input->name)
-                       strlcpy(ci->name, session->input->name, 128);
+                       strscpy(ci->name, session->input->name, 128);
                else
-                       strlcpy(ci->name, "HID Boot Device", 128);
+                       strscpy(ci->name, "HID Boot Device", 128);
        } else if (session->hid) {
                ci->vendor  = session->hid->vendor;
                ci->product = session->hid->product;
                ci->version = session->hid->version;
-               strlcpy(ci->name, session->hid->name, 128);
+               strscpy(ci->name, session->hid->name, 128);
        }
 }
 
index ced8ad4..613039b 100644 (file)
@@ -1309,7 +1309,7 @@ static int iso_sock_shutdown(struct socket *sock, int how)
        struct sock *sk = sock->sk;
        int err = 0;
 
-       BT_DBG("sock %p, sk %p", sock, sk);
+       BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
 
        if (!sk)
                return 0;
@@ -1317,17 +1317,32 @@ static int iso_sock_shutdown(struct socket *sock, int how)
        sock_hold(sk);
        lock_sock(sk);
 
-       if (!sk->sk_shutdown) {
-               sk->sk_shutdown = SHUTDOWN_MASK;
-               iso_sock_clear_timer(sk);
-               __iso_sock_close(sk);
-
-               if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
-                   !(current->flags & PF_EXITING))
-                       err = bt_sock_wait_state(sk, BT_CLOSED,
-                                                sk->sk_lingertime);
+       switch (how) {
+       case SHUT_RD:
+               if (sk->sk_shutdown & RCV_SHUTDOWN)
+                       goto unlock;
+               sk->sk_shutdown |= RCV_SHUTDOWN;
+               break;
+       case SHUT_WR:
+               if (sk->sk_shutdown & SEND_SHUTDOWN)
+                       goto unlock;
+               sk->sk_shutdown |= SEND_SHUTDOWN;
+               break;
+       case SHUT_RDWR:
+               if (sk->sk_shutdown & SHUTDOWN_MASK)
+                       goto unlock;
+               sk->sk_shutdown |= SHUTDOWN_MASK;
+               break;
        }
 
+       iso_sock_clear_timer(sk);
+       __iso_sock_close(sk);
+
+       if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+           !(current->flags & PF_EXITING))
+               err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
+
+unlock:
        release_sock(sk);
        sock_put(sk);
 
index cbe0cae..2c9de67 100644 (file)
@@ -1992,11 +1992,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                        src_match = !bacmp(&c->src, src);
                        dst_match = !bacmp(&c->dst, dst);
                        if (src_match && dst_match) {
-                               c = l2cap_chan_hold_unless_zero(c);
-                               if (c) {
-                                       read_unlock(&chan_list_lock);
-                                       return c;
-                               }
+                               if (!l2cap_chan_hold_unless_zero(c))
+                                       continue;
+
+                               read_unlock(&chan_list_lock);
+                               return c;
                        }
 
                        /* Closest match */
index 6e31023..72e6595 100644 (file)
@@ -4547,6 +4547,22 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
                               MGMT_STATUS_NOT_SUPPORTED);
 }
 
+static u32 get_params_flags(struct hci_dev *hdev,
+                           struct hci_conn_params *params)
+{
+       u32 flags = hdev->conn_flags;
+
+       /* Devices using RPAs can only be programmed in the acceptlist if
+        * LL Privacy has been enable otherwise they cannot mark
+        * HCI_CONN_FLAG_REMOTE_WAKEUP.
+        */
+       if ((flags & HCI_CONN_FLAG_REMOTE_WAKEUP) && !use_ll_privacy(hdev) &&
+           hci_find_irk_by_addr(hdev, &params->addr, params->addr_type))
+               flags &= ~HCI_CONN_FLAG_REMOTE_WAKEUP;
+
+       return flags;
+}
+
 static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
                            u16 data_len)
 {
@@ -4578,10 +4594,10 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
        } else {
                params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
                                                le_addr_type(cp->addr.type));
-
                if (!params)
                        goto done;
 
+               supported_flags = get_params_flags(hdev, params);
                current_flags = params->flags;
        }
 
@@ -4649,38 +4665,35 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
                        bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
                                    &cp->addr.bdaddr, cp->addr.type);
                }
-       } else {
-               params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
-                                               le_addr_type(cp->addr.type));
-               if (params) {
-                       /* Devices using RPAs can only be programmed in the
-                        * acceptlist LL Privacy has been enable otherwise they
-                        * cannot mark HCI_CONN_FLAG_REMOTE_WAKEUP.
-                        */
-                       if ((current_flags & HCI_CONN_FLAG_REMOTE_WAKEUP) &&
-                           !use_ll_privacy(hdev) &&
-                           hci_find_irk_by_addr(hdev, &params->addr,
-                                                params->addr_type)) {
-                               bt_dev_warn(hdev,
-                                           "Cannot set wakeable for RPA");
-                               goto unlock;
-                       }
 
-                       params->flags = current_flags;
-                       status = MGMT_STATUS_SUCCESS;
+               goto unlock;
+       }
 
-                       /* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
-                        * has been set.
-                        */
-                       if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
-                               hci_update_passive_scan(hdev);
-               } else {
-                       bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
-                                   &cp->addr.bdaddr,
-                                   le_addr_type(cp->addr.type));
-               }
+       params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
+                                       le_addr_type(cp->addr.type));
+       if (!params) {
+               bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
+                           &cp->addr.bdaddr, le_addr_type(cp->addr.type));
+               goto unlock;
        }
 
+       supported_flags = get_params_flags(hdev, params);
+
+       if ((supported_flags | current_flags) != supported_flags) {
+               bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
+                           current_flags, supported_flags);
+               goto unlock;
+       }
+
+       params->flags = current_flags;
+       status = MGMT_STATUS_SUCCESS;
+
+       /* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
+        * has been set.
+        */
+       if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
+               hci_update_passive_scan(hdev);
+
 unlock:
        hci_dev_unlock(hdev);
 
@@ -5054,7 +5067,6 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
                else
                        status = MGMT_STATUS_FAILED;
 
-               mgmt_pending_remove(cmd);
                goto unlock;
        }
 
index ff47790..f20f437 100644 (file)
@@ -384,6 +384,7 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_
                                /* - Bridged-and-DNAT'ed traffic doesn't
                                 *   require ip_forwarding. */
                                if (rt->dst.dev == dev) {
+                                       skb_dst_drop(skb);
                                        skb_dst_set(skb, &rt->dst);
                                        goto bridged_dnat;
                                }
@@ -413,6 +414,7 @@ bridged_dnat:
                        kfree_skb(skb);
                        return 0;
                }
+               skb_dst_drop(skb);
                skb_dst_set_noref(skb, &rt->dst);
        }
 
index e4e0c83..6b07f30 100644 (file)
@@ -197,6 +197,7 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc
                        kfree_skb(skb);
                        return 0;
                }
+               skb_dst_drop(skb);
                skb_dst_set_noref(skb, &rt->dst);
        }
 
index 9a0ae59..4f385d5 100644 (file)
@@ -1040,8 +1040,10 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
                goto free_iterate;
        }
 
-       if (repl->valid_hooks != t->valid_hooks)
+       if (repl->valid_hooks != t->valid_hooks) {
+               ret = -EINVAL;
                goto free_unlock;
+       }
 
        if (repl->num_counters && repl->num_counters != t->private->nentries) {
                ret = -EINVAL;
index fe9be3c..385f04a 100644 (file)
@@ -52,6 +52,7 @@ int __get_compat_msghdr(struct msghdr *kmsg,
                kmsg->msg_namelen = sizeof(struct sockaddr_storage);
 
        kmsg->msg_control_is_user = true;
+       kmsg->msg_get_inq = 0;
        kmsg->msg_control_user = compat_ptr(msg->msg_control);
        kmsg->msg_controllen = msg->msg_controllen;
 
diff --git a/net/core/.gitignore b/net/core/.gitignore
deleted file mode 100644 (file)
index df1e743..0000000
+++ /dev/null
@@ -1 +0,0 @@
-dropreason_str.c
index e8ce3bd..5857cec 100644 (file)
@@ -5,7 +5,7 @@
 
 obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \
         gen_stats.o gen_estimator.o net_namespace.o secure_seq.o \
-        flow_dissector.o dropreason_str.o
+        flow_dissector.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
@@ -40,23 +40,3 @@ obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
 obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
 obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
 obj-$(CONFIG_OF)       += of_net.o
-
-clean-files := dropreason_str.c
-
-quiet_cmd_dropreason_str = GEN     $@
-cmd_dropreason_str = awk -F ',' 'BEGIN{ print "\#include <net/dropreason.h>\n"; \
-       print "const char * const drop_reasons[] = {" }\
-       /^enum skb_drop/ { dr=1; }\
-       /^\};/ { dr=0; }\
-       /^\tSKB_DROP_REASON_/ {\
-               if (dr) {\
-                       sub(/\tSKB_DROP_REASON_/, "", $$1);\
-                       printf "\t[SKB_DROP_REASON_%s] = \"%s\",\n", $$1, $$1;\
-               }\
-       }\
-       END{ print "};" }' $< > $@
-
-$(obj)/dropreason_str.c: $(srctree)/include/net/dropreason.h
-       $(call cmd,dropreason_str)
-
-$(obj)/dropreason_str.o: $(obj)/dropreason_str.c
index 7255531..e4ff2db 100644 (file)
@@ -677,7 +677,7 @@ int __zerocopy_sg_from_iter(struct msghdr *msg, struct sock *sk,
                                page_ref_sub(last_head, refs);
                                refs = 0;
                        }
-                       skb_fill_page_desc(skb, frag++, head, start, size);
+                       skb_fill_page_desc_noacc(skb, frag++, head, start, size);
                }
                if (refs)
                        page_ref_sub(last_head, refs);
index 764c4cb..5dc3860 100644 (file)
@@ -1611,9 +1611,8 @@ static inline void __flow_hash_consistentify(struct flow_keys *keys)
 
        switch (keys->control.addr_type) {
        case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
-               addr_diff = (__force u32)keys->addrs.v4addrs.dst -
-                           (__force u32)keys->addrs.v4addrs.src;
-               if (addr_diff < 0)
+               if ((__force u32)keys->addrs.v4addrs.dst <
+                   (__force u32)keys->addrs.v4addrs.src)
                        swap(keys->addrs.v4addrs.src, keys->addrs.v4addrs.dst);
 
                if ((__force u16)keys->ports.dst <
index 6b9f191..0ec2f59 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/user_namespace.h>
 #include <linux/net_namespace.h>
 #include <linux/sched/task.h>
-#include <linux/sched/mm.h>
 #include <linux/uidgid.h>
 #include <linux/cookie.h>
 
@@ -1144,13 +1143,7 @@ static int __register_pernet_operations(struct list_head *list,
                 * setup_net() and cleanup_net() are not possible.
                 */
                for_each_net(net) {
-                       struct mem_cgroup *old, *memcg;
-
-                       memcg = mem_cgroup_or_root(get_mem_cgroup_from_obj(net));
-                       old = set_active_memcg(memcg);
                        error = ops_init(ops, net);
-                       set_active_memcg(old);
-                       mem_cgroup_put(memcg);
                        if (error)
                                goto out_undo;
                        list_add_tail(&net->exit_list, &net_exit_list);
index 84bb5e1..417463d 100644 (file)
@@ -91,7 +91,11 @@ static struct kmem_cache *skbuff_ext_cache __ro_after_init;
 int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
 EXPORT_SYMBOL(sysctl_max_skb_frags);
 
-/* The array 'drop_reasons' is auto-generated in dropreason_str.c */
+#undef FN
+#define FN(reason) [SKB_DROP_REASON_##reason] = #reason,
+const char * const drop_reasons[] = {
+       DEFINE_DROP_REASON(FN, FN)
+};
 EXPORT_SYMBOL(drop_reasons);
 
 /**
index 59e75ff..188f855 100644 (file)
@@ -461,7 +461,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
 
                        if (copied == len)
                                break;
-               } while (!sg_is_last(sge));
+               } while ((i != msg_rx->sg.end) && !sg_is_last(sge));
 
                if (unlikely(peek)) {
                        msg_rx = sk_psock_next_msg(psock, msg_rx);
@@ -471,7 +471,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                }
 
                msg_rx->sg.start = i;
-               if (!sge->length && sg_is_last(sge)) {
+               if (!sge->length && (i == msg_rx->sg.end || sg_is_last(sge))) {
                        msg_rx = sk_psock_dequeue_msg(psock);
                        kfree_sk_msg(msg_rx);
                }
index eb204ad..846588c 100644 (file)
@@ -45,7 +45,7 @@ static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
 
        skb->dev = dsa_master_find_slave(dev, 0, port);
        if (!skb->dev) {
-               netdev_warn(dev, "Failed to get source port: %d\n", port);
+               netdev_warn_once(dev, "Failed to get source port: %d\n", port);
                return NULL;
        }
 
index 718fb77..7889e1e 100644 (file)
@@ -200,8 +200,9 @@ static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len)
        int err = 0;
        struct net_device *dev = NULL;
 
-       if (len < sizeof(*uaddr))
-               return -EINVAL;
+       err = ieee802154_sockaddr_check_size(uaddr, len);
+       if (err < 0)
+               return err;
 
        uaddr = (struct sockaddr_ieee802154 *)_uaddr;
        if (uaddr->family != AF_IEEE802154)
@@ -493,7 +494,8 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
 
        ro->bound = 0;
 
-       if (len < sizeof(*addr))
+       err = ieee802154_sockaddr_check_size(addr, len);
+       if (err < 0)
                goto out;
 
        if (addr->family != AF_IEEE802154)
@@ -564,8 +566,9 @@ static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
        struct dgram_sock *ro = dgram_sk(sk);
        int err = 0;
 
-       if (len < sizeof(*addr))
-               return -EINVAL;
+       err = ieee802154_sockaddr_check_size(addr, len);
+       if (err < 0)
+               return err;
 
        if (addr->family != AF_IEEE802154)
                return -EINVAL;
@@ -604,6 +607,7 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
        struct ieee802154_mac_cb *cb;
        struct dgram_sock *ro = dgram_sk(sk);
        struct ieee802154_addr dst_addr;
+       DECLARE_SOCKADDR(struct sockaddr_ieee802154*, daddr, msg->msg_name);
        int hlen, tlen;
        int err;
 
@@ -612,10 +616,20 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
                return -EOPNOTSUPP;
        }
 
-       if (!ro->connected && !msg->msg_name)
-               return -EDESTADDRREQ;
-       else if (ro->connected && msg->msg_name)
-               return -EISCONN;
+       if (msg->msg_name) {
+               if (ro->connected)
+                       return -EISCONN;
+               if (msg->msg_namelen < IEEE802154_MIN_NAMELEN)
+                       return -EINVAL;
+               err = ieee802154_sockaddr_check_size(daddr, msg->msg_namelen);
+               if (err < 0)
+                       return err;
+               ieee802154_addr_from_sa(&dst_addr, &daddr->addr);
+       } else {
+               if (!ro->connected)
+                       return -EDESTADDRREQ;
+               dst_addr = ro->dst_addr;
+       }
 
        if (!ro->bound)
                dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
@@ -651,16 +665,6 @@ static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
        cb = mac_cb_init(skb);
        cb->type = IEEE802154_FC_TYPE_DATA;
        cb->ackreq = ro->want_ack;
-
-       if (msg->msg_name) {
-               DECLARE_SOCKADDR(struct sockaddr_ieee802154*,
-                                daddr, msg->msg_name);
-
-               ieee802154_addr_from_sa(&dst_addr, &daddr->addr);
-       } else {
-               dst_addr = ro->dst_addr;
-       }
-
        cb->secen = ro->secen;
        cb->secen_override = ro->secen_override;
        cb->seclevel = ro->seclevel;
index f361d3d..943edf4 100644 (file)
@@ -389,7 +389,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
        dev_match = dev_match || (res.type == RTN_LOCAL &&
                                  dev == net->loopback_dev);
        if (dev_match) {
-               ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
+               ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_LINK;
                return ret;
        }
        if (no_addr)
@@ -401,7 +401,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
        ret = 0;
        if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
                if (res.type == RTN_UNICAST)
-                       ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
+                       ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_LINK;
        }
        return ret;
 
index 5c58e21..f866d62 100644 (file)
@@ -609,7 +609,7 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
        ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
                            tunnel_id_to_key32(key->tun_id),
                            key->tos & ~INET_ECN_MASK, dev_net(dev), 0,
-                           skb->mark, skb_get_hash(skb));
+                           skb->mark, skb_get_hash(skb), key->flow_flags);
        rt = ip_route_output_key(dev_net(dev), &fl4);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
index e65e948..019f3b0 100644 (file)
@@ -295,7 +295,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
                ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
                                    iph->saddr, tunnel->parms.o_key,
                                    RT_TOS(iph->tos), dev_net(dev),
-                                   tunnel->parms.link, tunnel->fwmark, 0);
+                                   tunnel->parms.link, tunnel->fwmark, 0, 0);
                rt = ip_route_output_key(tunnel->net, &fl4);
 
                if (!IS_ERR(rt)) {
@@ -570,7 +570,8 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        }
        ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
                            tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
-                           dev_net(dev), 0, skb->mark, skb_get_hash(skb));
+                           dev_net(dev), 0, skb->mark, skb_get_hash(skb),
+                           key->flow_flags);
        if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
                goto tx_error;
 
@@ -729,7 +730,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
                            tunnel->parms.o_key, RT_TOS(tos),
                            dev_net(dev), tunnel->parms.link,
-                           tunnel->fwmark, skb_get_hash(skb));
+                           tunnel->fwmark, skb_get_hash(skb), 0);
 
        if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
                goto tx_error;
index 73651d1..e11d6b0 100644 (file)
@@ -1004,7 +1004,9 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
 
                        rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
                } else {
+                       rcu_read_lock();
                        ip_mr_forward(net, mrt, skb->dev, skb, c, 0);
+                       rcu_read_unlock();
                }
        }
 }
index e5011c1..e373dde 100644 (file)
@@ -1015,7 +1015,7 @@ new_segment:
                skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
        } else {
                get_page(page);
-               skb_fill_page_desc(skb, i, page, offset, copy);
+               skb_fill_page_desc_noacc(skb, i, page, offset, copy);
        }
 
        if (!(flags & MSG_NO_SHARED_FRAGS))
@@ -1761,19 +1761,28 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
        if (sk->sk_state == TCP_LISTEN)
                return -ENOTCONN;
 
-       skb = tcp_recv_skb(sk, seq, &offset);
-       if (!skb)
-               return 0;
+       while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
+               u8 tcp_flags;
+               int used;
 
-       __skb_unlink(skb, &sk->sk_receive_queue);
-       WARN_ON(!skb_set_owner_sk_safe(skb, sk));
-       copied = recv_actor(sk, skb);
-       if (copied >= 0) {
-               seq += copied;
-               if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+               __skb_unlink(skb, &sk->sk_receive_queue);
+               WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
+               tcp_flags = TCP_SKB_CB(skb)->tcp_flags;
+               used = recv_actor(sk, skb);
+               consume_skb(skb);
+               if (used < 0) {
+                       if (!copied)
+                               copied = used;
+                       break;
+               }
+               seq += used;
+               copied += used;
+
+               if (tcp_flags & TCPHDR_FIN) {
                        ++seq;
+                       break;
+               }
        }
-       consume_skb(skb);
        WRITE_ONCE(tp->copied_seq, seq);
 
        tcp_rcv_space_adjust(sk);
index ab5f0ea..bc2ea12 100644 (file)
@@ -2513,6 +2513,21 @@ static inline bool tcp_may_undo(const struct tcp_sock *tp)
        return tp->undo_marker && (!tp->undo_retrans || tcp_packet_delayed(tp));
 }
 
+static bool tcp_is_non_sack_preventing_reopen(struct sock *sk)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) {
+               /* Hold old state until something *above* high_seq
+                * is ACKed. For Reno it is MUST to prevent false
+                * fast retransmits (RFC2582). SACK TCP is safe. */
+               if (!tcp_any_retrans_done(sk))
+                       tp->retrans_stamp = 0;
+               return true;
+       }
+       return false;
+}
+
 /* People celebrate: "We love our President!" */
 static bool tcp_try_undo_recovery(struct sock *sk)
 {
@@ -2535,14 +2550,8 @@ static bool tcp_try_undo_recovery(struct sock *sk)
        } else if (tp->rack.reo_wnd_persist) {
                tp->rack.reo_wnd_persist--;
        }
-       if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) {
-               /* Hold old state until something *above* high_seq
-                * is ACKed. For Reno it is MUST to prevent false
-                * fast retransmits (RFC2582). SACK TCP is safe. */
-               if (!tcp_any_retrans_done(sk))
-                       tp->retrans_stamp = 0;
+       if (tcp_is_non_sack_preventing_reopen(sk))
                return true;
-       }
        tcp_set_ca_state(sk, TCP_CA_Open);
        tp->is_sack_reneg = 0;
        return false;
@@ -2578,6 +2587,8 @@ static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo)
                        NET_INC_STATS(sock_net(sk),
                                        LINUX_MIB_TCPSPURIOUSRTOS);
                inet_csk(sk)->icsk_retransmits = 0;
+               if (tcp_is_non_sack_preventing_reopen(sk))
+                       return true;
                if (frto_undo || tcp_is_sack(tp)) {
                        tcp_set_ca_state(sk, TCP_CA_Open);
                        tp->is_sack_reneg = 0;
@@ -3614,12 +3625,9 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb,
 /* RFC 5961 7 [ACK Throttling] */
 static void tcp_send_challenge_ack(struct sock *sk)
 {
-       /* unprotected vars, we dont care of overwrites */
-       static u32 challenge_timestamp;
-       static unsigned int challenge_count;
        struct tcp_sock *tp = tcp_sk(sk);
        struct net *net = sock_net(sk);
-       u32 count, now;
+       u32 count, now, ack_limit;
 
        /* First check our per-socket dupack rate limit. */
        if (__tcp_oow_rate_limited(net,
@@ -3627,18 +3635,22 @@ static void tcp_send_challenge_ack(struct sock *sk)
                                   &tp->last_oow_ack_time))
                return;
 
+       ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
+       if (ack_limit == INT_MAX)
+               goto send_ack;
+
        /* Then check host-wide RFC 5961 rate limit. */
        now = jiffies / HZ;
-       if (now != challenge_timestamp) {
-               u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
+       if (now != READ_ONCE(net->ipv4.tcp_challenge_timestamp)) {
                u32 half = (ack_limit + 1) >> 1;
 
-               challenge_timestamp = now;
-               WRITE_ONCE(challenge_count, half + prandom_u32_max(ack_limit));
+               WRITE_ONCE(net->ipv4.tcp_challenge_timestamp, now);
+               WRITE_ONCE(net->ipv4.tcp_challenge_count, half + prandom_u32_max(ack_limit));
        }
-       count = READ_ONCE(challenge_count);
+       count = READ_ONCE(net->ipv4.tcp_challenge_count);
        if (count > 0) {
-               WRITE_ONCE(challenge_count, count - 1);
+               WRITE_ONCE(net->ipv4.tcp_challenge_count, count - 1);
+send_ack:
                NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);
                tcp_send_ack(sk);
        }
index 0c83780..5b019ba 100644 (file)
@@ -3139,8 +3139,10 @@ static int __net_init tcp_sk_init(struct net *net)
        net->ipv4.sysctl_tcp_tso_win_divisor = 3;
        /* Default TSQ limit of 16 TSO segments */
        net->ipv4.sysctl_tcp_limit_output_bytes = 16 * 65536;
-       /* rfc5961 challenge ack rate limiting */
-       net->ipv4.sysctl_tcp_challenge_ack_limit = 1000;
+
+       /* rfc5961 challenge ack rate limiting, per net-ns, disabled by default. */
+       net->ipv4.sysctl_tcp_challenge_ack_limit = INT_MAX;
+
        net->ipv4.sysctl_tcp_min_tso_segs = 2;
        net->ipv4.sysctl_tcp_tso_rtt_log = 9;  /* 2^9 = 512 usec */
        net->ipv4.sysctl_tcp_min_rtt_wlen = 300;
index 34eda97..560d9ea 100644 (file)
@@ -783,6 +783,8 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
         */
        if (tunnel) {
                /* ...not for tunnels though: we don't have a sending socket */
+               if (udp_sk(sk)->encap_err_rcv)
+                       udp_sk(sk)->encap_err_rcv(sk, skb, iph->ihl << 2);
                goto out;
        }
        if (!inet->recverr) {
@@ -1819,7 +1821,7 @@ int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                        continue;
                }
 
-               WARN_ON(!skb_set_owner_sk_safe(skb, sk));
+               WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
                used = recv_actor(sk, skb);
                if (used <= 0) {
                        if (!copied)
index 8efaf8c..8242c89 100644 (file)
@@ -72,6 +72,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
 
        udp_sk(sk)->encap_type = cfg->encap_type;
        udp_sk(sk)->encap_rcv = cfg->encap_rcv;
+       udp_sk(sk)->encap_err_rcv = cfg->encap_err_rcv;
        udp_sk(sk)->encap_err_lookup = cfg->encap_err_lookup;
        udp_sk(sk)->encap_destroy = cfg->encap_destroy;
        udp_sk(sk)->gro_receive = cfg->gro_receive;
index e15f64f..10ce86b 100644 (file)
@@ -3557,11 +3557,15 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                fallthrough;
        case NETDEV_UP:
        case NETDEV_CHANGE:
-               if (dev->flags & IFF_SLAVE)
+               if (idev && idev->cnf.disable_ipv6)
                        break;
 
-               if (idev && idev->cnf.disable_ipv6)
+               if (dev->flags & IFF_SLAVE) {
+                       if (event == NETDEV_UP && !IS_ERR_OR_NULL(idev) &&
+                           dev->flags & IFF_UP && dev->flags & IFF_MULTICAST)
+                               ipv6_mc_up(idev);
                        break;
+               }
 
                if (event == NETDEV_UP) {
                        /* restore routes for permanent addresses */
index 2ce0c44..dbb1430 100644 (file)
@@ -1070,13 +1070,13 @@ static int __init inet6_init(void)
        for (r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
                INIT_LIST_HEAD(r);
 
+       raw_hashinfo_init(&raw_v6_hashinfo);
+
        if (disable_ipv6_mod) {
                pr_info("Loaded, but administratively disabled, reboot required to enable\n");
                goto out;
        }
 
-       raw_hashinfo_init(&raw_v6_hashinfo);
-
        err = proto_register(&tcpv6_prot, 1);
        if (err)
                goto out;
index a9ba416..858fd8a 100644 (file)
@@ -1028,8 +1028,11 @@ static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
                                ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
                        }
                        rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
-               } else
+               } else {
+                       rcu_read_lock();
                        ip6_mr_forward(net, mrt, skb->dev, skb, c);
+                       rcu_read_unlock();
+               }
        }
 }
 
index 73aaabf..0b0e34d 100644 (file)
@@ -191,6 +191,11 @@ static int seg6_genl_sethmac(struct sk_buff *skb, struct genl_info *info)
                goto out_unlock;
        }
 
+       if (slen > nla_len(info->attrs[SEG6_ATTR_SECRET])) {
+               err = -EINVAL;
+               goto out_unlock;
+       }
+
        if (hinfo) {
                err = seg6_hmac_info_del(net, hmackeyid);
                if (err)
index 16c176e..3366d6a 100644 (file)
@@ -616,8 +616,11 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        }
 
        /* Tunnels don't have an application socket: don't pass errors back */
-       if (tunnel)
+       if (tunnel) {
+               if (udp_sk(sk)->encap_err_rcv)
+                       udp_sk(sk)->encap_err_rcv(sk, skb, offset);
                goto out;
+       }
 
        if (!np->recverr) {
                if (!harderr || sk->sk_state != TCP_ESTABLISHED)
index 71899e5..1215c86 100644 (file)
@@ -1412,12 +1412,6 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
        psock->sk = csk;
        psock->bpf_prog = prog;
 
-       err = strp_init(&psock->strp, csk, &cb);
-       if (err) {
-               kmem_cache_free(kcm_psockp, psock);
-               goto out;
-       }
-
        write_lock_bh(&csk->sk_callback_lock);
 
        /* Check if sk_user_data is already by KCM or someone else.
@@ -1425,13 +1419,18 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
         */
        if (csk->sk_user_data) {
                write_unlock_bh(&csk->sk_callback_lock);
-               strp_stop(&psock->strp);
-               strp_done(&psock->strp);
                kmem_cache_free(kcm_psockp, psock);
                err = -EALREADY;
                goto out;
        }
 
+       err = strp_init(&psock->strp, csk, &cb);
+       if (err) {
+               write_unlock_bh(&csk->sk_callback_lock);
+               kmem_cache_free(kcm_psockp, psock);
+               goto out;
+       }
+
        psock->save_data_ready = csk->sk_data_ready;
        psock->save_write_space = csk->sk_write_space;
        psock->save_state_change = csk->sk_state_change;
index d56890e..9b283bb 100644 (file)
@@ -530,6 +530,10 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
 
        sdata_assert_lock(sdata);
 
+       /* When not connected/joined, sending CSA doesn't make sense. */
+       if (ifibss->state != IEEE80211_IBSS_MLME_JOINED)
+               return -ENOLINK;
+
        /* update cfg80211 bss information with the new channel */
        if (!is_zero_ether_addr(ifibss->bssid)) {
                cbss = cfg80211_get_bss(sdata->local->hw.wiphy,
index 3d4ab71..fc76498 100644 (file)
@@ -3420,11 +3420,11 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
                ieee80211_link_info_change_notify(sdata, &sdata->deflink,
                                                  BSS_CHANGED_BSSID);
                sdata->u.mgd.flags = 0;
+
                mutex_lock(&sdata->local->mtx);
                ieee80211_link_release_channel(&sdata->deflink);
-               mutex_unlock(&sdata->local->mtx);
-
                ieee80211_vif_set_links(sdata, 0);
+               mutex_unlock(&sdata->local->mtx);
        }
 
        cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
@@ -3462,10 +3462,6 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
                sdata->u.mgd.flags = 0;
                sdata->vif.bss_conf.mu_mimo_owner = false;
 
-               mutex_lock(&sdata->local->mtx);
-               ieee80211_link_release_channel(&sdata->deflink);
-               mutex_unlock(&sdata->local->mtx);
-
                if (status != ASSOC_REJECTED) {
                        struct cfg80211_assoc_failure data = {
                                .timeout = status == ASSOC_TIMEOUT,
@@ -3484,7 +3480,10 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
                        cfg80211_assoc_failure(sdata->dev, &data);
                }
 
+               mutex_lock(&sdata->local->mtx);
+               ieee80211_link_release_channel(&sdata->deflink);
                ieee80211_vif_set_links(sdata, 0);
+               mutex_unlock(&sdata->local->mtx);
        }
 
        kfree(assoc_data);
@@ -4041,7 +4040,6 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
 
        if (!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
            (!elems->he_cap || !elems->he_operation)) {
-               mutex_unlock(&sdata->local->sta_mtx);
                sdata_info(sdata,
                           "HE AP is missing HE capability/operation\n");
                ret = false;
@@ -5590,12 +5588,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
 
        mutex_lock(&local->sta_mtx);
        sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
-       if (WARN_ON(!sta))
+       if (WARN_ON(!sta)) {
+               mutex_unlock(&local->sta_mtx);
                goto free;
+       }
        link_sta = rcu_dereference_protected(sta->link[link->link_id],
                                             lockdep_is_held(&local->sta_mtx));
-       if (WARN_ON(!link_sta))
+       if (WARN_ON(!link_sta)) {
+               mutex_unlock(&local->sta_mtx);
                goto free;
+       }
 
        changed |= ieee80211_recalc_twt_req(link, link_sta, elems);
 
@@ -6509,6 +6511,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
        return 0;
 
 out_err:
+       ieee80211_link_release_channel(&sdata->deflink);
        ieee80211_vif_set_links(sdata, 0);
        return err;
 }
index 5f27e67..788a82f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/random.h>
 #include <linux/moduleparam.h>
 #include <linux/ieee80211.h>
+#include <linux/minmax.h>
 #include <net/mac80211.h>
 #include "rate.h"
 #include "sta_info.h"
@@ -1550,6 +1551,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 {
        struct ieee80211_sta_rates *rates;
        int i = 0;
+       int max_rates = min_t(int, mp->hw->max_rates, IEEE80211_TX_RATE_TABLE_SIZE);
 
        rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
        if (!rates)
@@ -1559,10 +1561,10 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
        minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]);
 
        /* Fill up remaining, keep one entry for max_probe_rate */
-       for (; i < (mp->hw->max_rates - 1); i++)
+       for (; i < (max_rates - 1); i++)
                minstrel_ht_set_rate(mp, mi, rates, i, mi->max_tp_rate[i]);
 
-       if (i < mp->hw->max_rates)
+       if (i < max_rates)
                minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
 
        if (i < IEEE80211_TX_RATE_TABLE_SIZE)
index 57df21e..45d7e71 100644 (file)
@@ -4074,6 +4074,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                .link_id = -1,
        };
        struct tid_ampdu_rx *tid_agg_rx;
+       u8 link_id;
 
        tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
        if (!tid_agg_rx)
@@ -4093,6 +4094,9 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                };
                drv_event_callback(rx.local, rx.sdata, &event);
        }
+       /* FIXME: statistics won't be right with this */
+       link_id = sta->sta.valid_links ? ffs(sta->sta.valid_links) - 1 : 0;
+       rx.link = rcu_dereference(sta->sdata->link[link_id]);
 
        ieee80211_rx_handlers(&rx, &frames);
 }
index fa8ddf5..c4f2aeb 100644 (file)
@@ -469,16 +469,19 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
        scan_req = rcu_dereference_protected(local->scan_req,
                                             lockdep_is_held(&local->mtx));
 
-       if (scan_req != local->int_scan_req) {
-               local->scan_info.aborted = aborted;
-               cfg80211_scan_done(scan_req, &local->scan_info);
-       }
        RCU_INIT_POINTER(local->scan_req, NULL);
        RCU_INIT_POINTER(local->scan_sdata, NULL);
 
        local->scanning = 0;
        local->scan_chandef.chan = NULL;
 
+       synchronize_rcu();
+
+       if (scan_req != local->int_scan_req) {
+               local->scan_info.aborted = aborted;
+               cfg80211_scan_done(scan_req, &local->scan_info);
+       }
+
        /* Set power back to normal operating levels. */
        ieee80211_hw_config(local, 0);
 
index cb23da9..58998d8 100644 (file)
@@ -494,7 +494,7 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        sta->sdata = sdata;
 
        if (sta_info_alloc_link(local, &sta->deflink, gfp))
-               return NULL;
+               goto free;
 
        if (link_id >= 0) {
                sta_info_add_link(sta, link_id, &sta->deflink,
@@ -2316,9 +2316,9 @@ static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats,
        u64 value;
 
        do {
-               start = u64_stats_fetch_begin(&rxstats->syncp);
+               start = u64_stats_fetch_begin_irq(&rxstats->syncp);
                value = rxstats->msdu[tid];
-       } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
 
        return value;
 }
@@ -2384,9 +2384,9 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
        u64 value;
 
        do {
-               start = u64_stats_fetch_begin(&rxstats->syncp);
+               start = u64_stats_fetch_begin_irq(&rxstats->syncp);
                value = rxstats->bytes;
-       } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
 
        return value;
 }
index 8e77fd2..3f9ddd7 100644 (file)
@@ -729,7 +729,7 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
 
                if (!sdata) {
                        skb->dev = NULL;
-               } else {
+               } else if (!dropped) {
                        unsigned int hdr_size =
                                ieee80211_hdrlen(hdr->frame_control);
 
index 45df993..13249e9 100644 (file)
@@ -5878,6 +5878,9 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
        skb_reset_network_header(skb);
        skb_reset_mac_header(skb);
 
+       if (local->hw.queues < IEEE80211_NUM_ACS)
+               goto start_xmit;
+
        /* update QoS header to prioritize control port frames if possible,
         * priorization also happens for control port frames send over
         * AF_PACKET
@@ -5885,6 +5888,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
        rcu_read_lock();
        err = ieee80211_lookup_ra_sta(sdata, skb, &sta);
        if (err) {
+               dev_kfree_skb(skb);
                rcu_read_unlock();
                return err;
        }
@@ -5899,11 +5903,12 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
                 * for MLO STA, the SA should be the AP MLD address, but
                 * the link ID has been selected already
                 */
-               if (sta->sta.mlo)
+               if (sta && sta->sta.mlo)
                        memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
        }
        rcu_read_unlock();
 
+start_xmit:
        /* mutex lock is only needed for incrementing the cookie counter */
        mutex_lock(&local->mtx);
 
index 53826c6..efcefb2 100644 (file)
@@ -301,14 +301,14 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
        local_bh_disable();
        spin_lock(&fq->lock);
 
+       sdata->vif.txqs_stopped[ac] = false;
+
        if (!test_bit(SDATA_STATE_RUNNING, &sdata->state))
                goto out;
 
        if (sdata->vif.type == NL80211_IFTYPE_AP)
                ps = &sdata->bss->ps;
 
-       sdata->vif.txqs_stopped[ac] = false;
-
        list_for_each_entry_rcu(sta, &local->sta_list, list) {
                if (sdata != sta->sdata)
                        continue;
index 93ec2f3..20f742b 100644 (file)
@@ -351,7 +351,7 @@ static u8 ccmp_gcmp_aad(struct sk_buff *skb, u8 *aad)
         * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
        put_unaligned_be16(len_a, &aad[0]);
        put_unaligned(mask_fc, (__le16 *)&aad[2]);
-       memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
+       memcpy(&aad[4], &hdr->addrs, 3 * ETH_ALEN);
 
        /* Mask Seq#, leave Frag# */
        aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
@@ -792,7 +792,7 @@ static void bip_aad(struct sk_buff *skb, u8 *aad)
                                IEEE80211_FCTL_MOREDATA);
        put_unaligned(mask_fc, (__le16 *) &aad[0]);
        /* A1 || A2 || A3 */
-       memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
+       memcpy(aad + 2, &hdr->addrs, 3 * ETH_ALEN);
 }
 
 
index b8ce846..c439125 100644 (file)
@@ -44,7 +44,7 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 
        switch (mac_cb(skb)->dest.mode) {
        case IEEE802154_ADDR_NONE:
-               if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
+               if (hdr->source.mode != IEEE802154_ADDR_NONE)
                        /* FIXME: check if we are PAN coordinator */
                        skb->pkt_type = PACKET_OTHERHOST;
                else
index 35b5f80..b52afe3 100644 (file)
@@ -1079,9 +1079,9 @@ static void mpls_get_stats(struct mpls_dev *mdev,
 
                p = per_cpu_ptr(mdev->stats, i);
                do {
-                       start = u64_stats_fetch_begin(&p->syncp);
+                       start = u64_stats_fetch_begin_irq(&p->syncp);
                        local = p->stats;
-               } while (u64_stats_fetch_retry(&p->syncp, start));
+               } while (u64_stats_fetch_retry_irq(&p->syncp, start));
 
                stats->rx_packets       += local.rx_packets;
                stats->rx_bytes         += local.rx_bytes;
index d398f38..f8897a7 100644 (file)
@@ -150,9 +150,15 @@ static bool mptcp_try_coalesce(struct sock *sk, struct sk_buff *to,
                 MPTCP_SKB_CB(from)->map_seq, MPTCP_SKB_CB(to)->map_seq,
                 to->len, MPTCP_SKB_CB(from)->end_seq);
        MPTCP_SKB_CB(to)->end_seq = MPTCP_SKB_CB(from)->end_seq;
-       kfree_skb_partial(from, fragstolen);
+
+       /* note the fwd memory can reach a negative value after accounting
+        * for the delta, but the later skb free will restore a non
+        * negative one
+        */
        atomic_add(delta, &sk->sk_rmem_alloc);
        mptcp_rmem_charge(sk, delta);
+       kfree_skb_partial(from, fragstolen);
+
        return true;
 }
 
@@ -2656,7 +2662,7 @@ static void __mptcp_clear_xmit(struct sock *sk)
                dfrag_clear(sk, dfrag);
 }
 
-static void mptcp_cancel_work(struct sock *sk)
+void mptcp_cancel_work(struct sock *sk)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
 
@@ -2796,13 +2802,12 @@ static void __mptcp_destroy_sock(struct sock *sk)
        sock_put(sk);
 }
 
-static void mptcp_close(struct sock *sk, long timeout)
+bool __mptcp_close(struct sock *sk, long timeout)
 {
        struct mptcp_subflow_context *subflow;
        struct mptcp_sock *msk = mptcp_sk(sk);
        bool do_cancel_work = false;
 
-       lock_sock(sk);
        sk->sk_shutdown = SHUTDOWN_MASK;
 
        if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
@@ -2844,6 +2849,17 @@ cleanup:
        } else {
                mptcp_reset_timeout(msk, 0);
        }
+
+       return do_cancel_work;
+}
+
+static void mptcp_close(struct sock *sk, long timeout)
+{
+       bool do_cancel_work;
+
+       lock_sock(sk);
+
+       do_cancel_work = __mptcp_close(sk, timeout);
        release_sock(sk);
        if (do_cancel_work)
                mptcp_cancel_work(sk);
index 132d508..8f372b8 100644 (file)
@@ -612,6 +612,8 @@ void mptcp_subflow_reset(struct sock *ssk);
 void mptcp_subflow_queue_clean(struct sock *ssk);
 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);
 
 bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
                           const struct mptcp_addr_info *b, bool use_port);
index c7d49fb..07dd23d 100644 (file)
@@ -602,30 +602,6 @@ static bool subflow_hmac_valid(const struct request_sock *req,
        return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN);
 }
 
-static void mptcp_sock_destruct(struct sock *sk)
-{
-       /* if new mptcp socket isn't accepted, it is free'd
-        * from the tcp listener sockets request queue, linked
-        * from req->sk.  The tcp socket is released.
-        * This calls the ULP release function which will
-        * also remove the mptcp socket, via
-        * sock_put(ctx->conn).
-        *
-        * Problem is that the mptcp socket will be in
-        * ESTABLISHED state and will not have the SOCK_DEAD flag.
-        * Both result in warnings from inet_sock_destruct.
-        */
-       if ((1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
-               sk->sk_state = TCP_CLOSE;
-               WARN_ON_ONCE(sk->sk_socket);
-               sock_orphan(sk);
-       }
-
-       /* We don't need to clear msk->subflow, as it's still NULL at this point */
-       mptcp_destroy_common(mptcp_sk(sk), 0);
-       inet_sock_destruct(sk);
-}
-
 static void mptcp_force_close(struct sock *sk)
 {
        /* the msk is not yet exposed to user-space */
@@ -768,7 +744,6 @@ create_child:
                        /* new mpc subflow takes ownership of the newly
                         * created mptcp socket
                         */
-                       new_msk->sk_destruct = mptcp_sock_destruct;
                        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));
@@ -1763,13 +1738,19 @@ void mptcp_subflow_queue_clean(struct sock *listener_ssk)
 
        for (msk = head; msk; msk = next) {
                struct sock *sk = (struct sock *)msk;
-               bool slow;
+               bool slow, do_cancel_work;
 
+               sock_hold(sk);
                slow = lock_sock_fast_nested(sk);
                next = msk->dl_next;
                msk->first = NULL;
                msk->dl_next = NULL;
+
+               do_cancel_work = __mptcp_close(sk, 0);
                unlock_sock_fast(sk, slow);
+               if (do_cancel_work)
+                       mptcp_cancel_work(sk);
+               sock_put(sk);
        }
 
        /* we are still under the listener msk socket lock */
index 71c2f4f..1357a27 100644 (file)
@@ -1782,7 +1782,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
                }
                spin_unlock_bh(&nf_conntrack_expect_lock);
        }
-       if (!exp)
+       if (!exp && tmpl)
                __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC);
 
        /* Other CPU might have obtained a pointer to this object before it was
@@ -2068,10 +2068,6 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
        ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
        if (ct->master || (help && !hlist_empty(&help->expectations)))
                return;
-
-       rcu_read_lock();
-       __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
-       rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
 
@@ -2797,7 +2793,6 @@ int nf_conntrack_init_net(struct net *net)
        nf_conntrack_acct_pernet_init(net);
        nf_conntrack_tstamp_pernet_init(net);
        nf_conntrack_ecache_pernet_init(net);
-       nf_conntrack_helper_pernet_init(net);
        nf_conntrack_proto_pernet_init(net);
 
        return 0;
index 0d9332e..617f744 100644 (file)
@@ -33,6 +33,7 @@ MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
 MODULE_DESCRIPTION("ftp connection tracking helper");
 MODULE_ALIAS("ip_conntrack_ftp");
 MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
+static DEFINE_SPINLOCK(nf_ftp_lock);
 
 #define MAX_PORTS 8
 static u_int16_t ports[MAX_PORTS];
@@ -409,7 +410,8 @@ static int help(struct sk_buff *skb,
        }
        datalen = skb->len - dataoff;
 
-       spin_lock_bh(&ct->lock);
+       /* seqadj (nat) uses ct->lock internally, nf_nat_ftp would cause deadlock */
+       spin_lock_bh(&nf_ftp_lock);
        fb_ptr = skb->data + dataoff;
 
        ends_in_nl = (fb_ptr[datalen - 1] == '\n');
@@ -538,7 +540,7 @@ out_update_nl:
        if (ends_in_nl)
                update_nl_seq(ct, seq, ct_ftp_info, dir, skb);
  out:
-       spin_unlock_bh(&ct->lock);
+       spin_unlock_bh(&nf_ftp_lock);
        return ret;
 }
 
index e96b322..ff737a7 100644 (file)
@@ -35,11 +35,6 @@ unsigned int nf_ct_helper_hsize __read_mostly;
 EXPORT_SYMBOL_GPL(nf_ct_helper_hsize);
 static unsigned int nf_ct_helper_count __read_mostly;
 
-static bool nf_ct_auto_assign_helper __read_mostly = false;
-module_param_named(nf_conntrack_helper, nf_ct_auto_assign_helper, bool, 0644);
-MODULE_PARM_DESC(nf_conntrack_helper,
-                "Enable automatic conntrack helper assignment (default 0)");
-
 static DEFINE_MUTEX(nf_ct_nat_helpers_mutex);
 static struct list_head nf_ct_nat_helpers __read_mostly;
 
@@ -51,24 +46,6 @@ static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
                (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize;
 }
 
-static struct nf_conntrack_helper *
-__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
-{
-       struct nf_conntrack_helper *helper;
-       struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
-       unsigned int h;
-
-       if (!nf_ct_helper_count)
-               return NULL;
-
-       h = helper_hash(tuple);
-       hlist_for_each_entry_rcu(helper, &nf_ct_helper_hash[h], hnode) {
-               if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask))
-                       return helper;
-       }
-       return NULL;
-}
-
 struct nf_conntrack_helper *
 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
 {
@@ -209,33 +186,11 @@ nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
 
-static struct nf_conntrack_helper *
-nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
-{
-       struct nf_conntrack_net *cnet = nf_ct_pernet(net);
-
-       if (!cnet->sysctl_auto_assign_helper) {
-               if (cnet->auto_assign_helper_warned)
-                       return NULL;
-               if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple))
-                       return NULL;
-               pr_info("nf_conntrack: default automatic helper assignment "
-                       "has been turned off for security reasons and CT-based "
-                       "firewall rule not found. Use the iptables CT target "
-                       "to attach helpers instead.\n");
-               cnet->auto_assign_helper_warned = true;
-               return NULL;
-       }
-
-       return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-}
-
 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
                              gfp_t flags)
 {
        struct nf_conntrack_helper *helper = NULL;
        struct nf_conn_help *help;
-       struct net *net = nf_ct_net(ct);
 
        /* We already got a helper explicitly attached. The function
         * nf_conntrack_alter_reply - in case NAT is in use - asks for looking
@@ -246,23 +201,21 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
        if (test_bit(IPS_HELPER_BIT, &ct->status))
                return 0;
 
-       if (tmpl != NULL) {
-               help = nfct_help(tmpl);
-               if (help != NULL) {
-                       helper = rcu_dereference(help->helper);
-                       set_bit(IPS_HELPER_BIT, &ct->status);
-               }
+       if (WARN_ON_ONCE(!tmpl))
+               return 0;
+
+       help = nfct_help(tmpl);
+       if (help != NULL) {
+               helper = rcu_dereference(help->helper);
+               set_bit(IPS_HELPER_BIT, &ct->status);
        }
 
        help = nfct_help(ct);
 
        if (helper == NULL) {
-               helper = nf_ct_lookup_helper(ct, net);
-               if (helper == NULL) {
-                       if (help)
-                               RCU_INIT_POINTER(help->helper, NULL);
-                       return 0;
-               }
+               if (help)
+                       RCU_INIT_POINTER(help->helper, NULL);
+               return 0;
        }
 
        if (help == NULL) {
@@ -545,19 +498,6 @@ void nf_nat_helper_unregister(struct nf_conntrack_nat_helper *nat)
 }
 EXPORT_SYMBOL_GPL(nf_nat_helper_unregister);
 
-void nf_ct_set_auto_assign_helper_warned(struct net *net)
-{
-       nf_ct_pernet(net)->auto_assign_helper_warned = true;
-}
-EXPORT_SYMBOL_GPL(nf_ct_set_auto_assign_helper_warned);
-
-void nf_conntrack_helper_pernet_init(struct net *net)
-{
-       struct nf_conntrack_net *cnet = nf_ct_pernet(net);
-
-       cnet->sysctl_auto_assign_helper = nf_ct_auto_assign_helper;
-}
-
 int nf_conntrack_helper_init(void)
 {
        nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
index 1796c45..5703846 100644 (file)
@@ -157,15 +157,37 @@ static int help(struct sk_buff *skb, unsigned int protoff,
        data = ib_ptr;
        data_limit = ib_ptr + datalen;
 
-       /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
-        * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
-       while (data < data_limit - (19 + MINMATCHLEN)) {
-               if (memcmp(data, "\1DCC ", 5)) {
+       /* Skip any whitespace */
+       while (data < data_limit - 10) {
+               if (*data == ' ' || *data == '\r' || *data == '\n')
+                       data++;
+               else
+                       break;
+       }
+
+       /* strlen("PRIVMSG x ")=10 */
+       if (data < data_limit - 10) {
+               if (strncasecmp("PRIVMSG ", data, 8))
+                       goto out;
+               data += 8;
+       }
+
+       /* strlen(" :\1DCC SENT t AAAAAAAA P\1\n")=26
+        * 7+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=26
+        */
+       while (data < data_limit - (21 + MINMATCHLEN)) {
+               /* Find first " :", the start of message */
+               if (memcmp(data, " :", 2)) {
                        data++;
                        continue;
                }
+               data += 2;
+
+               /* then check that place only for the DCC command */
+               if (memcmp(data, "\1DCC ", 5))
+                       goto out;
                data += 5;
-               /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
+               /* we have at least (21+MINMATCHLEN)-(2+5) bytes valid data left */
 
                iph = ip_hdr(skb);
                pr_debug("DCC found in master %pI4:%u %pI4:%u\n",
@@ -181,7 +203,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
                        pr_debug("DCC %s detected\n", dccprotos[i]);
 
                        /* we have at least
-                        * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
+                        * (21+MINMATCHLEN)-7-dccprotos[i].matchlen bytes valid
                         * data left (== 14/13 bytes) */
                        if (parse_dcc(data, data_limit, &dcc_ip,
                                       &dcc_port, &addr_beg_p, &addr_end_p)) {
@@ -194,8 +216,9 @@ static int help(struct sk_buff *skb, unsigned int protoff,
 
                        /* dcc_ip can be the internal OR external (NAT'ed) IP */
                        tuple = &ct->tuplehash[dir].tuple;
-                       if (tuple->src.u3.ip != dcc_ip &&
-                           tuple->dst.u3.ip != dcc_ip) {
+                       if ((tuple->src.u3.ip != dcc_ip &&
+                            ct->tuplehash[!dir].tuple.dst.u3.ip != dcc_ip) ||
+                           dcc_port == 0) {
                                net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
                                                     &tuple->src.u3.ip,
                                                     &dcc_ip, dcc_port);
index 04169b5..7562b21 100644 (file)
@@ -2298,11 +2298,6 @@ ctnetlink_create_conntrack(struct net *net,
                        ct->status |= IPS_HELPER;
                        RCU_INIT_POINTER(help->helper, helper);
                }
-       } else {
-               /* try an implicit helper assignation */
-               err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
-               if (err < 0)
-                       goto err2;
        }
 
        err = ctnetlink_setup_nat(ct, cda);
index daf06f7..77f5e82 100644 (file)
@@ -477,7 +477,7 @@ static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
                                return ret;
                        if (ret == 0)
                                break;
-                       dataoff += *matchoff;
+                       dataoff = *matchoff;
                }
                *in_header = 0;
        }
@@ -489,7 +489,7 @@ static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
                        break;
                if (ret == 0)
                        return ret;
-               dataoff += *matchoff;
+               dataoff = *matchoff;
        }
 
        if (in_header)
index 0589587..4ffe84c 100644 (file)
@@ -561,7 +561,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_LOG_INVALID,
        NF_SYSCTL_CT_EXPECT_MAX,
        NF_SYSCTL_CT_ACCT,
-       NF_SYSCTL_CT_HELPER,
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
        NF_SYSCTL_CT_EVENTS,
 #endif
@@ -680,14 +679,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .extra1         = SYSCTL_ZERO,
                .extra2         = SYSCTL_ONE,
        },
-       [NF_SYSCTL_CT_HELPER] = {
-               .procname       = "nf_conntrack_helper",
-               .maxlen         = sizeof(u8),
-               .mode           = 0644,
-               .proc_handler   = proc_dou8vec_minmax,
-               .extra1         = SYSCTL_ZERO,
-               .extra2         = SYSCTL_ONE,
-       },
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
        [NF_SYSCTL_CT_EVENTS] = {
                .procname       = "nf_conntrack_events",
@@ -1100,7 +1091,6 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
        table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum;
        table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid;
        table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct;
-       table[NF_SYSCTL_CT_HELPER].data = &cnet->sysctl_auto_assign_helper;
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
        table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events;
 #endif
index 2ee50e2..63c7014 100644 (file)
@@ -2166,8 +2166,10 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
        chain->flags |= NFT_CHAIN_BASE | flags;
        basechain->policy = NF_ACCEPT;
        if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
-           !nft_chain_offload_support(basechain))
+           !nft_chain_offload_support(basechain)) {
+               list_splice_init(&basechain->hook_list, &hook->list);
                return -EOPNOTSUPP;
+       }
 
        flow_block_init(&basechain->flow_block);
 
@@ -2195,7 +2197,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                              struct netlink_ext_ack *extack)
 {
        const struct nlattr * const *nla = ctx->nla;
-       struct nft_stats __percpu *stats = NULL;
        struct nft_table *table = ctx->table;
        struct nft_base_chain *basechain;
        struct net *net = ctx->net;
@@ -2210,6 +2211,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                return -EOVERFLOW;
 
        if (nla[NFTA_CHAIN_HOOK]) {
+               struct nft_stats __percpu *stats = NULL;
                struct nft_chain_hook hook;
 
                if (flags & NFT_CHAIN_BINDING)
@@ -2241,8 +2243,11 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                if (err < 0) {
                        nft_chain_release_hook(&hook);
                        kfree(basechain);
+                       free_percpu(stats);
                        return err;
                }
+               if (stats)
+                       static_branch_inc(&nft_counters_enabled);
        } else {
                if (flags & NFT_CHAIN_BASE)
                        return -EINVAL;
@@ -2317,9 +2322,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                goto err_unregister_hook;
        }
 
-       if (stats)
-               static_branch_inc(&nft_counters_enabled);
-
        table->use++;
 
        return 0;
index 0fa2e20..ee6840b 100644 (file)
@@ -269,6 +269,7 @@ bool nf_osf_find(const struct sk_buff *skb,
        struct nf_osf_hdr_ctx ctx;
        const struct tcphdr *tcp;
        struct tcphdr _tcph;
+       bool found = false;
 
        memset(&ctx, 0, sizeof(ctx));
 
@@ -283,10 +284,11 @@ bool nf_osf_find(const struct sk_buff *skb,
 
                data->genre = f->genre;
                data->version = f->version;
+               found = true;
                break;
        }
 
-       return true;
+       return found;
 }
 EXPORT_SYMBOL_GPL(nf_osf_find);
 
index b04995c..a3f01f2 100644 (file)
@@ -1089,9 +1089,6 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
        if (err < 0)
                goto err_put_helper;
 
-       /* Avoid the bogus warning, helper will be assigned after CT init */
-       nf_ct_set_auto_assign_helper_warned(ctx->net);
-
        return 0;
 
 err_put_helper:
index 7e8a39a..6c9d153 100644 (file)
@@ -1802,7 +1802,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
                                ovs_dp_reset_user_features(skb, info);
                }
 
-               goto err_unlock_and_destroy_meters;
+               goto err_destroy_portids;
        }
 
        err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
@@ -1817,6 +1817,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        ovs_notify(&dp_datapath_genl_family, reply, info);
        return 0;
 
+err_destroy_portids:
+       kfree(rcu_dereference_raw(dp->upcall_portids));
 err_unlock_and_destroy_meters:
        ovs_unlock();
        ovs_meters_exit(dp);
index 5714360..62c7070 100644 (file)
@@ -982,6 +982,7 @@ void rxrpc_send_keepalive(struct rxrpc_peer *);
 /*
  * peer_event.c
  */
+void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, unsigned int udp_offset);
 void rxrpc_error_report(struct sock *);
 void rxrpc_peer_keepalive_worker(struct work_struct *);
 
index f8ecad2..2a93e7b 100644 (file)
@@ -166,7 +166,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
        _enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
 
        now = ktime_get_real();
-       max_age = ktime_sub(now, jiffies_to_usecs(call->peer->rto_j));
+       max_age = ktime_sub_us(now, jiffies_to_usecs(call->peer->rto_j));
 
        spin_lock_bh(&call->lock);
 
index 96ecb73..38ea98f 100644 (file)
@@ -137,6 +137,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
 
        tuncfg.encap_type = UDP_ENCAP_RXRPC;
        tuncfg.encap_rcv = rxrpc_input_packet;
+       tuncfg.encap_err_rcv = rxrpc_encap_err_rcv;
        tuncfg.sk_user_data = local;
        setup_udp_tunnel_sock(net, local->socket, &tuncfg);
 
@@ -405,6 +406,9 @@ static void rxrpc_local_processor(struct work_struct *work)
                container_of(work, struct rxrpc_local, processor);
        bool again;
 
+       if (local->dead)
+               return;
+
        trace_rxrpc_local(local->debug_id, rxrpc_local_processing,
                          refcount_read(&local->ref), NULL);
 
index be03285..32561e9 100644 (file)
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
 #include <net/ip.h>
+#include <net/icmp.h>
 #include "ar-internal.h"
 
+static void rxrpc_adjust_mtu(struct rxrpc_peer *, unsigned int);
 static void rxrpc_store_error(struct rxrpc_peer *, struct sock_exterr_skb *);
 static void rxrpc_distribute_error(struct rxrpc_peer *, int,
                                   enum rxrpc_call_completion);
 
 /*
- * Find the peer associated with an ICMP packet.
+ * Find the peer associated with an ICMPv4 packet.
  */
 static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
-                                                    const struct sk_buff *skb,
+                                                    struct sk_buff *skb,
+                                                    unsigned int udp_offset,
+                                                    unsigned int *info,
                                                     struct sockaddr_rxrpc *srx)
 {
-       struct sock_exterr_skb *serr = SKB_EXT_ERR(skb);
+       struct iphdr *ip, *ip0 = ip_hdr(skb);
+       struct icmphdr *icmp = icmp_hdr(skb);
+       struct udphdr *udp = (struct udphdr *)(skb->data + udp_offset);
 
-       _enter("");
+       _enter("%u,%u,%u", ip0->protocol, icmp->type, icmp->code);
+
+       switch (icmp->type) {
+       case ICMP_DEST_UNREACH:
+               *info = ntohs(icmp->un.frag.mtu);
+               fallthrough;
+       case ICMP_TIME_EXCEEDED:
+       case ICMP_PARAMETERPROB:
+               ip = (struct iphdr *)((void *)icmp + 8);
+               break;
+       default:
+               return NULL;
+       }
+
+       memset(srx, 0, sizeof(*srx));
+       srx->transport_type = local->srx.transport_type;
+       srx->transport_len = local->srx.transport_len;
+       srx->transport.family = local->srx.transport.family;
+
+       /* Can we see an ICMP4 packet on an ICMP6 listening socket?  and vice
+        * versa?
+        */
+       switch (srx->transport.family) {
+       case AF_INET:
+               srx->transport_len = sizeof(srx->transport.sin);
+               srx->transport.family = AF_INET;
+               srx->transport.sin.sin_port = udp->dest;
+               memcpy(&srx->transport.sin.sin_addr, &ip->daddr,
+                      sizeof(struct in_addr));
+               break;
+
+#ifdef CONFIG_AF_RXRPC_IPV6
+       case AF_INET6:
+               srx->transport_len = sizeof(srx->transport.sin);
+               srx->transport.family = AF_INET;
+               srx->transport.sin.sin_port = udp->dest;
+               memcpy(&srx->transport.sin.sin_addr, &ip->daddr,
+                      sizeof(struct in_addr));
+               break;
+#endif
+
+       default:
+               WARN_ON_ONCE(1);
+               return NULL;
+       }
+
+       _net("ICMP {%pISp}", &srx->transport);
+       return rxrpc_lookup_peer_rcu(local, srx);
+}
+
+#ifdef CONFIG_AF_RXRPC_IPV6
+/*
+ * Find the peer associated with an ICMPv6 packet.
+ */
+static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local,
+                                                     struct sk_buff *skb,
+                                                     unsigned int udp_offset,
+                                                     unsigned int *info,
+                                                     struct sockaddr_rxrpc *srx)
+{
+       struct icmp6hdr *icmp = icmp6_hdr(skb);
+       struct ipv6hdr *ip, *ip0 = ipv6_hdr(skb);
+       struct udphdr *udp = (struct udphdr *)(skb->data + udp_offset);
+
+       _enter("%u,%u,%u", ip0->nexthdr, icmp->icmp6_type, icmp->icmp6_code);
+
+       switch (icmp->icmp6_type) {
+       case ICMPV6_DEST_UNREACH:
+               *info = ntohl(icmp->icmp6_mtu);
+               fallthrough;
+       case ICMPV6_PKT_TOOBIG:
+       case ICMPV6_TIME_EXCEED:
+       case ICMPV6_PARAMPROB:
+               ip = (struct ipv6hdr *)((void *)icmp + 8);
+               break;
+       default:
+               return NULL;
+       }
 
        memset(srx, 0, sizeof(*srx));
        srx->transport_type = local->srx.transport_type;
@@ -43,6 +126,165 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
         */
        switch (srx->transport.family) {
        case AF_INET:
+               _net("Rx ICMP6 on v4 sock");
+               srx->transport_len = sizeof(srx->transport.sin);
+               srx->transport.family = AF_INET;
+               srx->transport.sin.sin_port = udp->dest;
+               memcpy(&srx->transport.sin.sin_addr,
+                      &ip->daddr.s6_addr32[3], sizeof(struct in_addr));
+               break;
+       case AF_INET6:
+               _net("Rx ICMP6");
+               srx->transport.sin.sin_port = udp->dest;
+               memcpy(&srx->transport.sin6.sin6_addr, &ip->daddr,
+                      sizeof(struct in6_addr));
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return NULL;
+       }
+
+       _net("ICMP {%pISp}", &srx->transport);
+       return rxrpc_lookup_peer_rcu(local, srx);
+}
+#endif /* CONFIG_AF_RXRPC_IPV6 */
+
+/*
+ * Handle an error received on the local endpoint as a tunnel.
+ */
+void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
+                        unsigned int udp_offset)
+{
+       struct sock_extended_err ee;
+       struct sockaddr_rxrpc srx;
+       struct rxrpc_local *local;
+       struct rxrpc_peer *peer;
+       unsigned int info = 0;
+       int err;
+       u8 version = ip_hdr(skb)->version;
+       u8 type = icmp_hdr(skb)->type;
+       u8 code = icmp_hdr(skb)->code;
+
+       rcu_read_lock();
+       local = rcu_dereference_sk_user_data(sk);
+       if (unlikely(!local)) {
+               rcu_read_unlock();
+               return;
+       }
+
+       rxrpc_new_skb(skb, rxrpc_skb_received);
+
+       switch (ip_hdr(skb)->version) {
+       case IPVERSION:
+               peer = rxrpc_lookup_peer_icmp_rcu(local, skb, udp_offset,
+                                                 &info, &srx);
+               break;
+#ifdef CONFIG_AF_RXRPC_IPV6
+       case 6:
+               peer = rxrpc_lookup_peer_icmp6_rcu(local, skb, udp_offset,
+                                                  &info, &srx);
+               break;
+#endif
+       default:
+               rcu_read_unlock();
+               return;
+       }
+
+       if (peer && !rxrpc_get_peer_maybe(peer))
+               peer = NULL;
+       if (!peer) {
+               rcu_read_unlock();
+               return;
+       }
+
+       memset(&ee, 0, sizeof(ee));
+
+       switch (version) {
+       case IPVERSION:
+               switch (type) {
+               case ICMP_DEST_UNREACH:
+                       switch (code) {
+                       case ICMP_FRAG_NEEDED:
+                               rxrpc_adjust_mtu(peer, info);
+                               rcu_read_unlock();
+                               rxrpc_put_peer(peer);
+                               return;
+                       default:
+                               break;
+                       }
+
+                       err = EHOSTUNREACH;
+                       if (code <= NR_ICMP_UNREACH) {
+                               /* Might want to do something different with
+                                * non-fatal errors
+                                */
+                               //harderr = icmp_err_convert[code].fatal;
+                               err = icmp_err_convert[code].errno;
+                       }
+                       break;
+
+               case ICMP_TIME_EXCEEDED:
+                       err = EHOSTUNREACH;
+                       break;
+               default:
+                       err = EPROTO;
+                       break;
+               }
+
+               ee.ee_origin = SO_EE_ORIGIN_ICMP;
+               ee.ee_type = type;
+               ee.ee_code = code;
+               ee.ee_errno = err;
+               break;
+
+#ifdef CONFIG_AF_RXRPC_IPV6
+       case 6:
+               switch (type) {
+               case ICMPV6_PKT_TOOBIG:
+                       rxrpc_adjust_mtu(peer, info);
+                       rcu_read_unlock();
+                       rxrpc_put_peer(peer);
+                       return;
+               }
+
+               icmpv6_err_convert(type, code, &err);
+
+               if (err == EACCES)
+                       err = EHOSTUNREACH;
+
+               ee.ee_origin = SO_EE_ORIGIN_ICMP6;
+               ee.ee_type = type;
+               ee.ee_code = code;
+               ee.ee_errno = err;
+               break;
+#endif
+       }
+
+       trace_rxrpc_rx_icmp(peer, &ee, &srx);
+
+       rxrpc_distribute_error(peer, err, RXRPC_CALL_NETWORK_ERROR);
+       rcu_read_unlock();
+       rxrpc_put_peer(peer);
+}
+
+/*
+ * Find the peer associated with a local error.
+ */
+static struct rxrpc_peer *rxrpc_lookup_peer_local_rcu(struct rxrpc_local *local,
+                                                     const struct sk_buff *skb,
+                                                     struct sockaddr_rxrpc *srx)
+{
+       struct sock_exterr_skb *serr = SKB_EXT_ERR(skb);
+
+       _enter("");
+
+       memset(srx, 0, sizeof(*srx));
+       srx->transport_type = local->srx.transport_type;
+       srx->transport_len = local->srx.transport_len;
+       srx->transport.family = local->srx.transport.family;
+
+       switch (srx->transport.family) {
+       case AF_INET:
                srx->transport_len = sizeof(srx->transport.sin);
                srx->transport.family = AF_INET;
                srx->transport.sin.sin_port = serr->port;
@@ -104,10 +346,8 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
 /*
  * Handle an MTU/fragmentation problem.
  */
-static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, struct sock_exterr_skb *serr)
+static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, unsigned int mtu)
 {
-       u32 mtu = serr->ee.ee_info;
-
        _net("Rx ICMP Fragmentation Needed (%d)", mtu);
 
        /* wind down the local interface MTU */
@@ -148,7 +388,7 @@ void rxrpc_error_report(struct sock *sk)
        struct sock_exterr_skb *serr;
        struct sockaddr_rxrpc srx;
        struct rxrpc_local *local;
-       struct rxrpc_peer *peer;
+       struct rxrpc_peer *peer = NULL;
        struct sk_buff *skb;
 
        rcu_read_lock();
@@ -172,41 +412,20 @@ void rxrpc_error_report(struct sock *sk)
        }
        rxrpc_new_skb(skb, rxrpc_skb_received);
        serr = SKB_EXT_ERR(skb);
-       if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
-               _leave("UDP empty message");
-               rcu_read_unlock();
-               rxrpc_free_skb(skb, rxrpc_skb_freed);
-               return;
-       }
 
-       peer = rxrpc_lookup_peer_icmp_rcu(local, skb, &srx);
-       if (peer && !rxrpc_get_peer_maybe(peer))
-               peer = NULL;
-       if (!peer) {
-               rcu_read_unlock();
-               rxrpc_free_skb(skb, rxrpc_skb_freed);
-               _leave(" [no peer]");
-               return;
-       }
-
-       trace_rxrpc_rx_icmp(peer, &serr->ee, &srx);
-
-       if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP &&
-            serr->ee.ee_type == ICMP_DEST_UNREACH &&
-            serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
-               rxrpc_adjust_mtu(peer, serr);
-               rcu_read_unlock();
-               rxrpc_free_skb(skb, rxrpc_skb_freed);
-               rxrpc_put_peer(peer);
-               _leave(" [MTU update]");
-               return;
+       if (serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL) {
+               peer = rxrpc_lookup_peer_local_rcu(local, skb, &srx);
+               if (peer && !rxrpc_get_peer_maybe(peer))
+                       peer = NULL;
+               if (peer) {
+                       trace_rxrpc_rx_icmp(peer, &serr->ee, &srx);
+                       rxrpc_store_error(peer, serr);
+               }
        }
 
-       rxrpc_store_error(peer, serr);
        rcu_read_unlock();
        rxrpc_free_skb(skb, rxrpc_skb_freed);
        rxrpc_put_peer(peer);
-
        _leave("");
 }
 
index 250f23b..7e39c26 100644 (file)
@@ -771,46 +771,3 @@ call_complete:
        goto out;
 }
 EXPORT_SYMBOL(rxrpc_kernel_recv_data);
-
-/**
- * rxrpc_kernel_get_reply_time - Get timestamp on first reply packet
- * @sock: The socket that the call exists on
- * @call: The call to query
- * @_ts: Where to put the timestamp
- *
- * Retrieve the timestamp from the first DATA packet of the reply if it is
- * in the ring.  Returns true if successful, false if not.
- */
-bool rxrpc_kernel_get_reply_time(struct socket *sock, struct rxrpc_call *call,
-                                ktime_t *_ts)
-{
-       struct sk_buff *skb;
-       rxrpc_seq_t hard_ack, top, seq;
-       bool success = false;
-
-       mutex_lock(&call->user_mutex);
-
-       if (READ_ONCE(call->state) != RXRPC_CALL_CLIENT_RECV_REPLY)
-               goto out;
-
-       hard_ack = call->rx_hard_ack;
-       if (hard_ack != 0)
-               goto out;
-
-       seq = hard_ack + 1;
-       top = smp_load_acquire(&call->rx_top);
-       if (after(seq, top))
-               goto out;
-
-       skb = call->rxtx_buffer[seq & RXRPC_RXTX_BUFF_MASK];
-       if (!skb)
-               goto out;
-
-       *_ts = skb_get_ktime(skb);
-       success = true;
-
-out:
-       mutex_unlock(&call->user_mutex);
-       return success;
-}
-EXPORT_SYMBOL(rxrpc_kernel_get_reply_time);
index 258917a..78fa052 100644 (file)
@@ -540,7 +540,7 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
         * directly into the target buffer.
         */
        sg = _sg;
-       nsg = skb_shinfo(skb)->nr_frags;
+       nsg = skb_shinfo(skb)->nr_frags + 1;
        if (nsg <= 4) {
                nsg = 4;
        } else {
index d55afb8..5950974 100644 (file)
@@ -1394,7 +1394,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
 
        err = tcf_ct_flow_table_get(net, params);
        if (err)
-               goto cleanup;
+               goto cleanup_params;
 
        spin_lock_bh(&c->tcf_lock);
        goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
@@ -1409,6 +1409,9 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
 
        return res;
 
+cleanup_params:
+       if (params->tmpl)
+               nf_ct_put(params->tmpl);
 cleanup:
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
index 790d680..51d175f 100644 (file)
@@ -2137,6 +2137,7 @@ replay:
        }
 
        if (chain->tmplt_ops && chain->tmplt_ops != tp->ops) {
+               tfilter_put(tp, fh);
                NL_SET_ERR_MSG(extack, "Chain template is set to a different filter kind");
                err = -EINVAL;
                goto errout;
index 99b697a..7a8ea03 100644 (file)
@@ -1122,6 +1122,21 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
 }
 EXPORT_SYMBOL(dev_graft_qdisc);
 
+static void shutdown_scheduler_queue(struct net_device *dev,
+                                    struct netdev_queue *dev_queue,
+                                    void *_qdisc_default)
+{
+       struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
+       struct Qdisc *qdisc_default = _qdisc_default;
+
+       if (qdisc) {
+               rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
+               dev_queue->qdisc_sleeping = qdisc_default;
+
+               qdisc_put(qdisc);
+       }
+}
+
 static void attach_one_default_qdisc(struct net_device *dev,
                                     struct netdev_queue *dev_queue,
                                     void *_unused)
@@ -1169,6 +1184,7 @@ static void attach_default_qdiscs(struct net_device *dev)
        if (qdisc == &noop_qdisc) {
                netdev_warn(dev, "default qdisc (%s) fail, fallback to %s\n",
                            default_qdisc_ops->id, noqueue_qdisc_ops.id);
+               netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
                dev->priv_flags |= IFF_NO_QUEUE;
                netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);
                qdisc = txq->qdisc_sleeping;
@@ -1447,21 +1463,6 @@ void dev_init_scheduler(struct net_device *dev)
        timer_setup(&dev->watchdog_timer, dev_watchdog, 0);
 }
 
-static void shutdown_scheduler_queue(struct net_device *dev,
-                                    struct netdev_queue *dev_queue,
-                                    void *_qdisc_default)
-{
-       struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
-       struct Qdisc *qdisc_default = _qdisc_default;
-
-       if (qdisc) {
-               rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
-               dev_queue->qdisc_sleeping = qdisc_default;
-
-               qdisc_put(qdisc);
-       }
-}
-
 void dev_shutdown(struct net_device *dev)
 {
        netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
index 3d061a1..2829455 100644 (file)
@@ -135,15 +135,15 @@ static void increment_one_qlen(u32 sfbhash, u32 slot, struct sfb_sched_data *q)
        }
 }
 
-static void increment_qlen(const struct sk_buff *skb, struct sfb_sched_data *q)
+static void increment_qlen(const struct sfb_skb_cb *cb, struct sfb_sched_data *q)
 {
        u32 sfbhash;
 
-       sfbhash = sfb_hash(skb, 0);
+       sfbhash = cb->hashes[0];
        if (sfbhash)
                increment_one_qlen(sfbhash, 0, q);
 
-       sfbhash = sfb_hash(skb, 1);
+       sfbhash = cb->hashes[1];
        if (sfbhash)
                increment_one_qlen(sfbhash, 1, q);
 }
@@ -281,8 +281,10 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 {
 
        struct sfb_sched_data *q = qdisc_priv(sch);
+       unsigned int len = qdisc_pkt_len(skb);
        struct Qdisc *child = q->qdisc;
        struct tcf_proto *fl;
+       struct sfb_skb_cb cb;
        int i;
        u32 p_min = ~0;
        u32 minqlen = ~0;
@@ -399,11 +401,12 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
 
 enqueue:
+       memcpy(&cb, sfb_skb_cb(skb), sizeof(cb));
        ret = qdisc_enqueue(skb, child, to_free);
        if (likely(ret == NET_XMIT_SUCCESS)) {
-               qdisc_qstats_backlog_inc(sch, skb);
+               sch->qstats.backlog += len;
                sch->q.qlen++;
-               increment_qlen(skb, q);
+               increment_qlen(&cb, q);
        } else if (net_xmit_drop_count(ret)) {
                q->stats.childdrop++;
                qdisc_qstats_drop(sch);
index 0b941dd..86675a7 100644 (file)
@@ -67,6 +67,7 @@ struct taprio_sched {
        u32 flags;
        enum tk_offsets tk_offset;
        int clockid;
+       bool offloaded;
        atomic64_t picos_per_byte; /* Using picoseconds because for 10Gbps+
                                    * speeds it's sub-nanoseconds per byte
                                    */
@@ -1279,6 +1280,8 @@ static int taprio_enable_offload(struct net_device *dev,
                goto done;
        }
 
+       q->offloaded = true;
+
 done:
        taprio_offload_free(offload);
 
@@ -1293,12 +1296,9 @@ static int taprio_disable_offload(struct net_device *dev,
        struct tc_taprio_qopt_offload *offload;
        int err;
 
-       if (!FULL_OFFLOAD_IS_ENABLED(q->flags))
+       if (!q->offloaded)
                return 0;
 
-       if (!ops->ndo_setup_tc)
-               return -EOPNOTSUPP;
-
        offload = taprio_offload_alloc(0);
        if (!offload) {
                NL_SET_ERR_MSG(extack,
@@ -1314,6 +1314,8 @@ static int taprio_disable_offload(struct net_device *dev,
                goto out;
        }
 
+       q->offloaded = false;
+
 out:
        taprio_offload_free(offload);
 
@@ -1949,12 +1951,14 @@ start_error:
 
 static struct Qdisc *taprio_leaf(struct Qdisc *sch, unsigned long cl)
 {
-       struct netdev_queue *dev_queue = taprio_queue_get(sch, cl);
+       struct taprio_sched *q = qdisc_priv(sch);
+       struct net_device *dev = qdisc_dev(sch);
+       unsigned int ntx = cl - 1;
 
-       if (!dev_queue)
+       if (ntx >= dev->num_tx_queues)
                return NULL;
 
-       return dev_queue->qdisc_sleeping;
+       return q->qdiscs[ntx];
 }
 
 static unsigned long taprio_find(struct Qdisc *sch, u32 classid)
index 7210227..36079fd 100644 (file)
@@ -356,6 +356,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
        struct nlattr *tb[TCA_TBF_MAX + 1];
        struct tc_tbf_qopt *qopt;
        struct Qdisc *child = NULL;
+       struct Qdisc *old = NULL;
        struct psched_ratecfg rate;
        struct psched_ratecfg peak;
        u64 max_size;
@@ -447,7 +448,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
        sch_tree_lock(sch);
        if (child) {
                qdisc_tree_flush_backlog(q->qdisc);
-               qdisc_put(q->qdisc);
+               old = q->qdisc;
                q->qdisc = child;
        }
        q->limit = qopt->limit;
@@ -467,6 +468,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
        memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg));
 
        sch_tree_unlock(sch);
+       qdisc_put(old);
        err = 0;
 
        tbf_offload_change(sch);
index 79c1318..0939cc3 100644 (file)
@@ -1855,7 +1855,6 @@ static void smc_listen_out_connected(struct smc_sock *new_smc)
 {
        struct sock *newsmcsk = &new_smc->sk;
 
-       sk_refcnt_debug_inc(newsmcsk);
        if (newsmcsk->sk_state == SMC_INIT)
                newsmcsk->sk_state = SMC_ACTIVE;
 
index ff49a11..df89c2e 100644 (file)
@@ -757,6 +757,7 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
        lnk->lgr = lgr;
        smc_lgr_hold(lgr); /* lgr_put in smcr_link_clear() */
        lnk->link_idx = link_idx;
+       lnk->wr_rx_id_compl = 0;
        smc_ibdev_cnt_inc(lnk);
        smcr_copy_dev_info_to_link(lnk);
        atomic_set(&lnk->conn_cnt, 0);
@@ -2238,7 +2239,7 @@ out:
 static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
                                     struct smc_buf_desc *buf_desc, bool is_rmb)
 {
-       int i, rc = 0;
+       int i, rc = 0, cnt = 0;
 
        /* protect against parallel link reconfiguration */
        mutex_lock(&lgr->llc_conf_mutex);
@@ -2251,9 +2252,12 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
                        rc = -ENOMEM;
                        goto out;
                }
+               cnt++;
        }
 out:
        mutex_unlock(&lgr->llc_conf_mutex);
+       if (!rc && !cnt)
+               rc = -EINVAL;
        return rc;
 }
 
index fe8b524..285f9bd 100644 (file)
@@ -115,8 +115,10 @@ struct smc_link {
        dma_addr_t              wr_rx_dma_addr; /* DMA address of wr_rx_bufs */
        dma_addr_t              wr_rx_v2_dma_addr; /* DMA address of v2 rx buf*/
        u64                     wr_rx_id;       /* seq # of last recv WR */
+       u64                     wr_rx_id_compl; /* seq # of last completed WR */
        u32                     wr_rx_cnt;      /* number of WR recv buffers */
        unsigned long           wr_rx_tstamp;   /* jiffies when last buf rx */
+       wait_queue_head_t       wr_rx_empty_wait; /* wait for RQ empty */
 
        struct ib_reg_wr        wr_reg;         /* WR register memory region */
        wait_queue_head_t       wr_reg_wait;    /* wait for wr_reg result */
index 26f8f24..b0678a4 100644 (file)
@@ -454,6 +454,7 @@ static inline void smc_wr_rx_process_cqes(struct ib_wc wc[], int num)
 
        for (i = 0; i < num; i++) {
                link = wc[i].qp->qp_context;
+               link->wr_rx_id_compl = wc[i].wr_id;
                if (wc[i].status == IB_WC_SUCCESS) {
                        link->wr_rx_tstamp = jiffies;
                        smc_wr_rx_demultiplex(&wc[i]);
@@ -465,6 +466,8 @@ static inline void smc_wr_rx_process_cqes(struct ib_wc wc[], int num)
                        case IB_WC_RNR_RETRY_EXC_ERR:
                        case IB_WC_WR_FLUSH_ERR:
                                smcr_link_down_cond_sched(link);
+                               if (link->wr_rx_id_compl == link->wr_rx_id)
+                                       wake_up(&link->wr_rx_empty_wait);
                                break;
                        default:
                                smc_wr_rx_post(link); /* refill WR RX */
@@ -639,6 +642,7 @@ void smc_wr_free_link(struct smc_link *lnk)
                return;
        ibdev = lnk->smcibdev->ibdev;
 
+       smc_wr_drain_cq(lnk);
        smc_wr_wakeup_reg_wait(lnk);
        smc_wr_wakeup_tx_wait(lnk);
 
@@ -889,6 +893,7 @@ int smc_wr_create_link(struct smc_link *lnk)
        atomic_set(&lnk->wr_tx_refcnt, 0);
        init_waitqueue_head(&lnk->wr_reg_wait);
        atomic_set(&lnk->wr_reg_refcnt, 0);
+       init_waitqueue_head(&lnk->wr_rx_empty_wait);
        return rc;
 
 dma_unmap:
index a54e90a..45e9b89 100644 (file)
@@ -73,6 +73,11 @@ static inline void smc_wr_tx_link_put(struct smc_link *link)
                wake_up_all(&link->wr_tx_wait);
 }
 
+static inline void smc_wr_drain_cq(struct smc_link *lnk)
+{
+       wait_event(lnk->wr_rx_empty_wait, lnk->wr_rx_id_compl == lnk->wr_rx_id);
+}
+
 static inline void smc_wr_wakeup_tx_wait(struct smc_link *lnk)
 {
        wake_up_all(&lnk->wr_tx_wait);
index 7d268a2..c284efa 100644 (file)
@@ -2873,6 +2873,9 @@ int rpc_clnt_test_and_add_xprt(struct rpc_clnt *clnt,
 
        task = rpc_call_null_helper(clnt, xprt, NULL, RPC_TASK_ASYNC,
                        &rpc_cb_add_xprt_call_ops, data);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+
        data->xps->xps_nunique_destaddr_xprts++;
        rpc_put_task(task);
 success:
index d71eec4..f8fae78 100644 (file)
@@ -1179,11 +1179,8 @@ xprt_request_dequeue_receive_locked(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
 
-       if (test_and_clear_bit(RPC_TASK_NEED_RECV, &task->tk_runstate)) {
+       if (test_and_clear_bit(RPC_TASK_NEED_RECV, &task->tk_runstate))
                xprt_request_rb_remove(req->rq_xprt, req);
-               xdr_free_bvec(&req->rq_rcv_buf);
-               req->rq_private_buf.bvec = NULL;
-       }
 }
 
 /**
@@ -1221,6 +1218,8 @@ void xprt_complete_rqst(struct rpc_task *task, int copied)
 
        xprt->stat.recvs++;
 
+       xdr_free_bvec(&req->rq_rcv_buf);
+       req->rq_private_buf.bvec = NULL;
        req->rq_private_buf.len = copied;
        /* Ensure all writes are done before we update */
        /* req->rq_reply_bytes_recvd */
@@ -1453,6 +1452,7 @@ xprt_request_dequeue_xprt(struct rpc_task *task)
                xprt_request_dequeue_transmit_locked(task);
                xprt_request_dequeue_receive_locked(task);
                spin_unlock(&xprt->queue_lock);
+               xdr_free_bvec(&req->rq_rcv_buf);
        }
 }
 
index 2f4d232..9618e44 100644 (file)
@@ -160,7 +160,7 @@ static void map_set(u64 *up_map, int i, unsigned int v)
 
 static int map_get(u64 up_map, int i)
 {
-       return (up_map & (1 << i)) >> i;
+       return (up_map & (1ULL << i)) >> i;
 }
 
 static struct tipc_peer *peer_prev(struct tipc_peer *peer)
index aab4346..0878b16 100644 (file)
@@ -65,9 +65,10 @@ static ssize_t ht40allow_map_read(struct file *file,
 {
        struct wiphy *wiphy = file->private_data;
        char *buf;
-       unsigned int offset = 0, buf_size = PAGE_SIZE, i, r;
+       unsigned int offset = 0, buf_size = PAGE_SIZE, i;
        enum nl80211_band band;
        struct ieee80211_supported_band *sband;
+       ssize_t r;
 
        buf = kzalloc(buf_size, GFP_KERNEL);
        if (!buf)
index 6a5f08f..cca5e1c 100644 (file)
@@ -136,7 +136,7 @@ static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr,
        pos = (u8 *) hdr;
        aad[0] = pos[0] & 0x8f;
        aad[1] = pos[1] & 0xc7;
-       memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN);
+       memcpy(aad + 2, &hdr->addrs, 3 * ETH_ALEN);
        pos = (u8 *) & hdr->seq_ctrl;
        aad[20] = pos[0] & 0x0f;
        aad[21] = 0;            /* all bits masked */
index 2c12795..775836f 100644 (file)
@@ -1361,7 +1361,7 @@ static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
                 25599, /*  4.166666... */
                 17067, /*  2.777777... */
                 12801, /*  2.083333... */
-                11769, /*  1.851851... */
+                11377, /*  1.851725... */
                 10239, /*  1.666666... */
                  8532, /*  1.388888... */
                  7680, /*  1.250000... */
@@ -1444,7 +1444,7 @@ static u32 cfg80211_calculate_bitrate_eht(struct rate_info *rate)
                 25599, /*  4.166666... */
                 17067, /*  2.777777... */
                 12801, /*  2.083333... */
-                11769, /*  1.851851... */
+                11377, /*  1.851725... */
                 10239, /*  1.666666... */
                  8532, /*  1.388888... */
                  7680, /*  1.250000... */
index f701121..a71a8c6 100644 (file)
@@ -379,6 +379,16 @@ static void xp_check_dma_contiguity(struct xsk_dma_map *dma_map)
 
 static int xp_init_dma_info(struct xsk_buff_pool *pool, struct xsk_dma_map *dma_map)
 {
+       if (!pool->unaligned) {
+               u32 i;
+
+               for (i = 0; i < pool->heads_cnt; i++) {
+                       struct xdp_buff_xsk *xskb = &pool->heads[i];
+
+                       xp_init_xskb_dma(xskb, pool, dma_map->dma_pages, xskb->orig_addr);
+               }
+       }
+
        pool->dma_pages = kvcalloc(dma_map->dma_pages_cnt, sizeof(*pool->dma_pages), GFP_KERNEL);
        if (!pool->dma_pages)
                return -ENOMEM;
@@ -428,12 +438,6 @@ int xp_dma_map(struct xsk_buff_pool *pool, struct device *dev,
 
        if (pool->unaligned)
                xp_check_dma_contiguity(dma_map);
-       else
-               for (i = 0; i < pool->heads_cnt; i++) {
-                       struct xdp_buff_xsk *xskb = &pool->heads[i];
-
-                       xp_init_xskb_dma(xskb, pool, dma_map->dma_pages, xskb->orig_addr);
-               }
 
        err = xp_init_dma_info(pool, dma_map);
        if (err) {
index 9f39b01..8cf1cb2 100644 (file)
@@ -1,20 +1,19 @@
 DEBUG_CFLAGS   :=
+debug-flags-y  := -g
 
 ifdef CONFIG_DEBUG_INFO_SPLIT
 DEBUG_CFLAGS   += -gsplit-dwarf
-else
-DEBUG_CFLAGS   += -g
 endif
 
-ifndef CONFIG_AS_IS_LLVM
-KBUILD_AFLAGS  += -Wa,-gdwarf-2
-endif
-
-ifndef CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
-dwarf-version-$(CONFIG_DEBUG_INFO_DWARF4) := 4
-dwarf-version-$(CONFIG_DEBUG_INFO_DWARF5) := 5
-DEBUG_CFLAGS   += -gdwarf-$(dwarf-version-y)
+debug-flags-$(CONFIG_DEBUG_INFO_DWARF4)        += -gdwarf-4
+debug-flags-$(CONFIG_DEBUG_INFO_DWARF5)        += -gdwarf-5
+ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_AS_IS_GNU),yy)
+# Clang does not pass -g or -gdwarf-* option down to GAS.
+# Add -Wa, prefix to explicitly specify the flags.
+KBUILD_AFLAGS  += $(addprefix -Wa$(comma), $(debug-flags-y))
 endif
+DEBUG_CFLAGS   += $(debug-flags-y)
+KBUILD_AFLAGS  += $(debug-flags-y)
 
 ifdef CONFIG_DEBUG_INFO_REDUCED
 DEBUG_CFLAGS   += -fno-var-tracking
@@ -29,5 +28,5 @@ KBUILD_AFLAGS += -gz=zlib
 KBUILD_LDFLAGS += --compress-debug-sections=zlib
 endif
 
-KBUILD_CFLAGS += $(DEBUG_CFLAGS)
+KBUILD_CFLAGS  += $(DEBUG_CFLAGS)
 export DEBUG_CFLAGS
index 0621c39..6ae4821 100644 (file)
@@ -47,7 +47,19 @@ else
 
 ifdef CONFIG_CC_IS_CLANG
 KBUILD_CFLAGS += -Wno-initializer-overrides
+# Clang before clang-16 would warn on default argument promotions.
+ifeq ($(shell [ $(CONFIG_CLANG_VERSION) -lt 160000 ] && echo y),y)
+# Disable -Wformat
 KBUILD_CFLAGS += -Wno-format
+# Then re-enable flags that were part of the -Wformat group that aren't
+# problematic.
+KBUILD_CFLAGS += -Wformat-extra-args -Wformat-invalid-specifier
+KBUILD_CFLAGS += -Wformat-zero-length -Wnonnull
+# Requires clang-12+.
+ifeq ($(shell [ $(CONFIG_CLANG_VERSION) -ge 120000 ] && echo y),y)
+KBUILD_CFLAGS += -Wformat-insufficient-args
+endif
+endif
 KBUILD_CFLAGS += -Wno-sign-compare
 KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast)
 KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare
index 79e759a..4aa09e0 100755 (executable)
@@ -3751,7 +3751,7 @@ sub process {
                if ($realfile =~ /\.S$/ &&
                    $line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) {
                        WARN("AVOID_L_PREFIX",
-                            "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/asm-annotations.rst\n" . $herecurr);
+                            "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr);
                }
 
 # check we are in a valid source file C or perl if not then ignore this hunk
@@ -4695,12 +4695,12 @@ sub process {
                        }
                }
 
-# avoid BUG() or BUG_ON()
-               if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
+# do not use BUG() or variants
+               if ($line =~ /\b(?!AA_|BUILD_|DCCP_|IDA_|KVM_|RWLOCK_|snd_|SPIN_)(?:[a-zA-Z_]*_)?BUG(?:_ON)?(?:_[A-Z_]+)?\s*\(/) {
                        my $msg_level = \&WARN;
                        $msg_level = \&CHK if ($file);
                        &{$msg_level}("AVOID_BUG",
-                                     "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
+                                     "Do not crash the kernel unless it is absolutely unavoidable--use WARN_ON_ONCE() plus recovery code (if feasible) instead of BUG() or variants\n" . $herecurr);
                }
 
 # avoid LINUX_VERSION_CODE
index 1337ced..bb78c9b 100755 (executable)
@@ -12,7 +12,6 @@ compile_commands.json.
 import argparse
 import json
 import multiprocessing
-import os
 import subprocess
 import sys
 
index 3b42f25..8df33e7 100755 (executable)
@@ -62,6 +62,7 @@ try_decompress 'BZh'          xy    bunzip2
 try_decompress '\135\0\0\0'   xxx   unlzma
 try_decompress '\211\114\132' xy    'lzop -d'
 try_decompress '\002\041\114\030' xyy 'lz4 -d -l'
+try_decompress '\050\265\057\375' xxx unzstd
 
 # Bail out:
 echo "$me: Cannot find kernel config." >&2
diff --git a/scripts/gcc-ld b/scripts/gcc-ld
deleted file mode 100755 (executable)
index 997b818..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-# run gcc with ld options
-# used as a wrapper to execute link time optimizations
-# yes virginia, this is not pretty
-
-ARGS="-nostdlib"
-
-while [ "$1" != "" ] ; do
-       case "$1" in
-       -save-temps|-m32|-m64) N="$1" ;;
-       -r) N="$1" ;;
-       -[Wg]*) N="$1" ;;
-       -[olv]|-[Ofd]*|-nostdlib) N="$1" ;;
-       --end-group|--start-group)
-                N="-Wl,$1" ;;
-       -[RTFGhIezcbyYu]*|\
---script|--defsym|-init|-Map|--oformat|-rpath|\
--rpath-link|--sort-section|--section-start|-Tbss|-Tdata|-Ttext|\
---version-script|--dynamic-list|--version-exports-symbol|--wrap|-m)
-               A="$1" ; shift ; N="-Wl,$A,$1" ;;
-       -[m]*) N="$1" ;;
-       -*) N="-Wl,$1" ;;
-       *)  N="$1" ;;
-       esac
-       ARGS="$ARGS $N"
-       shift
-done
-
-exec $CC $ARGS
index fa8c010..c396aa1 100644 (file)
@@ -98,7 +98,6 @@ bool menu_is_empty(struct menu *menu);
 bool menu_is_visible(struct menu *menu);
 bool menu_has_prompt(struct menu *menu);
 const char *menu_get_prompt(struct menu *menu);
-struct menu *menu_get_root_menu(struct menu *menu);
 struct menu *menu_get_parent_menu(struct menu *menu);
 bool menu_has_help(struct menu *menu);
 const char *menu_get_help(struct menu *menu);
index 3d6f7cb..62b6313 100644 (file)
@@ -661,11 +661,6 @@ const char *menu_get_prompt(struct menu *menu)
        return NULL;
 }
 
-struct menu *menu_get_root_menu(struct menu *menu)
-{
-       return &rootmenu;
-}
-
 struct menu *menu_get_parent_menu(struct menu *menu)
 {
        enum prop_type type;
index 9aa23d1..ad8bbc5 100755 (executable)
@@ -41,4 +41,4 @@
 # so we just ignore them to let readprofile continue to work.
 # (At least sparc64 has __crc_ in the middle).
 
-$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)\|\( \.L\)' > $2
+$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)\|\( \.L\)\|\( L0\)' > $2
index ec5a624..a9dbd99 100644 (file)
@@ -150,6 +150,16 @@ retry:
 /* clang-format on */
 
 /*
+ * All access rights that are denied by default whether they are handled or not
+ * by a ruleset/layer.  This must be ORed with all ruleset->fs_access_masks[]
+ * entries when we need to get the absolute handled access masks.
+ */
+/* clang-format off */
+#define ACCESS_INITIALLY_DENIED ( \
+       LANDLOCK_ACCESS_FS_REFER)
+/* clang-format on */
+
+/*
  * @path: Should have been checked by get_path_from_fd().
  */
 int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
@@ -167,7 +177,9 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
                return -EINVAL;
 
        /* Transforms relative access rights to absolute ones. */
-       access_rights |= LANDLOCK_MASK_ACCESS_FS & ~ruleset->fs_access_masks[0];
+       access_rights |=
+               LANDLOCK_MASK_ACCESS_FS &
+               ~(ruleset->fs_access_masks[0] | ACCESS_INITIALLY_DENIED);
        object = get_inode_object(d_backing_inode(path->dentry));
        if (IS_ERR(object))
                return PTR_ERR(object);
@@ -277,23 +289,12 @@ static inline bool is_nouser_or_private(const struct dentry *dentry)
 static inline access_mask_t
 get_handled_accesses(const struct landlock_ruleset *const domain)
 {
-       access_mask_t access_dom = 0;
-       unsigned long access_bit;
-
-       for (access_bit = 0; access_bit < LANDLOCK_NUM_ACCESS_FS;
-            access_bit++) {
-               size_t layer_level;
+       access_mask_t access_dom = ACCESS_INITIALLY_DENIED;
+       size_t layer_level;
 
-               for (layer_level = 0; layer_level < domain->num_layers;
-                    layer_level++) {
-                       if (domain->fs_access_masks[layer_level] &
-                           BIT_ULL(access_bit)) {
-                               access_dom |= BIT_ULL(access_bit);
-                               break;
-                       }
-               }
-       }
-       return access_dom;
+       for (layer_level = 0; layer_level < domain->num_layers; layer_level++)
+               access_dom |= domain->fs_access_masks[layer_level];
+       return access_dom & LANDLOCK_MASK_ACCESS_FS;
 }
 
 static inline access_mask_t
@@ -316,8 +317,13 @@ init_layer_masks(const struct landlock_ruleset *const domain,
 
                for_each_set_bit(access_bit, &access_req,
                                 ARRAY_SIZE(*layer_masks)) {
-                       if (domain->fs_access_masks[layer_level] &
-                           BIT_ULL(access_bit)) {
+                       /*
+                        * Artificially handles all initially denied by default
+                        * access rights.
+                        */
+                       if (BIT_ULL(access_bit) &
+                           (domain->fs_access_masks[layer_level] |
+                            ACCESS_INITIALLY_DENIED)) {
                                (*layer_masks)[access_bit] |=
                                        BIT_ULL(layer_level);
                                handled_accesses |= BIT_ULL(access_bit);
@@ -857,10 +863,6 @@ static int current_check_refer_path(struct dentry *const old_dentry,
                                              NULL, NULL);
        }
 
-       /* Backward compatibility: no reparenting support. */
-       if (!(get_handled_accesses(dom) & LANDLOCK_ACCESS_FS_REFER))
-               return -EXDEV;
-
        access_request_parent1 |= LANDLOCK_ACCESS_FS_REFER;
        access_request_parent2 |= LANDLOCK_ACCESS_FS_REFER;
 
index 14d30fe..4b95de2 100644 (file)
@@ -2660,4 +2660,8 @@ int security_uring_sqpoll(void)
 {
        return call_int_hook(uring_sqpoll, 0);
 }
+int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       return call_int_hook(uring_cmd, 0, ioucmd);
+}
 #endif /* CONFIG_IO_URING */
index 7957350..03bca97 100644 (file)
@@ -91,6 +91,7 @@
 #include <uapi/linux/mount.h>
 #include <linux/fsnotify.h>
 #include <linux/fanotify.h>
+#include <linux/io_uring.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -6987,6 +6988,28 @@ static int selinux_uring_sqpoll(void)
        return avc_has_perm(&selinux_state, sid, sid,
                            SECCLASS_IO_URING, IO_URING__SQPOLL, NULL);
 }
+
+/**
+ * selinux_uring_cmd - check if IORING_OP_URING_CMD is allowed
+ * @ioucmd: the io_uring command structure
+ *
+ * Check to see if the current domain is allowed to execute an
+ * IORING_OP_URING_CMD against the device/file specified in @ioucmd.
+ *
+ */
+static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       struct file *file = ioucmd->file;
+       struct inode *inode = file_inode(file);
+       struct inode_security_struct *isec = selinux_inode(inode);
+       struct common_audit_data ad;
+
+       ad.type = LSM_AUDIT_DATA_FILE;
+       ad.u.file = file;
+
+       return avc_has_perm(&selinux_state, current_sid(), isec->sid,
+                           SECCLASS_IO_URING, IO_URING__CMD, &ad);
+}
 #endif /* CONFIG_IO_URING */
 
 /*
@@ -7231,6 +7254,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 #ifdef CONFIG_IO_URING
        LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds),
        LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll),
+       LSM_HOOK_INIT(uring_cmd, selinux_uring_cmd),
 #endif
 
        /*
index ff757ae..1c2f41f 100644 (file)
@@ -253,7 +253,7 @@ const struct security_class_mapping secclass_map[] = {
        { "anon_inode",
          { COMMON_FILE_PERMS, NULL } },
        { "io_uring",
-         { "override_creds", "sqpoll", NULL } },
+         { "override_creds", "sqpoll", "cmd", NULL } },
        { NULL }
   };
 
index 0018314..bffccdc 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/fs_context.h>
 #include <linux/fs_parser.h>
 #include <linux/watch_queue.h>
+#include <linux/io_uring.h>
 #include "smack.h"
 
 #define TRANS_TRUE     "TRUE"
@@ -4732,6 +4733,36 @@ static int smack_uring_sqpoll(void)
        return -EPERM;
 }
 
+/**
+ * smack_uring_cmd - check on file operations for io_uring
+ * @ioucmd: the command in question
+ *
+ * Make a best guess about whether a io_uring "command" should
+ * be allowed. Use the same logic used for determining if the
+ * file could be opened for read in the absence of better criteria.
+ */
+static int smack_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       struct file *file = ioucmd->file;
+       struct smk_audit_info ad;
+       struct task_smack *tsp;
+       struct inode *inode;
+       int rc;
+
+       if (!file)
+               return -EINVAL;
+
+       tsp = smack_cred(file->f_cred);
+       inode = file_inode(file);
+
+       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+       smk_ad_setfield_u_fs_path(&ad, file->f_path);
+       rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
+       rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc);
+
+       return rc;
+}
+
 #endif /* CONFIG_IO_URING */
 
 struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
@@ -4889,6 +4920,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
 #ifdef CONFIG_IO_URING
        LSM_HOOK_INIT(uring_override_creds, smack_uring_override_creds),
        LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll),
+       LSM_HOOK_INIT(uring_cmd, smack_uring_cmd),
 #endif
 };
 
index f3e8937..a727192 100644 (file)
@@ -385,14 +385,14 @@ static bool elem_id_matches(const struct snd_kcontrol *kctl,
 #define MULTIPLIER     37
 static unsigned long get_ctl_id_hash(const struct snd_ctl_elem_id *id)
 {
+       int i;
        unsigned long h;
-       const unsigned char *p;
 
        h = id->iface;
        h = MULTIPLIER * h + id->device;
        h = MULTIPLIER * h + id->subdevice;
-       for (p = id->name; *p; p++)
-               h = MULTIPLIER * h + *p;
+       for (i = 0; i < SNDRV_CTL_ELEM_ID_NAME_MAXLEN && id->name[i]; i++)
+               h = MULTIPLIER * h + id->name[i];
        h = MULTIPLIER * h + id->index;
        h &= LONG_MAX;
        return h;
index 193dae3..5377f94 100644 (file)
@@ -178,10 +178,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
                return -ENOMEM;
 
        err = snd_card_init(card, parent, idx, xid, module, extra_size);
-       if (err < 0) {
-               kfree(card);
-               return err;
-       }
+       if (err < 0)
+               return err; /* card is freed by error handler */
 
        *card_ret = card;
        return 0;
@@ -233,7 +231,7 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
        card->managed = true;
        err = snd_card_init(card, parent, idx, xid, module, extra_size);
        if (err < 0) {
-               devres_free(card);
+               devres_free(card); /* in managed mode, we need to free manually */
                return err;
        }
 
@@ -297,6 +295,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
                mutex_unlock(&snd_card_mutex);
                dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
                         idx, snd_ecards_limit - 1, err);
+               if (!card->managed)
+                       kfree(card); /* manually free here, as no destructor called */
                return err;
        }
        set_bit(idx, snd_cards_lock);           /* lock it */
index d3885cb..cfcd8ef 100644 (file)
 
 static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
 
+#ifdef CONFIG_SND_DMA_SGBUF
+static void *do_alloc_fallback_pages(struct device *dev, size_t size,
+                                    dma_addr_t *addr, bool wc);
+static void do_free_fallback_pages(void *p, size_t size, bool wc);
+static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
+#endif
+
 /* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
 static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
                                          gfp_t default_gfp)
@@ -277,16 +284,21 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
 /*
  * Continuous pages allocator
  */
-static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *do_alloc_pages(size_t size, dma_addr_t *addr, gfp_t gfp)
 {
-       gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
        void *p = alloc_pages_exact(size, gfp);
 
        if (p)
-               dmab->addr = page_to_phys(virt_to_page(p));
+               *addr = page_to_phys(virt_to_page(p));
        return p;
 }
 
+static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+       return do_alloc_pages(size, &dmab->addr,
+                             snd_mem_get_gfp_flags(dmab, GFP_KERNEL));
+}
+
 static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
 {
        free_pages_exact(dmab->area, dmab->bytes);
@@ -463,6 +475,25 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
 /*
  * Write-combined pages
  */
+/* x86-specific allocations */
+#ifdef CONFIG_SND_DMA_SGBUF
+static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+       return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true);
+}
+
+static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
+{
+       do_free_fallback_pages(dmab->area, dmab->bytes, true);
+}
+
+static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
+                          struct vm_area_struct *area)
+{
+       area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+       return snd_dma_continuous_mmap(dmab, area);
+}
+#else
 static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
@@ -479,6 +510,7 @@ static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
        return dma_mmap_wc(dmab->dev.dev, area,
                           dmab->area, dmab->addr, dmab->bytes);
 }
+#endif /* CONFIG_SND_DMA_SGBUF */
 
 static const struct snd_malloc_ops snd_dma_wc_ops = {
        .alloc = snd_dma_wc_alloc,
@@ -486,10 +518,6 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
        .mmap = snd_dma_wc_mmap,
 };
 
-#ifdef CONFIG_SND_DMA_SGBUF
-static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
-#endif
-
 /*
  * Non-contiguous pages allocator
  */
@@ -515,10 +543,13 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
        dmab->dev.need_sync = dma_need_sync(dmab->dev.dev,
                                            sg_dma_address(sgt->sgl));
        p = dma_vmap_noncontiguous(dmab->dev.dev, size, sgt);
-       if (p)
+       if (p) {
                dmab->private_data = sgt;
-       else
+               /* store the first page address for convenience */
+               dmab->addr = snd_sgbuf_get_addr(dmab, 0);
+       } else {
                dma_free_noncontiguous(dmab->dev.dev, size, sgt, dmab->dev.dir);
+       }
        return p;
 }
 
@@ -669,6 +700,37 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
        .get_chunk_size = snd_dma_noncontig_get_chunk_size,
 };
 
+/* manual page allocations with wc setup */
+static void *do_alloc_fallback_pages(struct device *dev, size_t size,
+                                    dma_addr_t *addr, bool wc)
+{
+       gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
+       void *p;
+
+ again:
+       p = do_alloc_pages(size, addr, gfp);
+       if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) {
+               if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
+                       gfp |= GFP_DMA32;
+                       goto again;
+               }
+               if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
+                       gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+                       goto again;
+               }
+       }
+       if (p && wc)
+               set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
+       return p;
+}
+
+static void do_free_fallback_pages(void *p, size_t size, bool wc)
+{
+       if (wc)
+               set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT);
+       free_pages_exact(p, size);
+}
+
 /* Fallback SG-buffer allocations for x86 */
 struct snd_dma_sg_fallback {
        size_t count;
@@ -679,14 +741,11 @@ struct snd_dma_sg_fallback {
 static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
                                       struct snd_dma_sg_fallback *sgbuf)
 {
+       bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
        size_t i;
 
-       if (sgbuf->count && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
-               set_pages_array_wb(sgbuf->pages, sgbuf->count);
        for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
-               dma_free_coherent(dmab->dev.dev, PAGE_SIZE,
-                                 page_address(sgbuf->pages[i]),
-                                 sgbuf->addrs[i]);
+               do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
        kvfree(sgbuf->pages);
        kvfree(sgbuf->addrs);
        kfree(sgbuf);
@@ -698,6 +757,7 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
        struct page **pages;
        size_t i, count;
        void *p;
+       bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
 
        sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
        if (!sgbuf)
@@ -712,19 +772,19 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
                goto error;
 
        for (i = 0; i < count; sgbuf->count++, i++) {
-               p = dma_alloc_coherent(dmab->dev.dev, PAGE_SIZE,
-                                      &sgbuf->addrs[i], DEFAULT_GFP);
+               p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE,
+                                           &sgbuf->addrs[i], wc);
                if (!p)
                        goto error;
                sgbuf->pages[i] = virt_to_page(p);
        }
 
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
-               set_pages_array_wc(pages, count);
        p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
        if (!p)
                goto error;
        dmab->private_data = sgbuf;
+       /* store the first page address for convenience */
+       dmab->addr = snd_sgbuf_get_addr(dmab, 0);
        return p;
 
  error:
index 90c3a36..02df915 100644 (file)
@@ -1672,14 +1672,14 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
                runtime = substream->runtime;
                if (atomic_read(&substream->mmap_count))
                        goto __direct;
-               err = snd_pcm_oss_make_ready(substream);
-               if (err < 0)
-                       return err;
                atomic_inc(&runtime->oss.rw_ref);
                if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
                        atomic_dec(&runtime->oss.rw_ref);
                        return -ERESTARTSYS;
                }
+               err = snd_pcm_oss_make_ready_locked(substream);
+               if (err < 0)
+                       goto unlock;
                format = snd_pcm_oss_format_from(runtime->oss.format);
                width = snd_pcm_format_physical_width(format);
                if (runtime->oss.buffer_used > 0) {
index 1e3bf08..07efb38 100644 (file)
@@ -270,7 +270,9 @@ snd_seq_oss_midi_clear_all(void)
 void
 snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
 {
+       spin_lock_irq(&register_lock);
        dp->max_mididev = max_midi_devs;
+       spin_unlock_irq(&register_lock);
 }
 
 /*
index 2e9d695..2d707af 100644 (file)
@@ -121,13 +121,13 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
        spin_unlock_irqrestore(&clients_lock, flags);
 #ifdef CONFIG_MODULES
        if (!in_interrupt()) {
-               static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
-               static char card_requested[SNDRV_CARDS];
+               static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);
+               static DECLARE_BITMAP(card_requested, SNDRV_CARDS);
+
                if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {
                        int idx;
                        
-                       if (!client_requested[clientid]) {
-                               client_requested[clientid] = 1;
+                       if (!test_and_set_bit(clientid, client_requested)) {
                                for (idx = 0; idx < 15; idx++) {
                                        if (seq_client_load[idx] < 0)
                                                break;
@@ -142,10 +142,8 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
                        int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /
                                SNDRV_SEQ_CLIENTS_PER_CARD;
                        if (card < snd_ecards_limit) {
-                               if (! card_requested[card]) {
-                                       card_requested[card] = 1;
+                               if (!test_and_set_bit(card, card_requested))
                                        snd_request_card(card);
-                               }
                                snd_seq_device_load_drivers();
                        }
                }
index 9b4a7cd..12f12a2 100644 (file)
@@ -605,17 +605,18 @@ static unsigned int loopback_jiffies_timer_pos_update
                        cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
        struct loopback_pcm *dpcm_capt =
                        cable->streams[SNDRV_PCM_STREAM_CAPTURE];
-       unsigned long delta_play = 0, delta_capt = 0;
+       unsigned long delta_play = 0, delta_capt = 0, cur_jiffies;
        unsigned int running, count1, count2;
 
+       cur_jiffies = jiffies;
        running = cable->running ^ cable->pause;
        if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
-               delta_play = jiffies - dpcm_play->last_jiffies;
+               delta_play = cur_jiffies - dpcm_play->last_jiffies;
                dpcm_play->last_jiffies += delta_play;
        }
 
        if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
-               delta_capt = jiffies - dpcm_capt->last_jiffies;
+               delta_capt = cur_jiffies - dpcm_capt->last_jiffies;
                dpcm_capt->last_jiffies += delta_capt;
        }
 
index d84ffdf..5a47864 100644 (file)
@@ -450,6 +450,16 @@ static const struct config_entry config_table[] = {
                .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
                .device = 0x51cb,
        },
+       /* RaptorLake-M */
+       {
+               .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+               .device = 0x51ce,
+       },
+       /* RaptorLake-PX */
+       {
+               .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+               .device = 0x51cf,
+       },
 #endif
 
 };
index 9db5ccd..13bb0cc 100644 (file)
@@ -55,16 +55,22 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
 
                /* find max number of channels based on format_configuration */
                if (fmt_configs->fmt_count) {
+                       struct nhlt_fmt_cfg *fmt_cfg = fmt_configs->fmt_config;
+
                        dev_dbg(dev, "found %d format definitions\n",
                                fmt_configs->fmt_count);
 
                        for (i = 0; i < fmt_configs->fmt_count; i++) {
                                struct wav_fmt_ext *fmt_ext;
 
-                               fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
+                               fmt_ext = &fmt_cfg->fmt_ext;
 
                                if (fmt_ext->fmt.channels > max_ch)
                                        max_ch = fmt_ext->fmt.channels;
+
+                               /* Move to the next nhlt_fmt_cfg */
+                               fmt_cfg = (struct nhlt_fmt_cfg *)(fmt_cfg->config.caps +
+                                                                 fmt_cfg->config.size);
                        }
                        dev_dbg(dev, "max channels found %d\n", max_ch);
                } else {
index b2701a4..48af77a 100644 (file)
@@ -124,7 +124,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
        epcm->voices[0]->epcm = epcm;
        if (voices > 1) {
                for (i = 1; i < voices; i++) {
-                       epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i];
+                       epcm->voices[i] = &epcm->emu->voices[(epcm->voices[0]->number + i) % NUM_G];
                        epcm->voices[i]->epcm = epcm;
                }
        }
index cae9a97..1a868dd 100644 (file)
@@ -157,10 +157,10 @@ static int hda_codec_driver_remove(struct device *dev)
                return codec->bus->core.ext_ops->hdev_detach(&codec->core);
        }
 
-       refcount_dec(&codec->pcm_ref);
        snd_hda_codec_disconnect_pcms(codec);
        snd_hda_jack_tbl_disconnect(codec);
-       wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref));
+       if (!refcount_dec_and_test(&codec->pcm_ref))
+               wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref));
        snd_power_sync_ref(codec->bus->card);
 
        if (codec->patch_ops.free)
index a77165b..6f30c37 100644 (file)
@@ -1817,7 +1817,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 
        /* use the non-cached pages in non-snoop mode */
        if (!azx_snoop(chip))
-               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
+               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC_SG;
 
        if (chip->driver_type == AZX_DRIVER_NVIDIA) {
                dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
@@ -2550,6 +2550,8 @@ static const struct pci_device_id azx_ids[] = {
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
+       { PCI_DEVICE(0x8086, 0x3b57),
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Poulsbo */
        { PCI_DEVICE(0x8086, 0x811b),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE },
index 7debb2c..976a112 100644 (file)
@@ -474,7 +474,8 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match);
 static int hda_tegra_probe(struct platform_device *pdev)
 {
        const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR |
-                                         AZX_DCAPS_PM_RUNTIME;
+                                         AZX_DCAPS_PM_RUNTIME |
+                                         AZX_DCAPS_4K_BDLE_BOUNDARY;
        struct snd_card *card;
        struct azx *chip;
        struct hda_tegra *hda;
index 6c209cd..c239d9d 100644 (file)
@@ -170,6 +170,8 @@ struct hdmi_spec {
        bool dyn_pcm_no_legacy;
        /* hdmi interrupt trigger control flag for Nvidia codec */
        bool hdmi_intr_trig_ctrl;
+       bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
+
        bool intel_hsw_fixup;   /* apply Intel platform-specific fixups */
        /*
         * Non-generic VIA/NVIDIA specific
@@ -679,15 +681,24 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
                                     int ca, int active_channels,
                                     int conn_type)
 {
+       struct hdmi_spec *spec = codec->spec;
        union audio_infoframe ai;
 
        memset(&ai, 0, sizeof(ai));
-       if (conn_type == 0) { /* HDMI */
+       if ((conn_type == 0) || /* HDMI */
+               /* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */
+               (conn_type == 1 && spec->nv_dp_workaround)) {
                struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
 
-               hdmi_ai->type           = 0x84;
-               hdmi_ai->ver            = 0x01;
-               hdmi_ai->len            = 0x0a;
+               if (conn_type == 0) { /* HDMI */
+                       hdmi_ai->type           = 0x84;
+                       hdmi_ai->ver            = 0x01;
+                       hdmi_ai->len            = 0x0a;
+               } else {/* Nvidia DP */
+                       hdmi_ai->type           = 0x84;
+                       hdmi_ai->ver            = 0x1b;
+                       hdmi_ai->len            = 0x11 << 2;
+               }
                hdmi_ai->CC02_CT47      = active_channels - 1;
                hdmi_ai->CA             = ca;
                hdmi_checksum_audio_infoframe(hdmi_ai);
@@ -1267,6 +1278,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
        set_bit(pcm_idx, &spec->pcm_in_use);
        per_pin = get_pin(spec, pin_idx);
        per_pin->cvt_nid = per_cvt->cvt_nid;
+       per_pin->silent_stream = false;
        hinfo->nid = per_cvt->cvt_nid;
 
        /* flip stripe flag for the assigned stream if supported */
@@ -3617,6 +3629,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
        spec->pcm_playback.rates = SUPPORTED_RATES;
        spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
        spec->pcm_playback.formats = SUPPORTED_FORMATS;
+       spec->nv_dp_workaround = true;
        return 0;
 }
 
@@ -3756,6 +3769,7 @@ static int patch_nvhdmi(struct hda_codec *codec)
        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
                nvhdmi_chmap_cea_alloc_validate_get_type;
        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+       spec->nv_dp_workaround = true;
 
        codec->link_down_at_suspend = 1;
 
@@ -3779,6 +3793,7 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec)
        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
                nvhdmi_chmap_cea_alloc_validate_get_type;
        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+       spec->nv_dp_workaround = true;
 
        codec->link_down_at_suspend = 1;
 
@@ -3984,6 +3999,7 @@ static int tegra_hdmi_init(struct hda_codec *codec)
 
        generic_hdmi_init_per_pins(codec);
 
+       codec->depop_delay = 10;
        codec->patch_ops.build_pcms = tegra_hdmi_build_pcms;
        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
                nvhdmi_chmap_cea_alloc_validate_get_type;
@@ -3992,6 +4008,7 @@ static int tegra_hdmi_init(struct hda_codec *codec)
        spec->chmap.ops.chmap_cea_alloc_validate_get_type =
                nvhdmi_chmap_cea_alloc_validate_get_type;
        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
+       spec->nv_dp_workaround = true;
 
        return 0;
 }
index 47e72cf..f9d46ae 100644 (file)
@@ -4700,6 +4700,48 @@ static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
        alc236_fixup_hp_micmute_led_vref(codec, fix, action);
 }
 
+static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
+                                                 const unsigned short coefs[2])
+{
+       alc_write_coef_idx(codec, 0x23, coefs[0]);
+       alc_write_coef_idx(codec, 0x25, coefs[1]);
+       alc_write_coef_idx(codec, 0x26, 0xb011);
+}
+
+struct alc298_samsung_amp_desc {
+       unsigned char nid;
+       unsigned short init_seq[2][2];
+};
+
+static void alc298_fixup_samsung_amp(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       int i, j;
+       static const unsigned short init_seq[][2] = {
+               { 0x19, 0x00 }, { 0x20, 0xc0 }, { 0x22, 0x44 }, { 0x23, 0x08 },
+               { 0x24, 0x85 }, { 0x25, 0x41 }, { 0x35, 0x40 }, { 0x36, 0x01 },
+               { 0x38, 0x81 }, { 0x3a, 0x03 }, { 0x3b, 0x81 }, { 0x40, 0x3e },
+               { 0x41, 0x07 }, { 0x400, 0x1 }
+       };
+       static const struct alc298_samsung_amp_desc amps[] = {
+               { 0x3a, { { 0x18, 0x1 }, { 0x26, 0x0 } } },
+               { 0x39, { { 0x18, 0x2 }, { 0x26, 0x1 } } }
+       };
+
+       if (action != HDA_FIXUP_ACT_INIT)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(amps); i++) {
+               alc_write_coef_idx(codec, 0x22, amps[i].nid);
+
+               for (j = 0; j < ARRAY_SIZE(amps[i].init_seq); j++)
+                       alc298_samsung_write_coef_pack(codec, amps[i].init_seq[j]);
+
+               for (j = 0; j < ARRAY_SIZE(init_seq); j++)
+                       alc298_samsung_write_coef_pack(codec, init_seq[j]);
+       }
+}
+
 #if IS_REACHABLE(CONFIG_INPUT)
 static void gpio2_mic_hotkey_event(struct hda_codec *codec,
                                   struct hda_jack_callback *event)
@@ -7025,11 +7067,14 @@ enum {
        ALC294_FIXUP_ASUS_GU502_HP,
        ALC294_FIXUP_ASUS_GU502_PINS,
        ALC294_FIXUP_ASUS_GU502_VERBS,
+       ALC294_FIXUP_ASUS_G513_PINS,
+       ALC285_FIXUP_ASUS_G533Z_PINS,
        ALC285_FIXUP_HP_GPIO_LED,
        ALC285_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_GPIO_LED,
        ALC236_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+       ALC298_FIXUP_SAMSUNG_AMP,
        ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
        ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
        ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -8363,6 +8408,24 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc294_fixup_gu502_hp,
        },
+        [ALC294_FIXUP_ASUS_G513_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                               { 0x19, 0x03a11050 }, /* front HP mic */
+                               { 0x1a, 0x03a11c30 }, /* rear external mic */
+                               { 0x21, 0x03211420 }, /* front HP out */
+                               { }
+               },
+       },
+       [ALC285_FIXUP_ASUS_G533Z_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x14, 0x90170120 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_G513_PINS,
+       },
        [ALC294_FIXUP_ASUS_COEF_1B] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -8396,6 +8459,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc236_fixup_hp_mute_led_micmute_vref,
        },
+       [ALC298_FIXUP_SAMSUNG_AMP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc298_fixup_samsung_amp,
+               .chained = true,
+               .chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
+       },
        [ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -9100,6 +9169,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
+       SND_PCI_QUIRK(0x1028, 0x087d, "Dell Precision 5530", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
@@ -9116,6 +9186,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        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, 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, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -9243,6 +9314,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x896e, "HP EliteBook x360 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8971, "HP EliteBook 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8972, "HP EliteBook 840 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
@@ -9290,10 +9362,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
+       SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
+       SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
        SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
-       SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
        SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
@@ -9309,14 +9382,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
        SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
+       SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
        SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
+       SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
-       SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
-       SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
        SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
@@ -9342,13 +9417,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
        SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
-       SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+       SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
        SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
-       SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+       SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
+       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(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
@@ -9520,6 +9595,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
        SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK),
        SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
+       SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
        SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
        SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
@@ -9716,7 +9792,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"},
        {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
        {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
-       {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
+       {.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
        {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
        {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
        {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
index 61df4d3..7f340f1 100644 (file)
@@ -209,6 +209,7 @@ struct sigmatel_spec {
 
        /* beep widgets */
        hda_nid_t anabeep_nid;
+       bool beep_power_on;
 
        /* SPDIF-out mux */
        const char * const *spdif_labels;
@@ -4443,6 +4444,28 @@ static int stac_suspend(struct hda_codec *codec)
 
        return 0;
 }
+
+static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid)
+{
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+       struct sigmatel_spec *spec = codec->spec;
+#endif
+       int ret = snd_hda_gen_check_power_status(codec, nid);
+
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+       if (nid == spec->gen.beep_nid && codec->beep) {
+               if (codec->beep->enabled != spec->beep_power_on) {
+                       spec->beep_power_on = codec->beep->enabled;
+                       if (spec->beep_power_on)
+                               snd_hda_power_up_pm(codec);
+                       else
+                               snd_hda_power_down_pm(codec);
+               }
+               ret |= spec->beep_power_on;
+       }
+#endif
+       return ret;
+}
 #else
 #define stac_suspend           NULL
 #endif /* CONFIG_PM */
@@ -4455,6 +4478,7 @@ static const struct hda_codec_ops stac_patch_ops = {
        .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .suspend = stac_suspend,
+       .check_power_status = stac_check_power_status,
 #endif
 };
 
index 4850a17..ab2d7a7 100644 (file)
@@ -196,7 +196,7 @@ struct mchp_spdiftx_dev {
        struct clk                              *pclk;
        struct clk                              *gclk;
        unsigned int                            fmt;
-       int                                     gclk_enabled:1;
+       unsigned int                            gclk_enabled:1;
 };
 
 static inline int mchp_spdiftx_is_running(struct mchp_spdiftx_dev *dev)
index d545a59..daafd42 100644 (file)
@@ -1617,7 +1617,6 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
        unsigned int current_plug_status;
        unsigned int current_button_status;
        unsigned int i;
-       int report = 0;
 
        mutex_lock(&cs42l42->irq_lock);
        if (cs42l42->suspended) {
@@ -1711,13 +1710,15 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 
                        if (current_button_status & CS42L42_M_DETECT_TF_MASK) {
                                dev_dbg(cs42l42->dev, "Button released\n");
-                               report = 0;
+                               snd_soc_jack_report(cs42l42->jack, 0,
+                                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                                                   SND_JACK_BTN_2 | SND_JACK_BTN_3);
                        } else if (current_button_status & CS42L42_M_DETECT_FT_MASK) {
-                               report = cs42l42_handle_button_press(cs42l42);
-
+                               snd_soc_jack_report(cs42l42->jack,
+                                                   cs42l42_handle_button_press(cs42l42),
+                                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                                                   SND_JACK_BTN_2 | SND_JACK_BTN_3);
                        }
-                       snd_soc_jack_report(cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 |
-                                                                  SND_JACK_BTN_2 | SND_JACK_BTN_3);
                }
        }
 
index 58f70a0..0626d56 100644 (file)
@@ -357,17 +357,32 @@ static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
        {"AIFTX", NULL, "Digital CH4 Mux"},
 };
 
-static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr)
+static const struct nau8540_osr_attr *
+nau8540_get_osr(struct nau8540 *nau8540)
 {
+       unsigned int osr;
+
+       regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
+       osr &= NAU8540_ADC_OSR_MASK;
        if (osr >= ARRAY_SIZE(osr_adc_sel))
-               return -EINVAL;
+               return NULL;
+       return &osr_adc_sel[osr];
+}
+
+static int nau8540_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
+       const struct nau8540_osr_attr *osr;
 
-       if (rate * osr > CLK_ADC_MAX) {
-               dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n");
+       osr = nau8540_get_osr(nau8540);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_ADC_MAX / osr->osr);
 }
 
 static int nau8540_hw_params(struct snd_pcm_substream *substream,
@@ -375,7 +390,8 @@ static int nau8540_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr;
+       unsigned int val_len = 0;
+       const struct nau8540_osr_attr *osr;
 
        /* CLK_ADC = OSR * FS
         * ADC clock frequency is defined as Over Sampling Rate (OSR)
@@ -383,13 +399,14 @@ static int nau8540_hw_params(struct snd_pcm_substream *substream,
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
-       osr &= NAU8540_ADC_OSR_MASK;
-       if (nau8540_clock_check(nau8540, params_rate(params), osr))
+       osr = nau8540_get_osr(nau8540);
+       if (!osr || !osr->osr)
+               return -EINVAL;
+       if (params_rate(params) * osr->osr > CLK_ADC_MAX)
                return -EINVAL;
        regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
                NAU8540_CLK_ADC_SRC_MASK,
-               osr_adc_sel[osr].clk_src << NAU8540_CLK_ADC_SRC_SFT);
+               osr->clk_src << NAU8540_CLK_ADC_SRC_SFT);
 
        switch (params_width(params)) {
        case 16:
@@ -515,6 +532,7 @@ static int nau8540_set_tdm_slot(struct snd_soc_dai *dai,
 
 
 static const struct snd_soc_dai_ops nau8540_dai_ops = {
+       .startup = nau8540_dai_startup,
        .hw_params = nau8540_hw_params,
        .set_fmt = nau8540_set_fmt,
        .set_tdm_slot = nau8540_set_tdm_slot,
index 2d21339..4a72b94 100644 (file)
@@ -670,28 +670,40 @@ static const struct snd_soc_dapm_route nau8821_dapm_routes[] = {
        {"HPOR", NULL, "Class G"},
 };
 
-static int nau8821_clock_check(struct nau8821 *nau8821,
-       int stream, int rate, int osr)
+static const struct nau8821_osr_attr *
+nau8821_get_osr(struct nau8821 *nau8821, int stream)
 {
-       int osrate = 0;
+       unsigned int osr;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               regmap_read(nau8821->regmap, NAU8821_R2C_DAC_CTRL1, &osr);
+               osr &= NAU8821_DAC_OVERSAMPLE_MASK;
                if (osr >= ARRAY_SIZE(osr_dac_sel))
-                       return -EINVAL;
-               osrate = osr_dac_sel[osr].osr;
+                       return NULL;
+               return &osr_dac_sel[osr];
        } else {
+               regmap_read(nau8821->regmap, NAU8821_R2B_ADC_RATE, &osr);
+               osr &= NAU8821_ADC_SYNC_DOWN_MASK;
                if (osr >= ARRAY_SIZE(osr_adc_sel))
-                       return -EINVAL;
-               osrate = osr_adc_sel[osr].osr;
+                       return NULL;
+               return &osr_adc_sel[osr];
        }
+}
 
-       if (!osrate || rate * osrate > CLK_DA_AD_MAX) {
-               dev_err(nau8821->dev,
-                       "exceed the maximum frequency of CLK_ADC or CLK_DAC");
+static int nau8821_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+       const struct nau8821_osr_attr *osr;
+
+       osr = nau8821_get_osr(nau8821, substream->stream);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_DA_AD_MAX / osr->osr);
 }
 
 static int nau8821_hw_params(struct snd_pcm_substream *substream,
@@ -699,7 +711,8 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr, ctrl_val, bclk_fs, clk_div;
+       unsigned int val_len = 0, ctrl_val, bclk_fs, clk_div;
+       const struct nau8821_osr_attr *osr;
 
        nau8821->fs = params_rate(params);
        /* CLK_DAC or CLK_ADC = OSR * FS
@@ -708,27 +721,19 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regmap_read(nau8821->regmap, NAU8821_R2C_DAC_CTRL1, &osr);
-               osr &= NAU8821_DAC_OVERSAMPLE_MASK;
-               if (nau8821_clock_check(nau8821, substream->stream,
-                       nau8821->fs, osr)) {
-                       return -EINVAL;
-               }
+       osr = nau8821_get_osr(nau8821, substream->stream);
+       if (!osr || !osr->osr)
+               return -EINVAL;
+       if (nau8821->fs * osr->osr > CLK_DA_AD_MAX)
+               return -EINVAL;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                regmap_update_bits(nau8821->regmap, NAU8821_R03_CLK_DIVIDER,
                        NAU8821_CLK_DAC_SRC_MASK,
-                       osr_dac_sel[osr].clk_src << NAU8821_CLK_DAC_SRC_SFT);
-       } else {
-               regmap_read(nau8821->regmap, NAU8821_R2B_ADC_RATE, &osr);
-               osr &= NAU8821_ADC_SYNC_DOWN_MASK;
-               if (nau8821_clock_check(nau8821, substream->stream,
-                       nau8821->fs, osr)) {
-                       return -EINVAL;
-               }
+                       osr->clk_src << NAU8821_CLK_DAC_SRC_SFT);
+       else
                regmap_update_bits(nau8821->regmap, NAU8821_R03_CLK_DIVIDER,
                        NAU8821_CLK_ADC_SRC_MASK,
-                       osr_adc_sel[osr].clk_src << NAU8821_CLK_ADC_SRC_SFT);
-       }
+                       osr->clk_src << NAU8821_CLK_ADC_SRC_SFT);
 
        /* make BCLK and LRC divde configuration if the codec as master. */
        regmap_read(nau8821->regmap, NAU8821_R1D_I2S_PCM_CTRL2, &ctrl_val);
@@ -843,6 +848,7 @@ static int nau8821_digital_mute(struct snd_soc_dai *dai, int mute,
 }
 
 static const struct snd_soc_dai_ops nau8821_dai_ops = {
+       .startup = nau8821_dai_startup,
        .hw_params = nau8821_hw_params,
        .set_fmt = nau8821_set_dai_fmt,
        .mute_stream = nau8821_digital_mute,
index ad54d70..4f19fd9 100644 (file)
@@ -901,7 +901,10 @@ static void nau8824_jdet_work(struct work_struct *work)
                NAU8824_IRQ_KEY_RELEASE_DIS |
                NAU8824_IRQ_KEY_SHORT_PRESS_DIS, 0);
 
-       nau8824_sema_release(nau8824);
+       if (nau8824->resume_lock) {
+               nau8824_sema_release(nau8824);
+               nau8824->resume_lock = false;
+       }
 }
 
 static void nau8824_setup_auto_irq(struct nau8824 *nau8824)
@@ -966,7 +969,10 @@ static irqreturn_t nau8824_interrupt(int irq, void *data)
                /* release semaphore held after resume,
                 * and cancel jack detection
                 */
-               nau8824_sema_release(nau8824);
+               if (nau8824->resume_lock) {
+                       nau8824_sema_release(nau8824);
+                       nau8824->resume_lock = false;
+               }
                cancel_work_sync(&nau8824->jdet_work);
        } else if (active_irq & NAU8824_KEY_SHORT_PRESS_IRQ) {
                int key_status, button_pressed;
@@ -1014,27 +1020,42 @@ static irqreturn_t nau8824_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int nau8824_clock_check(struct nau8824 *nau8824,
-       int stream, int rate, int osr)
+static const struct nau8824_osr_attr *
+nau8824_get_osr(struct nau8824 *nau8824, int stream)
 {
-       int osrate;
+       unsigned int osr;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               regmap_read(nau8824->regmap,
+                           NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
+               osr &= NAU8824_DAC_OVERSAMPLE_MASK;
                if (osr >= ARRAY_SIZE(osr_dac_sel))
-                       return -EINVAL;
-               osrate = osr_dac_sel[osr].osr;
+                       return NULL;
+               return &osr_dac_sel[osr];
        } else {
+               regmap_read(nau8824->regmap,
+                           NAU8824_REG_ADC_FILTER_CTRL, &osr);
+               osr &= NAU8824_ADC_SYNC_DOWN_MASK;
                if (osr >= ARRAY_SIZE(osr_adc_sel))
-                       return -EINVAL;
-               osrate = osr_adc_sel[osr].osr;
+                       return NULL;
+               return &osr_adc_sel[osr];
        }
+}
+
+static int nau8824_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
+       const struct nau8824_osr_attr *osr;
 
-       if (!osrate || rate * osr > CLK_DA_AD_MAX) {
-               dev_err(nau8824->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
+       osr = nau8824_get_osr(nau8824, substream->stream);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_DA_AD_MAX / osr->osr);
 }
 
 static int nau8824_hw_params(struct snd_pcm_substream *substream,
@@ -1042,7 +1063,9 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
+       unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
+       const struct nau8824_osr_attr *osr;
+       int err = -EINVAL;
 
        nau8824_sema_acquire(nau8824, HZ);
 
@@ -1053,27 +1076,19 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
         * than 6.144 MHz.
         */
        nau8824->fs = params_rate(params);
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regmap_read(nau8824->regmap,
-                       NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
-               osr &= NAU8824_DAC_OVERSAMPLE_MASK;
-               if (nau8824_clock_check(nau8824, substream->stream,
-                       nau8824->fs, osr))
-                       return -EINVAL;
+       osr = nau8824_get_osr(nau8824, substream->stream);
+       if (!osr || !osr->osr)
+               goto error;
+       if (nau8824->fs * osr->osr > CLK_DA_AD_MAX)
+               goto error;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
                        NAU8824_CLK_DAC_SRC_MASK,
-                       osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT);
-       } else {
-               regmap_read(nau8824->regmap,
-                       NAU8824_REG_ADC_FILTER_CTRL, &osr);
-               osr &= NAU8824_ADC_SYNC_DOWN_MASK;
-               if (nau8824_clock_check(nau8824, substream->stream,
-                       nau8824->fs, osr))
-                       return -EINVAL;
+                       osr->clk_src << NAU8824_CLK_DAC_SRC_SFT);
+       else
                regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
                        NAU8824_CLK_ADC_SRC_MASK,
-                       osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT);
-       }
+                       osr->clk_src << NAU8824_CLK_ADC_SRC_SFT);
 
        /* make BCLK and LRC divde configuration if the codec as master. */
        regmap_read(nau8824->regmap,
@@ -1090,7 +1105,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                else if (bclk_fs <= 256)
                        bclk_div = 0;
                else
-                       return -EINVAL;
+                       goto error;
                regmap_update_bits(nau8824->regmap,
                        NAU8824_REG_PORT0_I2S_PCM_CTRL_2,
                        NAU8824_I2S_LRC_DIV_MASK | NAU8824_I2S_BLK_DIV_MASK,
@@ -1111,15 +1126,17 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                val_len |= NAU8824_I2S_DL_32;
                break;
        default:
-               return -EINVAL;
+               goto error;
        }
 
        regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
                NAU8824_I2S_DL_MASK, val_len);
+       err = 0;
 
+ error:
        nau8824_sema_release(nau8824);
 
-       return 0;
+       return err;
 }
 
 static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -1128,8 +1145,6 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
        unsigned int ctrl1_val = 0, ctrl2_val = 0;
 
-       nau8824_sema_acquire(nau8824, HZ);
-
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                ctrl2_val |= NAU8824_I2S_MS_MASTER;
@@ -1171,6 +1186,8 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
+       nau8824_sema_acquire(nau8824, HZ);
+
        regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
                NAU8824_I2S_DF_MASK | NAU8824_I2S_BP_MASK |
                NAU8824_I2S_PCMB_EN, ctrl1_val);
@@ -1513,6 +1530,7 @@ static int __maybe_unused nau8824_suspend(struct snd_soc_component *component)
 static int __maybe_unused nau8824_resume(struct snd_soc_component *component)
 {
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
+       int ret;
 
        regcache_cache_only(nau8824->regmap, false);
        regcache_sync(nau8824->regmap);
@@ -1520,7 +1538,10 @@ static int __maybe_unused nau8824_resume(struct snd_soc_component *component)
                /* Hold semaphore to postpone playback happening
                 * until jack detection done.
                 */
-               nau8824_sema_acquire(nau8824, 0);
+               nau8824->resume_lock = true;
+               ret = nau8824_sema_acquire(nau8824, 0);
+               if (ret)
+                       nau8824->resume_lock = false;
                enable_irq(nau8824->irq);
        }
 
@@ -1547,6 +1568,7 @@ static const struct snd_soc_component_driver nau8824_component_driver = {
 };
 
 static const struct snd_soc_dai_ops nau8824_dai_ops = {
+       .startup = nau8824_dai_startup,
        .hw_params = nau8824_hw_params,
        .set_fmt = nau8824_set_fmt,
        .set_tdm_slot = nau8824_set_tdm_slot,
@@ -1928,6 +1950,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c)
        nau8824->regmap = devm_regmap_init_i2c(i2c, &nau8824_regmap_config);
        if (IS_ERR(nau8824->regmap))
                return PTR_ERR(nau8824->regmap);
+       nau8824->resume_lock = false;
        nau8824->dev = dev;
        nau8824->irq = i2c->irq;
        sema_init(&nau8824->jd_sem, 1);
index de4bae8..5fcfc43 100644 (file)
@@ -436,6 +436,7 @@ struct nau8824 {
        struct semaphore jd_sem;
        int fs;
        int irq;
+       int resume_lock;
        int micbias_voltage;
        int vref_impedance;
        int jkdet_polarity;
index 54ef7b0..8213273 100644 (file)
@@ -1247,27 +1247,42 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
        {"HPOR", NULL, "Class G"},
 };
 
-static int nau8825_clock_check(struct nau8825 *nau8825,
-       int stream, int rate, int osr)
+static const struct nau8825_osr_attr *
+nau8825_get_osr(struct nau8825 *nau8825, int stream)
 {
-       int osrate;
+       unsigned int osr;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               regmap_read(nau8825->regmap,
+                           NAU8825_REG_DAC_CTRL1, &osr);
+               osr &= NAU8825_DAC_OVERSAMPLE_MASK;
                if (osr >= ARRAY_SIZE(osr_dac_sel))
-                       return -EINVAL;
-               osrate = osr_dac_sel[osr].osr;
+                       return NULL;
+               return &osr_dac_sel[osr];
        } else {
+               regmap_read(nau8825->regmap,
+                           NAU8825_REG_ADC_RATE, &osr);
+               osr &= NAU8825_ADC_SYNC_DOWN_MASK;
                if (osr >= ARRAY_SIZE(osr_adc_sel))
-                       return -EINVAL;
-               osrate = osr_adc_sel[osr].osr;
+                       return NULL;
+               return &osr_adc_sel[osr];
        }
+}
 
-       if (!osrate || rate * osr > CLK_DA_AD_MAX) {
-               dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
+static int nau8825_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
+       const struct nau8825_osr_attr *osr;
+
+       osr = nau8825_get_osr(nau8825, substream->stream);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_DA_AD_MAX / osr->osr);
 }
 
 static int nau8825_hw_params(struct snd_pcm_substream *substream,
@@ -1276,7 +1291,9 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
+       unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
+       const struct nau8825_osr_attr *osr;
+       int err = -EINVAL;
 
        nau8825_sema_acquire(nau8825, 3 * HZ);
 
@@ -1286,29 +1303,19 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
-               osr &= NAU8825_DAC_OVERSAMPLE_MASK;
-               if (nau8825_clock_check(nau8825, substream->stream,
-                       params_rate(params), osr)) {
-                       nau8825_sema_release(nau8825);
-                       return -EINVAL;
-               }
+       osr = nau8825_get_osr(nau8825, substream->stream);
+       if (!osr || !osr->osr)
+               goto error;
+       if (params_rate(params) * osr->osr > CLK_DA_AD_MAX)
+               goto error;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
                        NAU8825_CLK_DAC_SRC_MASK,
-                       osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
-       } else {
-               regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
-               osr &= NAU8825_ADC_SYNC_DOWN_MASK;
-               if (nau8825_clock_check(nau8825, substream->stream,
-                       params_rate(params), osr)) {
-                       nau8825_sema_release(nau8825);
-                       return -EINVAL;
-               }
+                       osr->clk_src << NAU8825_CLK_DAC_SRC_SFT);
+       else
                regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
                        NAU8825_CLK_ADC_SRC_MASK,
-                       osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
-       }
+                       osr->clk_src << NAU8825_CLK_ADC_SRC_SFT);
 
        /* make BCLK and LRC divde configuration if the codec as master. */
        regmap_read(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, &ctrl_val);
@@ -1321,10 +1328,8 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
                        bclk_div = 1;
                else if (bclk_fs <= 128)
                        bclk_div = 0;
-               else {
-                       nau8825_sema_release(nau8825);
-                       return -EINVAL;
-               }
+               else
+                       goto error;
                regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
                        NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK,
                        ((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div);
@@ -1344,17 +1349,18 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
                val_len |= NAU8825_I2S_DL_32;
                break;
        default:
-               nau8825_sema_release(nau8825);
-               return -EINVAL;
+               goto error;
        }
 
        regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
                NAU8825_I2S_DL_MASK, val_len);
+       err = 0;
 
+ error:
        /* Release the semaphore. */
        nau8825_sema_release(nau8825);
 
-       return 0;
+       return err;
 }
 
 static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
@@ -1420,6 +1426,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 }
 
 static const struct snd_soc_dai_ops nau8825_dai_ops = {
+       .startup        = nau8825_dai_startup,
        .hw_params      = nau8825_hw_params,
        .set_fmt        = nau8825_set_dai_fmt,
 };
index 5a84432..0f8e6dd 100644 (file)
@@ -2494,7 +2494,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
 
        /* Select JD-source */
        snd_soc_component_update_bits(component, RT5640_JD_CTRL,
-               RT5640_JD_MASK, rt5640->jd_src);
+               RT5640_JD_MASK, rt5640->jd_src << RT5640_JD_SFT);
 
        /* Selecting GPIO01 as an interrupt */
        snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1,
@@ -2504,12 +2504,8 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
        snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3,
                RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT);
 
-       /* Enabling jd2 in general control 1 */
        snd_soc_component_write(component, RT5640_DUMMY1, 0x3f41);
 
-       /* Enabling jd2 in general control 2 */
-       snd_soc_component_write(component, RT5640_DUMMY2, 0x4001);
-
        rt5640_set_ovcd_params(component);
 
        /*
@@ -2518,12 +2514,25 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
         * pin 0/1 instead of it being stuck to 1. So we invert the JD polarity
         * on systems where the hardware does not already do this.
         */
-       if (rt5640->jd_inverted)
-               snd_soc_component_write(component, RT5640_IRQ_CTRL1,
-                                       RT5640_IRQ_JD_NOR);
-       else
-               snd_soc_component_write(component, RT5640_IRQ_CTRL1,
-                                       RT5640_IRQ_JD_NOR | RT5640_JD_P_INV);
+       if (rt5640->jd_inverted) {
+               if (rt5640->jd_src == RT5640_JD_SRC_JD1_IN4P)
+                       snd_soc_component_write(component, RT5640_IRQ_CTRL1,
+                               RT5640_IRQ_JD_NOR);
+               else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N)
+                       snd_soc_component_update_bits(component, RT5640_DUMMY2,
+                               RT5640_IRQ_JD2_MASK | RT5640_JD2_MASK,
+                               RT5640_IRQ_JD2_NOR | RT5640_JD2_EN);
+       } else {
+               if (rt5640->jd_src == RT5640_JD_SRC_JD1_IN4P)
+                       snd_soc_component_write(component, RT5640_IRQ_CTRL1,
+                               RT5640_IRQ_JD_NOR | RT5640_JD_P_INV);
+               else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N)
+                       snd_soc_component_update_bits(component, RT5640_DUMMY2,
+                               RT5640_IRQ_JD2_MASK | RT5640_JD2_P_MASK |
+                               RT5640_JD2_MASK,
+                               RT5640_IRQ_JD2_NOR | RT5640_JD2_P_INV |
+                               RT5640_JD2_EN);
+       }
 
        rt5640->jack = jack;
        if (rt5640->jack->status & SND_JACK_MICROPHONE) {
@@ -2725,10 +2734,8 @@ static int rt5640_probe(struct snd_soc_component *component)
 
        if (device_property_read_u32(component->dev,
                                     "realtek,jack-detect-source", &val) == 0) {
-               if (val <= RT5640_JD_SRC_GPIO4)
-                       rt5640->jd_src = val << RT5640_JD_SFT;
-               else if (val == RT5640_JD_SRC_HDA_HEADER)
-                       rt5640->jd_src = RT5640_JD_SRC_HDA_HEADER;
+               if (val <= RT5640_JD_SRC_HDA_HEADER)
+                       rt5640->jd_src = val;
                else
                        dev_warn(component->dev, "Warning: Invalid jack-detect-source value: %d, leaving jack-detect disabled\n",
                                 val);
@@ -2809,12 +2816,31 @@ static int rt5640_resume(struct snd_soc_component *component)
        regcache_sync(rt5640->regmap);
 
        if (rt5640->jack) {
-               if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER)
+               if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) {
                        snd_soc_component_update_bits(component,
                                RT5640_DUMMY2, 0x1100, 0x1100);
-               else
-                       snd_soc_component_write(component, RT5640_DUMMY2,
-                               0x4001);
+               } else {
+                       if (rt5640->jd_inverted) {
+                               if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N)
+                                       snd_soc_component_update_bits(
+                                               component, RT5640_DUMMY2,
+                                               RT5640_IRQ_JD2_MASK |
+                                               RT5640_JD2_MASK,
+                                               RT5640_IRQ_JD2_NOR |
+                                               RT5640_JD2_EN);
+
+                       } else {
+                               if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N)
+                                       snd_soc_component_update_bits(
+                                               component, RT5640_DUMMY2,
+                                               RT5640_IRQ_JD2_MASK |
+                                               RT5640_JD2_P_MASK |
+                                               RT5640_JD2_MASK,
+                                               RT5640_IRQ_JD2_NOR |
+                                               RT5640_JD2_P_INV |
+                                               RT5640_JD2_EN);
+                       }
+               }
 
                queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
        }
index 505c935..f58b88e 100644 (file)
 #define RT5640_M_MONO_ADC_R_SFT                        12
 #define RT5640_MCLK_DET                                (0x1 << 11)
 
+/* General Control 1 (0xfb) */
+#define RT5640_IRQ_JD2_MASK                    (0x1 << 12)
+#define RT5640_IRQ_JD2_SFT                     12
+#define RT5640_IRQ_JD2_BP                      (0x0 << 12)
+#define RT5640_IRQ_JD2_NOR                     (0x1 << 12)
+#define RT5640_JD2_P_MASK                      (0x1 << 10)
+#define RT5640_JD2_P_SFT                       10
+#define RT5640_JD2_P_NOR                       (0x0 << 10)
+#define RT5640_JD2_P_INV                       (0x1 << 10)
+#define RT5640_JD2_MASK                                (0x1 << 8)
+#define RT5640_JD2_SFT                         8
+#define RT5640_JD2_DIS                         (0x0 << 8)
+#define RT5640_JD2_EN                          (0x1 << 8)
+
 /* Codec Private Register definition */
 
 /* MIC Over current threshold scale factor (0x15) */
index bb653b6..b676523 100644 (file)
@@ -495,6 +495,8 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
        },
 };
 
+static const struct regmap_config tas2770_i2c_regmap;
+
 static int tas2770_codec_probe(struct snd_soc_component *component)
 {
        struct tas2770_priv *tas2770 =
@@ -508,6 +510,7 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
        }
 
        tas2770_reset(tas2770);
+       regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap);
 
        return 0;
 }
index 873295f..1e421d9 100644 (file)
@@ -234,18 +234,26 @@ static int fsl_aud2htx_probe(struct platform_device *pdev)
 
        regcache_cache_only(aud2htx->regmap, true);
 
+       /*
+        * Register platform component before registering cpu dai for there
+        * is not defer probe for platform component in snd_soc_add_pcm_runtime().
+        */
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to pcm register\n");
+               pm_runtime_disable(&pdev->dev);
+               return ret;
+       }
+
        ret = devm_snd_soc_register_component(&pdev->dev,
                                              &fsl_aud2htx_component,
                                              &fsl_aud2htx_dai, 1);
        if (ret) {
                dev_err(&pdev->dev, "failed to register ASoC DAI\n");
+               pm_runtime_disable(&pdev->dev);
                return ret;
        }
 
-       ret = imx_pcm_dma_init(pdev);
-       if (ret)
-               dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
-
        return ret;
 }
 
index c1e2f67..4922e67 100644 (file)
@@ -122,7 +122,7 @@ static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        }
 
        switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
-       case SND_SOC_DAIFMT_BP_FP:
+       case SND_SOC_DAIFMT_CBC_CFC:
                break;
        default:
                return -EINVAL;
index 7523bb9..d430eec 100644 (file)
@@ -1306,7 +1306,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
                sai->mclk_clk[i] = devm_clk_get(dev, tmp);
                if (IS_ERR(sai->mclk_clk[i])) {
                        dev_err(dev, "failed to get mclk%d clock: %ld\n",
-                                       i + 1, PTR_ERR(sai->mclk_clk[i]));
+                                       i, PTR_ERR(sai->mclk_clk[i]));
                        sai->mclk_clk[i] = NULL;
                }
        }
index 14be295..3f128ce 100644 (file)
@@ -698,6 +698,10 @@ static int imx_card_parse_of(struct imx_card_data *data)
                of_node_put(cpu);
                of_node_put(codec);
                of_node_put(platform);
+
+               cpu = NULL;
+               codec = NULL;
+               platform = NULL;
        }
 
        return 0;
index a49bfaa..2ff30b4 100644 (file)
@@ -270,6 +270,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                .callback = sof_sdw_quirk_cb,
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
+               },
+               .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+                                       RT711_JD2 |
+                                       SOF_SDW_FOUR_SPK),
+       },
+       {
+               .callback = sof_sdw_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
                },
                .driver_data = (void *)(SOF_SDW_TGL_HDMI |
index 2667045..0944024 100644 (file)
@@ -271,9 +271,6 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
                /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
                usleep_range(125, 135);
                mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 1);
-
-               /* reset dmic */
-               afe_priv->mtkaif_dmic = 0;
                break;
        default:
                break;
index ce4a571..98a2fde 100644 (file)
@@ -270,6 +270,7 @@ static int sm8250_platform_probe(struct platform_device *pdev)
        if (!card)
                return -ENOMEM;
 
+       card->owner = THIS_MODULE;
        /* Allocate the private data */
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
index e90f173..37f7df5 100644 (file)
@@ -196,6 +196,7 @@ config SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE
 
 config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST
        tristate "SOF enable IPC flood test"
+       depends on SND_SOC_SOF
        select SND_SOC_SOF_CLIENT
        help
          This option enables a separate client device for IPC flood test
@@ -214,6 +215,7 @@ config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM
 
 config SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR
        tristate "SOF enable IPC message injector"
+       depends on SND_SOC_SOF
        select SND_SOC_SOF_CLIENT
        help
          This option enables the IPC message injector which can be used to send
index af072b4..64929dc 100644 (file)
@@ -771,7 +771,7 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
                goto err;
 
        ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
-                                   swidget->num_tuples, sizeof(src), 1);
+                                   swidget->num_tuples, sizeof(*src), 1);
        if (ret) {
                dev_err(scomp->dev, "Parsing SRC tokens failed\n");
                goto err;
@@ -1251,7 +1251,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
                        if (blob->alh_cfg.count > 1) {
                                int group_id;
 
-                               group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT,
+                               group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1,
                                                         GFP_KERNEL);
 
                                if (group_id < 0)
index d356743..706d249 100644 (file)
@@ -699,7 +699,7 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
                if (delayed_register[i] &&
                    sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
                    id == chip->usb_id)
-                       return inum != iface;
+                       return iface < inum;
        }
 
        return false;
index 0d7b73b..eb71df9 100644 (file)
@@ -924,6 +924,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
                endpoint_set_interface(chip, ep, false);
 
        if (!--ep->opened) {
+               if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
+                       ep->clock_ref->rate = 0;
                ep->iface = 0;
                ep->altsetting = 0;
                ep->cur_audiofmt = NULL;
index 168fd80..5b4d8f5 100644 (file)
@@ -1764,7 +1764,7 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
 
        for (q = registration_quirks; q->usb_id; q++)
                if (chip->usb_id == q->usb_id)
-                       return iface != q->interface;
+                       return iface < q->interface;
 
        /* Register as normal */
        return false;
@@ -1903,6 +1903,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
+                  QUIRK_FLAG_SET_IFACE_FIRST),
        DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
index ceb93d7..f10f4e6 100644 (file)
@@ -495,6 +495,10 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                        return 0;
                }
        }
+
+       if (chip->card->registered)
+               chip->need_delayed_register = true;
+
        /* look for an empty stream */
        list_for_each_entry(as, &chip->pcm_list, list) {
                if (as->fmt_type != fp->fmt_type)
@@ -502,9 +506,6 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                subs = &as->substream[stream];
                if (subs->ep_num)
                        continue;
-               if (snd_device_get_state(chip->card, as->pcm) !=
-                   SNDRV_DEV_BUILD)
-                       chip->need_delayed_register = true;
                err = snd_pcm_new_stream(as->pcm, stream, 1);
                if (err < 0)
                        return err;
@@ -1105,7 +1106,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
         * Dallas DS4201 workaround: It presents 5 altsettings, but the last
         * one misses syncpipe, and does not produce any sound.
         */
-       if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+       if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4)
                num = 4;
 
        for (i = 0; i < num; i++) {
index 235dc85..ef4775c 100644 (file)
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 #define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
 #define X86_BUG_MMIO_STALE_DATA                X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
-#define X86_BUG_RETBLEED               X86_BUG(26) /* CPU is affected by RETBleed */
-#define X86_BUG_EIBRS_PBRSB            X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
+#define X86_BUG_MMIO_UNKNOWN           X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
+#define X86_BUG_RETBLEED               X86_BUG(27) /* CPU is affected by RETBleed */
+#define X86_BUG_EIBRS_PBRSB            X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index f1af27c..279be06 100755 (executable)
@@ -187,6 +187,7 @@ else
        echo " * auxiliary taint, defined for and used by distros (#16)"
 
 fi
+
 T=`expr $T / 2`
 if [ `expr $T % 2` -eq 0 ]; then
        addout " "
@@ -195,6 +196,14 @@ else
        echo " * kernel was built with the struct randomization plugin (#17)"
 fi
 
+T=`expr $T / 2`
+if [ `expr $T % 2` -eq 0 ]; then
+       addout " "
+else
+       addout "N"
+       echo " * an in-kernel test (such as a KUnit test) has been run (#18)"
+fi
+
 echo "For a more detailed explanation of the various taint flags see"
 echo " Documentation/admin-guide/tainted-kernels.rst in the Linux kernel sources"
 echo " or https://kernel.org/doc/html/latest/admin-guide/tainted-kernels.html"
index 1e6fd6c..27f5e7d 100644 (file)
@@ -44,7 +44,7 @@
 
 /*
  * KVP protocol: The user mode component first registers with the
- * the kernel component. Subsequently, the kernel component requests, data
+ * kernel component. Subsequently, the kernel component requests, data
  * for the specified keys. In response to this message the user mode component
  * fills in the value corresponding to the specified key. We overload the
  * sequence field in the cn_msg header to define our KVP message types.
@@ -772,11 +772,11 @@ static int kvp_process_ip_address(void *addrp,
        const char *str;
 
        if (family == AF_INET) {
-               addr = (struct sockaddr_in *)addrp;
+               addr = addrp;
                str = inet_ntop(family, &addr->sin_addr, tmp, 50);
                addr_length = INET_ADDRSTRLEN;
        } else {
-               addr6 = (struct sockaddr_in6 *)addrp;
+               addr6 = addrp;
                str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
                addr_length = INET6_ADDRSTRLEN;
        }
index b238dbc..6a10ff5 100644 (file)
@@ -3,26 +3,7 @@
 #define _TOOLS_INCLUDE_LINUX_GFP_H
 
 #include <linux/types.h>
-
-#define __GFP_BITS_SHIFT 26
-#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
-
-#define __GFP_HIGH             0x20u
-#define __GFP_IO               0x40u
-#define __GFP_FS               0x80u
-#define __GFP_NOWARN           0x200u
-#define __GFP_ZERO             0x8000u
-#define __GFP_ATOMIC           0x80000u
-#define __GFP_ACCOUNT          0x100000u
-#define __GFP_DIRECT_RECLAIM   0x400000u
-#define __GFP_KSWAPD_RECLAIM   0x2000000u
-
-#define __GFP_RECLAIM  (__GFP_DIRECT_RECLAIM | __GFP_KSWAPD_RECLAIM)
-
-#define GFP_ZONEMASK   0x0fu
-#define GFP_ATOMIC     (__GFP_HIGH | __GFP_ATOMIC | __GFP_KSWAPD_RECLAIM)
-#define GFP_KERNEL     (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
-#define GFP_NOWAIT     (__GFP_KSWAPD_RECLAIM)
+#include <linux/gfp_types.h>
 
 static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
 {
diff --git a/tools/include/linux/gfp_types.h b/tools/include/linux/gfp_types.h
new file mode 100644 (file)
index 0000000..5f9f1ed
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/gfp_types.h"
index 95e2b79..ba04771 100644 (file)
@@ -190,7 +190,7 @@ __asm__ (".section .text\n"
     ".option norelax\n"
     "lla   gp, __global_pointer$\n"
     ".option pop\n"
-    "ld    a0, 0(sp)\n"          // argc (a0) was in the stack
+    "lw    a0, 0(sp)\n"          // argc (a0) was in the stack
     "add   a1, sp, "SZREG"\n"    // argv (a1) = sp
     "slli  a2, a0, "PTRLOG"\n"   // envp (a2) = SZREG*argc ...
     "add   a2, a2, "SZREG"\n"    //             + SZREG (skip null)
index 0849107..ce3ee03 100644 (file)
@@ -692,12 +692,12 @@ void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
 {
 #ifndef my_syscall6
        /* Function not implemented. */
-       return -ENOSYS;
+       return (void *)-ENOSYS;
 #else
 
        int n;
 
-#if defined(__i386__)
+#if defined(__NR_mmap2)
        n = __NR_mmap2;
        offset >>= 12;
 #else
index d30439b..869379f 100644 (file)
@@ -9,8 +9,8 @@
 #include "../../../arch/alpha/include/uapi/asm/errno.h"
 #elif defined(__mips__)
 #include "../../../arch/mips/include/uapi/asm/errno.h"
-#elif defined(__xtensa__)
-#include "../../../arch/xtensa/include/uapi/asm/errno.h"
+#elif defined(__hppa__)
+#include "../../../arch/parisc/include/uapi/asm/errno.h"
 #else
 #include <asm-generic/errno.h>
 #endif
index e6c98a6..8ec5b9f 100644 (file)
@@ -441,6 +441,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
 
        perf_evlist__for_each_entry(evlist, evsel) {
                bool overwrite = evsel->attr.write_backward;
+               enum fdarray_flags flgs;
                struct perf_mmap *map;
                int *output, fd, cpu;
 
@@ -486,6 +487,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
                        if (ops->idx)
                                ops->idx(evlist, evsel, mp, idx);
 
+                       pr_debug("idx %d: mmapping fd %d\n", idx, *output);
                        if (ops->mmap(map, mp, *output, evlist_cpu) < 0)
                                return -1;
 
@@ -494,6 +496,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
                        if (!idx)
                                perf_evlist__set_mmap_first(evlist, map, overwrite);
                } else {
+                       pr_debug("idx %d: set output fd %d -> %d\n", idx, fd, *output);
                        if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
                                return -1;
 
@@ -502,8 +505,8 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
 
                revent = !overwrite ? POLLIN : 0;
 
-               if (!evsel->system_wide &&
-                   perf_evlist__add_pollfd(evlist, fd, map, revent, fdarray_flag__default) < 0) {
+               flgs = evsel->system_wide ? fdarray_flag__nonfilterable : fdarray_flag__default;
+               if (perf_evlist__add_pollfd(evlist, fd, map, revent, flgs) < 0) {
                        perf_mmap__put(map);
                        return -1;
                }
@@ -520,6 +523,48 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
 }
 
 static int
+mmap_per_thread(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
+               struct perf_mmap_param *mp)
+{
+       int nr_threads = perf_thread_map__nr(evlist->threads);
+       int nr_cpus    = perf_cpu_map__nr(evlist->all_cpus);
+       int cpu, thread, idx = 0;
+       int nr_mmaps = 0;
+
+       pr_debug("%s: nr cpu values (may include -1) %d nr threads %d\n",
+                __func__, nr_cpus, nr_threads);
+
+       /* per-thread mmaps */
+       for (thread = 0; thread < nr_threads; thread++, idx++) {
+               int output = -1;
+               int output_overwrite = -1;
+
+               if (mmap_per_evsel(evlist, ops, idx, mp, 0, thread, &output,
+                                  &output_overwrite, &nr_mmaps))
+                       goto out_unmap;
+       }
+
+       /* system-wide mmaps i.e. per-cpu */
+       for (cpu = 1; cpu < nr_cpus; cpu++, idx++) {
+               int output = -1;
+               int output_overwrite = -1;
+
+               if (mmap_per_evsel(evlist, ops, idx, mp, cpu, 0, &output,
+                                  &output_overwrite, &nr_mmaps))
+                       goto out_unmap;
+       }
+
+       if (nr_mmaps != evlist->nr_mmaps)
+               pr_err("Miscounted nr_mmaps %d vs %d\n", nr_mmaps, evlist->nr_mmaps);
+
+       return 0;
+
+out_unmap:
+       perf_evlist__munmap(evlist);
+       return -1;
+}
+
+static int
 mmap_per_cpu(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
             struct perf_mmap_param *mp)
 {
@@ -528,6 +573,8 @@ mmap_per_cpu(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
        int nr_mmaps = 0;
        int cpu, thread;
 
+       pr_debug("%s: nr cpu values %d nr threads %d\n", __func__, nr_cpus, nr_threads);
+
        for (cpu = 0; cpu < nr_cpus; cpu++) {
                int output = -1;
                int output_overwrite = -1;
@@ -569,6 +616,7 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
                          struct perf_evlist_mmap_ops *ops,
                          struct perf_mmap_param *mp)
 {
+       const struct perf_cpu_map *cpus = evlist->all_cpus;
        struct perf_evsel *evsel;
 
        if (!ops || !ops->get || !ops->mmap)
@@ -588,6 +636,9 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
        if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
                return -ENOMEM;
 
+       if (perf_cpu_map__empty(cpus))
+               return mmap_per_thread(evlist, ops, mp);
+
        return mmap_per_cpu(evlist, ops, mp);
 }
 
index 8a9d5d2..26554b1 100644 (file)
@@ -946,22 +946,39 @@ Limitations of the Linux-kernel memory model (LKMM) include:
        carrying a dependency, then the compiler can break that dependency
        by substituting a constant of that value.
 
-       Conversely, LKMM sometimes doesn't recognize that a particular
-       optimization is not allowed, and as a result, thinks that a
-       dependency is not present (because the optimization would break it).
-       The memory model misses some pretty obvious control dependencies
-       because of this limitation.  A simple example is:
+       Conversely, LKMM will sometimes overestimate the amount of
+       reordering compilers and CPUs can carry out, leading it to miss
+       some pretty obvious cases of ordering.  A simple example is:
 
                r1 = READ_ONCE(x);
                if (r1 == 0)
                        smp_mb();
                WRITE_ONCE(y, 1);
 
-       There is a control dependency from the READ_ONCE to the WRITE_ONCE,
-       even when r1 is nonzero, but LKMM doesn't realize this and thinks
-       that the write may execute before the read if r1 != 0.  (Yes, that
-       doesn't make sense if you think about it, but the memory model's
-       intelligence is limited.)
+       The WRITE_ONCE() does not depend on the READ_ONCE(), and as a
+       result, LKMM does not claim ordering.  However, even though no
+       dependency is present, the WRITE_ONCE() will not be executed before
+       the READ_ONCE().  There are two reasons for this:
+
+                The presence of the smp_mb() in one of the branches
+                prevents the compiler from moving the WRITE_ONCE()
+                up before the "if" statement, since the compiler has
+                to assume that r1 will sometimes be 0 (but see the
+                comment below);
+
+                CPUs do not execute stores before po-earlier conditional
+                branches, even in cases where the store occurs after the
+                two arms of the branch have recombined.
+
+       It is clear that it is not dangerous in the slightest for LKMM to
+       make weaker guarantees than architectures.  In fact, it is
+       desirable, as it gives compilers room for making optimizations.
+       For instance, suppose that a 0 value in r1 would trigger undefined
+       behavior elsewhere.  Then a clever compiler might deduce that r1
+       can never be 0 in the if condition.  As a result, said clever
+       compiler might deem it safe to optimize away the smp_mb(),
+       eliminating the branch and any ordering an architecture would
+       guarantee otherwise.
 
 2.     Multiple access sizes for a single variable are not supported,
        and neither are misaligned or partially overlapping accesses.
index e5921b3..bd94788 100644 (file)
@@ -954,11 +954,11 @@ ifndef NO_LIBBPF
        $(call QUIET_INSTALL, bpf-headers) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'; \
-               $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
-               $(INSTALL) include/bpf/linux/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'
+               $(INSTALL) include/bpf/*.h -m 644 -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
+               $(INSTALL) include/bpf/linux/*.h -m 644 -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'
        $(call QUIET_INSTALL, bpf-examples) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \
-               $(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
+               $(INSTALL) examples/bpf/*.c -m 644 -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
 endif
        $(call QUIET_INSTALL, perf-archive) \
                $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
@@ -967,13 +967,13 @@ endif
 ifndef NO_LIBAUDIT
        $(call QUIET_INSTALL, strace/groups) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(STRACE_GROUPS_INSTDIR_SQ)'; \
-               $(INSTALL) trace/strace/groups/* -t '$(DESTDIR_SQ)$(STRACE_GROUPS_INSTDIR_SQ)'
+               $(INSTALL) trace/strace/groups/* -m 644 -t '$(DESTDIR_SQ)$(STRACE_GROUPS_INSTDIR_SQ)'
 endif
 ifndef NO_LIBPERL
        $(call QUIET_INSTALL, perl-scripts) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
-               $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
-               $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'; \
+               $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
+               $(INSTALL) scripts/perl/*.pl -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'; \
                $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
 endif
@@ -990,23 +990,23 @@ endif
                $(INSTALL) $(DLFILTERS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/dlfilters';
        $(call QUIET_INSTALL, perf_completion-script) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
-               $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
+               $(INSTALL) perf-completion.sh -m 644 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
        $(call QUIET_INSTALL, perf-tip) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(tip_instdir_SQ)'; \
-               $(INSTALL) Documentation/tips.txt -t '$(DESTDIR_SQ)$(tip_instdir_SQ)'
+               $(INSTALL) Documentation/tips.txt -m 644 -t '$(DESTDIR_SQ)$(tip_instdir_SQ)'
 
 install-tests: all install-gtk
        $(call QUIET_INSTALL, tests) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
-               $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
+               $(INSTALL) tests/attr.py -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
                $(INSTALL) tests/pe-file.exe* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
-               $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
+               $(INSTALL) tests/attr/* -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
                $(INSTALL) tests/shell/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
-               $(INSTALL) tests/shell/lib/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
-               $(INSTALL) tests/shell/lib/*.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'
+               $(INSTALL) tests/shell/lib/*.sh -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
+               $(INSTALL) tests/shell/lib/*.py -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'
 
 install-bin: install-tools install-tests install-traceevent-plugins
 
index 653e13b..438fc22 100644 (file)
@@ -146,15 +146,15 @@ static void *c2c_he_zalloc(size_t size)
 
        c2c_he->cpuset = bitmap_zalloc(c2c.cpus_cnt);
        if (!c2c_he->cpuset)
-               return NULL;
+               goto out_free;
 
        c2c_he->nodeset = bitmap_zalloc(c2c.nodes_cnt);
        if (!c2c_he->nodeset)
-               return NULL;
+               goto out_free;
 
        c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
        if (!c2c_he->node_stats)
-               return NULL;
+               goto out_free;
 
        init_stats(&c2c_he->cstats.lcl_hitm);
        init_stats(&c2c_he->cstats.rmt_hitm);
@@ -163,6 +163,12 @@ static void *c2c_he_zalloc(size_t size)
        init_stats(&c2c_he->cstats.load);
 
        return &c2c_he->he;
+
+out_free:
+       free(c2c_he->nodeset);
+       free(c2c_he->cpuset);
+       free(c2c_he);
+       return NULL;
 }
 
 static void c2c_he_free(void *he)
index dd11d34..ea40ae5 100644 (file)
@@ -1874,8 +1874,7 @@ int cmd_lock(int argc, const char **argv)
                NULL
        };
        const char *const lock_subcommands[] = { "record", "report", "script",
-                                                "info", "contention",
-                                                "contention", NULL };
+                                                "info", "contention", NULL };
        const char *lock_usage[] = {
                NULL,
                NULL
index 4713f0f..0f711f8 100644 (file)
@@ -1906,14 +1906,18 @@ static int record__synthesize(struct record *rec, bool tail)
 
        err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
                                                machine, opts);
-       if (err < 0)
+       if (err < 0) {
                pr_warning("Couldn't synthesize bpf events.\n");
+               err = 0;
+       }
 
        if (rec->opts.synth & PERF_SYNTH_CGROUP) {
                err = perf_event__synthesize_cgroups(tool, process_synthesized_event,
                                                     machine);
-               if (err < 0)
+               if (err < 0) {
                        pr_warning("Couldn't synthesize cgroup events.\n");
+                       err = 0;
+               }
        }
 
        if (rec->opts.nr_threads_synthesize > 1) {
@@ -3358,16 +3362,24 @@ static struct option __record_options[] = {
 
 struct option *record_options = __record_options;
 
-static void record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus)
+static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus)
 {
        struct perf_cpu cpu;
        int idx;
 
        if (cpu_map__is_dummy(cpus))
-               return;
+               return 0;
 
-       perf_cpu_map__for_each_cpu(cpu, idx, cpus)
+       perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
+               if (cpu.cpu == -1)
+                       continue;
+               /* Return ENODEV is input cpu is greater than max cpu */
+               if ((unsigned long)cpu.cpu > mask->nbits)
+                       return -ENODEV;
                set_bit(cpu.cpu, mask->bits);
+       }
+
+       return 0;
 }
 
 static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const char *mask_spec)
@@ -3379,7 +3391,9 @@ static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const cha
                return -ENOMEM;
 
        bitmap_zero(mask->bits, mask->nbits);
-       record__mmap_cpu_mask_init(mask, cpus);
+       if (record__mmap_cpu_mask_init(mask, cpus))
+               return -ENODEV;
+
        perf_cpu_map__put(cpus);
 
        return 0;
@@ -3461,7 +3475,12 @@ static int record__init_thread_masks_spec(struct record *rec, struct perf_cpu_ma
                pr_err("Failed to allocate CPUs mask\n");
                return ret;
        }
-       record__mmap_cpu_mask_init(&cpus_mask, cpus);
+
+       ret = record__mmap_cpu_mask_init(&cpus_mask, cpus);
+       if (ret) {
+               pr_err("Failed to init cpu mask\n");
+               goto out_free_cpu_mask;
+       }
 
        ret = record__thread_mask_alloc(&full_mask, cpu__max_cpu().cpu);
        if (ret) {
@@ -3702,7 +3721,8 @@ static int record__init_thread_default_masks(struct record *rec, struct perf_cpu
        if (ret)
                return ret;
 
-       record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus);
+       if (record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus))
+               return -ENODEV;
 
        rec->nr_threads = 1;
 
index 13580a9..029b433 100644 (file)
@@ -445,6 +445,9 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
        struct perf_event_attr *attr = &evsel->core.attr;
        bool allow_user_set;
 
+       if (evsel__is_dummy_event(evsel))
+               return 0;
+
        if (perf_header__has_feat(&session->header, HEADER_STAT))
                return 0;
 
@@ -566,6 +569,8 @@ static struct evsel *find_first_output_type(struct evlist *evlist,
        struct evsel *evsel;
 
        evlist__for_each_entry(evlist, evsel) {
+               if (evsel__is_dummy_event(evsel))
+                       continue;
                if (output_type(evsel->core.attr.type) == (int)type)
                        return evsel;
        }
index 54cd29d..0b4a62e 100644 (file)
@@ -1932,6 +1932,9 @@ setup_metrics:
                free(str);
        }
 
+       if (!stat_config.topdown_level)
+               stat_config.topdown_level = TOPDOWN_MAX_LEVEL;
+
        if (!evsel_list->core.nr_entries) {
                if (target__has_cpu(&target))
                        default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
@@ -1948,8 +1951,6 @@ setup_metrics:
                }
                if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0)
                        return -1;
-
-               stat_config.topdown_level = TOPDOWN_MAX_LEVEL;
                /* Platform specific attrs */
                if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0)
                        return -1;
index 9eccc97..6d47298 100644 (file)
@@ -98,9 +98,9 @@ int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, vo
 static void print_vals(__u64 cycles, __u64 delta)
 {
        if (delta)
-               printf("%10llu %10llu ", cycles, delta);
+               printf("%10llu %10llu ", (unsigned long long)cycles, (unsigned long long)delta);
        else
-               printf("%10llu %10s ", cycles, "");
+               printf("%10llu %10s ", (unsigned long long)cycles, "");
 }
 
 int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
index dfb6173..9e9a2b6 100644 (file)
@@ -114,8 +114,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
 
        for (i = 0; i < nsyscalls; ++i)
                for (j = 0; j < expected_nr_events[i]; ++j) {
-                       int foo = syscalls[i]();
-                       ++foo;
+                       syscalls[i]();
                }
 
        md = &evlist->mmap[0];
index 6a001fc..4952abe 100644 (file)
@@ -332,7 +332,7 @@ out_delete_evlist:
 out:
        if (err == -EACCES)
                return TEST_SKIP;
-       if (err < 0)
+       if (err < 0 || errs != 0)
                return TEST_FAIL;
        return TEST_OK;
 }
index 00c7285..301f954 100755 (executable)
@@ -61,7 +61,7 @@ test_register_capture() {
     echo "Register capture test [Skipped missing registers]"
     return
   fi
-  if ! perf record -o - --intr-regs=di,r8,dx,cx -e cpu/br_inst_retired.near_call/p \
+  if ! perf record -o - --intr-regs=di,r8,dx,cx -e br_inst_retired.near_call:p \
     -c 1000 --per-thread true 2> /dev/null \
     | perf script -F ip,sym,iregs -i - 2> /dev/null \
     | egrep -q "DI:"
diff --git a/tools/perf/tests/shell/stat_bpf_counters_cgrp.sh b/tools/perf/tests/shell/stat_bpf_counters_cgrp.sh
new file mode 100755 (executable)
index 0000000..d724855
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/sh
+# perf stat --bpf-counters --for-each-cgroup test
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+test_cgroups=
+if [ "$1" = "-v" ]; then
+       verbose="1"
+fi
+
+# skip if --bpf-counters --for-each-cgroup is not supported
+check_bpf_counter()
+{
+       if ! perf stat -a --bpf-counters --for-each-cgroup / true > /dev/null 2>&1; then
+               if [ "${verbose}" = "1" ]; then
+                       echo "Skipping: --bpf-counters --for-each-cgroup not supported"
+                       perf --no-pager stat -a --bpf-counters --for-each-cgroup / true || true
+               fi
+               exit 2
+       fi
+}
+
+# find two cgroups to measure
+find_cgroups()
+{
+       # try usual systemd slices first
+       if [ -d /sys/fs/cgroup/system.slice -a -d /sys/fs/cgroup/user.slice ]; then
+               test_cgroups="system.slice,user.slice"
+               return
+       fi
+
+       # try root and self cgroups
+       local self_cgrp=$(grep perf_event /proc/self/cgroup | cut -d: -f3)
+       if [ -z ${self_cgrp} ]; then
+               # cgroup v2 doesn't specify perf_event
+               self_cgrp=$(grep ^0: /proc/self/cgroup | cut -d: -f3)
+       fi
+
+       if [ -z ${self_cgrp} ]; then
+               test_cgroups="/"
+       else
+               test_cgroups="/,${self_cgrp}"
+       fi
+}
+
+# As cgroup events are cpu-wide, we cannot simply compare the result.
+# Just check if it runs without failure and has non-zero results.
+check_system_wide_counted()
+{
+       local output
+
+       output=$(perf stat -a --bpf-counters --for-each-cgroup ${test_cgroups} -e cpu-clock -x, sleep 1  2>&1)
+       if echo ${output} | grep -q -F "<not "; then
+               echo "Some system-wide events are not counted"
+               if [ "${verbose}" = "1" ]; then
+                       echo ${output}
+               fi
+               exit 1
+       fi
+}
+
+check_cpu_list_counted()
+{
+       local output
+
+       output=$(perf stat -C 1 --bpf-counters --for-each-cgroup ${test_cgroups} -e cpu-clock -x, taskset -c 1 sleep 1  2>&1)
+       if echo ${output} | grep -q -F "<not "; then
+               echo "Some CPU events are not counted"
+               if [ "${verbose}" = "1" ]; then
+                       echo ${output}
+               fi
+               exit 1
+       fi
+}
+
+check_bpf_counter
+find_cgroups
+
+check_system_wide_counted
+check_cpu_list_counted
+
+exit 0
index c644f94..ec801cf 100755 (executable)
@@ -12,7 +12,8 @@ if ! [ -x "$(command -v cc)" ]; then
 fi
 
 # skip the test if the hardware doesn't support branch stack sampling
-perf record -b -o- -B true > /dev/null 2>&1 || exit 2
+# and if the architecture doesn't support filter types: any,save_type,u
+perf record -b -o- -B --branch-filter any,save_type,u true > /dev/null 2>&1 || exit 2
 
 TMPDIR=$(mktemp -d /tmp/__perf_test.program.XXXXX)
 
index 4fd8d70..8ab035b 100644 (file)
@@ -43,10 +43,11 @@ static bool is_ignored_symbol(const char *name, char type)
        /* Symbol names that begin with the following are ignored.*/
        static const char * const ignored_prefixes[] = {
                "$",                    /* local symbols for ARM, MIPS, etc. */
-               ".LASANPC",             /* s390 kasan local symbols */
+               ".L",                   /* local labels, .LBB,.Ltmpxxx,.L__unnamed_xx,.LASANPC, etc. */
                "__crc_",               /* modversions */
                "__efistub_",           /* arm64 EFI stub namespace */
-               "__kvm_nvhe_",          /* arm64 non-VHE KVM namespace */
+               "__kvm_nvhe_$",         /* arm64 local symbols in non-VHE KVM namespace */
+               "__kvm_nvhe_.L",        /* arm64 local symbols in non-VHE KVM namespace */
                "__AArch64ADRPThunk_",  /* arm64 lld */
                "__ARMV5PILongThunk_",  /* arm lld */
                "__ARMV7PILongThunk_",
index 9d4c451..56455da 100644 (file)
@@ -2,7 +2,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
 #include <sys/ioctl.h>
+#include <linux/compiler.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/kernel.h>
 #include "tests.h"
@@ -137,8 +139,7 @@ static int test__wp_rw(struct test_suite *test __maybe_unused,
 #endif
 }
 
-static int test__wp_modify(struct test_suite *test __maybe_unused,
-                          int subtest __maybe_unused)
+static int test__wp_modify(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
 {
 #if defined(__s390x__)
        return TEST_SKIP;
@@ -160,6 +161,11 @@ static int test__wp_modify(struct test_suite *test __maybe_unused,
        new_attr.disabled = 1;
        ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
        if (ret < 0) {
+               if (errno == ENOTTY) {
+                       test->test_cases[subtest].skip_reason = "missing kernel support";
+                       ret = TEST_SKIP;
+               }
+
                pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
                close(fd);
                return ret;
index 9dfae1b..485e1a3 100644 (file)
@@ -269,7 +269,7 @@ CFLAGS_expr-flex.o          += $(flex_flags)
 bison_flags := -DYYENABLE_NLS=0
 BISON_GE_35 := $(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 35)
 ifeq ($(BISON_GE_35),1)
-  bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum
+  bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum -Wno-unused-but-set-variable -Wno-unknown-warning-option
 else
   bison_flags += -w
 endif
index 4d216c0..4ee96b3 100644 (file)
@@ -49,8 +49,14 @@ void affinity__set(struct affinity *a, int cpu)
 {
        int cpu_set_size = get_cpu_set_size();
 
-       if (cpu == -1)
+       /*
+        * Return:
+        * - if cpu is -1
+        * - restrict out of bound access to sched_cpus
+        */
+       if (cpu == -1 || ((cpu >= (cpu_set_size * 8))))
                return;
+
        a->changed = true;
        set_bit(cpu, a->sched_cpus);
        /*
index 22dcfe0..906476a 100644 (file)
@@ -498,7 +498,7 @@ static void arm_spe__synth_data_source_generic(const struct arm_spe_record *reco
 static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr)
 {
        union perf_mem_data_src data_src = { 0 };
-       bool is_neoverse = is_midr_in_range(midr, neoverse_spe);
+       bool is_neoverse = is_midr_in_range_list(midr, neoverse_spe);
 
        if (record->op == ARM_SPE_LD)
                data_src.mem_op = PERF_MEM_OP_LOAD;
index 63b9db6..3c2df75 100644 (file)
@@ -95,7 +95,7 @@ static int bperf_load_program(struct evlist *evlist)
 
        perf_cpu_map__for_each_cpu(cpu, i, evlist->core.all_cpus) {
                link = bpf_program__attach_perf_event(skel->progs.on_cgrp_switch,
-                                                     FD(cgrp_switch, cpu.cpu));
+                                                     FD(cgrp_switch, i));
                if (IS_ERR(link)) {
                        pr_err("Failed to attach cgroup program\n");
                        err = PTR_ERR(link);
@@ -115,15 +115,15 @@ static int bperf_load_program(struct evlist *evlist)
                        evsel->cgrp = NULL;
 
                        /* open single copy of the events w/o cgroup */
-                       err = evsel__open_per_cpu(evsel, evlist->core.all_cpus, -1);
+                       err = evsel__open_per_cpu(evsel, evsel->core.cpus, -1);
                        if (err) {
                                pr_err("Failed to open first cgroup events\n");
                                goto out;
                        }
 
                        map_fd = bpf_map__fd(skel->maps.events);
-                       perf_cpu_map__for_each_cpu(cpu, j, evlist->core.all_cpus) {
-                               int fd = FD(evsel, cpu.cpu);
+                       perf_cpu_map__for_each_cpu(cpu, j, evsel->core.cpus) {
+                               int fd = FD(evsel, j);
                                __u32 idx = evsel->core.idx * total_cpus + cpu.cpu;
 
                                err = bpf_map_update_elem(map_fd, &idx, &fd,
@@ -269,7 +269,7 @@ static int bperf_cgrp__read(struct evsel *evsel)
                        goto out;
                }
 
-               perf_cpu_map__for_each_cpu(cpu, i, evlist->core.all_cpus) {
+               perf_cpu_map__for_each_cpu(cpu, i, evsel->core.cpus) {
                        counts = perf_counts(evsel->counts, i, 0);
                        counts->val = values[cpu.cpu].counter;
                        counts->ena = values[cpu.cpu].enabled;
index 292c430..9aa8cdd 100644 (file)
@@ -48,6 +48,7 @@ const volatile __u32 num_cpus = 1;
 
 int enabled = 0;
 int use_cgroup_v2 = 0;
+int perf_subsys_id = -1;
 
 static inline int get_cgroup_v1_idx(__u32 *cgrps, int size)
 {
@@ -58,7 +59,15 @@ static inline int get_cgroup_v1_idx(__u32 *cgrps, int size)
        int level;
        int cnt;
 
-       cgrp = BPF_CORE_READ(p, cgroups, subsys[perf_event_cgrp_id], cgroup);
+       if (perf_subsys_id == -1) {
+#if __has_builtin(__builtin_preserve_enum_value)
+               perf_subsys_id = bpf_core_enum_value(enum cgroup_subsys_id,
+                                                    perf_event_cgrp_id);
+#else
+               perf_subsys_id = perf_event_cgrp_id;
+#endif
+       }
+       cgrp = BPF_CORE_READ(p, cgroups, subsys[perf_subsys_id], cgroup);
        level = BPF_CORE_READ(cgrp, level);
 
        for (cnt = 0; i < MAX_LEVELS; i++) {
@@ -176,7 +185,7 @@ static int bperf_cgroup_count(void)
 }
 
 // This will be attached to cgroup-switches event for each cpu
-SEC("perf_events")
+SEC("perf_event")
 int BPF_PROG(on_cgrp_switch)
 {
        return bperf_cgroup_count();
index c4ba2bc..38e3b28 100644 (file)
@@ -94,6 +94,8 @@ const volatile bool has_prev_state = false;
 const volatile bool needs_cgroup = false;
 const volatile bool uses_cgroup_v1 = false;
 
+int perf_subsys_id = -1;
+
 /*
  * Old kernel used to call it task_struct->state and now it's '__state'.
  * Use BPF CO-RE "ignored suffix rule" to deal with it like below:
@@ -119,11 +121,19 @@ static inline __u64 get_cgroup_id(struct task_struct *t)
 {
        struct cgroup *cgrp;
 
-       if (uses_cgroup_v1)
-               cgrp = BPF_CORE_READ(t, cgroups, subsys[perf_event_cgrp_id], cgroup);
-       else
-               cgrp = BPF_CORE_READ(t, cgroups, dfl_cgrp);
+       if (!uses_cgroup_v1)
+               return BPF_CORE_READ(t, cgroups, dfl_cgrp, kn, id);
+
+       if (perf_subsys_id == -1) {
+#if __has_builtin(__builtin_preserve_enum_value)
+               perf_subsys_id = bpf_core_enum_value(enum cgroup_subsys_id,
+                                                    perf_event_cgrp_id);
+#else
+               perf_subsys_id = perf_event_cgrp_id;
+#endif
+       }
 
+       cgrp = BPF_CORE_READ(t, cgroups, subsys[perf_subsys_id], cgroup);
        return BPF_CORE_READ(cgrp, kn, id);
 }
 
index 953338b..d81b545 100644 (file)
 
 #define BUILD_ID_URANDOM /* different uuid for each run */
 
-// FIXME, remove this and fix the deprecation warnings before its removed and
-// We'll break for good here...
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
 #ifdef HAVE_LIBCRYPTO_SUPPORT
 
 #define BUILD_ID_MD5
@@ -45,6 +41,7 @@
 #endif
 
 #ifdef BUILD_ID_MD5
+#include <openssl/evp.h>
 #include <openssl/md5.h>
 #endif
 #endif
@@ -142,15 +139,20 @@ gen_build_id(struct buildid_note *note,
 static void
 gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize)
 {
-       MD5_CTX context;
+       EVP_MD_CTX *mdctx;
 
        if (sizeof(note->build_id) < 16)
                errx(1, "build_id too small for MD5");
 
-       MD5_Init(&context);
-       MD5_Update(&context, &load_addr, sizeof(load_addr));
-       MD5_Update(&context, code, csize);
-       MD5_Final((unsigned char *)note->build_id, &context);
+       mdctx = EVP_MD_CTX_new();
+       if (!mdctx)
+               errx(2, "failed to create EVP_MD_CTX");
+
+       EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
+       EVP_DigestUpdate(mdctx, &load_addr, sizeof(load_addr));
+       EVP_DigestUpdate(mdctx, code, csize);
+       EVP_DigestFinal_ex(mdctx, (unsigned char *)note->build_id, NULL);
+       EVP_MD_CTX_free(mdctx);
 }
 #endif
 
@@ -251,6 +253,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
        Elf_Data *d;
        Elf_Scn *scn;
        Elf_Ehdr *ehdr;
+       Elf_Phdr *phdr;
        Elf_Shdr *shdr;
        uint64_t eh_frame_base_offset;
        char *strsym = NULL;
@@ -286,6 +289,19 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
        ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */
 
        /*
+        * setup program header
+        */
+       phdr = elf_newphdr(e, 1);
+       phdr[0].p_type = PT_LOAD;
+       phdr[0].p_offset = 0;
+       phdr[0].p_vaddr = 0;
+       phdr[0].p_paddr = 0;
+       phdr[0].p_filesz = csize;
+       phdr[0].p_memsz = csize;
+       phdr[0].p_flags = PF_X | PF_R;
+       phdr[0].p_align = 8;
+
+       /*
         * setup text section
         */
        scn = elf_newscn(e);
index ae138af..b5c9095 100644 (file)
@@ -53,8 +53,10 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
 
 #if GEN_ELF_CLASS == ELFCLASS64
 #define elf_newehdr    elf64_newehdr
+#define elf_newphdr    elf64_newphdr
 #define elf_getshdr    elf64_getshdr
 #define Elf_Ehdr       Elf64_Ehdr
+#define Elf_Phdr       Elf64_Phdr
 #define Elf_Shdr       Elf64_Shdr
 #define Elf_Sym                Elf64_Sym
 #define ELF_ST_TYPE(a) ELF64_ST_TYPE(a)
@@ -62,8 +64,10 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
 #define ELF_ST_VIS(a)  ELF64_ST_VISIBILITY(a)
 #else
 #define elf_newehdr    elf32_newehdr
+#define elf_newphdr    elf32_newphdr
 #define elf_getshdr    elf32_getshdr
 #define Elf_Ehdr       Elf32_Ehdr
+#define Elf_Phdr       Elf32_Phdr
 #define Elf_Shdr       Elf32_Shdr
 #define Elf_Sym                Elf32_Sym
 #define ELF_ST_TYPE(a) ELF32_ST_TYPE(a)
index 464475f..c93bcaf 100644 (file)
@@ -1655,6 +1655,9 @@ int metricgroup__parse_groups(const struct option *opt,
        struct evlist *perf_evlist = *(struct evlist **)opt->value;
        const struct pmu_events_table *table = pmu_events_table__find();
 
+       if (!table)
+               return -EINVAL;
+
        return parse_groups(perf_evlist, str, metric_no_group,
                            metric_no_merge, NULL, metric_events, table);
 }
index 284f8ea..7c9f915 100644 (file)
@@ -33,7 +33,8 @@ static void config_hybrid_attr(struct perf_event_attr *attr,
         * If the PMU type ID is 0, the PERF_TYPE_RAW will be applied.
         */
        attr->type = type;
-       attr->config = attr->config | ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
+       attr->config = (attr->config & PERF_HW_EVENT_MASK) |
+                       ((__u64)pmu_type << PERF_PMU_TYPE_SHIFT);
 }
 
 static int create_event_hybrid(__u32 config_type, int *idx,
@@ -48,13 +49,25 @@ static int create_event_hybrid(__u32 config_type, int *idx,
        __u64 config = attr->config;
 
        config_hybrid_attr(attr, config_type, pmu->type);
+
+       /*
+        * Some hybrid hardware cache events are only available on one CPU
+        * PMU. For example, the 'L1-dcache-load-misses' is only available
+        * on cpu_core, while the 'L1-icache-loads' is only available on
+        * cpu_atom. We need to remove "not supported" hybrid cache events.
+        */
+       if (attr->type == PERF_TYPE_HW_CACHE
+           && !is_event_supported(attr->type, attr->config))
+               return 0;
+
        evsel = parse_events__add_event_hybrid(list, idx, attr, name, metric_id,
                                               pmu, config_terms);
-       if (evsel)
+       if (evsel) {
                evsel->pmu_name = strdup(pmu->name);
-       else
+               if (!evsel->pmu_name)
+                       return -ENOMEM;
+       } else
                return -ENOMEM;
-
        attr->type = type;
        attr->config = config;
        return 0;
index f05e15a..f3b2c2a 100644 (file)
@@ -28,6 +28,7 @@
 #include "util/parse-events-hybrid.h"
 #include "util/pmu-hybrid.h"
 #include "tracepoint.h"
+#include "thread_map.h"
 
 #define MAX_NAME_LEN 100
 
@@ -157,6 +158,44 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
 #define PERF_EVENT_TYPE(config)                __PERF_EVENT_FIELD(config, TYPE)
 #define PERF_EVENT_ID(config)          __PERF_EVENT_FIELD(config, EVENT)
 
+bool is_event_supported(u8 type, u64 config)
+{
+       bool ret = true;
+       int open_return;
+       struct evsel *evsel;
+       struct perf_event_attr attr = {
+               .type = type,
+               .config = config,
+               .disabled = 1,
+       };
+       struct perf_thread_map *tmap = thread_map__new_by_tid(0);
+
+       if (tmap == NULL)
+               return false;
+
+       evsel = evsel__new(&attr);
+       if (evsel) {
+               open_return = evsel__open(evsel, NULL, tmap);
+               ret = open_return >= 0;
+
+               if (open_return == -EACCES) {
+                       /*
+                        * This happens if the paranoid value
+                        * /proc/sys/kernel/perf_event_paranoid is set to 2
+                        * Re-run with exclude_kernel set; we don't do that
+                        * by default as some ARM machines do not support it.
+                        *
+                        */
+                       evsel->core.attr.exclude_kernel = 1;
+                       ret = evsel__open(evsel, NULL, tmap) >= 0;
+               }
+               evsel__delete(evsel);
+       }
+
+       perf_thread_map__put(tmap);
+       return ret;
+}
+
 const char *event_type(int type)
 {
        switch (type) {
index 7e6a601..07df7bb 100644 (file)
@@ -19,6 +19,7 @@ struct option;
 struct perf_pmu;
 
 bool have_tracepoints(struct list_head *evlist);
+bool is_event_supported(u8 type, u64 config);
 
 const char *event_type(int type);
 
index ba1ab51..c4d5d87 100644 (file)
@@ -22,7 +22,6 @@
 #include "probe-file.h"
 #include "string2.h"
 #include "strlist.h"
-#include "thread_map.h"
 #include "tracepoint.h"
 #include "pfm.h"
 #include "pmu-hybrid.h"
@@ -239,44 +238,6 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,
        strlist__delete(sdtlist);
 }
 
-static bool is_event_supported(u8 type, unsigned int config)
-{
-       bool ret = true;
-       int open_return;
-       struct evsel *evsel;
-       struct perf_event_attr attr = {
-               .type = type,
-               .config = config,
-               .disabled = 1,
-       };
-       struct perf_thread_map *tmap = thread_map__new_by_tid(0);
-
-       if (tmap == NULL)
-               return false;
-
-       evsel = evsel__new(&attr);
-       if (evsel) {
-               open_return = evsel__open(evsel, NULL, tmap);
-               ret = open_return >= 0;
-
-               if (open_return == -EACCES) {
-                       /*
-                        * This happens if the paranoid value
-                        * /proc/sys/kernel/perf_event_paranoid is set to 2
-                        * Re-run with exclude_kernel set; we don't do that
-                        * by default as some ARM machines do not support it.
-                        *
-                        */
-                       evsel->core.attr.exclude_kernel = 1;
-                       ret = evsel__open(evsel, NULL, tmap) >= 0;
-               }
-               evsel__delete(evsel);
-       }
-
-       perf_thread_map__put(tmap);
-       return ret;
-}
-
 int print_hwcache_events(const char *event_glob, bool name_only)
 {
        unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0;
index c92326c..0f5ba28 100644 (file)
@@ -3,4 +3,4 @@ perf-$(CONFIG_LIBPYTHON) += trace-event-python.o
 
 CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default -Wno-bad-function-cast -Wno-declaration-after-statement -Wno-switch-enum
 
-CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-error=deprecated-declarations
+CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-deprecated-declarations
index 75bec32..647b7df 100644 (file)
@@ -2102,8 +2102,8 @@ static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
  * unusual.  One significant peculiarity is that the mapping (start -> pgoff)
  * is not the same for the kernel map and the modules map.  That happens because
  * the data is copied adjacently whereas the original kcore has gaps.  Finally,
- * kallsyms and modules files are compared with their copies to check that
- * modules have not been loaded or unloaded while the copies were taking place.
+ * kallsyms file is compared with its copy to check that modules have not been
+ * loaded or unloaded while the copies were taking place.
  *
  * Return: %0 on success, %-1 on failure.
  */
@@ -2166,9 +2166,6 @@ int kcore_copy(const char *from_dir, const char *to_dir)
                        goto out_extract_close;
        }
 
-       if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
-               goto out_extract_close;
-
        if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
                goto out_extract_close;
 
index 812424d..5387907 100644 (file)
@@ -367,13 +367,24 @@ static void perf_record_mmap2__read_build_id(struct perf_record_mmap2 *event,
                                             bool is_kernel)
 {
        struct build_id bid;
+       struct nsinfo *nsi;
+       struct nscookie nc;
        int rc;
 
-       if (is_kernel)
+       if (is_kernel) {
                rc = sysfs__read_build_id("/sys/kernel/notes", &bid);
-       else
-               rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1;
+               goto out;
+       }
+
+       nsi = nsinfo__new(event->pid);
+       nsinfo__mountns_enter(nsi, &nc);
 
+       rc = filename__read_build_id(event->filename, &bid) > 0 ? 0 : -1;
+
+       nsinfo__mountns_exit(&nc);
+       nsinfo__put(nsi);
+
+out:
        if (rc == 0) {
                memcpy(event->build_id, bid.data, sizeof(bid.data));
                event->build_id_size = (u8) bid.size;
index d79c335..52aa035 100644 (file)
@@ -190,7 +190,7 @@ int main(int argc, char *argv[])
        void *addr_map_capsule;
        struct stat st;
        char *log_buf;
-       int ret = 0;
+       int ret;
 
        if (getuid() != 0) {
                printf("Please run the tool as root - Exiting.\n");
index 4d1a947..01ceb98 100644 (file)
@@ -134,39 +134,6 @@ static struct ndtest_mapping region1_mapping[] = {
        },
 };
 
-static struct ndtest_mapping region2_mapping[] = {
-       {
-               .dimm = 0,
-               .position = 0,
-               .start = 0,
-               .size = DIMM_SIZE,
-       },
-};
-
-static struct ndtest_mapping region3_mapping[] = {
-       {
-               .dimm = 1,
-               .start = 0,
-               .size = DIMM_SIZE,
-       }
-};
-
-static struct ndtest_mapping region4_mapping[] = {
-       {
-               .dimm = 2,
-               .start = 0,
-               .size = DIMM_SIZE,
-       }
-};
-
-static struct ndtest_mapping region5_mapping[] = {
-       {
-               .dimm = 3,
-               .start = 0,
-               .size = DIMM_SIZE,
-       }
-};
-
 static struct ndtest_region bus0_regions[] = {
        {
                .type = ND_DEVICE_NAMESPACE_PMEM,
@@ -182,34 +149,6 @@ static struct ndtest_region bus0_regions[] = {
                .size = DIMM_SIZE * 2,
                .range_index = 2,
        },
-       {
-               .type = ND_DEVICE_NAMESPACE_BLK,
-               .num_mappings = ARRAY_SIZE(region2_mapping),
-               .mapping = region2_mapping,
-               .size = DIMM_SIZE,
-               .range_index = 3,
-       },
-       {
-               .type = ND_DEVICE_NAMESPACE_BLK,
-               .num_mappings = ARRAY_SIZE(region3_mapping),
-               .mapping = region3_mapping,
-               .size = DIMM_SIZE,
-               .range_index = 4,
-       },
-       {
-               .type = ND_DEVICE_NAMESPACE_BLK,
-               .num_mappings = ARRAY_SIZE(region4_mapping),
-               .mapping = region4_mapping,
-               .size = DIMM_SIZE,
-               .range_index = 5,
-       },
-       {
-               .type = ND_DEVICE_NAMESPACE_BLK,
-               .num_mappings = ARRAY_SIZE(region5_mapping),
-               .mapping = region5_mapping,
-               .size = DIMM_SIZE,
-               .range_index = 6,
-       },
 };
 
 static struct ndtest_mapping region6_mapping[] = {
@@ -501,21 +440,6 @@ static int ndtest_create_region(struct ndtest_priv *p,
        nd_set->altcookie = nd_set->cookie1;
        ndr_desc->nd_set = nd_set;
 
-       if (region->type == ND_DEVICE_NAMESPACE_BLK) {
-               mappings[0].start = 0;
-               mappings[0].size = DIMM_SIZE;
-               mappings[0].nvdimm = p->config->dimms[ndimm].nvdimm;
-
-               ndr_desc->mapping = &mappings[0];
-               ndr_desc->num_mappings = 1;
-               ndr_desc->num_lanes = 1;
-               ndbr_desc.enable = ndtest_blk_region_enable;
-               ndbr_desc.do_io = ndtest_blk_do_io;
-               region->region = nvdimm_blk_region_create(p->bus, ndr_desc);
-
-               goto done;
-       }
-
        for (i = 0; i < region->num_mappings; i++) {
                ndimm = region->mapping[i].dimm;
                mappings[i].start = region->mapping[i].start;
@@ -527,7 +451,6 @@ static int ndtest_create_region(struct ndtest_priv *p,
        ndr_desc->num_mappings = region->num_mappings;
        region->region = nvdimm_pmem_region_create(p->bus, ndr_desc);
 
-done:
        if (!region->region) {
                dev_err(&p->pdev.dev, "Error registering region %pR\n",
                        ndr_desc->res);
index c2064a3..1fc89b8 100644 (file)
@@ -13,6 +13,7 @@ TARGETS += damon
 TARGETS += drivers/dma-buf
 TARGETS += drivers/s390x/uvdevice
 TARGETS += drivers/net/bonding
+TARGETS += drivers/net/team
 TARGETS += efivarfs
 TARGETS += exec
 TARGETS += filesystems
index e33cab3..db98106 100644 (file)
@@ -65,3 +65,4 @@ send_signal                              # intermittently fails to receive signa
 select_reuseport                         # intermittently fails on new s390x setup
 xdp_synproxy                             # JIT does not support calling kernel function                                (kfunc)
 unpriv_bpf_disabled                      # fentry
+lru_bug                                  # prog 'printk': failed to auto-attach: -524
index 9e75442..6c03a7d 100644 (file)
        .result = VERBOSE_ACCEPT,
        .retval = -1,
 },
+{
+       "precise: mark_chain_precision for ARG_CONST_ALLOC_SIZE_OR_ZERO",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, offsetof(struct xdp_md, ingress_ifindex)),
+       BPF_LD_MAP_FD(BPF_REG_6, 0),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+       BPF_MOV64_IMM(BPF_REG_2, 1),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_4, 0, 1),
+       BPF_MOV64_IMM(BPF_REG_2, 0x1000),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ringbuf_reserve),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 42),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ringbuf_submit),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_ringbuf = { 1 },
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = BPF_F_TEST_STATE_FREQ,
+       .errstr = "invalid access to memory, mem_size=1 off=42 size=8",
+       .result = REJECT,
+},
index ab6c54b..1d86665 100644 (file)
@@ -1,6 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for net selftests
 
-TEST_PROGS := bond-break-lacpdu-tx.sh
+TEST_PROGS := bond-break-lacpdu-tx.sh \
+             dev_addr_lists.sh \
+             bond-arp-interval-causes-panic.sh
+
+TEST_FILES := lag_lib.sh
 
 include ../../../lib.mk
diff --git a/tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh b/tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh
new file mode 100755 (executable)
index 0000000..71c00bf
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# cause kernel oops in bond_rr_gen_slave_id
+DEBUG=${DEBUG:-0}
+
+set -e
+test ${DEBUG} -ne 0 && set -x
+
+finish()
+{
+       ip netns delete server || true
+       ip netns delete client || true
+       ip link del link1_1 || true
+}
+
+trap finish EXIT
+
+client_ip4=192.168.1.198
+server_ip4=192.168.1.254
+
+# setup kernel so it reboots after causing the panic
+echo 180 >/proc/sys/kernel/panic
+
+# build namespaces
+ip link add dev link1_1 type veth peer name link1_2
+
+ip netns add "server"
+ip link set dev link1_2 netns server up name eth0
+ip netns exec server ip addr add ${server_ip4}/24 dev eth0
+
+ip netns add "client"
+ip link set dev link1_1 netns client down name eth0
+ip netns exec client ip link add dev bond0 down type bond mode 1 \
+       miimon 100 all_slaves_active 1
+ip netns exec client ip link set dev eth0 down master bond0
+ip netns exec client ip link set dev bond0 up
+ip netns exec client ip addr add ${client_ip4}/24 dev bond0
+ip netns exec client ping -c 5 $server_ip4 >/dev/null
+
+ip netns exec client ip link set dev eth0 down nomaster
+ip netns exec client ip link set dev bond0 down
+ip netns exec client ip link set dev bond0 type bond mode 0 \
+       arp_interval 1000 arp_ip_target "+${server_ip4}"
+ip netns exec client ip link set dev eth0 down master bond0
+ip netns exec client ip link set dev bond0 up
+ip netns exec client ping -c 5 $server_ip4 >/dev/null
+
+exit 0
diff --git a/tools/testing/selftests/drivers/net/bonding/dev_addr_lists.sh b/tools/testing/selftests/drivers/net/bonding/dev_addr_lists.sh
new file mode 100755 (executable)
index 0000000..e6fa24e
--- /dev/null
@@ -0,0 +1,109 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test bond device handling of addr lists (dev->uc, mc)
+#
+
+ALL_TESTS="
+       bond_cleanup_mode1
+       bond_cleanup_mode4
+       bond_listen_lacpdu_multicast_case_down
+       bond_listen_lacpdu_multicast_case_up
+"
+
+REQUIRE_MZ=no
+NUM_NETIFS=0
+lib_dir=$(dirname "$0")
+source "$lib_dir"/../../../net/forwarding/lib.sh
+
+source "$lib_dir"/lag_lib.sh
+
+
+destroy()
+{
+       local ifnames=(dummy1 dummy2 bond1 mv0)
+       local ifname
+
+       for ifname in "${ifnames[@]}"; do
+               ip link del "$ifname" &>/dev/null
+       done
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       destroy
+}
+
+
+# bond driver control paths vary between modes that have a primary slave
+# (bond_uses_primary()) and others. Test both kinds of modes.
+
+bond_cleanup_mode1()
+{
+       RET=0
+
+       test_LAG_cleanup "bonding" "active-backup"
+}
+
+bond_cleanup_mode4() {
+       RET=0
+
+       test_LAG_cleanup "bonding" "802.3ad"
+}
+
+bond_listen_lacpdu_multicast()
+{
+       # Initial state of bond device, up | down
+       local init_state=$1
+       local lacpdu_mc="01:80:c2:00:00:02"
+
+       ip link add dummy1 type dummy
+       ip link add bond1 "$init_state" type bond mode 802.3ad
+       ip link set dev dummy1 master bond1
+       if [ "$init_state" = "down" ]; then
+               ip link set dev bond1 up
+       fi
+
+       grep_bridge_fdb "$lacpdu_mc" bridge fdb show brport dummy1 >/dev/null
+       check_err $? "LACPDU multicast address not present on slave (1)"
+
+       ip link set dev bond1 down
+
+       not grep_bridge_fdb "$lacpdu_mc" bridge fdb show brport dummy1 >/dev/null
+       check_err $? "LACPDU multicast address still present on slave"
+
+       ip link set dev bond1 up
+
+       grep_bridge_fdb "$lacpdu_mc" bridge fdb show brport dummy1 >/dev/null
+       check_err $? "LACPDU multicast address not present on slave (2)"
+
+       cleanup
+
+       log_test "bonding LACPDU multicast address to slave (from bond $init_state)"
+}
+
+# The LACPDU mc addr is added by different paths depending on the initial state
+# of the bond when enslaving a device. Test both cases.
+
+bond_listen_lacpdu_multicast_case_down()
+{
+       RET=0
+
+       bond_listen_lacpdu_multicast "down"
+}
+
+bond_listen_lacpdu_multicast_case_up()
+{
+       RET=0
+
+       bond_listen_lacpdu_multicast "up"
+}
+
+
+trap cleanup EXIT
+
+tests_run
+
+exit "$EXIT_STATUS"
diff --git a/tools/testing/selftests/drivers/net/bonding/lag_lib.sh b/tools/testing/selftests/drivers/net/bonding/lag_lib.sh
new file mode 100644 (file)
index 0000000..16c7fb8
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Test that a link aggregation device (bonding, team) removes the hardware
+# addresses that it adds on its underlying devices.
+test_LAG_cleanup()
+{
+       local driver=$1
+       local mode=$2
+       local ucaddr="02:00:00:12:34:56"
+       local addr6="fe80::78:9abc/64"
+       local mcaddr="33:33:ff:78:9a:bc"
+       local name
+
+       ip link add dummy1 type dummy
+       ip link add dummy2 type dummy
+       if [ "$driver" = "bonding" ]; then
+               name="bond1"
+               ip link add "$name" up type bond mode "$mode"
+               ip link set dev dummy1 master "$name"
+               ip link set dev dummy2 master "$name"
+       elif [ "$driver" = "team" ]; then
+               name="team0"
+               teamd -d -c '
+                       {
+                               "device": "'"$name"'",
+                               "runner": {
+                                       "name": "'"$mode"'"
+                               },
+                               "ports": {
+                                       "dummy1":
+                                               {},
+                                       "dummy2":
+                                               {}
+                               }
+                       }
+               '
+               ip link set dev "$name" up
+       else
+               check_err 1
+               log_test test_LAG_cleanup ": unknown driver \"$driver\""
+               return
+       fi
+
+       # Used to test dev->uc handling
+       ip link add mv0 link "$name" up address "$ucaddr" type macvlan
+       # Used to test dev->mc handling
+       ip address add "$addr6" dev "$name"
+       ip link set dev "$name" down
+       ip link del "$name"
+
+       not grep_bridge_fdb "$ucaddr" bridge fdb show >/dev/null
+       check_err $? "macvlan unicast address still present on a slave"
+
+       not grep_bridge_fdb "$mcaddr" bridge fdb show >/dev/null
+       check_err $? "IPv6 solicited-node multicast mac address still present on a slave"
+
+       cleanup
+
+       log_test "$driver cleanup mode $mode"
+}
diff --git a/tools/testing/selftests/drivers/net/team/Makefile b/tools/testing/selftests/drivers/net/team/Makefile
new file mode 100644 (file)
index 0000000..642d8df
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for net selftests
+
+TEST_PROGS := dev_addr_lists.sh
+
+include ../../../lib.mk
diff --git a/tools/testing/selftests/drivers/net/team/config b/tools/testing/selftests/drivers/net/team/config
new file mode 100644 (file)
index 0000000..265b688
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_NET_TEAM=y
+CONFIG_NET_TEAM_MODE_LOADBALANCE=y
+CONFIG_MACVLAN=y
diff --git a/tools/testing/selftests/drivers/net/team/dev_addr_lists.sh b/tools/testing/selftests/drivers/net/team/dev_addr_lists.sh
new file mode 100755 (executable)
index 0000000..debda72
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test team device handling of addr lists (dev->uc, mc)
+#
+
+ALL_TESTS="
+       team_cleanup
+"
+
+REQUIRE_MZ=no
+NUM_NETIFS=0
+lib_dir=$(dirname "$0")
+source "$lib_dir"/../../../net/forwarding/lib.sh
+
+source "$lib_dir"/../bonding/lag_lib.sh
+
+
+destroy()
+{
+       local ifnames=(dummy0 dummy1 team0 mv0)
+       local ifname
+
+       for ifname in "${ifnames[@]}"; do
+               ip link del "$ifname" &>/dev/null
+       done
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       destroy
+}
+
+
+team_cleanup()
+{
+       RET=0
+
+       test_LAG_cleanup "team" "lacp"
+}
+
+
+require_command teamd
+
+trap cleanup EXIT
+
+tests_run
+
+exit "$EXIT_STATUS"
index 4c122f1..6448cb9 100644 (file)
@@ -48,6 +48,8 @@ LIBKVM += lib/rbtree.c
 LIBKVM += lib/sparsebit.c
 LIBKVM += lib/test_util.c
 
+LIBKVM_STRING += lib/string_override.c
+
 LIBKVM_x86_64 += lib/x86_64/apic.c
 LIBKVM_x86_64 += lib/x86_64/handlers.S
 LIBKVM_x86_64 += lib/x86_64/perf_test_util.c
@@ -220,7 +222,8 @@ LIBKVM_C := $(filter %.c,$(LIBKVM))
 LIBKVM_S := $(filter %.S,$(LIBKVM))
 LIBKVM_C_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_C))
 LIBKVM_S_OBJ := $(patsubst %.S, $(OUTPUT)/%.o, $(LIBKVM_S))
-LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ)
+LIBKVM_STRING_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_STRING))
+LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ) $(LIBKVM_STRING_OBJ)
 
 EXTRA_CLEAN += $(LIBKVM_OBJS) cscope.*
 
@@ -231,6 +234,12 @@ $(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c
 $(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S
        $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
 
+# Compile the string overrides as freestanding to prevent the compiler from
+# generating self-referential code, e.g. without "freestanding" the compiler may
+# "optimize" memcmp() by invoking memcmp(), thus causing infinite recursion.
+$(LIBKVM_STRING_OBJ): $(OUTPUT)/%.o: %.c
+       $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -ffreestanding $< -o $@
+
 x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
 $(TEST_GEN_PROGS): $(LIBKVM_OBJS)
 $(TEST_GEN_PROGS_EXTENDED): $(LIBKVM_OBJS)
index 1c2749b..76c583a 100644 (file)
@@ -31,8 +31,9 @@
  * These limitations are worked around in this test by using a large enough
  * region of memory for each vCPU such that the number of translations cached in
  * the TLB and the number of pages held in pagevecs are a small fraction of the
- * overall workload. And if either of those conditions are not true this test
- * will fail rather than silently passing.
+ * overall workload. And if either of those conditions are not true (for example
+ * in nesting, where TLB size is unlimited) this test will print a warning
+ * rather than silently passing.
  */
 #include <inttypes.h>
 #include <limits.h>
@@ -172,17 +173,23 @@ static void mark_vcpu_memory_idle(struct kvm_vm *vm,
                    vcpu_idx, no_pfn, pages);
 
        /*
-        * Test that at least 90% of memory has been marked idle (the rest might
-        * not be marked idle because the pages have not yet made it to an LRU
-        * list or the translations are still cached in the TLB). 90% is
+        * Check that at least 90% of memory has been marked idle (the rest
+        * might not be marked idle because the pages have not yet made it to an
+        * LRU list or the translations are still cached in the TLB). 90% is
         * arbitrary; high enough that we ensure most memory access went through
         * access tracking but low enough as to not make the test too brittle
         * over time and across architectures.
+        *
+        * Note that when run in nested virtualization, this check will trigger
+        * much more frequently because TLB size is unlimited and since no flush
+        * happens, much more pages are cached there and guest won't see the
+        * "idle" bit cleared.
         */
-       TEST_ASSERT(still_idle < pages / 10,
-                   "vCPU%d: Too many pages still idle (%"PRIu64 " out of %"
-                   PRIu64 ").\n",
-                   vcpu_idx, still_idle, pages);
+       if (still_idle < pages / 10)
+               printf("WARNING: vCPU%d: Too many pages still idle (%" PRIu64
+                      "out of %" PRIu64 "), this will affect performance results"
+                      ".\n",
+                      vcpu_idx, still_idle, pages);
 
        close(page_idle_fd);
        close(pagemap_fd);
index 45edf45..0cbc71b 100644 (file)
@@ -754,7 +754,7 @@ void vm_install_exception_handler(struct kvm_vm *vm, int vector,
                        void (*handler)(struct ex_regs *));
 
 /* If a toddler were to say "abracadabra". */
-#define KVM_EXCEPTION_MAGIC 0xabacadabaull
+#define KVM_EXCEPTION_MAGIC 0xabacadabaULL
 
 /*
  * KVM selftest exception fixup uses registers to coordinate with the exception
@@ -786,7 +786,7 @@ void vm_install_exception_handler(struct kvm_vm *vm, int vector,
        "lea 1f(%%rip), %%r10\n\t"                              \
        "lea 2f(%%rip), %%r11\n\t"                              \
        "1: " insn "\n\t"                                       \
-       "mov $0, %[vector]\n\t"                                 \
+       "movb $0, %[vector]\n\t"                                \
        "jmp 3f\n\t"                                            \
        "2:\n\t"                                                \
        "mov  %%r9b, %[vector]\n\t"                             \
index 99fa141..790c6d1 100644 (file)
@@ -617,6 +617,7 @@ void nested_map_memslot(struct vmx_pages *vmx, struct kvm_vm *vm,
                        uint32_t memslot);
 void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm,
                            uint64_t addr, uint64_t size);
+bool kvm_vm_has_ept(struct kvm_vm *vm);
 void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
                  uint32_t eptp_memslot);
 void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm);
index 71ade61..2bd25b1 100644 (file)
@@ -22,7 +22,7 @@ static void test_dump_stack(void)
         * Build and run this command:
         *
         *      addr2line -s -e /proc/$PPID/exe -fpai {backtrace addresses} | \
-        *              grep -v test_dump_stack | cat -n 1>&2
+        *              cat -n 1>&2
         *
         * Note that the spacing is different and there's no newline.
         */
@@ -36,18 +36,24 @@ static void test_dump_stack(void)
                 n * (((sizeof(void *)) * 2) + 1) +
                 /* Null terminator: */
                 1];
-       char *c;
+       char *c = cmd;
 
        n = backtrace(stack, n);
-       c = &cmd[0];
-       c += sprintf(c, "%s", addr2line);
        /*
-        * Skip the first 3 frames: backtrace, test_dump_stack, and
-        * test_assert. We hope that backtrace isn't inlined and the other two
-        * we've declared noinline.
+        * Skip the first 2 frames, which should be test_dump_stack() and
+        * test_assert(); both of which are declared noinline.  Bail if the
+        * resulting stack trace would be empty. Otherwise, addr2line will block
+        * waiting for addresses to be passed in via stdin.
         */
+       if (n <= 2) {
+               fputs("  (stack trace empty)\n", stderr);
+               return;
+       }
+
+       c += sprintf(c, "%s", addr2line);
        for (i = 2; i < n; i++)
                c += sprintf(c, " %lx", ((unsigned long) stack[i]) - 1);
+
        c += sprintf(c, "%s", pipeline);
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-result"
diff --git a/tools/testing/selftests/kvm/lib/string_override.c b/tools/testing/selftests/kvm/lib/string_override.c
new file mode 100644 (file)
index 0000000..632398a
--- /dev/null
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <stddef.h>
+
+/*
+ * Override the "basic" built-in string helpers so that they can be used in
+ * guest code.  KVM selftests don't support dynamic loading in guest code and
+ * will jump into the weeds if the compiler decides to insert an out-of-line
+ * call via the PLT.
+ */
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+       const unsigned char *su1, *su2;
+       int res = 0;
+
+       for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) {
+               if ((res = *su1 - *su2) != 0)
+                       break;
+       }
+       return res;
+}
+
+void *memcpy(void *dest, const void *src, size_t count)
+{
+       char *tmp = dest;
+       const char *s = src;
+
+       while (count--)
+               *tmp++ = *s++;
+       return dest;
+}
+
+void *memset(void *s, int c, size_t count)
+{
+       char *xs = s;
+
+       while (count--)
+               *xs++ = c;
+       return s;
+}
index 80a568c..d21049c 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright (C) 2018, Google LLC.
  */
 
+#include <asm/msr-index.h>
+
 #include "test_util.h"
 #include "kvm_util.h"
 #include "processor.h"
@@ -542,9 +544,27 @@ void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm,
        __nested_map(vmx, vm, addr, addr, size, PG_LEVEL_1G);
 }
 
+bool kvm_vm_has_ept(struct kvm_vm *vm)
+{
+       struct kvm_vcpu *vcpu;
+       uint64_t ctrl;
+
+       vcpu = list_first_entry(&vm->vcpus, struct kvm_vcpu, list);
+       TEST_ASSERT(vcpu, "Cannot determine EPT support without vCPUs.\n");
+
+       ctrl = vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS) >> 32;
+       if (!(ctrl & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
+               return false;
+
+       ctrl = vcpu_get_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS2) >> 32;
+       return ctrl & SECONDARY_EXEC_ENABLE_EPT;
+}
+
 void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
                  uint32_t eptp_memslot)
 {
+       TEST_REQUIRE(kvm_vm_has_ept(vm));
+
        vmx->eptp = (void *)vm_vaddr_alloc_page(vm);
        vmx->eptp_hva = addr_gva2hva(vm, (uintptr_t)vmx->eptp);
        vmx->eptp_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->eptp);
index fac248a..6f88da7 100644 (file)
@@ -227,7 +227,7 @@ int main(int argc, char *argv[])
        ucall_init(vm, NULL);
 
        pthread_create(&migration_thread, NULL, migration_worker,
-                      (void *)(unsigned long)gettid());
+                      (void *)(unsigned long)syscall(SYS_gettid));
 
        for (i = 0; !done; i++) {
                vcpu_run(vcpu);
index b1905d2..e0004bd 100644 (file)
@@ -14,6 +14,9 @@
 #include "kvm_util.h"
 #include "processor.h"
 
+/* VMCALL and VMMCALL are both 3-byte opcodes. */
+#define HYPERCALL_INSN_SIZE    3
+
 static bool ud_expected;
 
 static void guest_ud_handler(struct ex_regs *regs)
@@ -22,7 +25,7 @@ static void guest_ud_handler(struct ex_regs *regs)
        GUEST_DONE();
 }
 
-extern unsigned char svm_hypercall_insn;
+extern uint8_t svm_hypercall_insn[HYPERCALL_INSN_SIZE];
 static uint64_t svm_do_sched_yield(uint8_t apic_id)
 {
        uint64_t ret;
@@ -39,7 +42,7 @@ static uint64_t svm_do_sched_yield(uint8_t apic_id)
        return ret;
 }
 
-extern unsigned char vmx_hypercall_insn;
+extern uint8_t vmx_hypercall_insn[HYPERCALL_INSN_SIZE];
 static uint64_t vmx_do_sched_yield(uint8_t apic_id)
 {
        uint64_t ret;
@@ -56,30 +59,20 @@ static uint64_t vmx_do_sched_yield(uint8_t apic_id)
        return ret;
 }
 
-static void assert_hypercall_insn(unsigned char *exp_insn, unsigned char *obs_insn)
-{
-       uint32_t exp = 0, obs = 0;
-
-       memcpy(&exp, exp_insn, sizeof(exp));
-       memcpy(&obs, obs_insn, sizeof(obs));
-
-       GUEST_ASSERT_EQ(exp, obs);
-}
-
 static void guest_main(void)
 {
-       unsigned char *native_hypercall_insn, *hypercall_insn;
+       uint8_t *native_hypercall_insn, *hypercall_insn;
        uint8_t apic_id;
 
        apic_id = GET_APIC_ID_FIELD(xapic_read_reg(APIC_ID));
 
        if (is_intel_cpu()) {
-               native_hypercall_insn = &vmx_hypercall_insn;
-               hypercall_insn = &svm_hypercall_insn;
+               native_hypercall_insn = vmx_hypercall_insn;
+               hypercall_insn = svm_hypercall_insn;
                svm_do_sched_yield(apic_id);
        } else if (is_amd_cpu()) {
-               native_hypercall_insn = &svm_hypercall_insn;
-               hypercall_insn = &vmx_hypercall_insn;
+               native_hypercall_insn = svm_hypercall_insn;
+               hypercall_insn = vmx_hypercall_insn;
                vmx_do_sched_yield(apic_id);
        } else {
                GUEST_ASSERT(0);
@@ -87,8 +80,13 @@ static void guest_main(void)
                return;
        }
 
+       /*
+        * The hypercall didn't #UD (guest_ud_handler() signals "done" if a #UD
+        * occurs).  Verify that a #UD is NOT expected and that KVM patched in
+        * the native hypercall.
+        */
        GUEST_ASSERT(!ud_expected);
-       assert_hypercall_insn(native_hypercall_insn, hypercall_insn);
+       GUEST_ASSERT(!memcmp(native_hypercall_insn, hypercall_insn, HYPERCALL_INSN_SIZE));
        GUEST_DONE();
 }
 
index 02868ac..6632bff 100644 (file)
@@ -1,6 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
+#
+# First run: make -C ../../../.. headers_install
 
 CFLAGS += -Wall -O2 $(KHDR_INCLUDES)
+LDLIBS += -lcap
+
+LOCAL_HDRS += common.h
 
 src_test := $(wildcard *_test.c)
 
@@ -8,14 +13,10 @@ TEST_GEN_PROGS := $(src_test:.c=)
 
 TEST_GEN_PROGS_EXTENDED := true
 
-OVERRIDE_TARGETS := 1
-top_srcdir := ../../../..
-include ../lib.mk
-
-khdr_dir = $(top_srcdir)/usr/include
+# Static linking for short targets:
+$(TEST_GEN_PROGS_EXTENDED): LDFLAGS += -static
 
-$(OUTPUT)/true: true.c
-       $(LINK.c) $< $(LDLIBS) -o $@ -static
+include ../lib.mk
 
-$(OUTPUT)/%_test: %_test.c $(khdr_dir)/linux/landlock.h ../kselftest_harness.h common.h
-       $(LINK.c) $< $(LDLIBS) -o $@ -lcap -I$(khdr_dir)
+# Static linking for targets with $(OUTPUT)/ prefix:
+$(TEST_GEN_PROGS_EXTENDED): LDFLAGS += -static
index 21a2ce8..45de42a 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
  * Copyright © 2020 ANSSI
- * Copyright © 2020-2021 Microsoft Corporation
+ * Copyright © 2020-2022 Microsoft Corporation
  */
 
 #define _GNU_SOURCE
@@ -371,6 +371,13 @@ TEST_F_FORK(layout1, inval)
        ASSERT_EQ(EINVAL, errno);
        path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
 
+       /* Tests with denied-by-default access right. */
+       path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_REFER;
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+                                       &path_beneath, 0));
+       ASSERT_EQ(EINVAL, errno);
+       path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_REFER;
+
        /* Test with unknown (64-bits) value. */
        path_beneath.allowed_access |= (1ULL << 60);
        ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
@@ -1826,6 +1833,20 @@ TEST_F_FORK(layout1, link)
        ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
 }
 
+static int test_rename(const char *const oldpath, const char *const newpath)
+{
+       if (rename(oldpath, newpath))
+               return errno;
+       return 0;
+}
+
+static int test_exchange(const char *const oldpath, const char *const newpath)
+{
+       if (renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, RENAME_EXCHANGE))
+               return errno;
+       return 0;
+}
+
 TEST_F_FORK(layout1, rename_file)
 {
        const struct rule rules[] = {
@@ -1867,10 +1888,10 @@ TEST_F_FORK(layout1, rename_file)
         * to a different directory (which allows file removal).
         */
        ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
-       ASSERT_EQ(EXDEV, errno);
+       ASSERT_EQ(EACCES, errno);
        ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
                                RENAME_EXCHANGE));
-       ASSERT_EQ(EXDEV, errno);
+       ASSERT_EQ(EACCES, errno);
        ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
                                RENAME_EXCHANGE));
        ASSERT_EQ(EXDEV, errno);
@@ -1894,7 +1915,7 @@ TEST_F_FORK(layout1, rename_file)
        ASSERT_EQ(EXDEV, errno);
        ASSERT_EQ(0, unlink(file1_s1d3));
        ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
-       ASSERT_EQ(EXDEV, errno);
+       ASSERT_EQ(EACCES, errno);
 
        /* Exchanges and renames files with same parent. */
        ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
@@ -2014,6 +2035,115 @@ TEST_F_FORK(layout1, reparent_refer)
        ASSERT_EQ(0, rename(dir_s1d3, dir_s2d3));
 }
 
+/* Checks renames beneath dir_s1d1. */
+static void refer_denied_by_default(struct __test_metadata *const _metadata,
+                                   const struct rule layer1[],
+                                   const int layer1_err,
+                                   const struct rule layer2[])
+{
+       int ruleset_fd;
+
+       ASSERT_EQ(0, unlink(file1_s1d2));
+
+       ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+
+       /*
+        * If the first layer handles LANDLOCK_ACCESS_FS_REFER (according to
+        * layer1_err), then it allows some different-parent renames and links.
+        */
+       ASSERT_EQ(layer1_err, test_rename(file1_s1d1, file1_s1d2));
+       if (layer1_err == 0)
+               ASSERT_EQ(layer1_err, test_rename(file1_s1d2, file1_s1d1));
+       ASSERT_EQ(layer1_err, test_exchange(file2_s1d1, file2_s1d2));
+       ASSERT_EQ(layer1_err, test_exchange(file2_s1d2, file2_s1d1));
+
+       ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+
+       /*
+        * Now, either the first or the second layer does not handle
+        * LANDLOCK_ACCESS_FS_REFER, which means that any different-parent
+        * renames and links are denied, thus making the layer handling
+        * LANDLOCK_ACCESS_FS_REFER null and void.
+        */
+       ASSERT_EQ(EXDEV, test_rename(file1_s1d1, file1_s1d2));
+       ASSERT_EQ(EXDEV, test_exchange(file2_s1d1, file2_s1d2));
+       ASSERT_EQ(EXDEV, test_exchange(file2_s1d2, file2_s1d1));
+}
+
+const struct rule layer_dir_s1d1_refer[] = {
+       {
+               .path = dir_s1d1,
+               .access = LANDLOCK_ACCESS_FS_REFER,
+       },
+       {},
+};
+
+const struct rule layer_dir_s1d1_execute[] = {
+       {
+               /* Matches a parent directory. */
+               .path = dir_s1d1,
+               .access = LANDLOCK_ACCESS_FS_EXECUTE,
+       },
+       {},
+};
+
+const struct rule layer_dir_s2d1_execute[] = {
+       {
+               /* Does not match a parent directory. */
+               .path = dir_s2d1,
+               .access = LANDLOCK_ACCESS_FS_EXECUTE,
+       },
+       {},
+};
+
+/*
+ * Tests precedence over renames: denied by default for different parent
+ * directories, *with* a rule matching a parent directory, but not directly
+ * denying access (with MAKE_REG nor REMOVE).
+ */
+TEST_F_FORK(layout1, refer_denied_by_default1)
+{
+       refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
+                               layer_dir_s1d1_execute);
+}
+
+/*
+ * Same test but this time turning around the ABI version order: the first
+ * layer does not handle LANDLOCK_ACCESS_FS_REFER.
+ */
+TEST_F_FORK(layout1, refer_denied_by_default2)
+{
+       refer_denied_by_default(_metadata, layer_dir_s1d1_execute, EXDEV,
+                               layer_dir_s1d1_refer);
+}
+
+/*
+ * Tests precedence over renames: denied by default for different parent
+ * directories, *without* a rule matching a parent directory, but not directly
+ * denying access (with MAKE_REG nor REMOVE).
+ */
+TEST_F_FORK(layout1, refer_denied_by_default3)
+{
+       refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
+                               layer_dir_s2d1_execute);
+}
+
+/*
+ * Same test but this time turning around the ABI version order: the first
+ * layer does not handle LANDLOCK_ACCESS_FS_REFER.
+ */
+TEST_F_FORK(layout1, refer_denied_by_default4)
+{
+       refer_denied_by_default(_metadata, layer_dir_s2d1_execute, EXDEV,
+                               layer_dir_s1d1_refer);
+}
+
 TEST_F_FORK(layout1, reparent_link)
 {
        const struct rule layer1[] = {
@@ -2336,11 +2466,12 @@ TEST_F_FORK(layout1, reparent_exdev_layers_rename1)
        ASSERT_EQ(EXDEV, errno);
 
        /*
-        * However, moving the file2_s1d3 file below dir_s2d3 is allowed
-        * because it cannot inherit MAKE_REG nor MAKE_DIR rights (which are
-        * dedicated to directories).
+        * Moving the file2_s1d3 file below dir_s2d3 is denied because the
+        * second layer does not handle REFER, which is always denied by
+        * default.
         */
-       ASSERT_EQ(0, rename(file2_s1d3, file1_s2d3));
+       ASSERT_EQ(-1, rename(file2_s1d3, file1_s2d3));
+       ASSERT_EQ(EXDEV, errno);
 }
 
 TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
@@ -2373,8 +2504,12 @@ TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
        ASSERT_EQ(EACCES, errno);
        ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
        ASSERT_EQ(EXDEV, errno);
-       /* Modify layout! */
-       ASSERT_EQ(0, rename(file2_s1d2, file1_s2d3));
+       /*
+        * Modifying the layout is now denied because the second layer does not
+        * handle REFER, which is always denied by default.
+        */
+       ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
+       ASSERT_EQ(EXDEV, errno);
 
        /* Without REFER source, EACCES wins over EXDEV. */
        ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
index d44c72b..9d4cb94 100644 (file)
@@ -42,6 +42,10 @@ endif
 selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
 top_srcdir = $(selfdir)/../../..
 
+ifeq ($(KHDR_INCLUDES),)
+KHDR_INCLUDES := -isystem $(top_srcdir)/usr/include
+endif
+
 # The following are built by lib.mk common compile rules.
 # TEST_CUSTOM_PROGS should be used by tests that require
 # custom build rule and prevent common build rule use.
index 0e5751a..de7d5cc 100644 (file)
@@ -1,42 +1,42 @@
 # SPDX-License-Identifier: GPL-2.0-only
+cmsg_sender
+fin_ack_lat
+gro
+hwtstamp_config
+ioam6_parser
+ip_defrag
 ipsec
+ipv6_flowlabel
+ipv6_flowlabel_mgr
 msg_zerocopy
-socket
+nettest
 psock_fanout
 psock_snd
 psock_tpacket
-stress_reuseport_listen
+reuseaddr_conflict
+reuseaddr_ports_exhausted
 reuseport_addr_any
 reuseport_bpf
 reuseport_bpf_cpu
 reuseport_bpf_numa
 reuseport_dualstack
-reuseaddr_conflict
-tcp_mmap
-udpgso
-udpgso_bench_rx
-udpgso_bench_tx
-tcp_inq
-tls
-txring_overwrite
-ip_defrag
-ipv6_flowlabel
-ipv6_flowlabel_mgr
-so_txtime
-tcp_fastopen_backup_key
-nettest
-fin_ack_lat
-reuseaddr_ports_exhausted
-hwtstamp_config
 rxtimestamp
-timestamping
-txtimestamp
+socket
 so_netns_cookie
+so_txtime
+stress_reuseport_listen
+tap
+tcp_fastopen_backup_key
+tcp_inq
+tcp_mmap
 test_unix_oob
-gro
-ioam6_parser
+timestamping
+tls
 toeplitz
 tun
-cmsg_sender
+txring_overwrite
+txtimestamp
+udpgso
+udpgso_bench_rx
+udpgso_bench_tx
 unix_connect
-tap
\ No newline at end of file
index 57e90c8..5a58b1e 100755 (executable)
@@ -28,7 +28,7 @@
 # +------------------+       +------------------+
 #
 
-ALL_TESTS="mcast_v4 mcast_v6 rpf_v4 rpf_v6"
+ALL_TESTS="mcast_v4 mcast_v6 rpf_v4 rpf_v6 unres_v4 unres_v6"
 NUM_NETIFS=6
 source lib.sh
 source tc_common.sh
@@ -406,6 +406,96 @@ rpf_v6()
        log_test "RPF IPv6"
 }
 
+unres_v4()
+{
+       # Send a multicast packet not corresponding to an installed route,
+       # causing the kernel to queue the packet for resolution and emit an
+       # IGMPMSG_NOCACHE notification. smcrouted will react to this
+       # notification by consulting its (*, G) list and installing an (S, G)
+       # route, which will be used to forward the queued packet.
+
+       RET=0
+
+       tc filter add dev $h2 ingress protocol ip pref 1 handle 1 flower \
+               dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
+       tc filter add dev $h3 ingress protocol ip pref 1 handle 1 flower \
+               dst_ip 225.1.2.3 ip_proto udp dst_port 12345 action drop
+
+       # Forwarding should fail before installing a matching (*, G).
+       $MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
+               -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
+               -A 198.51.100.2 -B 225.1.2.3 -q
+
+       tc_check_packets "dev $h2 ingress" 1 0
+       check_err $? "Multicast received on first host when should not"
+       tc_check_packets "dev $h3 ingress" 1 0
+       check_err $? "Multicast received on second host when should not"
+
+       # Create (*, G). Will not be installed in the kernel.
+       create_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3
+
+       $MZ $h1 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
+               -a 00:11:22:33:44:55 -b 01:00:5e:01:02:03 \
+               -A 198.51.100.2 -B 225.1.2.3 -q
+
+       tc_check_packets "dev $h2 ingress" 1 1
+       check_err $? "Multicast not received on first host"
+       tc_check_packets "dev $h3 ingress" 1 1
+       check_err $? "Multicast not received on second host"
+
+       delete_mcast_sg $rp1 0.0.0.0 225.1.2.3 $rp2 $rp3
+
+       tc filter del dev $h3 ingress protocol ip pref 1 handle 1 flower
+       tc filter del dev $h2 ingress protocol ip pref 1 handle 1 flower
+
+       log_test "Unresolved queue IPv4"
+}
+
+unres_v6()
+{
+       # Send a multicast packet not corresponding to an installed route,
+       # causing the kernel to queue the packet for resolution and emit an
+       # MRT6MSG_NOCACHE notification. smcrouted will react to this
+       # notification by consulting its (*, G) list and installing an (S, G)
+       # route, which will be used to forward the queued packet.
+
+       RET=0
+
+       tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 1 flower \
+               dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
+       tc filter add dev $h3 ingress protocol ipv6 pref 1 handle 1 flower \
+               dst_ip ff0e::3 ip_proto udp dst_port 12345 action drop
+
+       # Forwarding should fail before installing a matching (*, G).
+       $MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
+               -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
+               -A 2001:db8:1::2 -B ff0e::3 -q
+
+       tc_check_packets "dev $h2 ingress" 1 0
+       check_err $? "Multicast received on first host when should not"
+       tc_check_packets "dev $h3 ingress" 1 0
+       check_err $? "Multicast received on second host when should not"
+
+       # Create (*, G). Will not be installed in the kernel.
+       create_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3
+
+       $MZ $h1 -6 -c 1 -p 128 -t udp "ttl=10,sp=54321,dp=12345" \
+               -a 00:11:22:33:44:55 -b 33:33:00:00:00:03 \
+               -A 2001:db8:1::2 -B ff0e::3 -q
+
+       tc_check_packets "dev $h2 ingress" 1 1
+       check_err $? "Multicast not received on first host"
+       tc_check_packets "dev $h3 ingress" 1 1
+       check_err $? "Multicast not received on second host"
+
+       delete_mcast_sg $rp1 :: ff0e::3 $rp2 $rp3
+
+       tc filter del dev $h3 ingress protocol ipv6 pref 1 handle 1 flower
+       tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 1 flower
+
+       log_test "Unresolved queue IPv6"
+}
+
 trap cleanup EXIT
 
 setup_prepare
index e714bae..81f3117 100755 (executable)
@@ -1,3 +1,4 @@
+#!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
 # This test sends one stream of traffic from H1 through a TBF shaper, to a RED
index 9d64c56..8ce48ac 100644 (file)
@@ -47,7 +47,6 @@ enum {
        MODE_MIXED      = 3,
 };
 
-static bool cfg_flush          = false;
 static bool cfg_cork           = false;
 static int  cfg_mode           = MODE_ZC_FIXED;
 static int  cfg_nr_reqs                = 8;
@@ -166,21 +165,6 @@ static int io_uring_register_buffers(struct io_uring *ring,
        return (ret < 0) ? -errno : ret;
 }
 
-static int io_uring_register_notifications(struct io_uring *ring,
-                                          unsigned nr,
-                                          struct io_uring_notification_slot *slots)
-{
-       int ret;
-       struct io_uring_notification_register r = {
-               .nr_slots = nr,
-               .data = (unsigned long)slots,
-       };
-
-       ret = syscall(__NR_io_uring_register, ring->ring_fd,
-                     IORING_REGISTER_NOTIFIERS, &r, sizeof(r));
-       return (ret < 0) ? -errno : ret;
-}
-
 static int io_uring_mmap(int fd, struct io_uring_params *p,
                         struct io_uring_sq *sq, struct io_uring_cq *cq)
 {
@@ -297,11 +281,10 @@ static inline void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd,
 
 static inline void io_uring_prep_sendzc(struct io_uring_sqe *sqe, int sockfd,
                                        const void *buf, size_t len, int flags,
-                                       unsigned slot_idx, unsigned zc_flags)
+                                       unsigned zc_flags)
 {
        io_uring_prep_send(sqe, sockfd, buf, len, flags);
-       sqe->opcode = (__u8) IORING_OP_SENDZC_NOTIF;
-       sqe->notification_idx = slot_idx;
+       sqe->opcode = (__u8) IORING_OP_SEND_ZC;
        sqe->ioprio = zc_flags;
 }
 
@@ -374,7 +357,6 @@ static int do_setup_tx(int domain, int type, int protocol)
 
 static void do_tx(int domain, int type, int protocol)
 {
-       struct io_uring_notification_slot b[1] = {{.tag = NOTIF_TAG}};
        struct io_uring_sqe *sqe;
        struct io_uring_cqe *cqe;
        unsigned long packets = 0, bytes = 0;
@@ -390,10 +372,6 @@ static void do_tx(int domain, int type, int protocol)
        if (ret)
                error(1, ret, "io_uring: queue init");
 
-       ret = io_uring_register_notifications(&ring, 1, b);
-       if (ret)
-               error(1, ret, "io_uring: tx ctx registration");
-
        iov.iov_base = payload;
        iov.iov_len = cfg_payload_len;
 
@@ -409,9 +387,8 @@ static void do_tx(int domain, int type, int protocol)
                for (i = 0; i < cfg_nr_reqs; i++) {
                        unsigned zc_flags = 0;
                        unsigned buf_idx = 0;
-                       unsigned slot_idx = 0;
                        unsigned mode = cfg_mode;
-                       unsigned msg_flags = 0;
+                       unsigned msg_flags = MSG_WAITALL;
 
                        if (cfg_mode == MODE_MIXED)
                                mode = rand() % 3;
@@ -423,13 +400,10 @@ static void do_tx(int domain, int type, int protocol)
                                                   cfg_payload_len, msg_flags);
                                sqe->user_data = NONZC_TAG;
                        } else {
-                               if (cfg_flush) {
-                                       zc_flags |= IORING_RECVSEND_NOTIF_FLUSH;
-                                       compl_cqes++;
-                               }
+                               compl_cqes++;
                                io_uring_prep_sendzc(sqe, fd, payload,
                                                     cfg_payload_len,
-                                                    msg_flags, slot_idx, zc_flags);
+                                                    msg_flags, zc_flags);
                                if (mode == MODE_ZC_FIXED) {
                                        sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
                                        sqe->buf_index = buf_idx;
@@ -442,51 +416,57 @@ static void do_tx(int domain, int type, int protocol)
                if (ret != cfg_nr_reqs)
                        error(1, ret, "submit");
 
+               if (cfg_cork)
+                       do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
                for (i = 0; i < cfg_nr_reqs; i++) {
                        ret = io_uring_wait_cqe(&ring, &cqe);
                        if (ret)
                                error(1, ret, "wait cqe");
 
-                       if (cqe->user_data == NOTIF_TAG) {
+                       if (cqe->user_data != NONZC_TAG &&
+                           cqe->user_data != ZC_TAG)
+                               error(1, -EINVAL, "invalid cqe->user_data");
+
+                       if (cqe->flags & IORING_CQE_F_NOTIF) {
+                               if (cqe->flags & IORING_CQE_F_MORE)
+                                       error(1, -EINVAL, "invalid notif flags");
                                compl_cqes--;
                                i--;
-                       } else if (cqe->user_data != NONZC_TAG &&
-                                  cqe->user_data != ZC_TAG) {
-                               error(1, cqe->res, "invalid user_data");
-                       } else if (cqe->res <= 0 && cqe->res != -EAGAIN) {
+                       } else if (cqe->res <= 0) {
+                               if (cqe->flags & IORING_CQE_F_MORE)
+                                       error(1, cqe->res, "more with a failed send");
                                error(1, cqe->res, "send failed");
                        } else {
-                               if (cqe->res > 0) {
-                                       packets++;
-                                       bytes += cqe->res;
-                               }
-                               /* failed requests don't flush */
-                               if (cfg_flush &&
-                                   cqe->res <= 0 &&
-                                   cqe->user_data == ZC_TAG)
-                                       compl_cqes--;
+                               if (cqe->user_data == ZC_TAG &&
+                                   !(cqe->flags & IORING_CQE_F_MORE))
+                                       error(1, cqe->res, "missing more flag");
+                               packets++;
+                               bytes += cqe->res;
                        }
                        io_uring_cqe_seen(&ring);
                }
-               if (cfg_cork)
-                       do_setsockopt(fd, IPPROTO_UDP, UDP_CORK, 0);
        } while (gettimeofday_ms() < tstop);
 
-       if (close(fd))
-               error(1, errno, "close");
-
-       fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n",
-                       packets, bytes >> 20,
-                       packets / (cfg_runtime_ms / 1000),
-                       (bytes >> 20) / (cfg_runtime_ms / 1000));
-
        while (compl_cqes) {
                ret = io_uring_wait_cqe(&ring, &cqe);
                if (ret)
                        error(1, ret, "wait cqe");
+               if (cqe->flags & IORING_CQE_F_MORE)
+                       error(1, -EINVAL, "invalid notif flags");
+               if (!(cqe->flags & IORING_CQE_F_NOTIF))
+                       error(1, -EINVAL, "missing notif flag");
+
                io_uring_cqe_seen(&ring);
                compl_cqes--;
        }
+
+       fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n",
+                       packets, bytes >> 20,
+                       packets / (cfg_runtime_ms / 1000),
+                       (bytes >> 20) / (cfg_runtime_ms / 1000));
+
+       if (close(fd))
+               error(1, errno, "close");
 }
 
 static void do_test(int domain, int type, int protocol)
@@ -500,8 +480,8 @@ static void do_test(int domain, int type, int protocol)
 
 static void usage(const char *filepath)
 {
-       error(1, 0, "Usage: %s [-f] [-n<N>] [-z0] [-s<payload size>] "
-                   "(-4|-6) [-t<time s>] -D<dst_ip> udp", filepath);
+       error(1, 0, "Usage: %s (-4|-6) (udp|tcp) -D<dst_ip> [-s<payload size>] "
+                   "[-t<time s>] [-n<batch>] [-p<port>] [-m<mode>]", filepath);
 }
 
 static void parse_opts(int argc, char **argv)
@@ -519,7 +499,7 @@ static void parse_opts(int argc, char **argv)
                usage(argv[0]);
        cfg_payload_len = max_payload_len;
 
-       while ((c = getopt(argc, argv, "46D:p:s:t:n:fc:m:")) != -1) {
+       while ((c = getopt(argc, argv, "46D:p:s:t:n:c:m:")) != -1) {
                switch (c) {
                case '4':
                        if (cfg_family != PF_UNSPEC)
@@ -548,9 +528,6 @@ static void parse_opts(int argc, char **argv)
                case 'n':
                        cfg_nr_reqs = strtoul(optarg, NULL, 0);
                        break;
-               case 'f':
-                       cfg_flush = 1;
-                       break;
                case 'c':
                        cfg_cork = strtol(optarg, NULL, 0);
                        break;
@@ -583,8 +560,6 @@ static void parse_opts(int argc, char **argv)
 
        if (cfg_payload_len > max_payload_len)
                error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
-       if (cfg_mode == MODE_NONZC && cfg_flush)
-               error(1, 0, "-f: only zerocopy modes support notifications");
        if (optind != argc - 1)
                usage(argv[0]);
 }
index 6a65e44..32aa6e9 100755 (executable)
@@ -25,15 +25,11 @@ readonly path_sysctl_mem="net.core.optmem_max"
 # No arguments: automated test
 if [[ "$#" -eq "0" ]]; then
        IPs=( "4" "6" )
-       protocols=( "tcp" "udp" )
 
        for IP in "${IPs[@]}"; do
-               for proto in "${protocols[@]}"; do
-                       for mode in $(seq 1 3); do
-                               $0 "$IP" "$proto" -m "$mode" -t 1 -n 32
-                               $0 "$IP" "$proto" -m "$mode" -t 1 -n 32 -f
-                               $0 "$IP" "$proto" -m "$mode" -t 1 -n 32 -c -f
-                       done
+               for mode in $(seq 1 3); do
+                       $0 "$IP" udp -m "$mode" -t 1 -n 32
+                       $0 "$IP" tcp -m "$mode" -t 1 -n 32
                done
        done
 
index 072d709..65aea27 100644 (file)
@@ -328,7 +328,7 @@ static void test_extra_filter(const struct test_params p)
        if (bind(fd1, addr, sockaddr_size()))
                error(1, errno, "failed to bind recv socket 1");
 
-       if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE)
+       if (!bind(fd2, addr, sockaddr_size()) || errno != EADDRINUSE)
                error(1, errno, "bind socket 2 should fail with EADDRINUSE");
 
        free(addr);
index a699187..e908009 100755 (executable)
@@ -91,7 +91,7 @@ src
 start          1
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    3
@@ -116,7 +116,7 @@ src
 start          10
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp6
 
 race_repeat    3
@@ -141,7 +141,7 @@ src
 start          1
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    0
@@ -163,7 +163,7 @@ src         mac
 start          10
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp6
 
 race_repeat    0
@@ -185,7 +185,7 @@ src         mac proto
 start          10
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp6
 
 race_repeat    0
@@ -207,7 +207,7 @@ src         addr4
 start          1
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    3
@@ -227,7 +227,7 @@ src         addr6 port
 start          10
 count          5
 src_delta      2000
-tools          sendip nc
+tools          sendip socat nc
 proto          udp6
 
 race_repeat    3
@@ -247,7 +247,7 @@ src         mac proto addr4
 start          1
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    0
@@ -264,7 +264,7 @@ src         mac
 start          1
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    0
@@ -286,7 +286,7 @@ src         mac addr4
 start          1
 count          5
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    0
@@ -337,7 +337,7 @@ src         addr4
 start          1
 count          5
 src_delta      2000
-tools          sendip nc
+tools          sendip socat nc
 proto          udp
 
 race_repeat    3
@@ -363,7 +363,7 @@ src         mac
 start          1
 count          1
 src_delta      2000
-tools          sendip nc bash
+tools          sendip socat nc bash
 proto          udp
 
 race_repeat    0
@@ -541,6 +541,24 @@ setup_send_udp() {
                        dst_port=
                        src_addr4=
                }
+       elif command -v socat -v >/dev/null; then
+               send_udp() {
+                       if [ -n "${src_addr4}" ]; then
+                               B ip addr add "${src_addr4}" dev veth_b
+                               __socatbind=",bind=${src_addr4}"
+                               if [ -n "${src_port}" ];then
+                                       __socatbind="${__socatbind}:${src_port}"
+                               fi
+                       fi
+
+                       ip addr add "${dst_addr4}" dev veth_a 2>/dev/null
+                       [ -z "${dst_port}" ] && dst_port=12345
+
+                       echo "test4" | B socat -t 0.01 STDIN UDP4-DATAGRAM:${dst_addr4}:${dst_port}"${__socatbind}"
+
+                       src_addr4=
+                       src_port=
+               }
        elif command -v nc >/dev/null; then
                if nc -u -w0 1.1.1.1 1 2>/dev/null; then
                        # OpenBSD netcat
@@ -606,6 +624,29 @@ setup_send_udp6() {
                        dst_port=
                        src_addr6=
                }
+       elif command -v socat -v >/dev/null; then
+               send_udp6() {
+                       ip -6 addr add "${dst_addr6}" dev veth_a nodad \
+                               2>/dev/null
+
+                       __socatbind6=
+
+                       if [ -n "${src_addr6}" ]; then
+                               if [ -n "${src_addr6} != "${src_addr6_added} ]; then
+                                       B ip addr add "${src_addr6}" dev veth_b nodad
+
+                                       src_addr6_added=${src_addr6}
+                               fi
+
+                               __socatbind6=",bind=[${src_addr6}]"
+
+                               if [ -n "${src_port}" ] ;then
+                                       __socatbind6="${__socatbind6}:${src_port}"
+                               fi
+                       fi
+
+                       echo "test6" | B socat -t 0.01 STDIN UDP6-DATAGRAM:[${dst_addr6}]:${dst_port}"${__socatbind6}"
+               }
        elif command -v nc >/dev/null && nc -u -w0 1.1.1.1 1 2>/dev/null; then
                # GNU netcat might not work with IPv6, try next tool
                send_udp6() {
index bf6b962..faa7778 100755 (executable)
@@ -102,26 +102,42 @@ check_for_helper()
 
        ip netns exec ${netns} conntrack -L -f $family -p tcp --dport $port 2> /dev/null |grep -q 'helper=ftp'
        if [ $? -ne 0 ] ; then
-               echo "FAIL: ${netns} did not show attached helper $message" 1>&2
-               ret=1
+               if [ $autoassign -eq 0 ] ;then
+                       echo "FAIL: ${netns} did not show attached helper $message" 1>&2
+                       ret=1
+               else
+                       echo "PASS: ${netns} did not show attached helper $message" 1>&2
+               fi
+       else
+               if [ $autoassign -eq 0 ] ;then
+                       echo "PASS: ${netns} connection on port $port has ftp helper attached" 1>&2
+               else
+                       echo "FAIL: ${netns} connection on port $port has ftp helper attached" 1>&2
+                       ret=1
+               fi
        fi
 
-       echo "PASS: ${netns} connection on port $port has ftp helper attached" 1>&2
        return 0
 }
 
 test_helper()
 {
        local port=$1
-       local msg=$2
+       local autoassign=$2
+
+       if [ $autoassign -eq 0 ] ;then
+               msg="set via ruleset"
+       else
+               msg="auto-assign"
+       fi
 
        sleep 3 | ip netns exec ${ns2} nc -w 2 -l -p $port > /dev/null &
 
        sleep 1 | ip netns exec ${ns1} nc -w 2 10.0.1.2 $port > /dev/null &
        sleep 1
 
-       check_for_helper "$ns1" "ip $msg" $port
-       check_for_helper "$ns2" "ip $msg" $port
+       check_for_helper "$ns1" "ip $msg" $port $autoassign
+       check_for_helper "$ns2" "ip $msg" $port $autoassign
 
        wait
 
@@ -173,9 +189,9 @@ if [ $? -ne 0 ];then
        fi
 fi
 
-test_helper 2121 "set via ruleset"
-ip netns exec ${ns1} sysctl -q 'net.netfilter.nf_conntrack_helper=1'
-ip netns exec ${ns2} sysctl -q 'net.netfilter.nf_conntrack_helper=1'
-test_helper 21 "auto-assign"
+test_helper 2121 0
+ip netns exec ${ns1} sysctl -qe 'net.netfilter.nf_conntrack_helper=1'
+ip netns exec ${ns2} sysctl -qe 'net.netfilter.nf_conntrack_helper=1'
+test_helper 21 1
 
 exit $ret
diff --git a/tools/testing/selftests/nolibc/.gitignore b/tools/testing/selftests/nolibc/.gitignore
new file mode 100644 (file)
index 0000000..4696df5
--- /dev/null
@@ -0,0 +1,4 @@
+/initramfs/
+/nolibc-test
+/run.out
+/sysroot/
diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile
new file mode 100644 (file)
index 0000000..69ea659
--- /dev/null
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for nolibc tests
+include ../../../scripts/Makefile.include
+
+# we're in ".../tools/testing/selftests/nolibc"
+ifeq ($(srctree),)
+srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR)))
+endif
+
+ifeq ($(ARCH),)
+include $(srctree)/scripts/subarch.include
+ARCH = $(SUBARCH)
+endif
+
+# kernel image names by architecture
+IMAGE_i386    = 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         = $(IMAGE_$(ARCH))
+IMAGE_NAME    = $(notdir $(IMAGE))
+
+# default kernel configurations that appear to be usable
+DEFCONFIG_i386    = defconfig
+DEFCONFIG_x86     = defconfig
+DEFCONFIG_arm64   = defconfig
+DEFCONFIG_arm     = multi_v7_defconfig
+DEFCONFIG_mips    = malta_defconfig
+DEFCONFIG_riscv   = 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     = x86_64
+QEMU_ARCH_arm64   = aarch64
+QEMU_ARCH_arm     = arm
+QEMU_ARCH_mips    = mipsel  # works with malta_defconfig
+QEMU_ARCH_riscv   = riscv64
+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     = -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         = $(QEMU_ARGS_$(ARCH))
+
+# OUTPUT is only set when run from the main makefile, otherwise
+# it defaults to this nolibc directory.
+OUTPUT ?= $(CURDIR)/
+
+ifeq ($(V),1)
+Q=
+else
+Q=@
+endif
+
+CFLAGS  ?= -Os -fno-ident -fno-asynchronous-unwind-tables
+LDFLAGS := -s
+
+help:
+       @echo "Supported targets under selftests/nolibc:"
+       @echo "  all          call the \"run\" target below"
+       @echo "  help         this help"
+       @echo "  sysroot      create the nolibc sysroot here (uses \$$ARCH)"
+       @echo "  nolibc-test  build the executable (uses \$$CC and \$$CROSS_COMPILE)"
+       @echo "  initramfs    prepare the initramfs with nolibc-test"
+       @echo "  defconfig    create a fresh new default config (uses \$$ARCH)"
+       @echo "  kernel       (re)build the kernel with the initramfs (uses \$$ARCH)"
+       @echo "  run          runs the kernel in QEMU after building it (uses \$$ARCH, \$$TEST)"
+       @echo "  rerun        runs a previously prebuilt kernel in QEMU (uses \$$ARCH, \$$TEST)"
+       @echo "  clean        clean the sysroot, initramfs, build and output files"
+       @echo ""
+       @echo "The output file is \"run.out\". Test ranges may be passed using \$$TEST."
+       @echo ""
+       @echo "Currently using the following variables:"
+       @echo "  ARCH          = $(ARCH)"
+       @echo "  CROSS_COMPILE = $(CROSS_COMPILE)"
+       @echo "  CC            = $(CC)"
+       @echo "  OUTPUT        = $(OUTPUT)"
+       @echo "  TEST          = $(TEST)"
+       @echo "  QEMU_ARCH     = $(if $(QEMU_ARCH),$(QEMU_ARCH),UNKNOWN_ARCH) [determined from \$$ARCH]"
+       @echo "  IMAGE_NAME    = $(if $(IMAGE_NAME),$(IMAGE_NAME),UNKNOWN_ARCH) [determined from \$$ARCH]"
+       @echo ""
+
+all: run
+
+sysroot: sysroot/$(ARCH)/include
+
+sysroot/$(ARCH)/include:
+       $(QUIET_MKDIR)mkdir -p sysroot
+       $(Q)$(MAKE) -C ../../../include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone
+       $(Q)mv sysroot/sysroot sysroot/$(ARCH)
+
+nolibc-test: nolibc-test.c sysroot/$(ARCH)/include
+       $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
+         -nostdlib -static -Isysroot/$(ARCH)/include $< -lgcc
+
+initramfs: nolibc-test
+       $(QUIET_MKDIR)mkdir -p initramfs
+       $(call QUIET_INSTALL, initramfs/init)
+       $(Q)cp nolibc-test initramfs/init
+
+defconfig:
+       $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) mrproper $(DEFCONFIG) prepare
+
+kernel: initramfs
+       $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs
+
+# run the tests after building the kernel
+run: kernel
+       $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
+       $(Q)grep -w FAIL "$(CURDIR)/run.out" && echo "See all results in $(CURDIR)/run.out" || echo "$$(grep -c ^[0-9].*OK $(CURDIR)/run.out) test(s) passed."
+
+# re-run the tests from an existing kernel
+rerun:
+       $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
+       $(Q)grep -w FAIL "$(CURDIR)/run.out" && echo "See all results in $(CURDIR)/run.out" || echo "$$(grep -c ^[0-9].*OK $(CURDIR)/run.out) test(s) passed."
+
+clean:
+       $(call QUIET_CLEAN, sysroot)
+       $(Q)rm -rf sysroot
+       $(call QUIET_CLEAN, nolibc-test)
+       $(Q)rm -f nolibc-test
+       $(call QUIET_CLEAN, initramfs)
+       $(Q)rm -rf initramfs
+       $(call QUIET_CLEAN, run.out)
+       $(Q)rm -rf run.out
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
new file mode 100644 (file)
index 0000000..78bced9
--- /dev/null
@@ -0,0 +1,757 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+
+/* platform-specific include files coming from the compiler */
+#include <limits.h>
+
+/* libc-specific include files
+ * The program may be built in 3 ways:
+ *   $(CC) -nostdlib -include /path/to/nolibc.h => NOLIBC already defined
+ *   $(CC) -nostdlib -I/path/to/nolibc/sysroot  => _NOLIBC_* guards are present
+ *   $(CC) with default libc                    => NOLIBC* never defined
+ */
+#ifndef NOLIBC
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _NOLIBC_STDIO_H
+/* standard libcs need more includes */
+#include <linux/reboot.h>
+#include <sys/io.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/sysmacros.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <unistd.h>
+#endif
+#endif
+
+/* will be used by nolibc by getenv() */
+char **environ;
+
+/* definition of a series of tests */
+struct test {
+       const char *name;              // test name
+       int (*func)(int min, int max); // handler
+};
+
+#ifndef _NOLIBC_STDLIB_H
+char *itoa(int i)
+{
+       static char buf[12];
+       int ret;
+
+       ret = snprintf(buf, sizeof(buf), "%d", i);
+       return (ret >= 0 && ret < sizeof(buf)) ? buf : "#err";
+}
+#endif
+
+#define CASE_ERR(err) \
+       case err: return #err
+
+/* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0,
+ * or the decimal value for less common ones.
+ */
+const char *errorname(int err)
+{
+       switch (err) {
+       case 0: return "SUCCESS";
+       CASE_ERR(EPERM);
+       CASE_ERR(ENOENT);
+       CASE_ERR(ESRCH);
+       CASE_ERR(EINTR);
+       CASE_ERR(EIO);
+       CASE_ERR(ENXIO);
+       CASE_ERR(E2BIG);
+       CASE_ERR(ENOEXEC);
+       CASE_ERR(EBADF);
+       CASE_ERR(ECHILD);
+       CASE_ERR(EAGAIN);
+       CASE_ERR(ENOMEM);
+       CASE_ERR(EACCES);
+       CASE_ERR(EFAULT);
+       CASE_ERR(ENOTBLK);
+       CASE_ERR(EBUSY);
+       CASE_ERR(EEXIST);
+       CASE_ERR(EXDEV);
+       CASE_ERR(ENODEV);
+       CASE_ERR(ENOTDIR);
+       CASE_ERR(EISDIR);
+       CASE_ERR(EINVAL);
+       CASE_ERR(ENFILE);
+       CASE_ERR(EMFILE);
+       CASE_ERR(ENOTTY);
+       CASE_ERR(ETXTBSY);
+       CASE_ERR(EFBIG);
+       CASE_ERR(ENOSPC);
+       CASE_ERR(ESPIPE);
+       CASE_ERR(EROFS);
+       CASE_ERR(EMLINK);
+       CASE_ERR(EPIPE);
+       CASE_ERR(EDOM);
+       CASE_ERR(ERANGE);
+       CASE_ERR(ENOSYS);
+       default:
+               return itoa(err);
+       }
+}
+
+static int pad_spc(int llen, int cnt, const char *fmt, ...)
+{
+       va_list args;
+       int len;
+       int ret;
+
+       for (len = 0; len < cnt - llen; len++)
+               putchar(' ');
+
+       va_start(args, fmt);
+       ret = vfprintf(stdout, fmt, args);
+       va_end(args);
+       return ret < 0 ? ret : ret + len;
+}
+
+/* The tests below are intended to be used by the macroes, which evaluate
+ * expression <expr>, print the status to stdout, and update the "ret"
+ * variable to count failures. The functions themselves return the number
+ * of failures, thus either 0 or 1.
+ */
+
+#define EXPECT_ZR(cond, expr)                          \
+       do { if (!cond) pad_spc(llen, 40, "[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");
+       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)
+
+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");
+       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)
+
+static int expect_eq(int expr, int llen, int val)
+{
+       int ret = !(expr == val);
+
+       llen += printf(" = %d ", expr);
+       pad_spc(llen, 40, 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)
+
+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");
+       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)
+
+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");
+       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)
+
+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");
+       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)
+
+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");
+       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)
+
+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");
+       return ret;
+}
+
+
+#define EXPECT_SYSZR(cond, expr)                               \
+       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0)
+
+static int expect_syszr(int expr, int llen)
+{
+       int ret = 0;
+
+       if (expr) {
+               ret = 1;
+               llen += printf(" = %d %s ", expr, errorname(errno));
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += printf(" = %d ", expr);
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_syseq(int expr, int llen, int val)
+{
+       int ret = 0;
+
+       if (expr != val) {
+               ret = 1;
+               llen += printf(" = %d %s ", expr, errorname(errno));
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += printf(" = %d ", expr);
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_sysne(int expr, int llen, int val)
+{
+       int ret = 0;
+
+       if (expr == val) {
+               ret = 1;
+               llen += printf(" = %d %s ", expr, errorname(errno));
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += printf(" = %d ", expr);
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_syserr(int expr, int expret, int experr, int llen)
+{
+       int ret = 0;
+       int _errno = errno;
+
+       llen += printf(" = %d %s ", expr, errorname(_errno));
+       if (expr != expret || _errno != experr) {
+               ret = 1;
+               llen += printf(" != (%d %s) ", expret, errorname(experr));
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_ptrzr(const void *expr, int llen)
+{
+       int ret = 0;
+
+       llen += printf(" = <%p> ", expr);
+       if (expr) {
+               ret = 1;
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_ptrnz(const void *expr, int llen)
+{
+       int ret = 0;
+
+       llen += printf(" = <%p> ", expr);
+       if (!expr) {
+               ret = 1;
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_strzr(const char *expr, int llen)
+{
+       int ret = 0;
+
+       llen += printf(" = <%s> ", expr);
+       if (expr) {
+               ret = 1;
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_strnz(const char *expr, int llen)
+{
+       int ret = 0;
+
+       llen += printf(" = <%s> ", expr);
+       if (!expr) {
+               ret = 1;
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_streq(const char *expr, int llen, const char *cmp)
+{
+       int ret = 0;
+
+       llen += printf(" = <%s> ", expr);
+       if (strcmp(expr, cmp) != 0) {
+               ret = 1;
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [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)
+
+static int expect_strne(const char *expr, int llen, const char *cmp)
+{
+       int ret = 0;
+
+       llen += printf(" = <%s> ", expr);
+       if (strcmp(expr, cmp) == 0) {
+               ret = 1;
+               llen += pad_spc(llen, 40, "[FAIL]\n");
+       } else {
+               llen += pad_spc(llen, 40, " [OK]\n");
+       }
+       return ret;
+}
+
+
+/* declare tests based on line numbers. There must be exactly one test per line. */
+#define CASE_TEST(name) \
+       case __LINE__: llen += printf("%d %s", test, #name);
+
+
+/* used by some syscall tests below */
+int test_getdents64(const char *dir)
+{
+       char buffer[4096];
+       int fd, ret;
+       int err;
+
+       ret = fd = open(dir, O_RDONLY | O_DIRECTORY, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = getdents64(fd, (void *)buffer, sizeof(buffer));
+       err = errno;
+       close(fd);
+
+       errno = err;
+       return ret;
+}
+
+/* Run syscall tests between IDs <min> and <max>.
+ * Return 0 on success, non-zero on failure.
+ */
+int run_syscall(int min, int max)
+{
+       struct stat stat_buf;
+       int proc;
+       int test;
+       int tmp;
+       int ret = 0;
+       void *p1, *p2;
+
+       /* <proc> indicates whether or not /proc is mounted */
+       proc = stat("/proc", &stat_buf) == 0;
+
+       for (test = min; test >= 0 && test <= max; test++) {
+               int llen = 0; // line length
+
+               /* avoid leaving empty lines below, this will insert holes into
+                * test numbers.
+                */
+               switch (test + __LINE__ + 1) {
+               CASE_TEST(getpid);            EXPECT_SYSNE(1, getpid(), -1); break;
+               CASE_TEST(getppid);           EXPECT_SYSNE(1, getppid(), -1); break;
+#ifdef NOLIBC
+               CASE_TEST(gettid);            EXPECT_SYSNE(1, gettid(), -1); break;
+#endif
+               CASE_TEST(getpgid_self);      EXPECT_SYSNE(1, getpgid(0), -1); break;
+               CASE_TEST(getpgid_bad);       EXPECT_SYSER(1, getpgid(-1), -1, ESRCH); break;
+               CASE_TEST(kill_0);            EXPECT_SYSZR(1, kill(getpid(), 0)); break;
+               CASE_TEST(kill_CONT);         EXPECT_SYSZR(1, kill(getpid(), 0)); break;
+               CASE_TEST(kill_BADPID);       EXPECT_SYSER(1, kill(INT_MAX, 0), -1, ESRCH); break;
+               CASE_TEST(sbrk);              if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break;
+               CASE_TEST(brk);               EXPECT_SYSZR(1, brk(sbrk(0))); break;
+               CASE_TEST(chdir_root);        EXPECT_SYSZR(1, chdir("/")); break;
+               CASE_TEST(chdir_dot);         EXPECT_SYSZR(1, chdir(".")); break;
+               CASE_TEST(chdir_blah);        EXPECT_SYSER(1, chdir("/blah"), -1, ENOENT); break;
+               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_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;
+               CASE_TEST(close_dup);         EXPECT_SYSZR(1, close(dup(0))); break;
+               CASE_TEST(dup_0);             tmp = dup(0);  EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
+               CASE_TEST(dup_m1);            tmp = dup(-1); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
+               CASE_TEST(dup2_0);            tmp = dup2(0, 100);  EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
+               CASE_TEST(dup2_m1);           tmp = dup2(-1, 100); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
+               CASE_TEST(dup3_0);            tmp = dup3(0, 100, 0);  EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
+               CASE_TEST(dup3_m1);           tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
+               CASE_TEST(execve_root);       EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break;
+               CASE_TEST(getdents64_root);   EXPECT_SYSNE(1, test_getdents64("/"), -1); break;
+               CASE_TEST(getdents64_null);   EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break;
+               CASE_TEST(gettimeofday_null); EXPECT_SYSZR(1, gettimeofday(NULL, NULL)); break;
+#ifdef NOLIBC
+               CASE_TEST(gettimeofday_bad1); EXPECT_SYSER(1, gettimeofday((void *)1, NULL), -1, EFAULT); break;
+               CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break;
+               CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break;
+#endif
+               CASE_TEST(ioctl_tiocinq);     EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
+               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_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;
+               CASE_TEST(mkdir_root);        EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break;
+               CASE_TEST(open_tty);          EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break;
+               CASE_TEST(open_blah);         EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break;
+               CASE_TEST(poll_null);         EXPECT_SYSZR(1, poll(NULL, 0, 0)); break;
+               CASE_TEST(poll_stdout);       EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break;
+               CASE_TEST(poll_fault);        EXPECT_SYSER(1, poll((void *)1, 1, 0), -1, EFAULT); break;
+               CASE_TEST(read_badf);         EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break;
+               CASE_TEST(sched_yield);       EXPECT_SYSZR(1, sched_yield()); break;
+               CASE_TEST(select_null);       EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break;
+               CASE_TEST(select_stdout);     EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break;
+               CASE_TEST(select_fault);      EXPECT_SYSER(1, select(1, (void *)1, NULL, NULL, 0), -1, EFAULT); break;
+               CASE_TEST(stat_blah);         EXPECT_SYSER(1, stat("/proc/self/blah", &stat_buf), -1, ENOENT); break;
+               CASE_TEST(stat_fault);        EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break;
+               CASE_TEST(symlink_root);      EXPECT_SYSER(1, symlink("/", "/"), -1, EEXIST); break;
+               CASE_TEST(unlink_root);       EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break;
+               CASE_TEST(unlink_blah);       EXPECT_SYSER(1, unlink("/proc/self/blah"), -1, ENOENT); break;
+               CASE_TEST(wait_child);        EXPECT_SYSER(1, wait(&tmp), -1, ECHILD); break;
+               CASE_TEST(waitpid_min);       EXPECT_SYSER(1, waitpid(INT_MIN, &tmp, WNOHANG), -1, ESRCH); break;
+               CASE_TEST(waitpid_child);     EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break;
+               CASE_TEST(write_badf);        EXPECT_SYSER(1, write(-1, &tmp, 1), -1, EBADF); break;
+               CASE_TEST(write_zero);        EXPECT_SYSZR(1, write(1, &tmp, 0)); break;
+               case __LINE__:
+                       return ret; /* must be last */
+               /* note: do not set any defaults so as to permit holes above */
+               }
+       }
+       return ret;
+}
+
+int run_stdlib(int min, int max)
+{
+       int test;
+       int tmp;
+       int ret = 0;
+       void *p1, *p2;
+
+       for (test = min; test >= 0 && test <= max; test++) {
+               int llen = 0; // line length
+
+               /* avoid leaving empty lines below, this will insert holes into
+                * test numbers.
+                */
+               switch (test + __LINE__ + 1) {
+               CASE_TEST(getenv_TERM);        EXPECT_STRNZ(1, getenv("TERM")); break;
+               CASE_TEST(getenv_blah);        EXPECT_STRZR(1, getenv("blah")); break;
+               CASE_TEST(setcmp_blah_blah);   EXPECT_EQ(1, strcmp("blah", "blah"), 0); break;
+               CASE_TEST(setcmp_blah_blah2);  EXPECT_NE(1, strcmp("blah", "blah2"), 0); break;
+               CASE_TEST(setncmp_blah_blah);  EXPECT_EQ(1, strncmp("blah", "blah", 10), 0); break;
+               CASE_TEST(setncmp_blah_blah4); EXPECT_EQ(1, strncmp("blah", "blah4", 4), 0); break;
+               CASE_TEST(setncmp_blah_blah5); EXPECT_NE(1, strncmp("blah", "blah5", 5), 0); break;
+               CASE_TEST(setncmp_blah_blah6); EXPECT_NE(1, strncmp("blah", "blah6", 6), 0); break;
+               CASE_TEST(strchr_foobar_o);    EXPECT_STREQ(1, strchr("foobar", 'o'), "oobar"); break;
+               CASE_TEST(strchr_foobar_z);    EXPECT_STRZR(1, strchr("foobar", 'z')); break;
+               CASE_TEST(strrchr_foobar_o);   EXPECT_STREQ(1, strrchr("foobar", 'o'), "obar"); break;
+               CASE_TEST(strrchr_foobar_z);   EXPECT_STRZR(1, strrchr("foobar", 'z')); break;
+               case __LINE__:
+                       return ret; /* must be last */
+               /* note: do not set any defaults so as to permit holes above */
+               }
+       }
+       return ret;
+}
+
+/* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
+int prepare(void)
+{
+       struct stat stat_buf;
+
+       /* It's possible that /dev doesn't even exist or was not mounted, so
+        * we'll try to create it, mount it, or create minimal entries into it.
+        * We want at least /dev/null and /dev/console.
+        */
+       if (stat("/dev/.", &stat_buf) == 0 || mkdir("/dev", 0755) == 0) {
+               if (stat("/dev/console", &stat_buf) != 0 ||
+                   stat("/dev/null", &stat_buf) != 0) {
+                       /* try devtmpfs first, otherwise fall back to manual creation */
+                       if (mount("/dev", "/dev", "devtmpfs", 0, 0) != 0) {
+                               mknod("/dev/console", 0600 | S_IFCHR, makedev(5, 1));
+                               mknod("/dev/null",    0666 | S_IFCHR, makedev(1, 3));
+                       }
+               }
+       }
+
+       /* If no /dev/console was found before calling init, stdio is closed so
+        * we need to reopen it from /dev/console. If it failed above, it will
+        * still fail here and we cannot emit a message anyway.
+        */
+       if (close(dup(1)) == -1) {
+               int fd = open("/dev/console", O_RDWR);
+
+               if (fd >= 0) {
+                       if (fd != 0)
+                               dup2(fd, 0);
+                       if (fd != 1)
+                               dup2(fd, 1);
+                       if (fd != 2)
+                               dup2(fd, 2);
+                       if (fd > 2)
+                               close(fd);
+                       puts("\nSuccessfully reopened /dev/console.");
+               }
+       }
+
+       /* try to mount /proc if not mounted. Silently fail otherwise */
+       if (stat("/proc/.", &stat_buf) == 0 || mkdir("/proc", 0755) == 0) {
+               if (stat("/proc/self", &stat_buf) != 0)
+                       mount("/proc", "/proc", "proc", 0, 0);
+       }
+
+       return 0;
+}
+
+/* This is the definition of known test names, with their functions */
+static struct test test_names[] = {
+       /* add new tests here */
+       { .name = "syscall",   .func = run_syscall  },
+       { .name = "stdlib",    .func = run_stdlib   },
+       { 0 }
+};
+
+int main(int argc, char **argv, char **envp)
+{
+       int min = 0;
+       int max = __INT_MAX__;
+       int ret = 0;
+       int err;
+       int idx;
+       char *test;
+
+       environ = envp;
+
+       /* when called as init, it's possible that no console was opened, for
+        * example if no /dev file system was provided. We'll check that fd#1
+        * was opened, and if not we'll attempt to create and open /dev/console
+        * and /dev/null that we'll use for later tests.
+        */
+       if (getpid() == 1)
+               prepare();
+
+       /* the definition of a series of tests comes from either argv[1] or the
+        * "NOLIBC_TEST" environment variable. It's made of a comma-delimited
+        * series of test names and optional ranges:
+        *    syscall:5-15[:.*],stdlib:8-10
+        */
+       test = argv[1];
+       if (!test)
+               test = getenv("NOLIBC_TEST");
+
+       if (test) {
+               char *comma, *colon, *dash, *value;
+
+               do {
+                       comma = strchr(test, ',');
+                       if (comma)
+                               *(comma++) = '\0';
+
+                       colon = strchr(test, ':');
+                       if (colon)
+                               *(colon++) = '\0';
+
+                       for (idx = 0; test_names[idx].name; idx++) {
+                               if (strcmp(test, test_names[idx].name) == 0)
+                                       break;
+                       }
+
+                       if (test_names[idx].name) {
+                               /* The test was named, it will be called at least
+                                * once. We may have an optional range at <colon>
+                                * here, which defaults to the full range.
+                                */
+                               do {
+                                       min = 0; max = __INT_MAX__;
+                                       value = colon;
+                                       if (value && *value) {
+                                               colon = strchr(value, ':');
+                                               if (colon)
+                                                       *(colon++) = '\0';
+
+                                               dash = strchr(value, '-');
+                                               if (dash)
+                                                       *(dash++) = '\0';
+
+                                               /* support :val: :min-max: :min-: :-max: */
+                                               if (*value)
+                                                       min = atoi(value);
+                                               if (!dash)
+                                                       max = min;
+                                               else if (*dash)
+                                                       max = atoi(dash);
+
+                                               value = colon;
+                                       }
+
+                                       /* now's time to call the test */
+                                       printf("Running test '%s'\n", test_names[idx].name);
+                                       err = test_names[idx].func(min, max);
+                                       ret += err;
+                                       printf("Errors during this test: %d\n\n", err);
+                               } while (colon && *colon);
+                       } else
+                               printf("Ignoring unknown test name '%s'\n", test);
+
+                       test = comma;
+               } while (test && *test);
+       } else {
+               /* no test mentioned, run everything */
+               for (idx = 0; test_names[idx].name; idx++) {
+                       printf("Running test '%s'\n", test_names[idx].name);
+                       err = test_names[idx].func(min, max);
+                       ret += err;
+                       printf("Errors during this test: %d\n\n", err);
+               }
+       }
+
+       printf("Total number of errors: %d\n", ret);
+
+       if (getpid() == 1) {
+               /* we're running as init, there's no other process on the
+                * system, thus likely started from a VM for a quick check.
+                * Exiting will provoke a kernel panic that may be reported
+                * as an error by Qemu or the hypervisor, while stopping
+                * cleanly will often be reported as a success. This allows
+                * to use the output of this program for bisecting kernels.
+                */
+               printf("Leaving init with final status: %d\n", !!ret);
+               if (ret == 0)
+                       reboot(LINUX_REBOOT_CMD_POWER_OFF);
+#if defined(__x86_64__)
+               /* QEMU started with "-device isa-debug-exit -no-reboot" will
+                * exit with status code 2N+1 when N is written to 0x501. We
+                * hard-code the syscall here as it's arch-dependent.
+                */
+#if defined(_NOLIBC_SYS_H)
+               else if (my_syscall3(__NR_ioperm, 0x501, 1, 1) == 0)
+#else
+               else if (ioperm(0x501, 1, 1) == 0)
+#endif
+                       asm volatile ("outb %%al, %%dx" :: "d"(0x501), "a"(0));
+               /* if it does nothing, fall back to the regular panic */
+#endif
+       }
+
+       printf("Exiting with status %d\n", !!ret);
+       return !!ret;
+}
index f0d51d4..3a5936c 100644 (file)
@@ -1,4 +1,4 @@
-TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec futex vfork_exec
+TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec futex
 TEST_GEN_PROGS_EXTENDED := gettime_perf
 
 CFLAGS := -Wall -Werror -pthread
diff --git a/tools/testing/selftests/timens/vfork_exec.c b/tools/testing/selftests/timens/vfork_exec.c
deleted file mode 100644 (file)
index e6ccd90..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#define _GNU_SOURCE
-#include <errno.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "log.h"
-#include "timens.h"
-
-#define OFFSET (36000)
-
-int main(int argc, char *argv[])
-{
-       struct timespec now, tst;
-       int status, i;
-       pid_t pid;
-
-       if (argc > 1) {
-               if (sscanf(argv[1], "%ld", &now.tv_sec) != 1)
-                       return pr_perror("sscanf");
-
-               for (i = 0; i < 2; i++) {
-                       _gettime(CLOCK_MONOTONIC, &tst, i);
-                       if (abs(tst.tv_sec - now.tv_sec) > 5)
-                               return pr_fail("%ld %ld\n", now.tv_sec, tst.tv_sec);
-               }
-               return 0;
-       }
-
-       nscheck();
-
-       ksft_set_plan(1);
-
-       clock_gettime(CLOCK_MONOTONIC, &now);
-
-       if (unshare_timens())
-               return 1;
-
-       if (_settime(CLOCK_MONOTONIC, OFFSET))
-               return 1;
-
-       for (i = 0; i < 2; i++) {
-               _gettime(CLOCK_MONOTONIC, &tst, i);
-               if (abs(tst.tv_sec - now.tv_sec) > 5)
-                       return pr_fail("%ld %ld\n",
-                                       now.tv_sec, tst.tv_sec);
-       }
-
-       pid = vfork();
-       if (pid < 0)
-               return pr_perror("fork");
-
-       if (pid == 0) {
-               char now_str[64];
-               char *cargv[] = {"exec", now_str, NULL};
-               char *cenv[] = {NULL};
-
-               // Check that we are still in the source timens.
-               for (i = 0; i < 2; i++) {
-                       _gettime(CLOCK_MONOTONIC, &tst, i);
-                       if (abs(tst.tv_sec - now.tv_sec) > 5)
-                               return pr_fail("%ld %ld\n",
-                                               now.tv_sec, tst.tv_sec);
-               }
-
-               /* Check for proper vvar offsets after execve. */
-               snprintf(now_str, sizeof(now_str), "%ld", now.tv_sec + OFFSET);
-               execve("/proc/self/exe", cargv, cenv);
-               return pr_perror("execve");
-       }
-
-       if (waitpid(pid, &status, 0) != pid)
-               return pr_perror("waitpid");
-
-       if (status)
-               ksft_exit_fail();
-
-       ksft_test_result_pass("exec\n");
-       ksft_exit_pass();
-       return 0;
-}
index fda7628..e95bd56 100644 (file)
@@ -343,8 +343,10 @@ $(KERNEL_BZIMAGE): $(TOOLCHAIN_PATH)/.installed $(KERNEL_BUILD_PATH)/.config $(B
 .PHONY: $(KERNEL_BZIMAGE)
 
 $(TOOLCHAIN_PATH)/$(CHOST)/include/linux/.installed: | $(KERNEL_BUILD_PATH)/.config $(TOOLCHAIN_PATH)/.installed
+ifneq ($(ARCH),um)
        rm -rf $(TOOLCHAIN_PATH)/$(CHOST)/include/linux
        $(MAKE) -C $(KERNEL_PATH) O=$(KERNEL_BUILD_PATH) INSTALL_HDR_PATH=$(TOOLCHAIN_PATH)/$(CHOST) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(CROSS_COMPILE) headers_install
+endif
        touch $@
 
 $(TOOLCHAIN_PATH)/.installed: $(TOOLCHAIN_TAR)
index 363b982..5d3440f 100644 (file)
@@ -14,6 +14,7 @@ struct virtio_device {
        u64 features;
        struct list_head vqs;
        spinlock_t vqs_list_lock;
+       const struct virtio_config_ops *config;
 };
 
 struct virtqueue {
@@ -23,7 +24,9 @@ struct virtqueue {
        struct virtio_device *vdev;
         unsigned int index;
         unsigned int num_free;
+       unsigned int num_max;
        void *priv;
+       bool reset;
 };
 
 /* Interfaces exported by virtio_ring. */
index f2640e5..2a8a70e 100644 (file)
@@ -3,6 +3,11 @@
 #include <linux/virtio.h>
 #include <uapi/linux/virtio_config.h>
 
+struct virtio_config_ops {
+       int (*disable_vq_and_reset)(struct virtqueue *vq);
+       int (*enable_vq_after_reset)(struct virtqueue *vq);
+};
+
 /*
  * __virtio_test_bit - helper to test feature bits. For use by transports.
  *                     Devices should normally use virtio_has_feature,