summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-01-12 12:15:35 +0000
committerMark Brown <broonie@kernel.org>2026-01-12 12:15:35 +0000
commit6eb6b62f002f1cbc538c2e773539d1d4c37749cb (patch)
treee5170ea004e5cce5ef2e5d2a32c3aa41c4f18fa6
parentb0655377aa5a410df02d89170c20141a1a5bbc28 (diff)
parent8d38423d9dea7353a8a54a3ab2e0d0aa04ed34d0 (diff)
regulator: core: allow regulator_register() with
Merge series from André Draszik <andre.draszik@linaro.org>: With these attached patches it becomes possible again to support hardware designs with multiple PMICs where individual rails of each act as required supplies for rails of the other (due to the latter being e.g. always-on), and vice-versa. Google Pixel 6 and 6 Pro (oriole and raven) are examples of such designs. Rather than returning -EPORBE_DEFER in regulator_register() when set_machine_constraints() fails with -EPROBE_DEFER (due to missing required supplies), we still allow rail registration and try to reresolve supplies each time a new rail gets registered. This is implemented using a bus (regulator bus), which allows the core to reresolve supplies for regulators that still need them whenever new regulators (i.e. devices) are added. Using a bus also solves existing problems around late resolution of supplies as mentioned in the commit message introducing that bus. The series starts with a few bug fixes and the last two commits implement the changes mentioned above, but do depend on the bug fixes.
-rw-r--r--.clang-format1
-rw-r--r--.mailmap4
-rw-r--r--CREDITS1
-rw-r--r--Documentation/admin-guide/blockdev/zoned_loop.rst2
-rw-r--r--Documentation/arch/riscv/hwprobe.rst8
-rw-r--r--Documentation/arch/x86/boot.rst198
-rw-r--r--Documentation/devicetree/bindings/arm/arm,integrator.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/arm,realview.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/arm,scu.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/arm,versatile-sysreg.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/arm,versatile.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/gemini.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/ux500.yaml2
-rw-r--r--Documentation/devicetree/bindings/ata/ata-generic.yaml2
-rw-r--r--Documentation/devicetree/bindings/ata/cortina,gemini-sata-bridge.yaml2
-rw-r--r--Documentation/devicetree/bindings/ata/faraday,ftide010.yaml2
-rw-r--r--Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml2
-rw-r--r--Documentation/devicetree/bindings/ata/pata-common.yaml2
-rw-r--r--Documentation/devicetree/bindings/ata/sata-common.yaml2
-rw-r--r--Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/sprd,sc9860-clk.yaml26
-rw-r--r--Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml2
-rw-r--r--Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/dsi-controller.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/faraday,tve200.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/arm,rtsm-display.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,s6d16d0.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/ti,nspire.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/ste,mcde.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml3
-rw-r--r--Documentation/devicetree/bindings/dma/stericsson,dma40.yaml2
-rw-r--r--Documentation/devicetree/bindings/extcon/fcs,fsa880.yaml2
-rw-r--r--Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml2
-rw-r--r--Documentation/devicetree/bindings/gnss/brcm,bcm4751.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/faraday,ftgpio010.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-consumer-common.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-mmio.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/mrvl-gpio.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/pl061-gpio.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml2
-rw-r--r--Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml4
-rw-r--r--Documentation/devicetree/bindings/hwmon/ntc-thermistor.yaml2
-rw-r--r--Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml2
-rw-r--r--Documentation/devicetree/bindings/i2c/arm,i2c-versatile.yaml2
-rw-r--r--Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml2
-rw-r--r--Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml7
-rw-r--r--Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/light/capella,cm3605.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8974.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/yamaha,yas530.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/st,st-sensors.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/atmel,maxtouch.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma140.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma340.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/melfas,mms114.yaml2
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/zinitix,bt400.yaml2
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.yaml2
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/faraday,ftintc010.yaml2
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/register-bit-led.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/regulator-led.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/richtek,rt8515.yaml2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-bus-controller.yaml2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-peripheral-props.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/st,stmpe.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml2
-rw-r--r--Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml2
-rw-r--r--Documentation/devicetree/bindings/mmc/arm,pl18x.yaml2
-rw-r--r--Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/seama.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/bluetooth/brcm,bluetooth.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/micrel,ks8995.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/realtek.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/intel,ixp46x-ptp-timer.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/intel,ixp4xx-hss.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml2
-rw-r--r--Documentation/devicetree/bindings/power/supply/samsung,battery.yaml2
-rw-r--r--Documentation/devicetree/bindings/riscv/extensions.yaml36
-rw-r--r--Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml2
-rw-r--r--Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml4
-rw-r--r--Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml6
-rw-r--r--Documentation/devicetree/bindings/spi/spi-pl022.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/faraday,fttmr010.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/faraday,fotg210.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/intel,ixp4xx-udc.yaml2
-rw-r--r--Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml2
-rw-r--r--Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml2
-rw-r--r--Documentation/hwmon/ds620.rst4
-rw-r--r--Documentation/i2c/busses/i2c-i801.rst1
-rw-r--r--Documentation/input/event-codes.rst6
-rw-r--r--MAINTAINERS11
-rw-r--r--Makefile2
-rw-r--r--arch/arm64/boot/dts/mediatek/Makefile55
-rw-r--r--arch/arm64/include/asm/simd.h9
-rw-r--r--arch/arm64/kernel/fpsimd.c130
-rw-r--r--arch/arm64/kernel/process.c1
-rw-r--r--arch/arm64/mm/mmu.c33
-rw-r--r--arch/arm64/net/bpf_jit_comp.c2
-rw-r--r--arch/loongarch/include/asm/loongarch.h7
-rw-r--r--arch/loongarch/kernel/head.S4
-rw-r--r--arch/loongarch/kernel/mcount_dyn.S14
-rw-r--r--arch/loongarch/kernel/traps.c5
-rw-r--r--arch/loongarch/kernel/unwind_orc.c27
-rw-r--r--arch/loongarch/mm/cache.c8
-rw-r--r--arch/loongarch/net/bpf_jit.c58
-rw-r--r--arch/loongarch/net/bpf_jit.h26
-rw-r--r--arch/mips/alchemy/common/setup.c3
-rw-r--r--arch/mips/sgi-ip22/ip22-gio.c3
-rw-r--r--arch/powerpc/include/asm/hw_irq.h2
-rw-r--r--arch/powerpc/include/asm/reg.h1
-rw-r--r--arch/powerpc/kernel/btext.c3
-rw-r--r--arch/powerpc/kernel/entry_32.S15
-rw-r--r--arch/powerpc/kernel/interrupt.c5
-rw-r--r--arch/powerpc/kexec/core_64.c19
-rw-r--r--arch/powerpc/platforms/powernv/idle.c9
-rwxr-xr-xarch/powerpc/tools/gcc-check-fpatchable-function-entry.sh1
-rwxr-xr-xarch/powerpc/tools/gcc-check-mprofile-kernel.sh1
-rw-r--r--arch/riscv/include/asm/atomic.h8
-rw-r--r--arch/riscv/include/asm/hwcap.h2
-rw-r--r--arch/riscv/include/asm/pgtable.h16
-rw-r--r--arch/riscv/include/asm/sbi.h29
-rw-r--r--arch/riscv/include/asm/vector.h3
-rw-r--r--arch/riscv/include/uapi/asm/hwprobe.h3
-rw-r--r--arch/riscv/kernel/cpufeature.c24
-rw-r--r--arch/riscv/kernel/signal.c62
-rw-r--r--arch/riscv/kernel/sys_hwprobe.c2
-rw-r--r--arch/s390/include/uapi/asm/ipl.h1
-rw-r--r--arch/s390/kernel/ipl.c48
-rw-r--r--arch/s390/kernel/stacktrace.c18
-rw-r--r--arch/s390/pci/pci.c7
-rw-r--r--arch/s390/pci/pci_bus.c98
-rw-r--r--arch/s390/pci/pci_bus.h15
-rw-r--r--arch/x86/include/asm/bug.h2
-rw-r--r--arch/x86/include/asm/irq_remapping.h7
-rw-r--r--arch/x86/include/asm/irqflags.h2
-rw-r--r--arch/x86/include/asm/uv/bios.h2
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c2
-rw-r--r--arch/x86/kernel/cpu/sgx/ioctl.c2
-rw-r--r--arch/x86/kernel/fpu/xstate.c4
-rw-r--r--arch/x86/kernel/irq.c23
-rw-r--r--arch/x86/kernel/unwind_orc.c39
-rw-r--r--arch/x86/kvm/cpuid.c11
-rw-r--r--arch/x86/kvm/svm/nested.c4
-rw-r--r--arch/x86/kvm/svm/svm.c2
-rw-r--r--arch/x86/kvm/svm/svm.h7
-rw-r--r--arch/x86/kvm/vmx/nested.c3
-rw-r--r--arch/x86/kvm/vmx/vmx.c9
-rw-r--r--arch/x86/kvm/x86.c7
-rw-r--r--arch/x86/net/bpf_jit_comp.c12
-rw-r--r--arch/x86/xen/enlighten_pv.c2
-rw-r--r--block/bfq-cgroup.c2
-rw-r--r--block/bfq-iosched.c2
-rw-r--r--block/bfq-iosched.h2
-rw-r--r--block/blk-mq.c2
-rw-r--r--block/blk-settings.c14
-rw-r--r--block/blk-sysfs.c2
-rw-r--r--block/blk-wbt.c20
-rw-r--r--block/blk-wbt.h5
-rw-r--r--block/elevator.c4
-rw-r--r--block/elevator.h1
-rw-r--r--block/ioctl.c9
-rw-r--r--crypto/seqiv.c8
-rw-r--r--drivers/accel/amdxdna/aie2_pci.c6
-rw-r--r--drivers/acpi/acpi_pcc.c2
-rw-r--r--drivers/acpi/cppc_acpi.c3
-rw-r--r--drivers/ata/libata-core.c3
-rw-r--r--drivers/base/power/runtime.c22
-rw-r--r--drivers/block/loop.c22
-rw-r--r--drivers/block/rnbd/rnbd-clt.c13
-rw-r--r--drivers/block/rnbd/rnbd-clt.h2
-rw-r--r--drivers/block/ublk_drv.c70
-rw-r--r--drivers/block/zloop.c8
-rw-r--r--drivers/bluetooth/btusb.c12
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c7
-rw-r--r--drivers/crypto/hisilicon/qm.c9
-rw-r--r--drivers/firewire/nosy.c10
-rw-r--r--drivers/firmware/efi/efi.c1
-rw-r--r--drivers/firmware/efi/libstub/gop.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c5
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c37
-rw-r--r--drivers/gpu/drm/drm_gem.c8
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c5
-rw-r--r--drivers/gpu/drm/drm_pagemap.c17
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c37
-rw-r--r--drivers/gpu/drm/imagination/pvr_gem.c11
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_catalog.c13
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c52
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_preempt.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h13
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c38
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h8
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c29
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h84
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h23
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h47
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h21
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h16
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c137
-rw-r--r--drivers/gpu/drm/msm/disp/mdp_format.h6
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.h2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_drm.c1
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.h9
-rw-r--r--drivers/gpu/drm/msm/dp/dp_panel.h8
-rw-r--r--drivers/gpu/drm/msm/msm_fence.h36
-rw-r--r--drivers/gpu/drm/msm/msm_gem_vma.c5
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h68
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c4
-rw-r--r--drivers/gpu/drm/msm/msm_perf.c10
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/atom.h13
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c2
-rw-r--r--drivers/gpu/drm/panel/Kconfig1
-rw-r--r--drivers/gpu/drm/panel/panel-sony-td4353-jdi.c2
-rw-r--r--drivers/gpu/drm/tests/drm_atomic_state_test.c40
-rw-r--r--drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c143
-rw-r--r--drivers/gpu/drm/xe/xe_bo.c15
-rw-r--r--drivers/gpu/drm/xe/xe_device.c2
-rw-r--r--drivers/gpu/drm/xe/xe_dma_buf.c2
-rw-r--r--drivers/gpu/drm/xe/xe_eu_stall.c2
-rw-r--r--drivers/gpu/drm/xe/xe_exec.c3
-rw-r--r--drivers/gpu/drm/xe/xe_gt.c7
-rw-r--r--drivers/gpu/drm/xe/xe_gt_freq.c4
-rw-r--r--drivers/gpu/drm/xe/xe_gt_idle.c8
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_vf.c2
-rw-r--r--drivers/gpu/drm/xe/xe_gt_throttle.c2
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ct.c14
-rw-r--r--drivers/gpu/drm/xe/xe_guc_submit.c35
-rw-r--r--drivers/gpu/drm/xe/xe_heci_gsc.c4
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c25
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.h6
-rw-r--r--drivers/gpu/drm/xe/xe_oa.c12
-rw-r--r--drivers/gpu/drm/xe/xe_sriov_vfio.c2
-rw-r--r--drivers/gpu/drm/xe/xe_svm.c51
-rw-r--r--drivers/gpu/drm/xe/xe_svm.h2
-rw-r--r--drivers/gpu/drm/xe/xe_vm.c8
-rw-r--r--drivers/gpu/drm/xe/xe_vm_types.h2
-rw-r--r--drivers/gpu/drm/xe/xe_wa.c8
-rw-r--r--drivers/gpu/drm/xe/xe_wa_oob.rules1
-rw-r--r--drivers/hid/hid-debug.c1
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c9
-rw-r--r--drivers/hwmon/ibmpex.c9
-rw-r--r--drivers/hwmon/ltc4282.c9
-rw-r--r--drivers/hwmon/tmp401.c2
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c3
-rw-r--r--drivers/i2c/busses/i2c-i801.c3
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/busses/i2c-rcar.c2
-rw-r--r--drivers/infiniband/core/addr.c33
-rw-r--r--drivers/infiniband/core/cma.c3
-rw-r--r--drivers/infiniband/core/device.c4
-rw-r--r--drivers/infiniband/core/verbs.c2
-rw-r--r--drivers/infiniband/hw/bnxt_re/hw_counters.h6
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c7
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c2
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c8
-rw-r--r--drivers/infiniband/hw/efa/efa_verbs.c4
-rw-r--r--drivers/infiniband/hw/irdma/utils.c3
-rw-r--r--drivers/infiniband/hw/mana/cq.c4
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.c32
-rw-r--r--drivers/infiniband/sw/rxe/rxe_odp.c4
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c1
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-pri.h32
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs.h24
-rw-r--r--drivers/input/joystick/xpad.c5
-rw-r--r--drivers/input/keyboard/atkbd.c7
-rw-r--r--drivers/input/keyboard/lkkbd.c5
-rw-r--r--drivers/input/mouse/alps.c1
-rw-r--r--drivers/input/serio/i8042-acpipnpio.h7
-rw-r--r--drivers/input/touchscreen/apple_z2.c4
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c2
-rw-r--r--drivers/iommu/amd/amd_iommu.h5
-rw-r--r--drivers/iommu/amd/init.c24
-rw-r--r--drivers/iommu/amd/iommu.c27
-rw-r--r--drivers/iommu/generic_pt/iommu_pt.h3
-rw-r--r--drivers/iommu/intel/irq_remapping.c8
-rw-r--r--drivers/iommu/iommufd/io_pagetable.c6
-rw-r--r--drivers/iommu/iommufd/selftest.c14
-rw-r--r--drivers/md/md.c61
-rw-r--r--drivers/md/raid5.c10
-rw-r--r--drivers/misc/lkdtm/bugs.c53
-rw-r--r--drivers/mmc/host/Kconfig4
-rw-r--r--drivers/mmc/host/sdhci-of-arasan.c2
-rw-r--r--drivers/net/can/Kconfig7
-rw-r--r--drivers/net/can/Makefile2
-rw-r--r--drivers/net/can/dev/Makefile5
-rw-r--r--drivers/net/can/usb/gs_usb.c2
-rw-r--r--drivers/net/dsa/b53/b53_common.c3
-rw-r--r--drivers/net/dsa/lantiq/lantiq_gswip.c3
-rw-r--r--drivers/net/dsa/lantiq/lantiq_gswip.h2
-rw-r--r--drivers/net/dsa/lantiq/lantiq_gswip_common.c19
-rw-r--r--drivers/net/dsa/lantiq/mxl-gsw1xx.c46
-rw-r--r--drivers/net/ethernet/airoha/airoha_eth.c39
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c2
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig8
-rw-r--r--drivers/net/ethernet/broadcom/b44.c3
-rw-r--r--drivers/net/ethernet/broadcom/bnge/bnge.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnge/bnge_core.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c3
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c3
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c3
-rw-r--r--drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c8
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c7
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c19
-rw-r--r--drivers/net/ethernet/google/gve/gve_utils.c2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c4
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c10
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h11
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c12
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c4
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c4
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lib.c2
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_virtchnl.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/devlink.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c97
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tx.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c48
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c27
-rw-r--r--drivers/net/ethernet/microsoft/mana/gdma_main.c2
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c5
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c17
-rw-r--r--drivers/net/ethernet/ti/Kconfig3
-rw-r--r--drivers/net/ethernet/wangxun/Kconfig4
-rw-r--r--drivers/net/fjes/fjes_hw.c12
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c3
-rw-r--r--drivers/net/mdio/mdio-aspeed.c7
-rw-r--r--drivers/net/mdio/mdio-realtek-rtl9300.c6
-rw-r--r--drivers/net/phy/marvell-88q2xxx.c2
-rw-r--r--drivers/net/phy/mediatek/mtk-ge-soc.c2
-rw-r--r--drivers/net/phy/realtek/realtek_main.c4
-rw-r--r--drivers/net/phy/sfp.c2
-rw-r--r--drivers/net/team/team_core.c2
-rw-r--r--drivers/net/usb/asix_common.c5
-rw-r--r--drivers/net/usb/ax88172a.c6
-rw-r--r--drivers/net/usb/rtl8150.c2
-rw-r--r--drivers/net/usb/sr9700.c9
-rw-r--r--drivers/net/usb/usbnet.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mld/ptp.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ptp.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c12
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c4
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c3
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c5
-rw-r--r--drivers/nfc/pn533/usb.c2
-rw-r--r--drivers/of/fdt.c2
-rw-r--r--drivers/parisc/sba_iommu.c4
-rw-r--r--drivers/platform/mellanox/mlxbf-pmc.c14
-rw-r--r--drivers/platform/x86/asus-armoury.h176
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c1
-rw-r--r--drivers/platform/x86/dell/alienware-wmi-wmax.c32
-rw-r--r--drivers/platform/x86/dell/dell-lis3lv02d.c1
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c4
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/int-attributes.c2
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c5
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c5
-rw-r--r--drivers/platform/x86/hp/hp-bioscfg/string-attributes.c2
-rw-r--r--drivers/platform/x86/ibm_rtl.c2
-rw-r--r--drivers/platform/x86/intel/pmt/discovery.c8
-rw-r--r--drivers/platform/x86/lenovo/ideapad-laptop.c2
-rw-r--r--drivers/platform/x86/lenovo/think-lmi.c6
-rw-r--r--drivers/platform/x86/msi-laptop.c3
-rw-r--r--drivers/platform/x86/samsung-galaxybook.c9
-rw-r--r--drivers/platform/x86/uniwill/uniwill-acpi.c7
-rw-r--r--drivers/pmdomain/imx/gpc.c5
-rw-r--r--drivers/pmdomain/mediatek/mtk-pm-domains.c21
-rw-r--r--drivers/powercap/intel_rapl_common.c24
-rw-r--r--drivers/powercap/intel_rapl_msr.c4
-rw-r--r--drivers/powercap/powercap_sys.c22
-rw-r--r--drivers/regulator/core.c351
-rw-r--r--drivers/regulator/fp9931.c3
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_ioc.h1
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c2
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/scsi/sg.c20
-rw-r--r--drivers/spi/spi-cadence-quadspi.c31
-rw-r--r--drivers/spi/spi-fsl-spi.c2
-rw-r--r--drivers/spi/spi-mpfs.c1
-rw-r--r--drivers/spi/spi-mt65xx.c2
-rw-r--r--drivers/spi/spi-sun6i.c11
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c3
-rw-r--r--drivers/thermal/thermal_core.c4
-rw-r--r--drivers/tty/serial/8250/8250_loongson.c4
-rw-r--r--drivers/tty/serial/serial_base_bus.c11
-rw-r--r--drivers/tty/serial/sh-sci.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c14
-rw-r--r--drivers/ufs/core/ufshcd.c5
-rw-r--r--drivers/usb/dwc3/dwc3-of-simple.c7
-rw-r--r--drivers/usb/dwc3/gadget.c2
-rw-r--r--drivers/usb/dwc3/host.c2
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c42
-rw-r--r--drivers/usb/host/ohci-nxp.c18
-rw-r--r--drivers/usb/host/xhci-dbgtty.c2
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c1
-rw-r--r--drivers/usb/phy/phy-isp1301.c7
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c2
-rw-r--r--drivers/usb/storage/unusual_uas.h2
-rw-r--r--drivers/usb/typec/altmodes/displayport.c8
-rw-r--r--drivers/usb/typec/ucsi/Kconfig1
-rw-r--r--drivers/usb/typec/ucsi/cros_ec_ucsi.c5
-rw-r--r--drivers/usb/typec/ucsi/debugfs.c36
-rw-r--r--drivers/usb/typec/ucsi/displayport.c11
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c118
-rw-r--r--drivers/usb/typec/ucsi/ucsi.h22
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c25
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c11
-rw-r--r--drivers/usb/typec/ucsi/ucsi_yoga_c630.c15
-rw-r--r--drivers/vfio/pci/nvgrace-gpu/main.c4
-rw-r--r--drivers/vfio/pci/pds/dirty.c7
-rw-r--r--drivers/vfio/pci/vfio_pci_rdwr.c25
-rw-r--r--drivers/vfio/pci/xe/main.c5
-rw-r--r--drivers/vhost/vsock.c15
-rw-r--r--fs/btrfs/file.c3
-rw-r--r--fs/btrfs/inode.c1
-rw-r--r--fs/btrfs/qgroup.c27
-rw-r--r--fs/btrfs/tests/qgroup-tests.c1
-rw-r--r--fs/btrfs/tree-log.c46
-rw-r--r--fs/btrfs/volumes.c1
-rw-r--r--fs/debugfs/inode.c7
-rw-r--r--fs/erofs/zdata.c8
-rw-r--r--fs/file_attr.c2
-rw-r--r--fs/kernfs/dir.c6
-rw-r--r--fs/libfs.c50
-rw-r--r--fs/lockd/svc4proc.c4
-rw-r--r--fs/lockd/svclock.c21
-rw-r--r--fs/lockd/svcproc.c5
-rw-r--r--fs/locks.c12
-rw-r--r--fs/nfsd/export.c2
-rw-r--r--fs/nfsd/nfs4state.c20
-rw-r--r--fs/nfsd/nfs4xdr.c5
-rw-r--r--fs/nfsd/nfsd.h8
-rw-r--r--fs/nfsd/nfssvc.c5
-rw-r--r--fs/nfsd/vfs.h3
-rw-r--r--fs/notify/fsnotify.c9
-rw-r--r--fs/smb/client/cifsfs.h4
-rw-r--r--fs/smb/client/cifspdu.h2
-rw-r--r--fs/smb/client/fs_context.c2
-rw-r--r--fs/smb/client/ioctl.c3
-rw-r--r--fs/smb/client/smb2ops.c6
-rw-r--r--fs/smb/client/trace.h1
-rw-r--r--fs/smb/common/smb1pdu.h56
-rw-r--r--fs/smb/common/smb2pdu.h41
-rw-r--r--fs/smb/common/smbdirect/smbdirect_socket.h12
-rw-r--r--fs/smb/common/smbglob.h2
-rw-r--r--fs/smb/server/auth.c4
-rw-r--r--fs/smb/server/connection.c11
-rw-r--r--fs/smb/server/mgmt/user_session.c4
-rw-r--r--fs/smb/server/oplock.c8
-rw-r--r--fs/smb/server/server.c2
-rw-r--r--fs/smb/server/smb2pdu.c86
-rw-r--r--fs/smb/server/smb2pdu.h9
-rw-r--r--fs/smb/server/smb_common.c26
-rw-r--r--fs/smb/server/smb_common.h10
-rw-r--r--fs/smb/server/smbacl.c3
-rw-r--r--fs/smb/server/transport_rdma.c175
-rw-r--r--fs/smb/server/vfs.c2
-rw-r--r--fs/xfs/libxfs/xfs_sb.c15
-rw-r--r--fs/xfs/scrub/attr_repair.c2
-rw-r--r--fs/xfs/xfs_attr_item.c2
-rw-r--r--fs/xfs/xfs_buf_item.c1
-rw-r--r--fs/xfs/xfs_discard.c27
-rw-r--r--fs/xfs/xfs_discard.h2
-rw-r--r--fs/xfs/xfs_file.c58
-rw-r--r--fs/xfs/xfs_rtalloc.c14
-rw-r--r--include/drm/drm_pagemap.h17
-rw-r--r--include/kunit/run-in-irq-context.h53
-rw-r--r--include/linux/bio.h30
-rw-r--r--include/linux/bpf.h3
-rw-r--r--include/linux/compiler-clang.h1
-rw-r--r--include/linux/compiler_types.h3
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/genalloc.h1
-rw-r--r--include/linux/intel_rapl.h4
-rw-r--r--include/linux/intel_vsec.h17
-rw-r--r--include/linux/io_uring_types.h8
-rw-r--r--include/linux/irq-entry-common.h4
-rw-r--r--include/linux/kasan.h16
-rw-r--r--include/linux/kexec.h4
-rw-r--r--include/linux/leafops.h4
-rw-r--r--include/linux/memory-failure.h2
-rw-r--r--include/linux/mm.h8
-rw-r--r--include/linux/mm_types.h1
-rw-r--r--include/linux/property.h1
-rw-r--r--include/linux/regulator/driver.h2
-rw-r--r--include/linux/vfio_pci_core.h10
-rw-r--r--include/linux/virtio.h2
-rw-r--r--include/linux/virtio_features.h2
-rw-r--r--include/net/dsa.h1
-rw-r--r--include/net/inet_frag.h18
-rw-r--r--include/net/ipv6_frag.h9
-rw-r--r--include/net/netfilter/nf_tables.h34
-rw-r--r--include/sound/soc-acpi.h5
-rw-r--r--include/trace/events/tlb.h5
-rw-r--r--include/uapi/drm/xe_drm.h1
-rw-r--r--include/uapi/linux/energy_model.h1
-rw-r--r--include/uapi/linux/input-event-codes.h9
-rw-r--r--include/uapi/linux/mptcp.h1
-rw-r--r--include/uapi/linux/pr.h2
-rw-r--r--include/uapi/rdma/irdma-abi.h2
-rw-r--r--include/uapi/rdma/rdma_user_cm.h4
-rw-r--r--include/uapi/regulator/regulator.h6
-rw-r--r--io_uring/cancel.c5
-rw-r--r--io_uring/io_uring.c7
-rw-r--r--io_uring/memmap.c9
-rw-r--r--io_uring/openclose.c2
-rw-r--r--io_uring/register.c2
-rw-r--r--io_uring/rsrc.c1
-rw-r--r--io_uring/tctx.c8
-rw-r--r--kernel/bpf/core.c16
-rw-r--r--kernel/bpf/dmabuf_iter.c56
-rw-r--r--kernel/cgroup/cpuset.c21
-rw-r--r--kernel/cgroup/rstat.c13
-rw-r--r--kernel/irq/manage.c2
-rw-r--r--kernel/kexec_core.c16
-rw-r--r--kernel/kthread.c1
-rw-r--r--kernel/power/em_netlink_autogen.c1
-rw-r--r--kernel/power/em_netlink_autogen.h1
-rw-r--r--kernel/power/suspend.c9
-rw-r--r--kernel/sched/ext.c95
-rw-r--r--kernel/trace/bpf_trace.c2
-rw-r--r--kernel/trace/ftrace.c7
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace_events.c2
-rw-r--r--lib/crypto/riscv/.gitignore2
-rw-r--r--lib/idr.c2
-rw-r--r--lib/kunit/Kconfig2
-rw-r--r--lib/kunit/device.c7
-rw-r--r--mm/damon/vaddr.c2
-rw-r--r--mm/kasan/common.c32
-rw-r--r--mm/kasan/hw_tags.c2
-rw-r--r--mm/kasan/shadow.c4
-rw-r--r--mm/ksm.c2
-rw-r--r--mm/memcontrol.c4
-rw-r--r--mm/memory-failure.c29
-rw-r--r--mm/memremap.c2
-rw-r--r--mm/page_alloc.c26
-rw-r--r--mm/page_owner.c2
-rw-r--r--mm/shmem.c32
-rw-r--r--mm/slub.c2
-rw-r--r--mm/vmalloc.c8
-rw-r--r--net/bluetooth/mgmt.c6
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/caif/cffrml.c9
-rw-r--r--net/can/Kconfig1
-rw-r--r--net/can/j1939/socket.c6
-rw-r--r--net/can/j1939/transport.c2
-rw-r--r--net/core/dev.c8
-rw-r--r--net/dsa/dsa.c67
-rw-r--r--net/ethtool/ioctl.c30
-rw-r--r--net/handshake/netlink.c3
-rw-r--r--net/handshake/request.c8
-rw-r--r--net/hsr/hsr_forward.c2
-rw-r--r--net/ipv4/fib_semantics.c26
-rw-r--r--net/ipv4/fib_trie.c7
-rw-r--r--net/ipv4/inet_fragment.c55
-rw-r--r--net/ipv4/ip_fragment.c22
-rw-r--r--net/ipv4/ip_gre.c6
-rw-r--r--net/ipv6/calipso.c3
-rw-r--r--net/ipv6/ip6_gre.c15
-rw-r--r--net/ipv6/route.c13
-rw-r--r--net/mac80211/cfg.c10
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/mlme.c5
-rw-r--r--net/mac80211/ocb.c3
-rw-r--r--net/mac80211/rx.c5
-rw-r--r--net/mptcp/Kconfig2
-rw-r--r--net/mptcp/options.c10
-rw-r--r--net/mptcp/pm_netlink.c3
-rw-r--r--net/mptcp/protocol.c30
-rw-r--r--net/mptcp/protocol.h9
-rw-r--r--net/mptcp/subflow.c6
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c3
-rw-r--r--net/netfilter/nf_conncount.c25
-rw-r--r--net/netfilter/nf_conntrack_core.c3
-rw-r--r--net/netfilter/nf_flow_table_path.c4
-rw-r--r--net/netfilter/nf_nat_core.c14
-rw-r--r--net/netfilter/nf_tables_api.c84
-rw-r--r--net/netrom/nr_out.c4
-rw-r--r--net/nfc/core.c9
-rw-r--r--net/openvswitch/flow_netlink.c13
-rw-r--r--net/openvswitch/vport-netdev.c17
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/sched/act_mirred.c9
-rw-r--r--net/sched/sch_ets.c6
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/socket.c7
-rw-r--r--net/smc/Kconfig4
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c3
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_rw.c7
-rw-r--r--net/unix/af_unix.c11
-rw-r--r--net/unix/garbage.c2
-rw-r--r--net/wireless/sme.c2
-rw-r--r--rust/helpers/dma.c21
-rw-r--r--rust/kernel/maple_tree.rs11
-rw-r--r--samples/ftrace/ftrace-direct-modify.c8
-rw-r--r--samples/ftrace/ftrace-direct-multi-modify.c8
-rw-r--r--samples/ftrace/ftrace-direct-multi.c4
-rw-r--r--samples/ftrace/ftrace-direct-too.c4
-rw-r--r--samples/ftrace/ftrace-direct.c4
-rw-r--r--samples/rust/rust_driver_pci.rs2
-rw-r--r--scripts/Makefile.build26
-rwxr-xr-xscripts/clang-tools/gen_compile_commands.py135
-rwxr-xr-xscripts/coccicheck6
-rw-r--r--scripts/coccinelle/api/pm_runtime.cocci2
-rw-r--r--scripts/mod/devicetable-offsets.c3
-rw-r--r--scripts/mod/file2alias.c9
-rw-r--r--security/integrity/ima/ima_kexec.c4
-rw-r--r--sound/hda/codecs/realtek/alc269.c32
-rw-r--r--sound/hda/controllers/cix-ipbloq.c4
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c8
-rw-r--r--sound/pcmcia/vx/vxpocket.c8
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c7
-rw-r--r--sound/soc/codecs/ak4458.c4
-rw-r--r--sound/soc/codecs/rt1320-sdw.c16
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c8
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c3
-rw-r--r--sound/soc/fsl/fsl_easrc.c3
-rw-r--r--sound/soc/fsl/fsl_sai.c13
-rw-r--r--sound/soc/fsl/fsl_xcvr.c3
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c104
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-nvl-match.c49
-rw-r--r--sound/soc/intel/common/sof-function-topology-lib.c5
-rw-r--r--sound/soc/intel/common/sof-function-topology-lib.h2
-rw-r--r--sound/soc/qcom/sdm845.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c8
-rw-r--r--sound/soc/soc-ops.c32
-rw-r--r--sound/soc/sof/intel/pci-mtl.c6
-rw-r--r--sound/soc/sof/ipc4-topology.c49
-rw-r--r--sound/soc/sof/topology.c26
-rw-r--r--sound/soc/tegra/tegra210_ahub.c6
-rw-r--r--sound/usb/endpoint.c6
-rw-r--r--sound/usb/format.c5
-rw-r--r--sound/usb/mixer_us16x08.c20
-rw-r--r--sound/usb/quirks.c14
-rw-r--r--tools/arch/arm64/include/asm/cputype.h8
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h11
-rw-r--r--tools/arch/x86/include/asm/msr-index.h30
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h1
-rw-r--r--tools/bpf/bpftool/Makefile2
-rw-r--r--tools/build/Makefile.feature6
-rw-r--r--tools/build/feature/Makefile10
-rw-r--r--tools/build/feature/test-all.c5
-rw-r--r--tools/build/feature/test-libopenssl.c7
-rw-r--r--tools/include/linux/gfp_types.h6
-rw-r--r--tools/include/linux/types.h8
-rw-r--r--tools/include/uapi/asm-generic/unistd.h4
-rw-r--r--tools/include/uapi/drm/drm.h15
-rw-r--r--tools/include/uapi/linux/kvm.h11
-rw-r--r--tools/lib/bpf/libbpf.c7
-rw-r--r--tools/mm/page_owner_sort.c6
-rw-r--r--tools/net/ynl/Makefile.deps2
-rw-r--r--tools/perf/Makefile.config8
-rw-r--r--tools/perf/arch/arm/entry/syscalls/syscall.tbl1
-rw-r--r--tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl1
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/syscall.tbl1
-rw-r--r--tools/perf/arch/s390/entry/syscalls/syscall.tbl1
-rw-r--r--tools/perf/arch/sh/entry/syscalls/syscall.tbl1
-rw-r--r--tools/perf/arch/sparc/entry/syscalls/syscall.tbl1
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_32.tbl1
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl1
-rw-r--r--tools/perf/arch/xtensa/entry/syscalls/syscall.tbl1
-rw-r--r--tools/perf/builtin-buildid-cache.c6
-rwxr-xr-xtools/perf/tests/shell/kvm.sh2
-rwxr-xr-xtools/perf/tests/shell/top.sh2
-rw-r--r--tools/perf/trace/beauty/include/linux/socket.h24
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/fcntl.h12
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/fs.h3
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/mount.h2
-rw-r--r--tools/perf/trace/beauty/include/uapi/sound/asound.h2
-rw-r--r--tools/perf/util/arm-spe.c1
-rw-r--r--tools/perf/util/libbfd.c4
-rw-r--r--tools/perf/util/symbol-elf.c4
-rw-r--r--tools/perf/util/symbol-minimal.c4
-rw-r--r--tools/sched_ext/scx_show_state.py10
-rw-r--r--tools/scripts/syscall.tbl1
-rw-r--r--tools/testing/radix-tree/idr-test.c21
-rw-r--r--tools/testing/selftests/bpf/Makefile2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/d_path.c89
-rw-r--r--tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c47
-rw-r--r--tools/testing/selftests/bpf/progs/test_d_path.c23
-rwxr-xr-xtools/testing/selftests/drivers/net/psp.py6
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc5
-rw-r--r--tools/testing/selftests/iommu/iommufd.c8
-rw-r--r--tools/testing/selftests/kselftest_harness.h8
-rw-r--r--tools/testing/selftests/kvm/rseq_test.c1
-rw-r--r--tools/testing/selftests/kvm/x86/cpuid_test.c15
-rw-r--r--tools/testing/selftests/lkdtm/tests.txt2
-rw-r--r--tools/testing/selftests/mm/uffd-unit-tests.c2
-rw-r--r--tools/testing/selftests/net/af_unix/Makefile7
-rwxr-xr-xtools/testing/selftests/net/fib_nexthops.sh15
-rwxr-xr-xtools/testing/selftests/net/fib_tests.sh70
-rw-r--r--tools/testing/selftests/net/forwarding/config1
-rwxr-xr-xtools/testing/selftests/net/forwarding/vxlan_bridge_1q_mc_ul.sh76
-rw-r--r--tools/testing/selftests/net/lib.sh3
-rw-r--r--tools/testing/selftests/net/lib/ksft.h6
-rwxr-xr-xtools/testing/selftests/net/mptcp/pm_netlink.sh4
-rw-r--r--tools/testing/selftests/net/mptcp/pm_nl_ctl.c11
-rwxr-xr-xtools/testing/selftests/net/netfilter/conntrack_clash.sh9
-rw-r--r--tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c13
-rwxr-xr-xtools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh2
-rw-r--r--tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt2
-rw-r--r--tools/testing/selftests/net/tap.c16
-rw-r--r--tools/testing/selftests/net/tfo.c3
-rw-r--r--tools/testing/selftests/net/tls.c2
-rw-r--r--tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore1
-rw-r--r--tools/testing/selftests/sched_ext/runner.c8
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json46
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json78
-rw-r--r--tools/testing/selftests/ublk/Makefile13
-rw-r--r--tools/testing/selftests/ublk/file_backed.c7
-rw-r--r--tools/testing/selftests/ublk/kublk.c64
-rw-r--r--tools/testing/selftests/ublk/kublk.h23
-rw-r--r--tools/testing/selftests/ublk/stripe.c2
-rwxr-xr-xtools/testing/selftests/ublk/test_common.sh21
-rwxr-xr-xtools/testing/selftests/ublk/test_generic_04.sh2
-rwxr-xr-xtools/testing/selftests/ublk/test_generic_05.sh2
-rwxr-xr-xtools/testing/selftests/ublk/test_generic_11.sh2
-rwxr-xr-xtools/testing/selftests/ublk/test_generic_14.sh40
-rwxr-xr-xtools/testing/selftests/ublk/test_generic_15.sh68
-rwxr-xr-xtools/testing/selftests/ublk/test_loop_06.sh25
-rwxr-xr-xtools/testing/selftests/ublk/test_loop_07.sh21
-rwxr-xr-xtools/testing/selftests/ublk/test_null_03.sh24
-rwxr-xr-xtools/testing/selftests/ublk/test_stress_04.sh12
-rwxr-xr-xtools/testing/selftests/ublk/test_stress_05.sh10
-rwxr-xr-xtools/testing/selftests/ublk/test_stress_06.sh39
-rwxr-xr-xtools/testing/selftests/ublk/test_stress_07.sh39
-rwxr-xr-xtools/testing/selftests/ublk/test_stripe_05.sh26
-rwxr-xr-xtools/testing/selftests/ublk/test_stripe_06.sh21
-rw-r--r--tools/testing/selftests/ublk/trace/seq_io.bt3
-rw-r--r--tools/testing/selftests/vfio/lib/include/libvfio/iova_allocator.h1
-rw-r--r--tools/testing/selftests/vfio/lib/iommu.c1
-rw-r--r--tools/testing/selftests/vfio/lib/iova_allocator.c1
-rw-r--r--tools/testing/selftests/vfio/lib/vfio_pci_device.c1
-rw-r--r--tools/testing/selftests/vfio/vfio_dma_mapping_test.c1
-rw-r--r--tools/testing/selftests/vfio/vfio_iommufd_setup_test.c1
-rw-r--r--tools/virtio/Makefile8
-rw-r--r--tools/virtio/linux/compiler.h6
-rw-r--r--tools/virtio/linux/cpumask.h4
-rw-r--r--tools/virtio/linux/device.h8
-rw-r--r--tools/virtio/linux/dma-mapping.h4
-rw-r--r--tools/virtio/linux/kernel.h16
-rw-r--r--tools/virtio/linux/module.h2
-rw-r--r--tools/virtio/linux/ucopysize.h21
-rw-r--r--tools/virtio/linux/virtio.h73
-rw-r--r--tools/virtio/linux/virtio_config.h102
-rw-r--r--tools/virtio/oot-stubs.h10
-rw-r--r--virt/kvm/kvm_main.c17
816 files changed, 6522 insertions, 3254 deletions
diff --git a/.clang-format b/.clang-format
index 2ceca764122f..c7060124a47a 100644
--- a/.clang-format
+++ b/.clang-format
@@ -748,6 +748,7 @@ ForEachMacros:
- 'ynl_attr_for_each_nested'
- 'ynl_attr_for_each_payload'
- 'zorro_for_each_dev'
+ - 'zpci_bus_for_each'
IncludeBlocks: Preserve
IncludeCategories:
diff --git a/.mailmap b/.mailmap
index 84309a39d329..7a6110d0e46d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -127,7 +127,8 @@ Barry Song <baohua@kernel.org> <Baohua.Song@csr.com>
Barry Song <baohua@kernel.org> <barry.song@analog.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
-Bartosz Golaszewski <brgl@bgdev.pl> <bgolaszewski@baylibre.com>
+Bartosz Golaszewski <brgl@kernel.org> <bartosz.golaszewski@linaro.org>
+Bartosz Golaszewski <brgl@kernel.org> <bgolaszewski@baylibre.com>
Ben Dooks <ben-linux@fluff.org> <ben.dooks@simtec.co.uk>
Ben Dooks <ben-linux@fluff.org> <ben.dooks@sifive.com>
Ben Gardner <bgardner@wabtec.com>
@@ -857,7 +858,6 @@ Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
WangYuli <wangyuli@aosc.io> <wangyl5933@chinaunicom.cn>
WangYuli <wangyuli@aosc.io> <wangyuli@deepin.org>
-WangYuli <wangyuli@aosc.io> <wangyuli@uniontech.com>
Weiwen Hu <huweiwen@linux.alibaba.com> <sehuww@mail.scut.edu.cn>
WeiXiong Liao <gmpy.liaowx@gmail.com> <liaoweixiong@allwinnertech.com>
Wen Gong <quic_wgong@quicinc.com> <wgong@codeaurora.org>
diff --git a/CREDITS b/CREDITS
index b735b8c58102..ca75f110edb6 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1987,6 +1987,7 @@ D: netfilter: TCP window tracking code
D: netfilter: raw table
D: netfilter: iprange match
D: netfilter: new logging interfaces
+D: netfilter: ipset
D: netfilter: various other hacks
S: Tata
S: Hungary
diff --git a/Documentation/admin-guide/blockdev/zoned_loop.rst b/Documentation/admin-guide/blockdev/zoned_loop.rst
index 806adde664db..6aa865424ac3 100644
--- a/Documentation/admin-guide/blockdev/zoned_loop.rst
+++ b/Documentation/admin-guide/blockdev/zoned_loop.rst
@@ -134,7 +134,7 @@ MB and a zone capacity of 63 MB::
$ modprobe zloop
$ mkdir -p /var/local/zloop/0
- $ echo "add capacity_mb=2048,zone_size_mb=64,zone_capacity=63MB" > /dev/zloop-control
+ $ echo "add capacity_mb=2048,zone_size_mb=64,zone_capacity_mb=63" > /dev/zloop-control
For the device created (/dev/zloop0), the zone backing files are all created
under the default base directory (/var/local/zloop)::
diff --git a/Documentation/arch/riscv/hwprobe.rst b/Documentation/arch/riscv/hwprobe.rst
index 06c5280b728a..641ec4abb906 100644
--- a/Documentation/arch/riscv/hwprobe.rst
+++ b/Documentation/arch/riscv/hwprobe.rst
@@ -281,6 +281,14 @@ The following keys are defined:
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOP`: The Zicbop extension is supported, as
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
+ * :c:macro:`RISCV_HWPROBE_EXT_ZILSD`: The Zilsd extension is supported as
+ defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
+ load/store pair for RV32 with the main manual") of the riscv-isa-manual.
+
+ * :c:macro:`RISCV_HWPROBE_EXT_ZCLSD`: The Zclsd extension is supported as
+ defined in the RISC-V ISA manual starting from commit f88abf1 ("Integrating
+ load/store pair for RV32 with the main manual") of the riscv-isa-manual.
+
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: Deprecated. Returns similar values to
:c:macro:`RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF`, but the key was
mistakenly classified as a bitmask rather than a value.
diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index 6d36ce86fd8e..dca3875a2435 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -95,26 +95,26 @@ Memory Layout
The traditional memory map for the kernel loader, used for Image or
zImage kernels, typically looks like::
- | |
+ | |
0A0000 +------------------------+
- | Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
+ | Reserved for BIOS | Do not use. Reserved for BIOS EBDA.
09A000 +------------------------+
- | Command line |
- | Stack/heap | For use by the kernel real-mode code.
+ | Command line |
+ | Stack/heap | For use by the kernel real-mode code.
098000 +------------------------+
- | Kernel setup | The kernel real-mode code.
+ | Kernel setup | The kernel real-mode code.
090200 +------------------------+
- | Kernel boot sector | The kernel legacy boot sector.
+ | Kernel boot sector | The kernel legacy boot sector.
090000 +------------------------+
- | Protected-mode kernel | The bulk of the kernel image.
+ | Protected-mode kernel | The bulk of the kernel image.
010000 +------------------------+
- | Boot loader | <- Boot sector entry point 0000:7C00
+ | Boot loader | <- Boot sector entry point 0000:7C00
001000 +------------------------+
- | Reserved for MBR/BIOS |
+ | Reserved for MBR/BIOS |
000800 +------------------------+
- | Typically used by MBR |
+ | Typically used by MBR |
000600 +------------------------+
- | BIOS use only |
+ | BIOS use only |
000000 +------------------------+
When using bzImage, the protected-mode kernel was relocated to
@@ -142,27 +142,27 @@ above the 0x9A000 point; too many BIOSes will break above that point.
For a modern bzImage kernel with boot protocol version >= 2.02, a
memory layout like the following is suggested::
- ~ ~
- | Protected-mode kernel |
+ ~ ~
+ | Protected-mode kernel |
100000 +------------------------+
- | I/O memory hole |
+ | I/O memory hole |
0A0000 +------------------------+
- | Reserved for BIOS | Leave as much as possible unused
- ~ ~
- | Command line | (Can also be below the X+10000 mark)
+ | Reserved for BIOS | Leave as much as possible unused
+ ~ ~
+ | Command line | (Can also be below the X+10000 mark)
X+10000 +------------------------+
- | Stack/heap | For use by the kernel real-mode code.
+ | Stack/heap | For use by the kernel real-mode code.
X+08000 +------------------------+
- | Kernel setup | The kernel real-mode code.
- | Kernel boot sector | The kernel legacy boot sector.
+ | Kernel setup | The kernel real-mode code.
+ | Kernel boot sector | The kernel legacy boot sector.
X +------------------------+
- | Boot loader | <- Boot sector entry point 0000:7C00
+ | Boot loader | <- Boot sector entry point 0000:7C00
001000 +------------------------+
- | Reserved for MBR/BIOS |
+ | Reserved for MBR/BIOS |
000800 +------------------------+
- | Typically used by MBR |
+ | Typically used by MBR |
000600 +------------------------+
- | BIOS use only |
+ | BIOS use only |
000000 +------------------------+
... where the address X is as low as the design of the boot loader permits.
@@ -433,7 +433,7 @@ Protocol: 2.00+
Assigned boot loader IDs:
- == =======================================
+ ==== =======================================
0x0 LILO
(0x00 reserved for pre-2.00 bootloader)
0x1 Loadlin
@@ -456,7 +456,7 @@ Protocol: 2.00+
<http://sebastian-plotz.blogspot.de>
0x12 OVMF UEFI virtualization stack
0x13 barebox
- == =======================================
+ ==== =======================================
Please contact <hpa@zytor.com> if you need a bootloader ID value assigned.
@@ -809,12 +809,12 @@ Protocol: 2.09+
as follow::
struct setup_data {
- __u64 next;
- __u32 type;
- __u32 len;
- __u8 data[];
+ __u64 next;
+ __u32 type;
+ __u32 len;
+ __u8 data[];
}
-
+
Where, the next is a 64-bit physical pointer to the next node of
linked list, the next field of the last node is 0; the type is used
to identify the contents of data; the len is the length of data
@@ -835,10 +835,10 @@ Protocol: 2.09+
protocol 2.15::
struct setup_indirect {
- __u32 type;
- __u32 reserved; /* Reserved, must be set to zero. */
- __u64 len;
- __u64 addr;
+ __u32 type;
+ __u32 reserved; /* Reserved, must be set to zero. */
+ __u64 len;
+ __u64 addr;
};
The type member is a SETUP_INDIRECT | SETUP_* type. However, it cannot be
@@ -850,15 +850,15 @@ Protocol: 2.09+
In this case setup_data and setup_indirect will look like this::
struct setup_data {
- .next = 0, /* or <addr_of_next_setup_data_struct> */
- .type = SETUP_INDIRECT,
- .len = sizeof(setup_indirect),
- .data[sizeof(setup_indirect)] = (struct setup_indirect) {
- .type = SETUP_INDIRECT | SETUP_E820_EXT,
- .reserved = 0,
- .len = <len_of_SETUP_E820_EXT_data>,
- .addr = <addr_of_SETUP_E820_EXT_data>,
- },
+ .next = 0, /* or <addr_of_next_setup_data_struct> */
+ .type = SETUP_INDIRECT,
+ .len = sizeof(setup_indirect),
+ .data[sizeof(setup_indirect)] = (struct setup_indirect) {
+ .type = SETUP_INDIRECT | SETUP_E820_EXT,
+ .reserved = 0,
+ .len = <len_of_SETUP_E820_EXT_data>,
+ .addr = <addr_of_SETUP_E820_EXT_data>,
+ },
}
.. note::
@@ -897,11 +897,11 @@ Offset/size: 0x260/4
The kernel runtime start address is determined by the following algorithm::
if (relocatable_kernel) {
- if (load_address < pref_address)
- load_address = pref_address;
- runtime_start = align_up(load_address, kernel_alignment);
+ if (load_address < pref_address)
+ load_address = pref_address;
+ runtime_start = align_up(load_address, kernel_alignment);
} else {
- runtime_start = pref_address;
+ runtime_start = pref_address;
}
Hence the necessary memory window location and size can be estimated by
@@ -975,22 +975,22 @@ after kernel_info_var_len_data label. Each chunk of variable size data has to
be prefixed with header/magic and its size, e.g.::
kernel_info:
- .ascii "LToP" /* Header, Linux top (structure). */
- .long kernel_info_var_len_data - kernel_info
- .long kernel_info_end - kernel_info
- .long 0x01234567 /* Some fixed size data for the bootloaders. */
+ .ascii "LToP" /* Header, Linux top (structure). */
+ .long kernel_info_var_len_data - kernel_info
+ .long kernel_info_end - kernel_info
+ .long 0x01234567 /* Some fixed size data for the bootloaders. */
kernel_info_var_len_data:
example_struct: /* Some variable size data for the bootloaders. */
- .ascii "0123" /* Header/Magic. */
- .long example_struct_end - example_struct
- .ascii "Struct"
- .long 0x89012345
+ .ascii "0123" /* Header/Magic. */
+ .long example_struct_end - example_struct
+ .ascii "Struct"
+ .long 0x89012345
example_struct_end:
example_strings: /* Some variable size data for the bootloaders. */
- .ascii "ABCD" /* Header/Magic. */
- .long example_strings_end - example_strings
- .asciz "String_0"
- .asciz "String_1"
+ .ascii "ABCD" /* Header/Magic. */
+ .long example_strings_end - example_strings
+ .asciz "String_0"
+ .asciz "String_1"
example_strings_end:
kernel_info_end:
@@ -1132,53 +1132,53 @@ Such a boot loader should enter the following fields in the header::
unsigned long base_ptr; /* base address for real-mode segment */
if (setup_sects == 0)
- setup_sects = 4;
+ setup_sects = 4;
if (protocol >= 0x0200) {
- type_of_loader = <type code>;
- if (loading_initrd) {
- ramdisk_image = <initrd_address>;
- ramdisk_size = <initrd_size>;
- }
-
- if (protocol >= 0x0202 && loadflags & 0x01)
- heap_end = 0xe000;
- else
- heap_end = 0x9800;
-
- if (protocol >= 0x0201) {
- heap_end_ptr = heap_end - 0x200;
- loadflags |= 0x80; /* CAN_USE_HEAP */
- }
-
- if (protocol >= 0x0202) {
- cmd_line_ptr = base_ptr + heap_end;
- strcpy(cmd_line_ptr, cmdline);
- } else {
- cmd_line_magic = 0xA33F;
- cmd_line_offset = heap_end;
- setup_move_size = heap_end + strlen(cmdline) + 1;
- strcpy(base_ptr + cmd_line_offset, cmdline);
- }
+ type_of_loader = <type code>;
+ if (loading_initrd) {
+ ramdisk_image = <initrd_address>;
+ ramdisk_size = <initrd_size>;
+ }
+
+ if (protocol >= 0x0202 && loadflags & 0x01)
+ heap_end = 0xe000;
+ else
+ heap_end = 0x9800;
+
+ if (protocol >= 0x0201) {
+ heap_end_ptr = heap_end - 0x200;
+ loadflags |= 0x80; /* CAN_USE_HEAP */
+ }
+
+ if (protocol >= 0x0202) {
+ cmd_line_ptr = base_ptr + heap_end;
+ strcpy(cmd_line_ptr, cmdline);
+ } else {
+ cmd_line_magic = 0xA33F;
+ cmd_line_offset = heap_end;
+ setup_move_size = heap_end + strlen(cmdline) + 1;
+ strcpy(base_ptr + cmd_line_offset, cmdline);
+ }
} else {
- /* Very old kernel */
+ /* Very old kernel */
- heap_end = 0x9800;
+ heap_end = 0x9800;
- cmd_line_magic = 0xA33F;
- cmd_line_offset = heap_end;
+ cmd_line_magic = 0xA33F;
+ cmd_line_offset = heap_end;
- /* A very old kernel MUST have its real-mode code loaded at 0x90000 */
- if (base_ptr != 0x90000) {
- /* Copy the real-mode kernel */
- memcpy(0x90000, base_ptr, (setup_sects + 1) * 512);
- base_ptr = 0x90000; /* Relocated */
- }
+ /* A very old kernel MUST have its real-mode code loaded at 0x90000 */
+ if (base_ptr != 0x90000) {
+ /* Copy the real-mode kernel */
+ memcpy(0x90000, base_ptr, (setup_sects + 1) * 512);
+ base_ptr = 0x90000; /* Relocated */
+ }
- strcpy(0x90000 + cmd_line_offset, cmdline);
+ strcpy(0x90000 + cmd_line_offset, cmdline);
- /* It is recommended to clear memory up to the 32K mark */
- memset(0x90000 + (setup_sects + 1) * 512, 0, (64 - (setup_sects + 1)) * 512);
+ /* It is recommended to clear memory up to the 32K mark */
+ memset(0x90000 + (setup_sects + 1) * 512, 0, (64 - (setup_sects + 1)) * 512);
}
diff --git a/Documentation/devicetree/bindings/arm/arm,integrator.yaml b/Documentation/devicetree/bindings/arm/arm,integrator.yaml
index 1bdbd1b7ee38..8fe22185a337 100644
--- a/Documentation/devicetree/bindings/arm/arm,integrator.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,integrator.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Integrator Boards
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |+
These were the first ARM platforms officially supported by ARM Ltd.
diff --git a/Documentation/devicetree/bindings/arm/arm,realview.yaml b/Documentation/devicetree/bindings/arm/arm,realview.yaml
index 3c5f1688dbd7..0b3133ecddac 100644
--- a/Documentation/devicetree/bindings/arm/arm,realview.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,realview.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM RealView Boards
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |+
The ARM RealView series of reference designs were built to explore the Arm11,
diff --git a/Documentation/devicetree/bindings/arm/arm,scu.yaml b/Documentation/devicetree/bindings/arm/arm,scu.yaml
index dae2aa27e641..f735b7fb8e1c 100644
--- a/Documentation/devicetree/bindings/arm/arm,scu.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,scu.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Snoop Control Unit (SCU)
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
As part of the MPCore complex, Cortex-A5 and Cortex-A9 are provided
diff --git a/Documentation/devicetree/bindings/arm/arm,versatile-sysreg.yaml b/Documentation/devicetree/bindings/arm/arm,versatile-sysreg.yaml
index 3b060c36b90c..e72dc45c1afa 100644
--- a/Documentation/devicetree/bindings/arm/arm,versatile-sysreg.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,versatile-sysreg.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Arm Versatile system registers
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
This is a system control registers block, providing multiple low level
diff --git a/Documentation/devicetree/bindings/arm/arm,versatile.yaml b/Documentation/devicetree/bindings/arm/arm,versatile.yaml
index 7a3caf6af200..c777e455d038 100644
--- a/Documentation/devicetree/bindings/arm/arm,versatile.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,versatile.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Versatile Boards
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |+
The ARM Versatile boards are two variants of ARM926EJ-S evaluation boards
diff --git a/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml b/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
index 4cdca5320544..6430218ba1ce 100644
--- a/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
@@ -8,7 +8,7 @@ title: ARM Versatile Express and Juno Boards
maintainers:
- Sudeep Holla <sudeep.holla@arm.com>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |+
ARM's Versatile Express platform were built as reference designs for exploring
diff --git a/Documentation/devicetree/bindings/arm/gemini.yaml b/Documentation/devicetree/bindings/arm/gemini.yaml
index f6a0b675830f..fc092962ab56 100644
--- a/Documentation/devicetree/bindings/arm/gemini.yaml
+++ b/Documentation/devicetree/bindings/arm/gemini.yaml
@@ -20,7 +20,7 @@ description: |
Many of the IP blocks used in the SoC comes from Faraday Technology.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
index b7b430896596..0f1bf634a98a 100644
--- a/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
+++ b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/arm/ux500.yaml b/Documentation/devicetree/bindings/arm/ux500.yaml
index b42d20fa4359..3a8611e5786e 100644
--- a/Documentation/devicetree/bindings/arm/ux500.yaml
+++ b/Documentation/devicetree/bindings/arm/ux500.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ux500 platforms
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/ata/ata-generic.yaml b/Documentation/devicetree/bindings/ata/ata-generic.yaml
index 0697927f3d7e..9da341ea091e 100644
--- a/Documentation/devicetree/bindings/ata/ata-generic.yaml
+++ b/Documentation/devicetree/bindings/ata/ata-generic.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic Parallel ATA Controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
Generic Parallel ATA controllers supporting PIO modes only.
diff --git a/Documentation/devicetree/bindings/ata/cortina,gemini-sata-bridge.yaml b/Documentation/devicetree/bindings/ata/cortina,gemini-sata-bridge.yaml
index 529093666508..66de6d4769c1 100644
--- a/Documentation/devicetree/bindings/ata/cortina,gemini-sata-bridge.yaml
+++ b/Documentation/devicetree/bindings/ata/cortina,gemini-sata-bridge.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cortina Systems Gemini SATA Bridge
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Gemini SATA bridge in a SoC-internal PATA to SATA bridge that
diff --git a/Documentation/devicetree/bindings/ata/faraday,ftide010.yaml b/Documentation/devicetree/bindings/ata/faraday,ftide010.yaml
index fa16f3767c6a..32e11d8a0a3b 100644
--- a/Documentation/devicetree/bindings/ata/faraday,ftide010.yaml
+++ b/Documentation/devicetree/bindings/ata/faraday,ftide010.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FTIDE010 PATA controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This controller is the first Faraday IDE interface block, used in the
diff --git a/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml b/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml
index 378692010c56..894a8b9eb910 100644
--- a/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml
+++ b/Documentation/devicetree/bindings/ata/intel,ixp4xx-compact-flash.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx CompactFlash Card Controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The IXP4xx network processors have a CompactFlash interface that presents
diff --git a/Documentation/devicetree/bindings/ata/pata-common.yaml b/Documentation/devicetree/bindings/ata/pata-common.yaml
index 4e867dd4d402..cee4bb7eb0b9 100644
--- a/Documentation/devicetree/bindings/ata/pata-common.yaml
+++ b/Documentation/devicetree/bindings/ata/pata-common.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Common Properties for Parallel AT attachment (PATA) controllers
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This document defines device tree properties common to most Parallel
diff --git a/Documentation/devicetree/bindings/ata/sata-common.yaml b/Documentation/devicetree/bindings/ata/sata-common.yaml
index 58c9342b9925..667f48c33195 100644
--- a/Documentation/devicetree/bindings/ata/sata-common.yaml
+++ b/Documentation/devicetree/bindings/ata/sata-common.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Common Properties for Serial AT attachment (SATA) controllers
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This document defines device tree properties common to most Serial
diff --git a/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml b/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
index 439f7b811a94..51d68a778b5c 100644
--- a/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
+++ b/Documentation/devicetree/bindings/auxdisplay/arm,versatile-lcd.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Versatile Character LCD
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Rob Herring <robh@kernel.org>
description:
diff --git a/Documentation/devicetree/bindings/clock/sprd,sc9860-clk.yaml b/Documentation/devicetree/bindings/clock/sprd,sc9860-clk.yaml
index 502cd723511f..b131390207d6 100644
--- a/Documentation/devicetree/bindings/clock/sprd,sc9860-clk.yaml
+++ b/Documentation/devicetree/bindings/clock/sprd,sc9860-clk.yaml
@@ -114,25 +114,6 @@ allOf:
- reg
properties:
sprd,syscon: false
- - if:
- properties:
- compatible:
- contains:
- enum:
- - sprd,sc9860-agcp-gate
- - sprd,sc9860-aon-gate
- - sprd,sc9860-apahb-gate
- - sprd,sc9860-apapb-gate
- - sprd,sc9860-cam-gate
- - sprd,sc9860-disp-gate
- - sprd,sc9860-pll
- - sprd,sc9860-pmu-gate
- - sprd,sc9860-vsp-gate
- then:
- required:
- - sprd,syscon
- properties:
- reg: false
additionalProperties: false
@@ -142,13 +123,6 @@ examples:
#address-cells = <2>;
#size-cells = <2>;
- pmu-gate {
- compatible = "sprd,sc9860-pmu-gate";
- clocks = <&ext_26m>;
- #clock-cells = <1>;
- sprd,syscon = <&pmu_regs>;
- };
-
clock-controller@20000000 {
compatible = "sprd,sc9860-ap-clk";
reg = <0 0x20000000 0 0x400>;
diff --git a/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml b/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml
index 2150307219a0..4ebfa5a8d524 100644
--- a/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml
+++ b/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml
@@ -8,7 +8,7 @@ title: ST-Ericsson DB8500 (U8500) clocks
maintainers:
- Ulf Hansson <ulf.hansson@linaro.org>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: While named "U8500 clocks" these clocks are inside the
DB8500 digital baseband system-on-chip and its siblings such as
diff --git a/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml b/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml
index a4006237aa89..fd20b8197207 100644
--- a/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml
+++ b/Documentation/devicetree/bindings/crypto/intel,ixp4xx-crypto.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx cryptographic engine
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Intel IXP4xx cryptographic engine makes use of the IXP4xx NPE
diff --git a/Documentation/devicetree/bindings/display/dsi-controller.yaml b/Documentation/devicetree/bindings/display/dsi-controller.yaml
index bb4d6e9e7d0c..850b86fe03cc 100644
--- a/Documentation/devicetree/bindings/display/dsi-controller.yaml
+++ b/Documentation/devicetree/bindings/display/dsi-controller.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Common Properties for DSI Display Panels
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This document defines device tree properties common to DSI, Display
diff --git a/Documentation/devicetree/bindings/display/faraday,tve200.yaml b/Documentation/devicetree/bindings/display/faraday,tve200.yaml
index e2ee77767321..b09628b69177 100644
--- a/Documentation/devicetree/bindings/display/faraday,tve200.yaml
+++ b/Documentation/devicetree/bindings/display/faraday,tve200.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday TV Encoder TVE200
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/display/panel/arm,rtsm-display.yaml b/Documentation/devicetree/bindings/display/panel/arm,rtsm-display.yaml
index 4ad484f09ba3..fc04558fcc8d 100644
--- a/Documentation/devicetree/bindings/display/panel/arm,rtsm-display.yaml
+++ b/Documentation/devicetree/bindings/display/panel/arm,rtsm-display.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Arm RTSM Virtual Platforms Display
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml b/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml
index c9958f824d9a..b6c18e7283cd 100644
--- a/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml
+++ b/Documentation/devicetree/bindings/display/panel/arm,versatile-tft-panel.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Versatile TFT Panels
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
These panels are connected to the daughterboards found on the
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
index 44423465f6e3..4bdc33d12306 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9322.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ilitek ILI9322 TFT panel driver with SPI control bus
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This is a driver for 320x240 TFT panels, accepting a variety of input
diff --git a/Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml b/Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
index bb50fd5506c3..b39fd0c5a48a 100644
--- a/Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
+++ b/Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Novatek NT35510-based display panels
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
index 7ce8540551f9..74c2a617c2ff 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
@@ -11,7 +11,7 @@ description: The LMS380KF01 is a 480x800 DPI display panel from Samsung Mobile
used with internal or external backlight control.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
index 9363032883de..4cecf502a150 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
@@ -10,7 +10,7 @@ description: The datasheet claims this is based around a display controller
named DB7430 with a separate backlight controller.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6d16d0.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6d16d0.yaml
index 2af5bc47323f..0872476a8ac9 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6d16d0.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6d16d0.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S6D16D0 4" 864x480 AMOLED panel
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml b/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml
index fd778a20f760..64fa086730b0 100644
--- a/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml
@@ -12,7 +12,7 @@ description: The Sony ACX424AKP and ACX424AKM are panels built around
AKP.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/ti,nspire.yaml b/Documentation/devicetree/bindings/display/panel/ti,nspire.yaml
index 5c5a3b519e31..fc722f706ad7 100644
--- a/Documentation/devicetree/bindings/display/panel/ti,nspire.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ti,nspire.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments NSPIRE Display Panels
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: panel-common.yaml#
diff --git a/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml b/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
index 99db268eb9b3..e5f3108cde5a 100644
--- a/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
+++ b/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: TPO TPG110 Panel
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Thierry Reding <thierry.reding@gmail.com>
description: |+
diff --git a/Documentation/devicetree/bindings/display/ste,mcde.yaml b/Documentation/devicetree/bindings/display/ste,mcde.yaml
index 564ea845c82e..7a12d0b817e6 100644
--- a/Documentation/devicetree/bindings/display/ste,mcde.yaml
+++ b/Documentation/devicetree/bindings/display/ste,mcde.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST-Ericsson Multi Channel Display Engine MCDE
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
index 361e9cae6896..38fcee91211e 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
@@ -84,8 +84,7 @@ properties:
maxItems: 1
description: phandle to the associated power domain
- dma-coherent:
- type: boolean
+ dma-coherent: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
diff --git a/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml
index fad7cba58d39..65ae8a1c3998 100644
--- a/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml
+++ b/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml
@@ -103,8 +103,7 @@ properties:
maxItems: 1
description: phandle to the associated power domain
- dma-coherent:
- type: boolean
+ dma-coherent: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
diff --git a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml
index 8b42d9880400..607da11e7baa 100644
--- a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml
+++ b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST-Ericsson DMA40 DMA Engine
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: dma-controller.yaml#
diff --git a/Documentation/devicetree/bindings/extcon/fcs,fsa880.yaml b/Documentation/devicetree/bindings/extcon/fcs,fsa880.yaml
index ef6a246a1337..bff3fd5f7f4e 100644
--- a/Documentation/devicetree/bindings/extcon/fcs,fsa880.yaml
+++ b/Documentation/devicetree/bindings/extcon/fcs,fsa880.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Fairchild Semiconductor FSA880, FSA9480 and compatibles
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
The FSA880 and FSA9480 are USB port accessory detectors and switches.
diff --git a/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml b/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
index 50f1f08744a1..4d66ef483522 100644
--- a/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
+++ b/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx Network Processing Engine
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
On the IXP4xx SoCs, the Network Processing Engine (NPE) is a small
diff --git a/Documentation/devicetree/bindings/gnss/brcm,bcm4751.yaml b/Documentation/devicetree/bindings/gnss/brcm,bcm4751.yaml
index 089166089498..c34b86bb7f6f 100644
--- a/Documentation/devicetree/bindings/gnss/brcm,bcm4751.yaml
+++ b/Documentation/devicetree/bindings/gnss/brcm,bcm4751.yaml
@@ -8,7 +8,7 @@ title: Broadcom BCM4751 family GNSS Receiver
maintainers:
- Johan Hovold <johan@kernel.org>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
Broadcom GPS chips can be used over the UART or I2C bus. The UART
diff --git a/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.yaml b/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.yaml
index 640da5b9b0cc..3a6a47f12982 100644
--- a/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.yaml
+++ b/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FTGPIO010 GPIO Controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/gpio/gpio-consumer-common.yaml b/Documentation/devicetree/bindings/gpio/gpio-consumer-common.yaml
index 40d0be31e200..fa0148758b4b 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-consumer-common.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-consumer-common.yaml
@@ -8,7 +8,7 @@ title: Common GPIO lines
maintainers:
- Bartosz Golaszewski <brgl@bgdev.pl>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
Pay attention to using proper GPIO flag (e.g. GPIO_ACTIVE_LOW) for the GPIOs
diff --git a/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml b/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml
index 3a1079d6ee20..ebdb7ee5b790 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-ep9301.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: EP93xx GPIO controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Bartosz Golaszewski <brgl@bgdev.pl>
- Nikita Shubin <nikita.shubin@maquefel.me>
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
index b4d55bf6a285..ee5d5d25ae82 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic MMIO GPIO
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Bartosz Golaszewski <brgl@bgdev.pl>
description:
diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
index bfcb1f364c3a..2a980c0ed86f 100644
--- a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.yaml
@@ -22,7 +22,7 @@ description: |
and this can be enabled by a special flag.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/gpio/mrvl-gpio.yaml b/Documentation/devicetree/bindings/gpio/mrvl-gpio.yaml
index 65155bb701a9..7f420b9c0480 100644
--- a/Documentation/devicetree/bindings/gpio/mrvl-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/mrvl-gpio.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Marvell PXA GPIO controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Bartosz Golaszewski <bgolaszewski@baylibre.com>
- Rob Herring <robh@kernel.org>
diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml b/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml
index c51e10680c0a..4d970e55104b 100644
--- a/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM PL061 GPIO controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Rob Herring <robh@kernel.org>
# We need a select here so we don't match all nodes with 'arm,primecell'
diff --git a/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml b/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
index b3e8951959b5..40b4a7551449 100644
--- a/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml
@@ -12,7 +12,7 @@ description:
with pinctrl-nomadik.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml b/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml
index 4555f1644a4d..66dd602e797d 100644
--- a/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/st,stmpe-gpio.yaml
@@ -14,7 +14,7 @@ description:
GPIO portions of these expanders.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
index 225a6e1b7fcd..86ef68985317 100644
--- a/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
+++ b/Documentation/devicetree/bindings/gpu/img,powervr-rogue.yaml
@@ -20,7 +20,9 @@ properties:
- const: img,img-gx6250
- const: img,img-rogue
- items:
- - const: renesas,r8a77965-gpu
+ - enum:
+ - renesas,r8a77965-gpu
+ - renesas,r8a779a0-gpu
- const: img,img-ge7800
- const: img,img-rogue
- items:
diff --git a/Documentation/devicetree/bindings/hwmon/ntc-thermistor.yaml b/Documentation/devicetree/bindings/hwmon/ntc-thermistor.yaml
index dc8bc4c6df34..efd10bcfb082 100644
--- a/Documentation/devicetree/bindings/hwmon/ntc-thermistor.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ntc-thermistor.yaml
@@ -6,7 +6,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: NTC thermistor temperature sensors
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
Thermistors with negative temperature coefficient (NTC) are resistors that
diff --git a/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml b/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml
index 6971ecb314eb..d97b0e698477 100644
--- a/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml
+++ b/Documentation/devicetree/bindings/hwmon/winbond,w83781d.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Winbond W83781 and compatible hardware monitor IC
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/i2c/arm,i2c-versatile.yaml b/Documentation/devicetree/bindings/i2c/arm,i2c-versatile.yaml
index e58465d1b0c8..26026dfd788a 100644
--- a/Documentation/devicetree/bindings/i2c/arm,i2c-versatile.yaml
+++ b/Documentation/devicetree/bindings/i2c/arm,i2c-versatile.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: I2C Controller on ARM Ltd development platforms
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: /schemas/i2c/i2c-controller.yaml#
diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
index 33852a5ffca8..a3fe1eea6aec 100644
--- a/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
@@ -38,6 +38,7 @@ properties:
- qcom,sm8450-cci
- qcom,sm8550-cci
- qcom,sm8650-cci
+ - qcom,sm8750-cci
- qcom,x1e80100-cci
- const: qcom,msm8996-cci # CCI v2
@@ -132,6 +133,7 @@ allOf:
enum:
- qcom,kaanapali-cci
- qcom,qcm2290-cci
+ - qcom,sm8750-cci
then:
properties:
clocks:
diff --git a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
index d904191bb0c6..914200188809 100644
--- a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
@@ -34,8 +34,15 @@ properties:
- const: snps,designware-i2c
- description: Baikal-T1 SoC System I2C controller
const: baikal,bt1-sys-i2c
+ - description: Mobileye EyeQ DesignWare I2C controller
+ items:
+ - enum:
+ - mobileye,eyeq7h-i2c
+ - const: mobileye,eyeq6lplus-i2c
+ - const: snps,designware-i2c
- items:
- enum:
+ - mobileye,eyeq6lplus-i2c
- mscc,ocelot-i2c
- sophgo,sg2044-i2c
- thead,th1520-i2c
diff --git a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
index 012402debfeb..63a459c63f6a 100644
--- a/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/st,nomadik-i2c.yaml
@@ -12,7 +12,7 @@ description: The Nomadik I2C host controller began its life in the ST
DB8500 after the merge of these two companies wireless divisions.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
# Need a custom select here or 'arm,primecell' will match on lots of nodes
select:
diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
index 85c9537f1f02..c1387e02eb82 100644
--- a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bosch BMA255 and Similar Accelerometers
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Stephan Gerhold <stephan@gerhold.net>
description:
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml
index 58ea1ca4a5ee..c978c3a3e31a 100644
--- a/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/qcom,pm8018-adc.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm's PM8xxx voltage XOADC
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Qualcomm PM8xxx PMICs contain a HK/XO ADC (Housekeeping/Crystal
diff --git a/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml b/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml
index f3242dc0e7e6..3a307ac50aa7 100644
--- a/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml
+++ b/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Invensense MPU-3050 Gyroscope
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/iio/light/capella,cm3605.yaml b/Documentation/devicetree/bindings/iio/light/capella,cm3605.yaml
index c63b79c3351b..01376c386a03 100644
--- a/Documentation/devicetree/bindings/iio/light/capella,cm3605.yaml
+++ b/Documentation/devicetree/bindings/iio/light/capella,cm3605.yaml
@@ -8,7 +8,7 @@ title:
Capella Microsystems CM3605 Ambient Light and Short Distance Proximity Sensor
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Kevin Tsai <ktsai@capellamicro.com>
description: |
diff --git a/Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml b/Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml
index f8a932be0d10..99bddf31cbed 100644
--- a/Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml
+++ b/Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sharp GP2AP002A00F and GP2AP002S00F proximity and ambient light sensors
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
Proximity and ambient light sensor with IR LED for the proximity
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8974.yaml b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8974.yaml
index cefb70def188..f6b4d9874190 100644
--- a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8974.yaml
+++ b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8974.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Asahi Kasei AK8974 magnetometer sensor
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/yamaha,yas530.yaml b/Documentation/devicetree/bindings/iio/magnetometer/yamaha,yas530.yaml
index 877226e9219b..5cbf60f3b08b 100644
--- a/Documentation/devicetree/bindings/iio/magnetometer/yamaha,yas530.yaml
+++ b/Documentation/devicetree/bindings/iio/magnetometer/yamaha,yas530.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Yamaha YAS530 family of magnetometer sensors
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
The Yamaha YAS530 magnetometers is a line of 3-axis magnetometers
diff --git a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml
index e955eb8e8797..a1a958215cdb 100644
--- a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml
+++ b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml
@@ -14,7 +14,7 @@ description: The STMicroelectronics sensor devices are pretty straight-forward
maintainers:
- Denis Ciocca <denis.ciocca@st.com>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml b/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
index d79b254f1cde..9bf07acea599 100644
--- a/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
+++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
@@ -8,7 +8,7 @@ title: Atmel maXTouch touchscreen/touchpad
maintainers:
- Nick Dyer <nick@shmanahar.org>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
Atmel maXTouch touchscreen or touchpads such as the mXT244
diff --git a/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma140.yaml b/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma140.yaml
index 86a6d18f952a..afeab49a9544 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma140.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma140.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cypress CY8CTMA140 series touchscreen controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: touchscreen.yaml#
diff --git a/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma340.yaml b/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma340.yaml
index 4dfbb93678b5..a0b8c12977a1 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma340.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/cypress,cy8ctma340.yaml
@@ -12,7 +12,7 @@ description: The Cypress CY8CTMA340 series (also known as "CYTTSP" after
maintainers:
- Javier Martinez Canillas <javier@dowhile0.org>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: touchscreen.yaml#
diff --git a/Documentation/devicetree/bindings/input/touchscreen/melfas,mms114.yaml b/Documentation/devicetree/bindings/input/touchscreen/melfas,mms114.yaml
index 90ebd4f8354c..a8a93f755458 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/melfas,mms114.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/melfas,mms114.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Melfas MMS114 family touchscreen controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: touchscreen.yaml#
diff --git a/Documentation/devicetree/bindings/input/touchscreen/zinitix,bt400.yaml b/Documentation/devicetree/bindings/input/touchscreen/zinitix,bt400.yaml
index 3f663ce3e44e..f1ce837b16df 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/zinitix,bt400.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/zinitix,bt400.yaml
@@ -12,7 +12,7 @@ description: The Zinitix BT4xx and BT5xx series of touchscreen controllers
maintainers:
- Michael Srba <Michael.Srba@seznam.cz>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: touchscreen.yaml#
diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.yaml
index 8d581b3aac3a..42ab873665e1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Versatile FPGA IRQ Controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
One or more FPGA IRQ controllers can be synthesized in an ARM reference board
diff --git a/Documentation/devicetree/bindings/interrupt-controller/faraday,ftintc010.yaml b/Documentation/devicetree/bindings/interrupt-controller/faraday,ftintc010.yaml
index 980e5c45f25b..e6495acea038 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/faraday,ftintc010.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/faraday,ftintc010.yaml
@@ -6,7 +6,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FTINTC010 interrupt controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
This interrupt controller is a stock IP block from Faraday Technology found
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
index a02a6b5af205..c375e08ba410 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx XScale Networking Processors Interrupt Controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This interrupt controller is found in the Intel IXP4xx processors.
diff --git a/Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml b/Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml
index 73fa59e62181..e7207eb26584 100644
--- a/Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml
+++ b/Documentation/devicetree/bindings/leds/backlight/kinetic,ktd253.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Kinetic Technologies KTD253 and KTD259 one-wire backlight
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Kinetic Technologies KTD253 and KTD259 are white LED backlights
diff --git a/Documentation/devicetree/bindings/leds/register-bit-led.yaml b/Documentation/devicetree/bindings/leds/register-bit-led.yaml
index 20930d327ae9..a6bafc96bd0c 100644
--- a/Documentation/devicetree/bindings/leds/register-bit-led.yaml
+++ b/Documentation/devicetree/bindings/leds/register-bit-led.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Register Bit LEDs
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |+
Register bit leds are used with syscon multifunctional devices where single
diff --git a/Documentation/devicetree/bindings/leds/regulator-led.yaml b/Documentation/devicetree/bindings/leds/regulator-led.yaml
index 4ef7b96e9a08..75ee87d4a786 100644
--- a/Documentation/devicetree/bindings/leds/regulator-led.yaml
+++ b/Documentation/devicetree/bindings/leds/regulator-led.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Regulator LEDs
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
Regulator LEDs are powered by a single regulator such that they can
diff --git a/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
index 68c328eec03b..0356371a6b01 100644
--- a/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
+++ b/Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Richtek RT8515 1.5A dual channel LED driver
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Richtek RT8515 is a dual channel (two mode) LED driver that
diff --git a/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-bus-controller.yaml b/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-bus-controller.yaml
index 3049d6bb0b1f..2a4bf905a369 100644
--- a/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-bus-controller.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-bus-controller.yaml
@@ -12,7 +12,7 @@ description: |
including IXP42x, IXP43x, IXP45x and IXP46x.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-peripheral-props.yaml b/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-peripheral-props.yaml
index d1479a7b9c8d..020fa49c3454 100644
--- a/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion-peripheral-props.yaml
@@ -12,7 +12,7 @@ description:
including IXP42x, IXP43x, IXP45x and IXP46x.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
intel,ixp4xx-eb-t1:
diff --git a/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml b/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml
index 46b164ae0831..7f3b1b77293c 100644
--- a/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/arm,dev-platforms-syscon.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Arm Ltd Developer Platforms System Controllers
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
The Arm Ltd Integrator, Realview, and Versatile families of developer
diff --git a/Documentation/devicetree/bindings/mfd/st,stmpe.yaml b/Documentation/devicetree/bindings/mfd/st,stmpe.yaml
index b77cc3f3075d..df43878fbe18 100644
--- a/Documentation/devicetree/bindings/mfd/st,stmpe.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stmpe.yaml
@@ -12,7 +12,7 @@ description: STMicroelectronics Port Expander (STMPE) is a series of slow
peripherals connected to SPI or I2C.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
diff --git a/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml b/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml
index ce5e845ab5c5..0fdfbfdfe88a 100644
--- a/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml
+++ b/Documentation/devicetree/bindings/mfd/stericsson,ab8500.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST-Ericsson Analog Baseband AB8500 and AB8505
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
the AB8500 "Analog Baseband" is the mixed-signals integrated circuit
diff --git a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
index d6c13779d44e..4edd4a3bab88 100644
--- a/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
+++ b/Documentation/devicetree/bindings/mfd/stericsson,db8500-prcmu.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST-Ericsson DB8500 PRCMU - Power Reset and Control Management Unit
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
The DB8500 Power Reset and Control Management Unit is an XP70 8-bit
diff --git a/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
index aab89946b04f..1198d87d0ab6 100644
--- a/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
+++ b/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx AHB Queue Manager
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The IXP4xx AHB Queue Manager maintains queues as circular buffers in
diff --git a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml
index 8f62e2c7fa64..f90fd73904a2 100644
--- a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml
+++ b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM PrimeCell MultiMedia Card Interface (MMCI) PL180 and PL181
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Ulf Hansson <ulf.hansson@linaro.org>
description:
diff --git a/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
index 9fce8cd7b0b6..d24950ccea95 100644
--- a/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
@@ -41,7 +41,7 @@ properties:
patternProperties:
"^sdhci@[0-9a-f]+$":
type: object
- $ref: mmc-controller.yaml
+ $ref: sdhci-common.yaml
unevaluatedProperties: false
properties:
diff --git a/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml b/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
index 97618847ee35..e9b1a6869910 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM Firmware Suite (AFS) Partitions
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
select: false
diff --git a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
index ba7445cd69e8..e3978d2bc056 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
@@ -14,7 +14,7 @@ description: The FLASH Image System (FIS) directory is a flash description
32 KB in size.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
select: false
diff --git a/Documentation/devicetree/bindings/mtd/partitions/seama.yaml b/Documentation/devicetree/bindings/mtd/partitions/seama.yaml
index 4c1cbf43e81a..4af185204b4b 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/seama.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/seama.yaml
@@ -18,7 +18,7 @@ allOf:
- $ref: partition.yaml#
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/net/bluetooth/brcm,bluetooth.yaml b/Documentation/devicetree/bindings/net/bluetooth/brcm,bluetooth.yaml
index 3c410cadff23..95501e858e6f 100644
--- a/Documentation/devicetree/bindings/net/bluetooth/brcm,bluetooth.yaml
+++ b/Documentation/devicetree/bindings/net/bluetooth/brcm,bluetooth.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom Bluetooth Chips
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
This binding describes Broadcom UART-attached bluetooth chips.
diff --git a/Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml b/Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml
index a930358f6a66..f0b5bea2458d 100644
--- a/Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml
+++ b/Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cortina Systems Gemini Ethernet Controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This ethernet controller is found in the Gemini SoC family:
diff --git a/Documentation/devicetree/bindings/net/dsa/micrel,ks8995.yaml b/Documentation/devicetree/bindings/net/dsa/micrel,ks8995.yaml
index 854808ff5ad5..e9ce36067033 100644
--- a/Documentation/devicetree/bindings/net/dsa/micrel,ks8995.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/micrel,ks8995.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Micrel KS8995 Family DSA Switches
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
The Micrel KS8995 DSA Switches are 100 Mbit switches that were produced in
diff --git a/Documentation/devicetree/bindings/net/dsa/realtek.yaml b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
index f348e66fb515..473facd87a62 100644
--- a/Documentation/devicetree/bindings/net/dsa/realtek.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/realtek.yaml
@@ -10,7 +10,7 @@ allOf:
- $ref: dsa.yaml#/$defs/ethernet-ports
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
Realtek advertises these chips as fast/gigabit switches or unmanaged
diff --git a/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.yaml b/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.yaml
index 51cf574249be..c41f479bdee9 100644
--- a/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/vitesse,vsc73xx.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Vitesse VSC73xx DSA Switches
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
The Vitesse DSA Switches were produced in the early-to-mid 2000s.
diff --git a/Documentation/devicetree/bindings/net/intel,ixp46x-ptp-timer.yaml b/Documentation/devicetree/bindings/net/intel,ixp46x-ptp-timer.yaml
index f92730b1d2fa..80336b7e64ec 100644
--- a/Documentation/devicetree/bindings/net/intel,ixp46x-ptp-timer.yaml
+++ b/Documentation/devicetree/bindings/net/intel,ixp46x-ptp-timer.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP46x PTP Timer (TSYNC)
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Intel IXP46x PTP timer is known in the manual as IEEE1588 Hardware
diff --git a/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml b/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml
index 8689de1aaea1..3b8f83b7099d 100644
--- a/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml
+++ b/Documentation/devicetree/bindings/net/intel,ixp4xx-ethernet.yaml
@@ -11,7 +11,7 @@ allOf:
- $ref: ethernet-controller.yaml#
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Intel IXP4xx ethernet makes use of the IXP4xx NPE (Network
diff --git a/Documentation/devicetree/bindings/net/intel,ixp4xx-hss.yaml b/Documentation/devicetree/bindings/net/intel,ixp4xx-hss.yaml
index 7a405e9b37b2..1d952735c81b 100644
--- a/Documentation/devicetree/bindings/net/intel,ixp4xx-hss.yaml
+++ b/Documentation/devicetree/bindings/net/intel,ixp4xx-hss.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx V.35 WAN High Speed Serial Link (HSS)
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The Intel IXP4xx HSS makes use of the IXP4xx NPE (Network
diff --git a/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml b/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml
index 378dd1c8e2ee..fed393a89563 100644
--- a/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml
+++ b/Documentation/devicetree/bindings/pci/faraday,ftpci100.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FTPCI100 PCI Host Bridge
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This PCI bridge is found inside that Cortina Systems Gemini SoC platform and
diff --git a/Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml b/Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
index 3cae2e0f7f5e..c1806aef7bac 100644
--- a/Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
+++ b/Documentation/devicetree/bindings/pci/intel,ixp4xx-pci.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx PCI controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: PCI host controller found in the Intel IXP4xx SoC series.
diff --git a/Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml b/Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml
index 38cac88f17bf..0e2ac2f8faed 100644
--- a/Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml
+++ b/Documentation/devicetree/bindings/pci/v3,v360epc-pci.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: V3 Semiconductor V360 EPC PCI bridge
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
This bridge is found in the ARM Integrator/AP (Application Platform)
diff --git a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
index d1bc389e0a6d..a916d0fc79a9 100644
--- a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic Pin Configuration Node
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
Many data items that are represented in a pin configuration node are common
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl.yaml
index d471563119a9..290438826c50 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Pin controller device
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Rafał Miłecki <rafal@milecki.pl>
description: |
diff --git a/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml b/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
index ca9d246d46fe..7ba26271c4d6 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic Pin Multiplexing Node
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
The contents of the pin configuration child nodes are defined by the binding
diff --git a/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml b/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml
index 40292d581b10..fa1ccff043be 100644
--- a/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml
+++ b/Documentation/devicetree/bindings/power/supply/samsung,battery.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung SDI Batteries
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
Samsung SDI (Samsung Digital Interface) batteries are all different versions
diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index 565cb2cbb49b..5bab356addc8 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -377,6 +377,20 @@ properties:
guarantee on LR/SC sequences, as ratified in commit b1d806605f87
("Updated to ratified state.") of the riscv profiles specification.
+ - const: zilsd
+ description:
+ The standard Zilsd extension which provides support for aligned
+ register-pair load and store operations in 32-bit instruction
+ encodings, as ratified in commit f88abf1 ("Integrating
+ load/store pair for RV32 with the main manual") of riscv-isa-manual.
+
+ - const: zclsd
+ description:
+ The Zclsd extension implements the compressed (16-bit) version of the
+ Load/Store Pair for RV32. As with Zilsd, this extension was ratified
+ in commit f88abf1 ("Integrating load/store pair for RV32 with the
+ main manual") of riscv-isa-manual.
+
- const: zk
description:
The standard Zk Standard Scalar cryptography extension as ratified
@@ -882,6 +896,16 @@ properties:
anyOf:
- const: v
- const: zve32x
+ # Zclsd depends on Zilsd and Zca
+ - if:
+ contains:
+ anyOf:
+ - const: zclsd
+ then:
+ contains:
+ allOf:
+ - const: zilsd
+ - const: zca
allOf:
# Zcf extension does not exist on rv64
@@ -899,6 +923,18 @@ allOf:
not:
contains:
const: zcf
+ # Zilsd extension does not exist on rv64
+ - if:
+ properties:
+ riscv,isa-base:
+ contains:
+ const: rv64i
+ then:
+ properties:
+ riscv,isa-extensions:
+ not:
+ contains:
+ const: zilsd
additionalProperties: true
...
diff --git a/Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml b/Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
index 9f7590ce6b3d..146593a669d6 100644
--- a/Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml
@@ -12,7 +12,7 @@ description: |
32 bit random number.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml b/Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml
index b1c1a0e21318..2b1215b49580 100644
--- a/Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml
+++ b/Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FTRTC010 Real Time Clock
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: |
This RTC appears in for example the Storlink Gemini family of SoCs.
diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
index 3b47b68b92cb..1b91d1566c95 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
oneOf:
- const: allwinner,sun50i-r329-spi
+ - const: allwinner,sun55i-a523-spi
- const: allwinner,sun6i-a31-spi
- const: allwinner,sun8i-h3-spi
- items:
@@ -35,6 +36,9 @@ properties:
- const: allwinner,sun20i-d1-spi-dbi
- const: allwinner,sun50i-r329-spi-dbi
- const: allwinner,sun50i-r329-spi
+ - items:
+ - const: allwinner,sun55i-a523-spi-dbi
+ - const: allwinner,sun55i-a523-spi
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml
index bb8b6863b109..f976e416395b 100644
--- a/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/arm,pl022-peripheral-props.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Peripheral-specific properties for Arm PL022 SPI controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
select: false
diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
index 5c87fc8a845d..81838577cf9c 100644
--- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
@@ -121,7 +121,7 @@ properties:
num-cs:
default: 4
minimum: 1
- maximum: 4
+ maximum: 16
dmas:
items:
@@ -153,14 +153,14 @@ properties:
provides an interface to override the native DWC SSI CS control.
patternProperties:
- "@[0-9a-f]+$":
+ "@[0-9a-f]$":
type: object
additionalProperties: true
properties:
reg:
minimum: 0
- maximum: 3
+ maximum: 0xf
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/spi/spi-pl022.yaml b/Documentation/devicetree/bindings/spi/spi-pl022.yaml
index 7f174b7d0a26..680fdfa184d0 100644
--- a/Documentation/devicetree/bindings/spi/spi-pl022.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-pl022.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ARM PL022 SPI controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: spi-controller.yaml#
diff --git a/Documentation/devicetree/bindings/timer/faraday,fttmr010.yaml b/Documentation/devicetree/bindings/timer/faraday,fttmr010.yaml
index 39506323556c..e93c20243dba 100644
--- a/Documentation/devicetree/bindings/timer/faraday,fttmr010.yaml
+++ b/Documentation/devicetree/bindings/timer/faraday,fttmr010.yaml
@@ -8,7 +8,7 @@ title: Faraday FTTMR010 timer
maintainers:
- Joel Stanley <joel@jms.id.au>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description:
This timer is a generic IP block from Faraday Technology, embedded in the
diff --git a/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
index 526b8db4d575..c92e6b9cd5e2 100644
--- a/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx XScale Networking Processors Timers
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: This timer is found in the Intel IXP4xx processors.
diff --git a/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml b/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml
index fa65878b3571..873a01c287f4 100644
--- a/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml
+++ b/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: ST Microelectronics Nomadik Multi-Timer Unit MTU Timer
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
description: This timer is found in the ST Microelectronics Nomadik
SoCs STn8800, STn8810 and STn8815 as well as in ST-Ericsson DB8500.
diff --git a/Documentation/devicetree/bindings/usb/faraday,fotg210.yaml b/Documentation/devicetree/bindings/usb/faraday,fotg210.yaml
index 3fe4d1564dfe..b97ba535087c 100644
--- a/Documentation/devicetree/bindings/usb/faraday,fotg210.yaml
+++ b/Documentation/devicetree/bindings/usb/faraday,fotg210.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FOTG200 series HS OTG USB 2.0 controller
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: usb-drd.yaml#
diff --git a/Documentation/devicetree/bindings/usb/intel,ixp4xx-udc.yaml b/Documentation/devicetree/bindings/usb/intel,ixp4xx-udc.yaml
index 4ed602746897..91a149ad3ad6 100644
--- a/Documentation/devicetree/bindings/usb/intel,ixp4xx-udc.yaml
+++ b/Documentation/devicetree/bindings/usb/intel,ixp4xx-udc.yaml
@@ -10,7 +10,7 @@ description: The IXP4xx SoCs has a full-speed USB Device
Controller with 16 endpoints and a built-in transceiver.
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml
index 726dc872ad02..3eb35f325f4c 100644
--- a/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml
+++ b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Faraday Technology FTWDT010 watchdog
maintainers:
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
- Corentin Labbe <clabbe@baylibre.com>
description: |
diff --git a/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml b/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml
index 442c21f12a3b..defe0401ded0 100644
--- a/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml
+++ b/Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml
@@ -8,7 +8,7 @@ title: Maxim 63xx Watchdog Timers
maintainers:
- Marc Zyngier <maz@kernel.org>
- - Linus Walleij <linus.walleij@linaro.org>
+ - Linus Walleij <linusw@kernel.org>
allOf:
- $ref: watchdog.yaml#
diff --git a/Documentation/hwmon/ds620.rst b/Documentation/hwmon/ds620.rst
index 2d686b17b547..e2d915a988a2 100644
--- a/Documentation/hwmon/ds620.rst
+++ b/Documentation/hwmon/ds620.rst
@@ -7,9 +7,9 @@ Supported chips:
Prefix: 'ds620'
- Datasheet: Publicly available at the Dallas Semiconductor website
+ Datasheet: Publicly available at the Analog Devices website
- http://www.dalsemi.com/
+ https://www.analog.com/media/en/technical-documentation/data-sheets/DS620.pdf
Authors:
Roland Stigge <stigge@antcom.de>
diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst
index c939a5bfc8d0..bbbce90eb7d8 100644
--- a/Documentation/i2c/busses/i2c-i801.rst
+++ b/Documentation/i2c/busses/i2c-i801.rst
@@ -52,6 +52,7 @@ Supported adapters:
* Intel Panther Lake (SOC)
* Intel Wildcat Lake (SOC)
* Intel Diamond Rapids (SOC)
+ * Intel Nova Lake (PCH)
Datasheets: Publicly available at the Intel website
diff --git a/Documentation/input/event-codes.rst b/Documentation/input/event-codes.rst
index 4424cbff251f..77a6c9b3956d 100644
--- a/Documentation/input/event-codes.rst
+++ b/Documentation/input/event-codes.rst
@@ -241,6 +241,12 @@ A few EV_ABS codes have special meanings:
emitted only when the selected profile changes, indicating the newly
selected profile value.
+* ABS_SND_PROFILE:
+
+ - Used to describe the state of a multi-value sound profile switch.
+ An event is emitted only when the selected profile changes,
+ indicating the newly selected profile value.
+
* ABS_MT_<name>:
- Used to describe multitouch input events. Please see
diff --git a/MAINTAINERS b/MAINTAINERS
index 5b11839cba9d..765ad2daa218 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13959,6 +13959,7 @@ S: Maintained
F: Documentation/admin-guide/mm/kho.rst
F: Documentation/core-api/kho/*
F: include/linux/kexec_handover.h
+F: include/linux/kho/
F: kernel/liveupdate/kexec_handover*
F: lib/test_kho.c
F: tools/testing/selftests/kho/
@@ -14637,6 +14638,7 @@ S: Maintained
F: Documentation/core-api/liveupdate.rst
F: Documentation/mm/memfd_preservation.rst
F: Documentation/userspace-api/liveupdate.rst
+F: include/linux/kho/abi/
F: include/linux/liveupdate.h
F: include/linux/liveupdate/
F: include/uapi/linux/liveupdate.h
@@ -16426,6 +16428,7 @@ MEMORY HOT(UN)PLUG
M: David Hildenbrand <david@kernel.org>
M: Oscar Salvador <osalvador@suse.de>
L: linux-mm@kvack.org
+L: linux-cxl@vger.kernel.org
S: Maintained
F: Documentation/admin-guide/mm/memory-hotplug.rst
F: Documentation/core-api/memory-hotplug.rst
@@ -16751,6 +16754,7 @@ F: tools/testing/selftests/mm/transhuge-stress.c
MEMORY MANAGEMENT - USERFAULTFD
M: Andrew Morton <akpm@linux-foundation.org>
+M: Mike Rapoport <rppt@kernel.org>
R: Peter Xu <peterx@redhat.com>
L: linux-mm@kvack.org
S: Maintained
@@ -18028,7 +18032,6 @@ F: drivers/net/ethernet/neterion/
NETFILTER
M: Pablo Neira Ayuso <pablo@netfilter.org>
-M: Jozsef Kadlecsik <kadlec@netfilter.org>
M: Florian Westphal <fw@strlen.de>
R: Phil Sutter <phil@nwl.cc>
L: netfilter-devel@vger.kernel.org
@@ -21346,7 +21349,7 @@ F: Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
F: drivers/net/wwan/qcom_bam_dmux.c
QUALCOMM BLUETOOTH DRIVER
-M: Bartosz Golaszewski <brgl@bgdev.pl>
+M: Bartosz Golaszewski <brgl@kernel.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/bluetooth/btqca.[ch]
@@ -24572,7 +24575,7 @@ F: drivers/tty/vcc.c
F: include/linux/sunserialcore.h
SPARSE CHECKER
-M: "Luc Van Oostenryck" <luc.vanoostenryck@gmail.com>
+M: Chris Li <sparse@chrisli.org>
L: linux-sparse@vger.kernel.org
S: Maintained
W: https://sparse.docs.kernel.org/
@@ -26464,6 +26467,7 @@ L: linux-trace-kernel@vger.kernel.org
S: Maintained
Q: https://patchwork.kernel.org/project/linux-trace-kernel/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
+F: Documentation/core-api/tracepoint.rst
F: Documentation/trace/*
F: fs/tracefs/
F: include/linux/trace*.h
@@ -27920,6 +27924,7 @@ F: drivers/regulator/
F: rust/kernel/regulator.rs
F: include/dt-bindings/regulator/
F: include/linux/regulator/
+F: include/uapi/regulator/
K: regulator_get_optional
VOLTAGE AND CURRENT REGULATOR IRQ HELPERS
diff --git a/Makefile b/Makefile
index e404e4767944..665b79aa21b8 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 6
PATCHLEVEL = 19
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc4
NAME = Baby Opossum Posse
# *DOCUMENTATION*
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index c5fd6191a925..3f76d9ce9879 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -19,6 +19,27 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sata.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo
+mt7986a-bananapi-bpi-r3-emmc-nand-dtbs := \
+ mt7986a-bananapi-bpi-r3.dtb \
+ mt7986a-bananapi-bpi-r3-emmc.dtbo \
+ mt7986a-bananapi-bpi-r3-nand.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc-nand.dtb
+mt7986a-bananapi-bpi-r3-emmc-nor-dtbs := \
+ mt7986a-bananapi-bpi-r3.dtb \
+ mt7986a-bananapi-bpi-r3-emmc.dtbo \
+ mt7986a-bananapi-bpi-r3-nor.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc-nor.dtb
+mt7986a-bananapi-bpi-r3-sd-nand-dtbs := \
+ mt7986a-bananapi-bpi-r3.dtb \
+ mt7986a-bananapi-bpi-r3-sd.dtbo \
+ mt7986a-bananapi-bpi-r3-nand.dtbo \
+ mt7986a-bananapi-bpi-r3-sata.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd-nand.dtb
+mt7986a-bananapi-bpi-r3-sd-nor-dtbs := \
+ mt7986a-bananapi-bpi-r3.dtb \
+ mt7986a-bananapi-bpi-r3-sd.dtbo \
+ mt7986a-bananapi-bpi-r3-nor.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd-nor.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4.dtb
@@ -31,6 +52,38 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-cn18.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-emmc.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-sd.dtbo
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-sd.dtbo
+mt7988a-bananapi-bpi-r4-emmc-dtbs := \
+ mt7988a-bananapi-bpi-r4.dtb \
+ mt7988a-bananapi-bpi-r4-emmc.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-emmc.dtb
+mt7988a-bananapi-bpi-r4-sd-dtbs := \
+ mt7988a-bananapi-bpi-r4.dtb \
+ mt7988a-bananapi-bpi-r4-sd.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-sd.dtb
+mt7988a-bananapi-bpi-r4-2g5-emmc-dtbs := \
+ mt7988a-bananapi-bpi-r4-2g5.dtb \
+ mt7988a-bananapi-bpi-r4-emmc.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-2g5-emmc.dtb
+mt7988a-bananapi-bpi-r4-2g5-sd-dtbs := \
+ mt7988a-bananapi-bpi-r4-2g5.dtb \
+ mt7988a-bananapi-bpi-r4-sd.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-2g5-sd.dtb
+mt7988a-bananapi-bpi-r4-pro-8x-emmc-dtbs := \
+ mt7988a-bananapi-bpi-r4-pro-8x.dtb \
+ mt7988a-bananapi-bpi-r4-pro-emmc.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-emmc.dtb
+mt7988a-bananapi-bpi-r4-pro-8x-sd-dtbs := \
+ mt7988a-bananapi-bpi-r4-pro-8x.dtb \
+ mt7988a-bananapi-bpi-r4-pro-sd.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-sd.dtb
+mt7988a-bananapi-bpi-r4-pro-8x-sd-cn15-dtbs := \
+ mt7988a-bananapi-bpi-r4-pro-8x-sd.dtb \
+ mt7988a-bananapi-bpi-r4-pro-cn15.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-sd-cn15.dtb
+mt7988a-bananapi-bpi-r4-pro-8x-sd-cn18-dtbs := \
+ mt7988a-bananapi-bpi-r4-pro-8x-sd.dtb \
+ mt7988a-bananapi-bpi-r4-pro-cn18.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-sd-cn18.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb
@@ -113,6 +166,8 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8390-grinn-genio-700-sbc.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-kontron-3-5-sbc-i1200.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l-8-hd-panel.dtbo
+mt8395-radxa-nio-12l-8-hd-panel-dtbs := mt8395-radxa-nio-12l.dtb mt8395-radxa-nio-12l-8-hd-panel.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l-8-hd-panel.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb
# Device tree overlays support
diff --git a/arch/arm64/include/asm/simd.h b/arch/arm64/include/asm/simd.h
index 0941f6f58a14..69ecbd69ca8c 100644
--- a/arch/arm64/include/asm/simd.h
+++ b/arch/arm64/include/asm/simd.h
@@ -48,6 +48,13 @@ DEFINE_LOCK_GUARD_1(ksimd,
kernel_neon_begin(_T->lock),
kernel_neon_end(_T->lock))
-#define scoped_ksimd() scoped_guard(ksimd, &(struct user_fpsimd_state){})
+#define __scoped_ksimd(_label) \
+ for (struct user_fpsimd_state __uninitialized __st; \
+ true; ({ goto _label; })) \
+ if (0) { \
+_label: break; \
+ } else scoped_guard(ksimd, &__st)
+
+#define scoped_ksimd() __scoped_ksimd(__UNIQUE_ID(label))
#endif
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index c154f72634e0..9de1d8a604cb 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -180,13 +180,6 @@ static inline void set_sve_default_vl(int val)
set_default_vl(ARM64_VEC_SVE, val);
}
-static u8 *efi_sve_state;
-
-#else /* ! CONFIG_ARM64_SVE */
-
-/* Dummy declaration for code that will be optimised out: */
-extern u8 *efi_sve_state;
-
#endif /* ! CONFIG_ARM64_SVE */
#ifdef CONFIG_ARM64_SME
@@ -1095,36 +1088,6 @@ int vec_verify_vq_map(enum vec_type type)
return 0;
}
-static void __init sve_efi_setup(void)
-{
- int max_vl = 0;
- int i;
-
- if (!IS_ENABLED(CONFIG_EFI))
- return;
-
- for (i = 0; i < ARRAY_SIZE(vl_info); i++)
- max_vl = max(vl_info[i].max_vl, max_vl);
-
- /*
- * alloc_percpu() warns and prints a backtrace if this goes wrong.
- * This is evidence of a crippled system and we are returning void,
- * so no attempt is made to handle this situation here.
- */
- if (!sve_vl_valid(max_vl))
- goto fail;
-
- efi_sve_state = kmalloc(SVE_SIG_REGS_SIZE(sve_vq_from_vl(max_vl)),
- GFP_KERNEL);
- if (!efi_sve_state)
- goto fail;
-
- return;
-
-fail:
- panic("Cannot allocate memory for EFI SVE save/restore");
-}
-
void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)
{
write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
@@ -1185,8 +1148,6 @@ void __init sve_setup(void)
if (sve_max_virtualisable_vl() < sve_max_vl())
pr_warn("%s: unvirtualisable vector lengths present\n",
info->name);
-
- sve_efi_setup();
}
/*
@@ -1947,9 +1908,6 @@ EXPORT_SYMBOL_GPL(kernel_neon_end);
#ifdef CONFIG_EFI
static struct user_fpsimd_state efi_fpsimd_state;
-static bool efi_fpsimd_state_used;
-static bool efi_sve_state_used;
-static bool efi_sm_state;
/*
* EFI runtime services support functions
@@ -1976,43 +1934,26 @@ void __efi_fpsimd_begin(void)
if (may_use_simd()) {
kernel_neon_begin(&efi_fpsimd_state);
} else {
- WARN_ON(preemptible());
-
/*
- * If !efi_sve_state, SVE can't be in use yet and doesn't need
- * preserving:
+ * We are running in hardirq or NMI context, and the only
+ * legitimate case where this might happen is when EFI pstore
+ * is attempting to record the system's dying gasps into EFI
+ * variables. This could be due to an oops, a panic or a call
+ * to emergency_restart(), and in none of those cases, we can
+ * expect the current task to ever return to user space again,
+ * or for the kernel to resume any normal execution, for that
+ * matter (an oops in hardirq context triggers a panic too).
+ *
+ * Therefore, there is no point in attempting to preserve any
+ * SVE/SME state here. On the off chance that we might have
+ * ended up here for a different reason inadvertently, kill the
+ * task and preserve/restore the base FP/SIMD state, which
+ * might belong to kernel mode FP/SIMD.
*/
- if (system_supports_sve() && efi_sve_state != NULL) {
- bool ffr = true;
- u64 svcr;
-
- efi_sve_state_used = true;
-
- if (system_supports_sme()) {
- svcr = read_sysreg_s(SYS_SVCR);
-
- efi_sm_state = svcr & SVCR_SM_MASK;
-
- /*
- * Unless we have FA64 FFR does not
- * exist in streaming mode.
- */
- if (!system_supports_fa64())
- ffr = !(svcr & SVCR_SM_MASK);
- }
-
- sve_save_state(efi_sve_state + sve_ffr_offset(sve_max_vl()),
- &efi_fpsimd_state.fpsr, ffr);
-
- if (system_supports_sme())
- sysreg_clear_set_s(SYS_SVCR,
- SVCR_SM_MASK, 0);
-
- } else {
- fpsimd_save_state(&efi_fpsimd_state);
- }
-
- efi_fpsimd_state_used = true;
+ pr_warn_ratelimited("Calling EFI runtime from %s context\n",
+ in_nmi() ? "NMI" : "hardirq");
+ force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
+ fpsimd_save_state(&efi_fpsimd_state);
}
}
@@ -2024,41 +1965,10 @@ void __efi_fpsimd_end(void)
if (!system_supports_fpsimd())
return;
- if (!efi_fpsimd_state_used) {
+ if (may_use_simd()) {
kernel_neon_end(&efi_fpsimd_state);
} else {
- if (system_supports_sve() && efi_sve_state_used) {
- bool ffr = true;
-
- /*
- * Restore streaming mode; EFI calls are
- * normal function calls so should not return in
- * streaming mode.
- */
- if (system_supports_sme()) {
- if (efi_sm_state) {
- sysreg_clear_set_s(SYS_SVCR,
- 0,
- SVCR_SM_MASK);
-
- /*
- * Unless we have FA64 FFR does not
- * exist in streaming mode.
- */
- if (!system_supports_fa64())
- ffr = false;
- }
- }
-
- sve_load_state(efi_sve_state + sve_ffr_offset(sve_max_vl()),
- &efi_fpsimd_state.fpsr, ffr);
-
- efi_sve_state_used = false;
- } else {
- fpsimd_load_state(&efi_fpsimd_state);
- }
-
- efi_fpsimd_state_used = false;
+ fpsimd_load_state(&efi_fpsimd_state);
}
}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index fba7ca102a8c..489554931231 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -292,6 +292,7 @@ static void flush_gcs(void)
current->thread.gcs_base = 0;
current->thread.gcs_size = 0;
current->thread.gcs_el0_mode = 0;
+ current->thread.gcs_el0_locked = 0;
write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1);
write_sysreg_s(0, SYS_GCSPR_EL0);
}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 9ae7ce00a7ef..8e1d80a7033e 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -767,18 +767,6 @@ static inline bool force_pte_mapping(void)
return rodata_full || arm64_kfence_can_set_direct_map() || is_realm_world();
}
-static inline bool split_leaf_mapping_possible(void)
-{
- /*
- * !BBML2_NOABORT systems should never run into scenarios where we would
- * have to split. So exit early and let calling code detect it and raise
- * a warning.
- */
- if (!system_supports_bbml2_noabort())
- return false;
- return !force_pte_mapping();
-}
-
static DEFINE_MUTEX(pgtable_split_lock);
int split_kernel_leaf_mapping(unsigned long start, unsigned long end)
@@ -786,11 +774,22 @@ int split_kernel_leaf_mapping(unsigned long start, unsigned long end)
int ret;
/*
- * Exit early if the region is within a pte-mapped area or if we can't
- * split. For the latter case, the permission change code will raise a
- * warning if not already pte-mapped.
+ * !BBML2_NOABORT systems should not be trying to change permissions on
+ * anything that is not pte-mapped in the first place. Just return early
+ * and let the permission change code raise a warning if not already
+ * pte-mapped.
*/
- if (!split_leaf_mapping_possible() || is_kfence_address((void *)start))
+ if (!system_supports_bbml2_noabort())
+ return 0;
+
+ /*
+ * If the region is within a pte-mapped area, there is no need to try to
+ * split. Additionally, CONFIG_DEBUG_PAGEALLOC and CONFIG_KFENCE may
+ * change permissions from atomic context so for those cases (which are
+ * always pte-mapped), we must not go any further because taking the
+ * mutex below may sleep.
+ */
+ if (force_pte_mapping() || is_kfence_address((void *)start))
return 0;
/*
@@ -1089,7 +1088,7 @@ bool arch_kfence_init_pool(void)
int ret;
/* Exit early if we know the linear map is already pte-mapped. */
- if (!split_leaf_mapping_possible())
+ if (force_pte_mapping())
return true;
/* Kfence pool is already pte-mapped for the early init case. */
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 74dd29816f36..b6eb7a465ad2 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1004,7 +1004,7 @@ static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx)
arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE)
return;
- if (capable(CAP_SYS_ADMIN))
+ if (ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
return;
if (supports_clearbhb(SCOPE_SYSTEM)) {
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h
index e6b8ff61c8cc..553c4dc7a156 100644
--- a/arch/loongarch/include/asm/loongarch.h
+++ b/arch/loongarch/include/asm/loongarch.h
@@ -94,6 +94,12 @@
#define CPUCFG2_LSPW BIT(21)
#define CPUCFG2_LAM BIT(22)
#define CPUCFG2_PTW BIT(24)
+#define CPUCFG2_FRECIPE BIT(25)
+#define CPUCFG2_DIV32 BIT(26)
+#define CPUCFG2_LAM_BH BIT(27)
+#define CPUCFG2_LAMCAS BIT(28)
+#define CPUCFG2_LLACQ_SCREL BIT(29)
+#define CPUCFG2_SCQ BIT(30)
#define LOONGARCH_CPUCFG3 0x3
#define CPUCFG3_CCDMA BIT(0)
@@ -108,6 +114,7 @@
#define CPUCFG3_SPW_HG_HF BIT(11)
#define CPUCFG3_RVA BIT(12)
#define CPUCFG3_RVAMAX GENMASK(16, 13)
+#define CPUCFG3_DBAR_HINTS BIT(17)
#define CPUCFG3_ALDORDER_CAP BIT(18) /* All address load ordered, capability */
#define CPUCFG3_ASTORDER_CAP BIT(19) /* All address store ordered, capability */
#define CPUCFG3_ALDORDER_STA BIT(20) /* All address load ordered, status */
diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S
index aba548db2446..7f288e89573b 100644
--- a/arch/loongarch/kernel/head.S
+++ b/arch/loongarch/kernel/head.S
@@ -42,6 +42,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
.align 12
SYM_CODE_START(kernel_entry) # kernel entry point
+ UNWIND_HINT_END_OF_STACK
SETUP_TWINS
SETUP_MODES t0
@@ -113,6 +114,7 @@ SYM_CODE_END(kernel_entry)
* function after setting up the stack and tp registers.
*/
SYM_CODE_START(smpboot_entry)
+ UNWIND_HINT_END_OF_STACK
SETUP_TWINS
SETUP_MODES t0
@@ -142,5 +144,3 @@ SYM_CODE_START(smpboot_entry)
SYM_CODE_END(smpboot_entry)
#endif /* CONFIG_SMP */
-
-SYM_ENTRY(kernel_entry_end, SYM_L_GLOBAL, SYM_A_NONE)
diff --git a/arch/loongarch/kernel/mcount_dyn.S b/arch/loongarch/kernel/mcount_dyn.S
index d6b474ad1d5e..5729c20e5b8b 100644
--- a/arch/loongarch/kernel/mcount_dyn.S
+++ b/arch/loongarch/kernel/mcount_dyn.S
@@ -94,7 +94,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
* at the callsite, so there is no need to restore the T series regs.
*/
ftrace_common_return:
- PTR_L ra, sp, PT_R1
PTR_L a0, sp, PT_R4
PTR_L a1, sp, PT_R5
PTR_L a2, sp, PT_R6
@@ -104,12 +103,17 @@ ftrace_common_return:
PTR_L a6, sp, PT_R10
PTR_L a7, sp, PT_R11
PTR_L fp, sp, PT_R22
- PTR_L t0, sp, PT_ERA
PTR_L t1, sp, PT_R13
- PTR_ADDI sp, sp, PT_SIZE
bnez t1, .Ldirect
+
+ PTR_L ra, sp, PT_R1
+ PTR_L t0, sp, PT_ERA
+ PTR_ADDI sp, sp, PT_SIZE
jr t0
.Ldirect:
+ PTR_L t0, sp, PT_R1
+ PTR_L ra, sp, PT_ERA
+ PTR_ADDI sp, sp, PT_SIZE
jr t1
SYM_CODE_END(ftrace_common)
@@ -161,6 +165,8 @@ SYM_CODE_END(return_to_handler)
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
SYM_CODE_START(ftrace_stub_direct_tramp)
UNWIND_HINT_UNDEFINED
- jr t0
+ move t1, ra
+ move ra, t0
+ jr t1
SYM_CODE_END(ftrace_stub_direct_tramp)
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c
index 004b8ebf0051..5d49b742e3bf 100644
--- a/arch/loongarch/kernel/traps.c
+++ b/arch/loongarch/kernel/traps.c
@@ -535,10 +535,15 @@ out:
asmlinkage void noinstr do_ade(struct pt_regs *regs)
{
irqentry_state_t state = irqentry_enter(regs);
+ unsigned int esubcode = FIELD_GET(CSR_ESTAT_ESUBCODE, regs->csr_estat);
+
+ if ((esubcode == EXSUBCODE_ADEM) && fixup_exception(regs))
+ goto out;
die_if_kernel("Kernel ade access", regs);
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)regs->csr_badvaddr);
+out:
irqentry_exit(regs, state);
}
diff --git a/arch/loongarch/kernel/unwind_orc.c b/arch/loongarch/kernel/unwind_orc.c
index 0d5fa64a2225..8a6e3429a860 100644
--- a/arch/loongarch/kernel/unwind_orc.c
+++ b/arch/loongarch/kernel/unwind_orc.c
@@ -348,24 +348,10 @@ void unwind_start(struct unwind_state *state, struct task_struct *task,
}
EXPORT_SYMBOL_GPL(unwind_start);
-static bool is_entry_func(unsigned long addr)
-{
- extern u32 kernel_entry;
- extern u32 kernel_entry_end;
-
- return addr >= (unsigned long)&kernel_entry && addr < (unsigned long)&kernel_entry_end;
-}
-
static inline unsigned long bt_address(unsigned long ra)
{
extern unsigned long eentry;
- if (__kernel_text_address(ra))
- return ra;
-
- if (__module_text_address(ra))
- return ra;
-
if (ra >= eentry && ra < eentry + EXCCODE_INT_END * VECSIZE) {
unsigned long func;
unsigned long type = (ra - eentry) / VECSIZE;
@@ -383,10 +369,13 @@ static inline unsigned long bt_address(unsigned long ra)
break;
}
- return func + offset;
+ ra = func + offset;
}
- return ra;
+ if (__kernel_text_address(ra))
+ return ra;
+
+ return 0;
}
bool unwind_next_frame(struct unwind_state *state)
@@ -402,9 +391,6 @@ bool unwind_next_frame(struct unwind_state *state)
/* Don't let modules unload while we're reading their ORC data. */
guard(rcu)();
- if (is_entry_func(state->pc))
- goto end;
-
orc = orc_find(state->pc);
if (!orc) {
/*
@@ -512,9 +498,6 @@ bool unwind_next_frame(struct unwind_state *state)
goto err;
}
- if (!__kernel_text_address(state->pc))
- goto err;
-
return true;
err:
diff --git a/arch/loongarch/mm/cache.c b/arch/loongarch/mm/cache.c
index 6be04d36ca07..496916845ff7 100644
--- a/arch/loongarch/mm/cache.c
+++ b/arch/loongarch/mm/cache.c
@@ -160,8 +160,8 @@ void cpu_cache_init(void)
static const pgprot_t protection_map[16] = {
[VM_NONE] = __pgprot(_CACHE_CC | _PAGE_USER |
- _PAGE_PROTNONE | _PAGE_NO_EXEC |
- _PAGE_NO_READ),
+ _PAGE_NO_EXEC | _PAGE_NO_READ |
+ (_PAGE_PROTNONE ? : _PAGE_PRESENT)),
[VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
_PAGE_USER | _PAGE_PRESENT |
_PAGE_NO_EXEC),
@@ -180,8 +180,8 @@ static const pgprot_t protection_map[16] = {
[VM_EXEC | VM_WRITE | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
_PAGE_USER | _PAGE_PRESENT),
[VM_SHARED] = __pgprot(_CACHE_CC | _PAGE_USER |
- _PAGE_PROTNONE | _PAGE_NO_EXEC |
- _PAGE_NO_READ),
+ _PAGE_NO_EXEC | _PAGE_NO_READ |
+ (_PAGE_PROTNONE ? : _PAGE_PRESENT)),
[VM_SHARED | VM_READ] = __pgprot(_CACHE_CC | _PAGE_VALID |
_PAGE_USER | _PAGE_PRESENT |
_PAGE_NO_EXEC),
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index 8dc58781b8eb..d1d5a65308b9 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -139,6 +139,7 @@ static void build_prologue(struct jit_ctx *ctx)
stack_adjust = round_up(stack_adjust, 16);
stack_adjust += bpf_stack_adjust;
+ move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA);
/* Reserve space for the move_imm + jirl instruction */
for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++)
emit_insn(ctx, nop);
@@ -238,7 +239,7 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
* Call the next bpf prog and skip the first instruction
* of TCC initialization.
*/
- emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 6);
+ emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7);
}
}
@@ -280,6 +281,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
* goto out;
*/
tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0];
+ emit_zext_32(ctx, a2, true);
+
off = offsetof(struct bpf_array, map.max_entries);
emit_insn(ctx, ldwu, t1, a1, off);
/* bgeu $a2, $t1, jmp_offset */
@@ -950,6 +953,22 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off);
}
+ if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
+ const struct btf_func_model *m;
+ int i;
+
+ m = bpf_jit_find_kfunc_model(ctx->prog, insn);
+ if (!m)
+ return -EINVAL;
+
+ for (i = 0; i < m->nr_args; i++) {
+ u8 reg = regmap[BPF_REG_1 + i];
+ bool sign = m->arg_flags[i] & BTF_FMODEL_SIGNED_ARG;
+
+ emit_abi_ext(ctx, reg, m->arg_size[i], sign);
+ }
+ }
+
move_addr(ctx, t1, func_addr);
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0);
@@ -1265,7 +1284,7 @@ static int emit_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
return 0;
}
- return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO, (u64)target);
+ return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_RA : LOONGARCH_GPR_ZERO, (u64)target);
}
static int emit_call(struct jit_ctx *ctx, u64 addr)
@@ -1290,15 +1309,30 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
{
int ret;
bool is_call;
+ unsigned long size = 0;
+ unsigned long offset = 0;
+ void *image = NULL;
+ char namebuf[KSYM_NAME_LEN];
u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
/* Only poking bpf text is supported. Since kernel function entry
* is set up by ftrace, we rely on ftrace to poke kernel functions.
*/
- if (!is_bpf_text_address((unsigned long)ip))
+ if (!__bpf_address_lookup((unsigned long)ip, &size, &offset, namebuf))
return -ENOTSUPP;
+ image = ip - offset;
+
+ /* zero offset means we're poking bpf prog entry */
+ if (offset == 0) {
+ /* skip to the nop instruction in bpf prog entry:
+ * move t0, ra
+ * nop
+ */
+ ip = image + LOONGARCH_INSN_SIZE;
+ }
+
is_call = old_t == BPF_MOD_CALL;
ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call);
if (ret)
@@ -1622,14 +1656,12 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
/* To traced function */
/* Ftrace jump skips 2 NOP instructions */
- if (is_kernel_text((unsigned long)orig_call))
+ if (is_kernel_text((unsigned long)orig_call) ||
+ is_module_text_address((unsigned long)orig_call))
orig_call += LOONGARCH_FENTRY_NBYTES;
/* Direct jump skips 5 NOP instructions */
else if (is_bpf_text_address((unsigned long)orig_call))
orig_call += LOONGARCH_BPF_FENTRY_NBYTES;
- /* Module tracing not supported - cause kernel lockups */
- else if (is_module_text_address((unsigned long)orig_call))
- return -ENOTSUPP;
if (flags & BPF_TRAMP_F_CALL_ORIG) {
move_addr(ctx, LOONGARCH_GPR_A0, (const u64)im);
@@ -1722,12 +1754,16 @@ static int __arch_prepare_bpf_trampoline(struct jit_ctx *ctx, struct bpf_tramp_i
emit_insn(ctx, ldd, LOONGARCH_GPR_FP, LOONGARCH_GPR_SP, 0);
emit_insn(ctx, addid, LOONGARCH_GPR_SP, LOONGARCH_GPR_SP, 16);
- if (flags & BPF_TRAMP_F_SKIP_FRAME)
+ if (flags & BPF_TRAMP_F_SKIP_FRAME) {
/* return to parent function */
- emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
- else
- /* return to traced function */
+ move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0);
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T0, 0);
+ } else {
+ /* return to traced function */
+ move_reg(ctx, LOONGARCH_GPR_T1, LOONGARCH_GPR_RA);
+ move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0);
+ emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T1, 0);
+ }
}
ret = ctx->idx;
diff --git a/arch/loongarch/net/bpf_jit.h b/arch/loongarch/net/bpf_jit.h
index 5697158fd164..75b6330030a9 100644
--- a/arch/loongarch/net/bpf_jit.h
+++ b/arch/loongarch/net/bpf_jit.h
@@ -88,6 +88,32 @@ static inline void emit_sext_32(struct jit_ctx *ctx, enum loongarch_gpr reg, boo
emit_insn(ctx, addiw, reg, reg, 0);
}
+/* Emit proper extension according to ABI requirements.
+ * Note that it requires a value of size `size` already resides in register `reg`.
+ */
+static inline void emit_abi_ext(struct jit_ctx *ctx, int reg, u8 size, bool sign)
+{
+ /* ABI requires unsigned char/short to be zero-extended */
+ if (!sign && (size == 1 || size == 2))
+ return;
+
+ switch (size) {
+ case 1:
+ emit_insn(ctx, extwb, reg, reg);
+ break;
+ case 2:
+ emit_insn(ctx, extwh, reg, reg);
+ break;
+ case 4:
+ emit_insn(ctx, addiw, reg, reg, 0);
+ break;
+ case 8:
+ break;
+ default:
+ pr_warn("bpf_jit: invalid size %d for extension\n", size);
+ }
+}
+
static inline void move_addr(struct jit_ctx *ctx, enum loongarch_gpr rd, u64 addr)
{
u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c
index c35b4f809d51..992134a8c23a 100644
--- a/arch/mips/alchemy/common/setup.c
+++ b/arch/mips/alchemy/common/setup.c
@@ -94,8 +94,7 @@ phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
return phys_addr;
}
-static inline unsigned long io_remap_pfn_range_pfn(unsigned long pfn,
- unsigned long size)
+unsigned long io_remap_pfn_range_pfn(unsigned long pfn, unsigned long size)
{
phys_addr_t phys_addr = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
index 5893ea4e382c..19b70928d6dc 100644
--- a/arch/mips/sgi-ip22/ip22-gio.c
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -372,7 +372,8 @@ static void ip22_check_gio(int slotno, unsigned long addr, int irq)
gio_dev->resource.flags = IORESOURCE_MEM;
gio_dev->irq = irq;
dev_set_name(&gio_dev->dev, "%d", slotno);
- gio_device_register(gio_dev);
+ if (gio_device_register(gio_dev))
+ gio_dev_put(gio_dev);
} else
printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
}
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 1078ba88efaf..9cd945f2acaf 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -90,7 +90,7 @@ static inline void __hard_EE_RI_disable(void)
if (IS_ENABLED(CONFIG_BOOKE))
wrtee(0);
else if (IS_ENABLED(CONFIG_PPC_8xx))
- wrtspr(SPRN_NRI);
+ wrtspr_sync(SPRN_NRI);
else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64))
__mtmsrd(0, 1);
else
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 3fe186635432..3449dd2b577d 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1400,6 +1400,7 @@ static inline void mtmsr_isync(unsigned long val)
: "r" ((unsigned long)(v)) \
: "memory")
#define wrtspr(rn) asm volatile("mtspr " __stringify(rn) ",2" : : : "memory")
+#define wrtspr_sync(rn) asm volatile("mtspr " __stringify(rn) ",2; sync" : : : "memory")
static inline void wrtee(unsigned long val)
{
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 7f63f1cdc6c3..ca00c4824e31 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -20,6 +20,7 @@
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/udbg.h>
+#include <asm/setup.h>
#define NO_SCROLL
@@ -463,7 +464,7 @@ static noinline void draw_byte(unsigned char c, long locX, long locY)
{
unsigned char *base = calc_base(locX << 3, locY << 4);
unsigned int font_index = c * 16;
- const unsigned char *font = font_sun_8x16.data + font_index;
+ const unsigned char *font = PTRRELOC(font_sun_8x16.data) + font_index;
int rb = dispDeviceRowBytes;
rmci_maybe_on();
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 16f8ee6cb2cd..d8426251b1cd 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -101,17 +101,6 @@ SYM_FUNC_END(__kuep_unlock)
.endm
#endif
-.macro clr_ri trash
-#ifndef CONFIG_BOOKE
-#ifdef CONFIG_PPC_8xx
- mtspr SPRN_NRI, \trash
-#else
- li \trash, MSR_KERNEL & ~MSR_RI
- mtmsr \trash
-#endif
-#endif
-.endm
-
.globl transfer_to_syscall
transfer_to_syscall:
stw r3, ORIG_GPR3(r1)
@@ -160,7 +149,6 @@ ret_from_syscall:
cmpwi r3,0
REST_GPR(3, r1)
syscall_exit_finish:
- clr_ri r4
mtspr SPRN_SRR0,r7
mtspr SPRN_SRR1,r8
@@ -237,7 +225,6 @@ fast_exception_return:
/* Clear the exception marker on the stack to avoid confusing stacktrace */
li r10, 0
stw r10, 8(r11)
- clr_ri r10
mtspr SPRN_SRR1,r9
mtspr SPRN_SRR0,r12
REST_GPR(9, r11)
@@ -270,7 +257,6 @@ interrupt_return:
.Lfast_user_interrupt_return:
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
- clr_ri r4
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r12
@@ -313,7 +299,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
cmpwi cr1,r3,0
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
- clr_ri r4
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r12
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index aea6f7e8e9c6..e63bfde13e03 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -38,7 +38,7 @@ static inline bool exit_must_hard_disable(void)
#else
static inline bool exit_must_hard_disable(void)
{
- return false;
+ return true;
}
#endif
@@ -443,6 +443,9 @@ again:
if (unlikely(stack_store))
__hard_EE_RI_disable();
+#else
+ } else {
+ __hard_EE_RI_disable();
#endif /* CONFIG_PPC64 */
}
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index 222aa326dace..825ab8a88f18 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -202,6 +202,23 @@ static void kexec_prepare_cpus_wait(int wait_state)
mb();
}
+
+/*
+ * The add_cpu() call in wake_offline_cpus() can fail as cpu_bootable()
+ * returns false for CPUs that fail the cpu_smt_thread_allowed() check
+ * or non primary threads if SMT is disabled. Re-enable SMT and set the
+ * number of SMT threads to threads per core.
+ */
+static void kexec_smt_reenable(void)
+{
+#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
+ lock_device_hotplug();
+ cpu_smt_num_threads = threads_per_core;
+ cpu_smt_control = CPU_SMT_ENABLED;
+ unlock_device_hotplug();
+#endif
+}
+
/*
* We need to make sure each present CPU is online. The next kernel will scan
* the device tree and assume primary threads are online and query secondary
@@ -216,6 +233,8 @@ static void wake_offline_cpus(void)
{
int cpu = 0;
+ kexec_smt_reenable();
+
for_each_present_cpu(cpu) {
if (!cpu_online(cpu)) {
printk(KERN_INFO "kexec: Waking offline cpu %d.\n",
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index d98b933e4984..e4f4e907f6e3 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -1171,8 +1171,9 @@ static void __init pnv_arch300_idle_init(void)
u64 max_residency_ns = 0;
int i;
- /* stop is not really architected, we only have p9,p10 drivers */
- if (!pvr_version_is(PVR_POWER10) && !pvr_version_is(PVR_POWER9))
+ /* stop is not really architected, we only have p9,p10 and p11 drivers */
+ if (!pvr_version_is(PVR_POWER9) && !pvr_version_is(PVR_POWER10) &&
+ !pvr_version_is(PVR_POWER11))
return;
/*
@@ -1189,8 +1190,8 @@ static void __init pnv_arch300_idle_init(void)
struct pnv_idle_states_t *state = &pnv_idle_states[i];
u64 psscr_rl = state->psscr_val & PSSCR_RL_MASK;
- /* No deep loss driver implemented for POWER10 yet */
- if (pvr_version_is(PVR_POWER10) &&
+ /* No deep loss driver implemented for POWER10 and POWER11 yet */
+ if ((pvr_version_is(PVR_POWER10) || pvr_version_is(PVR_POWER11)) &&
state->flags & (OPAL_PM_TIMEBASE_STOP|OPAL_PM_LOSE_FULL_CONTEXT))
continue;
diff --git a/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh b/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
index 06706903503b..baed467a016b 100755
--- a/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
+++ b/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
set -e
-set -o pipefail
# To debug, uncomment the following line
# set -x
diff --git a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
index 73e331e7660e..6193b0ed0c77 100755
--- a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
+++ b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0
set -e
-set -o pipefail
# To debug, uncomment the following line
# set -x
diff --git a/arch/riscv/include/asm/atomic.h b/arch/riscv/include/asm/atomic.h
index 5b96c2f61adb..3f33dc54f94b 100644
--- a/arch/riscv/include/asm/atomic.h
+++ b/arch/riscv/include/asm/atomic.h
@@ -203,7 +203,7 @@ ATOMIC_OPS(xor, xor, i)
" add %[rc], %[p], %[a]\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
- " fence rw, rw\n" \
+ RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: [a]"r" (_a), [u]"r" (_u) \
@@ -242,7 +242,7 @@ static __always_inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a,
" addi %[rc], %[p], 1\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
- " fence rw, rw\n" \
+ RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: \
@@ -268,7 +268,7 @@ static __always_inline bool arch_atomic_inc_unless_negative(atomic_t *v)
" addi %[rc], %[p], -1\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
- " fence rw, rw\n" \
+ RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: \
@@ -294,7 +294,7 @@ static __always_inline bool arch_atomic_dec_unless_positive(atomic_t *v)
" bltz %[rc], 1f\n" \
" sc." sfx ".rl %[rc], %[rc], %[c]\n" \
" bnez %[rc], 0b\n" \
- " fence rw, rw\n" \
+ RISCV_FULL_BARRIER \
"1:\n" \
: [p]"=&r" (_prev), [rc]"=&r" (_rc), [c]"+A" (counter) \
: \
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index dfe57b215e6c..4369a2338541 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -108,6 +108,8 @@
#define RISCV_ISA_EXT_ZICBOP 99
#define RISCV_ISA_EXT_SVRSW60T59B 100
#define RISCV_ISA_EXT_ZALASR 101
+#define RISCV_ISA_EXT_ZILSD 102
+#define RISCV_ISA_EXT_ZCLSD 103
#define RISCV_ISA_EXT_XLINUXENVCFG 127
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 8bd36ac842eb..6bb1f5bdc5d2 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -660,7 +660,13 @@ extern int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long a
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, pte_t *ptep)
{
- pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+#ifdef CONFIG_SMP
+ pte_t pte = __pte(xchg(&ptep->pte, 0));
+#else
+ pte_t pte = *ptep;
+
+ set_pte(ptep, __pte(0));
+#endif
page_table_check_pte_clear(mm, pte);
@@ -997,7 +1003,13 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
unsigned long address, pmd_t *pmdp)
{
- pmd_t pmd = __pmd(atomic_long_xchg((atomic_long_t *)pmdp, 0));
+#ifdef CONFIG_SMP
+ pmd_t pmd = __pmd(xchg(&pmdp->pmd, 0));
+#else
+ pmd_t pmd = *pmdp;
+
+ pmd_clear(pmdp);
+#endif
page_table_check_pmd_clear(mm, pmd);
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index ccc77a89b1e2..5725e0ca4dda 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -37,6 +37,7 @@ enum sbi_ext_id {
SBI_EXT_NACL = 0x4E41434C,
SBI_EXT_FWFT = 0x46574654,
SBI_EXT_MPXY = 0x4D505859,
+ SBI_EXT_DBTR = 0x44425452,
/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@@ -505,6 +506,34 @@ enum sbi_mpxy_rpmi_attribute_id {
#define SBI_MPXY_CHAN_CAP_SEND_WITHOUT_RESP BIT(4)
#define SBI_MPXY_CHAN_CAP_GET_NOTIFICATIONS BIT(5)
+/* SBI debug triggers function IDs */
+enum sbi_ext_dbtr_fid {
+ SBI_EXT_DBTR_NUM_TRIGGERS = 0,
+ SBI_EXT_DBTR_SETUP_SHMEM,
+ SBI_EXT_DBTR_TRIG_READ,
+ SBI_EXT_DBTR_TRIG_INSTALL,
+ SBI_EXT_DBTR_TRIG_UPDATE,
+ SBI_EXT_DBTR_TRIG_UNINSTALL,
+ SBI_EXT_DBTR_TRIG_ENABLE,
+ SBI_EXT_DBTR_TRIG_DISABLE,
+};
+
+struct sbi_dbtr_data_msg {
+ unsigned long tstate;
+ unsigned long tdata1;
+ unsigned long tdata2;
+ unsigned long tdata3;
+};
+
+struct sbi_dbtr_id_msg {
+ unsigned long idx;
+};
+
+union sbi_dbtr_shmem_entry {
+ struct sbi_dbtr_data_msg data;
+ struct sbi_dbtr_id_msg id;
+};
+
/* SBI spec version fields */
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
index e7aa449368ad..00cb9c0982b1 100644
--- a/arch/riscv/include/asm/vector.h
+++ b/arch/riscv/include/asm/vector.h
@@ -424,6 +424,9 @@ static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
#define riscv_v_thread_free(tsk) do {} while (0)
#define riscv_v_setup_ctx_cache() do {} while (0)
#define riscv_v_thread_alloc(tsk) do {} while (0)
+#define get_cpu_vector_context() do {} while (0)
+#define put_cpu_vector_context() do {} while (0)
+#define riscv_v_vstate_set_restore(task, regs) do {} while (0)
#endif /* CONFIG_RISCV_ISA_V */
diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
index 1edea2331b8b..cd3c126730c3 100644
--- a/arch/riscv/include/uapi/asm/hwprobe.h
+++ b/arch/riscv/include/uapi/asm/hwprobe.h
@@ -84,6 +84,9 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_EXT_ZABHA (1ULL << 58)
#define RISCV_HWPROBE_EXT_ZALASR (1ULL << 59)
#define RISCV_HWPROBE_EXT_ZICBOP (1ULL << 60)
+#define RISCV_HWPROBE_EXT_ZILSD (1ULL << 61)
+#define RISCV_HWPROBE_EXT_ZCLSD (1ULL << 62)
+
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index b057362f8fb5..c05b11596c19 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -242,6 +242,28 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data,
return -EPROBE_DEFER;
}
+static int riscv_ext_zilsd_validate(const struct riscv_isa_ext_data *data,
+ const unsigned long *isa_bitmap)
+{
+ if (IS_ENABLED(CONFIG_64BIT))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int riscv_ext_zclsd_validate(const struct riscv_isa_ext_data *data,
+ const unsigned long *isa_bitmap)
+{
+ if (IS_ENABLED(CONFIG_64BIT))
+ return -EINVAL;
+
+ if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZILSD) &&
+ __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZCA))
+ return 0;
+
+ return -EPROBE_DEFER;
+}
+
static int riscv_vector_f_validate(const struct riscv_isa_ext_data *data,
const unsigned long *isa_bitmap)
{
@@ -484,6 +506,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA_VALIDATE(zcd, RISCV_ISA_EXT_ZCD, riscv_ext_zcd_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zcf, RISCV_ISA_EXT_ZCF, riscv_ext_zcf_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zcmop, RISCV_ISA_EXT_ZCMOP, riscv_ext_zca_depends),
+ __RISCV_ISA_EXT_DATA_VALIDATE(zclsd, RISCV_ISA_EXT_ZCLSD, riscv_ext_zclsd_validate),
+ __RISCV_ISA_EXT_DATA_VALIDATE(zilsd, RISCV_ISA_EXT_ZILSD, riscv_ext_zilsd_validate),
__RISCV_ISA_EXT_DATA(zba, RISCV_ISA_EXT_ZBA),
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
__RISCV_ISA_EXT_DATA(zbc, RISCV_ISA_EXT_ZBC),
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 08378fea3a11..5a956108b1ea 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -68,18 +68,19 @@ static long save_fp_state(struct pt_regs *regs,
#define restore_fp_state(task, regs) (0)
#endif
-#ifdef CONFIG_RISCV_ISA_V
-
-static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
+static long save_v_state(struct pt_regs *regs, void __user *sc_vec)
{
- struct __riscv_ctx_hdr __user *hdr;
struct __sc_riscv_v_state __user *state;
void __user *datap;
long err;
- hdr = *sc_vec;
- /* Place state to the user's signal context space after the hdr */
- state = (struct __sc_riscv_v_state __user *)(hdr + 1);
+ if (!IS_ENABLED(CONFIG_RISCV_ISA_V) ||
+ !((has_vector() || has_xtheadvector()) &&
+ riscv_v_vstate_query(regs)))
+ return 0;
+
+ /* Place state to the user's signal context space */
+ state = (struct __sc_riscv_v_state __user *)sc_vec;
/* Point datap right after the end of __sc_riscv_v_state */
datap = state + 1;
@@ -97,15 +98,11 @@ static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
err |= __put_user((__force void *)datap, &state->v_state.datap);
/* Copy the whole vector content to user space datap. */
err |= __copy_to_user(datap, current->thread.vstate.datap, riscv_v_vsize);
- /* Copy magic to the user space after saving all vector conetext */
- err |= __put_user(RISCV_V_MAGIC, &hdr->magic);
- err |= __put_user(riscv_v_sc_size, &hdr->size);
if (unlikely(err))
- return err;
+ return -EFAULT;
- /* Only progress the sv_vec if everything has done successfully */
- *sc_vec += riscv_v_sc_size;
- return 0;
+ /* Only return the size if everything has done successfully */
+ return riscv_v_sc_size;
}
/*
@@ -142,10 +139,20 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
*/
return copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize);
}
-#else
-#define save_v_state(task, regs) (0)
-#define __restore_v_state(task, regs) (0)
-#endif
+
+struct arch_ext_priv {
+ __u32 magic;
+ long (*save)(struct pt_regs *regs, void __user *sc_vec);
+};
+
+struct arch_ext_priv arch_ext_list[] = {
+ {
+ .magic = RISCV_V_MAGIC,
+ .save = &save_v_state,
+ },
+};
+
+const size_t nr_arch_exts = ARRAY_SIZE(arch_ext_list);
static long restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
@@ -270,7 +277,8 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
{
struct sigcontext __user *sc = &frame->uc.uc_mcontext;
struct __riscv_ctx_hdr __user *sc_ext_ptr = &sc->sc_extdesc.hdr;
- long err;
+ struct arch_ext_priv *arch_ext;
+ long err, i, ext_size;
/* sc_regs is structured the same as the start of pt_regs */
err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
@@ -278,8 +286,20 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
if (has_fpu())
err |= save_fp_state(regs, &sc->sc_fpregs);
/* Save the vector state. */
- if ((has_vector() || has_xtheadvector()) && riscv_v_vstate_query(regs))
- err |= save_v_state(regs, (void __user **)&sc_ext_ptr);
+ for (i = 0; i < nr_arch_exts; i++) {
+ arch_ext = &arch_ext_list[i];
+ if (!arch_ext->save)
+ continue;
+
+ ext_size = arch_ext->save(regs, sc_ext_ptr + 1);
+ if (ext_size <= 0) {
+ err |= ext_size;
+ } else {
+ err |= __put_user(arch_ext->magic, &sc_ext_ptr->magic);
+ err |= __put_user(ext_size, &sc_ext_ptr->size);
+ sc_ext_ptr = (void *)sc_ext_ptr + ext_size;
+ }
+ }
/* Write zero to fp-reserved space and check it on restore_sigcontext */
err |= __put_user(0, &sc->sc_extdesc.reserved);
/* And put END __riscv_ctx_hdr at the end. */
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index 0f701ace3bb9..e6787ba7f2fc 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -121,6 +121,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZBS);
EXT_KEY(ZCA);
EXT_KEY(ZCB);
+ EXT_KEY(ZCLSD);
EXT_KEY(ZCMOP);
EXT_KEY(ZICBOM);
EXT_KEY(ZICBOP);
@@ -130,6 +131,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZIHINTNTL);
EXT_KEY(ZIHINTPAUSE);
EXT_KEY(ZIHPM);
+ EXT_KEY(ZILSD);
EXT_KEY(ZIMOP);
EXT_KEY(ZKND);
EXT_KEY(ZKNE);
diff --git a/arch/s390/include/uapi/asm/ipl.h b/arch/s390/include/uapi/asm/ipl.h
index 2cd28af50dd4..3d64a2251699 100644
--- a/arch/s390/include/uapi/asm/ipl.h
+++ b/arch/s390/include/uapi/asm/ipl.h
@@ -15,6 +15,7 @@ struct ipl_pl_hdr {
#define IPL_PL_FLAG_IPLPS 0x80
#define IPL_PL_FLAG_SIPL 0x40
#define IPL_PL_FLAG_IPLSR 0x20
+#define IPL_PL_FLAG_SBP 0x10
/* IPL Parameter Block header */
struct ipl_pb_hdr {
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 961a3d60a4dd..dcdc7e274848 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -262,6 +262,24 @@ static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
sys_##_prefix##_##_name##_show, \
sys_##_prefix##_##_name##_store)
+#define DEFINE_IPL_ATTR_BOOTPROG_RW(_prefix, _name, _fmt_out, _fmt_in, _hdr, _value) \
+ IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, (unsigned long long) _value) \
+static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, size_t len) \
+{ \
+ unsigned long long value; \
+ if (sscanf(buf, _fmt_in, &value) != 1) \
+ return -EINVAL; \
+ (_value) = value; \
+ (_hdr).flags &= ~IPL_PL_FLAG_SBP; \
+ return len; \
+} \
+static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
+ __ATTR(_name, 0644, \
+ sys_##_prefix##_##_name##_show, \
+ sys_##_prefix##_##_name##_store)
+
#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, _value) \
static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
@@ -818,12 +836,13 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
reipl_block_fcp->fcp.wwpn);
DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
reipl_block_fcp->fcp.lun);
-DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
- reipl_block_fcp->fcp.bootprog);
DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
reipl_block_fcp->fcp.br_lba);
DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
reipl_block_fcp->fcp.devno);
+DEFINE_IPL_ATTR_BOOTPROG_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
+ reipl_block_fcp->hdr,
+ reipl_block_fcp->fcp.bootprog);
static void reipl_get_ascii_loadparm(char *loadparm,
struct ipl_parameter_block *ibp)
@@ -942,10 +961,11 @@ DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n",
reipl_block_nvme->nvme.fid);
DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n",
reipl_block_nvme->nvme.nsid);
-DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
- reipl_block_nvme->nvme.bootprog);
DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n",
reipl_block_nvme->nvme.br_lba);
+DEFINE_IPL_ATTR_BOOTPROG_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
+ reipl_block_nvme->hdr,
+ reipl_block_nvme->nvme.bootprog);
static struct attribute *reipl_nvme_attrs[] = {
&sys_reipl_nvme_fid_attr.attr,
@@ -1038,8 +1058,9 @@ static const struct bin_attribute *const reipl_eckd_bin_attrs[] = {
};
DEFINE_IPL_CCW_ATTR_RW(reipl_eckd, device, reipl_block_eckd->eckd);
-DEFINE_IPL_ATTR_RW(reipl_eckd, bootprog, "%lld\n", "%lld\n",
- reipl_block_eckd->eckd.bootprog);
+DEFINE_IPL_ATTR_BOOTPROG_RW(reipl_eckd, bootprog, "%lld\n", "%lld\n",
+ reipl_block_eckd->hdr,
+ reipl_block_eckd->eckd.bootprog);
static struct attribute *reipl_eckd_attrs[] = {
&sys_reipl_eckd_device_attr.attr,
@@ -1567,12 +1588,13 @@ DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
dump_block_fcp->fcp.wwpn);
DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
dump_block_fcp->fcp.lun);
-DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
- dump_block_fcp->fcp.bootprog);
DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
dump_block_fcp->fcp.br_lba);
DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
dump_block_fcp->fcp.devno);
+DEFINE_IPL_ATTR_BOOTPROG_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
+ dump_block_fcp->hdr,
+ dump_block_fcp->fcp.bootprog);
DEFINE_IPL_ATTR_SCP_DATA_RW(dump_fcp, dump_block_fcp->hdr,
dump_block_fcp->fcp,
@@ -1604,10 +1626,11 @@ DEFINE_IPL_ATTR_RW(dump_nvme, fid, "0x%08llx\n", "%llx\n",
dump_block_nvme->nvme.fid);
DEFINE_IPL_ATTR_RW(dump_nvme, nsid, "0x%08llx\n", "%llx\n",
dump_block_nvme->nvme.nsid);
-DEFINE_IPL_ATTR_RW(dump_nvme, bootprog, "%lld\n", "%llx\n",
- dump_block_nvme->nvme.bootprog);
DEFINE_IPL_ATTR_RW(dump_nvme, br_lba, "%lld\n", "%llx\n",
dump_block_nvme->nvme.br_lba);
+DEFINE_IPL_ATTR_BOOTPROG_RW(dump_nvme, bootprog, "%lld\n", "%llx\n",
+ dump_block_nvme->hdr,
+ dump_block_nvme->nvme.bootprog);
DEFINE_IPL_ATTR_SCP_DATA_RW(dump_nvme, dump_block_nvme->hdr,
dump_block_nvme->nvme,
@@ -1635,8 +1658,9 @@ static const struct attribute_group dump_nvme_attr_group = {
/* ECKD dump device attributes */
DEFINE_IPL_CCW_ATTR_RW(dump_eckd, device, dump_block_eckd->eckd);
-DEFINE_IPL_ATTR_RW(dump_eckd, bootprog, "%lld\n", "%llx\n",
- dump_block_eckd->eckd.bootprog);
+DEFINE_IPL_ATTR_BOOTPROG_RW(dump_eckd, bootprog, "%lld\n", "%llx\n",
+ dump_block_eckd->hdr,
+ dump_block_eckd->eckd.bootprog);
IPL_ATTR_BR_CHR_SHOW_FN(dump, dump_block_eckd->eckd);
IPL_ATTR_BR_CHR_STORE_FN(dump, dump_block_eckd->eckd);
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 3aae7f70e6ab..18520d333058 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -104,7 +104,6 @@ void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *coo
struct stack_frame_vdso_wrapper __user *sf_vdso;
struct stack_frame_user __user *sf;
unsigned long ip, sp;
- bool first = true;
if (!current->mm)
return;
@@ -133,24 +132,11 @@ void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *coo
if (__get_user(ip, &sf->gprs[8]))
break;
}
- /* Sanity check: ABI requires SP to be 8 byte aligned. */
- if (sp & 0x7)
+ /* Validate SP and RA (ABI requires SP to be 8 byte aligned). */
+ if (sp & 0x7 || ip_invalid(ip))
break;
- if (ip_invalid(ip)) {
- /*
- * If the instruction address is invalid, and this
- * is the first stack frame, assume r14 has not
- * been written to the stack yet. Otherwise exit.
- */
- if (!first)
- break;
- ip = regs->gprs[14];
- if (ip_invalid(ip))
- break;
- }
if (!store_ip(consume_entry, cookie, entry, perf, ip))
break;
- first = false;
}
pagefault_enable();
}
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 5a6ace9d875a..57f3980b98a9 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -961,6 +961,7 @@ void zpci_device_reserved(struct zpci_dev *zdev)
}
void zpci_release_device(struct kref *kref)
+ __releases(&zpci_list_lock)
{
struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
@@ -1148,6 +1149,7 @@ static void zpci_add_devices(struct list_head *scan_list)
int zpci_scan_devices(void)
{
+ struct zpci_bus *zbus;
LIST_HEAD(scan_list);
int rc;
@@ -1156,7 +1158,10 @@ int zpci_scan_devices(void)
return rc;
zpci_add_devices(&scan_list);
- zpci_bus_scan_busses();
+ zpci_bus_for_each(zbus) {
+ zpci_bus_scan_bus(zbus);
+ cond_resched();
+ }
return 0;
}
diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c
index 66c4bd888b29..42a13e451f64 100644
--- a/arch/s390/pci/pci_bus.c
+++ b/arch/s390/pci/pci_bus.c
@@ -153,23 +153,6 @@ int zpci_bus_scan_bus(struct zpci_bus *zbus)
return ret;
}
-/* zpci_bus_scan_busses - Scan all registered busses
- *
- * Scan all available zbusses
- *
- */
-void zpci_bus_scan_busses(void)
-{
- struct zpci_bus *zbus = NULL;
-
- mutex_lock(&zbus_list_lock);
- list_for_each_entry(zbus, &zbus_list, bus_next) {
- zpci_bus_scan_bus(zbus);
- cond_resched();
- }
- mutex_unlock(&zbus_list_lock);
-}
-
static bool zpci_bus_is_multifunction_root(struct zpci_dev *zdev)
{
return !s390_pci_no_rid && zdev->rid_available &&
@@ -222,10 +205,29 @@ out_free_domain:
return -ENOMEM;
}
-static void zpci_bus_release(struct kref *kref)
+/**
+ * zpci_bus_release - Un-initialize resources associated with the zbus and
+ * free memory
+ * @kref: refcount * that is part of struct zpci_bus
+ *
+ * MUST be called with `zbus_list_lock` held, but the lock is released during
+ * run of the function.
+ */
+static inline void zpci_bus_release(struct kref *kref)
+ __releases(&zbus_list_lock)
{
struct zpci_bus *zbus = container_of(kref, struct zpci_bus, kref);
+ lockdep_assert_held(&zbus_list_lock);
+
+ list_del(&zbus->bus_next);
+ mutex_unlock(&zbus_list_lock);
+
+ /*
+ * At this point no-one should see this object, or be able to get a new
+ * reference to it.
+ */
+
if (zbus->bus) {
pci_lock_rescan_remove();
pci_stop_root_bus(zbus->bus);
@@ -237,16 +239,19 @@ static void zpci_bus_release(struct kref *kref)
pci_unlock_rescan_remove();
}
- mutex_lock(&zbus_list_lock);
- list_del(&zbus->bus_next);
- mutex_unlock(&zbus_list_lock);
zpci_remove_parent_msi_domain(zbus);
kfree(zbus);
}
-static void zpci_bus_put(struct zpci_bus *zbus)
+static inline void __zpci_bus_get(struct zpci_bus *zbus)
+{
+ lockdep_assert_held(&zbus_list_lock);
+ kref_get(&zbus->kref);
+}
+
+static inline void zpci_bus_put(struct zpci_bus *zbus)
{
- kref_put(&zbus->kref, zpci_bus_release);
+ kref_put_mutex(&zbus->kref, zpci_bus_release, &zbus_list_lock);
}
static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid)
@@ -258,7 +263,7 @@ static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid)
if (!zbus->multifunction)
continue;
if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) {
- kref_get(&zbus->kref);
+ __zpci_bus_get(zbus);
goto out_unlock;
}
}
@@ -268,6 +273,44 @@ out_unlock:
return zbus;
}
+/**
+ * zpci_bus_get_next - get the next zbus object from given position in the list
+ * @pos: current position/cursor in the global zbus list
+ *
+ * Acquires and releases references as the cursor iterates (might also free/
+ * release the cursor). Is tolerant of concurrent operations on the list.
+ *
+ * To begin the iteration, set *@pos to %NULL before calling the function.
+ *
+ * *@pos is set to %NULL in cases where either the list is empty, or *@pos is
+ * the last element in the list.
+ *
+ * Context: Process context. May sleep.
+ */
+void zpci_bus_get_next(struct zpci_bus **pos)
+{
+ struct zpci_bus *curp = *pos, *next = NULL;
+
+ mutex_lock(&zbus_list_lock);
+ if (curp)
+ next = list_next_entry(curp, bus_next);
+ else
+ next = list_first_entry(&zbus_list, typeof(*curp), bus_next);
+
+ if (list_entry_is_head(next, &zbus_list, bus_next))
+ next = NULL;
+
+ if (next)
+ __zpci_bus_get(next);
+
+ *pos = next;
+ mutex_unlock(&zbus_list_lock);
+
+ /* zpci_bus_put() might drop refcount to 0 and locks zbus_list_lock */
+ if (curp)
+ zpci_bus_put(curp);
+}
+
static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid)
{
struct zpci_bus *zbus;
@@ -279,9 +322,6 @@ static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid)
zbus->topo = topo;
zbus->topo_is_tid = topo_is_tid;
INIT_LIST_HEAD(&zbus->bus_next);
- mutex_lock(&zbus_list_lock);
- list_add_tail(&zbus->bus_next, &zbus_list);
- mutex_unlock(&zbus_list_lock);
kref_init(&zbus->kref);
INIT_LIST_HEAD(&zbus->resources);
@@ -291,6 +331,10 @@ static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid)
zbus->bus_resource.flags = IORESOURCE_BUS;
pci_add_resource(&zbus->resources, &zbus->bus_resource);
+ mutex_lock(&zbus_list_lock);
+ list_add_tail(&zbus->bus_next, &zbus_list);
+ mutex_unlock(&zbus_list_lock);
+
return zbus;
}
diff --git a/arch/s390/pci/pci_bus.h b/arch/s390/pci/pci_bus.h
index ae3d7a9159bd..e440742e3145 100644
--- a/arch/s390/pci/pci_bus.h
+++ b/arch/s390/pci/pci_bus.h
@@ -15,7 +15,20 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops);
void zpci_bus_device_unregister(struct zpci_dev *zdev);
int zpci_bus_scan_bus(struct zpci_bus *zbus);
-void zpci_bus_scan_busses(void);
+void zpci_bus_get_next(struct zpci_bus **pos);
+
+/**
+ * zpci_bus_for_each - iterate over all the registered zbus objects
+ * @pos: a struct zpci_bus * as cursor
+ *
+ * Acquires and releases references as the cursor iterates over the registered
+ * objects. Is tolerant against concurrent removals of objects.
+ *
+ * Context: Process context. May sleep.
+ */
+#define zpci_bus_for_each(pos) \
+ for ((pos) = NULL, zpci_bus_get_next(&(pos)); (pos) != NULL; \
+ zpci_bus_get_next(&(pos)))
int zpci_bus_scan_device(struct zpci_dev *zdev);
void zpci_bus_remove_device(struct zpci_dev *zdev, bool set_error);
diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h
index d561a8443c13..9b4e04690e1a 100644
--- a/arch/x86/include/asm/bug.h
+++ b/arch/x86/include/asm/bug.h
@@ -15,7 +15,7 @@ extern void __WARN_trap(struct bug_entry *bug, ...);
/*
* Despite that some emulators terminate on UD2, we use it for WARN().
*/
-#define ASM_UD2 _ASM_BYTES(0x0f, 0x0b)
+#define ASM_UD2 __ASM_FORM(ud2)
#define INSN_UD2 0x0b0f
#define LEN_UD2 2
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 5a0d42464d44..4e55d1755846 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -87,4 +87,11 @@ static inline void panic_if_irq_remap(const char *msg)
}
#endif /* CONFIG_IRQ_REMAP */
+
+#ifdef CONFIG_X86_POSTED_MSI
+void intel_ack_posted_msi_irq(struct irq_data *irqd);
+#else
+#define intel_ack_posted_msi_irq NULL
+#endif
+
#endif /* __X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h
index b30e5474c18e..a1193e9d65f2 100644
--- a/arch/x86/include/asm/irqflags.h
+++ b/arch/x86/include/asm/irqflags.h
@@ -25,7 +25,7 @@ extern __always_inline unsigned long native_save_fl(void)
*/
asm volatile("# __raw_save_flags\n\t"
"pushf ; pop %0"
- : "=rm" (flags)
+ : ASM_OUTPUT_RM (flags)
: /* no input */
: "memory");
diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index 6989b824fd32..d0b62e255290 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -122,7 +122,7 @@ struct uv_systab {
struct {
u32 type:8; /* type of entry */
u32 offset:24; /* byte offset from struct start to entry */
- } entry[1]; /* additional entries follow */
+ } entry[]; /* additional entries follow */
};
extern struct uv_systab *uv_systab;
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 3821a985f4ff..46673530bc6f 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -258,7 +258,7 @@ static bool cpu_has_entrysign(void)
if (fam == 0x1a) {
if (model <= 0x2f ||
(0x40 <= model && model <= 0x4f) ||
- (0x60 <= model && model <= 0x6f))
+ (0x60 <= model && model <= 0x7f))
return true;
}
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 66f1efa16fbb..9322a9287dc7 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -242,7 +242,7 @@ static int __sgx_encl_add_page(struct sgx_encl *encl,
/*
* If the caller requires measurement of the page as a proof for the content,
* use EEXTEND to add a measurement for 256 bytes of the page. Repeat this
- * operation until the entire page is measured."
+ * operation until the entire page is measured.
*/
static int __sgx_encl_extend(struct sgx_encl *encl,
struct sgx_epc_page *epc_page)
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 48113c5193aa..76153dfb58c9 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1946,7 +1946,7 @@ static int dump_xsave_layout_desc(struct coredump_params *cprm)
};
if (!dump_emit(cprm, &xc, sizeof(xc)))
- return 0;
+ return -1;
num_records++;
}
@@ -1984,7 +1984,7 @@ int elf_coredump_extra_notes_write(struct coredump_params *cprm)
return 1;
num_records = dump_xsave_layout_desc(cprm);
- if (!num_records)
+ if (num_records < 0)
return 1;
/* Total size should be equal to the number of records */
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 86f4e574de02..b2fe6181960c 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -397,6 +397,7 @@ DEFINE_IDTENTRY_SYSVEC_SIMPLE(sysvec_kvm_posted_intr_nested_ipi)
/* Posted Interrupt Descriptors for coalesced MSIs to be posted */
DEFINE_PER_CPU_ALIGNED(struct pi_desc, posted_msi_pi_desc);
+static DEFINE_PER_CPU_CACHE_HOT(bool, posted_msi_handler_active);
void intel_posted_msi_init(void)
{
@@ -414,6 +415,25 @@ void intel_posted_msi_init(void)
this_cpu_write(posted_msi_pi_desc.ndst, destination);
}
+void intel_ack_posted_msi_irq(struct irq_data *irqd)
+{
+ irq_move_irq(irqd);
+
+ /*
+ * Handle the rare case that irq_retrigger() raised the actual
+ * assigned vector on the target CPU, which means that it was not
+ * invoked via the posted MSI handler below. In that case APIC EOI
+ * is required as otherwise the ISR entry becomes stale and lower
+ * priority interrupts are never going to be delivered after that.
+ *
+ * If the posted handler invoked the device interrupt handler then
+ * the EOI would be premature because it would acknowledge the
+ * posted vector.
+ */
+ if (unlikely(!__this_cpu_read(posted_msi_handler_active)))
+ apic_eoi();
+}
+
static __always_inline bool handle_pending_pir(unsigned long *pir, struct pt_regs *regs)
{
unsigned long pir_copy[NR_PIR_WORDS];
@@ -446,6 +466,8 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_posted_msi_notification)
pid = this_cpu_ptr(&posted_msi_pi_desc);
+ /* Mark the handler active for intel_ack_posted_msi_irq() */
+ __this_cpu_write(posted_msi_handler_active, true);
inc_irq_stat(posted_msi_notification_count);
irq_enter();
@@ -474,6 +496,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_posted_msi_notification)
apic_eoi();
irq_exit();
+ __this_cpu_write(posted_msi_handler_active, false);
set_irq_regs(old_regs);
}
#endif /* X86_POSTED_MSI */
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index 977ee75e047c..f610fde2d5c4 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -2,6 +2,7 @@
#include <linux/objtool.h>
#include <linux/module.h>
#include <linux/sort.h>
+#include <linux/bpf.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>
#include <asm/unwind.h>
@@ -172,6 +173,25 @@ static struct orc_entry *orc_ftrace_find(unsigned long ip)
}
#endif
+/* Fake frame pointer entry -- used as a fallback for generated code */
+static struct orc_entry orc_fp_entry = {
+ .type = ORC_TYPE_CALL,
+ .sp_reg = ORC_REG_BP,
+ .sp_offset = 16,
+ .bp_reg = ORC_REG_PREV_SP,
+ .bp_offset = -16,
+};
+
+static struct orc_entry *orc_bpf_find(unsigned long ip)
+{
+#ifdef CONFIG_BPF_JIT
+ if (bpf_has_frame_pointer(ip))
+ return &orc_fp_entry;
+#endif
+
+ return NULL;
+}
+
/*
* If we crash with IP==0, the last successfully executed instruction
* was probably an indirect function call with a NULL function pointer,
@@ -186,15 +206,6 @@ static struct orc_entry null_orc_entry = {
.type = ORC_TYPE_CALL
};
-/* Fake frame pointer entry -- used as a fallback for generated code */
-static struct orc_entry orc_fp_entry = {
- .type = ORC_TYPE_CALL,
- .sp_reg = ORC_REG_BP,
- .sp_offset = 16,
- .bp_reg = ORC_REG_PREV_SP,
- .bp_offset = -16,
-};
-
static struct orc_entry *orc_find(unsigned long ip)
{
static struct orc_entry *orc;
@@ -238,6 +249,11 @@ static struct orc_entry *orc_find(unsigned long ip)
if (orc)
return orc;
+ /* BPF lookup: */
+ orc = orc_bpf_find(ip);
+ if (orc)
+ return orc;
+
return orc_ftrace_find(ip);
}
@@ -495,9 +511,8 @@ bool unwind_next_frame(struct unwind_state *state)
if (!orc) {
/*
* As a fallback, try to assume this code uses a frame pointer.
- * This is useful for generated code, like BPF, which ORC
- * doesn't know about. This is just a guess, so the rest of
- * the unwind is no longer considered reliable.
+ * This is just a guess, so the rest of the unwind is no longer
+ * considered reliable.
*/
orc = &orc_fp_entry;
state->error = true;
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index d563a948318b..88a5426674a1 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -510,10 +510,17 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
int r;
/*
+ * Apply pending runtime CPUID updates to the current CPUID entries to
+ * avoid false positives due to mismatches on KVM-owned feature flags.
+ */
+ if (vcpu->arch.cpuid_dynamic_bits_dirty)
+ kvm_update_cpuid_runtime(vcpu);
+
+ /*
* Swap the existing (old) entries with the incoming (new) entries in
* order to massage the new entries, e.g. to account for dynamic bits
- * that KVM controls, without clobbering the current guest CPUID, which
- * KVM needs to preserve in order to unwind on failure.
+ * that KVM controls, without losing the current guest CPUID, which KVM
+ * needs to preserve in order to unwind on failure.
*
* Similarly, save the vCPU's current cpu_caps so that the capabilities
* can be updated alongside the CPUID entries when performing runtime
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index c81005b24522..ba0f11c68372 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -985,7 +985,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu)
if (!nested_vmcb_check_save(vcpu) ||
!nested_vmcb_check_controls(vcpu)) {
vmcb12->control.exit_code = SVM_EXIT_ERR;
- vmcb12->control.exit_code_hi = 0;
+ vmcb12->control.exit_code_hi = -1u;
vmcb12->control.exit_info_1 = 0;
vmcb12->control.exit_info_2 = 0;
goto out;
@@ -1018,7 +1018,7 @@ out_exit_err:
svm->soft_int_injected = false;
svm->vmcb->control.exit_code = SVM_EXIT_ERR;
- svm->vmcb->control.exit_code_hi = 0;
+ svm->vmcb->control.exit_code_hi = -1u;
svm->vmcb->control.exit_info_1 = 0;
svm->vmcb->control.exit_info_2 = 0;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index f56c2d895011..24d59ccfa40d 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2443,6 +2443,7 @@ static bool check_selective_cr0_intercepted(struct kvm_vcpu *vcpu,
if (cr0 ^ val) {
svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE;
+ svm->vmcb->control.exit_code_hi = 0;
ret = (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE);
}
@@ -4617,6 +4618,7 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
if (static_cpu_has(X86_FEATURE_NRIPS))
vmcb->control.next_rip = info->next_rip;
vmcb->control.exit_code = icpt_info.exit_code;
+ vmcb->control.exit_code_hi = 0;
vmexit = nested_svm_exit_handled(svm);
ret = (vmexit == NESTED_EXIT_DONE) ? X86EMUL_INTERCEPTED
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 9e151dbdef25..01be93a53d07 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -761,9 +761,10 @@ int nested_svm_vmexit(struct vcpu_svm *svm);
static inline int nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit_code)
{
- svm->vmcb->control.exit_code = exit_code;
- svm->vmcb->control.exit_info_1 = 0;
- svm->vmcb->control.exit_info_2 = 0;
+ svm->vmcb->control.exit_code = exit_code;
+ svm->vmcb->control.exit_code_hi = 0;
+ svm->vmcb->control.exit_info_1 = 0;
+ svm->vmcb->control.exit_info_2 = 0;
return nested_svm_vmexit(svm);
}
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 40777278eabb..6137e5307d0f 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -19,6 +19,7 @@
#include "trace.h"
#include "vmx.h"
#include "smm.h"
+#include "x86_ops.h"
static bool __read_mostly enable_shadow_vmcs = 1;
module_param_named(enable_shadow_vmcs, enable_shadow_vmcs, bool, S_IRUGO);
@@ -5165,7 +5166,7 @@ void __nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
if (vmx->nested.update_vmcs01_apicv_status) {
vmx->nested.update_vmcs01_apicv_status = false;
- kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
+ vmx_refresh_apicv_exec_ctrl(vcpu);
}
if (vmx->nested.update_vmcs01_hwapic_isr) {
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 4cbe8c84b636..6b96f7aea20b 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6937,15 +6937,6 @@ void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
* VM-Exit, otherwise L1 with run with a stale SVI.
*/
if (is_guest_mode(vcpu)) {
- /*
- * KVM is supposed to forward intercepted L2 EOIs to L1 if VID
- * is enabled in vmcs12; as above, the EOIs affect L2's vAPIC.
- * Note, userspace can stuff state while L2 is active; assert
- * that VID is disabled if and only if the vCPU is in KVM_RUN
- * to avoid false positives if userspace is setting APIC state.
- */
- WARN_ON_ONCE(vcpu->wants_to_run &&
- nested_cpu_has_vid(get_vmcs12(vcpu)));
to_vmx(vcpu)->nested.update_vmcs01_hwapic_isr = true;
return;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0c6d899d53dd..ff8812f3a129 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10886,9 +10886,16 @@ void __kvm_vcpu_update_apicv(struct kvm_vcpu *vcpu)
* pending. At the same time, KVM_REQ_EVENT may not be set as APICv was
* still active when the interrupt got accepted. Make sure
* kvm_check_and_inject_events() is called to check for that.
+ *
+ * Update SVI when APICv gets enabled, otherwise SVI won't reflect the
+ * highest bit in vISR and the next accelerated EOI in the guest won't
+ * be virtualized correctly (the CPU uses SVI to determine which vISR
+ * vector to clear).
*/
if (!apic->apicv_active)
kvm_make_request(KVM_REQ_EVENT, vcpu);
+ else
+ kvm_apic_update_hwapic_isr(vcpu);
out:
preempt_enable();
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index b69dc7194e2c..b0bac2a66eff 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1678,6 +1678,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
emit_prologue(&prog, image, stack_depth,
bpf_prog_was_classic(bpf_prog), tail_call_reachable,
bpf_is_subprog(bpf_prog), bpf_prog->aux->exception_cb);
+
+ bpf_prog->aux->ksym.fp_start = prog - temp;
+
/* Exception callback will clobber callee regs for its own use, and
* restore the original callee regs from main prog's stack frame.
*/
@@ -2736,6 +2739,8 @@ emit_jmp:
pop_r12(&prog);
}
EMIT1(0xC9); /* leave */
+ bpf_prog->aux->ksym.fp_end = prog - temp;
+
emit_return(&prog, image + addrs[i - 1] + (prog - temp));
break;
@@ -3325,6 +3330,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
}
EMIT1(0x55); /* push rbp */
EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */
+ if (im)
+ im->ksym.fp_start = prog - (u8 *)rw_image;
+
if (!is_imm8(stack_size)) {
/* sub rsp, stack_size */
EMIT3_off32(0x48, 0x81, 0xEC, stack_size);
@@ -3462,7 +3470,11 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8);
emit_ldx(&prog, BPF_DW, BPF_REG_6, BPF_REG_FP, -rbx_off);
+
EMIT1(0xC9); /* leave */
+ if (im)
+ im->ksym.fp_end = prog - (u8 *)rw_image;
+
if (flags & BPF_TRAMP_F_SKIP_FRAME) {
/* skip our return address and return to parent */
EMIT4(0x48, 0x83, 0xC4, 8); /* add rsp, 8 */
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 4806cc28d7ca..b74ff8bc7f2a 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -108,7 +108,7 @@ static int xen_cpu_dead_pv(unsigned int cpu);
* calls.
*/
DEFINE_PER_CPU(bool, xen_in_preemptible_hcall);
-EXPORT_SYMBOL_GPL(xen_in_preemptible_hcall);
+EXPORT_PER_CPU_SYMBOL_GPL(xen_in_preemptible_hcall);
/*
* In case of scheduling the flag must be cleared and restored after
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index 9fb9f3533150..6a75fe1c7a5c 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -380,7 +380,7 @@ static void bfqg_stats_add_aux(struct bfqg_stats *to, struct bfqg_stats *from)
blkg_rwstat_add_aux(&to->merged, &from->merged);
blkg_rwstat_add_aux(&to->service_time, &from->service_time);
blkg_rwstat_add_aux(&to->wait_time, &from->wait_time);
- bfq_stat_add_aux(&from->time, &from->time);
+ bfq_stat_add_aux(&to->time, &from->time);
bfq_stat_add_aux(&to->avg_queue_size_sum, &from->avg_queue_size_sum);
bfq_stat_add_aux(&to->avg_queue_size_samples,
&from->avg_queue_size_samples);
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 4a8d3d96bfe4..6e54b1d3d8bc 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -7181,7 +7181,7 @@ static void bfq_exit_queue(struct elevator_queue *e)
blk_stat_disable_accounting(bfqd->queue);
blk_queue_flag_clear(QUEUE_FLAG_DISABLE_WBT_DEF, bfqd->queue);
- set_bit(ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT, &e->flags);
+ wbt_enable_default(bfqd->queue->disk);
kfree(bfqd);
}
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
index 34a498e6b2a5..355a731e2c04 100644
--- a/block/bfq-iosched.h
+++ b/block/bfq-iosched.h
@@ -984,7 +984,7 @@ struct bfq_group_data {
* unused for the root group. Used to know whether there
* are groups with more than one active @bfq_entity
* (see the comments to the function
- * bfq_bfqq_may_idle()).
+ * bfq_better_to_idle()).
* @rq_pos_tree: rbtree sorted by next_request position, used when
* determining if two or more queues have interleaving
* requests (see bfq_find_close_cooperator()).
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 1978eef95dca..eff4f72ce83b 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3721,7 +3721,7 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
struct blk_mq_hw_ctx, cpuhp_online);
int ret = 0;
- if (blk_mq_hctx_has_online_cpu(hctx, cpu))
+ if (!hctx->nr_ctx || blk_mq_hctx_has_online_cpu(hctx, cpu))
return 0;
/*
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 51401f08ce05..a9e65dc090da 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -161,10 +161,9 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
return -EINVAL;
}
- if (bi->pi_tuple_size > bi->metadata_size) {
- pr_warn("pi_tuple_size (%u) exceeds metadata_size (%u)\n",
- bi->pi_tuple_size,
- bi->metadata_size);
+ if (bi->pi_offset + bi->pi_tuple_size > bi->metadata_size) {
+ pr_warn("pi_offset (%u) + pi_tuple_size (%u) exceeds metadata_size (%u)\n",
+ bi->pi_offset, bi->pi_tuple_size, bi->metadata_size);
return -EINVAL;
}
@@ -194,8 +193,13 @@ static int blk_validate_integrity_limits(struct queue_limits *lim)
break;
}
- if (!bi->interval_exp)
+ if (!bi->interval_exp) {
bi->interval_exp = ilog2(lim->logical_block_size);
+ } else if (bi->interval_exp < SECTOR_SHIFT ||
+ bi->interval_exp > ilog2(lim->logical_block_size)) {
+ pr_warn("invalid interval_exp %u\n", bi->interval_exp);
+ return -EINVAL;
+ }
/*
* The PI generation / validation helpers do not expect intervals to
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 8684c57498cc..e0a70d26972b 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -932,7 +932,7 @@ int blk_register_queue(struct gendisk *disk)
elevator_set_default(q);
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
- wbt_enable_default(disk);
+ wbt_init_enable_default(disk);
/* Now everything is ready and send out KOBJ_ADD uevent */
kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index eb8037bae0bd..0974875f77bd 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -699,7 +699,7 @@ static void wbt_requeue(struct rq_qos *rqos, struct request *rq)
/*
* Enable wbt if defaults are configured that way
*/
-void wbt_enable_default(struct gendisk *disk)
+static bool __wbt_enable_default(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
struct rq_qos *rqos;
@@ -716,19 +716,31 @@ void wbt_enable_default(struct gendisk *disk)
if (enable && RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
mutex_unlock(&disk->rqos_state_mutex);
- return;
+ return false;
}
mutex_unlock(&disk->rqos_state_mutex);
/* Queue not registered? Maybe shutting down... */
if (!blk_queue_registered(q))
- return;
+ return false;
if (queue_is_mq(q) && enable)
- wbt_init(disk);
+ return true;
+ return false;
+}
+
+void wbt_enable_default(struct gendisk *disk)
+{
+ __wbt_enable_default(disk);
}
EXPORT_SYMBOL_GPL(wbt_enable_default);
+void wbt_init_enable_default(struct gendisk *disk)
+{
+ if (__wbt_enable_default(disk))
+ WARN_ON_ONCE(wbt_init(disk));
+}
+
u64 wbt_default_latency_nsec(struct request_queue *q)
{
/*
diff --git a/block/blk-wbt.h b/block/blk-wbt.h
index e5fc653b9b76..925f22475738 100644
--- a/block/blk-wbt.h
+++ b/block/blk-wbt.h
@@ -5,6 +5,7 @@
#ifdef CONFIG_BLK_WBT
int wbt_init(struct gendisk *disk);
+void wbt_init_enable_default(struct gendisk *disk);
void wbt_disable_default(struct gendisk *disk);
void wbt_enable_default(struct gendisk *disk);
@@ -16,6 +17,10 @@ u64 wbt_default_latency_nsec(struct request_queue *);
#else
+static inline void wbt_init_enable_default(struct gendisk *disk)
+{
+}
+
static inline void wbt_disable_default(struct gendisk *disk)
{
}
diff --git a/block/elevator.c b/block/elevator.c
index 5b37ef44f52d..a2f8b2251dc6 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -633,14 +633,10 @@ static int elevator_change_done(struct request_queue *q,
.et = ctx->old->et,
.data = ctx->old->elevator_data
};
- bool enable_wbt = test_bit(ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT,
- &ctx->old->flags);
elv_unregister_queue(q, ctx->old);
blk_mq_free_sched_res(&res, ctx->old->type, q->tag_set);
kobject_put(&ctx->old->kobj);
- if (enable_wbt)
- wbt_enable_default(q->disk);
}
if (ctx->new) {
ret = elv_register_queue(q, ctx->new, !ctx->no_uevent);
diff --git a/block/elevator.h b/block/elevator.h
index a9d092c5a9e8..3eb32516be0b 100644
--- a/block/elevator.h
+++ b/block/elevator.h
@@ -156,7 +156,6 @@ struct elevator_queue
#define ELEVATOR_FLAG_REGISTERED 0
#define ELEVATOR_FLAG_DYING 1
-#define ELEVATOR_FLAG_ENABLE_WBT_ON_EXIT 2
/*
* block elevator interface
diff --git a/block/ioctl.c b/block/ioctl.c
index 61feed686418..344478348a54 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -442,11 +442,12 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
if (copy_from_user(&read_keys, arg, sizeof(read_keys)))
return -EFAULT;
- keys_info_len = struct_size(keys_info, keys, read_keys.num_keys);
- if (keys_info_len == SIZE_MAX)
+ if (read_keys.num_keys > PR_KEYS_MAX)
return -EINVAL;
- keys_info = kzalloc(keys_info_len, GFP_KERNEL);
+ keys_info_len = struct_size(keys_info, keys, read_keys.num_keys);
+
+ keys_info = kvzalloc(keys_info_len, GFP_KERNEL);
if (!keys_info)
return -ENOMEM;
@@ -473,7 +474,7 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
if (copy_to_user(arg, &read_keys, sizeof(read_keys)))
ret = -EFAULT;
out:
- kfree(keys_info);
+ kvfree(keys_info);
return ret;
}
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index 2bae99e33526..678bb4145d78 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -50,6 +50,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
struct aead_request *subreq = aead_request_ctx(req);
crypto_completion_t compl;
+ bool unaligned_info;
void *data;
u8 *info;
unsigned int ivsize = 8;
@@ -68,8 +69,9 @@ static int seqiv_aead_encrypt(struct aead_request *req)
memcpy_sglist(req->dst, req->src,
req->assoclen + req->cryptlen);
- if (unlikely(!IS_ALIGNED((unsigned long)info,
- crypto_aead_alignmask(geniv) + 1))) {
+ unaligned_info = !IS_ALIGNED((unsigned long)info,
+ crypto_aead_alignmask(geniv) + 1);
+ if (unlikely(unaligned_info)) {
info = kmemdup(req->iv, ivsize, req->base.flags &
CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
GFP_ATOMIC);
@@ -89,7 +91,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
err = crypto_aead_encrypt(subreq);
- if (unlikely(info != req->iv))
+ if (unlikely(unaligned_info))
seqiv_aead_encrypt_complete2(req, err);
return err;
}
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index ceef1c502e9e..8141d8e51636 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -17,6 +17,7 @@
#include <linux/iopoll.h>
#include <linux/pci.h>
#include <linux/xarray.h>
+#include <asm/hypervisor.h>
#include "aie2_msg_priv.h"
#include "aie2_pci.h"
@@ -508,6 +509,11 @@ static int aie2_init(struct amdxdna_dev *xdna)
unsigned long bars = 0;
int i, nvec, ret;
+ if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
+ XDNA_ERR(xdna, "Running under hypervisor not supported");
+ return -EINVAL;
+ }
+
ndev = drmm_kzalloc(&xdna->ddev, sizeof(*ndev), GFP_KERNEL);
if (!ndev)
return -ENOMEM;
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c
index 97064e943768..e3f302b9dee5 100644
--- a/drivers/acpi/acpi_pcc.c
+++ b/drivers/acpi/acpi_pcc.c
@@ -52,7 +52,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
struct pcc_data *data;
struct acpi_pcc_info *ctx = handler_context;
struct pcc_mbox_chan *pcc_chan;
- static acpi_status ret;
+ acpi_status ret;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 3bdeeee3414e..e66e20d1f31b 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -1366,7 +1366,8 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
/* Are any of the regs PCC ?*/
if (CPC_IN_PCC(highest_reg) || CPC_IN_PCC(lowest_reg) ||
CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg) ||
- CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg)) {
+ CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg) ||
+ CPC_IN_PCC(guaranteed_reg)) {
if (pcc_ss_id < 0) {
pr_debug("Invalid pcc_ss_id\n");
return -ENODEV;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 0b24bd169d61..09d8c035fcdf 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4143,6 +4143,9 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
{ "ST3320[68]13AS", "SD1[5-9]", ATA_QUIRK_NONCQ |
ATA_QUIRK_FIRMWARE_WARN },
+ /* Seagate disks with LPM issues */
+ { "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM },
+
/* drives which fail FPDMA_AA activation (some may freeze afterwards)
the ST disks also have LPM issues */
{ "ST1000LM024 HN-M101MBB", NULL, ATA_QUIRK_BROKEN_FPDMA_AA |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 84676cc24221..0ee8ea971aa4 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1868,16 +1868,18 @@ void pm_runtime_init(struct device *dev)
*/
void pm_runtime_reinit(struct device *dev)
{
- if (!pm_runtime_enabled(dev)) {
- if (dev->power.runtime_status == RPM_ACTIVE)
- pm_runtime_set_suspended(dev);
- if (dev->power.irq_safe) {
- spin_lock_irq(&dev->power.lock);
- dev->power.irq_safe = 0;
- spin_unlock_irq(&dev->power.lock);
- if (dev->parent)
- pm_runtime_put(dev->parent);
- }
+ if (pm_runtime_enabled(dev))
+ return;
+
+ if (dev->power.runtime_status == RPM_ACTIVE)
+ pm_runtime_set_suspended(dev);
+
+ if (dev->power.irq_safe) {
+ spin_lock_irq(&dev->power.lock);
+ dev->power.irq_safe = 0;
+ spin_unlock_irq(&dev->power.lock);
+ if (dev->parent)
+ pm_runtime_put(dev->parent);
}
/*
* Clear power.needs_force_resume in case it has been set by
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 272bc608e528..32a3a5b13802 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1082,7 +1082,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
/* Order wrt reading lo_state in loop_validate_file(). */
wmb();
- lo->lo_state = Lo_bound;
+ WRITE_ONCE(lo->lo_state, Lo_bound);
if (part_shift)
lo->lo_flags |= LO_FLAGS_PARTSCAN;
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN;
@@ -1179,7 +1179,7 @@ static void __loop_clr_fd(struct loop_device *lo)
if (!part_shift)
set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
mutex_lock(&lo->lo_mutex);
- lo->lo_state = Lo_unbound;
+ WRITE_ONCE(lo->lo_state, Lo_unbound);
mutex_unlock(&lo->lo_mutex);
/*
@@ -1218,7 +1218,7 @@ static int loop_clr_fd(struct loop_device *lo)
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
if (disk_openers(lo->lo_disk) == 1)
- lo->lo_state = Lo_rundown;
+ WRITE_ONCE(lo->lo_state, Lo_rundown);
loop_global_unlock(lo, true);
return 0;
@@ -1743,7 +1743,7 @@ static void lo_release(struct gendisk *disk)
mutex_lock(&lo->lo_mutex);
if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
- lo->lo_state = Lo_rundown;
+ WRITE_ONCE(lo->lo_state, Lo_rundown);
need_clear = (lo->lo_state == Lo_rundown);
mutex_unlock(&lo->lo_mutex);
@@ -1858,7 +1858,7 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(rq);
- if (lo->lo_state != Lo_bound)
+ if (data_race(READ_ONCE(lo->lo_state)) != Lo_bound)
return BLK_STS_IOERR;
switch (req_op(rq)) {
@@ -2016,7 +2016,7 @@ static int loop_add(int i)
lo->worker_tree = RB_ROOT;
INIT_LIST_HEAD(&lo->idle_worker_list);
timer_setup(&lo->timer, loop_free_idle_workers_timer, TIMER_DEFERRABLE);
- lo->lo_state = Lo_unbound;
+ WRITE_ONCE(lo->lo_state, Lo_unbound);
err = mutex_lock_killable(&loop_ctl_mutex);
if (err)
@@ -2174,7 +2174,7 @@ static int loop_control_remove(int idx)
goto mark_visible;
}
/* Mark this loop device as no more bound, but not quite unbound yet */
- lo->lo_state = Lo_deleting;
+ WRITE_ONCE(lo->lo_state, Lo_deleting);
mutex_unlock(&lo->lo_mutex);
loop_remove(lo);
@@ -2197,8 +2197,12 @@ static int loop_control_get_free(int idx)
if (ret)
return ret;
idr_for_each_entry(&loop_index_idr, lo, id) {
- /* Hitting a race results in creating a new loop device which is harmless. */
- if (lo->idr_visible && data_race(lo->lo_state) == Lo_unbound)
+ /*
+ * Hitting a race results in creating a new loop device
+ * which is harmless.
+ */
+ if (lo->idr_visible &&
+ data_race(READ_ONCE(lo->lo_state)) == Lo_unbound)
goto found;
}
mutex_unlock(&loop_ctl_mutex);
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
index f1409e54010a..d1c354636315 100644
--- a/drivers/block/rnbd/rnbd-clt.c
+++ b/drivers/block/rnbd/rnbd-clt.c
@@ -1423,9 +1423,11 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
goto out_alloc;
}
- ret = ida_alloc_max(&index_ida, (1 << (MINORBITS - RNBD_PART_BITS)) - 1,
- GFP_KERNEL);
- if (ret < 0) {
+ dev->clt_device_id = ida_alloc_max(&index_ida,
+ (1 << (MINORBITS - RNBD_PART_BITS)) - 1,
+ GFP_KERNEL);
+ if (dev->clt_device_id < 0) {
+ ret = dev->clt_device_id;
pr_err("Failed to initialize device '%s' from session %s, allocating idr failed, err: %d\n",
pathname, sess->sessname, ret);
goto out_queues;
@@ -1434,10 +1436,9 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
dev->pathname = kstrdup(pathname, GFP_KERNEL);
if (!dev->pathname) {
ret = -ENOMEM;
- goto out_queues;
+ goto out_ida;
}
- dev->clt_device_id = ret;
dev->sess = sess;
dev->access_mode = access_mode;
dev->nr_poll_queues = nr_poll_queues;
@@ -1453,6 +1454,8 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
return dev;
+out_ida:
+ ida_free(&index_ida, dev->clt_device_id);
out_queues:
kfree(dev->hw_queues);
out_alloc:
diff --git a/drivers/block/rnbd/rnbd-clt.h b/drivers/block/rnbd/rnbd-clt.h
index a48e040abe63..fbc1ed766025 100644
--- a/drivers/block/rnbd/rnbd-clt.h
+++ b/drivers/block/rnbd/rnbd-clt.h
@@ -112,7 +112,7 @@ struct rnbd_clt_dev {
struct rnbd_queue *hw_queues;
u32 device_id;
/* local Idr index - used to track minor number allocations. */
- u32 clt_device_id;
+ int clt_device_id;
struct mutex lock;
enum rnbd_clt_dev_state dev_state;
refcount_t refcount;
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index df9831783a13..837fedb02e0d 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -237,6 +237,7 @@ struct ublk_device {
bool canceling;
pid_t ublksrv_tgid;
struct delayed_work exit_work;
+ struct work_struct partition_scan_work;
struct ublk_queue *queues[];
};
@@ -254,6 +255,20 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
u16 q_id, u16 tag, struct ublk_io *io, size_t offset);
static inline unsigned int ublk_req_build_flags(struct request *req);
+static void ublk_partition_scan_work(struct work_struct *work)
+{
+ struct ublk_device *ub =
+ container_of(work, struct ublk_device, partition_scan_work);
+
+ if (WARN_ON_ONCE(!test_and_clear_bit(GD_SUPPRESS_PART_SCAN,
+ &ub->ub_disk->state)))
+ return;
+
+ mutex_lock(&ub->ub_disk->open_mutex);
+ bdev_disk_changed(ub->ub_disk, false);
+ mutex_unlock(&ub->ub_disk->open_mutex);
+}
+
static inline struct ublksrv_io_desc *
ublk_get_iod(const struct ublk_queue *ubq, unsigned tag)
{
@@ -1080,12 +1095,20 @@ static inline struct ublk_uring_cmd_pdu *ublk_get_uring_cmd_pdu(
return io_uring_cmd_to_pdu(ioucmd, struct ublk_uring_cmd_pdu);
}
+static void ublk_end_request(struct request *req, blk_status_t error)
+{
+ local_bh_disable();
+ blk_mq_end_request(req, error);
+ local_bh_enable();
+}
+
/* todo: handle partial completion */
static inline void __ublk_complete_rq(struct request *req, struct ublk_io *io,
bool need_map)
{
unsigned int unmapped_bytes;
blk_status_t res = BLK_STS_OK;
+ bool requeue;
/* failed read IO if nothing is read */
if (!io->res && req_op(req) == REQ_OP_READ)
@@ -1117,14 +1140,30 @@ static inline void __ublk_complete_rq(struct request *req, struct ublk_io *io,
if (unlikely(unmapped_bytes < io->res))
io->res = unmapped_bytes;
- if (blk_update_request(req, BLK_STS_OK, io->res))
+ /*
+ * Run bio->bi_end_io() with softirqs disabled. If the final fput
+ * happens off this path, then that will prevent ublk's blkdev_release()
+ * from being called on current's task work, see fput() implementation.
+ *
+ * Otherwise, ublk server may not provide forward progress in case of
+ * reading the partition table from bdev_open() with disk->open_mutex
+ * held, and causes dead lock as we could already be holding
+ * disk->open_mutex here.
+ *
+ * Preferably we would not be doing IO with a mutex held that is also
+ * used for release, but this work-around will suffice for now.
+ */
+ local_bh_disable();
+ requeue = blk_update_request(req, BLK_STS_OK, io->res);
+ local_bh_enable();
+ if (requeue)
blk_mq_requeue_request(req, true);
else if (likely(!blk_should_fake_timeout(req->q)))
__blk_mq_end_request(req, BLK_STS_OK);
return;
exit:
- blk_mq_end_request(req, res);
+ ublk_end_request(req, res);
}
static struct io_uring_cmd *__ublk_prep_compl_io_cmd(struct ublk_io *io,
@@ -1164,7 +1203,7 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
if (ublk_nosrv_dev_should_queue_io(ubq->dev))
blk_mq_requeue_request(rq, false);
else
- blk_mq_end_request(rq, BLK_STS_IOERR);
+ ublk_end_request(rq, BLK_STS_IOERR);
}
static void
@@ -1209,7 +1248,7 @@ __ublk_do_auto_buf_reg(const struct ublk_queue *ubq, struct request *req,
ublk_auto_buf_reg_fallback(ubq, req->tag);
return AUTO_BUF_REG_FALLBACK;
}
- blk_mq_end_request(req, BLK_STS_IOERR);
+ ublk_end_request(req, BLK_STS_IOERR);
return AUTO_BUF_REG_FAIL;
}
@@ -1583,8 +1622,7 @@ static bool ublk_check_and_reset_active_ref(struct ublk_device *ub)
{
int i, j;
- if (!(ub->dev_info.flags & (UBLK_F_SUPPORT_ZERO_COPY |
- UBLK_F_AUTO_BUF_REG)))
+ if (!ublk_dev_need_req_ref(ub))
return false;
for (i = 0; i < ub->dev_info.nr_hw_queues; i++) {
@@ -2003,6 +2041,7 @@ static void ublk_stop_dev(struct ublk_device *ub)
mutex_lock(&ub->mutex);
ublk_stop_dev_unlocked(ub);
mutex_unlock(&ub->mutex);
+ flush_work(&ub->partition_scan_work);
ublk_cancel_dev(ub);
}
@@ -2931,9 +2970,17 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
ublk_apply_params(ub);
- /* don't probe partitions if any daemon task is un-trusted */
- if (ub->unprivileged_daemons)
- set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
+ /*
+ * Suppress partition scan to avoid potential IO hang.
+ *
+ * If ublk server error occurs during partition scan, the IO may
+ * wait while holding ub->mutex, which can deadlock with other
+ * operations that need the mutex. Defer partition scan to async
+ * work.
+ * For unprivileged daemons, keep GD_SUPPRESS_PART_SCAN set
+ * permanently.
+ */
+ set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
ublk_get_device(ub);
ub->dev_info.state = UBLK_S_DEV_LIVE;
@@ -2950,6 +2997,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
set_bit(UB_STATE_USED, &ub->state);
+ /* Schedule async partition scan for trusted daemons */
+ if (!ub->unprivileged_daemons)
+ schedule_work(&ub->partition_scan_work);
+
out_put_cdev:
if (ret) {
ublk_detach_disk(ub);
@@ -3115,6 +3166,7 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
mutex_init(&ub->mutex);
spin_lock_init(&ub->lock);
mutex_init(&ub->cancel_mutex);
+ INIT_WORK(&ub->partition_scan_work, ublk_partition_scan_work);
ret = ublk_alloc_dev_number(ub, header->dev_id);
if (ret < 0)
diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c
index 77bd6081b244..8e334f5025fc 100644
--- a/drivers/block/zloop.c
+++ b/drivers/block/zloop.c
@@ -697,7 +697,7 @@ static blk_status_t zloop_queue_rq(struct blk_mq_hw_ctx *hctx,
struct zloop_cmd *cmd = blk_mq_rq_to_pdu(rq);
struct zloop_device *zlo = rq->q->queuedata;
- if (zlo->state == Zlo_deleting)
+ if (data_race(READ_ONCE(zlo->state)) == Zlo_deleting)
return BLK_STS_IOERR;
/*
@@ -1002,7 +1002,7 @@ static int zloop_ctl_add(struct zloop_options *opts)
ret = -ENOMEM;
goto out;
}
- zlo->state = Zlo_creating;
+ WRITE_ONCE(zlo->state, Zlo_creating);
ret = mutex_lock_killable(&zloop_ctl_mutex);
if (ret)
@@ -1113,7 +1113,7 @@ static int zloop_ctl_add(struct zloop_options *opts)
}
mutex_lock(&zloop_ctl_mutex);
- zlo->state = Zlo_live;
+ WRITE_ONCE(zlo->state, Zlo_live);
mutex_unlock(&zloop_ctl_mutex);
pr_info("zloop: device %d, %u zones of %llu MiB, %u B block size\n",
@@ -1177,7 +1177,7 @@ static int zloop_ctl_remove(struct zloop_options *opts)
ret = -EINVAL;
} else {
idr_remove(&zloop_index_idr, zlo->id);
- zlo->state = Zlo_deleting;
+ WRITE_ONCE(zlo->state, Zlo_deleting);
}
mutex_unlock(&zloop_ctl_mutex);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8ed3883ab8ee..ded09e94d296 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -4052,7 +4052,7 @@ static int btusb_probe(struct usb_interface *intf,
return -ENODEV;
}
- data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -4075,8 +4075,10 @@ static int btusb_probe(struct usb_interface *intf,
}
}
- if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
+ if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
+ kfree(data);
return -ENODEV;
+ }
if (id->driver_info & BTUSB_AMP) {
data->cmdreq_type = USB_TYPE_CLASS | 0x01;
@@ -4131,8 +4133,10 @@ static int btusb_probe(struct usb_interface *intf,
data->recv_acl = hci_recv_frame;
hdev = hci_alloc_dev_priv(priv_size);
- if (!hdev)
+ if (!hdev) {
+ kfree(data);
return -ENOMEM;
+ }
hdev->bus = HCI_USB;
hci_set_drvdata(hdev, data);
@@ -4406,6 +4410,7 @@ out_free_dev:
if (data->reset_gpio)
gpiod_put(data->reset_gpio);
hci_free_dev(hdev);
+ kfree(data);
return err;
}
@@ -4454,6 +4459,7 @@ static void btusb_disconnect(struct usb_interface *intf)
}
hci_free_dev(hdev);
+ kfree(data);
}
#ifdef CONFIG_PM
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index a1d11ecd1ac8..b06a43143d23 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -219,11 +219,12 @@ static bool __init cpu0_node_has_opp_v2_prop(void)
static int __init cpufreq_dt_platdev_init(void)
{
- const void *data;
+ const void *data = NULL;
- data = of_machine_get_match_data(allowlist);
- if (data)
+ if (of_machine_device_match(allowlist)) {
+ data = of_machine_get_match_data(allowlist);
goto create_pdev;
+ }
if (cpu0_node_has_opp_v2_prop() && !of_machine_device_match(blocklist))
goto create_pdev;
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index f8bfff5dd0bd..d47bf06a90f7 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -991,7 +991,7 @@ static void qm_get_complete_eqe_num(struct hisi_qm *qm)
return;
poll_data = &qm->poll_data[cqn];
- while (QM_EQE_PHASE(dw0) != qm->status.eqc_phase) {
+ do {
poll_data->qp_finish_id[eqe_num] = dw0 & QM_EQE_CQN_MASK;
eqe_num++;
@@ -1004,11 +1004,10 @@ static void qm_get_complete_eqe_num(struct hisi_qm *qm)
qm->status.eq_head++;
}
- if (eqe_num == (eq_depth >> 1) - 1)
- break;
-
dw0 = le32_to_cpu(eqe->dw0);
- }
+ if (QM_EQE_PHASE(dw0) != qm->status.eqc_phase)
+ break;
+ } while (eqe_num < (eq_depth >> 1) - 1);
poll_data->eqe_num = eqe_num;
queue_work(qm->wq, &poll_data->work);
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index ea31ac7ac1ca..e59053738a43 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -36,6 +36,8 @@
static char driver_name[] = KBUILD_MODNAME;
+#define RCV_BUFFER_SIZE (16 * 1024)
+
/* this is the physical layout of a PCL, its size is 128 bytes */
struct pcl {
__le32 next;
@@ -517,16 +519,14 @@ remove_card(struct pci_dev *dev)
lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
lynx->rcv_pcl, lynx->rcv_pcl_bus);
- dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE, lynx->rcv_buffer,
- lynx->rcv_buffer_bus);
+ dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
+ lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
pci_disable_device(dev);
lynx_put(lynx);
}
-#define RCV_BUFFER_SIZE (16 * 1024)
-
static int
add_card(struct pci_dev *dev, const struct pci_device_id *unused)
{
@@ -680,7 +680,7 @@ fail_deallocate_buffers:
dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
lynx->rcv_pcl, lynx->rcv_pcl_bus);
if (lynx->rcv_buffer)
- dma_free_coherent(&lynx->pci_device->dev, PAGE_SIZE,
+ dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a9070d00b833..55452e61af31 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -73,6 +73,7 @@ struct mm_struct efi_mm = {
MMAP_LOCK_INITIALIZER(efi_mm)
.page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
.mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
+ .user_ns = &init_user_ns,
.cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0},
#ifdef CONFIG_SCHED_MM_CID
.mm_cid.lock = __RAW_SPIN_LOCK_UNLOCKED(efi_mm.mm_cid.lock),
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 72d74436a7a4..80dc8cfeb33e 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -513,15 +513,15 @@ efi_status_t efi_setup_graphics(struct screen_info *si, struct edid_info *edid)
status = efi_bs_call(handle_protocol, handle, &EFI_EDID_ACTIVE_PROTOCOL_GUID,
(void **)&active_edid);
if (status == EFI_SUCCESS) {
- gop_size_of_edid = active_edid->size_of_edid;
- gop_edid = active_edid->edid;
+ gop_size_of_edid = efi_table_attr(active_edid, size_of_edid);
+ gop_edid = efi_table_attr(active_edid, edid);
} else {
status = efi_bs_call(handle_protocol, handle,
&EFI_EDID_DISCOVERED_PROTOCOL_GUID,
(void **)&discovered_edid);
if (status == EFI_SUCCESS) {
- gop_size_of_edid = discovered_edid->size_of_edid;
- gop_edid = discovered_edid->edid;
+ gop_size_of_edid = efi_table_attr(discovered_edid, size_of_edid);
+ gop_edid = efi_table_attr(discovered_edid, edid);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 58c3ffe707d1..12201b8e99b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -6613,6 +6613,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
struct amdgpu_hive_info *hive = NULL;
int r = 0;
bool need_emergency_restart = false;
+ /* save the pasid here as the job may be freed before the end of the reset */
+ int pasid = job ? job->pasid : -EINVAL;
/*
* If it reaches here because of hang/timeout and a RAS error is
@@ -6713,8 +6715,12 @@ end_reset:
if (!r) {
struct amdgpu_task_info *ti = NULL;
- if (job)
- ti = amdgpu_vm_get_task_info_pasid(adev, job->pasid);
+ /*
+ * The job may already be freed at this point via the sched tdr workqueue so
+ * use the cached pasid.
+ */
+ if (pasid >= 0)
+ ti = amdgpu_vm_get_task_info_pasid(adev, pasid);
drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE,
ti ? &ti->task : NULL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 2dfbddcef9ab..848e6b7db482 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -33,6 +33,7 @@
#include <drm/drm_vblank.h>
#include <linux/cc_platform.h>
+#include <linux/console.h>
#include <linux/dynamic_debug.h>
#include <linux/module.h>
#include <linux/mmu_notifier.h>
@@ -2704,7 +2705,9 @@ static int amdgpu_pmops_thaw(struct device *dev)
struct drm_device *drm_dev = dev_get_drvdata(dev);
/* do not resume device if it's normal hibernation */
- if (!pm_hibernate_is_recovering() && !pm_hibernation_mode_is_suspend())
+ if (console_suspend_enabled &&
+ !pm_hibernate_is_recovering() &&
+ !pm_hibernation_mode_is_suspend())
return 0;
return amdgpu_device_resume(drm_dev, true);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
index a499449fcb06..d2bc169e84b0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c
@@ -312,7 +312,7 @@ void kfd_smi_event_queue_restore(struct kfd_node *node, pid_t pid)
{
kfd_smi_event_add(pid, node, KFD_SMI_EVENT_QUEUE_RESTORE,
KFD_EVENT_FMT_QUEUE_RESTORE(ktime_get_boottime_ns(), pid,
- node->id, 0));
+ node->id, '0'));
}
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 4986f12dc9df..0cdd8c74abdf 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -1118,13 +1118,13 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL)
num_audio++;
}
+ if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa) {
+ /*wake AZ from D3 first before access az endpoint*/
+ clk_mgr->funcs->enable_pme_wa(clk_mgr);
+ }
pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
- if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa)
- /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
- clk_mgr->funcs->enable_pme_wa(clk_mgr);
-
link_hwss->enable_audio_packet(pipe_ctx);
if (pipe_ctx->stream_res.audio)
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index ef69898d2cc5..d056e5fd5458 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -203,12 +203,12 @@ enum dcn35_clk_src_array_id {
NBIO_BASE_INNER(seg)
#define NBIO_SR(reg_name)\
- REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
- regBIF_BX2_ ## reg_name
+ REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
+ regBIF_BX1_ ## reg_name
#define NBIO_SR_ARR(reg_name, id)\
- REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
- regBIF_BX2_ ## reg_name
+ REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
+ regBIF_BX1_ ## reg_name
#define bios_regs_init() \
( \
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index f3c614c4490c..9fab3169069c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -183,12 +183,12 @@ enum dcn351_clk_src_array_id {
NBIO_BASE_INNER(seg)
#define NBIO_SR(reg_name)\
- REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
- regBIF_BX2_ ## reg_name
+ REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
+ regBIF_BX1_ ## reg_name
#define NBIO_SR_ARR(reg_name, id)\
- REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX2_ ## reg_name ## _BASE_IDX) + \
- regBIF_BX2_ ## reg_name
+ REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX1_ ## reg_name ## _BASE_IDX) + \
+ regBIF_BX1_ ## reg_name
#define bios_regs_init() \
( \
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index f9b0938c57ea..f2a16dfee599 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@ -1939,6 +1939,11 @@ int smu_v14_0_od_edit_dpm_table(struct smu_context *smu,
dev_err(smu->adev->dev, "Set soft max sclk failed!");
return ret;
}
+ if (smu->gfx_actual_hard_min_freq != smu->gfx_default_hard_min_freq ||
+ smu->gfx_actual_soft_max_freq != smu->gfx_default_soft_max_freq)
+ smu->user_dpm_profile.user_od = true;
+ else
+ smu->user_dpm_profile.user_od = false;
break;
default:
return -ENOSYS;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
index b1bd946d8e30..97414bc39764 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c
@@ -1514,9 +1514,10 @@ static int smu_v14_0_1_set_fine_grain_gfx_freq_parameters(struct smu_context *sm
smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
- smu->gfx_actual_hard_min_freq = 0;
- smu->gfx_actual_soft_max_freq = 0;
-
+ if (smu->gfx_actual_hard_min_freq == 0)
+ smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
+ if (smu->gfx_actual_soft_max_freq == 0)
+ smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
return 0;
}
@@ -1526,8 +1527,10 @@ static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *sm
smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
- smu->gfx_actual_hard_min_freq = 0;
- smu->gfx_actual_soft_max_freq = 0;
+ if (smu->gfx_actual_hard_min_freq == 0)
+ smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
+ if (smu->gfx_actual_soft_max_freq == 0)
+ smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
return 0;
}
@@ -1665,6 +1668,29 @@ static int smu_v14_0_common_set_mall_enable(struct smu_context *smu)
return ret;
}
+static int smu_v14_0_0_restore_user_od_settings(struct smu_context *smu)
+{
+ int ret;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+ smu->gfx_actual_hard_min_freq,
+ NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to restore hard min sclk!\n");
+ return ret;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ smu->gfx_actual_soft_max_freq,
+ NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to restore soft max sclk!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
.check_fw_status = smu_v14_0_check_fw_status,
.check_fw_version = smu_v14_0_check_fw_version,
@@ -1688,6 +1714,7 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
.mode2_reset = smu_v14_0_0_mode2_reset,
.get_dpm_ultimate_freq = smu_v14_0_common_get_dpm_ultimate_freq,
.set_soft_freq_limited_range = smu_v14_0_0_set_soft_freq_limited_range,
+ .restore_user_od_settings = smu_v14_0_0_restore_user_od_settings,
.od_edit_dpm_table = smu_v14_0_od_edit_dpm_table,
.print_clk_levels = smu_v14_0_0_print_clk_levels,
.force_clk_levels = smu_v14_0_0_force_clk_levels,
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index efc79bbf3c73..e4df43427394 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -969,8 +969,10 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
if (!obj)
return -ENOENT;
- if (args->handle == args->new_handle)
- return 0;
+ if (args->handle == args->new_handle) {
+ ret = 0;
+ goto out;
+ }
mutex_lock(&file_priv->prime.lock);
@@ -1002,6 +1004,8 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
out_unlock:
mutex_unlock(&file_priv->prime.lock);
+out:
+ drm_gem_object_put(obj);
return ret;
}
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 93b9cff89080..f13eb5f36e8a 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -96,7 +96,8 @@ err_release:
/**
* drm_gem_shmem_init - Initialize an allocated object.
* @dev: DRM device
- * @obj: The allocated shmem GEM object.
+ * @shmem: The allocated shmem GEM object.
+ * @size: Buffer size in bytes
*
* Returns:
* 0 on success, or a negative error code on failure.
@@ -895,4 +896,4 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_no_map);
MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
MODULE_IMPORT_NS("DMA_BUF");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
index 37d7cfbbb3e8..06c1bd8fc4d1 100644
--- a/drivers/gpu/drm/drm_pagemap.c
+++ b/drivers/gpu/drm/drm_pagemap.c
@@ -3,6 +3,7 @@
* Copyright © 2024-2025 Intel Corporation
*/
+#include <linux/dma-fence.h>
#include <linux/dma-mapping.h>
#include <linux/migrate.h>
#include <linux/pagemap.h>
@@ -408,10 +409,14 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
drm_pagemap_get_devmem_page(page, zdd);
}
- err = ops->copy_to_devmem(pages, pagemap_addr, npages);
+ err = ops->copy_to_devmem(pages, pagemap_addr, npages,
+ devmem_allocation->pre_migrate_fence);
if (err)
goto err_finalize;
+ dma_fence_put(devmem_allocation->pre_migrate_fence);
+ devmem_allocation->pre_migrate_fence = NULL;
+
/* Upon success bind devmem allocation to range and zdd */
devmem_allocation->timeslice_expiration = get_jiffies_64() +
msecs_to_jiffies(timeslice_ms);
@@ -596,7 +601,7 @@ retry:
for (i = 0; i < npages; ++i)
pages[i] = migrate_pfn_to_page(src[i]);
- err = ops->copy_to_ram(pages, pagemap_addr, npages);
+ err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
if (err)
goto err_finalize;
@@ -732,7 +737,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
for (i = 0; i < npages; ++i)
pages[i] = migrate_pfn_to_page(migrate.src[i]);
- err = ops->copy_to_ram(pages, pagemap_addr, npages);
+ err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
if (err)
goto err_finalize;
@@ -813,11 +818,14 @@ EXPORT_SYMBOL_GPL(drm_pagemap_pagemap_ops_get);
* @ops: Pointer to the operations structure for GPU SVM device memory
* @dpagemap: The struct drm_pagemap we're allocating from.
* @size: Size of device memory allocation
+ * @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
+ * (May be NULL).
*/
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
struct device *dev, struct mm_struct *mm,
const struct drm_pagemap_devmem_ops *ops,
- struct drm_pagemap *dpagemap, size_t size)
+ struct drm_pagemap *dpagemap, size_t size,
+ struct dma_fence *pre_migrate_fence)
{
init_completion(&devmem_allocation->detached);
devmem_allocation->dev = dev;
@@ -825,6 +833,7 @@ void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
devmem_allocation->ops = ops;
devmem_allocation->dpagemap = dpagemap;
devmem_allocation->size = size;
+ devmem_allocation->pre_migrate_fence = pre_migrate_fence;
}
EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index b057c2fa03a4..d49e96f9be51 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -951,13 +951,13 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
vma = eb_lookup_vma(eb, eb->exec[i].handle);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
- goto err;
+ return err;
}
err = eb_validate_vma(eb, &eb->exec[i], vma);
if (unlikely(err)) {
i915_vma_put(vma);
- goto err;
+ return err;
}
err = eb_add_vma(eb, &current_batch, i, vma);
@@ -966,19 +966,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
if (i915_gem_object_is_userptr(vma->obj)) {
err = i915_gem_object_userptr_submit_init(vma->obj);
- if (err) {
- if (i + 1 < eb->buffer_count) {
- /*
- * Execbuffer code expects last vma entry to be NULL,
- * since we already initialized this entry,
- * set the next value to NULL or we mess up
- * cleanup handling.
- */
- eb->vma[i + 1].vma = NULL;
- }
-
+ if (err)
return err;
- }
eb->vma[i].flags |= __EXEC_OBJECT_USERPTR_INIT;
eb->args->flags |= __EXEC_USERPTR_USED;
@@ -986,10 +975,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
}
return 0;
-
-err:
- eb->vma[i].vma = NULL;
- return err;
}
static int eb_lock_vmas(struct i915_execbuffer *eb)
@@ -3375,7 +3360,8 @@ i915_gem_do_execbuffer(struct drm_device *dev,
eb.exec = exec;
eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1);
- eb.vma[0].vma = NULL;
+ memset(eb.vma, 0, (args->buffer_count + 1) * sizeof(struct eb_vma));
+
eb.batch_pool = NULL;
eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
@@ -3584,7 +3570,18 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
if (err)
return err;
- /* Allocate extra slots for use by the command parser */
+ /*
+ * Allocate extra slots for use by the command parser.
+ *
+ * Note that this allocation handles two different arrays (the
+ * exec2_list array, and the eventual eb.vma array introduced in
+ * i915_gem_do_execbuffer()), that reside in virtually contiguous
+ * memory. Also note that the allocation intentionally doesn't fill the
+ * area with zeros, because the exec2_list part doesn't need to be, as
+ * it's immediately overwritten by user data a few lines below.
+ * However, the eb.vma part is explicitly zeroed later in
+ * i915_gem_do_execbuffer().
+ */
exec2_list = kvmalloc_array(count + 2, eb_element_size(),
__GFP_NOWARN | GFP_KERNEL);
if (exec2_list == NULL) {
diff --git a/drivers/gpu/drm/imagination/pvr_gem.c b/drivers/gpu/drm/imagination/pvr_gem.c
index a66cf082af24..c07c9a915190 100644
--- a/drivers/gpu/drm/imagination/pvr_gem.c
+++ b/drivers/gpu/drm/imagination/pvr_gem.c
@@ -28,6 +28,16 @@ static void pvr_gem_object_free(struct drm_gem_object *obj)
drm_gem_shmem_object_free(obj);
}
+static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags)
+{
+ struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(obj);
+
+ if (pvr_obj->flags & DRM_PVR_BO_PM_FW_PROTECT)
+ return ERR_PTR(-EPERM);
+
+ return drm_gem_prime_export(obj, flags);
+}
+
static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *vma)
{
struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(gem_obj);
@@ -42,6 +52,7 @@ static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *v
static const struct drm_gem_object_funcs pvr_gem_object_funcs = {
.free = pvr_gem_object_free,
.print_info = drm_gem_shmem_object_print_info,
+ .export = pvr_gem_export,
.pin = drm_gem_shmem_object_pin,
.unpin = drm_gem_shmem_object_unpin,
.get_sg_table = drm_gem_shmem_object_get_sg_table,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 29107b362346..ac9a95aab2fb 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -1376,7 +1376,6 @@ static const uint32_t a7xx_pwrup_reglist_regs[] = {
REG_A6XX_UCHE_MODE_CNTL,
REG_A6XX_RB_NC_MODE_CNTL,
REG_A6XX_RB_CMP_DBG_ECO_CNTL,
- REG_A7XX_GRAS_NC_MODE_CNTL,
REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE,
REG_A6XX_UCHE_GBIF_GX_CONFIG,
REG_A6XX_UCHE_CLIENT_PF,
@@ -1392,6 +1391,7 @@ static const u32 a750_ifpc_reglist_regs[] = {
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
+ REG_A6XX_RBBM_PERFCTR_CNTL,
REG_A6XX_TPL1_NC_MODE_CNTL,
REG_A6XX_SP_NC_MODE_CNTL,
REG_A6XX_CP_DBG_ECO_CNTL,
@@ -1448,6 +1448,12 @@ static const u32 a750_ifpc_reglist_regs[] = {
DECLARE_ADRENO_REGLIST_LIST(a750_ifpc_reglist);
+static const struct adreno_reglist_pipe a7xx_dyn_pwrup_reglist_regs[] = {
+ { REG_A7XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+};
+
+DECLARE_ADRENO_REGLIST_PIPE_LIST(a7xx_dyn_pwrup_reglist);
+
static const struct adreno_info a7xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x07000200),
@@ -1491,6 +1497,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a730_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_cgc_mode = 0x00020000,
},
@@ -1513,6 +1520,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7020100,
.gmu_cgc_mode = 0x00020202,
@@ -1547,6 +1555,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.ifpc_reglist = &a750_ifpc_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7050001,
@@ -1589,6 +1598,7 @@ static const struct adreno_info a7xx_gpus[] = {
.a6xx = &(const struct a6xx_info) {
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.ifpc_reglist = &a750_ifpc_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x7090100,
@@ -1623,6 +1633,7 @@ static const struct adreno_info a7xx_gpus[] = {
.hwcg = a740_hwcg,
.protect = &a730_protect,
.pwrup_reglist = &a7xx_pwrup_reglist,
+ .dyn_pwrup_reglist = &a7xx_dyn_pwrup_reglist,
.gbif_cx = a640_gbif,
.gmu_chipid = 0x70f0000,
.gmu_cgc_mode = 0x00020222,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 0200a7e71cdf..2129d230a92b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -849,9 +849,16 @@ static void a6xx_set_ubwc_config(struct msm_gpu *gpu)
min_acc_len_64b << 3 |
hbb_lo << 1 | ubwc_mode);
- if (adreno_is_a7xx(adreno_gpu))
- gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL,
- FIELD_PREP(GENMASK(8, 5), hbb_lo));
+ if (adreno_is_a7xx(adreno_gpu)) {
+ for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_BV; pipe_id++) {
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id));
+ gpu_write(gpu, REG_A7XX_GRAS_NC_MODE_CNTL,
+ FIELD_PREP(GENMASK(8, 5), hbb_lo));
+ }
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
+ }
gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL,
min_acc_len_64b << 23 | hbb_lo << 21);
@@ -865,23 +872,27 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
const struct adreno_reglist_list *reglist;
+ const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
void *ptr = a6xx_gpu->pwrup_reglist_ptr;
struct cpu_gpu_lock *lock = ptr;
u32 *dest = (u32 *)&lock->regs[0];
+ u32 dyn_pwrup_reglist_count = 0;
int i;
lock->gpu_req = lock->cpu_req = lock->turn = 0;
reglist = adreno_gpu->info->a6xx->ifpc_reglist;
- lock->ifpc_list_len = reglist->count;
+ if (reglist) {
+ lock->ifpc_list_len = reglist->count;
- /*
- * For each entry in each of the lists, write the offset and the current
- * register value into the GPU buffer
- */
- for (i = 0; i < reglist->count; i++) {
- *dest++ = reglist->regs[i];
- *dest++ = gpu_read(gpu, reglist->regs[i]);
+ /*
+ * For each entry in each of the lists, write the offset and the current
+ * register value into the GPU buffer
+ */
+ for (i = 0; i < reglist->count; i++) {
+ *dest++ = reglist->regs[i];
+ *dest++ = gpu_read(gpu, reglist->regs[i]);
+ }
}
reglist = adreno_gpu->info->a6xx->pwrup_reglist;
@@ -907,7 +918,24 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu)
* (<aperture, shifted 12 bits> <address> <data>), and the length is
* stored as number for triplets in dynamic_list_len.
*/
- lock->dynamic_list_len = 0;
+ dyn_pwrup_reglist = adreno_gpu->info->a6xx->dyn_pwrup_reglist;
+ if (dyn_pwrup_reglist) {
+ for (u32 pipe_id = PIPE_BR; pipe_id <= PIPE_BV; pipe_id++) {
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id));
+ for (i = 0; i < dyn_pwrup_reglist->count; i++) {
+ if ((dyn_pwrup_reglist->regs[i].pipe & BIT(pipe_id)) == 0)
+ continue;
+ *dest++ = A7XX_CP_APERTURE_CNTL_HOST_PIPE(pipe_id);
+ *dest++ = dyn_pwrup_reglist->regs[i].offset;
+ *dest++ = gpu_read(gpu, dyn_pwrup_reglist->regs[i].offset);
+ dyn_pwrup_reglist_count++;
+ }
+ }
+ gpu_write(gpu, REG_A7XX_CP_APERTURE_CNTL_HOST,
+ A7XX_CP_APERTURE_CNTL_HOST_PIPE(PIPE_NONE));
+ }
+ lock->dynamic_list_len = dyn_pwrup_reglist_count;
}
static int a7xx_preempt_start(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 6820216ec5fc..4eaa04711246 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -45,6 +45,7 @@ struct a6xx_info {
const struct adreno_reglist *hwcg;
const struct adreno_protect *protect;
const struct adreno_reglist_list *pwrup_reglist;
+ const struct adreno_reglist_pipe_list *dyn_pwrup_reglist;
const struct adreno_reglist_list *ifpc_reglist;
const struct adreno_reglist *gbif_cx;
const struct adreno_reglist_pipe *nonctxt_reglist;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index afc5f4aa3b17..747a22afad9f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -454,11 +454,11 @@ void a6xx_preempt_init(struct msm_gpu *gpu)
gpu->vm, &a6xx_gpu->preempt_postamble_bo,
&a6xx_gpu->preempt_postamble_iova);
- preempt_prepare_postamble(a6xx_gpu);
-
if (IS_ERR(a6xx_gpu->preempt_postamble_ptr))
goto fail;
+ preempt_prepare_postamble(a6xx_gpu);
+
timer_setup(&a6xx_gpu->preempt_timer, a6xx_preempt_timer, 0);
return;
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 0f8d3de97636..1d0145f8b3ec 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -188,6 +188,19 @@ static const struct adreno_reglist_list name = { \
.count = ARRAY_SIZE(name ## _regs), \
};
+struct adreno_reglist_pipe_list {
+ /** @reg: List of register **/
+ const struct adreno_reglist_pipe *regs;
+ /** @count: Number of registers in the list **/
+ u32 count;
+};
+
+#define DECLARE_ADRENO_REGLIST_PIPE_LIST(name) \
+static const struct adreno_reglist_pipe_list name = { \
+ .regs = name ## _regs, \
+ .count = ARRAY_SIZE(name ## _regs), \
+};
+
struct adreno_gpu {
struct msm_gpu base;
const struct adreno_info *info;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index c39f1908ea65..2d06c950e814 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -200,7 +200,7 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc,
struct dpu_crtc_state *crtc_state)
{
struct dpu_crtc_mixer *m;
- u32 crcs[CRTC_QUAD_MIXERS];
+ u32 crcs[CRTC_DUAL_MIXERS];
int rc = 0;
int i;
@@ -1328,7 +1328,6 @@ static struct msm_display_topology dpu_crtc_get_topology(
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
struct msm_display_topology topology = {0};
struct drm_encoder *drm_enc;
- u32 num_rt_intf;
drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
@@ -1342,14 +1341,11 @@ static struct msm_display_topology dpu_crtc_get_topology(
* Dual display
* 2 LM, 2 INTF ( Split display using 2 interfaces)
*
- * If DSC is enabled, try to use 4:4:2 topology if there is enough
- * resource. Otherwise, use 2:2:2 topology.
- *
* Single display
* 1 LM, 1 INTF
* 2 LM, 1 INTF (stream merge to support high resolution interfaces)
*
- * If DSC is enabled, use 2:2:1 topology
+ * If DSC is enabled, use 2 LMs for 2:2:1 topology
*
* Add dspps to the reservation requirements if ctm is requested
*
@@ -1361,23 +1357,14 @@ static struct msm_display_topology dpu_crtc_get_topology(
* (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
*/
- num_rt_intf = topology.num_intf;
- if (topology.cwb_enabled)
- num_rt_intf--;
-
- if (topology.num_dsc) {
- if (dpu_kms->catalog->dsc_count >= num_rt_intf * 2)
- topology.num_dsc = num_rt_intf * 2;
- else
- topology.num_dsc = num_rt_intf;
- topology.num_lm = topology.num_dsc;
- } else if (num_rt_intf == 2) {
+ if (topology.num_intf == 2 && !topology.cwb_enabled)
+ topology.num_lm = 2;
+ else if (topology.num_dsc == 2)
topology.num_lm = 2;
- } else if (dpu_kms->catalog->caps->has_3d_merge) {
+ else if (dpu_kms->catalog->caps->has_3d_merge)
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
- } else {
+ else
topology.num_lm = 1;
- }
if (crtc_state->ctm)
topology.num_dspp = topology.num_lm;
@@ -1620,17 +1607,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
return 0;
}
-/**
- * dpu_crtc_get_num_lm - Get mixer number in this CRTC pipeline
- * @state: Pointer to drm crtc state object
- */
-unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state)
-{
- struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
-
- return cstate->num_mixers;
-}
-
#ifdef CONFIG_DEBUG_FS
static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
{
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 455073c7025b..94392b9b9245 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -210,7 +210,7 @@ struct dpu_crtc_state {
bool bw_control;
bool bw_split_vote;
- struct drm_rect lm_bounds[CRTC_QUAD_MIXERS];
+ struct drm_rect lm_bounds[CRTC_DUAL_MIXERS];
uint64_t input_fence_timeout_ns;
@@ -218,10 +218,10 @@ struct dpu_crtc_state {
/* HW Resources reserved for the crtc */
u32 num_mixers;
- struct dpu_crtc_mixer mixers[CRTC_QUAD_MIXERS];
+ struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS];
u32 num_ctls;
- struct dpu_hw_ctl *hw_ctls[CRTC_QUAD_MIXERS];
+ struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS];
enum dpu_crtc_crc_source crc_source;
int crc_frame_skip_count;
@@ -267,6 +267,4 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type(
void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event);
-unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state);
-
#endif /* _DPU_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index d1cfe81a3373..9f3957f24c6a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -55,7 +55,7 @@
#define MAX_PHYS_ENCODERS_PER_VIRTUAL \
(MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES)
-#define MAX_CHANNELS_PER_ENC 4
+#define MAX_CHANNELS_PER_ENC 2
#define MAX_CWB_PER_ENC 2
#define IDLE_SHORT_TIMEOUT 1
@@ -661,6 +661,7 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
struct msm_drm_private *priv = dpu_enc->base.dev->dev_private;
struct msm_display_info *disp_info = &dpu_enc->disp_info;
+ struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
struct drm_connector *connector;
struct drm_connector_state *conn_state;
struct drm_framebuffer *fb;
@@ -674,12 +675,22 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
dsc = dpu_encoder_get_dsc_config(drm_enc);
- /*
- * Set DSC number as 1 to mark the enabled status, will be adjusted
- * in dpu_crtc_get_topology()
- */
- if (dsc)
- topology->num_dsc = 1;
+ /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
+ if (dsc) {
+ /*
+ * Use 2 DSC encoders, 2 layer mixers and 1 or 2 interfaces
+ * when Display Stream Compression (DSC) is enabled,
+ * and when enough DSC blocks are available.
+ * This is power-optimal and can drive up to (including) 4k
+ * screens.
+ */
+ WARN(topology->num_intf > 2,
+ "DSC topology cannot support more than 2 interfaces\n");
+ if (topology->num_intf >= 2 || dpu_kms->catalog->dsc_count >= 2)
+ topology->num_dsc = 2;
+ else
+ topology->num_dsc = 1;
+ }
connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
if (!connector)
@@ -2169,8 +2180,8 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
{
int i, num_lm;
struct dpu_global_state *global_state;
- struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
- struct dpu_hw_mixer *hw_mixer[MAX_CHANNELS_PER_ENC];
+ struct dpu_hw_blk *hw_lm[2];
+ struct dpu_hw_mixer *hw_mixer[2];
struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
/* reset all mixers for this encoder */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 09395d7910ac..61b22d949454 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -302,7 +302,7 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
/* Use merge_3d unless DSC MERGE topology is used */
if (phys_enc->split_role == ENC_ROLE_SOLO &&
- (dpu_cstate->num_mixers != 1) &&
+ dpu_cstate->num_mixers == CRTC_DUAL_MIXERS &&
!dpu_encoder_use_dsc_merge(phys_enc->parent))
return BLEND_3D_H_ROW_INT;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 46f348972a97..6d28f2281c76 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -247,14 +247,12 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
if (hw_cdm)
intf_cfg.cdm = hw_cdm->idx;
- if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode)
- phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
- mode_3d);
+ if (hw_pp && hw_pp->merge_3d && hw_pp->merge_3d->ops.setup_3d_mode)
+ hw_pp->merge_3d->ops.setup_3d_mode(hw_pp->merge_3d, mode_3d);
/* setup which pp blk will connect to this wb */
- if (hw_pp && phys_enc->hw_wb->ops.bind_pingpong_blk)
- phys_enc->hw_wb->ops.bind_pingpong_blk(phys_enc->hw_wb,
- phys_enc->hw_pp->idx);
+ if (hw_pp && hw_wb->ops.bind_pingpong_blk)
+ hw_wb->ops.bind_pingpong_blk(hw_wb, hw_pp->idx);
phys_enc->hw_ctl->ops.setup_intf_cfg(phys_enc->hw_ctl, &intf_cfg);
} else if (phys_enc->hw_ctl && phys_enc->hw_ctl->ops.setup_intf_cfg) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 336757103b5a..4964e70610d1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -24,7 +24,7 @@
#define DPU_MAX_IMG_WIDTH 0x3fff
#define DPU_MAX_IMG_HEIGHT 0x3fff
-#define CRTC_QUAD_MIXERS 4
+#define CRTC_DUAL_MIXERS 2
#define MAX_XIN_COUNT 16
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
index 6bb3476a05f8..75e6dae0fcd9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
@@ -89,13 +89,13 @@ enum dpu_hw_cdwn_op_mode_method_h_v {
*/
struct dpu_hw_cdm_ops {
/**
- * Enable the CDM module
+ * @enable: Enable the CDM module
* @cdm Pointer to chroma down context
*/
int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
/**
- * Enable/disable the connection with pingpong
+ * @bind_pingpong_blk: Enable/disable the connection with pingpong
* @cdm Pointer to chroma down context
* @pp pingpong block id.
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 15931b22ec94..e535bf013825 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -12,9 +12,9 @@
#include "dpu_hw_sspp.h"
/**
- * dpu_ctl_mode_sel: Interface mode selection
- * DPU_CTL_MODE_SEL_VID: Video mode interface
- * DPU_CTL_MODE_SEL_CMD: Command mode interface
+ * enum dpu_ctl_mode_sel: Interface mode selection
+ * @DPU_CTL_MODE_SEL_VID: Video mode interface
+ * @DPU_CTL_MODE_SEL_CMD: Command mode interface
*/
enum dpu_ctl_mode_sel {
DPU_CTL_MODE_SEL_VID = 0,
@@ -37,6 +37,7 @@ struct dpu_hw_stage_cfg {
* struct dpu_hw_intf_cfg :Describes how the DPU writes data to output interface
* @intf : Interface id
* @intf_master: Master interface id in the dual pipe topology
+ * @wb: Writeback mode
* @mode_3d: 3d mux configuration
* @merge_3d: 3d merge block used
* @intf_mode_sel: Interface mode, cmd / vid
@@ -64,21 +65,21 @@ struct dpu_hw_intf_cfg {
*/
struct dpu_hw_ctl_ops {
/**
- * kickoff hw operation for Sw controlled interfaces
+ * @trigger_start: kickoff hw operation for Sw controlled interfaces
* DSI cmd mode and WB interface are SW controlled
* @ctx : ctl path ctx pointer
*/
void (*trigger_start)(struct dpu_hw_ctl *ctx);
/**
- * check if the ctl is started
+ * @is_started: check if the ctl is started
* @ctx : ctl path ctx pointer
* @Return: true if started, false if stopped
*/
bool (*is_started)(struct dpu_hw_ctl *ctx);
/**
- * kickoff prepare is in progress hw operation for sw
+ * @trigger_pending: kickoff prepare is in progress hw operation for sw
* controlled interfaces: DSI cmd mode and WB interface
* are SW controlled
* @ctx : ctl path ctx pointer
@@ -86,7 +87,7 @@ struct dpu_hw_ctl_ops {
void (*trigger_pending)(struct dpu_hw_ctl *ctx);
/**
- * Clear the value of the cached pending_flush_mask
+ * @clear_pending_flush: Clear the value of the cached pending_flush_mask
* No effect on hardware.
* Required to be implemented.
* @ctx : ctl path ctx pointer
@@ -94,14 +95,15 @@ struct dpu_hw_ctl_ops {
void (*clear_pending_flush)(struct dpu_hw_ctl *ctx);
/**
- * Query the value of the cached pending_flush_mask
+ * @get_pending_flush: Query the value of the cached pending_flush_mask
* No effect on hardware
* @ctx : ctl path ctx pointer
*/
u32 (*get_pending_flush)(struct dpu_hw_ctl *ctx);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush: OR in the given flushbits to the cached
+ * pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @flushbits : module flushmask
@@ -110,7 +112,8 @@ struct dpu_hw_ctl_ops {
u32 flushbits);
/**
- * OR in the given flushbits to the cached pending_(wb_)flush_mask
+ * @update_pending_flush_wb: OR in the given flushbits to the
+ * cached pending_(wb_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : writeback block index
@@ -119,7 +122,8 @@ struct dpu_hw_ctl_ops {
enum dpu_wb blk);
/**
- * OR in the given flushbits to the cached pending_(cwb_)flush_mask
+ * @update_pending_flush_cwb: OR in the given flushbits to the
+ * cached pending_(cwb_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : concurrent writeback block index
@@ -128,7 +132,8 @@ struct dpu_hw_ctl_ops {
enum dpu_cwb blk);
/**
- * OR in the given flushbits to the cached pending_(intf_)flush_mask
+ * @update_pending_flush_intf: OR in the given flushbits to the
+ * cached pending_(intf_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@@ -137,7 +142,8 @@ struct dpu_hw_ctl_ops {
enum dpu_intf blk);
/**
- * OR in the given flushbits to the cached pending_(periph_)flush_mask
+ * @update_pending_flush_periph: OR in the given flushbits to the
+ * cached pending_(periph_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@@ -146,7 +152,8 @@ struct dpu_hw_ctl_ops {
enum dpu_intf blk);
/**
- * OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
+ * @update_pending_flush_merge_3d: OR in the given flushbits to the
+ * cached pending_(merge_3d_)flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : interface block index
@@ -155,7 +162,8 @@ struct dpu_hw_ctl_ops {
enum dpu_merge_3d blk);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush_sspp: OR in the given flushbits to the
+ * cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : SSPP block index
@@ -164,7 +172,8 @@ struct dpu_hw_ctl_ops {
enum dpu_sspp blk);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush_mixer: OR in the given flushbits to the
+ * cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : LM block index
@@ -173,7 +182,8 @@ struct dpu_hw_ctl_ops {
enum dpu_lm blk);
/**
- * OR in the given flushbits to the cached pending_flush_mask
+ * @update_pending_flush_dspp: OR in the given flushbits to the
+ * cached pending_flush_mask.
* No effect on hardware
* @ctx : ctl path ctx pointer
* @blk : DSPP block index
@@ -183,7 +193,8 @@ struct dpu_hw_ctl_ops {
enum dpu_dspp blk, u32 dspp_sub_blk);
/**
- * OR in the given flushbits to the cached pending_(dsc_)flush_mask
+ * @update_pending_flush_dsc: OR in the given flushbits to the
+ * cached pending_(dsc_)flush_mask.
* No effect on hardware
* @ctx: ctl path ctx pointer
* @blk: interface block index
@@ -192,7 +203,8 @@ struct dpu_hw_ctl_ops {
enum dpu_dsc blk);
/**
- * OR in the given flushbits to the cached pending_(cdm_)flush_mask
+ * @update_pending_flush_cdm: OR in the given flushbits to the
+ * cached pending_(cdm_)flush_mask.
* No effect on hardware
* @ctx: ctl path ctx pointer
* @cdm_num: idx of cdm to be flushed
@@ -200,20 +212,20 @@ struct dpu_hw_ctl_ops {
void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num);
/**
- * Write the value of the pending_flush_mask to hardware
+ * @trigger_flush: Write the value of the pending_flush_mask to hardware
* @ctx : ctl path ctx pointer
*/
void (*trigger_flush)(struct dpu_hw_ctl *ctx);
/**
- * Read the value of the flush register
+ * @get_flush_register: Read the value of the flush register
* @ctx : ctl path ctx pointer
* @Return: value of the ctl flush register.
*/
u32 (*get_flush_register)(struct dpu_hw_ctl *ctx);
/**
- * Setup ctl_path interface config
+ * @setup_intf_cfg: Setup ctl_path interface config
* @ctx
* @cfg : interface config structure pointer
*/
@@ -221,17 +233,20 @@ struct dpu_hw_ctl_ops {
struct dpu_hw_intf_cfg *cfg);
/**
- * reset ctl_path interface config
+ * @reset_intf_cfg: reset ctl_path interface config
* @ctx : ctl path ctx pointer
* @cfg : interface config structure pointer
*/
void (*reset_intf_cfg)(struct dpu_hw_ctl *ctx,
struct dpu_hw_intf_cfg *cfg);
+ /**
+ * @reset: reset function for this ctl type
+ */
int (*reset)(struct dpu_hw_ctl *c);
- /*
- * wait_reset_status - checks ctl reset status
+ /**
+ * @wait_reset_status: checks ctl reset status
* @ctx : ctl path ctx pointer
*
* This function checks the ctl reset status bit.
@@ -242,13 +257,13 @@ struct dpu_hw_ctl_ops {
int (*wait_reset_status)(struct dpu_hw_ctl *ctx);
/**
- * Set all blend stages to disabled
+ * @clear_all_blendstages: Set all blend stages to disabled
* @ctx : ctl path ctx pointer
*/
void (*clear_all_blendstages)(struct dpu_hw_ctl *ctx);
/**
- * Configure layer mixer to pipe configuration
+ * @setup_blendstage: Configure layer mixer to pipe configuration
* @ctx : ctl path ctx pointer
* @lm : layer mixer enumeration
* @cfg : blend stage configuration
@@ -256,11 +271,16 @@ struct dpu_hw_ctl_ops {
void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
+ /**
+ * @set_active_fetch_pipes: Set active pipes attached to this CTL
+ * @ctx: ctl path ctx pointer
+ * @active_pipes: bitmap of enum dpu_sspp
+ */
void (*set_active_fetch_pipes)(struct dpu_hw_ctl *ctx,
unsigned long *fetch_active);
/**
- * Set active pipes attached to this CTL
+ * @set_active_pipes: Set active pipes attached to this CTL
* @ctx: ctl path ctx pointer
* @active_pipes: bitmap of enum dpu_sspp
*/
@@ -268,13 +288,12 @@ struct dpu_hw_ctl_ops {
unsigned long *active_pipes);
/**
- * Set active layer mixers attached to this CTL
+ * @set_active_lms: Set active layer mixers attached to this CTL
* @ctx: ctl path ctx pointer
* @active_lms: bitmap of enum dpu_lm
*/
void (*set_active_lms)(struct dpu_hw_ctl *ctx,
unsigned long *active_lms);
-
};
/**
@@ -289,6 +308,9 @@ struct dpu_hw_ctl_ops {
* @pending_intf_flush_mask: pending INTF flush
* @pending_wb_flush_mask: pending WB flush
* @pending_cwb_flush_mask: pending CWB flush
+ * @pending_periph_flush_mask: pending PERIPH flush
+ * @pending_merge_3d_flush_mask: pending MERGE 3D flush
+ * @pending_dspp_flush_mask: pending DSPP flush
* @pending_dsc_flush_mask: pending DSC flush
* @pending_cdm_flush_mask: pending CDM flush
* @mdss_ver: MDSS revision information
@@ -320,7 +342,7 @@ struct dpu_hw_ctl {
};
/**
- * dpu_hw_ctl - convert base object dpu_hw_base to container
+ * to_dpu_hw_ctl - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
index 96b6edf6b2bb..ed7bfcee7f1c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
@@ -28,7 +28,6 @@ struct dpu_hw_cwb_setup_cfg {
};
/**
- *
* struct dpu_hw_cwb_ops : Interface to the cwb hw driver functions
* @config_cwb: configure CWB mux
*/
@@ -54,7 +53,7 @@ struct dpu_hw_cwb {
};
/**
- * dpu_hw_cwb - convert base object dpu_hw_base to container
+ * to_dpu_hw_cwb - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
index cc7cc6f6f7cd..39d93b9df051 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -21,13 +21,13 @@ struct dpu_hw_dsc;
*/
struct dpu_hw_dsc_ops {
/**
- * dsc_disable - disable dsc
+ * @dsc_disable: disable dsc
* @hw_dsc: Pointer to dsc context
*/
void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
/**
- * dsc_config - configures dsc encoder
+ * @dsc_config: configures dsc encoder
* @hw_dsc: Pointer to dsc context
* @dsc: panel dsc parameters
* @mode: dsc topology mode to be set
@@ -39,13 +39,17 @@ struct dpu_hw_dsc_ops {
u32 initial_lines);
/**
- * dsc_config_thresh - programs panel thresholds
+ * @dsc_config_thresh: programs panel thresholds
* @hw_dsc: Pointer to dsc context
* @dsc: panel dsc parameters
*/
void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
struct drm_dsc_config *dsc);
+ /**
+ * @dsc_bind_pingpong_blk: binds pixel output from a DSC block
+ * to a pingpong block
+ */
void (*dsc_bind_pingpong_blk)(struct dpu_hw_dsc *hw_dsc,
enum dpu_pingpong pp);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
index 45c26cd49fa3..722b0f482e9b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h
@@ -22,7 +22,7 @@ struct dpu_hw_pcc_coeff {
};
/**
- * struct dpu_hw_pcc - pcc feature structure
+ * struct dpu_hw_pcc_cfg - pcc feature structure
* @r: red coefficients.
* @g: green coefficients.
* @b: blue coefficients.
@@ -40,7 +40,7 @@ struct dpu_hw_pcc_cfg {
*/
struct dpu_hw_dspp_ops {
/**
- * setup_pcc - setup dspp pcc
+ * @setup_pcc: setup_pcc - setup dspp pcc
* @ctx: Pointer to dspp context
* @cfg: Pointer to configuration
*/
@@ -69,7 +69,7 @@ struct dpu_hw_dspp {
};
/**
- * dpu_hw_dspp - convert base object dpu_hw_base to container
+ * to_dpu_hw_dspp - convert base object dpu_hw_base to container
* @hw: Pointer to base hardware block
* return: Pointer to hardware block container
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index f31067a9aaf1..5a19cd74fa94 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -57,11 +57,11 @@ struct dpu_hw_intf_cmd_mode_cfg {
/**
* struct dpu_hw_intf_ops : Interface to the interface Hw driver functions
* Assumption is these functions will be called after clocks are enabled
- * @ setup_timing_gen : programs the timing engine
- * @ setup_prog_fetch : enables/disables the programmable fetch logic
- * @ enable_timing: enable/disable timing engine
- * @ get_status: returns if timing engine is enabled or not
- * @ get_line_count: reads current vertical line counter
+ * @setup_timing_gen : programs the timing engine
+ * @setup_prg_fetch : enables/disables the programmable fetch logic
+ * @enable_timing: enable/disable timing engine
+ * @get_status: returns if timing engine is enabled or not
+ * @get_line_count: reads current vertical line counter
* @bind_pingpong_blk: enable/disable the connection with pingpong which will
* feed pixels to this interface
* @setup_misr: enable/disable MISR
@@ -70,12 +70,9 @@ struct dpu_hw_intf_cmd_mode_cfg {
* pointer and programs the tear check configuration
* @disable_tearcheck: Disables tearcheck block
* @connect_external_te: Read, modify, write to either set or clear listening to external TE
- * Return: 1 if TE was originally connected, 0 if not, or -ERROR
- * @get_vsync_info: Provides the programmed and current line_count
- * @setup_autorefresh: Configure and enable the autorefresh config
- * @get_autorefresh: Retrieve autorefresh config from hardware
- * Return: 0 on success, -ETIMEDOUT on timeout
+ * Returns 1 if TE was originally connected, 0 if not, or -ERROR
* @vsync_sel: Select vsync signal for tear-effect configuration
+ * @disable_autorefresh: Disable autorefresh if enabled
* @program_intf_cmd_cfg: Program the DPU to interface datapath for command mode
*/
struct dpu_hw_intf_ops {
@@ -109,9 +106,6 @@ struct dpu_hw_intf_ops {
void (*vsync_sel)(struct dpu_hw_intf *intf, enum dpu_vsync_source vsync_source);
- /**
- * Disable autorefresh if enabled
- */
void (*disable_autorefresh)(struct dpu_hw_intf *intf, uint32_t encoder_id, u16 vdisplay);
void (*program_intf_cmd_cfg)(struct dpu_hw_intf *intf,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
index 1b9ecd082d7f..ecbb77711d83 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
@@ -25,39 +25,38 @@ struct dpu_hw_color3_cfg {
};
/**
- *
* struct dpu_hw_lm_ops : Interface to the mixer Hw driver functions
* Assumption is these functions will be called after clocks are enabled
*/
struct dpu_hw_lm_ops {
- /*
- * Sets up mixer output width and height
+ /**
+ * @setup_mixer_out: Sets up mixer output width and height
* and border color if enabled
*/
void (*setup_mixer_out)(struct dpu_hw_mixer *ctx,
struct dpu_hw_mixer_cfg *cfg);
- /*
- * Alpha blending configuration
+ /**
+ * @setup_blend_config: Alpha blending configuration
* for the specified stage
*/
void (*setup_blend_config)(struct dpu_hw_mixer *ctx, uint32_t stage,
uint32_t fg_alpha, uint32_t bg_alpha, uint32_t blend_op);
- /*
- * Alpha color component selection from either fg or bg
+ /**
+ * @setup_alpha_out: Alpha color component selection from either fg or bg
*/
void (*setup_alpha_out)(struct dpu_hw_mixer *ctx, uint32_t mixer_op);
/**
- * Clear layer mixer to pipe configuration
+ * @clear_all_blendstages: Clear layer mixer to pipe configuration
* @ctx : mixer ctx pointer
* Returns: 0 on success or -error
*/
int (*clear_all_blendstages)(struct dpu_hw_mixer *ctx);
/**
- * Configure layer mixer to pipe configuration
+ * @setup_blendstage: Configure layer mixer to pipe configuration
* @ctx : mixer ctx pointer
* @lm : layer mixer enumeration
* @stage_cfg : blend stage configuration
@@ -67,19 +66,19 @@ struct dpu_hw_lm_ops {
struct dpu_hw_stage_cfg *stage_cfg);
/**
- * setup_border_color : enable/disable border color
+ * @setup_border_color : enable/disable border color
*/
void (*setup_border_color)(struct dpu_hw_mixer *ctx,
struct dpu_mdss_color *color,
u8 border_en);
/**
- * setup_misr: Enable/disable MISR
+ * @setup_misr: Enable/disable MISR
*/
void (*setup_misr)(struct dpu_hw_mixer *ctx);
/**
- * collect_misr: Read MISR signature
+ * @collect_misr: Read MISR signature
*/
int (*collect_misr)(struct dpu_hw_mixer *ctx, u32 *misr_value);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 31451241f083..046b683d4c66 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -34,7 +34,7 @@
#define DPU_MAX_PLANES 4
#endif
-#define STAGES_PER_PLANE 2
+#define STAGES_PER_PLANE 1
#define PIPES_PER_STAGE 2
#define PIPES_PER_PLANE (PIPES_PER_STAGE * STAGES_PER_PLANE)
#ifndef DPU_MAX_DE_CURVES
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
index 6833c0207523..b57f88187148 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h
@@ -12,7 +12,6 @@
struct dpu_hw_merge_3d;
/**
- *
* struct dpu_hw_merge_3d_ops : Interface to the merge_3d Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @setup_3d_mode : enable 3D merge
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index dd99e1c21a1e..effd012d864a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -34,7 +34,6 @@ struct dpu_hw_dither_cfg {
};
/**
- *
* struct dpu_hw_pingpong_ops : Interface to the pingpong Hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @enable_tearcheck: program and enable tear check block
@@ -44,51 +43,52 @@ struct dpu_hw_dither_cfg {
*/
struct dpu_hw_pingpong_ops {
/**
- * enables vysnc generation and sets up init value of
+ * @enable_tearcheck: enables vysnc generation and sets up init value of
* read pointer and programs the tear check cofiguration
*/
int (*enable_tearcheck)(struct dpu_hw_pingpong *pp,
struct dpu_hw_tear_check *cfg);
/**
- * disables tear check block
+ * @disable_tearcheck: disables tear check block
*/
int (*disable_tearcheck)(struct dpu_hw_pingpong *pp);
/**
- * read, modify, write to either set or clear listening to external TE
+ * @connect_external_te: read, modify, write to either set or clear
+ * listening to external TE
* @Return: 1 if TE was originally connected, 0 if not, or -ERROR
*/
int (*connect_external_te)(struct dpu_hw_pingpong *pp,
bool enable_external_te);
/**
- * Obtain current vertical line counter
+ * @get_line_count: Obtain current vertical line counter
*/
u32 (*get_line_count)(struct dpu_hw_pingpong *pp);
/**
- * Disable autorefresh if enabled
+ * @disable_autorefresh: Disable autorefresh if enabled
*/
void (*disable_autorefresh)(struct dpu_hw_pingpong *pp, uint32_t encoder_id, u16 vdisplay);
/**
- * Setup dither matix for pingpong block
+ * @setup_dither: Setup dither matix for pingpong block
*/
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
/**
- * Enable DSC
+ * @enable_dsc: Enable DSC
*/
int (*enable_dsc)(struct dpu_hw_pingpong *pp);
/**
- * Disable DSC
+ * @disable_dsc: Disable DSC
*/
void (*disable_dsc)(struct dpu_hw_pingpong *pp);
/**
- * Setup DSC
+ * @setup_dsc: Setup DSC
*/
int (*setup_dsc)(struct dpu_hw_pingpong *pp);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index bdac5c04bf79..3822094f85bc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -14,7 +14,7 @@ struct dpu_hw_sspp;
#define DPU_SSPP_MAX_PITCH_SIZE 0xffff
-/**
+/*
* Flags
*/
#define DPU_SSPP_FLIP_LR BIT(0)
@@ -23,7 +23,7 @@ struct dpu_hw_sspp;
#define DPU_SSPP_ROT_90 BIT(3)
#define DPU_SSPP_SOLID_FILL BIT(4)
-/**
+/*
* Component indices
*/
enum {
@@ -36,9 +36,10 @@ enum {
};
/**
- * DPU_SSPP_RECT_SOLO - multirect disabled
- * DPU_SSPP_RECT_0 - rect0 of a multirect pipe
- * DPU_SSPP_RECT_1 - rect1 of a multirect pipe
+ * enum dpu_sspp_multirect_index - multirect mode
+ * @DPU_SSPP_RECT_SOLO: multirect disabled
+ * @DPU_SSPP_RECT_0: rect0 of a multirect pipe
+ * @DPU_SSPP_RECT_1: rect1 of a multirect pipe
*
* Note: HW supports multirect with either RECT0 or
* RECT1. Considering no benefit of such configs over
@@ -143,7 +144,7 @@ struct dpu_hw_pixel_ext {
* struct dpu_sw_pipe_cfg : software pipe configuration
* @src_rect: src ROI, caller takes into account the different operations
* such as decimation, flip etc to program this field
- * @dest_rect: destination ROI.
+ * @dst_rect: destination ROI.
* @rotation: simplified drm rotation hint
*/
struct dpu_sw_pipe_cfg {
@@ -165,8 +166,8 @@ struct dpu_hw_pipe_ts_cfg {
/**
* struct dpu_sw_pipe - software pipe description
* @sspp: backing SSPP pipe
- * @index: index of the rectangle of SSPP
- * @mode: parallel or time multiplex multirect mode
+ * @multirect_index: index of the rectangle of SSPP
+ * @multirect_mode: parallel or time multiplex multirect mode
*/
struct dpu_sw_pipe {
struct dpu_hw_sspp *sspp;
@@ -181,7 +182,7 @@ struct dpu_sw_pipe {
*/
struct dpu_hw_sspp_ops {
/**
- * setup_format - setup pixel format cropping rectangle, flip
+ * @setup_format: setup pixel format cropping rectangle, flip
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
* @flags: Extra flags for format config
@@ -190,7 +191,7 @@ struct dpu_hw_sspp_ops {
const struct msm_format *fmt, u32 flags);
/**
- * setup_rects - setup pipe ROI rectangles
+ * @setup_rects: setup pipe ROI rectangles
* @pipe: Pointer to software pipe context
* @cfg: Pointer to pipe config structure
*/
@@ -198,7 +199,7 @@ struct dpu_hw_sspp_ops {
struct dpu_sw_pipe_cfg *cfg);
/**
- * setup_pe - setup pipe pixel extension
+ * @setup_pe: setup pipe pixel extension
* @ctx: Pointer to pipe context
* @pe_ext: Pointer to pixel ext settings
*/
@@ -206,7 +207,7 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_pixel_ext *pe_ext);
/**
- * setup_sourceaddress - setup pipe source addresses
+ * @setup_sourceaddress: setup pipe source addresses
* @pipe: Pointer to software pipe context
* @layout: format layout information for programming buffer to hardware
*/
@@ -214,14 +215,14 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_fmt_layout *layout);
/**
- * setup_csc - setup color space coversion
+ * @setup_csc: setup color space coversion
* @ctx: Pointer to pipe context
* @data: Pointer to config structure
*/
void (*setup_csc)(struct dpu_hw_sspp *ctx, const struct dpu_csc_cfg *data);
/**
- * setup_solidfill - enable/disable colorfill
+ * @setup_solidfill: enable/disable colorfill
* @pipe: Pointer to software pipe context
* @const_color: Fill color value
* @flags: Pipe flags
@@ -229,23 +230,22 @@ struct dpu_hw_sspp_ops {
void (*setup_solidfill)(struct dpu_sw_pipe *pipe, u32 color);
/**
- * setup_multirect - setup multirect configuration
+ * @setup_multirect: setup multirect configuration
* @pipe: Pointer to software pipe context
*/
void (*setup_multirect)(struct dpu_sw_pipe *pipe);
/**
- * setup_sharpening - setup sharpening
+ * @setup_sharpening: setup sharpening
* @ctx: Pointer to pipe context
* @cfg: Pointer to config structure
*/
void (*setup_sharpening)(struct dpu_hw_sspp *ctx,
struct dpu_hw_sharp_cfg *cfg);
-
/**
- * setup_qos_lut - setup QoS LUTs
+ * @setup_qos_lut: setup QoS LUTs
* @ctx: Pointer to pipe context
* @cfg: LUT configuration
*/
@@ -253,7 +253,7 @@ struct dpu_hw_sspp_ops {
struct dpu_hw_qos_cfg *cfg);
/**
- * setup_qos_ctrl - setup QoS control
+ * @setup_qos_ctrl: setup QoS control
* @ctx: Pointer to pipe context
* @danger_safe_en: flags controlling enabling of danger/safe QoS/LUT
*/
@@ -261,7 +261,7 @@ struct dpu_hw_sspp_ops {
bool danger_safe_en);
/**
- * setup_clk_force_ctrl - setup clock force control
+ * @setup_clk_force_ctrl: setup clock force control
* @ctx: Pointer to pipe context
* @enable: enable clock force if true
*/
@@ -269,7 +269,7 @@ struct dpu_hw_sspp_ops {
bool enable);
/**
- * setup_histogram - setup histograms
+ * @setup_histogram: setup histograms
* @ctx: Pointer to pipe context
* @cfg: Pointer to histogram configuration
*/
@@ -277,7 +277,7 @@ struct dpu_hw_sspp_ops {
void *cfg);
/**
- * setup_scaler - setup scaler
+ * @setup_scaler: setup scaler
* @scaler3_cfg: Pointer to scaler configuration
* @format: pixel format parameters
*/
@@ -286,7 +286,7 @@ struct dpu_hw_sspp_ops {
const struct msm_format *format);
/**
- * setup_cdp - setup client driven prefetch
+ * @setup_cdp: setup client driven prefetch
* @pipe: Pointer to software pipe context
* @fmt: format used by the sw pipe
* @enable: whether the CDP should be enabled for this pipe
@@ -303,6 +303,7 @@ struct dpu_hw_sspp_ops {
* @ubwc: UBWC configuration data
* @idx: pipe index
* @cap: pointer to layer_cfg
+ * @mdss_ver: MDSS version info to use for feature checks
* @ops: pointer to operations possible for this pipe
*/
struct dpu_hw_sspp {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 04efdcd21ceb..80279d87c2cd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -77,12 +77,11 @@ enum dpu_dp_phy_sel {
/**
* struct dpu_hw_mdp_ops - interface to the MDP TOP Hw driver functions
* Assumption is these functions will be called after clocks are enabled.
- * @setup_split_pipe : Programs the pipe control registers
- * @setup_pp_split : Programs the pp split control registers
- * @setup_traffic_shaper : programs traffic shaper control
*/
struct dpu_hw_mdp_ops {
- /** setup_split_pipe() : Registers are not double buffered, thisk
+ /**
+ * @setup_split_pipe : Programs the pipe control registers.
+ * Registers are not double buffered, this
* function should be called before timing control enable
* @mdp : mdp top context driver
* @cfg : upper and lower part of pipe configuration
@@ -91,7 +90,7 @@ struct dpu_hw_mdp_ops {
struct split_pipe_cfg *p);
/**
- * setup_traffic_shaper() : Setup traffic shaper control
+ * @setup_traffic_shaper : programs traffic shaper control.
* @mdp : mdp top context driver
* @cfg : traffic shaper configuration
*/
@@ -99,7 +98,7 @@ struct dpu_hw_mdp_ops {
struct traffic_shaper_cfg *cfg);
/**
- * setup_clk_force_ctrl - set clock force control
+ * @setup_clk_force_ctrl: set clock force control
* @mdp: mdp top context driver
* @clk_ctrl: clock to be controlled
* @enable: force on enable
@@ -109,7 +108,7 @@ struct dpu_hw_mdp_ops {
enum dpu_clk_ctrl_type clk_ctrl, bool enable);
/**
- * get_danger_status - get danger status
+ * @get_danger_status: get danger status
* @mdp: mdp top context driver
* @status: Pointer to danger safe status
*/
@@ -117,7 +116,7 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
- * setup_vsync_source - setup vsync source configuration details
+ * @setup_vsync_source: setup vsync source configuration details
* @mdp: mdp top context driver
* @cfg: vsync source selection configuration
*/
@@ -125,7 +124,7 @@ struct dpu_hw_mdp_ops {
struct dpu_vsync_source_cfg *cfg);
/**
- * get_safe_status - get safe status
+ * @get_safe_status: get safe status
* @mdp: mdp top context driver
* @status: Pointer to danger safe status
*/
@@ -133,14 +132,14 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
- * dp_phy_intf_sel - configure intf to phy mapping
+ * @dp_phy_intf_sel: configure intf to phy mapping
* @mdp: mdp top context driver
* @phys: list of phys the DP interfaces should be connected to. 0 disables the INTF.
*/
void (*dp_phy_intf_sel)(struct dpu_hw_mdp *mdp, enum dpu_dp_phy_sel phys[2]);
/**
- * intf_audio_select - select the external interface for audio
+ * @intf_audio_select: select the external interface for audio
* @mdp: mdp top context driver
*/
void (*intf_audio_select)(struct dpu_hw_mdp *mdp);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index 285121ec804c..9ac49448e432 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -17,7 +17,7 @@ struct dpu_hw_vbif;
*/
struct dpu_hw_vbif_ops {
/**
- * set_limit_conf - set transaction limit config
+ * @set_limit_conf: set transaction limit config
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @rd: true for read limit; false for write limit
@@ -27,7 +27,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool rd, u32 limit);
/**
- * get_limit_conf - get transaction limit config
+ * @get_limit_conf: get transaction limit config
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @rd: true for read limit; false for write limit
@@ -37,7 +37,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool rd);
/**
- * set_halt_ctrl - set halt control
+ * @set_halt_ctrl: set halt control
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @enable: halt control enable
@@ -46,7 +46,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, bool enable);
/**
- * get_halt_ctrl - get halt control
+ * @get_halt_ctrl: get halt control
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @return: halt control enable
@@ -55,7 +55,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id);
/**
- * set_qos_remap - set QoS priority remap
+ * @set_qos_remap: set QoS priority remap
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @level: priority level
@@ -65,7 +65,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, u32 level, u32 remap_level);
/**
- * set_mem_type - set memory type
+ * @set_mem_type: set memory type
* @vbif: vbif context driver
* @xin_id: client interface identifier
* @value: memory type value
@@ -74,7 +74,7 @@ struct dpu_hw_vbif_ops {
u32 xin_id, u32 value);
/**
- * clear_errors - clear any vbif errors
+ * @clear_errors: clear any vbif errors
* This function clears any detected pending/source errors
* on the VBIF interface, and optionally returns the detected
* error mask(s).
@@ -86,7 +86,7 @@ struct dpu_hw_vbif_ops {
u32 *pnd_errors, u32 *src_errors);
/**
- * set_write_gather_en - set write_gather enable
+ * @set_write_gather_en: set write_gather enable
* @vbif: vbif context driver
* @xin_id: client interface identifier
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
index ee5e5ab786e1..cfdbb5bb2a0f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
@@ -22,11 +22,11 @@ struct dpu_hw_wb_cfg {
};
/**
- *
* struct dpu_hw_wb_ops : Interface to the wb hw driver functions
* Assumption is these functions will be called after clocks are enabled
* @setup_outaddress: setup output address from the writeback job
* @setup_outformat: setup output format of writeback block from writeback job
+ * @setup_roi: setup ROI (Region of Interest) parameters
* @setup_qos_lut: setup qos LUT for writeback block based on input
* @setup_cdp: setup chroma down prefetch block for writeback block
* @setup_clk_force_ctrl: setup clock force control
@@ -61,7 +61,7 @@ struct dpu_hw_wb_ops {
* struct dpu_hw_wb : WB driver object
* @hw: block hardware details
* @idx: hardware index number within type
- * @wb_hw_caps: hardware capabilities
+ * @caps: hardware capabilities
* @ops: function pointers
*/
struct dpu_hw_wb {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index d07a6ab6e7ee..9b7a8b46bfa9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -826,12 +826,8 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
struct dpu_sw_pipe_cfg *pipe_cfg;
struct dpu_sw_pipe_cfg *r_pipe_cfg;
- struct dpu_sw_pipe_cfg init_pipe_cfg;
struct drm_rect fb_rect = { 0 };
- const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
uint32_t max_linewidth;
- u32 num_lm;
- int stage_id, num_stages;
min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO);
max_scale = MAX_DOWNSCALE_RATIO << 16;
@@ -854,10 +850,13 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
return -EINVAL;
}
- num_lm = dpu_crtc_get_num_lm(crtc_state);
-
+ /* move the assignment here, to ease handling to another pairs later */
+ pipe_cfg = &pstate->pipe_cfg[0];
+ r_pipe_cfg = &pstate->pipe_cfg[1];
/* state->src is 16.16, src_rect is not */
- drm_rect_fp_to_int(&init_pipe_cfg.src_rect, &new_plane_state->src);
+ drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
+
+ pipe_cfg->dst_rect = new_plane_state->dst;
fb_rect.x2 = new_plane_state->fb->width;
fb_rect.y2 = new_plane_state->fb->height;
@@ -882,94 +881,35 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
max_linewidth = pdpu->catalog->caps->max_linewidth;
- drm_rect_rotate(&init_pipe_cfg.src_rect,
+ drm_rect_rotate(&pipe_cfg->src_rect,
new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
- /*
- * We have 1 mixer pair cfg for 1:1:1 and 2:2:1 topology, 2 mixer pair
- * configs for left and right half screen in case of 4:4:2 topology.
- * But we may have 2 rect to split wide plane that exceeds limit with 1
- * config for 2:2:1. So need to handle both wide plane splitting, and
- * two halves of screen splitting for quad-pipe case. Check dest
- * rectangle left/right clipping first, then check wide rectangle
- * splitting in every half next.
- */
- num_stages = (num_lm + 1) / 2;
- /* iterate mixer configs for this plane, to separate left/right with the id */
- for (stage_id = 0; stage_id < num_stages; stage_id++) {
- struct drm_rect mixer_rect = {
- .x1 = stage_id * mode->hdisplay / num_stages,
- .y1 = 0,
- .x2 = (stage_id + 1) * mode->hdisplay / num_stages,
- .y2 = mode->vdisplay
- };
- int cfg_idx = stage_id * PIPES_PER_STAGE;
-
- pipe_cfg = &pstate->pipe_cfg[cfg_idx];
- r_pipe_cfg = &pstate->pipe_cfg[cfg_idx + 1];
-
- drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
- pipe_cfg->dst_rect = new_plane_state->dst;
-
- DPU_DEBUG_PLANE(pdpu, "checking src " DRM_RECT_FMT
- " vs clip window " DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect),
- DRM_RECT_ARG(&mixer_rect));
-
- /*
- * If this plane does not fall into mixer rect, check next
- * mixer rect.
- */
- if (!drm_rect_clip_scaled(&pipe_cfg->src_rect,
- &pipe_cfg->dst_rect,
- &mixer_rect)) {
- memset(pipe_cfg, 0, 2 * sizeof(struct dpu_sw_pipe_cfg));
-
- continue;
+ if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
+ _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {
+ if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
+ DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
+ DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
+ return -E2BIG;
}
- pipe_cfg->dst_rect.x1 -= mixer_rect.x1;
- pipe_cfg->dst_rect.x2 -= mixer_rect.x1;
-
- DPU_DEBUG_PLANE(pdpu, "Got clip src:" DRM_RECT_FMT " dst: " DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect), DRM_RECT_ARG(&pipe_cfg->dst_rect));
-
- /* Split wide rect into 2 rect */
- if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
- _dpu_plane_calc_clk(mode, pipe_cfg) > max_mdp_clk_rate) {
-
- if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) {
- DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth);
- return -E2BIG;
- }
-
- memcpy(r_pipe_cfg, pipe_cfg, sizeof(struct dpu_sw_pipe_cfg));
- pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
- pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
- r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
- r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
- DPU_DEBUG_PLANE(pdpu, "Split wide plane into:"
- DRM_RECT_FMT " and " DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&pipe_cfg->src_rect),
- DRM_RECT_ARG(&r_pipe_cfg->src_rect));
- } else {
- memset(r_pipe_cfg, 0, sizeof(struct dpu_sw_pipe_cfg));
- }
+ *r_pipe_cfg = *pipe_cfg;
+ pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
+ pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
+ r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
+ r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
+ } else {
+ memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg));
+ }
- drm_rect_rotate_inv(&pipe_cfg->src_rect,
- new_plane_state->fb->width,
- new_plane_state->fb->height,
+ drm_rect_rotate_inv(&pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
+ new_plane_state->rotation);
+ if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
+ drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
+ new_plane_state->fb->width, new_plane_state->fb->height,
new_plane_state->rotation);
- if (drm_rect_width(&r_pipe_cfg->src_rect) != 0)
- drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
- new_plane_state->fb->width,
- new_plane_state->fb->height,
- new_plane_state->rotation);
- }
-
pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
return 0;
@@ -1045,17 +985,20 @@ static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
drm_atomic_get_new_plane_state(state, plane);
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
- struct dpu_sw_pipe *pipe;
- struct dpu_sw_pipe_cfg *pipe_cfg;
- int ret = 0, i;
+ struct dpu_sw_pipe *pipe = &pstate->pipe[0];
+ struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
+ struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
+ struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
+ int ret = 0;
- for (i = 0; i < PIPES_PER_PLANE; i++) {
- pipe = &pstate->pipe[i];
- pipe_cfg = &pstate->pipe_cfg[i];
- if (!drm_rect_width(&pipe_cfg->src_rect))
- continue;
- DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i);
- ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
+ ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
+ &crtc_state->adjusted_mode,
+ new_plane_state);
+ if (ret)
+ return ret;
+
+ if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) {
+ ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg,
&crtc_state->adjusted_mode,
new_plane_state);
if (ret)
diff --git a/drivers/gpu/drm/msm/disp/mdp_format.h b/drivers/gpu/drm/msm/disp/mdp_format.h
index a00d646ff4d4..915954bf5dc7 100644
--- a/drivers/gpu/drm/msm/disp/mdp_format.h
+++ b/drivers/gpu/drm/msm/disp/mdp_format.h
@@ -24,7 +24,7 @@ enum msm_format_flags {
#define MSM_FORMAT_FLAG_UNPACK_TIGHT BIT(MSM_FORMAT_FLAG_UNPACK_TIGHT_BIT)
#define MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB BIT(MSM_FORMAT_FLAG_UNPACK_ALIGN_MSB_BIT)
-/**
+/*
* DPU HW,Component order color map
*/
enum {
@@ -37,6 +37,10 @@ enum {
/**
* struct msm_format: defines the format configuration
* @pixel_format: format fourcc
+ * @bpc_g_y: element bit widths: BPC for G or Y
+ * @bpc_b_cb: element bit widths: BPC for B or Cb
+ * @bpc_r_cr: element bit widths: BPC for R or Cr
+ * @bpc_a: element bit widths: BPC for the alpha channel
* @element: element color ordering
* @fetch_type: how the color components are packed in pixel format
* @chroma_sample: chroma sub-samplng type
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h
index 6dc0ff4f0f65..a90083fec856 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.h
+++ b/drivers/gpu/drm/msm/dp/dp_debug.h
@@ -12,7 +12,7 @@
#if defined(CONFIG_DEBUG_FS)
/**
- * msm_dp_debug_get() - configure and get the DisplayPlot debug module data
+ * msm_dp_debug_init() - configure and get the DisplayPlot debug module data
*
* @dev: device instance of the caller
* @panel: instance of panel module
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 9a461ab2f32f..fd6443d2b6ce 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -18,6 +18,7 @@
/**
* msm_dp_bridge_detect - callback to determine if connector is connected
* @bridge: Pointer to drm bridge structure
+ * @connector: Pointer to drm connector structure
* Returns: Bridge's 'is connected' status
*/
static enum drm_connector_status
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index b1eb2de6d2a7..8460e4ad2d35 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -80,11 +80,11 @@ struct msm_dp_link {
};
/**
- * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
+ * msm_dp_link_bit_depth_to_bpp() - convert test bit depth to bpp
* @tbd: test bit depth
*
- * Returns the bits per pixel (bpp) to be used corresponding to the
- * git bit depth value. This function assumes that bit depth has
+ * Returns: the bits per pixel (bpp) to be used corresponding to the
+ * bit depth value. This function assumes that bit depth has
* already been validated.
*/
static inline u32 msm_dp_link_bit_depth_to_bpp(u32 tbd)
@@ -120,7 +120,8 @@ bool msm_dp_link_send_edid_checksum(struct msm_dp_link *msm_dp_link, u8 checksum
/**
* msm_dp_link_get() - get the functionalities of dp test module
- *
+ * @dev: kernel device structure
+ * @aux: DisplayPort AUX channel
*
* return: a pointer to msm_dp_link struct
*/
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 921a296852d4..177c1328fd99 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -63,9 +63,9 @@ void msm_dp_panel_disable_vsc_sdp(struct msm_dp_panel *msm_dp_panel);
/**
* is_link_rate_valid() - validates the link rate
- * @lane_rate: link rate requested by the sink
+ * @bw_code: link rate requested by the sink
*
- * Returns true if the requested link rate is supported.
+ * Returns: true if the requested link rate is supported.
*/
static inline bool is_link_rate_valid(u32 bw_code)
{
@@ -76,10 +76,10 @@ static inline bool is_link_rate_valid(u32 bw_code)
}
/**
- * msm_dp_link_is_lane_count_valid() - validates the lane count
+ * is_lane_count_valid() - validates the lane count
* @lane_count: lane count requested by the sink
*
- * Returns true if the requested lane count is supported.
+ * Returns: true if the requested lane count is supported.
*/
static inline bool is_lane_count_valid(u32 lane_count)
{
diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h
index 148196375a0b..3317a485beef 100644
--- a/drivers/gpu/drm/msm/msm_fence.h
+++ b/drivers/gpu/drm/msm/msm_fence.h
@@ -16,34 +16,29 @@
* incrementing fence seqno at the end of each submit
*/
struct msm_fence_context {
+ /** @dev: the drm device */
struct drm_device *dev;
- /** name: human readable name for fence timeline */
+ /** @name: human readable name for fence timeline */
char name[32];
- /** context: see dma_fence_context_alloc() */
+ /** @context: see dma_fence_context_alloc() */
unsigned context;
- /** index: similar to context, but local to msm_fence_context's */
+ /** @index: similar to context, but local to msm_fence_context's */
unsigned index;
-
/**
- * last_fence:
- *
+ * @last_fence:
* Last assigned fence, incremented each time a fence is created
* on this fence context. If last_fence == completed_fence,
* there is no remaining pending work
*/
uint32_t last_fence;
-
/**
- * completed_fence:
- *
+ * @completed_fence:
* The last completed fence, updated from the CPU after interrupt
* from GPU
*/
uint32_t completed_fence;
-
/**
- * fenceptr:
- *
+ * @fenceptr:
* The address that the GPU directly writes with completed fence
* seqno. This can be ahead of completed_fence. We can peek at
* this to see if a fence has already signaled but the CPU hasn't
@@ -51,6 +46,9 @@ struct msm_fence_context {
*/
volatile uint32_t *fenceptr;
+ /**
+ * @spinlock: fence context spinlock
+ */
spinlock_t spinlock;
/*
@@ -59,18 +57,22 @@ struct msm_fence_context {
* don't queue, so maybe that is ok
*/
- /** next_deadline: Time of next deadline */
+ /** @next_deadline: Time of next deadline */
ktime_t next_deadline;
-
/**
- * next_deadline_fence:
- *
+ * @next_deadline_fence:
* Fence value for next pending deadline. The deadline timer is
* canceled when this fence is signaled.
*/
uint32_t next_deadline_fence;
-
+ /**
+ * @deadline_timer: tracks nearest deadline of a fence timeline and
+ * expires just before it.
+ */
struct hrtimer deadline_timer;
+ /**
+ * @deadline_work: work to do after deadline_timer expires
+ */
struct kthread_work deadline_work;
};
diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c
index 71d5238437eb..8f7c90167447 100644
--- a/drivers/gpu/drm/msm/msm_gem_vma.c
+++ b/drivers/gpu/drm/msm/msm_gem_vma.c
@@ -65,7 +65,7 @@ struct msm_vm_unmap_op {
};
/**
- * struct msm_vma_op - A MAP or UNMAP operation
+ * struct msm_vm_op - A MAP or UNMAP operation
*/
struct msm_vm_op {
/** @op: The operation type */
@@ -798,6 +798,9 @@ static const struct drm_sched_backend_ops msm_vm_bind_ops = {
* synchronous operations are supported. In a user managed VM, userspace
* handles virtual address allocation, and both async and sync operations
* are supported.
+ *
+ * Returns: pointer to the created &struct drm_gpuvm on success
+ * or an ERR_PTR(-errno) on failure.
*/
struct drm_gpuvm *
msm_gem_vm_create(struct drm_device *drm, struct msm_mmu *mmu, const char *name,
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 2894fc118485..666cf499b7ec 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -116,15 +116,12 @@ struct msm_gpu_fault_info {
* struct msm_gpu_devfreq - devfreq related state
*/
struct msm_gpu_devfreq {
- /** devfreq: devfreq instance */
+ /** @devfreq: devfreq instance */
struct devfreq *devfreq;
-
- /** lock: lock for "suspended", "busy_cycles", and "time" */
+ /** @lock: lock for "suspended", "busy_cycles", and "time" */
struct mutex lock;
-
/**
- * idle_freq:
- *
+ * @idle_freq:
* Shadow frequency used while the GPU is idle. From the PoV of
* the devfreq governor, we are continuing to sample busyness and
* adjust frequency while the GPU is idle, but we use this shadow
@@ -132,43 +129,34 @@ struct msm_gpu_devfreq {
* it is inactive.
*/
unsigned long idle_freq;
-
/**
- * boost_constraint:
- *
+ * @boost_freq:
* A PM QoS constraint to boost min freq for a period of time
* until the boost expires.
*/
struct dev_pm_qos_request boost_freq;
-
/**
- * busy_cycles: Last busy counter value, for calculating elapsed busy
+ * @busy_cycles: Last busy counter value, for calculating elapsed busy
* cycles since last sampling period.
*/
u64 busy_cycles;
-
- /** time: Time of last sampling period. */
+ /** @time: Time of last sampling period. */
ktime_t time;
-
- /** idle_time: Time of last transition to idle: */
+ /** @idle_time: Time of last transition to idle. */
ktime_t idle_time;
-
/**
- * idle_work:
- *
+ * @idle_work:
* Used to delay clamping to idle freq on active->idle transition.
*/
struct msm_hrtimer_work idle_work;
-
/**
- * boost_work:
- *
+ * @boost_work:
* Used to reset the boost_constraint after the boost period has
* elapsed
*/
struct msm_hrtimer_work boost_work;
- /** suspended: tracks if we're suspended */
+ /** @suspended: tracks if we're suspended */
bool suspended;
};
@@ -358,57 +346,43 @@ struct msm_gpu_perfcntr {
struct msm_context {
/** @queuelock: synchronizes access to submitqueues list */
rwlock_t queuelock;
-
/** @submitqueues: list of &msm_gpu_submitqueue created by userspace */
struct list_head submitqueues;
-
/**
* @queueid:
- *
* Counter incremented each time a submitqueue is created, used to
* assign &msm_gpu_submitqueue.id
*/
int queueid;
-
/**
* @closed: The device file associated with this context has been closed.
- *
* Once the device is closed, any submits that have not been written
* to the ring buffer are no-op'd.
*/
bool closed;
-
/**
* @userspace_managed_vm:
- *
* Has userspace opted-in to userspace managed VM (ie. VM_BIND) via
* MSM_PARAM_EN_VM_BIND?
*/
bool userspace_managed_vm;
-
/**
* @vm:
- *
* The per-process GPU address-space. Do not access directly, use
* msm_context_vm().
*/
struct drm_gpuvm *vm;
-
- /** @kref: the reference count */
+ /** @ref: the reference count */
struct kref ref;
-
/**
* @seqno:
- *
* A unique per-process sequence number. Used to detect context
* switches, without relying on keeping a, potentially dangling,
* pointer to the previous context.
*/
int seqno;
-
/**
* @sysprof:
- *
* The value of MSM_PARAM_SYSPROF set by userspace. This is
* intended to be used by system profiling tools like Mesa's
* pps-producer (perfetto), and restricted to CAP_SYS_ADMIN.
@@ -423,40 +397,32 @@ struct msm_context {
* file is closed.
*/
int sysprof;
-
/**
* @comm: Overridden task comm, see MSM_PARAM_COMM
*
* Accessed under msm_gpu::lock
*/
char *comm;
-
/**
* @cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE
*
* Accessed under msm_gpu::lock
*/
char *cmdline;
-
/**
- * @elapsed:
- *
+ * @elapsed_ns:
* The total (cumulative) elapsed time GPU was busy with rendering
* from this context in ns.
*/
uint64_t elapsed_ns;
-
/**
* @cycles:
- *
* The total (cumulative) GPU cycles elapsed attributed to this
* context.
*/
uint64_t cycles;
-
/**
* @entities:
- *
* Table of per-priority-level sched entities used by submitqueues
* associated with this &drm_file. Because some userspace apps
* make assumptions about rendering from multiple gl contexts
@@ -466,10 +432,8 @@ struct msm_context {
* level.
*/
struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS];
-
/**
* @ctx_mem:
- *
* Total amount of memory of GEM buffers with handles attached for
* this context.
*/
@@ -479,7 +443,7 @@ struct msm_context {
struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx);
/**
- * msm_context_is_vm_bind() - has userspace opted in to VM_BIND?
+ * msm_context_is_vmbind() - has userspace opted in to VM_BIND?
*
* @ctx: the drm_file context
*
@@ -487,6 +451,8 @@ struct drm_gpuvm *msm_context_vm(struct drm_device *dev, struct msm_context *ctx
* do sparse binding including having multiple, potentially partial,
* mappings in the VM. Therefore certain legacy uabi (ie. GET_IOVA,
* SET_IOVA) are rejected because they don't have a sensible meaning.
+ *
+ * Returns: %true if userspace is managing the VM, %false otherwise.
*/
static inline bool
msm_context_is_vmbind(struct msm_context *ctx)
@@ -518,6 +484,8 @@ msm_context_is_vmbind(struct msm_context *ctx)
* This allows generations without preemption (nr_rings==1) to have some
* amount of prioritization, and provides more priority levels for gens
* that do have preemption.
+ *
+ * Returns: %0 on success, %-errno on error.
*/
static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
unsigned *ring_nr, enum drm_sched_priority *sched_prio)
@@ -541,7 +509,7 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio,
}
/**
- * struct msm_gpu_submitqueues - Userspace created context.
+ * struct msm_gpu_submitqueue - Userspace created context.
*
* A submitqueue is associated with a gl context or vk queue (or equiv)
* in userspace.
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index a188617653e8..d5dede4ff761 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -364,7 +364,7 @@ msm_iommu_pagetable_prealloc_cleanup(struct msm_mmu *mmu, struct msm_mmu_preallo
}
/**
- * alloc_pt() - Custom page table allocator
+ * msm_iommu_pagetable_alloc_pt() - Custom page table allocator
* @cookie: Cookie passed at page table allocation time.
* @size: Size of the page table. This size should be fixed,
* and determined at creation time based on the granule size.
@@ -416,7 +416,7 @@ msm_iommu_pagetable_alloc_pt(void *cookie, size_t size, gfp_t gfp)
/**
- * free_pt() - Custom page table free function
+ * msm_iommu_pagetable_free_pt() - Custom page table free function
* @cookie: Cookie passed at page table allocation time.
* @data: Page table to free.
* @size: Size of the page table. This size should be fixed,
diff --git a/drivers/gpu/drm/msm/msm_perf.c b/drivers/gpu/drm/msm/msm_perf.c
index d3c7889aaf26..c369d4acc378 100644
--- a/drivers/gpu/drm/msm/msm_perf.c
+++ b/drivers/gpu/drm/msm/msm_perf.c
@@ -65,13 +65,13 @@ static int refill_buf(struct msm_perf_state *perf)
if ((perf->cnt++ % 32) == 0) {
/* Header line: */
- n = snprintf(ptr, rem, "%%BUSY");
+ n = scnprintf(ptr, rem, "%%BUSY");
ptr += n;
rem -= n;
for (i = 0; i < gpu->num_perfcntrs; i++) {
const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
- n = snprintf(ptr, rem, "\t%s", perfcntr->name);
+ n = scnprintf(ptr, rem, "\t%s", perfcntr->name);
ptr += n;
rem -= n;
}
@@ -93,21 +93,21 @@ static int refill_buf(struct msm_perf_state *perf)
return ret;
val = totaltime ? 1000 * activetime / totaltime : 0;
- n = snprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
+ n = scnprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
ptr += n;
rem -= n;
for (i = 0; i < ret; i++) {
/* cycle counters (I think).. convert to MHz.. */
val = cntrs[i] / 10000;
- n = snprintf(ptr, rem, "\t%5d.%02d",
+ n = scnprintf(ptr, rem, "\t%5d.%02d",
val / 100, val % 100);
ptr += n;
rem -= n;
}
}
- n = snprintf(ptr, rem, "\n");
+ n = scnprintf(ptr, rem, "\n");
ptr += n;
rem -= n;
diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
index 93f8f4f64578..b43c4f9bbcdf 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
@@ -152,8 +152,21 @@ static inline struct nv50_head_atom *
nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);
+
if (IS_ERR(statec))
return (void *)statec;
+
+ return nv50_head_atom(statec);
+}
+
+static inline struct nv50_head_atom *
+nv50_head_atom_get_new(struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+ struct drm_crtc_state *statec = drm_atomic_get_new_crtc_state(state, crtc);
+
+ if (!statec)
+ return NULL;
+
return nv50_head_atom(statec);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index ef9e410babbf..9a2c20fce0f3 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -583,7 +583,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
asyw->image.offset[0] = nvbo->offset;
if (wndw->func->prepare) {
- asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+ asyh = nv50_head_atom_get_new(asyw->state.state, asyw->state.crtc);
if (IS_ERR(asyh))
return PTR_ERR(asyh);
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 76f6af819037..7a83804fedca 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -1165,6 +1165,7 @@ config DRM_PANEL_VISIONOX_RM69299
tristate "Visionox RM69299"
depends on OF
depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for Visionox
RM69299 DSI Video Mode panel.
diff --git a/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c b/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c
index 7c989b70ab51..a14c86c60d19 100644
--- a/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c
+++ b/drivers/gpu/drm/panel/panel-sony-td4353-jdi.c
@@ -212,6 +212,8 @@ static int sony_td4353_jdi_probe(struct mipi_dsi_device *dsi)
if (ret)
return dev_err_probe(dev, ret, "Failed to get backlight\n");
+ ctx->panel.prepare_prev_first = true;
+
drm_panel_add(&ctx->panel);
ret = mipi_dsi_attach(dsi);
diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c
index 2f6ac7a09f44..bc27f65b2823 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c
@@ -156,24 +156,29 @@ static int set_up_atomic_state(struct kunit *test,
if (connector) {
conn_state = drm_atomic_get_connector_state(state, connector);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
+ if (IS_ERR(conn_state))
+ return PTR_ERR(conn_state);
ret = drm_atomic_set_crtc_for_connector(conn_state, crtc);
- KUNIT_EXPECT_EQ(test, ret, 0);
+ if (ret)
+ return ret;
}
crtc_state = drm_atomic_get_crtc_state(state, crtc);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
ret = drm_atomic_set_mode_for_crtc(crtc_state, &drm_atomic_test_mode);
- KUNIT_EXPECT_EQ(test, ret, 0);
+ if (ret)
+ return ret;
crtc_state->enable = true;
crtc_state->active = true;
if (connector) {
ret = drm_atomic_commit(state);
- KUNIT_ASSERT_EQ(test, ret, 0);
+ if (ret)
+ return ret;
} else {
// dummy connector mask
crtc_state->connector_mask = DRM_TEST_CONN_0;
@@ -206,7 +211,13 @@ static void drm_test_check_connector_changed_modeset(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
// first modeset to enable
+retry_set_up:
ret = set_up_atomic_state(test, priv, old_conn, &ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_set_up;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -277,13 +288,26 @@ static void drm_test_check_valid_clones(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_set_up:
ret = set_up_atomic_state(test, priv, NULL, &ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_set_up;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+retry:
crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
+ if (PTR_ERR(crtc_state) == -EDEADLK) {
+ drm_atomic_state_clear(state);
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry;
+ }
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
crtc_state->encoder_mask = param->encoder_mask;
@@ -292,6 +316,12 @@ static void drm_test_check_valid_clones(struct kunit *test)
crtc_state->mode_changed = true;
ret = drm_atomic_helper_check_modeset(drm, state);
+ if (ret == -EDEADLK) {
+ drm_atomic_state_clear(state);
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry;
+ }
KUNIT_ASSERT_EQ(test, ret, param->expected_result);
drm_modeset_drop_locks(&ctx);
diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
index 8bd412735000..70f9aa702143 100644
--- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
@@ -257,10 +257,16 @@ static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -326,10 +332,16 @@ static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *tes
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -397,10 +409,16 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -457,10 +475,17 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test)
KUNIT_ASSERT_NOT_NULL(test, mode);
crtc = priv->crtc;
+
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
mode,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -518,10 +543,16 @@ static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -580,10 +611,17 @@ static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test)
KUNIT_ASSERT_NOT_NULL(test, mode);
crtc = priv->crtc;
+
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
mode,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -643,10 +681,16 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -705,10 +749,17 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *te
KUNIT_ASSERT_NOT_NULL(test, mode);
crtc = priv->crtc;
+
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
mode,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -870,10 +921,16 @@ static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -946,10 +1003,16 @@ static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
@@ -1022,10 +1085,16 @@ static void drm_test_check_output_bpc_dvi(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1069,10 +1138,16 @@ static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1118,10 +1193,16 @@ static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1167,10 +1248,16 @@ static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1218,10 +1305,16 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
/* You shouldn't be doing that at home. */
@@ -1292,10 +1385,16 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1440,10 +1539,16 @@ static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1669,10 +1774,17 @@ static void drm_test_check_output_bpc_format_vic_1(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
crtc = priv->crtc;
+
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
mode,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1736,10 +1848,16 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1805,10 +1923,16 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1865,10 +1989,16 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1927,10 +2057,16 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes
drm_modeset_acquire_init(&ctx, 0);
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_EXPECT_EQ(test, ret, 0);
conn_state = conn->state;
@@ -1970,10 +2106,17 @@ static void drm_test_check_disable_connector(struct kunit *test)
drm = &priv->drm;
crtc = priv->crtc;
+
+retry_conn_enable:
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
crtc, conn,
preferred,
&ctx);
+ if (ret == -EDEADLK) {
+ ret = drm_modeset_backoff(&ctx);
+ if (!ret)
+ goto retry_conn_enable;
+ }
KUNIT_ASSERT_EQ(test, ret, 0);
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index b0bd31d14bb9..bf4ee976b680 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -1527,7 +1527,7 @@ static bool xe_ttm_bo_lock_in_destructor(struct ttm_buffer_object *ttm_bo)
* always succeed here, as long as we hold the lru lock.
*/
spin_lock(&ttm_bo->bdev->lru_lock);
- locked = dma_resv_trylock(ttm_bo->base.resv);
+ locked = dma_resv_trylock(&ttm_bo->base._resv);
spin_unlock(&ttm_bo->bdev->lru_lock);
xe_assert(xe, locked);
@@ -1547,13 +1547,6 @@ static void xe_ttm_bo_release_notify(struct ttm_buffer_object *ttm_bo)
bo = ttm_to_xe_bo(ttm_bo);
xe_assert(xe_bo_device(bo), !(bo->created && kref_read(&ttm_bo->base.refcount)));
- /*
- * Corner case where TTM fails to allocate memory and this BOs resv
- * still points the VMs resv
- */
- if (ttm_bo->base.resv != &ttm_bo->base._resv)
- return;
-
if (!xe_ttm_bo_lock_in_destructor(ttm_bo))
return;
@@ -1563,14 +1556,14 @@ static void xe_ttm_bo_release_notify(struct ttm_buffer_object *ttm_bo)
* TODO: Don't do this for external bos once we scrub them after
* unbind.
*/
- dma_resv_for_each_fence(&cursor, ttm_bo->base.resv,
+ dma_resv_for_each_fence(&cursor, &ttm_bo->base._resv,
DMA_RESV_USAGE_BOOKKEEP, fence) {
if (xe_fence_is_xe_preempt(fence) &&
!dma_fence_is_signaled(fence)) {
if (!replacement)
replacement = dma_fence_get_stub();
- dma_resv_replace_fences(ttm_bo->base.resv,
+ dma_resv_replace_fences(&ttm_bo->base._resv,
fence->context,
replacement,
DMA_RESV_USAGE_BOOKKEEP);
@@ -1578,7 +1571,7 @@ static void xe_ttm_bo_release_notify(struct ttm_buffer_object *ttm_bo)
}
dma_fence_put(replacement);
- dma_resv_unlock(ttm_bo->base.resv);
+ dma_resv_unlock(&ttm_bo->base._resv);
}
static void xe_ttm_bo_delete_mem_notify(struct ttm_buffer_object *ttm_bo)
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index c7d373c70f0f..cf29e259861f 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -1056,7 +1056,7 @@ static void tdf_request_sync(struct xe_device *xe)
* transient and need to be flushed..
*/
if (xe_mmio_wait32(&gt->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST, 0,
- 150, NULL, false))
+ 300, NULL, false))
xe_gt_err_once(gt, "TD flush timeout\n");
xe_force_wake_put(gt_to_fw(gt), fw_ref);
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
index 54e42960daad..7c74a31d4486 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.c
+++ b/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -124,7 +124,7 @@ static struct sg_table *xe_dma_buf_map(struct dma_buf_attachment *attach,
case XE_PL_TT:
sgt = drm_prime_pages_to_sg(obj->dev,
bo->ttm.ttm->pages,
- bo->ttm.ttm->num_pages);
+ obj->size >> PAGE_SHIFT);
if (IS_ERR(sgt))
return sgt;
diff --git a/drivers/gpu/drm/xe/xe_eu_stall.c b/drivers/gpu/drm/xe/xe_eu_stall.c
index 97dfb7945b7a..a5c36a317a70 100644
--- a/drivers/gpu/drm/xe/xe_eu_stall.c
+++ b/drivers/gpu/drm/xe/xe_eu_stall.c
@@ -315,7 +315,7 @@ static int xe_eu_stall_user_ext_set_property(struct xe_device *xe, u64 extension
return -EFAULT;
if (XE_IOCTL_DBG(xe, ext.property >= ARRAY_SIZE(xe_set_eu_stall_property_funcs)) ||
- XE_IOCTL_DBG(xe, ext.pad))
+ XE_IOCTL_DBG(xe, !ext.property) || XE_IOCTL_DBG(xe, ext.pad))
return -EINVAL;
idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_set_eu_stall_property_funcs));
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index 4d81210e41f5..fd9480031750 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -132,7 +132,8 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (XE_IOCTL_DBG(xe, args->extensions) ||
XE_IOCTL_DBG(xe, args->pad[0] || args->pad[1] || args->pad[2]) ||
- XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]))
+ XE_IOCTL_DBG(xe, args->reserved[0] || args->reserved[1]) ||
+ XE_IOCTL_DBG(xe, args->num_syncs > DRM_XE_MAX_SYNCS))
return -EINVAL;
q = xe_exec_queue_lookup(xef, args->exec_queue_id);
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index dbb5e7a9bc6a..cdce210e36f2 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -797,9 +797,6 @@ static int do_gt_restart(struct xe_gt *gt)
xe_gt_sriov_pf_init_hw(gt);
xe_mocs_init(gt);
- err = xe_uc_start(&gt->uc);
- if (err)
- return err;
for_each_hw_engine(hwe, gt, id)
xe_reg_sr_apply_mmio(&hwe->reg_sr, gt);
@@ -807,6 +804,10 @@ static int do_gt_restart(struct xe_gt *gt)
/* Get CCS mode in sync between sw/hw */
xe_gt_apply_ccs_mode(gt);
+ err = xe_uc_start(&gt->uc);
+ if (err)
+ return err;
+
/* Restore GT freq to expected values */
xe_gt_sanitize_freq(gt);
diff --git a/drivers/gpu/drm/xe/xe_gt_freq.c b/drivers/gpu/drm/xe/xe_gt_freq.c
index 849ea6c86e8e..ce3c7810469f 100644
--- a/drivers/gpu/drm/xe/xe_gt_freq.c
+++ b/drivers/gpu/drm/xe/xe_gt_freq.c
@@ -293,8 +293,10 @@ int xe_gt_freq_init(struct xe_gt *gt)
return -ENOMEM;
err = sysfs_create_files(gt->freq, freq_attrs);
- if (err)
+ if (err) {
+ kobject_put(gt->freq);
return err;
+ }
err = devm_add_action_or_reset(xe->drm.dev, freq_fini, gt->freq);
if (err)
diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c
index bdc9d9877ec4..3e3d1d52f630 100644
--- a/drivers/gpu/drm/xe/xe_gt_idle.c
+++ b/drivers/gpu/drm/xe/xe_gt_idle.c
@@ -5,6 +5,7 @@
#include <drm/drm_managed.h>
+#include <generated/xe_wa_oob.h>
#include "xe_force_wake.h"
#include "xe_device.h"
#include "xe_gt.h"
@@ -16,6 +17,7 @@
#include "xe_mmio.h"
#include "xe_pm.h"
#include "xe_sriov.h"
+#include "xe_wa.h"
/**
* DOC: Xe GT Idle
@@ -145,6 +147,12 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt)
xe_mmio_write32(mmio, RENDER_POWERGATE_IDLE_HYSTERESIS, 25);
}
+ if (XE_GT_WA(gt, 14020316580))
+ gtidle->powergate_enable &= ~(VDN_HCP_POWERGATE_ENABLE(0) |
+ VDN_MFXVDENC_POWERGATE_ENABLE(0) |
+ VDN_HCP_POWERGATE_ENABLE(2) |
+ VDN_MFXVDENC_POWERGATE_ENABLE(2));
+
xe_mmio_write32(mmio, POWERGATE_ENABLE, gtidle->powergate_enable);
xe_force_wake_put(gt_to_fw(gt), fw_ref);
}
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
index 4c73a077d314..033eae2d03d3 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
@@ -733,7 +733,7 @@ static void vf_start_migration_recovery(struct xe_gt *gt)
spin_lock(&gt->sriov.vf.migration.lock);
- if (!gt->sriov.vf.migration.recovery_queued ||
+ if (!gt->sriov.vf.migration.recovery_queued &&
!gt->sriov.vf.migration.recovery_teardown) {
gt->sriov.vf.migration.recovery_queued = true;
WRITE_ONCE(gt->sriov.vf.migration.recovery_inprogress, true);
diff --git a/drivers/gpu/drm/xe/xe_gt_throttle.c b/drivers/gpu/drm/xe/xe_gt_throttle.c
index 82c5fbcdfbe3..01477fc7b37b 100644
--- a/drivers/gpu/drm/xe/xe_gt_throttle.c
+++ b/drivers/gpu/drm/xe/xe_gt_throttle.c
@@ -140,7 +140,7 @@ static ssize_t reasons_show(struct kobject *kobj,
struct throttle_attribute *other_ta = kobj_attribute_to_throttle(kattr);
if (other_ta->mask != U32_MAX && reasons & other_ta->mask)
- ret += sysfs_emit_at(buff, ret, "%s ", (*pother)->name);
+ ret += sysfs_emit_at(buff, ret, "%s ", (*pother)->name + strlen("reason_"));
}
if (drm_WARN_ONCE(&xe->drm, !ret, "Unknown reason: %#x\n", reasons))
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 4ac434ad216f..a5019d1e741b 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -104,7 +104,9 @@ static void g2h_fence_cancel(struct g2h_fence *g2h_fence)
{
g2h_fence->cancel = true;
g2h_fence->fail = true;
- g2h_fence->done = true;
+
+ /* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
+ WRITE_ONCE(g2h_fence->done, true);
}
static bool g2h_fence_needs_alloc(struct g2h_fence *g2h_fence)
@@ -1203,10 +1205,13 @@ retry_same_fence:
return ret;
}
- ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ);
+ /* READ_ONCEs pairs with WRITE_ONCEs in parse_g2h_response
+ * and g2h_fence_cancel.
+ */
+ ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ);
if (!ret) {
LNL_FLUSH_WORK(&ct->g2h_worker);
- if (g2h_fence.done) {
+ if (READ_ONCE(g2h_fence.done)) {
xe_gt_warn(gt, "G2H fence %u, action %04x, done\n",
g2h_fence.seqno, action[0]);
ret = 1;
@@ -1454,7 +1459,8 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len)
g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
- g2h_fence->done = true;
+ /* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */
+ WRITE_ONCE(g2h_fence->done, true);
smp_mb();
wake_up_all(&ct->g2h_fence_wq);
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index ed7be50b2f72..f6ba2b0f074d 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -717,26 +717,46 @@ static bool vf_recovery(struct xe_guc *guc)
return xe_gt_recovery_pending(guc_to_gt(guc));
}
+static inline void relaxed_ms_sleep(unsigned int delay_ms)
+{
+ unsigned long min_us, max_us;
+
+ if (!delay_ms)
+ return;
+
+ if (delay_ms > 20) {
+ msleep(delay_ms);
+ return;
+ }
+
+ min_us = mul_u32_u32(delay_ms, 1000);
+ max_us = min_us + 500;
+
+ usleep_range(min_us, max_us);
+}
+
static int wq_wait_for_space(struct xe_exec_queue *q, u32 wqi_size)
{
struct xe_guc *guc = exec_queue_to_guc(q);
struct xe_device *xe = guc_to_xe(guc);
struct iosys_map map = xe_lrc_parallel_map(q->lrc[0]);
- unsigned int sleep_period_ms = 1;
+ unsigned int sleep_period_ms = 1, sleep_total_ms = 0;
#define AVAILABLE_SPACE \
CIRC_SPACE(q->guc->wqi_tail, q->guc->wqi_head, WQ_SIZE)
if (wqi_size > AVAILABLE_SPACE && !vf_recovery(guc)) {
try_again:
q->guc->wqi_head = parallel_read(xe, map, wq_desc.head);
- if (wqi_size > AVAILABLE_SPACE) {
- if (sleep_period_ms == 1024) {
+ if (wqi_size > AVAILABLE_SPACE && !vf_recovery(guc)) {
+ if (sleep_total_ms > 2000) {
xe_gt_reset_async(q->gt);
return -ENODEV;
}
msleep(sleep_period_ms);
- sleep_period_ms <<= 1;
+ sleep_total_ms += sleep_period_ms;
+ if (sleep_period_ms < 64)
+ sleep_period_ms <<= 1;
goto try_again;
}
}
@@ -1585,7 +1605,7 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
since_resume_ms;
if (wait_ms > 0 && q->guc->resume_time)
- msleep(wait_ms);
+ relaxed_ms_sleep(wait_ms);
set_exec_queue_suspended(q);
disable_scheduling(q, false);
@@ -2253,10 +2273,11 @@ static void guc_exec_queue_unpause_prepare(struct xe_guc *guc,
struct xe_exec_queue *q)
{
struct xe_gpu_scheduler *sched = &q->guc->sched;
- struct xe_sched_job *job = NULL;
+ struct xe_sched_job *job = NULL, *__job;
bool restore_replay = false;
- list_for_each_entry(job, &sched->base.pending_list, drm.list) {
+ list_for_each_entry(__job, &sched->base.pending_list, drm.list) {
+ job = __job;
restore_replay |= job->restore_replay;
if (restore_replay) {
xe_gt_dbg(guc_to_gt(guc), "Replay JOB - guc_id=%d, seqno=%d",
diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.c b/drivers/gpu/drm/xe/xe_heci_gsc.c
index 2b3d49dd394c..495cdd4f948d 100644
--- a/drivers/gpu/drm/xe/xe_heci_gsc.c
+++ b/drivers/gpu/drm/xe/xe_heci_gsc.c
@@ -223,7 +223,7 @@ void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
if (xe->heci_gsc.irq < 0)
return;
- ret = generic_handle_irq(xe->heci_gsc.irq);
+ ret = generic_handle_irq_safe(xe->heci_gsc.irq);
if (ret)
drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
}
@@ -243,7 +243,7 @@ void xe_heci_csc_irq_handler(struct xe_device *xe, u32 iir)
if (xe->heci_gsc.irq < 0)
return;
- ret = generic_handle_irq(xe->heci_gsc.irq);
+ ret = generic_handle_irq_safe(xe->heci_gsc.irq);
if (ret)
drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
}
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 2184af413b91..5a95b08a4723 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -2062,6 +2062,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
unsigned long sram_offset,
struct drm_pagemap_addr *sram_addr,
u64 vram_addr,
+ struct dma_fence *deps,
const enum xe_migrate_copy_dir dir)
{
struct xe_gt *gt = m->tile->primary_gt;
@@ -2150,6 +2151,14 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
xe_sched_job_add_migrate_flush(job, MI_INVALIDATE_TLB);
+ if (deps && !dma_fence_is_signaled(deps)) {
+ dma_fence_get(deps);
+ err = drm_sched_job_add_dependency(&job->drm, deps);
+ if (err)
+ dma_fence_wait(deps, false);
+ err = 0;
+ }
+
mutex_lock(&m->job_mutex);
xe_sched_job_arm(job);
fence = dma_fence_get(&job->drm.s_fence->finished);
@@ -2175,6 +2184,8 @@ err:
* @npages: Number of pages to migrate.
* @src_addr: Array of DMA information (source of migrate)
* @dst_addr: Device physical address of VRAM (destination of migrate)
+ * @deps: struct dma_fence representing the dependencies that need
+ * to be signaled before migration.
*
* Copy from an array dma addresses to a VRAM device physical address
*
@@ -2184,10 +2195,11 @@ err:
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
unsigned long npages,
struct drm_pagemap_addr *src_addr,
- u64 dst_addr)
+ u64 dst_addr,
+ struct dma_fence *deps)
{
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, src_addr, dst_addr,
- XE_MIGRATE_COPY_TO_VRAM);
+ deps, XE_MIGRATE_COPY_TO_VRAM);
}
/**
@@ -2196,6 +2208,8 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
* @npages: Number of pages to migrate.
* @src_addr: Device physical address of VRAM (source of migrate)
* @dst_addr: Array of DMA information (destination of migrate)
+ * @deps: struct dma_fence representing the dependencies that need
+ * to be signaled before migration.
*
* Copy from a VRAM device physical address to an array dma addresses
*
@@ -2205,10 +2219,11 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
unsigned long npages,
u64 src_addr,
- struct drm_pagemap_addr *dst_addr)
+ struct drm_pagemap_addr *dst_addr,
+ struct dma_fence *deps)
{
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, dst_addr, src_addr,
- XE_MIGRATE_COPY_TO_SRAM);
+ deps, XE_MIGRATE_COPY_TO_SRAM);
}
static void xe_migrate_dma_unmap(struct xe_device *xe,
@@ -2384,7 +2399,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
__fence = xe_migrate_vram(m, current_bytes,
(unsigned long)buf & ~PAGE_MASK,
&pagemap_addr[current_page],
- vram_addr, write ?
+ vram_addr, NULL, write ?
XE_MIGRATE_COPY_TO_VRAM :
XE_MIGRATE_COPY_TO_SRAM);
if (IS_ERR(__fence)) {
diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h
index 260e298e5dd7..b76441f062b4 100644
--- a/drivers/gpu/drm/xe/xe_migrate.h
+++ b/drivers/gpu/drm/xe/xe_migrate.h
@@ -116,12 +116,14 @@ int xe_migrate_init(struct xe_migrate *m);
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
unsigned long npages,
struct drm_pagemap_addr *src_addr,
- u64 dst_addr);
+ u64 dst_addr,
+ struct dma_fence *deps);
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
unsigned long npages,
u64 src_addr,
- struct drm_pagemap_addr *dst_addr);
+ struct drm_pagemap_addr *dst_addr,
+ struct dma_fence *deps);
struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
struct xe_bo *src_bo,
diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c
index 890c363282ae..f8bb28ab8124 100644
--- a/drivers/gpu/drm/xe/xe_oa.c
+++ b/drivers/gpu/drm/xe/xe_oa.c
@@ -1105,11 +1105,12 @@ static int xe_oa_enable_metric_set(struct xe_oa_stream *stream)
oag_buf_size_select(stream) |
oag_configure_mmio_trigger(stream, true));
- xe_mmio_write32(mmio, __oa_regs(stream)->oa_ctx_ctrl, stream->periodic ?
- (OAG_OAGLBCTXCTRL_COUNTER_RESUME |
+ xe_mmio_write32(mmio, __oa_regs(stream)->oa_ctx_ctrl,
+ OAG_OAGLBCTXCTRL_COUNTER_RESUME |
+ (stream->periodic ?
OAG_OAGLBCTXCTRL_TIMER_ENABLE |
REG_FIELD_PREP(OAG_OAGLBCTXCTRL_TIMER_PERIOD_MASK,
- stream->period_exponent)) : 0);
+ stream->period_exponent) : 0));
/*
* Initialize Super Queue Internal Cnt Register
@@ -1254,6 +1255,9 @@ static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value,
static int xe_oa_set_prop_num_syncs(struct xe_oa *oa, u64 value,
struct xe_oa_open_param *param)
{
+ if (XE_IOCTL_DBG(oa->xe, value > DRM_XE_MAX_SYNCS))
+ return -EINVAL;
+
param->num_syncs = value;
return 0;
}
@@ -1343,7 +1347,7 @@ static int xe_oa_user_ext_set_property(struct xe_oa *oa, enum xe_oa_user_extn_fr
ARRAY_SIZE(xe_oa_set_property_funcs_config));
if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs_open)) ||
- XE_IOCTL_DBG(oa->xe, ext.pad))
+ XE_IOCTL_DBG(oa->xe, !ext.property) || XE_IOCTL_DBG(oa->xe, ext.pad))
return -EINVAL;
idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs_open));
diff --git a/drivers/gpu/drm/xe/xe_sriov_vfio.c b/drivers/gpu/drm/xe/xe_sriov_vfio.c
index e9a7615bb5c5..3da81af97b8b 100644
--- a/drivers/gpu/drm/xe/xe_sriov_vfio.c
+++ b/drivers/gpu/drm/xe/xe_sriov_vfio.c
@@ -21,7 +21,7 @@ EXPORT_SYMBOL_FOR_MODULES(xe_sriov_vfio_get_pf, "xe-vfio-pci");
bool xe_sriov_vfio_migration_supported(struct xe_device *xe)
{
if (!IS_SRIOV_PF(xe))
- return -EPERM;
+ return false;
return xe_sriov_pf_migration_supported(xe);
}
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index 55c5a0eb82e1..f97e0af6a9b0 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -476,7 +476,8 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt,
static int xe_svm_copy(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages, const enum xe_svm_copy_dir dir)
+ unsigned long npages, const enum xe_svm_copy_dir dir,
+ struct dma_fence *pre_migrate_fence)
{
struct xe_vram_region *vr = NULL;
struct xe_gt *gt = NULL;
@@ -565,7 +566,8 @@ static int xe_svm_copy(struct page **pages,
__fence = xe_migrate_from_vram(vr->migrate,
i - pos + incr,
vram_addr,
- &pagemap_addr[pos]);
+ &pagemap_addr[pos],
+ pre_migrate_fence);
} else {
vm_dbg(&xe->drm,
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%ld",
@@ -574,13 +576,14 @@ static int xe_svm_copy(struct page **pages,
__fence = xe_migrate_to_vram(vr->migrate,
i - pos + incr,
&pagemap_addr[pos],
- vram_addr);
+ vram_addr,
+ pre_migrate_fence);
}
if (IS_ERR(__fence)) {
err = PTR_ERR(__fence);
goto err_out;
}
-
+ pre_migrate_fence = NULL;
dma_fence_put(fence);
fence = __fence;
}
@@ -603,20 +606,22 @@ static int xe_svm_copy(struct page **pages,
vram_addr, (u64)pagemap_addr[pos].addr, 1);
__fence = xe_migrate_from_vram(vr->migrate, 1,
vram_addr,
- &pagemap_addr[pos]);
+ &pagemap_addr[pos],
+ pre_migrate_fence);
} else {
vm_dbg(&xe->drm,
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%d",
(u64)pagemap_addr[pos].addr, vram_addr, 1);
__fence = xe_migrate_to_vram(vr->migrate, 1,
&pagemap_addr[pos],
- vram_addr);
+ vram_addr,
+ pre_migrate_fence);
}
if (IS_ERR(__fence)) {
err = PTR_ERR(__fence);
goto err_out;
}
-
+ pre_migrate_fence = NULL;
dma_fence_put(fence);
fence = __fence;
}
@@ -629,6 +634,8 @@ err_out:
dma_fence_wait(fence, false);
dma_fence_put(fence);
}
+ if (pre_migrate_fence)
+ dma_fence_wait(pre_migrate_fence, false);
/*
* XXX: We can't derive the GT here (or anywhere in this functions, but
@@ -645,16 +652,20 @@ err_out:
static int xe_svm_copy_to_devmem(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages)
+ unsigned long npages,
+ struct dma_fence *pre_migrate_fence)
{
- return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM);
+ return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM,
+ pre_migrate_fence);
}
static int xe_svm_copy_to_ram(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages)
+ unsigned long npages,
+ struct dma_fence *pre_migrate_fence)
{
- return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM);
+ return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM,
+ pre_migrate_fence);
}
static struct xe_bo *to_xe_bo(struct drm_pagemap_devmem *devmem_allocation)
@@ -667,6 +678,7 @@ static void xe_svm_devmem_release(struct drm_pagemap_devmem *devmem_allocation)
struct xe_bo *bo = to_xe_bo(devmem_allocation);
struct xe_device *xe = xe_bo_device(bo);
+ dma_fence_put(devmem_allocation->pre_migrate_fence);
xe_bo_put_async(bo);
xe_pm_runtime_put(xe);
}
@@ -861,6 +873,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
unsigned long timeslice_ms)
{
struct xe_vram_region *vr = container_of(dpagemap, typeof(*vr), dpagemap);
+ struct dma_fence *pre_migrate_fence = NULL;
struct xe_device *xe = vr->xe;
struct device *dev = xe->drm.dev;
struct drm_buddy_block *block;
@@ -887,8 +900,20 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
break;
}
+ /* Ensure that any clearing or async eviction will complete before migration. */
+ if (!dma_resv_test_signaled(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL)) {
+ err = dma_resv_get_singleton(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
+ &pre_migrate_fence);
+ if (err)
+ dma_resv_wait_timeout(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
+ false, MAX_SCHEDULE_TIMEOUT);
+ else if (pre_migrate_fence)
+ dma_fence_enable_sw_signaling(pre_migrate_fence);
+ }
+
drm_pagemap_devmem_init(&bo->devmem_allocation, dev, mm,
- &dpagemap_devmem_ops, dpagemap, end - start);
+ &dpagemap_devmem_ops, dpagemap, end - start,
+ pre_migrate_fence);
blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks;
list_for_each_entry(block, blocks, link)
@@ -941,7 +966,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, struct xe_vm
xe_assert(vm->xe, IS_DGFX(vm->xe));
if (xe_svm_range_in_vram(range)) {
- drm_info(&vm->xe->drm, "Range is already in VRAM\n");
+ drm_dbg(&vm->xe->drm, "Range is already in VRAM\n");
return false;
}
diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index 0955d2ac8d74..fa757dd07954 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -214,7 +214,7 @@ int xe_svm_init(struct xe_vm *vm)
{
#if IS_ENABLED(CONFIG_DRM_GPUSVM)
return drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM (simple)", &vm->xe->drm,
- NULL, NULL, 0, 0, 0, NULL, NULL, 0);
+ NULL, 0, 0, 0, NULL, NULL, 0);
#else
return 0;
#endif
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 7cac646bdf1c..79ab6c512d3e 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -1508,7 +1508,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
INIT_WORK(&vm->destroy_work, vm_destroy_work_func);
INIT_LIST_HEAD(&vm->preempt.exec_queues);
- vm->preempt.min_run_period_ms = 10; /* FIXME: Wire up to uAPI */
+ if (flags & XE_VM_FLAG_FAULT_MODE)
+ vm->preempt.min_run_period_ms = 0;
+ else
+ vm->preempt.min_run_period_ms = 5;
for_each_tile(tile, xe, id)
xe_range_fence_tree_init(&vm->rftree[id]);
@@ -3324,6 +3327,9 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm,
if (XE_IOCTL_DBG(xe, args->extensions))
return -EINVAL;
+ if (XE_IOCTL_DBG(xe, args->num_syncs > DRM_XE_MAX_SYNCS))
+ return -EINVAL;
+
if (args->num_binds > 1) {
u64 __user *bind_user =
u64_to_user_ptr(args->vector_of_binds);
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index ccd6cc090309..2168ef052499 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -263,7 +263,7 @@ struct xe_vm {
* @min_run_period_ms: The minimum run period before preempting
* an engine again
*/
- s64 min_run_period_ms;
+ unsigned int min_run_period_ms;
/** @exec_queues: list of exec queues attached to this VM */
struct list_head exec_queues;
/** @num_exec_queues: number exec queues attached to this VM */
diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
index 3764abca3d4f..e32dd2fde6f1 100644
--- a/drivers/gpu/drm/xe/xe_wa.c
+++ b/drivers/gpu/drm/xe/xe_wa.c
@@ -270,14 +270,6 @@ static const struct xe_rtp_entry_sr gt_was[] = {
XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F1C(0), MFXPIPE_CLKGATE_DIS)),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
},
- { XE_RTP_NAME("14020316580"),
- XE_RTP_RULES(MEDIA_VERSION(1301)),
- XE_RTP_ACTIONS(CLR(POWERGATE_ENABLE,
- VDN_HCP_POWERGATE_ENABLE(0) |
- VDN_MFXVDENC_POWERGATE_ENABLE(0) |
- VDN_HCP_POWERGATE_ENABLE(2) |
- VDN_MFXVDENC_POWERGATE_ENABLE(2))),
- },
{ XE_RTP_NAME("14019449301"),
XE_RTP_RULES(MEDIA_VERSION(1301), ENGINE_CLASS(VIDEO_DECODE)),
XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F08(0), CG3DDISHRS_CLKGATE_DIS)),
diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules
index fb38eb3d6e9a..7ca7258eb5d8 100644
--- a/drivers/gpu/drm/xe/xe_wa_oob.rules
+++ b/drivers/gpu/drm/xe/xe_wa_oob.rules
@@ -76,3 +76,4 @@
15015404425_disable PLATFORM(PANTHERLAKE), MEDIA_STEP(B0, FOREVER)
16026007364 MEDIA_VERSION(3000)
+14020316580 MEDIA_VERSION(1301)
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 337d2dc81b4c..c5865b0d2aaa 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -3513,6 +3513,7 @@ static const char *absolutes[ABS_CNT] = {
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth",
[ABS_VOLUME] = "Volume", [ABS_PROFILE] = "Profile",
+ [ABS_SND_PROFILE] = "SoundProfile",
[ABS_MISC] = "Misc",
[ABS_MT_SLOT] = "MTSlot",
[ABS_MT_TOUCH_MAJOR] = "MTMajor",
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index a34753fc2973..6040a8940674 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -76,6 +76,9 @@
#define DELL_SMM_NO_TEMP 10
#define DELL_SMM_NO_FANS 4
+/* limit fan multiplier to avoid overflow */
+#define DELL_SMM_MAX_FAN_MULT (INT_MAX / U16_MAX)
+
struct smm_regs {
unsigned int eax;
unsigned int ebx;
@@ -1253,6 +1256,12 @@ static int dell_smm_init_data(struct device *dev, const struct dell_smm_ops *ops
data->ops = ops;
/* All options must not be 0 */
data->i8k_fan_mult = fan_mult ? : I8K_FAN_MULT;
+ if (data->i8k_fan_mult > DELL_SMM_MAX_FAN_MULT) {
+ dev_err(dev,
+ "fan multiplier %u is too large (max %u)\n",
+ data->i8k_fan_mult, DELL_SMM_MAX_FAN_MULT);
+ return -EINVAL;
+ }
data->i8k_fan_max = fan_max ? : I8K_FAN_HIGH;
data->i8k_pwm_mult = DIV_ROUND_UP(255, data->i8k_fan_max);
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index 228c5f6c6f38..129f3a9e8fe9 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -277,6 +277,9 @@ static ssize_t ibmpex_high_low_store(struct device *dev,
{
struct ibmpex_bmc_data *data = dev_get_drvdata(dev);
+ if (!data)
+ return -ENODEV;
+
ibmpex_reset_high_low_data(data);
return count;
@@ -508,6 +511,9 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data)
{
int i, j;
+ hwmon_device_unregister(data->hwmon_dev);
+ dev_set_drvdata(data->bmc_device, NULL);
+
device_remove_file(data->bmc_device,
&sensor_dev_attr_reset_high_low.dev_attr);
device_remove_file(data->bmc_device, &dev_attr_name.attr);
@@ -521,8 +527,7 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data)
}
list_del(&data->list);
- dev_set_drvdata(data->bmc_device, NULL);
- hwmon_device_unregister(data->hwmon_dev);
+
ipmi_destroy_user(data->user);
kfree(data->sensors);
kfree(data);
diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
index b9cad89f2cd9..db6534e67991 100644
--- a/drivers/hwmon/ltc4282.c
+++ b/drivers/hwmon/ltc4282.c
@@ -1000,8 +1000,9 @@ static umode_t ltc4282_in_is_visible(const struct ltc4282_state *st, u32 attr)
case hwmon_in_max:
case hwmon_in_min:
case hwmon_in_enable:
- case hwmon_in_reset_history:
return 0644;
+ case hwmon_in_reset_history:
+ return 0200;
default:
return 0;
}
@@ -1020,8 +1021,9 @@ static umode_t ltc4282_curr_is_visible(u32 attr)
return 0444;
case hwmon_curr_max:
case hwmon_curr_min:
- case hwmon_curr_reset_history:
return 0644;
+ case hwmon_curr_reset_history:
+ return 0200;
default:
return 0;
}
@@ -1039,8 +1041,9 @@ static umode_t ltc4282_power_is_visible(u32 attr)
return 0444;
case hwmon_power_max:
case hwmon_power_min:
- case hwmon_power_reset_history:
return 0644;
+ case hwmon_power_reset_history:
+ return 0200;
default:
return 0;
}
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index fbaa34973694..07f596581c6e 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -397,7 +397,7 @@ static int tmp401_chip_read(struct device *dev, u32 attr, int channel, long *val
ret = regmap_read(data->regmap, TMP401_CONVERSION_RATE, &regval);
if (ret < 0)
return ret;
- *val = (1 << (7 - regval)) * 125;
+ *val = (1 << (7 - min(regval, 7))) * 125;
break;
case hwmon_chip_temp_reset_history:
*val = 0;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index cea87fcb4a1a..09ba55bae1fa 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -167,6 +167,7 @@ config I2C_I801
Panther Lake (SOC)
Wildcat Lake (SOC)
Diamond Rapids (SOC)
+ Nova Lake (PCH)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index e418a4f23f15..b5629cffe99b 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -1098,8 +1098,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iproc_i2c);
iproc_i2c->device = &pdev->dev;
- iproc_i2c->type =
- (enum bcm_iproc_i2c_type)of_device_get_match_data(&pdev->dev);
+ iproc_i2c->type = (kernel_ulong_t)of_device_get_match_data(&pdev->dev);
init_completion(&iproc_i2c->done);
iproc_i2c->base = devm_platform_ioremap_resource(pdev, 0);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 81e6e2d7ad3d..9e1789725edf 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -85,6 +85,7 @@
* Panther Lake-P (SOC) 0xe422 32 hard yes yes yes
* Wildcat Lake-U (SOC) 0x4d22 32 hard yes yes yes
* Diamond Rapids (SOC) 0x5827 32 hard yes yes yes
+ * Nova Lake-S (PCH) 0x6e23 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -245,6 +246,7 @@
#define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796
#define PCI_DEVICE_ID_INTEL_DIAMOND_RAPIDS_SMBUS 0x5827
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
+#define PCI_DEVICE_ID_INTEL_NOVA_LAKE_S_SMBUS 0x6e23
#define PCI_DEVICE_ID_INTEL_ARROW_LAKE_H_SMBUS 0x7722
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
@@ -1061,6 +1063,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ PCI_DEVICE_DATA(INTEL, WILDCAT_LAKE_U_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
+ { PCI_DEVICE_DATA(INTEL, NOVA_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 968a8b8794da..09af3b3625f1 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1266,7 +1266,7 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c,
i2c->use_pio = of_property_read_bool(np, "mrvl,i2c-polling");
i2c->fast_mode = of_property_read_bool(np, "mrvl,i2c-fast-mode");
- *i2c_types = (enum pxa_i2c_types)device_get_match_data(&pdev->dev);
+ *i2c_types = (kernel_ulong_t)device_get_match_data(&pdev->dev);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index d51884ab99f4..5ce8f8e4856f 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -1141,7 +1141,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
if (IS_ERR(priv->io))
return PTR_ERR(priv->io);
- priv->devtype = (enum rcar_i2c_type)of_device_get_match_data(dev);
+ priv->devtype = (kernel_ulong_t)of_device_get_match_data(dev);
init_waitqueue_head(&priv->wait);
adap = &priv->adap;
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 61596cda2b65..35ba852a172a 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -80,37 +80,25 @@ static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
.min = sizeof(struct rdma_nla_ls_gid)},
};
-static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
+static void ib_nl_process_ip_rsep(const struct nlmsghdr *nlh)
{
struct nlattr *tb[LS_NLA_TYPE_MAX] = {};
+ union ib_gid gid;
+ struct addr_req *req;
+ int found = 0;
int ret;
if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)
- return false;
+ return;
ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_addr_policy, NULL);
if (ret)
- return false;
-
- return true;
-}
-
-static void ib_nl_process_good_ip_rsep(const struct nlmsghdr *nlh)
-{
- const struct nlattr *head, *curr;
- union ib_gid gid;
- struct addr_req *req;
- int len, rem;
- int found = 0;
-
- head = (const struct nlattr *)nlmsg_data(nlh);
- len = nlmsg_len(nlh);
+ return;
- nla_for_each_attr(curr, head, len, rem) {
- if (curr->nla_type == LS_NLA_TYPE_DGID)
- memcpy(&gid, nla_data(curr), nla_len(curr));
- }
+ if (!tb[LS_NLA_TYPE_DGID])
+ return;
+ memcpy(&gid, nla_data(tb[LS_NLA_TYPE_DGID]), sizeof(gid));
spin_lock_bh(&lock);
list_for_each_entry(req, &req_list, list) {
@@ -137,8 +125,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
!(NETLINK_CB(skb).sk))
return -EPERM;
- if (ib_nl_is_good_ip_resp(nlh))
- ib_nl_process_good_ip_rsep(nlh);
+ ib_nl_process_ip_rsep(nlh);
return 0;
}
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 95e89f5c147c..f00f1d3fbd9c 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2009,6 +2009,7 @@ static void destroy_mc(struct rdma_id_private *id_priv,
ib_sa_free_multicast(mc->sa_mc);
if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
+ struct rdma_cm_event *event = &mc->iboe_join.event;
struct rdma_dev_addr *dev_addr =
&id_priv->id.route.addr.dev_addr;
struct net_device *ndev = NULL;
@@ -2031,6 +2032,8 @@ static void destroy_mc(struct rdma_id_private *id_priv,
dev_put(ndev);
cancel_work_sync(&mc->iboe_join.work);
+ if (event->event == RDMA_CM_EVENT_MULTICAST_JOIN)
+ rdma_destroy_ah_attr(&event->param.ud.ah_attr);
}
kfree(mc);
}
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 13e8a1714bbd..1174ab7da629 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -2881,8 +2881,10 @@ int ib_del_sub_device_and_put(struct ib_device *sub)
{
struct ib_device *parent = sub->parent;
- if (!parent)
+ if (!parent) {
+ ib_device_put(sub);
return -EOPNOTSUPP;
+ }
mutex_lock(&parent->subdev_lock);
list_del(&sub->subdev_list);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 11b1a194de44..ee390928511a 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -738,7 +738,7 @@ int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
(struct in6_addr *)dgid);
return 0;
} else if (net_type == RDMA_NETWORK_IPV6 ||
- net_type == RDMA_NETWORK_IB || RDMA_NETWORK_ROCE_V1) {
+ net_type == RDMA_NETWORK_IB || net_type == RDMA_NETWORK_ROCE_V1) {
*dgid = hdr->ibgrh.dgid;
*sgid = hdr->ibgrh.sgid;
return 0;
diff --git a/drivers/infiniband/hw/bnxt_re/hw_counters.h b/drivers/infiniband/hw/bnxt_re/hw_counters.h
index 09d371d442aa..cebec033f4a0 100644
--- a/drivers/infiniband/hw/bnxt_re/hw_counters.h
+++ b/drivers/infiniband/hw/bnxt_re/hw_counters.h
@@ -89,6 +89,9 @@ enum bnxt_re_hw_stats {
BNXT_RE_RES_SRQ_LOAD_ERR,
BNXT_RE_RES_TX_PCI_ERR,
BNXT_RE_RES_RX_PCI_ERR,
+ BNXT_RE_REQ_CQE_ERROR,
+ BNXT_RE_RESP_CQE_ERROR,
+ BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_OUT_OF_SEQ_ERR,
BNXT_RE_TX_ATOMIC_REQ,
BNXT_RE_TX_READ_REQ,
@@ -110,9 +113,6 @@ enum bnxt_re_hw_stats {
BNXT_RE_TX_CNP,
BNXT_RE_RX_CNP,
BNXT_RE_RX_ECN,
- BNXT_RE_REQ_CQE_ERROR,
- BNXT_RE_RESP_CQE_ERROR,
- BNXT_RE_RESP_REMOTE_ACCESS_ERRS,
BNXT_RE_NUM_EXT_COUNTERS
};
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index f19b55c13d58..ff91511bd338 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -2919,14 +2919,9 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC;
}
- switch (wr->send_flags) {
- case IB_SEND_IP_CSUM:
+ if (wr->send_flags & IB_SEND_IP_CSUM)
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM;
- break;
- default:
- break;
- }
fallthrough;
case IB_WR_SEND_WITH_INV:
rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 295a9610f3e6..4dad0cfcfa98 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -1112,7 +1112,7 @@ static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt)
creq_db->dbinfo.flags = 0;
creq_db->reg.bar_id = RCFW_COMM_CONS_PCI_BAR_REGION;
creq_db->reg.bar_base = pci_resource_start(pdev, creq_db->reg.bar_id);
- if (!creq_db->reg.bar_id)
+ if (!creq_db->reg.bar_base)
dev_err(&pdev->dev,
"QPLIB: CREQ BAR region %d resc start is 0!",
creq_db->reg.bar_id);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index 875d7b52c06a..4d674a3aee1a 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -64,9 +64,7 @@ static void __free_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,
for (i = 0; i < pbl->pg_count; i++) {
if (pbl->pg_arr[i])
dma_free_coherent(&pdev->dev, pbl->pg_size,
- (void *)((unsigned long)
- pbl->pg_arr[i] &
- PAGE_MASK),
+ pbl->pg_arr[i],
pbl->pg_map_arr[i]);
else
dev_warn(&pdev->dev,
@@ -237,7 +235,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
if (npbl % BIT(MAX_PDL_LVL_SHIFT))
npde++;
/* Alloc PDE pages */
- sginfo.pgsize = npde * pg_size;
+ sginfo.pgsize = npde * ROCE_PG_SIZE_4K;
sginfo.npages = 1;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
if (rc)
@@ -245,7 +243,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
/* Alloc PBL pages */
sginfo.npages = npbl;
- sginfo.pgsize = PAGE_SIZE;
+ sginfo.pgsize = ROCE_PG_SIZE_4K;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo);
if (rc)
goto fail;
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index 22d3e25c3b9d..755bba8d58bb 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -1320,13 +1320,9 @@ static int umem_to_page_list(struct efa_dev *dev,
u32 hp_cnt,
u8 hp_shift)
{
- u32 pages_in_hp = BIT(hp_shift - PAGE_SHIFT);
struct ib_block_iter biter;
unsigned int hp_idx = 0;
- ibdev_dbg(&dev->ibdev, "hp_cnt[%u], pages_in_hp[%u]\n",
- hp_cnt, pages_in_hp);
-
rdma_umem_for_each_dma_block(umem, &biter, BIT(hp_shift))
page_list[hp_idx++] = rdma_block_iter_dma_address(&biter);
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index cc2a12f735d3..13d7499131d4 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -251,7 +251,7 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
void *ptr)
{
struct neighbour *neigh = ptr;
- struct net_device *real_dev, *netdev = (struct net_device *)neigh->dev;
+ struct net_device *real_dev, *netdev;
struct irdma_device *iwdev;
struct ib_device *ibdev;
__be32 *p;
@@ -260,6 +260,7 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
switch (event) {
case NETEVENT_NEIGH_UPDATE:
+ netdev = neigh->dev;
real_dev = rdma_vlan_dev_real_dev(netdev);
if (!real_dev)
real_dev = netdev;
diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c
index 1becc8779123..7600412b0739 100644
--- a/drivers/infiniband/hw/mana/cq.c
+++ b/drivers/infiniband/hw/mana/cq.c
@@ -56,6 +56,10 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
doorbell = mana_ucontext->doorbell;
} else {
is_rnic_cq = true;
+ if (attr->cqe > U32_MAX / COMP_ENTRY_SIZE / 2 + 1) {
+ ibdev_dbg(ibdev, "CQE %d exceeding limit\n", attr->cqe);
+ return -EINVAL;
+ }
buf_size = MANA_PAGE_ALIGN(roundup_pow_of_two(attr->cqe * COMP_ENTRY_SIZE));
cq->cqe = buf_size / COMP_ENTRY_SIZE;
err = mana_ib_create_kernel_queue(mdev, buf_size, GDMA_CQ, &cq->queue);
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 0195d361e5e3..0bd0902b11f7 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -64,7 +64,39 @@ static inline void rxe_reclassify_recv_socket(struct socket *sock)
break;
default:
WARN_ON_ONCE(1);
+ return;
}
+ /*
+ * sock_lock_init_class_and_name() calls
+ * sk_owner_set(sk, THIS_MODULE); in order
+ * to make sure the referenced global
+ * variables rxe_recv_slock_key and
+ * rxe_recv_sk_key are not removed
+ * before the socket is closed.
+ *
+ * However this prevents rxe_net_exit()
+ * from being called and 'rmmod rdma_rxe'
+ * is refused because of the references.
+ *
+ * For the global sockets in recv_sockets,
+ * we are sure that rxe_net_exit() will call
+ * rxe_release_udp_tunnel -> udp_tunnel_sock_release.
+ *
+ * So we don't need the additional reference to
+ * our own (THIS_MODULE).
+ */
+ sk_owner_put(sk);
+ /*
+ * We also call sk_owner_clear() otherwise
+ * sk_owner_put(sk) in sk_prot_free will
+ * fail, which is called via
+ * sk_free -> __sk_free -> sk_destruct
+ * and sk_destruct calls __sk_destruct
+ * directly or via call_rcu()
+ * so sk_prot_free() might be called
+ * after rxe_net_exit().
+ */
+ sk_owner_clear(sk);
#endif /* CONFIG_DEBUG_LOCK_ALLOC */
}
diff --git a/drivers/infiniband/sw/rxe/rxe_odp.c b/drivers/infiniband/sw/rxe/rxe_odp.c
index ae71812bea82..c928cbf2e35f 100644
--- a/drivers/infiniband/sw/rxe/rxe_odp.c
+++ b/drivers/infiniband/sw/rxe/rxe_odp.c
@@ -179,8 +179,10 @@ static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, u
return err;
need_fault = rxe_check_pagefault(umem_odp, iova, length);
- if (need_fault)
+ if (need_fault) {
+ mutex_unlock(&umem_odp->umem_mutex);
return -EFAULT;
+ }
}
return 0;
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index 71387811b281..2b397a544cb9 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -1464,6 +1464,7 @@ static void query_fast_reg_mode(struct rtrs_clt_path *clt_path)
mr_page_shift = max(12, ffs(ib_dev->attrs.page_size_cap) - 1);
max_pages_per_mr = ib_dev->attrs.max_mr_size;
do_div(max_pages_per_mr, (1ull << mr_page_shift));
+ max_pages_per_mr = min_not_zero((u32)max_pages_per_mr, U32_MAX);
clt_path->max_pages_per_mr =
min3(clt_path->max_pages_per_mr, (u32)max_pages_per_mr,
ib_dev->attrs.max_fast_reg_page_list_len);
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h
index ef29bd483b5a..59529d593869 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h
@@ -150,7 +150,7 @@ enum rtrs_msg_types {
/**
* enum rtrs_msg_flags - RTRS message flags.
- * @RTRS_NEED_INVAL: Send invalidation in response.
+ * @RTRS_MSG_NEED_INVAL_F: Send invalidation in response.
* @RTRS_MSG_NEW_RKEY_F: Send refreshed rkey in response.
*/
enum rtrs_msg_flags {
@@ -179,16 +179,19 @@ struct rtrs_sg_desc {
* @recon_cnt: Reconnections counter
* @sess_uuid: UUID of a session (path)
* @paths_uuid: UUID of a group of sessions (paths)
- *
+ * @first_conn: %1 if the connection request is the first for that session,
+ * otherwise %0
* NOTE: max size 56 bytes, see man rdma_connect().
*/
struct rtrs_msg_conn_req {
- /* Is set to 0 by cma.c in case of AF_IB, do not touch that.
- * see https://www.spinics.net/lists/linux-rdma/msg22397.html
+ /**
+ * @__cma_version: Is set to 0 by cma.c in case of AF_IB, do not touch
+ * that. See https://www.spinics.net/lists/linux-rdma/msg22397.html
*/
u8 __cma_version;
- /* On sender side that should be set to 0, or cma_save_ip_info()
- * extract garbage and will fail.
+ /**
+ * @__ip_version: On sender side that should be set to 0, or
+ * cma_save_ip_info() extract garbage and will fail.
*/
u8 __ip_version;
__le16 magic;
@@ -199,6 +202,7 @@ struct rtrs_msg_conn_req {
uuid_t sess_uuid;
uuid_t paths_uuid;
u8 first_conn : 1;
+ /* private: */
u8 reserved_bits : 7;
u8 reserved[11];
};
@@ -211,6 +215,7 @@ struct rtrs_msg_conn_req {
* @queue_depth: max inflight messages (queue-depth) in this session
* @max_io_size: max io size server supports
* @max_hdr_size: max msg header size server supports
+ * @flags: RTRS message flags for this message
*
* NOTE: size is 56 bytes, max possible is 136 bytes, see man rdma_accept().
*/
@@ -222,22 +227,24 @@ struct rtrs_msg_conn_rsp {
__le32 max_io_size;
__le32 max_hdr_size;
__le32 flags;
+ /* private: */
u8 reserved[36];
};
/**
- * struct rtrs_msg_info_req
+ * struct rtrs_msg_info_req - client additional info request
* @type: @RTRS_MSG_INFO_REQ
* @pathname: Path name chosen by client
*/
struct rtrs_msg_info_req {
__le16 type;
u8 pathname[NAME_MAX];
+ /* private: */
u8 reserved[15];
};
/**
- * struct rtrs_msg_info_rsp
+ * struct rtrs_msg_info_rsp - server additional info response
* @type: @RTRS_MSG_INFO_RSP
* @sg_cnt: Number of @desc entries
* @desc: RDMA buffers where the client can write to server
@@ -245,12 +252,14 @@ struct rtrs_msg_info_req {
struct rtrs_msg_info_rsp {
__le16 type;
__le16 sg_cnt;
+ /* private: */
u8 reserved[4];
+ /* public: */
struct rtrs_sg_desc desc[];
};
/**
- * struct rtrs_msg_rkey_rsp
+ * struct rtrs_msg_rkey_rsp - server refreshed rkey response
* @type: @RTRS_MSG_RKEY_RSP
* @buf_id: RDMA buf_id of the new rkey
* @rkey: new remote key for RDMA buffers id from server
@@ -264,6 +273,7 @@ struct rtrs_msg_rkey_rsp {
/**
* struct rtrs_msg_rdma_read - RDMA data transfer request from client
* @type: always @RTRS_MSG_READ
+ * @flags: RTRS message flags (enum rtrs_msg_flags)
* @usr_len: length of user payload
* @sg_cnt: number of @desc entries
* @desc: RDMA buffers where the server can write the result to
@@ -277,7 +287,7 @@ struct rtrs_msg_rdma_read {
};
/**
- * struct_msg_rdma_write - Message transferred to server with RDMA-Write
+ * struct rtrs_msg_rdma_write - Message transferred to server with RDMA-Write
* @type: always @RTRS_MSG_WRITE
* @usr_len: length of user payload
*/
@@ -287,7 +297,7 @@ struct rtrs_msg_rdma_write {
};
/**
- * struct_msg_rdma_hdr - header for read or write request
+ * struct rtrs_msg_rdma_hdr - header for read or write request
* @type: @RTRS_MSG_WRITE | @RTRS_MSG_READ
*/
struct rtrs_msg_rdma_hdr {
diff --git a/drivers/infiniband/ulp/rtrs/rtrs.h b/drivers/infiniband/ulp/rtrs/rtrs.h
index b48b53a7c143..b5bd35712de0 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs.h
+++ b/drivers/infiniband/ulp/rtrs/rtrs.h
@@ -24,8 +24,8 @@ struct rtrs_srv_op;
/**
* enum rtrs_clt_link_ev - Events about connectivity state of a client
- * @RTRS_CLT_LINK_EV_RECONNECTED Client was reconnected.
- * @RTRS_CLT_LINK_EV_DISCONNECTED Client was disconnected.
+ * @RTRS_CLT_LINK_EV_RECONNECTED: Client was reconnected.
+ * @RTRS_CLT_LINK_EV_DISCONNECTED: Client was disconnected.
*/
enum rtrs_clt_link_ev {
RTRS_CLT_LINK_EV_RECONNECTED,
@@ -33,7 +33,9 @@ enum rtrs_clt_link_ev {
};
/**
- * Source and destination address of a path to be established
+ * struct rtrs_addr - Source and destination address of a path to be established
+ * @src: source address
+ * @dst: destination address
*/
struct rtrs_addr {
struct sockaddr_storage *src;
@@ -41,7 +43,7 @@ struct rtrs_addr {
};
/**
- * rtrs_clt_ops - it holds the link event callback and private pointer.
+ * struct rtrs_clt_ops - it holds the link event callback and private pointer.
* @priv: User supplied private data.
* @link_ev: Event notification callback function for connection state changes
* @priv: User supplied data that was passed to rtrs_clt_open()
@@ -67,10 +69,10 @@ enum wait_type {
};
/**
- * enum rtrs_clt_con_type() type of ib connection to use with a given
+ * enum rtrs_clt_con_type - type of ib connection to use with a given
* rtrs_permit
- * @ADMIN_CON - use connection reserved for "service" messages
- * @IO_CON - use a connection reserved for IO
+ * @RTRS_ADMIN_CON: use connection reserved for "service" messages
+ * @RTRS_IO_CON: use a connection reserved for IO
*/
enum rtrs_clt_con_type {
RTRS_ADMIN_CON,
@@ -85,7 +87,7 @@ void rtrs_clt_put_permit(struct rtrs_clt_sess *sess,
struct rtrs_permit *permit);
/**
- * rtrs_clt_req_ops - it holds the request confirmation callback
+ * struct rtrs_clt_req_ops - it holds the request confirmation callback
* and a private pointer.
* @priv: User supplied private data.
* @conf_fn: callback function to be called as confirmation
@@ -105,7 +107,11 @@ int rtrs_clt_request(int dir, struct rtrs_clt_req_ops *ops,
int rtrs_clt_rdma_cq_direct(struct rtrs_clt_sess *clt, unsigned int index);
/**
- * rtrs_attrs - RTRS session attributes
+ * struct rtrs_attrs - RTRS session attributes
+ * @queue_depth: queue_depth saved from rtrs_clt_sess message
+ * @max_io_size: max_io_size from rtrs_clt_sess message, capped to
+ * @max_segments * %SZ_4K
+ * @max_segments: max_segments saved from rtrs_clt_sess message
*/
struct rtrs_attrs {
u32 queue_depth;
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index d72e89c25e50..363d50949386 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -133,6 +133,8 @@ static const struct xpad_device {
} xpad_device[] = {
/* Please keep this list sorted by vendor and product ID. */
{ 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 },
+ { 0x0351, 0x1000, "CRKD LP Blueberry Burst Pro Edition (Xbox)", 0, XTYPE_XBOX360 },
+ { 0x0351, 0x2000, "CRKD LP Black Tribal Edition (Xbox) ", 0, XTYPE_XBOX360 },
{ 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 },
{ 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 },
{ 0x03f0, 0x038D, "HyperX Clutch", 0, XTYPE_XBOX360 }, /* wired */
@@ -420,6 +422,7 @@ static const struct xpad_device {
{ 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE },
{ 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 },
{ 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE },
+ { 0x3651, 0x1000, "CRKD SG", 0, XTYPE_XBOX360 },
{ 0x366c, 0x0005, "ByoWave Proteus Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE, FLAG_DELAY_INIT },
{ 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },
{ 0x37d7, 0x2501, "Flydigi Apex 5", 0, XTYPE_XBOX360 },
@@ -518,6 +521,7 @@ static const struct usb_device_id xpad_table[] = {
*/
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */
XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */
+ XPAD_XBOX360_VENDOR(0x0351), /* CRKD Controllers */
XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */
XPAD_XBOX360_VENDOR(0x03f0), /* HP HyperX Xbox 360 controllers */
XPAD_XBOXONE_VENDOR(0x03f0), /* HP HyperX Xbox One controllers */
@@ -578,6 +582,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOXONE_VENDOR(0x3285), /* Nacon Evol-X */
XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */
XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */
+ XPAD_XBOX360_VENDOR(0x3651), /* CRKD Controllers */
XPAD_XBOXONE_VENDOR(0x366c), /* ByoWave controllers */
XPAD_XBOX360_VENDOR(0x37d7), /* Flydigi Controllers */
XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 6c999d89ee4b..422e28ad1e8e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1937,6 +1937,13 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
},
.callback = atkbd_deactivate_fixup,
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "FMB-P"),
+ },
+ .callback = atkbd_deactivate_fixup,
+ },
{ }
};
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index c035216dd27c..2f130f819363 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -670,7 +670,8 @@ static int lkkbd_connect(struct serio *serio, struct serio_driver *drv)
return 0;
- fail3: serio_close(serio);
+ fail3: disable_work_sync(&lk->tq);
+ serio_close(serio);
fail2: serio_set_drvdata(serio, NULL);
fail1: input_free_device(input_dev);
kfree(lk);
@@ -684,6 +685,8 @@ static void lkkbd_disconnect(struct serio *serio)
{
struct lkkbd *lk = serio_get_drvdata(serio);
+ disable_work_sync(&lk->tq);
+
input_get_device(lk->dev);
input_unregister_device(lk->dev);
serio_close(serio);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index d0cb9fb94821..df8953a5196e 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -2975,6 +2975,7 @@ static void alps_disconnect(struct psmouse *psmouse)
psmouse_reset(psmouse);
timer_shutdown_sync(&priv->timer);
+ disable_delayed_work_sync(&priv->dev3_register_work);
if (priv->dev2)
input_unregister_device(priv->dev2);
if (!IS_ERR_OR_NULL(priv->dev3))
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 1caa6c4ca435..654771275ce8 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1169,6 +1169,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
/*
* A lot of modern Clevo barebones have touchpad and/or keyboard issues
* after suspend fixable with the forcenorestore quirk.
diff --git a/drivers/input/touchscreen/apple_z2.c b/drivers/input/touchscreen/apple_z2.c
index 0de161eae59a..271ababf0ad5 100644
--- a/drivers/input/touchscreen/apple_z2.c
+++ b/drivers/input/touchscreen/apple_z2.c
@@ -21,6 +21,7 @@
#define APPLE_Z2_TOUCH_STARTED 3
#define APPLE_Z2_TOUCH_MOVED 4
#define APPLE_Z2_CMD_READ_INTERRUPT_DATA 0xEB
+#define APPLE_Z2_REPLY_INTERRUPT_DATA 0xE1
#define APPLE_Z2_HBPP_CMD_BLOB 0x3001
#define APPLE_Z2_FW_MAGIC 0x5746325A
#define LOAD_COMMAND_INIT_PAYLOAD 0
@@ -142,6 +143,9 @@ static int apple_z2_read_packet(struct apple_z2 *z2)
if (error)
return error;
+ if (z2->rx_buf[0] != APPLE_Z2_REPLY_INTERRUPT_DATA)
+ return 0;
+
pkt_len = (get_unaligned_le16(z2->rx_buf + 1) + 8) & 0xfffffffc;
error = spi_read(z2->spidev, z2->rx_buf, pkt_len);
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index d6edfab16770..0534b2ba650b 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -85,7 +85,7 @@ static int titsc_config_wires(struct titsc *ts_dev)
wire_order[i] = ts_dev->config_inp[i] & 0x0F;
if (WARN_ON(analog_line[i] > 7))
return -EINVAL;
- if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
+ if (WARN_ON(wire_order[i] >= ARRAY_SIZE(config_pins)))
return -EINVAL;
}
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 25044d28f28a..b742ef1adb35 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -173,6 +173,11 @@ static inline struct protection_domain *to_pdomain(struct iommu_domain *dom)
bool translation_pre_enabled(struct amd_iommu *iommu);
int __init add_special_device(u8 type, u8 id, u32 *devid, bool cmd_line);
+int amd_iommu_pdom_id_alloc(void);
+int amd_iommu_pdom_id_reserve(u16 id, gfp_t gfp);
+void amd_iommu_pdom_id_free(int id);
+void amd_iommu_pdom_id_destroy(void);
+
#ifdef CONFIG_DMI
void amd_iommu_apply_ivrs_quirks(void);
#else
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 4b2953418977..384c90b4f90a 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -1136,8 +1136,11 @@ static void set_dte_bit(struct dev_table_entry *dte, u8 bit)
static bool __reuse_device_table(struct amd_iommu *iommu)
{
struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;
- u32 lo, hi, old_devtb_size;
+ struct dev_table_entry *old_dev_tbl_entry;
+ u32 lo, hi, old_devtb_size, devid;
phys_addr_t old_devtb_phys;
+ u16 dom_id;
+ bool dte_v;
u64 entry;
/* Each IOMMU use separate device table with the same size */
@@ -1173,6 +1176,22 @@ static bool __reuse_device_table(struct amd_iommu *iommu)
return false;
}
+ for (devid = 0; devid <= pci_seg->last_bdf; devid++) {
+ old_dev_tbl_entry = &pci_seg->old_dev_tbl_cpy[devid];
+ dte_v = FIELD_GET(DTE_FLAG_V, old_dev_tbl_entry->data[0]);
+ dom_id = FIELD_GET(DEV_DOMID_MASK, old_dev_tbl_entry->data[1]);
+
+ if (!dte_v || !dom_id)
+ continue;
+ /*
+ * ID reservation can fail with -ENOSPC when there
+ * are multiple devices present in the same domain,
+ * hence check only for -ENOMEM.
+ */
+ if (amd_iommu_pdom_id_reserve(dom_id, GFP_KERNEL) == -ENOMEM)
+ return false;
+ }
+
return true;
}
@@ -3127,8 +3146,7 @@ static bool __init check_ioapic_information(void)
static void __init free_dma_resources(void)
{
- ida_destroy(&pdom_ids);
-
+ amd_iommu_pdom_id_destroy();
free_unity_maps();
}
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 9f1d56a5e145..5d45795c367a 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1811,17 +1811,26 @@ int amd_iommu_complete_ppr(struct device *dev, u32 pasid, int status, int tag)
* contain.
*
****************************************************************************/
-
-static int pdom_id_alloc(void)
+int amd_iommu_pdom_id_alloc(void)
{
return ida_alloc_range(&pdom_ids, 1, MAX_DOMAIN_ID - 1, GFP_ATOMIC);
}
-static void pdom_id_free(int id)
+int amd_iommu_pdom_id_reserve(u16 id, gfp_t gfp)
+{
+ return ida_alloc_range(&pdom_ids, id, id, gfp);
+}
+
+void amd_iommu_pdom_id_free(int id)
{
ida_free(&pdom_ids, id);
}
+void amd_iommu_pdom_id_destroy(void)
+{
+ ida_destroy(&pdom_ids);
+}
+
static void free_gcr3_tbl_level1(u64 *tbl)
{
u64 *ptr;
@@ -1864,7 +1873,7 @@ static void free_gcr3_table(struct gcr3_tbl_info *gcr3_info)
gcr3_info->glx = 0;
/* Free per device domain ID */
- pdom_id_free(gcr3_info->domid);
+ amd_iommu_pdom_id_free(gcr3_info->domid);
iommu_free_pages(gcr3_info->gcr3_tbl);
gcr3_info->gcr3_tbl = NULL;
@@ -1900,14 +1909,14 @@ static int setup_gcr3_table(struct gcr3_tbl_info *gcr3_info,
return -EBUSY;
/* Allocate per device domain ID */
- domid = pdom_id_alloc();
+ domid = amd_iommu_pdom_id_alloc();
if (domid <= 0)
return -ENOSPC;
gcr3_info->domid = domid;
gcr3_info->gcr3_tbl = iommu_alloc_pages_node_sz(nid, GFP_ATOMIC, SZ_4K);
if (gcr3_info->gcr3_tbl == NULL) {
- pdom_id_free(domid);
+ amd_iommu_pdom_id_free(domid);
return -ENOMEM;
}
@@ -2503,7 +2512,7 @@ struct protection_domain *protection_domain_alloc(void)
if (!domain)
return NULL;
- domid = pdom_id_alloc();
+ domid = amd_iommu_pdom_id_alloc();
if (domid <= 0) {
kfree(domain);
return NULL;
@@ -2802,7 +2811,7 @@ void amd_iommu_domain_free(struct iommu_domain *dom)
WARN_ON(!list_empty(&domain->dev_list));
pt_iommu_deinit(&domain->iommu);
- pdom_id_free(domain->id);
+ amd_iommu_pdom_id_free(domain->id);
kfree(domain);
}
@@ -2853,7 +2862,7 @@ void amd_iommu_init_identity_domain(void)
domain->ops = &identity_domain_ops;
domain->owner = &amd_iommu_ops;
- identity_domain.id = pdom_id_alloc();
+ identity_domain.id = amd_iommu_pdom_id_alloc();
protection_domain_init(&identity_domain);
}
diff --git a/drivers/iommu/generic_pt/iommu_pt.h b/drivers/iommu/generic_pt/iommu_pt.h
index 97aeda1ad01c..3327116a441c 100644
--- a/drivers/iommu/generic_pt/iommu_pt.h
+++ b/drivers/iommu/generic_pt/iommu_pt.h
@@ -372,6 +372,9 @@ static inline struct pt_table_p *_table_alloc(struct pt_common *common,
table_mem = iommu_alloc_pages_node_sz(iommu_table->nid, gfp,
log2_to_int(lg2sz));
+ if (!table_mem)
+ return ERR_PTR(-ENOMEM);
+
if (pt_feature(common, PT_FEAT_DMA_INCOHERENT) &&
mode == ALLOC_NORMAL) {
int ret = iommu_pages_start_incoherent(
diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c
index 4f9b01dc91e8..8bcbfe3d9c72 100644
--- a/drivers/iommu/intel/irq_remapping.c
+++ b/drivers/iommu/intel/irq_remapping.c
@@ -1303,17 +1303,17 @@ static struct irq_chip intel_ir_chip = {
* irq_enter();
* handle_edge_irq()
* irq_chip_ack_parent()
- * irq_move_irq(); // No EOI
+ * intel_ack_posted_msi_irq(); // No EOI
* handle_irq_event()
* driver_handler()
* handle_edge_irq()
* irq_chip_ack_parent()
- * irq_move_irq(); // No EOI
+ * intel_ack_posted_msi_irq(); // No EOI
* handle_irq_event()
* driver_handler()
* handle_edge_irq()
* irq_chip_ack_parent()
- * irq_move_irq(); // No EOI
+ * intel_ack_posted_msi_irq(); // No EOI
* handle_irq_event()
* driver_handler()
* apic_eoi()
@@ -1322,7 +1322,7 @@ static struct irq_chip intel_ir_chip = {
*/
static struct irq_chip intel_ir_chip_post_msi = {
.name = "INTEL-IR-POST",
- .irq_ack = irq_move_irq,
+ .irq_ack = intel_ack_posted_msi_irq,
.irq_set_affinity = intel_ir_set_affinity,
.irq_compose_msi_msg = intel_ir_compose_msi_msg,
.irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity,
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index 54cf4d856179..436992331111 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -495,7 +495,11 @@ int iopt_map_file_pages(struct iommufd_ctx *ictx, struct io_pagetable *iopt,
return -EOVERFLOW;
start_byte = start - ALIGN_DOWN(start, PAGE_SIZE);
- dmabuf = dma_buf_get(fd);
+ if (IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
+ dmabuf = dma_buf_get(fd);
+ else
+ dmabuf = ERR_PTR(-ENXIO);
+
if (!IS_ERR(dmabuf)) {
pages = iopt_alloc_dmabuf_pages(ictx, dmabuf, start_byte, start,
length,
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index c4322fd26f93..550ff36dec3a 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -1184,14 +1184,20 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd,
unsigned int mockpt_id,
unsigned long start, size_t length)
{
+ unsigned long last;
struct iommufd_ioas *ioas;
int rc;
+ if (!length)
+ return -EINVAL;
+ if (check_add_overflow(start, length - 1, &last))
+ return -EOVERFLOW;
+
ioas = iommufd_get_ioas(ucmd->ictx, mockpt_id);
if (IS_ERR(ioas))
return PTR_ERR(ioas);
down_write(&ioas->iopt.iova_rwsem);
- rc = iopt_reserve_iova(&ioas->iopt, start, start + length - 1, NULL);
+ rc = iopt_reserve_iova(&ioas->iopt, start, last, NULL);
up_write(&ioas->iopt.iova_rwsem);
iommufd_put_object(ucmd->ictx, &ioas->obj);
return rc;
@@ -1215,8 +1221,10 @@ static int iommufd_test_md_check_pa(struct iommufd_ucmd *ucmd,
page_size = 1 << __ffs(mock->domain.pgsize_bitmap);
if (iova % page_size || length % page_size ||
(uintptr_t)uptr % page_size ||
- check_add_overflow((uintptr_t)uptr, (uintptr_t)length, &end))
- return -EINVAL;
+ check_add_overflow((uintptr_t)uptr, (uintptr_t)length, &end)) {
+ rc = -EINVAL;
+ goto out_put;
+ }
for (; length; length -= page_size) {
struct page *pages[1];
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e5922a682953..6d73f6e196a9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1999,7 +1999,6 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struc
mddev->layout = le32_to_cpu(sb->layout);
mddev->raid_disks = le32_to_cpu(sb->raid_disks);
mddev->dev_sectors = le64_to_cpu(sb->size);
- mddev->logical_block_size = le32_to_cpu(sb->logical_block_size);
mddev->events = ev1;
mddev->bitmap_info.offset = 0;
mddev->bitmap_info.space = 0;
@@ -2015,6 +2014,9 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struc
mddev->max_disks = (4096-256)/2;
+ if (!mddev->logical_block_size)
+ mddev->logical_block_size = le32_to_cpu(sb->logical_block_size);
+
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
mddev->bitmap_info.file == NULL) {
mddev->bitmap_info.offset =
@@ -3882,7 +3884,6 @@ out_free_rdev:
static int analyze_sbs(struct mddev *mddev)
{
- int i;
struct md_rdev *rdev, *freshest, *tmp;
freshest = NULL;
@@ -3909,11 +3910,9 @@ static int analyze_sbs(struct mddev *mddev)
super_types[mddev->major_version].
validate_super(mddev, NULL/*freshest*/, freshest);
- i = 0;
rdev_for_each_safe(rdev, tmp, mddev) {
if (mddev->max_disks &&
- (rdev->desc_nr >= mddev->max_disks ||
- i > mddev->max_disks)) {
+ rdev->desc_nr >= mddev->max_disks) {
pr_warn("md: %s: %pg: only %d devices permitted\n",
mdname(mddev), rdev->bdev,
mddev->max_disks);
@@ -4407,7 +4406,7 @@ raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
if (err < 0)
return err;
- err = mddev_lock(mddev);
+ err = mddev_suspend_and_lock(mddev);
if (err)
return err;
if (mddev->pers)
@@ -4432,7 +4431,7 @@ raid_disks_store(struct mddev *mddev, const char *buf, size_t len)
} else
mddev->raid_disks = n;
out_unlock:
- mddev_unlock(mddev);
+ mddev_unlock_and_resume(mddev);
return err ? err : len;
}
static struct md_sysfs_entry md_raid_disks =
@@ -5981,13 +5980,33 @@ lbs_store(struct mddev *mddev, const char *buf, size_t len)
if (mddev->major_version == 0)
return -EINVAL;
- if (mddev->pers)
- return -EBUSY;
-
err = kstrtouint(buf, 10, &lbs);
if (err < 0)
return -EINVAL;
+ if (mddev->pers) {
+ unsigned int curr_lbs;
+
+ if (mddev->logical_block_size)
+ return -EBUSY;
+ /*
+ * To fix forward compatibility issues, LBS is not
+ * configured for arrays from old kernels (<=6.18) by default.
+ * If the user confirms no rollback to old kernels,
+ * enable LBS by writing current LBS — to prevent data
+ * loss from LBS changes.
+ */
+ curr_lbs = queue_logical_block_size(mddev->gendisk->queue);
+ if (lbs != curr_lbs)
+ return -EINVAL;
+
+ mddev->logical_block_size = curr_lbs;
+ set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+ pr_info("%s: logical block size configured successfully, array will not be assembled in old kernels (<= 6.18)\n",
+ mdname(mddev));
+ return len;
+ }
+
err = mddev_lock(mddev);
if (err)
goto unlock;
@@ -6163,7 +6182,27 @@ int mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim,
mdname(mddev));
return -EINVAL;
}
- mddev->logical_block_size = lim->logical_block_size;
+
+ /* Only 1.x meta needs to set logical block size */
+ if (mddev->major_version == 0)
+ return 0;
+
+ /*
+ * Fix forward compatibility issue. Only set LBS by default for
+ * new arrays, mddev->events == 0 indicates the array was just
+ * created. When assembling an array, read LBS from the superblock
+ * instead — LBS is 0 in superblocks created by old kernels.
+ */
+ if (!mddev->events) {
+ pr_info("%s: array will not be assembled in old kernels that lack configurable LBS support (<= 6.18)\n",
+ mdname(mddev));
+ mddev->logical_block_size = lim->logical_block_size;
+ }
+
+ if (!mddev->logical_block_size)
+ pr_warn("%s: echo current LBS to md/logical_block_size to prevent data loss issues from LBS changes.\n"
+ "\tNote: After setting, array will not be assembled in old kernels (<= 6.18)\n",
+ mdname(mddev));
return 0;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e57ce3295292..8dc98f545969 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7187,12 +7187,14 @@ raid5_store_group_thread_cnt(struct mddev *mddev, const char *page, size_t len)
err = mddev_suspend_and_lock(mddev);
if (err)
return err;
+ conf = mddev->private;
+ if (!conf) {
+ mddev_unlock_and_resume(mddev);
+ return -ENODEV;
+ }
raid5_quiesce(mddev, true);
- conf = mddev->private;
- if (!conf)
- err = -ENODEV;
- else if (new != conf->worker_cnt_per_group) {
+ if (new != conf->worker_cnt_per_group) {
old_groups = conf->worker_groups;
if (old_groups)
flush_workqueue(raid5_wq);
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 376047beea3d..502059078b45 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -8,6 +8,7 @@
#include "lkdtm.h"
#include <linux/cpu.h>
#include <linux/list.h>
+#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/sched/task_stack.h>
@@ -100,11 +101,61 @@ static void lkdtm_PANIC_STOP_IRQOFF(void)
stop_machine(panic_stop_irqoff_fn, &v, cpu_online_mask);
}
+static bool wait_for_panic;
+
+static enum hrtimer_restart panic_in_hardirq(struct hrtimer *timer)
+{
+ panic("from hard IRQ context");
+
+ wait_for_panic = false;
+ return HRTIMER_NORESTART;
+}
+
+static void lkdtm_PANIC_IN_HARDIRQ(void)
+{
+ struct hrtimer timer;
+
+ wait_for_panic = true;
+ hrtimer_setup_on_stack(&timer, panic_in_hardirq,
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ hrtimer_start(&timer, us_to_ktime(100), HRTIMER_MODE_REL_HARD);
+
+ while (READ_ONCE(wait_for_panic))
+ cpu_relax();
+
+ hrtimer_cancel(&timer);
+}
+
static void lkdtm_BUG(void)
{
BUG();
}
+static bool wait_for_bug;
+
+static enum hrtimer_restart bug_in_hardirq(struct hrtimer *timer)
+{
+ BUG();
+
+ wait_for_bug = false;
+ return HRTIMER_NORESTART;
+}
+
+static void lkdtm_BUG_IN_HARDIRQ(void)
+{
+ struct hrtimer timer;
+
+ wait_for_bug = true;
+ hrtimer_setup_on_stack(&timer, bug_in_hardirq,
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ hrtimer_start(&timer, us_to_ktime(100), HRTIMER_MODE_REL_HARD);
+
+ while (READ_ONCE(wait_for_bug))
+ cpu_relax();
+
+ hrtimer_cancel(&timer);
+}
+
static int warn_counter;
static void lkdtm_WARNING(void)
@@ -696,7 +747,9 @@ static noinline void lkdtm_CORRUPT_PAC(void)
static struct crashtype crashtypes[] = {
CRASHTYPE(PANIC),
CRASHTYPE(PANIC_STOP_IRQOFF),
+ CRASHTYPE(PANIC_IN_HARDIRQ),
CRASHTYPE(BUG),
+ CRASHTYPE(BUG_IN_HARDIRQ),
CRASHTYPE(WARNING),
CRASHTYPE(WARNING_MESSAGE),
CRASHTYPE(EXCEPTION),
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 24f07df32a1a..6d79cc9a79e2 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -315,14 +315,14 @@ config MMC_SDHCI_ESDHC_MCF
config MMC_SDHCI_ESDHC_IMX
tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
- depends on ARCH_MXC || COMPILE_TEST
+ depends on ARCH_MXC || ARCH_S32 || COMPILE_TEST
depends on MMC_SDHCI_PLTFM
depends on OF
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
help
This selects the Freescale eSDHC/uSDHC controller support
- found on i.MX25, i.MX35 i.MX5x and i.MX6x.
+ found on i.MX25, i.MX35, i.MX5x, i.MX6x, and S32G.
If you have a controller with this interface, say Y or M here.
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index b97d042897ad..ab7f0ffe7b4f 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -99,7 +99,7 @@
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
-#define CD_STABLE_TIMEOUT_US 1000000
+#define CD_STABLE_TIMEOUT_US 2000000
#define CD_STABLE_MAX_SLEEP_US 10
/**
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index e15e320db476..cfaea6178a71 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig CAN_DEV
- tristate "CAN Device Drivers"
+ bool "CAN Device Drivers"
default y
depends on CAN
help
@@ -17,10 +17,7 @@ menuconfig CAN_DEV
virtual ones. If you own such devices or plan to use the virtual CAN
interfaces to develop applications, say Y here.
- To compile as a module, choose M here: the module will be called
- can-dev.
-
-if CAN_DEV
+if CAN_DEV && CAN
config CAN_VCAN
tristate "Virtual Local CAN Interface (vcan)"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index d7bc10a6b8ea..37e2f1a2faec 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
obj-$(CONFIG_CAN_VXCAN) += vxcan.o
obj-$(CONFIG_CAN_SLCAN) += slcan/
-obj-y += dev/
+obj-$(CONFIG_CAN_DEV) += dev/
obj-y += esd/
obj-y += rcar/
obj-y += rockchip/
diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
index 633687d6b6c0..64226acf0f3d 100644
--- a/drivers/net/can/dev/Makefile
+++ b/drivers/net/can/dev/Makefile
@@ -1,9 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_CAN_DEV) += can-dev.o
-
-can-dev-y += skb.o
+obj-$(CONFIG_CAN) += can-dev.o
+can-dev-$(CONFIG_CAN_DEV) += skb.o
can-dev-$(CONFIG_CAN_CALC_BITTIMING) += calc_bittiming.o
can-dev-$(CONFIG_CAN_NETLINK) += bittiming.o
can-dev-$(CONFIG_CAN_NETLINK) += dev.o
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index e29e85b67fd4..a0233e550a5a 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -1074,7 +1074,7 @@ out_usb_free_urb:
usb_free_urb(urb);
out_usb_kill_anchored_urbs:
if (!parent->active_channels) {
- usb_kill_anchored_urbs(&dev->tx_submitted);
+ usb_kill_anchored_urbs(&parent->rx_submitted);
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
gs_usb_timestamp_stop(parent);
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index a1a177713d99..2c4131ed7e30 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -2169,6 +2169,9 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
if (!ent->is_valid)
return 0;
+ if (is_multicast_ether_addr(ent->mac))
+ return 0;
+
if (port != ent->port)
return 0;
diff --git a/drivers/net/dsa/lantiq/lantiq_gswip.c b/drivers/net/dsa/lantiq/lantiq_gswip.c
index 57dd063c0740..b094001a7c80 100644
--- a/drivers/net/dsa/lantiq/lantiq_gswip.c
+++ b/drivers/net/dsa/lantiq/lantiq_gswip.c
@@ -444,9 +444,6 @@ static void gswip_remove(struct platform_device *pdev)
if (!priv)
return;
- /* disable the switch */
- gswip_disable_switch(priv);
-
dsa_unregister_switch(priv->ds);
for (i = 0; i < priv->num_gphy_fw; i++)
diff --git a/drivers/net/dsa/lantiq/lantiq_gswip.h b/drivers/net/dsa/lantiq/lantiq_gswip.h
index 9c38e51a75e8..2e0f2afbadbb 100644
--- a/drivers/net/dsa/lantiq/lantiq_gswip.h
+++ b/drivers/net/dsa/lantiq/lantiq_gswip.h
@@ -294,8 +294,6 @@ struct gswip_priv {
u16 version;
};
-void gswip_disable_switch(struct gswip_priv *priv);
-
int gswip_probe_common(struct gswip_priv *priv, u32 version);
#endif /* __LANTIQ_GSWIP_H */
diff --git a/drivers/net/dsa/lantiq/lantiq_gswip_common.c b/drivers/net/dsa/lantiq/lantiq_gswip_common.c
index 9da39edf8f57..e790f2ef7588 100644
--- a/drivers/net/dsa/lantiq/lantiq_gswip_common.c
+++ b/drivers/net/dsa/lantiq/lantiq_gswip_common.c
@@ -752,6 +752,13 @@ static int gswip_setup(struct dsa_switch *ds)
return 0;
}
+static void gswip_teardown(struct dsa_switch *ds)
+{
+ struct gswip_priv *priv = ds->priv;
+
+ regmap_clear_bits(priv->mdio, GSWIP_MDIO_GLOB, GSWIP_MDIO_GLOB_ENABLE);
+}
+
static enum dsa_tag_protocol gswip_get_tag_protocol(struct dsa_switch *ds,
int port,
enum dsa_tag_protocol mp)
@@ -1629,6 +1636,7 @@ static const struct phylink_mac_ops gswip_phylink_mac_ops = {
static const struct dsa_switch_ops gswip_switch_ops = {
.get_tag_protocol = gswip_get_tag_protocol,
.setup = gswip_setup,
+ .teardown = gswip_teardown,
.port_setup = gswip_port_setup,
.port_enable = gswip_port_enable,
.port_disable = gswip_port_disable,
@@ -1656,12 +1664,6 @@ static const struct dsa_switch_ops gswip_switch_ops = {
.port_hsr_leave = dsa_port_simple_hsr_leave,
};
-void gswip_disable_switch(struct gswip_priv *priv)
-{
- regmap_clear_bits(priv->mdio, GSWIP_MDIO_GLOB, GSWIP_MDIO_GLOB_ENABLE);
-}
-EXPORT_SYMBOL_GPL(gswip_disable_switch);
-
static int gswip_validate_cpu_port(struct dsa_switch *ds)
{
struct gswip_priv *priv = ds->priv;
@@ -1718,15 +1720,14 @@ int gswip_probe_common(struct gswip_priv *priv, u32 version)
err = gswip_validate_cpu_port(priv->ds);
if (err)
- goto disable_switch;
+ goto unregister_switch;
dev_info(priv->dev, "probed GSWIP version %lx mod %lx\n",
GSWIP_VERSION_REV(version), GSWIP_VERSION_MOD(version));
return 0;
-disable_switch:
- gswip_disable_switch(priv);
+unregister_switch:
dsa_unregister_switch(priv->ds);
return err;
diff --git a/drivers/net/dsa/lantiq/mxl-gsw1xx.c b/drivers/net/dsa/lantiq/mxl-gsw1xx.c
index 0816c61a47f1..f8ff8a604bf5 100644
--- a/drivers/net/dsa/lantiq/mxl-gsw1xx.c
+++ b/drivers/net/dsa/lantiq/mxl-gsw1xx.c
@@ -11,10 +11,12 @@
#include <linux/bits.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/regmap.h>
+#include <linux/workqueue.h>
#include <net/dsa.h>
#include "lantiq_gswip.h"
@@ -29,6 +31,7 @@ struct gsw1xx_priv {
struct regmap *clk;
struct regmap *shell;
struct phylink_pcs pcs;
+ struct delayed_work clear_raneg;
phy_interface_t tbi_interface;
struct gswip_priv gswip;
};
@@ -145,7 +148,9 @@ static void gsw1xx_pcs_disable(struct phylink_pcs *pcs)
{
struct gsw1xx_priv *priv = pcs_to_gsw1xx(pcs);
- /* Assert SGMII shell reset */
+ cancel_delayed_work_sync(&priv->clear_raneg);
+
+ /* Assert SGMII shell reset (will also clear RANEG bit) */
regmap_set_bits(priv->shell, GSW1XX_SHELL_RST_REQ,
GSW1XX_RST_REQ_SGMII_SHELL);
@@ -255,10 +260,16 @@ static int gsw1xx_pcs_reset(struct gsw1xx_priv *priv)
FIELD_PREP(GSW1XX_SGMII_PHY_RX0_CFG2_FILT_CNT,
GSW1XX_SGMII_PHY_RX0_CFG2_FILT_CNT_DEF);
- /* TODO: Take care of inverted RX pair once generic property is
+ /* RX lane seems to be inverted internally, so bit
+ * GSW1XX_SGMII_PHY_RX0_CFG2_INVERT needs to be set for normal
+ * (ie. non-inverted) operation.
+ *
+ * TODO: Take care of inverted RX pair once generic property is
* available
*/
+ val |= GSW1XX_SGMII_PHY_RX0_CFG2_INVERT;
+
ret = regmap_write(priv->sgmii, GSW1XX_SGMII_PHY_RX0_CFG2, val);
if (ret < 0)
return ret;
@@ -422,12 +433,29 @@ static int gsw1xx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
return 0;
}
+static void gsw1xx_pcs_clear_raneg(struct work_struct *work)
+{
+ struct gsw1xx_priv *priv =
+ container_of(work, struct gsw1xx_priv, clear_raneg.work);
+
+ regmap_clear_bits(priv->sgmii, GSW1XX_SGMII_TBI_ANEGCTL,
+ GSW1XX_SGMII_TBI_ANEGCTL_RANEG);
+}
+
static void gsw1xx_pcs_an_restart(struct phylink_pcs *pcs)
{
struct gsw1xx_priv *priv = pcs_to_gsw1xx(pcs);
+ cancel_delayed_work_sync(&priv->clear_raneg);
+
regmap_set_bits(priv->sgmii, GSW1XX_SGMII_TBI_ANEGCTL,
GSW1XX_SGMII_TBI_ANEGCTL_RANEG);
+
+ /* despite being documented as self-clearing, the RANEG bit
+ * sometimes remains set, preventing auto-negotiation from happening.
+ * MaxLinear advises to manually clear the bit after 10ms.
+ */
+ schedule_delayed_work(&priv->clear_raneg, msecs_to_jiffies(10));
}
static void gsw1xx_pcs_link_up(struct phylink_pcs *pcs,
@@ -630,6 +658,8 @@ static int gsw1xx_probe(struct mdio_device *mdiodev)
if (ret)
return ret;
+ INIT_DELAYED_WORK(&priv->clear_raneg, gsw1xx_pcs_clear_raneg);
+
ret = gswip_probe_common(&priv->gswip, version);
if (ret)
return ret;
@@ -642,25 +672,31 @@ static int gsw1xx_probe(struct mdio_device *mdiodev)
static void gsw1xx_remove(struct mdio_device *mdiodev)
{
struct gswip_priv *priv = dev_get_drvdata(&mdiodev->dev);
+ struct gsw1xx_priv *gsw1xx_priv;
if (!priv)
return;
- gswip_disable_switch(priv);
-
dsa_unregister_switch(priv->ds);
+
+ gsw1xx_priv = container_of(priv, struct gsw1xx_priv, gswip);
+ cancel_delayed_work_sync(&gsw1xx_priv->clear_raneg);
}
static void gsw1xx_shutdown(struct mdio_device *mdiodev)
{
struct gswip_priv *priv = dev_get_drvdata(&mdiodev->dev);
+ struct gsw1xx_priv *gsw1xx_priv;
if (!priv)
return;
+ dsa_switch_shutdown(priv->ds);
+
dev_set_drvdata(&mdiodev->dev, NULL);
- gswip_disable_switch(priv);
+ gsw1xx_priv = container_of(priv, struct gsw1xx_priv, gswip);
+ cancel_delayed_work_sync(&gsw1xx_priv->clear_raneg);
}
static const struct gswip_hw_info gsw12x_data = {
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 75893c90a0a1..315d97036ac1 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2924,19 +2924,26 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
port->id = id;
eth->ports[p] = port;
- err = airoha_metadata_dst_alloc(port);
- if (err)
- return err;
+ return airoha_metadata_dst_alloc(port);
+}
- err = register_netdev(dev);
- if (err)
- goto free_metadata_dst;
+static int airoha_register_gdm_devices(struct airoha_eth *eth)
+{
+ int i;
- return 0;
+ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
+ struct airoha_gdm_port *port = eth->ports[i];
+ int err;
-free_metadata_dst:
- airoha_metadata_dst_free(port);
- return err;
+ if (!port)
+ continue;
+
+ err = register_netdev(port->dev);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
static int airoha_probe(struct platform_device *pdev)
@@ -3027,6 +3034,10 @@ static int airoha_probe(struct platform_device *pdev)
}
}
+ err = airoha_register_gdm_devices(eth);
+ if (err)
+ goto error_napi_stop;
+
return 0;
error_napi_stop:
@@ -3040,10 +3051,12 @@ error_hw_cleanup:
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
- if (port && port->dev->reg_state == NETREG_REGISTERED) {
+ if (!port)
+ continue;
+
+ if (port->dev->reg_state == NETREG_REGISTERED)
unregister_netdev(port->dev);
- airoha_metadata_dst_free(port);
- }
+ airoha_metadata_dst_free(port);
}
free_netdev(eth->napi_dev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index a68757e8fd22..c63ddb12237e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -1928,6 +1928,7 @@ static void xgbe_set_rx_adap_mode(struct xgbe_prv_data *pdata,
{
if (pdata->rx_adapt_retries++ >= MAX_RX_ADAPT_RETRIES) {
pdata->rx_adapt_retries = 0;
+ pdata->mode_set = false;
return;
}
@@ -1974,6 +1975,7 @@ static void xgbe_rx_adaptation(struct xgbe_prv_data *pdata)
*/
netif_dbg(pdata, link, pdata->netdev, "Block_lock done");
pdata->rx_adapt_done = true;
+ pdata->rx_adapt_retries = 0;
pdata->mode_set = false;
return;
}
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 666522d64775..ca565ace6e6a 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -255,14 +255,14 @@ config BNXT_HWMON
devices, via the hwmon sysfs interface.
config BNGE
- tristate "Broadcom Ethernet device support"
+ tristate "Broadcom ThorUltra Ethernet device support"
depends on PCI
select NET_DEVLINK
select PAGE_POOL
help
- This driver supports Broadcom 50/100/200/400/800 gigabit Ethernet cards.
- The module will be called bng_en. To compile this driver as a module,
- choose M here.
+ This driver supports Broadcom ThorUltra 50/100/200/400/800 gigabit
+ Ethernet cards. The module will be called bng_en. To compile this
+ driver as a module, choose M here.
config BCMASP
tristate "Broadcom ASP 2.0 Ethernet support"
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 888f28f11406..90df02e0039c 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1790,6 +1790,9 @@ static int b44_nway_reset(struct net_device *dev)
u32 bmcr;
int r;
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+ return phy_ethtool_nway_reset(dev);
+
spin_lock_irq(&bp->lock);
b44_readphy(bp, MII_BMCR, &bmcr);
b44_readphy(bp, MII_BMCR, &bmcr);
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h
index 411744894349..32fc16a37d02 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge.h
+++ b/drivers/net/ethernet/broadcom/bnge/bnge.h
@@ -5,7 +5,7 @@
#define _BNGE_H_
#define DRV_NAME "bng_en"
-#define DRV_SUMMARY "Broadcom 800G Ethernet Linux Driver"
+#define DRV_SUMMARY "Broadcom ThorUltra NIC Ethernet Driver"
#include <linux/etherdevice.h>
#include <linux/bnxt/hsi.h>
diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_core.c b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
index c94e132bebc8..b4090283df0f 100644
--- a/drivers/net/ethernet/broadcom/bnge/bnge_core.c
+++ b/drivers/net/ethernet/broadcom/bnge/bnge_core.c
@@ -19,7 +19,7 @@ char bnge_driver_name[] = DRV_NAME;
static const struct {
char *name;
} board_info[] = {
- [BCM57708] = { "Broadcom BCM57708 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" },
+ [BCM57708] = { "Broadcom BCM57708 ThorUltra 50Gb/100Gb/200Gb/400Gb/800Gb Ethernet" },
};
static const struct pci_device_id bnge_pci_tbl[] = {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index 3e77a96e5a3e..c94a391b1ba5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -268,13 +268,11 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
case XDP_TX:
rx_buf = &rxr->rx_buf_ring[cons];
mapping = rx_buf->mapping - bp->rx_dma_offset;
- *event &= BNXT_TX_CMP_EVENT;
if (unlikely(xdp_buff_has_frags(xdp))) {
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
tx_needed += sinfo->nr_frags;
- *event = BNXT_AGG_EVENT;
}
if (tx_avail < tx_needed) {
@@ -287,6 +285,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
dma_sync_single_for_device(&pdev->dev, mapping + offset, *len,
bp->rx_dir);
+ *event &= ~BNXT_RX_EVENT;
*event |= BNXT_TX_EVENT;
__bnxt_xmit_xdp(bp, txr, mapping + offset, *len,
NEXT_RX(rxr->rx_prod), xdp);
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index e461f5072884..6511ecd5856b 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -708,7 +708,6 @@ static void macb_mac_link_up(struct phylink_config *config,
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
* cleared the pipeline and control registers.
*/
- bp->macbgem_ops.mog_init_rings(bp);
macb_init_buffers(bp);
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
@@ -2954,6 +2953,8 @@ static int macb_open(struct net_device *dev)
goto pm_exit;
}
+ bp->macbgem_ops.mog_init_rings(bp);
+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
napi_enable(&queue->napi_rx);
napi_enable(&queue->napi_tx);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index d5e5800b84ef..53b26cece16a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1787,7 +1787,8 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
int xdp_tx_bd_cnt, i, k;
int xdp_tx_frm_cnt = 0;
- if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags)))
+ if (unlikely(test_bit(ENETC_TX_DOWN, &priv->flags) ||
+ !netif_carrier_ok(ndev)))
return -ENETDOWN;
enetc_lock_mdio();
diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
index 443983fdecd9..7fd39f895290 100644
--- a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
+++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
@@ -577,11 +577,17 @@ static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
}
addr = netc_get_phy_addr(np);
- if (addr <= 0) {
+ if (addr < 0) {
dev_err(dev, "Failed to get PHY address\n");
return addr;
}
+ /* The default value of LaBCR[MDIO_PHYAD_PRTAD] is 0,
+ * so no need to set the register.
+ */
+ if (!addr)
+ return 0;
+
if (phy_mask & BIT(addr)) {
dev_err(dev,
"Find same PHY address in EMDIO and ENETC node\n");
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index c685a5c0cc51..a753265961af 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3933,7 +3933,12 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
txq->bd.cur = bdp;
/* Trigger transmission start */
- writel(0, txq->bd.reg_desc_active);
+ if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
+ !readl(txq->bd.reg_desc_active) ||
+ !readl(txq->bd.reg_desc_active) ||
+ !readl(txq->bd.reg_desc_active) ||
+ !readl(txq->bd.reg_desc_active))
+ writel(0, txq->bd.reg_desc_active);
return 0;
}
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index a5a2b18d309b..7eb64e1e4d85 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -558,7 +558,7 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv)
block->priv = priv;
err = request_irq(priv->msix_vectors[msix_idx].vector,
gve_is_gqi(priv) ? gve_intr : gve_intr_dqo,
- 0, block->name, block);
+ IRQF_NO_AUTOEN, block->name, block);
if (err) {
dev_err(&priv->pdev->dev,
"Failed to receive msix vector %d\n", i);
@@ -647,12 +647,9 @@ static int gve_setup_device_resources(struct gve_priv *priv)
err = gve_alloc_counter_array(priv);
if (err)
goto abort_with_rss_config_cache;
- err = gve_init_clock(priv);
- if (err)
- goto abort_with_counter;
err = gve_alloc_notify_blocks(priv);
if (err)
- goto abort_with_clock;
+ goto abort_with_counter;
err = gve_alloc_stats_report(priv);
if (err)
goto abort_with_ntfy_blocks;
@@ -683,10 +680,16 @@ static int gve_setup_device_resources(struct gve_priv *priv)
}
}
+ err = gve_init_clock(priv);
+ if (err) {
+ dev_err(&priv->pdev->dev, "Failed to init clock");
+ goto abort_with_ptype_lut;
+ }
+
err = gve_init_rss_config(priv, priv->rx_cfg.num_queues);
if (err) {
dev_err(&priv->pdev->dev, "Failed to init RSS config");
- goto abort_with_ptype_lut;
+ goto abort_with_clock;
}
err = gve_adminq_report_stats(priv, priv->stats_report_len,
@@ -698,6 +701,8 @@ static int gve_setup_device_resources(struct gve_priv *priv)
gve_set_device_resources_ok(priv);
return 0;
+abort_with_clock:
+ gve_teardown_clock(priv);
abort_with_ptype_lut:
kvfree(priv->ptype_lut_dqo);
priv->ptype_lut_dqo = NULL;
@@ -705,8 +710,6 @@ abort_with_stats_report:
gve_free_stats_report(priv);
abort_with_ntfy_blocks:
gve_free_notify_blocks(priv);
-abort_with_clock:
- gve_teardown_clock(priv);
abort_with_counter:
gve_free_counter_array(priv);
abort_with_rss_config_cache:
diff --git a/drivers/net/ethernet/google/gve/gve_utils.c b/drivers/net/ethernet/google/gve/gve_utils.c
index ace9b8698021..b53b7fcdcdaf 100644
--- a/drivers/net/ethernet/google/gve/gve_utils.c
+++ b/drivers/net/ethernet/google/gve/gve_utils.c
@@ -112,11 +112,13 @@ void gve_add_napi(struct gve_priv *priv, int ntfy_idx,
netif_napi_add_locked(priv->dev, &block->napi, gve_poll);
netif_napi_set_irq_locked(&block->napi, block->irq);
+ enable_irq(block->irq);
}
void gve_remove_napi(struct gve_priv *priv, int ntfy_idx)
{
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
+ disable_irq(block->irq);
netif_napi_del_locked(&block->napi);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index cf8abbe01840..c589baea7c77 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -10555,6 +10555,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
bool writen_to_tbl = false;
int ret = 0;
+ if (vlan_id >= VLAN_N_VID)
+ return -EINVAL;
+
/* When device is resetting or reset failed, firmware is unable to
* handle mailbox. Just record the vlan id, and remove it after
* reset finished.
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
index c7ff12a6c076..b7d4e06a55d4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
@@ -193,10 +193,10 @@ static int hclge_get_ring_chain_from_mbx(
return -EINVAL;
for (i = 0; i < ring_num; i++) {
- if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) {
+ if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) {
dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n",
req->msg.param[i].tqp_index,
- vport->nic.kinfo.rss_size - 1U);
+ vport->nic.kinfo.num_tqps - 1U);
return -EINVAL;
}
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 8fcf220a120d..70327a73dee3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -368,12 +368,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
new_tqps = kinfo->rss_size * num_tc;
kinfo->num_tqps = min(new_tqps, hdev->num_tqps);
- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps,
+ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
sizeof(struct hnae3_queue *), GFP_KERNEL);
if (!kinfo->tqp)
return -ENOMEM;
- for (i = 0; i < kinfo->num_tqps; i++) {
+ for (i = 0; i < hdev->num_tqps; i++) {
hdev->htqp[i].q.handle = &hdev->nic;
hdev->htqp[i].q.tqp_index = i;
kinfo->tqp[i] = &hdev->htqp[i].q;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 292389aceb2d..7f078ec9c14c 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -4094,7 +4094,15 @@ static bool e1000_tbi_should_accept(struct e1000_adapter *adapter,
u32 length, const u8 *data)
{
struct e1000_hw *hw = &adapter->hw;
- u8 last_byte = *(data + length - 1);
+ u8 last_byte;
+
+ /* Guard against OOB on data[length - 1] */
+ if (unlikely(!length))
+ return false;
+ /* Upper bound: length must not exceed rx_buffer_len */
+ if (unlikely(length > adapter->rx_buffer_len))
+ return false;
+ last_byte = *(data + length - 1);
if (TBI_ACCEPT(hw, status, errors, length, last_byte)) {
unsigned long irq_flags;
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index d2d03db2acec..dcb50c2e1aa2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -1422,4 +1422,15 @@ static inline struct i40e_veb *i40e_pf_get_main_veb(struct i40e_pf *pf)
return (pf->lan_veb != I40E_NO_VEB) ? pf->veb[pf->lan_veb] : NULL;
}
+static inline u32 i40e_get_max_num_descriptors(const struct i40e_pf *pf)
+{
+ const struct i40e_hw *hw = &pf->hw;
+
+ switch (hw->mac.type) {
+ case I40E_MAC_XL710:
+ return I40E_MAX_NUM_DESCRIPTORS_XL710;
+ default:
+ return I40E_MAX_NUM_DESCRIPTORS;
+ }
+}
#endif /* _I40E_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index f2c2646ea298..6a47ea0927e9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -2013,18 +2013,6 @@ static void i40e_get_drvinfo(struct net_device *netdev,
drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;
}
-static u32 i40e_get_max_num_descriptors(struct i40e_pf *pf)
-{
- struct i40e_hw *hw = &pf->hw;
-
- switch (hw->mac.type) {
- case I40E_MAC_XL710:
- return I40E_MAX_NUM_DESCRIPTORS_XL710;
- default:
- return I40E_MAX_NUM_DESCRIPTORS;
- }
-}
-
static void i40e_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d8192aa23254..0b1cc0481027 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -2234,6 +2234,7 @@ static void i40e_set_rx_mode(struct net_device *netdev)
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state);
}
+ i40e_service_event_schedule(vsi->back);
}
/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 8b30a3accd31..1fa877b52f61 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -656,7 +656,7 @@ static int i40e_config_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_id,
/* ring_len has to be multiple of 8 */
if (!IS_ALIGNED(info->ring_len, 8) ||
- info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) {
+ info->ring_len > i40e_get_max_num_descriptors(pf)) {
ret = -EINVAL;
goto error_context;
}
@@ -726,7 +726,7 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
/* ring_len has to be multiple of 32 */
if (!IS_ALIGNED(info->ring_len, 32) ||
- info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) {
+ info->ring_len > i40e_get_max_num_descriptors(pf)) {
ret = -EINVAL;
goto error_param;
}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index c2fbe443ef85..4b0fc8f354bc 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -1726,11 +1726,11 @@ static int iavf_config_rss_reg(struct iavf_adapter *adapter)
u16 i;
dw = (u32 *)adapter->rss_key;
- for (i = 0; i <= adapter->rss_key_size / 4; i++)
+ for (i = 0; i < adapter->rss_key_size / 4; i++)
wr32(hw, IAVF_VFQF_HKEY(i), dw[i]);
dw = (u32 *)adapter->rss_lut;
- for (i = 0; i <= adapter->rss_lut_size / 4; i++)
+ for (i = 0; i < adapter->rss_lut_size / 4; i++)
wr32(hw, IAVF_VFQF_HLUT(i), dw[i]);
iavf_flush(hw);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 7a7e101afeb6..7ce4eb71a433 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1271,7 +1271,7 @@ void idpf_mbx_task(struct work_struct *work)
idpf_mb_irq_enable(adapter);
else
queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task,
- msecs_to_jiffies(300));
+ usecs_to_jiffies(300));
idpf_recv_mb_msg(adapter);
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 44cd4b466c48..5bbe7d9294c1 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -1016,6 +1016,9 @@ static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
struct idpf_vc_xn_params xn_params = {
.vc_op = VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS,
.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN,
+ .send_buf.iov_len =
+ sizeof(struct virtchnl2_get_lan_memory_regions) +
+ sizeof(struct virtchnl2_mem_region),
.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC,
};
int num_regions, size;
@@ -1028,6 +1031,8 @@ static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
return -ENOMEM;
xn_params.recv_buf.iov_base = rcvd_regions;
+ rcvd_regions->num_memory_regions = cpu_to_le16(1);
+ xn_params.send_buf.iov_base = rcvd_regions;
reply_sz = idpf_vc_xn_exec(adapter, &xn_params);
if (reply_sz < 0)
return reply_sz;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index b90e23dc49de..b6449f0a9e7d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -418,6 +418,14 @@ static int otx2_set_ringparam(struct net_device *netdev,
*/
if (rx_count < pfvf->hw.rq_skid)
rx_count = pfvf->hw.rq_skid;
+
+ if (ring->rx_pending < 16) {
+ netdev_err(netdev,
+ "rx ring size %u invalid, min is 16\n",
+ ring->rx_pending);
+ return -EINVAL;
+ }
+
rx_count = Q_COUNT(Q_SIZE(rx_count, 3));
/* Due pipelining impact minimum 2000 unused SQ CQE's
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index 887adf4807d1..ea77fbd98396 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -197,6 +197,11 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
struct pci_dev *pdev = dev->pdev;
int ret = 0;
+ if (mlx5_fw_reset_in_progress(dev)) {
+ NL_SET_ERR_MSG_MOD(extack, "Can't reload during firmware reset");
+ return -EBUSY;
+ }
+
if (mlx5_dev_is_lightweight(dev)) {
if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
index 7bcf822a89f9..6b4ec457ce22 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
@@ -33,6 +33,7 @@
#include "lib/eq.h"
#include "fw_tracer.h"
#include "fw_tracer_tracepoint.h"
+#include <linux/ctype.h>
static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer)
{
@@ -358,6 +359,47 @@ static const char *VAL_PARM = "%llx";
static const char *REPLACE_64_VAL_PARM = "%x%x";
static const char *PARAM_CHAR = "%";
+static bool mlx5_is_valid_spec(const char *str)
+{
+ /* Parse format specifiers to find the actual type.
+ * Structure: %[flags][width][.precision][length]type
+ * Skip flags, width, precision & length.
+ */
+ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l')
+ str++;
+
+ /* Check if it's a valid integer/hex specifier or %%:
+ * Valid formats: %x, %d, %i, %u, etc.
+ */
+ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' &&
+ *str != 'u' && *str != 'c' && *str != '%')
+ return false;
+
+ return true;
+}
+
+static bool mlx5_tracer_validate_params(const char *str)
+{
+ const char *substr = str;
+
+ if (!str)
+ return false;
+
+ substr = strstr(substr, PARAM_CHAR);
+ while (substr) {
+ if (!mlx5_is_valid_spec(substr + 1))
+ return false;
+
+ if (*(substr + 1) == '%')
+ substr = strstr(substr + 2, PARAM_CHAR);
+ else
+ substr = strstr(substr + 1, PARAM_CHAR);
+
+ }
+
+ return true;
+}
+
static int mlx5_tracer_message_hash(u32 message_id)
{
return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1);
@@ -419,6 +461,10 @@ static int mlx5_tracer_get_num_of_params(char *str)
char *substr, *pstr = str;
int num_of_params = 0;
+ /* Validate that all parameters are valid before processing */
+ if (!mlx5_tracer_validate_params(str))
+ return -EINVAL;
+
/* replace %llx with %x%x */
substr = strstr(pstr, VAL_PARM);
while (substr) {
@@ -427,11 +473,15 @@ static int mlx5_tracer_get_num_of_params(char *str)
substr = strstr(pstr, VAL_PARM);
}
- /* count all the % characters */
+ /* count all the % characters, but skip %% (escaped percent) */
substr = strstr(str, PARAM_CHAR);
while (substr) {
- num_of_params += 1;
- str = substr + 1;
+ if (*(substr + 1) != '%') {
+ num_of_params += 1;
+ str = substr + 1;
+ } else {
+ str = substr + 2;
+ }
substr = strstr(str, PARAM_CHAR);
}
@@ -570,14 +620,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt,
{
char tmp[512];
- snprintf(tmp, sizeof(tmp), str_frmt->string,
- str_frmt->params[0],
- str_frmt->params[1],
- str_frmt->params[2],
- str_frmt->params[3],
- str_frmt->params[4],
- str_frmt->params[5],
- str_frmt->params[6]);
+ if (str_frmt->invalid_string)
+ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string);
+ else
+ snprintf(tmp, sizeof(tmp), str_frmt->string,
+ str_frmt->params[0],
+ str_frmt->params[1],
+ str_frmt->params[2],
+ str_frmt->params[3],
+ str_frmt->params[4],
+ str_frmt->params[5],
+ str_frmt->params[6]);
trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost,
str_frmt->event_id, tmp);
@@ -609,6 +662,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer,
return 0;
}
+static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer,
+ struct tracer_string_format *cur_string)
+{
+ cur_string->invalid_string = true;
+ list_add_tail(&cur_string->list, &tracer->ready_strings_list);
+}
+
static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
struct tracer_event *tracer_event)
{
@@ -619,12 +679,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
if (!cur_string)
return mlx5_tracer_handle_raw_string(tracer, tracer_event);
- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string);
- cur_string->last_param_num = 0;
cur_string->event_id = tracer_event->event_id;
cur_string->tmsn = tracer_event->string_event.tmsn;
cur_string->timestamp = tracer_event->string_event.timestamp;
cur_string->lost = tracer_event->lost_event;
+ cur_string->last_param_num = 0;
+ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string);
+ if (cur_string->num_of_params < 0) {
+ pr_debug("%s Invalid format string parameters\n",
+ __func__);
+ mlx5_tracer_handle_bad_format_string(tracer, cur_string);
+ return 0;
+ }
if (cur_string->num_of_params == 0) /* trace with no params */
list_add_tail(&cur_string->list, &tracer->ready_strings_list);
} else {
@@ -634,6 +700,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
__func__, tracer_event->string_event.tmsn);
return mlx5_tracer_handle_raw_string(tracer, tracer_event);
}
+ if (cur_string->num_of_params < 0) {
+ pr_debug("%s string parameter of invalid string, dumping\n",
+ __func__);
+ return 0;
+ }
cur_string->last_param_num += 1;
if (cur_string->last_param_num > TRACER_MAX_PARAMS) {
pr_debug("%s Number of params exceeds the max (%d)\n",
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
index 5c548bb74f07..30d0bcba8847 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
@@ -125,6 +125,7 @@ struct tracer_string_format {
struct list_head list;
u32 timestamp;
bool lost;
+ bool invalid_string;
};
enum mlx5_fw_tracer_ownership_state {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 811178d8976c..262dc032e276 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -69,7 +69,7 @@ struct page_pool;
#define MLX5E_METADATA_ETHER_TYPE (0x8CE4)
#define MLX5E_METADATA_ETHER_LEN 8
-#define MLX5E_ETH_HARD_MTU (ETH_HLEN + PSP_ENCAP_HLEN + PSP_TRL_SIZE + VLAN_HLEN + ETH_FCS_LEN)
+#define MLX5E_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
#define MLX5E_HW2SW_MTU(params, hwmtu) ((hwmtu) - ((params)->hard_mtu))
#define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu))
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
index 35d9530037a6..a8fb4bec369c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -342,9 +342,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
rt_dst_entry = &rt->dst;
break;
case AF_INET6:
- rt_dst_entry = ipv6_stub->ipv6_dst_lookup_flow(
- dev_net(netdev), NULL, &fl6, NULL);
- if (IS_ERR(rt_dst_entry))
+ if (!IS_ENABLED(CONFIG_IPV6) ||
+ ip6_dst_lookup(dev_net(netdev), NULL, &rt_dst_entry, &fl6))
goto neigh;
break;
default:
@@ -359,6 +358,9 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
neigh_ha_snapshot(addr, n, netdev);
ether_addr_copy(dst, addr);
+ if (attrs->dir == XFRM_DEV_OFFLOAD_OUT &&
+ is_zero_ether_addr(addr))
+ neigh_event_send(n, NULL);
dst_release(rt_dst_entry);
neigh_release(n);
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 6168f0814414..07fc4d2c8fad 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -6825,7 +6825,6 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
* is already unregistered before changing to NIC profile.
*/
if (priv->netdev->reg_state == NETREG_REGISTERED) {
- mlx5e_psp_unregister(priv);
unregister_netdev(priv->netdev);
_mlx5e_suspend(adev, false);
} else {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index 14884b9ea7f3..a01ee656a1e7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -939,7 +939,11 @@ void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq)
sq->dma_fifo_cc = dma_fifo_cc;
sq->cc = sqcc;
- netdev_tx_completed_queue(sq->txq, npkts, nbytes);
+ /* Do not update BQL for TXQs that got replaced by new active ones, as
+ * netdev_tx_reset_queue() is called for them in mlx5e_activate_txqsq().
+ */
+ if (sq == sq->priv->txq2sq[sq->txq_ix])
+ netdev_tx_completed_queue(sq->txq, npkts, nbytes);
}
#ifdef CONFIG_MLX5_CORE_IPOIB
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 8de6c7f6c294..ea94a727633f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -52,6 +52,7 @@
#include "devlink.h"
#include "lag/lag.h"
#include "en/tc/post_meter.h"
+#include "fw_reset.h"
/* There are two match-all miss flows, one for unicast dst mac and
* one for multicast.
@@ -3991,6 +3992,11 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
if (IS_ERR(esw))
return PTR_ERR(esw);
+ if (mlx5_fw_reset_in_progress(esw->dev)) {
+ NL_SET_ERR_MSG_MOD(extack, "Can't change eswitch mode during firmware reset");
+ return -EBUSY;
+ }
+
if (esw_mode_from_devlink(mode, &mlx5_mode))
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
index 2bceb42c98cc..ae10665c53f3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -15,6 +15,7 @@ enum {
MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS,
MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED,
MLX5_FW_RESET_FLAGS_UNLOAD_EVENT,
+ MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS,
};
struct mlx5_fw_reset {
@@ -128,6 +129,16 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty
return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL, NULL);
}
+bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev)
+{
+ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+
+ if (!fw_reset)
+ return false;
+
+ return test_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
+}
+
static int mlx5_fw_reset_get_reset_method(struct mlx5_core_dev *dev,
u8 *reset_method)
{
@@ -243,6 +254,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE));
devl_unlock(devlink);
}
+
+ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
}
static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
@@ -462,27 +475,48 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
reset_request_work);
struct mlx5_core_dev *dev = fw_reset->dev;
+ bool nack_request = false;
+ struct devlink *devlink;
int err;
err = mlx5_fw_reset_get_reset_method(dev, &fw_reset->reset_method);
- if (err)
+ if (err) {
+ nack_request = true;
mlx5_core_warn(dev, "Failed reading MFRL, err %d\n", err);
+ } else if (!mlx5_is_reset_now_capable(dev, fw_reset->reset_method) ||
+ test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST,
+ &fw_reset->reset_flags)) {
+ nack_request = true;
+ }
- if (err || test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) ||
- !mlx5_is_reset_now_capable(dev, fw_reset->reset_method)) {
+ devlink = priv_to_devlink(dev);
+ /* For external resets, try to acquire devl_lock. Skip if devlink reset is
+ * pending (lock already held)
+ */
+ if (nack_request ||
+ (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP,
+ &fw_reset->reset_flags) &&
+ !devl_trylock(devlink))) {
err = mlx5_fw_reset_set_reset_sync_nack(dev);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s",
err ? "Failed" : "Sent");
return;
}
+
if (mlx5_sync_reset_set_reset_requested(dev))
- return;
+ goto unlock;
+
+ set_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
err = mlx5_fw_reset_set_reset_sync_ack(dev);
if (err)
mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err);
else
mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n");
+
+unlock:
+ if (!test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags))
+ devl_unlock(devlink);
}
static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev, u16 dev_id)
@@ -722,6 +756,8 @@ static void mlx5_sync_reset_abort_event(struct work_struct *work)
if (mlx5_sync_reset_clear_reset_requested(dev, true))
return;
+
+ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n");
}
@@ -758,6 +794,7 @@ static void mlx5_sync_reset_timeout_work(struct work_struct *work)
if (mlx5_sync_reset_clear_reset_requested(dev, true))
return;
+ clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Timeout.\n");
}
@@ -844,7 +881,8 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev)
cancel_work_sync(&fw_reset->reset_reload_work);
cancel_work_sync(&fw_reset->reset_now_work);
cancel_work_sync(&fw_reset->reset_abort_work);
- cancel_delayed_work(&fw_reset->reset_timeout_work);
+ if (test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags))
+ mlx5_sync_reset_clear_reset_requested(dev, true);
}
static const struct devlink_param mlx5_fw_reset_devlink_params[] = {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h
index d5b28525c960..2d96b2adc1cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h
@@ -10,6 +10,7 @@ int mlx5_fw_reset_query(struct mlx5_core_dev *dev, u8 *reset_level, u8 *reset_ty
int mlx5_fw_reset_set_reset_sync(struct mlx5_core_dev *dev, u8 reset_type_sel,
struct netlink_ext_ack *extack);
int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev);
+bool mlx5_fw_reset_in_progress(struct mlx5_core_dev *dev);
int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev);
void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 1ac933cd8f02..a459a30f36ca 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -1413,6 +1413,7 @@ static int __mlx5_lag_dev_add_mdev(struct mlx5_core_dev *dev)
static void mlx5_lag_unregister_hca_devcom_comp(struct mlx5_core_dev *dev)
{
mlx5_devcom_unregister_component(dev->priv.hca_devcom_comp);
+ dev->priv.hca_devcom_comp = NULL;
}
static int mlx5_lag_register_hca_devcom_comp(struct mlx5_core_dev *dev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
index aad52d3a90e6..2d86af8f0d9b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
@@ -67,12 +67,19 @@ err_metadata:
static int enable_mpesw(struct mlx5_lag *ldev)
{
- int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_core_dev *dev0;
int err;
+ int idx;
int i;
- if (idx < 0 || ldev->mode != MLX5_LAG_MODE_NONE)
+ if (ldev->mode == MLX5_LAG_MODE_MPESW)
+ return 0;
+
+ if (ldev->mode != MLX5_LAG_MODE_NONE)
+ return -EINVAL;
+
+ idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ if (idx < 0)
return -EINVAL;
dev0 = ldev->pf[idx].dev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 1ab569ce3fcf..4209da722f9a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -2231,6 +2231,7 @@ static void shutdown(struct pci_dev *pdev)
mlx5_core_info(dev, "Shutdown was called\n");
set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
+ mlx5_drain_fw_reset(dev);
mlx5_drain_health_wq(dev);
err = mlx5_try_fast_unload(dev);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
index 5afe6b155ef0..81935f87bfcd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
rhashtable_remove_fast(&mr_table->route_ht,
&mr_orig_route->ht_node,
mlxsw_sp_mr_route_ht_params);
+ mutex_lock(&mr_table->route_list_lock);
list_del(&mr_orig_route->node);
+ mutex_unlock(&mr_table->route_list_lock);
mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index a2033837182e..2d0e89bd2fb9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -2265,6 +2265,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
if (!neigh_entry)
return NULL;
+ neigh_hold(n);
neigh_entry->key.n = n;
neigh_entry->rif = rif;
INIT_LIST_HEAD(&neigh_entry->nexthop_list);
@@ -2274,6 +2275,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
{
+ neigh_release(neigh_entry->key.n);
kfree(neigh_entry);
}
@@ -2858,6 +2860,11 @@ static int mlxsw_sp_router_schedule_work(struct net *net,
if (!net_work)
return NOTIFY_BAD;
+ /* Take a reference to ensure the neighbour won't be destructed until
+ * we drop the reference in the work item.
+ */
+ neigh_clone(n);
+
INIT_WORK(&net_work->work, cb);
net_work->mlxsw_sp = router->mlxsw_sp;
net_work->n = n;
@@ -2881,11 +2888,6 @@ static int mlxsw_sp_router_schedule_neigh_work(struct mlxsw_sp_router *router,
struct net *net;
net = neigh_parms_net(n->parms);
-
- /* Take a reference to ensure the neighbour won't be destructed until we
- * drop the reference in delayed work.
- */
- neigh_clone(n);
return mlxsw_sp_router_schedule_work(net, router, n,
mlxsw_sp_router_neigh_event_work);
}
@@ -4320,6 +4322,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_neigh_entry_insert;
+ neigh_release(old_n);
+
read_lock_bh(&n->lock);
nud_state = n->nud_state;
dead = n->dead;
@@ -4328,14 +4332,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
list_for_each_entry(nh, &neigh_entry->nexthop_list,
neigh_list_node) {
- neigh_release(old_n);
- neigh_clone(n);
__mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
}
- neigh_release(n);
-
return 0;
err_neigh_entry_insert:
@@ -4428,6 +4428,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
}
}
+ /* Release the reference taken by neigh_lookup() / neigh_create() since
+ * neigh_entry already holds one.
+ */
+ neigh_release(n);
+
/* If that is the first nexthop connected to that neigh, add to
* nexthop_neighs_list
*/
@@ -4454,11 +4459,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
- struct neighbour *n;
if (!neigh_entry)
return;
- n = neigh_entry->key.n;
__mlxsw_sp_nexthop_neigh_update(nh, true);
list_del(&nh->neigh_list_node);
@@ -4472,8 +4475,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
-
- neigh_release(n);
}
static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index efb4e412ec7e..0055c231acf6 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -481,7 +481,7 @@ static void mana_serv_reset(struct pci_dev *pdev)
/* Perform PCI rescan on device if we failed on HWC */
dev_err(&pdev->dev, "MANA service: resume failed, rescanning\n");
mana_serv_rescan(pdev);
- goto out;
+ return;
}
if (ret)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 405e91eb3141..755083852eef 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2655,9 +2655,6 @@ static void rtl_wol_enable_rx(struct rtl8169_private *tp)
static void rtl_prepare_power_down(struct rtl8169_private *tp)
{
- if (tp->dash_enabled)
- return;
-
if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
tp->mac_version == RTL_GIGA_MAC_VER_33)
rtl_ephy_write(tp, 0x19, 0xff64);
@@ -4812,7 +4809,7 @@ static void rtl8169_down(struct rtl8169_private *tp)
rtl_disable_exit_l1(tp);
rtl_prepare_power_down(tp);
- if (tp->dash_type != RTL_DASH_NONE)
+ if (tp->dash_type != RTL_DASH_NONE && !tp->saved_wolopts)
rtl8168_driver_stop(tp);
}
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 9d1a83a5fa7e..d16c178d1034 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -516,15 +516,7 @@ static inline void smc_rcv(struct net_device *dev)
* any other concurrent access and C would always interrupt B. But life
* isn't that easy in a SMP world...
*/
-#define smc_special_trylock(lock, flags) \
-({ \
- int __ret; \
- local_irq_save(flags); \
- __ret = spin_trylock(lock); \
- if (!__ret) \
- local_irq_restore(flags); \
- __ret; \
-})
+#define smc_special_trylock(lock, flags) spin_trylock_irqsave(lock, flags)
#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags)
#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags)
#else
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index da206b24aaed..b3730312aeed 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -89,6 +89,7 @@ MODULE_PARM_DESC(phyaddr, "Physical device address");
#define STMMAC_XDP_CONSUMED BIT(0)
#define STMMAC_XDP_TX BIT(1)
#define STMMAC_XDP_REDIRECT BIT(2)
+#define STMMAC_XSK_CONSUMED BIT(3)
static int flow_ctrl = 0xdead;
module_param(flow_ctrl, int, 0644);
@@ -5126,6 +5127,7 @@ static int stmmac_xdp_get_tx_queue(struct stmmac_priv *priv,
static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
struct xdp_buff *xdp)
{
+ bool zc = !!(xdp->rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL);
struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
int cpu = smp_processor_id();
struct netdev_queue *nq;
@@ -5142,9 +5144,18 @@ static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
/* Avoids TX time-out as we are sharing with slow path */
txq_trans_cond_update(nq);
- res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, false);
- if (res == STMMAC_XDP_TX)
+ /* For zero copy XDP_TX action, dma_map is true */
+ res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, zc);
+ if (res == STMMAC_XDP_TX) {
stmmac_flush_tx_descriptors(priv, queue);
+ } else if (res == STMMAC_XDP_CONSUMED && zc) {
+ /* xdp has been freed by xdp_convert_buff_to_frame(),
+ * no need to call xsk_buff_free() again, so return
+ * STMMAC_XSK_CONSUMED.
+ */
+ res = STMMAC_XSK_CONSUMED;
+ xdp_return_frame(xdpf);
+ }
__netif_tx_unlock(nq);
@@ -5494,6 +5505,8 @@ read_again:
break;
case STMMAC_XDP_CONSUMED:
xsk_buff_free(buf->xdp);
+ fallthrough;
+ case STMMAC_XSK_CONSUMED:
rx_dropped++;
break;
case STMMAC_XDP_TX:
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index a54d71155263..fe5b2926d8ab 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -209,6 +209,7 @@ config TI_ICSSG_PRUETH_SR1
depends on PRU_REMOTEPROC
depends on NET_SWITCHDEV
depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
+ depends on PTP_1588_CLOCK_OPTIONAL
help
Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem.
This subsystem is available on the AM65 SR1.0 platform.
@@ -234,7 +235,7 @@ config TI_PRUETH
depends on PRU_REMOTEPROC
depends on NET_SWITCHDEV
select TI_ICSS_IEP
- imply PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK_OPTIONAL
help
Some TI SoCs has Programmable Realtime Unit (PRU) cores which can
support Single or Dual Ethernet ports with the help of firmware code
diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig
index d138dea7d208..ec278f99d295 100644
--- a/drivers/net/ethernet/wangxun/Kconfig
+++ b/drivers/net/ethernet/wangxun/Kconfig
@@ -21,6 +21,7 @@ config LIBWX
depends on PTP_1588_CLOCK_OPTIONAL
select PAGE_POOL
select DIMLIB
+ select PHYLINK
help
Common library for Wangxun(R) Ethernet drivers.
@@ -29,7 +30,6 @@ config NGBE
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
select LIBWX
- select PHYLINK
help
This driver supports Wangxun(R) GbE PCI Express family of
adapters.
@@ -48,7 +48,6 @@ config TXGBE
depends on PTP_1588_CLOCK_OPTIONAL
select MARVELL_10G_PHY
select REGMAP
- select PHYLINK
select HWMON if TXGBE=y
select SFP
select GPIOLIB
@@ -71,7 +70,6 @@ config TXGBEVF
depends on PCI_MSI
depends on PTP_1588_CLOCK_OPTIONAL
select LIBWX
- select PHYLINK
help
This driver supports virtual functions for SP1000A, WX1820AL,
WX5XXX, WX5XXXAL.
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index b9b5554ea862..5ad2673f213d 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -334,7 +334,7 @@ int fjes_hw_init(struct fjes_hw *hw)
ret = fjes_hw_reset(hw);
if (ret)
- return ret;
+ goto err_iounmap;
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
@@ -347,8 +347,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->max_epid = fjes_hw_get_max_epid(hw);
hw->my_epid = fjes_hw_get_my_epid(hw);
- if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid))
- return -ENXIO;
+ if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid)) {
+ ret = -ENXIO;
+ goto err_iounmap;
+ }
ret = fjes_hw_setup(hw);
@@ -356,6 +358,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
return ret;
+
+err_iounmap:
+ fjes_hw_iounmap(hw);
+ return ret;
}
void fjes_hw_exit(struct fjes_hw *hw)
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index dea411e132db..2efa3ba148aa 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -737,6 +737,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
struct ethhdr *eth = eth_hdr(skb);
rx_handler_result_t ret = RX_HANDLER_PASS;
+ if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+ return RX_HANDLER_PASS;
+
if (is_multicast_ether_addr(eth->h_dest)) {
if (ipvlan_external_frame(skb, port)) {
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c
index e55be6dc9ae7..d6b9004c61dc 100644
--- a/drivers/net/mdio/mdio-aspeed.c
+++ b/drivers/net/mdio/mdio-aspeed.c
@@ -63,6 +63,13 @@ static int aspeed_mdio_op(struct mii_bus *bus, u8 st, u8 op, u8 phyad, u8 regad,
iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL);
+ /* Workaround for read-after-write issue.
+ * The controller may return stale data if a read follows immediately
+ * after a write. A dummy read forces the hardware to update its
+ * internal state, ensuring that the next real read returns correct data.
+ */
+ ioread32(ctx->base + ASPEED_MDIO_CTRL);
+
return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
!(ctrl & ASPEED_MDIO_CTRL_FIRE),
ASPEED_MDIO_INTERVAL_US,
diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 33694c3ff9a7..405a07075dd1 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -354,7 +354,6 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri
struct fwnode_handle *node)
{
struct rtl9300_mdio_chan *chan;
- struct fwnode_handle *child;
struct mii_bus *bus;
u32 mdio_bus;
int err;
@@ -371,7 +370,7 @@ static int rtl9300_mdiobus_probe_one(struct device *dev, struct rtl9300_mdio_pri
* compatible = "ethernet-phy-ieee802.3-c45". This does mean we can't
* support both c45 and c22 on the same MDIO bus.
*/
- fwnode_for_each_child_node(node, child)
+ fwnode_for_each_child_node_scoped(node, child)
if (fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"))
priv->smi_bus_is_c45[mdio_bus] = true;
@@ -409,7 +408,6 @@ static int rtl9300_mdiobus_map_ports(struct device *dev)
{
struct rtl9300_mdio_priv *priv = dev_get_drvdata(dev);
struct device *parent = dev->parent;
- struct fwnode_handle *port;
int err;
struct fwnode_handle *ports __free(fwnode_handle) =
@@ -418,7 +416,7 @@ static int rtl9300_mdiobus_map_ports(struct device *dev)
return dev_err_probe(dev, -EINVAL, "%pfwP missing ethernet-ports\n",
dev_fwnode(parent));
- fwnode_for_each_child_node(ports, port) {
+ fwnode_for_each_child_node_scoped(ports, port) {
struct device_node *mdio_dn;
u32 addr;
u32 bus;
diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
index f3d83b04c953..201dee1a1698 100644
--- a/drivers/net/phy/marvell-88q2xxx.c
+++ b/drivers/net/phy/marvell-88q2xxx.c
@@ -698,7 +698,7 @@ static int mv88q2xxx_hwmon_write(struct device *dev,
switch (attr) {
case hwmon_temp_max:
- clamp_val(val, -75000, 180000);
+ val = clamp(val, -75000, 180000);
val = (val / 1000) + 75;
val = FIELD_PREP(MDIO_MMD_PCS_MV_TEMP_SENSOR3_INT_THRESH_MASK,
val);
diff --git a/drivers/net/phy/mediatek/mtk-ge-soc.c b/drivers/net/phy/mediatek/mtk-ge-soc.c
index cd09fbf92ef2..2c4bbc236202 100644
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
@@ -1167,9 +1167,9 @@ static int mt798x_phy_calibration(struct phy_device *phydev)
}
buf = (u32 *)nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
if (IS_ERR(buf))
return PTR_ERR(buf);
- nvmem_cell_put(cell);
if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
phydev_err(phydev, "invalid efuse data\n");
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index 67ecf3d4af2b..6ff0385201a5 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -691,10 +691,6 @@ static int rtl8211f_config_aldps(struct phy_device *phydev)
static int rtl8211f_config_phy_eee(struct phy_device *phydev)
{
- /* RTL8211FVD has no PHYCR2 register */
- if (phydev->drv->phy_id == RTL_8211FVD_PHYID)
- return 0;
-
/* Disable PHY-mode EEE so LPI is passed to the MAC */
return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2,
RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 0401fa6b24d2..6166e9196364 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -497,6 +497,8 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
sfp_fixup_nokia),
+ SFP_QUIRK_F("BIDB", "X-ONU-SFPP", sfp_fixup_potron),
+
// FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY.
SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball),
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index 4d5c9ae8f221..c08a5c1bd6e4 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -878,7 +878,7 @@ static void __team_queue_override_enabled_check(struct team *team)
static void team_queue_override_port_prio_changed(struct team *team,
struct team_port *port)
{
- if (!port->queue_id || team_port_enabled(port))
+ if (!port->queue_id || !team_port_enabled(port))
return;
__team_queue_override_port_del(team, port);
__team_queue_override_port_add(team, port);
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 7fd763917ae2..6ab3486072cb 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -335,6 +335,11 @@ int asix_read_phy_addr(struct usbnet *dev, bool internal)
offset = (internal ? 1 : 0);
ret = buf[offset];
+ if (ret >= PHY_MAX_ADDR) {
+ netdev_err(dev->net, "invalid PHY address: %d\n", ret);
+ return -ENODEV;
+ }
+
netdev_dbg(dev->net, "%s PHY address 0x%x\n",
internal ? "internal" : "external", ret);
diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
index f613e4bc68c8..758a423a459b 100644
--- a/drivers/net/usb/ax88172a.c
+++ b/drivers/net/usb/ax88172a.c
@@ -210,11 +210,7 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
ret = asix_read_phy_addr(dev, priv->use_embdphy);
if (ret < 0)
goto free;
- if (ret >= PHY_MAX_ADDR) {
- netdev_err(dev->net, "Invalid PHY address %#x\n", ret);
- ret = -ENODEV;
- goto free;
- }
+
priv->phy_addr = ret;
ax88172a_reset_phy(dev, priv->use_embdphy);
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 278e6cb6f4d9..e40b0669d9f4 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -211,6 +211,8 @@ static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)
if (res == -ENODEV)
netif_device_detach(dev->netdev);
dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res);
+ kfree(req);
+ usb_free_urb(async_urb);
}
return res;
}
diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
index 091bc2aca7e8..820c4c506979 100644
--- a/drivers/net/usb/sr9700.c
+++ b/drivers/net/usb/sr9700.c
@@ -52,7 +52,7 @@ static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
{
- return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ return usbnet_write_cmd(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0);
}
@@ -65,7 +65,7 @@ static void sr_write_async(struct usbnet *dev, u8 reg, u16 length,
static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
{
- usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ usbnet_write_cmd_async(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0);
}
@@ -539,6 +539,11 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0fe6, 0x9700), /* SR9700 device */
.driver_info = (unsigned long)&sr9700_driver_info,
},
+ {
+ /* SR9700 with virtual driver CD-ROM - interface 0 is the CD-ROM device */
+ USB_DEVICE_INTERFACE_NUMBER(0x0fe6, 0x9702, 1),
+ .driver_info = (unsigned long)&sr9700_driver_info,
+ },
{}, /* END */
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 1d9faa70ba3b..36742e64cff7 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -831,7 +831,6 @@ int usbnet_stop(struct net_device *net)
clear_bit(EVENT_DEV_OPEN, &dev->flags);
netif_stop_queue(net);
- netdev_reset_queue(net);
netif_info(dev, ifdown, dev->net,
"stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
@@ -875,6 +874,8 @@ int usbnet_stop(struct net_device *net)
timer_delete_sync(&dev->delay);
cancel_work_sync(&dev->kevent);
+ netdev_reset_queue(net);
+
if (!pm)
usb_autopm_put_interface(dev->intf);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 3391f07b01de..f8fc6f30fbe5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -1597,7 +1597,7 @@ static void _iwl_op_mode_stop(struct iwl_drv *drv)
*/
static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
{
- unsigned int min_core, max_core, loaded_core;
+ int min_core, max_core, loaded_core;
struct iwl_drv *drv = context;
struct iwl_fw *fw = &drv->fw;
const struct iwl_ucode_header *ucode;
@@ -1676,7 +1676,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
if (loaded_core < min_core || loaded_core > max_core) {
IWL_ERR(drv,
"Driver unable to support your firmware API. "
- "Driver supports FW core %u..%u, firmware is %u.\n",
+ "Driver supports FW core %d..%d, firmware is %d.\n",
min_core, max_core, loaded_core);
goto try_again;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
index ffeb37a7f830..231920425c06 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c
@@ -121,6 +121,12 @@ static int iwl_mld_ptp_gettime(struct ptp_clock_info *ptp,
return 0;
}
+static int iwl_mld_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ return -EOPNOTSUPP;
+}
+
static int iwl_mld_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct iwl_mld *mld = container_of(ptp, struct iwl_mld,
@@ -279,6 +285,7 @@ void iwl_mld_ptp_init(struct iwl_mld *mld)
mld->ptp_data.ptp_clock_info.owner = THIS_MODULE;
mld->ptp_data.ptp_clock_info.gettime64 = iwl_mld_ptp_gettime;
+ mld->ptp_data.ptp_clock_info.settime64 = iwl_mld_ptp_settime;
mld->ptp_data.ptp_clock_info.max_adj = 0x7fffffff;
mld->ptp_data.ptp_clock_info.adjtime = iwl_mld_ptp_adjtime;
mld->ptp_data.ptp_clock_info.adjfine = iwl_mld_ptp_adjfine;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
index 06a4c9f74797..ad156b82eaa9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ptp.c
@@ -220,6 +220,12 @@ static int iwl_mvm_ptp_gettime(struct ptp_clock_info *ptp,
return 0;
}
+static int iwl_mvm_ptp_settime(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ return -EOPNOTSUPP;
+}
+
static int iwl_mvm_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct iwl_mvm *mvm = container_of(ptp, struct iwl_mvm,
@@ -281,6 +287,7 @@ void iwl_mvm_ptp_init(struct iwl_mvm *mvm)
mvm->ptp_data.ptp_clock_info.adjfine = iwl_mvm_ptp_adjfine;
mvm->ptp_data.ptp_clock_info.adjtime = iwl_mvm_ptp_adjtime;
mvm->ptp_data.ptp_clock_info.gettime64 = iwl_mvm_ptp_gettime;
+ mvm->ptp_data.ptp_clock_info.settime64 = iwl_mvm_ptp_settime;
mvm->ptp_data.scaled_freq = SCALE_FACTOR;
/* Give a short 'friendly name' to identify the PHC clock */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index ea99167765b0..0457712286d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -3019,7 +3019,7 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
}
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
- dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
+ dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s",
hdr->fw_ver, hdr->build_date);
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false);
@@ -3048,7 +3048,7 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
}
hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
- dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
+ dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s",
hdr->fw_ver, hdr->build_date);
ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true);
@@ -3101,7 +3101,6 @@ int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
const struct mt76_connac2_patch_hdr *hdr;
const struct firmware *fw = NULL;
- char build_date[17];
sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);
switch (sem) {
@@ -3125,11 +3124,8 @@ int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
}
hdr = (const void *)fw->data;
- strscpy(build_date, hdr->build_date, sizeof(build_date));
- build_date[16] = '\0';
- strim(build_date);
- dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
- be32_to_cpu(hdr->hw_sw_ver), build_date);
+ dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s",
+ be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
struct mt76_connac2_patch_sec *sec;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index aa702ba7c9f5..d6c35e8d02a5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -511,7 +511,8 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
if (sta) {
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
tid = ieee80211_get_tid(hdr);
- agg_state = sta_entry->tids[tid].agg.agg_state;
+ if (tid < MAX_TID_COUNT)
+ agg_state = sta_entry->tids[tid].agg.agg_state;
ampdu_density = sta->deflink.ht_cap.ampdu_density;
}
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 99d7c629eac6..e35de52d8eb4 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -144,8 +144,10 @@ static u32 rtw_sdio_to_io_address(struct rtw_dev *rtwdev, u32 addr,
static bool rtw_sdio_use_direct_io(struct rtw_dev *rtwdev, u32 addr)
{
+ bool might_indirect_under_power_off = rtwdev->chip->id == RTW_CHIP_TYPE_8822C;
+
if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags) &&
- !rtw_sdio_is_bus_addr(addr))
+ !rtw_sdio_is_bus_addr(addr) && might_indirect_under_power_off)
return false;
return !rtw_sdio_is_sdio30_supported(rtwdev) ||
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 009202c627d2..3b5126ffc81a 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -965,8 +965,7 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
struct sk_buff *rx_skb;
int i;
- rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH | WQ_UNBOUND,
- 0);
+ rtwusb->rxwq = alloc_workqueue("rtw88_usb: rx wq", WQ_BH, 0);
if (!rtwusb->rxwq) {
rtw_err(rtwdev, "failed to create RX work queue\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index f76087be2f75..6241866d39df 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -207,6 +207,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
if (total_blocks <= wl->tx_blocks_available) {
+ if (skb_headroom(skb) < (total_len - skb->len) &&
+ pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) {
+ wl1271_free_tx_id(wl, id);
+ return -EAGAIN;
+ }
desc = skb_push(skb, total_len - skb->len);
wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks,
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
index ffd7367ce119..018a80674f06 100644
--- a/drivers/nfc/pn533/usb.c
+++ b/drivers/nfc/pn533/usb.c
@@ -406,7 +406,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
if (rc || (transferred != sizeof(cmd))) {
nfc_err(&phy->udev->dev,
"Reader power on cmd error %d\n", rc);
- return rc;
+ return rc ?: -EINVAL;
}
rc = usb_submit_urb(phy->in_urb, GFP_KERNEL);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index d378d4b4109f..331646d667b9 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -503,8 +503,8 @@ void __init early_init_fdt_scan_reserved_mem(void)
if (!initial_boot_params)
return;
- fdt_scan_reserved_mem();
fdt_reserve_elfcorehdr();
+ fdt_scan_reserved_mem();
/* Process header /memreserve/ fields */
for (n = 0; ; n++) {
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index a6eb6bffa5ea..eefb2bac8443 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -578,8 +578,8 @@ sba_io_pdir_entry(__le64 *pdir_ptr, space_t sid, phys_addr_t pba,
pba &= IOVP_MASK;
pba |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */
- pba |= SBA_PDIR_VALID_BIT; /* set "valid" bit */
- *pdir_ptr = cpu_to_le64(pba); /* swap and store into I/O Pdir */
+ /* set "valid" bit, swap and store into I/O Pdir */
+ *pdir_ptr = cpu_to_le64((unsigned long)pba | SBA_PDIR_VALID_BIT);
/*
* If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set
diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c
index 16a2fd9fdd9b..5ec1ad471696 100644
--- a/drivers/platform/mellanox/mlxbf-pmc.c
+++ b/drivers/platform/mellanox/mlxbf-pmc.c
@@ -801,18 +801,18 @@ static const struct mlxbf_pmc_events mlxbf_pmc_llt_miss_events[] = {
{11, "GDC_MISS_MACHINE_CHI_TXDAT"},
{12, "GDC_MISS_MACHINE_CHI_RXDAT"},
{13, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_0"},
- {14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1 "},
+ {14, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_1"},
{15, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_2"},
- {16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3 "},
- {17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0 "},
- {18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1 "},
- {19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2 "},
- {20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3 "},
+ {16, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC0_3"},
+ {17, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_0"},
+ {18, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_1"},
+ {19, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_2"},
+ {20, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC1_3"},
{21, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_0"},
{22, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_1"},
{23, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_2"},
{24, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE0_3"},
- {25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0 "},
+ {25, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_0"},
{26, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_1"},
{27, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_2"},
{28, "GDC_MISS_MACHINE_G_FIFO_FF_EXEC_DONE1_3"},
diff --git a/drivers/platform/x86/asus-armoury.h b/drivers/platform/x86/asus-armoury.h
index a1bb2005c3f3..3ac7aea37838 100644
--- a/drivers/platform/x86/asus-armoury.h
+++ b/drivers/platform/x86/asus-armoury.h
@@ -449,12 +449,27 @@ static const struct dmi_system_id power_limits[] = {
.ac_data = &(struct power_limits) {
.ppt_pl1_spl_min = 15,
.ppt_pl1_spl_max = 80,
- .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_min = 35,
.ppt_pl2_sppt_max = 80,
.ppt_pl3_fppt_min = 35,
- .ppt_pl3_fppt_max = 80
+ .ppt_pl3_fppt_max = 80,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_def = 45,
+ .ppt_pl1_spl_max = 65,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_def = 54,
+ .ppt_pl2_sppt_max = 65,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
},
- .dc_data = NULL,
},
},
{
@@ -554,6 +569,42 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "FA608UM"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_def = 45,
+ .ppt_pl1_spl_max = 90,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_def = 54,
+ .ppt_pl2_sppt_max = 90,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_def = 90,
+ .ppt_pl3_fppt_max = 65,
+ .nv_dynamic_boost_min = 10,
+ .nv_dynamic_boost_max = 15,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 55,
+ .nv_tgp_max = 100,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_def = 45,
+ .ppt_pl1_spl_max = 65,
+ .ppt_pl2_sppt_min = 35,
+ .ppt_pl2_sppt_def = 54,
+ .ppt_pl2_sppt_max = 65,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "FA608WI"),
},
.driver_data = &(struct power_data) {
@@ -824,6 +875,38 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GA403WR"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_max = 80,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 80,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 80,
+ .nv_dynamic_boost_min = 0,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 80,
+ .nv_tgp_max = 95,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 15,
+ .ppt_pl1_spl_max = 35,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 35,
+ .ppt_pl3_fppt_min = 35,
+ .ppt_pl3_fppt_max = 65,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "GA503QR"),
},
.driver_data = &(struct power_data) {
@@ -952,6 +1035,35 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GU605CR"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 30,
+ .ppt_pl1_spl_max = 85,
+ .ppt_pl2_sppt_min = 38,
+ .ppt_pl2_sppt_max = 110,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 20,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 80,
+ .nv_tgp_def = 90,
+ .nv_tgp_max = 105,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 30,
+ .ppt_pl1_spl_max = 85,
+ .ppt_pl2_sppt_min = 38,
+ .ppt_pl2_sppt_max = 110,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "GU605CW"),
},
.driver_data = &(struct power_data) {
@@ -1262,6 +1374,35 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "G615LR"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 28,
+ .ppt_pl1_spl_def = 140,
+ .ppt_pl1_spl_max = 175,
+ .ppt_pl2_sppt_min = 28,
+ .ppt_pl2_sppt_max = 175,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_tgp_min = 65,
+ .nv_tgp_max = 115,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 25,
+ .ppt_pl1_spl_max = 55,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 70,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "G634J"),
},
.driver_data = &(struct power_data) {
@@ -1428,6 +1569,35 @@ static const struct dmi_system_id power_limits[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "G835LW"),
+ },
+ .driver_data = &(struct power_data) {
+ .ac_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 28,
+ .ppt_pl1_spl_def = 140,
+ .ppt_pl1_spl_max = 175,
+ .ppt_pl2_sppt_min = 28,
+ .ppt_pl2_sppt_max = 175,
+ .nv_dynamic_boost_min = 5,
+ .nv_dynamic_boost_max = 25,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ .nv_tgp_min = 80,
+ .nv_tgp_max = 150,
+ },
+ .dc_data = &(struct power_limits) {
+ .ppt_pl1_spl_min = 25,
+ .ppt_pl1_spl_max = 55,
+ .ppt_pl2_sppt_min = 25,
+ .ppt_pl2_sppt_max = 70,
+ .nv_temp_target_min = 75,
+ .nv_temp_target_max = 87,
+ },
+ .requires_fan_curve = true,
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_BOARD_NAME, "H7606W"),
},
.driver_data = &(struct power_data) {
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 6a62bc5b02fd..a38a65f5c550 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -580,6 +580,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x2a, { KEY_SELECTIVE_SCREENSHOT } },
{ KE_IGNORE, 0x2b, }, /* PrintScreen (also send via PS/2) on newer models */
{ KE_IGNORE, 0x2c, }, /* CapsLock (also send via PS/2) on newer models */
+ { KE_KEY, 0x2d, { KEY_DISPLAYTOGGLE } },
{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
{ KE_KEY, 0x32, { KEY_MUTE } },
diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
index 1418bd326edf..e69b50162bb1 100644
--- a/drivers/platform/x86/dell/alienware-wmi-wmax.c
+++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c
@@ -90,6 +90,30 @@ static struct awcc_quirks empty_quirks;
static const struct dmi_system_id awcc_dmi_table[] __initconst = {
{
+ .ident = "Alienware 16 Area-51",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 16 Area-51"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Alienware 16X Aurora",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 16X Aurora"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Alienware 18 Area-51",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 18 Area-51"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
.ident = "Alienware 16 Aurora",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
@@ -162,6 +186,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
.driver_data = &generic_quirks,
},
{
+ .ident = "Alienware x16",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x16"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
.ident = "Alienware x17",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
diff --git a/drivers/platform/x86/dell/dell-lis3lv02d.c b/drivers/platform/x86/dell/dell-lis3lv02d.c
index 77905a9ddde9..fe52bcd896f7 100644
--- a/drivers/platform/x86/dell/dell-lis3lv02d.c
+++ b/drivers/platform/x86/dell/dell-lis3lv02d.c
@@ -44,6 +44,7 @@ static const struct dmi_system_id lis3lv02d_devices[] __initconst = {
/*
* Additional individual entries were added after verification.
*/
+ DELL_LIS3LV02D_DMI_ENTRY("Latitude 5400", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude 5480", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude 5500", 0x29),
DELL_LIS3LV02D_DMI_ENTRY("Latitude E6330", 0x29),
diff --git a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
index c50ad5880503..f346aad8e9d8 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/enum-attributes.c
@@ -207,7 +207,7 @@ static int hp_populate_enumeration_elements_from_package(union acpi_object *enum
case PREREQUISITES:
size = min_t(u32, enum_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
- if (elem >= enum_obj_count) {
+ if (elem + reqs >= enum_obj_count) {
pr_err("Error enum-objects package is too small\n");
return -EINVAL;
}
@@ -255,7 +255,7 @@ static int hp_populate_enumeration_elements_from_package(union acpi_object *enum
for (pos_values = 0; pos_values < size && pos_values < MAX_VALUES_SIZE;
pos_values++) {
- if (elem >= enum_obj_count) {
+ if (elem + pos_values >= enum_obj_count) {
pr_err("Error enum-objects package is too small\n");
return -EINVAL;
}
diff --git a/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
index 6c7f4d5fa9cb..63b1fda2be4e 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/int-attributes.c
@@ -227,7 +227,7 @@ static int hp_populate_integer_elements_from_package(union acpi_object *integer_
size = min_t(u32, integer_data->common.prerequisites_size, MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
- if (elem >= integer_obj_count) {
+ if (elem + reqs >= integer_obj_count) {
pr_err("Error elem-objects package is too small\n");
return -EINVAL;
}
diff --git a/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
index c6e57bb9d8b7..6a31f47ce3f5 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/order-list-attributes.c
@@ -216,6 +216,11 @@ static int hp_populate_ordered_list_elements_from_package(union acpi_object *ord
size = min_t(u32, ordered_list_data->common.prerequisites_size,
MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
+ if (elem + reqs >= order_obj_count) {
+ pr_err("Error elem-objects package is too small\n");
+ return -EINVAL;
+ }
+
ret = hp_convert_hexstr_to_str(order_obj[elem + reqs].string.pointer,
order_obj[elem + reqs].string.length,
&str_value, &value_len);
diff --git a/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
index 187b372123ed..ec79d9d50377 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/passwdobj-attributes.c
@@ -303,6 +303,11 @@ static int hp_populate_password_elements_from_package(union acpi_object *passwor
MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
+ if (elem + reqs >= password_obj_count) {
+ pr_err("Error elem-objects package is too small\n");
+ return -EINVAL;
+ }
+
ret = hp_convert_hexstr_to_str(password_obj[elem + reqs].string.pointer,
password_obj[elem + reqs].string.length,
&str_value, &value_len);
diff --git a/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
index 27758b779b2d..7b885d25650c 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/string-attributes.c
@@ -217,7 +217,7 @@ static int hp_populate_string_elements_from_package(union acpi_object *string_ob
MAX_PREREQUISITES_SIZE);
for (reqs = 0; reqs < size; reqs++) {
- if (elem >= string_obj_count) {
+ if (elem + reqs >= string_obj_count) {
pr_err("Error elem-objects package is too small\n");
return -EINVAL;
}
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
index 231b37909801..139956168cf9 100644
--- a/drivers/platform/x86/ibm_rtl.c
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -273,7 +273,7 @@ static int __init ibm_rtl_init(void) {
/* search for the _RTL_ signature at the start of the table */
for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
struct ibm_rtl_table __iomem * tmp;
- tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
+ tmp = (struct ibm_rtl_table __iomem *) (ebda_map + i*sizeof(unsigned int));
if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
phys_addr_t addr;
unsigned int plen;
diff --git a/drivers/platform/x86/intel/pmt/discovery.c b/drivers/platform/x86/intel/pmt/discovery.c
index 32713a194a55..e500aa327d23 100644
--- a/drivers/platform/x86/intel/pmt/discovery.c
+++ b/drivers/platform/x86/intel/pmt/discovery.c
@@ -503,8 +503,10 @@ static int pmt_features_discovery(struct pmt_features_priv *priv,
ret = kobject_init_and_add(&feature->kobj, ktype, &priv->dev->kobj,
"%s", pmt_feature_names[feature->id]);
- if (ret)
+ if (ret) {
+ kobject_put(&feature->kobj);
return ret;
+ }
kobject_uevent(&feature->kobj, KOBJ_ADD);
pmt_features_add_feat(feature);
@@ -546,9 +548,9 @@ static int pmt_features_probe(struct auxiliary_device *auxdev, const struct auxi
priv->dev = device_create(&intel_pmt_class, &auxdev->dev, MKDEV(0, 0), priv,
"%s-%s", "features", dev_name(priv->parent));
if (IS_ERR(priv->dev))
- return dev_err_probe(priv->dev, PTR_ERR(priv->dev),
+ return dev_err_probe(&auxdev->dev, PTR_ERR(priv->dev),
"Could not create %s-%s device node\n",
- "features", dev_name(priv->dev));
+ "features", dev_name(priv->parent));
/* Initialize each feature */
for (i = 0; i < ivdev->num_resources; i++) {
diff --git a/drivers/platform/x86/lenovo/ideapad-laptop.c b/drivers/platform/x86/lenovo/ideapad-laptop.c
index 5171a077f62c..7d5f7a2f6564 100644
--- a/drivers/platform/x86/lenovo/ideapad-laptop.c
+++ b/drivers/platform/x86/lenovo/ideapad-laptop.c
@@ -1367,7 +1367,7 @@ static const struct key_entry ideapad_keymap[] = {
/* Performance toggle also Fn+Q, handled inside ideapad_wmi_notify() */
{ KE_KEY, 0x3d | IDEAPAD_WMI_KEY, { KEY_PROG4 } },
/* shift + prtsc */
- { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_CUT } },
+ { KE_KEY, 0x2d | IDEAPAD_WMI_KEY, { KEY_SELECTIVE_SCREENSHOT } },
{ KE_KEY, 0x29 | IDEAPAD_WMI_KEY, { KEY_TOUCHPAD_TOGGLE } },
{ KE_KEY, 0x2a | IDEAPAD_WMI_KEY, { KEY_ROOT_MENU } },
diff --git a/drivers/platform/x86/lenovo/think-lmi.c b/drivers/platform/x86/lenovo/think-lmi.c
index 540b472b1bf3..c45f0206b4ab 100644
--- a/drivers/platform/x86/lenovo/think-lmi.c
+++ b/drivers/platform/x86/lenovo/think-lmi.c
@@ -195,7 +195,7 @@ static const struct tlmi_cert_guids thinkpad_cert_guid = {
};
static const struct tlmi_cert_guids thinkcenter_cert_guid = {
- .thumbprint = NULL,
+ .thumbprint = LENOVO_CERT_THUMBPRINT_GUID, /* Same GUID as TP */
.set_bios_setting = LENOVO_TC_SET_BIOS_SETTING_CERT_GUID,
.save_bios_setting = LENOVO_TC_SAVE_BIOS_SETTING_CERT_GUID,
.cert_to_password = LENOVO_TC_CERT_TO_PASSWORD_GUID,
@@ -709,6 +709,10 @@ static ssize_t cert_thumbprint(char *buf, const char *arg, int count)
if (!tlmi_priv.cert_guid->thumbprint)
return -EOPNOTSUPP;
+ /* Older ThinkCenter BIOS may not have support */
+ if (!wmi_has_guid(tlmi_priv.cert_guid->thumbprint))
+ return -EOPNOTSUPP;
+
status = wmi_evaluate_method(tlmi_priv.cert_guid->thumbprint, 0, 0, &input, &output);
if (ACPI_FAILURE(status)) {
kfree(output.pointer);
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index c4b150fa093f..ddef6b78d2fa 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -1130,6 +1130,9 @@ static void __exit msi_cleanup(void)
sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
if (!quirks->old_ec_model && threeg_exists)
device_remove_file(&msipf_device->dev, &dev_attr_threeg);
+ if (quirks->old_ec_model)
+ sysfs_remove_group(&msipf_device->dev.kobj,
+ &msipf_old_attribute_group);
platform_device_unregister(msipf_device);
platform_driver_unregister(&msipf_driver);
backlight_device_unregister(msibl_device);
diff --git a/drivers/platform/x86/samsung-galaxybook.c b/drivers/platform/x86/samsung-galaxybook.c
index 3c13e13d4885..755cb82bdb60 100644
--- a/drivers/platform/x86/samsung-galaxybook.c
+++ b/drivers/platform/x86/samsung-galaxybook.c
@@ -442,12 +442,13 @@ static int galaxybook_battery_ext_property_get(struct power_supply *psy,
union power_supply_propval *val)
{
struct samsung_galaxybook *galaxybook = ext_data;
+ u8 value;
int err;
if (psp != POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD)
return -EINVAL;
- err = charge_control_end_threshold_acpi_get(galaxybook, (u8 *)&val->intval);
+ err = charge_control_end_threshold_acpi_get(galaxybook, &value);
if (err)
return err;
@@ -455,8 +456,10 @@ static int galaxybook_battery_ext_property_get(struct power_supply *psy,
* device stores "no end threshold" as 0 instead of 100;
* if device has 0, report 100
*/
- if (val->intval == 0)
- val->intval = 100;
+ if (value == 0)
+ value = 100;
+
+ val->intval = value;
return 0;
}
diff --git a/drivers/platform/x86/uniwill/uniwill-acpi.c b/drivers/platform/x86/uniwill/uniwill-acpi.c
index bd7e63dd5181..0f935532f250 100644
--- a/drivers/platform/x86/uniwill/uniwill-acpi.c
+++ b/drivers/platform/x86/uniwill/uniwill-acpi.c
@@ -1845,6 +1845,13 @@ static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
},
},
{
+ .ident = "TUXEDO Book BA15 Gen10 AMD",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
+ },
+ },
+ {
.ident = "TUXEDO Pulse 14 Gen1 AMD",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
diff --git a/drivers/pmdomain/imx/gpc.c b/drivers/pmdomain/imx/gpc.c
index a34b260274f7..de695f1944ab 100644
--- a/drivers/pmdomain/imx/gpc.c
+++ b/drivers/pmdomain/imx/gpc.c
@@ -402,13 +402,12 @@ clk_err:
static int imx_gpc_probe(struct platform_device *pdev)
{
const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev);
- struct device_node *pgc_node;
+ struct device_node *pgc_node __free(device_node)
+ = of_get_child_by_name(pdev->dev.of_node, "pgc");
struct regmap *regmap;
void __iomem *base;
int ret;
- pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
-
/* bail out if DT too old and doesn't provide the necessary info */
if (!of_property_present(pdev->dev.of_node, "#power-domain-cells") &&
!pgc_node)
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index 80561d27f2b2..f64f24d520dd 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -984,18 +984,6 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
}
}
-static struct device_node *scpsys_get_legacy_regmap(struct device_node *np, const char *pn)
-{
- struct device_node *local_node;
-
- for_each_child_of_node(np, local_node) {
- if (of_property_present(local_node, pn))
- return local_node;
- }
-
- return NULL;
-}
-
static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys)
{
const u8 bp_blocks[3] = {
@@ -1017,7 +1005,8 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
* this makes it then possible to allocate the array of bus_prot
* regmaps and convert all to the new style handling.
*/
- node = scpsys_get_legacy_regmap(np, "mediatek,infracfg");
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,infracfg");
if (node) {
regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg");
of_node_put(node);
@@ -1030,7 +1019,8 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
regmap[0] = NULL;
}
- node = scpsys_get_legacy_regmap(np, "mediatek,smi");
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,smi");
if (node) {
smi_np = of_parse_phandle(node, "mediatek,smi", 0);
of_node_put(node);
@@ -1048,7 +1038,8 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
regmap[1] = NULL;
}
- node = scpsys_get_legacy_regmap(np, "mediatek,infracfg-nao");
+ of_node_get(np);
+ node = of_find_node_with_property(np, "mediatek,infracfg-nao");
if (node) {
regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
num_regmaps++;
diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c
index b9d87e56cbbc..3ff6da3bf4e6 100644
--- a/drivers/powercap/intel_rapl_common.c
+++ b/drivers/powercap/intel_rapl_common.c
@@ -2032,7 +2032,7 @@ end:
return ret;
}
-int rapl_package_add_pmu(struct rapl_package *rp)
+int rapl_package_add_pmu_locked(struct rapl_package *rp)
{
struct rapl_package_pmu_data *data = &rp->pmu_data;
int idx;
@@ -2040,8 +2040,6 @@ int rapl_package_add_pmu(struct rapl_package *rp)
if (rp->has_pmu)
return -EEXIST;
- guard(cpus_read_lock)();
-
for (idx = 0; idx < rp->nr_domains; idx++) {
struct rapl_domain *rd = &rp->domains[idx];
int domain = rd->id;
@@ -2091,17 +2089,23 @@ int rapl_package_add_pmu(struct rapl_package *rp)
return rapl_pmu_update(rp);
}
+EXPORT_SYMBOL_GPL(rapl_package_add_pmu_locked);
+
+int rapl_package_add_pmu(struct rapl_package *rp)
+{
+ guard(cpus_read_lock)();
+
+ return rapl_package_add_pmu_locked(rp);
+}
EXPORT_SYMBOL_GPL(rapl_package_add_pmu);
-void rapl_package_remove_pmu(struct rapl_package *rp)
+void rapl_package_remove_pmu_locked(struct rapl_package *rp)
{
struct rapl_package *pos;
if (!rp->has_pmu)
return;
- guard(cpus_read_lock)();
-
list_for_each_entry(pos, &rapl_packages, plist) {
/* PMU is still needed */
if (pos->has_pmu && pos != rp)
@@ -2111,6 +2115,14 @@ void rapl_package_remove_pmu(struct rapl_package *rp)
perf_pmu_unregister(&rapl_pmu.pmu);
memset(&rapl_pmu, 0, sizeof(struct rapl_pmu));
}
+EXPORT_SYMBOL_GPL(rapl_package_remove_pmu_locked);
+
+void rapl_package_remove_pmu(struct rapl_package *rp)
+{
+ guard(cpus_read_lock)();
+
+ rapl_package_remove_pmu_locked(rp);
+}
EXPORT_SYMBOL_GPL(rapl_package_remove_pmu);
#endif
diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c
index 0ce1096b6314..9a7e150b3536 100644
--- a/drivers/powercap/intel_rapl_msr.c
+++ b/drivers/powercap/intel_rapl_msr.c
@@ -82,7 +82,7 @@ static int rapl_cpu_online(unsigned int cpu)
if (IS_ERR(rp))
return PTR_ERR(rp);
if (rapl_msr_pmu)
- rapl_package_add_pmu(rp);
+ rapl_package_add_pmu_locked(rp);
}
cpumask_set_cpu(cpu, &rp->cpumask);
return 0;
@@ -101,7 +101,7 @@ static int rapl_cpu_down_prep(unsigned int cpu)
lead_cpu = cpumask_first(&rp->cpumask);
if (lead_cpu >= nr_cpu_ids) {
if (rapl_msr_pmu)
- rapl_package_remove_pmu(rp);
+ rapl_package_remove_pmu_locked(rp);
rapl_remove_package_cpuslocked(rp);
} else if (rp->lead_cpu == cpu) {
rp->lead_cpu = lead_cpu;
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
index 4112a0097338..1ff369880beb 100644
--- a/drivers/powercap/powercap_sys.c
+++ b/drivers/powercap/powercap_sys.c
@@ -68,7 +68,7 @@ static ssize_t show_constraint_##_attr(struct device *dev, \
int id; \
struct powercap_zone_constraint *pconst;\
\
- if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+ if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \
return -EINVAL; \
if (id >= power_zone->const_id_cnt) \
return -EINVAL; \
@@ -93,7 +93,7 @@ static ssize_t store_constraint_##_attr(struct device *dev,\
int id; \
struct powercap_zone_constraint *pconst;\
\
- if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+ if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \
return -EINVAL; \
if (id >= power_zone->const_id_cnt) \
return -EINVAL; \
@@ -162,7 +162,7 @@ static ssize_t show_constraint_name(struct device *dev,
ssize_t len = -ENODATA;
struct powercap_zone_constraint *pconst;
- if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id))
+ if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1)
return -EINVAL;
if (id >= power_zone->const_id_cnt)
return -EINVAL;
@@ -625,17 +625,23 @@ struct powercap_control_type *powercap_register_control_type(
INIT_LIST_HEAD(&control_type->node);
control_type->dev.class = &powercap_class;
dev_set_name(&control_type->dev, "%s", name);
- result = device_register(&control_type->dev);
- if (result) {
- put_device(&control_type->dev);
- return ERR_PTR(result);
- }
idr_init(&control_type->idr);
mutex_lock(&powercap_cntrl_list_lock);
list_add_tail(&control_type->node, &powercap_cntrl_list);
mutex_unlock(&powercap_cntrl_list_lock);
+ result = device_register(&control_type->dev);
+ if (result) {
+ mutex_lock(&powercap_cntrl_list_lock);
+ list_del(&control_type->node);
+ mutex_unlock(&powercap_cntrl_list_lock);
+
+ idr_destroy(&control_type->idr);
+ put_device(&control_type->dev);
+ return ERR_PTR(result);
+ }
+
return control_type;
}
EXPORT_SYMBOL_GPL(powercap_register_control_type);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 4b6182cde859..8c2fd20edd50 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -44,6 +44,8 @@ static LIST_HEAD(regulator_supply_alias_list);
static LIST_HEAD(regulator_coupler_list);
static bool has_full_constraints;
+static const struct bus_type regulator_bus;
+
static struct dentry *debugfs_root;
/*
@@ -96,6 +98,7 @@ struct regulator_event_work {
unsigned long event;
};
+static int _regulator_enable(struct regulator *regulator);
static int _regulator_is_enabled(struct regulator_dev *rdev);
static int _regulator_disable(struct regulator *regulator);
static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);
@@ -1183,7 +1186,7 @@ static void print_constraints_debug(struct regulator_dev *rdev)
count += scnprintf(buf + count, len - count, "standby ");
if (constraints->pw_budget_mW)
- count += scnprintf(buf + count, len - count, "%d mW budget",
+ count += scnprintf(buf + count, len - count, "%d mW budget ",
constraints->pw_budget_mW);
if (!count)
@@ -1430,6 +1433,7 @@ static int handle_notify_limits(struct regulator_dev *rdev,
/**
* set_machine_constraints - sets regulator constraints
* @rdev: regulator source
+ * @is_locked: whether or not this is called with locks held already
*
* Allows platform initialisation code to define and constrain
* regulator circuits e.g. valid voltage/current ranges, etc. NOTE:
@@ -1439,11 +1443,39 @@ static int handle_notify_limits(struct regulator_dev *rdev,
*
* Return: 0 on success or a negative error number on failure.
*/
-static int set_machine_constraints(struct regulator_dev *rdev)
+static int set_machine_constraints(struct regulator_dev *rdev,
+ bool is_locked)
{
int ret = 0;
const struct regulator_ops *ops = rdev->desc->ops;
+ /*
+ * If there is no mechanism for controlling the regulator then
+ * flag it as always_on so we don't end up duplicating checks
+ * for this so much. Note that we could control the state of
+ * a supply to control the output on a regulator that has no
+ * direct control.
+ */
+ if (!rdev->ena_pin && !ops->enable) {
+ if (rdev->supply_name && !rdev->supply)
+ return -EPROBE_DEFER;
+
+ if (rdev->supply)
+ rdev->constraints->always_on =
+ rdev->supply->rdev->constraints->always_on;
+ else
+ rdev->constraints->always_on = true;
+ }
+
+ /*
+ * If we want to enable this regulator, make sure that we know the
+ * supplying regulator.
+ */
+ if (rdev->constraints->always_on || rdev->constraints->boot_on) {
+ if (rdev->supply_name && !rdev->supply)
+ return -EPROBE_DEFER;
+ }
+
ret = machine_constraints_voltage(rdev, rdev->constraints);
if (ret != 0)
return ret;
@@ -1609,44 +1641,24 @@ static int set_machine_constraints(struct regulator_dev *rdev)
}
}
- /*
- * If there is no mechanism for controlling the regulator then
- * flag it as always_on so we don't end up duplicating checks
- * for this so much. Note that we could control the state of
- * a supply to control the output on a regulator that has no
- * direct control.
- */
- if (!rdev->ena_pin && !ops->enable) {
- if (rdev->supply_name && !rdev->supply)
- return -EPROBE_DEFER;
-
- if (rdev->supply)
- rdev->constraints->always_on =
- rdev->supply->rdev->constraints->always_on;
- else
- rdev->constraints->always_on = true;
- }
-
/* If the constraints say the regulator should be on at this point
* and we have control then make sure it is enabled.
*/
if (rdev->constraints->always_on || rdev->constraints->boot_on) {
bool supply_enabled = false;
- /* If we want to enable this regulator, make sure that we know
- * the supplying regulator.
- */
- if (rdev->supply_name && !rdev->supply)
- return -EPROBE_DEFER;
-
- /* If supplying regulator has already been enabled,
+ /* We have ensured a potential supply has been resolved above.
+ *
+ * If supplying regulator has already been enabled,
* it's not intended to have use_count increment
* when rdev is only boot-on.
*/
if (rdev->supply &&
(rdev->constraints->always_on ||
!regulator_is_enabled(rdev->supply))) {
- ret = regulator_enable(rdev->supply);
+ ret = (is_locked
+ ? _regulator_enable(rdev->supply)
+ : regulator_enable(rdev->supply));
if (ret < 0) {
_regulator_put(rdev->supply);
rdev->supply = NULL;
@@ -1774,6 +1786,15 @@ static int register_regulator_event_forwarding(struct regulator_dev *rdev)
return 0;
}
+static void unregister_regulator_event_forwarding(struct regulator_dev *rdev)
+{
+ if (!rdev->supply_fwd_nb.notifier_call)
+ return;
+
+ regulator_unregister_notifier(rdev->supply, &rdev->supply_fwd_nb);
+ rdev->supply_fwd_nb.notifier_call = NULL;
+}
+
/**
* set_supply - set regulator supply regulator
* @rdev: regulator (locked)
@@ -2162,6 +2183,8 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
struct regulator_dev *r;
struct device *dev = rdev->dev.parent;
struct ww_acquire_ctx ww_ctx;
+ struct regulator *supply;
+ bool do_final_setup;
int ret = 0;
/* No supply to resolve? */
@@ -2169,7 +2192,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
return 0;
/* Supply already resolved? (fast-path without locking contention) */
- if (rdev->supply)
+ if (rdev->supply && !rdev->constraints_pending)
return 0;
/* first do a dt based lookup on the node described in the virtual
@@ -2250,49 +2273,115 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
/* Supply just resolved by a concurrent task? */
if (rdev->supply) {
- regulator_unlock_two(rdev, r, &ww_ctx);
- put_device(&r->dev);
- goto out;
- }
+ /* Constraints might still be pending due to concurrency. */
+ bool done = !rdev->constraints_pending;
+
+ supply = rdev->supply;
- ret = set_supply(rdev, r);
- if (ret < 0) {
regulator_unlock_two(rdev, r, &ww_ctx);
put_device(&r->dev);
- goto out;
- }
- /*
- * Automatically register for event forwarding from the new supply.
- * This creates the downstream propagation link for events like
- * under-voltage.
- */
- ret = register_regulator_event_forwarding(rdev);
- if (ret < 0)
- rdev_warn(rdev, "Failed to register event forwarding: %pe\n",
- ERR_PTR(ret));
+ /*
+ * Supply resolved by concurrent task, and constraints set as
+ * well (or not required): fast path.
+ */
+ if (done)
+ goto out;
- regulator_unlock_two(rdev, r, &ww_ctx);
+ do_final_setup = false;
+ } else {
+ ret = set_supply(rdev, r);
+ if (ret < 0) {
+ regulator_unlock_two(rdev, r, &ww_ctx);
+ put_device(&r->dev);
+ goto out;
+ }
- /* rdev->supply was created in set_supply() */
- link_and_create_debugfs(rdev->supply, r, &rdev->dev);
+ supply = rdev->supply;
+
+ /*
+ * Automatically register for event forwarding from the new
+ * supply. This creates the downstream propagation link for
+ * events like under-voltage.
+ */
+ ret = register_regulator_event_forwarding(rdev);
+ if (ret < 0) {
+ rdev_warn(rdev,
+ "Failed to register event forwarding: %pe\n",
+ ERR_PTR(ret));
+
+ goto unset_supply;
+ }
+
+ regulator_unlock_two(rdev, r, &ww_ctx);
+
+ do_final_setup = true;
+ }
/*
- * In set_machine_constraints() we may have turned this regulator on
- * but we couldn't propagate to the supply if it hadn't been resolved
- * yet. Do it now.
+ * Now that we have the supply, we can retry setting the machine
+ * constraints, if necessary.
*/
- if (rdev->use_count) {
- ret = regulator_enable(rdev->supply);
- if (ret < 0) {
- _regulator_put(rdev->supply);
- rdev->supply = NULL;
+ regulator_lock_dependent(rdev, &ww_ctx);
+ if (rdev->constraints_pending) {
+ if (!rdev->supply) {
+ /*
+ * Supply could have been released by another task that
+ * failed to set the constraints or event forwarding.
+ */
+ regulator_unlock_dependent(rdev, &ww_ctx);
+ ret = -EPROBE_DEFER;
goto out;
}
+
+ ret = set_machine_constraints(rdev, true);
+ if (ret < 0) {
+ regulator_unlock_dependent(rdev, &ww_ctx);
+
+ rdev_warn(rdev,
+ "Failed to set machine constraints: %pe\n",
+ ERR_PTR(ret));
+
+ regulator_lock_two(rdev, r, &ww_ctx);
+
+ if (supply != rdev->supply) {
+ /*
+ * Supply could have been released by another
+ * task that got here before us. If it did, it
+ * will have released 'supply' (i.e. the
+ * previous rdev->supply) and we shouldn't do
+ * that again via unset_supply.
+ */
+ regulator_unlock_two(rdev, r, &ww_ctx);
+ goto out;
+ }
+
+ unregister_regulator_event_forwarding(rdev);
+ rdev->constraints_pending = true;
+ goto unset_supply;
+ }
+ rdev->constraints_pending = false;
}
+ regulator_unlock_dependent(rdev, &ww_ctx);
+
+ if (!do_final_setup)
+ goto out;
+
+ /* rdev->supply was created in set_supply() */
+ link_and_create_debugfs(rdev->supply, rdev->supply->rdev, &rdev->dev);
out:
return ret;
+
+unset_supply:
+ lockdep_assert_held_once(&rdev->mutex.base);
+ lockdep_assert_held_once(&r->mutex.base);
+ rdev->supply = NULL;
+ regulator_unlock_two(rdev, supply->rdev, &ww_ctx);
+
+ regulator_put(supply);
+
+ return ret;
}
/* common pre-checks for regulator requests */
@@ -5692,16 +5781,6 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
&rdev->bypass_count);
}
-static int regulator_register_resolve_supply(struct device *dev, void *data)
-{
- struct regulator_dev *rdev = dev_to_rdev(dev);
-
- if (regulator_resolve_supply(rdev))
- rdev_dbg(rdev, "unable to resolve supply\n");
-
- return 0;
-}
-
int regulator_coupler_register(struct regulator_coupler *coupler)
{
mutex_lock(&regulator_list_mutex);
@@ -5920,10 +5999,10 @@ regulator_register(struct device *dev,
struct regulator_config *config = NULL;
static atomic_t regulator_no = ATOMIC_INIT(-1);
struct regulator_dev *rdev;
+ bool tried_supply_resolve = false;
bool dangling_cfg_gpiod = false;
bool dangling_of_gpiod = false;
int ret, i;
- bool resolved_early = false;
if (cfg == NULL)
return ERR_PTR(-EINVAL);
@@ -6061,17 +6140,6 @@ regulator_register(struct device *dev,
goto wash;
}
- if ((rdev->supply_name && !rdev->supply) &&
- (rdev->constraints->always_on ||
- rdev->constraints->boot_on)) {
- ret = regulator_resolve_supply(rdev);
- if (ret)
- rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
- ERR_PTR(ret));
-
- resolved_early = true;
- }
-
if (config->ena_gpiod) {
ret = regulator_ena_gpio_request(rdev, config);
if (ret != 0) {
@@ -6084,10 +6152,11 @@ regulator_register(struct device *dev,
dangling_of_gpiod = false;
}
- ret = set_machine_constraints(rdev);
- if (ret == -EPROBE_DEFER && !resolved_early) {
- /* Regulator might be in bypass mode and so needs its supply
- * to set the constraints
+ ret = set_machine_constraints(rdev, false);
+ if (ret == -EPROBE_DEFER) {
+ /* Regulator might be in bypass mode or an always-on or boot-on
+ * regulator and so needs its supply to set the constraints or
+ * for enable.
*/
/* FIXME: this currently triggers a chicken-and-egg problem
* when creating -SUPPLY symlink in sysfs to a regulator
@@ -6097,13 +6166,17 @@ regulator_register(struct device *dev,
rdev->supply_name);
ret = regulator_resolve_supply(rdev);
if (!ret)
- ret = set_machine_constraints(rdev);
+ ret = set_machine_constraints(rdev, false);
else
rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
ERR_PTR(ret));
+ tried_supply_resolve = true;
+ }
+ if (ret < 0) {
+ if (ret != -EPROBE_DEFER)
+ goto wash;
+ rdev->constraints_pending = true;
}
- if (ret < 0)
- goto wash;
ret = regulator_init_coupling(rdev);
if (ret < 0)
@@ -6132,6 +6205,37 @@ regulator_register(struct device *dev,
if (ret != 0)
goto unset_supplies;
+ if (!tried_supply_resolve) {
+ /*
+ * As an optimisation, try to resolve our supply (if any) now to
+ * avoid adding the bus device. Errors are not fatal at this
+ * stage, we'll simply try again later.
+ */
+ ret = regulator_resolve_supply(rdev);
+ if (ret)
+ rdev_dbg(rdev,
+ "unable to resolve supply (ignoring): %pe\n",
+ ERR_PTR(ret));
+ }
+
+ /*
+ * If we have a supply but couldn't resolve it yet, register a device
+ * with our bus, so that the bus probe gets called whenever any new
+ * driver binds, allowing us to retry matching supplies and which then
+ * triggers (re)probe of consumers if successful.
+ */
+ if (rdev->supply_name && !rdev->supply) {
+ device_initialize(&rdev->bdev);
+ rdev->bdev.bus = &regulator_bus;
+ rdev->bdev.parent = &rdev->dev;
+ device_set_pm_not_required(&rdev->dev);
+ dev_set_name(&rdev->bdev, "%s.bdev", dev_name(&rdev->dev));
+
+ ret = device_add(&rdev->bdev);
+ if (ret)
+ goto del_cdev_and_bdev;
+ }
+
rdev_init_debugfs(rdev);
/* try to resolve regulators coupling since a new one was registered */
@@ -6139,12 +6243,13 @@ regulator_register(struct device *dev,
regulator_resolve_coupling(rdev);
mutex_unlock(&regulator_list_mutex);
- /* try to resolve regulators supply since a new one was registered */
- class_for_each_device(&regulator_class, NULL, NULL,
- regulator_register_resolve_supply);
kfree(config);
return rdev;
+del_cdev_and_bdev:
+ if (rdev->bdev.bus == &regulator_bus)
+ put_device(&rdev->bdev);
+ device_del(&rdev->dev);
unset_supplies:
mutex_lock(&regulator_list_mutex);
unset_regulator_supplies(rdev);
@@ -6197,6 +6302,9 @@ void regulator_unregister(struct regulator_dev *rdev)
unset_regulator_supplies(rdev);
list_del(&rdev->list);
regulator_ena_gpio_free(rdev);
+ if (rdev->bdev.bus == &regulator_bus)
+ /* only if the device was added in the first place */
+ device_unregister(&rdev->bdev);
device_unregister(&rdev->dev);
mutex_unlock(&regulator_list_mutex);
@@ -6277,6 +6385,45 @@ const struct class regulator_class = {
.pm = &regulator_pm_ops,
#endif
};
+
+#define bdev_to_rdev(__bdev) container_of_const(__bdev, struct regulator_dev, bdev)
+
+static int regulator_bus_match(struct device *bdev,
+ const struct device_driver *drv)
+{
+ /* Match always succeeds, we only have one driver */
+ return 1;
+}
+
+static int regulator_bus_probe(struct device *bdev)
+{
+ struct regulator_dev *rdev = bdev_to_rdev(bdev);
+ int ret;
+
+ ret = regulator_resolve_supply(rdev);
+ if (ret)
+ rdev_dbg(rdev,
+ "unable to resolve supply or constraints '%s': %pe\n",
+ rdev->supply_name, ERR_PTR(ret));
+ else
+ rdev_dbg(rdev, "resolved supply '%s'\n", rdev->supply_name);
+
+ return ret;
+}
+
+static const struct bus_type regulator_bus = {
+ .name = "regulator",
+ .match = regulator_bus_match,
+ .probe = regulator_bus_probe,
+};
+
+static struct device_driver regulator_bus_driver = {
+ .name = "regulator-bus-drv",
+ .bus = &regulator_bus,
+ .suppress_bind_attrs = true,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+};
+
/**
* regulator_has_full_constraints - the system has fully specified constraints
*
@@ -6610,7 +6757,17 @@ static int __init regulator_init(void)
{
int ret;
+ ret = bus_register(&regulator_bus);
+ if (ret)
+ return ret;
+
ret = class_register(&regulator_class);
+ if (ret)
+ goto err_class;
+
+ ret = driver_register(&regulator_bus_driver);
+ if (ret)
+ goto err_driver;
debugfs_root = debugfs_create_dir("regulator", NULL);
if (IS_ERR(debugfs_root))
@@ -6627,6 +6784,12 @@ static int __init regulator_init(void)
regulator_coupler_register(&generic_regulator_coupler);
+ return 0;
+
+err_driver:
+ class_unregister(&regulator_class);
+err_class:
+ bus_unregister(&regulator_bus);
return ret;
}
@@ -6688,16 +6851,6 @@ __setup("regulator_ignore_unused", regulator_ignore_unused_setup);
static void regulator_init_complete_work_function(struct work_struct *work)
{
/*
- * Regulators may had failed to resolve their input supplies
- * when were registered, either because the input supply was
- * not registered yet or because its parent device was not
- * bound yet. So attempt to resolve the input supplies for
- * pending regulators before trying to disable unused ones.
- */
- class_for_each_device(&regulator_class, NULL, NULL,
- regulator_register_resolve_supply);
-
- /*
* For debugging purposes, it may be useful to prevent unused
* regulators from being disabled.
*/
diff --git a/drivers/regulator/fp9931.c b/drivers/regulator/fp9931.c
index fef0bb07fd5d..69b3c712e5d5 100644
--- a/drivers/regulator/fp9931.c
+++ b/drivers/regulator/fp9931.c
@@ -391,6 +391,7 @@ static const struct regulator_desc regulators[] = {
{
.name = "v3p3",
.of_match = of_match_ptr("v3p3"),
+ .regulators_node = of_match_ptr("regulators"),
.id = 0,
.ops = &fp9931_v3p3ops,
.type = REGULATOR_VOLTAGE,
@@ -403,6 +404,7 @@ static const struct regulator_desc regulators[] = {
{
.name = "vposneg",
.of_match = of_match_ptr("vposneg"),
+ .regulators_node = of_match_ptr("regulators"),
.id = 1,
.ops = &fp9931_vposneg_ops,
.type = REGULATOR_VOLTAGE,
@@ -415,6 +417,7 @@ static const struct regulator_desc regulators[] = {
{
.name = "vcom",
.of_match = of_match_ptr("vcom"),
+ .regulators_node = of_match_ptr("regulators"),
.id = 2,
.ops = &fp9931_vcom_ops,
.type = REGULATOR_VOLTAGE,
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
index b42933fcd423..6561f98c3cb2 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
@@ -166,6 +166,7 @@ struct mpi3_ioc_facts_data {
#define MPI3_IOCFACTS_FLAGS_SIGNED_NVDATA_REQUIRED (0x00010000)
#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK (0x0000ff00)
#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT (8)
+#define MPI3_IOCFACTS_FLAGS_MAX_REQ_PER_REPLY_QUEUE_LIMIT (0x00000040)
#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK (0x00000030)
#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_SHIFT (4)
#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_NOT_STARTED (0x00000000)
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 8fe6e0bf342e..8c4bb7169a87 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -3158,6 +3158,8 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
mrioc->facts.dma_mask = (facts_flags &
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
+ mrioc->facts.max_req_limit = (facts_flags &
+ MPI3_IOCFACTS_FLAGS_MAX_REQ_PER_REPLY_QUEUE_LIMIT);
mrioc->facts.protocol_flags = facts_data->protocol_flags;
mrioc->facts.mpi_version = le32_to_cpu(facts_data->mpi_version.word);
mrioc->facts.max_reqs = le16_to_cpu(facts_data->max_outstanding_requests);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 1f2a53ba5dd9..c5085e6d2e75 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -7459,7 +7459,7 @@ MODULE_PARM_DESC(lbprz,
MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
-MODULE_PARM_DESC(atomic_write, "enable ATOMIC WRITE support, support WRITE ATOMIC(16) (def=0)");
+MODULE_PARM_DESC(atomic_wr, "enable ATOMIC WRITE support, support WRITE ATOMIC(16) (def=0)");
MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
MODULE_PARM_DESC(lun_format, "LUN format: 0->peripheral (def); 1 --> flat address method");
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b3af9b78fa12..57fba34832ad 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -731,6 +731,8 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
sg_remove_request(sfp, srp);
return -EFAULT;
}
+ hp->duration = jiffies_to_msecs(jiffies);
+
if (hp->interface_id != 'S') {
sg_remove_request(sfp, srp);
return -ENOSYS;
@@ -815,7 +817,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return -ENODEV;
}
- hp->duration = jiffies_to_msecs(jiffies);
if (hp->interface_id != '\0' && /* v3 (or later) interface */
(SG_FLAG_Q_AT_TAIL & hp->flags))
at_head = 0;
@@ -1338,9 +1339,6 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
"sg_cmd_done: pack_id=%d, res=0x%x\n",
srp->header.pack_id, result));
srp->header.resid = resid;
- ms = jiffies_to_msecs(jiffies);
- srp->header.duration = (ms > srp->header.duration) ?
- (ms - srp->header.duration) : 0;
if (0 != result) {
struct scsi_sense_hdr sshdr;
@@ -1389,6 +1387,9 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
done = 0;
}
srp->done = done;
+ ms = jiffies_to_msecs(jiffies);
+ srp->header.duration = (ms > srp->header.duration) ?
+ (ms - srp->header.duration) : 0;
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
if (likely(done)) {
@@ -2533,6 +2534,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
const sg_io_hdr_t *hp;
const char * cp;
unsigned int ms;
+ unsigned int duration;
k = 0;
list_for_each_entry(fp, &sdp->sfds, sfd_siblings) {
@@ -2570,13 +2572,17 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
seq_printf(s, " id=%d blen=%d",
srp->header.pack_id, blen);
if (srp->done)
- seq_printf(s, " dur=%d", hp->duration);
+ seq_printf(s, " dur=%u", hp->duration);
else {
ms = jiffies_to_msecs(jiffies);
- seq_printf(s, " t_o/elap=%d/%d",
+ duration = READ_ONCE(hp->duration);
+ if (duration)
+ duration = (ms > duration ?
+ ms - duration : 0);
+ seq_printf(s, " t_o/elap=%u/%u",
(new_interface ? hp->timeout :
jiffies_to_msecs(fp->timeout)),
- (ms > hp->duration ? ms - hp->duration : 0));
+ duration);
}
seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
(int) srp->data.cmd_opcode);
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index af6d050da1c8..965b4cea3388 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -300,6 +300,9 @@ struct cqspi_driver_platdata {
CQSPI_REG_IRQ_IND_SRAM_FULL | \
CQSPI_REG_IRQ_IND_COMP)
+#define CQSPI_IRQ_MASK_RD_SLOW_SRAM (CQSPI_REG_IRQ_WATERMARK | \
+ CQSPI_REG_IRQ_IND_COMP)
+
#define CQSPI_IRQ_MASK_WR (CQSPI_REG_IRQ_IND_COMP | \
CQSPI_REG_IRQ_WATERMARK | \
CQSPI_REG_IRQ_UNDERFLOW)
@@ -381,7 +384,7 @@ static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
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;
+ irq_status &= CQSPI_IRQ_MASK_RD_SLOW_SRAM | CQSPI_IRQ_MASK_WR;
if (irq_status)
complete(&cqspi->transfer_complete);
@@ -757,7 +760,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
*/
if (use_irq && cqspi->slow_sram)
- writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK);
+ writel(CQSPI_IRQ_MASK_RD_SLOW_SRAM, reg_base + CQSPI_REG_IRQMASK);
else if (use_irq)
writel(CQSPI_IRQ_MASK_RD, reg_base + CQSPI_REG_IRQMASK);
else
@@ -769,17 +772,19 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
readl(reg_base + CQSPI_REG_INDIRECTRD); /* Flush posted write. */
while (remaining > 0) {
+ ret = 0;
if (use_irq &&
!wait_for_completion_timeout(&cqspi->transfer_complete,
msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS)))
ret = -ETIMEDOUT;
/*
- * Disable all read interrupts until
- * we are out of "bytes to read"
+ * Prevent lost interrupt and race condition by reinitializing early.
+ * A spurious wakeup and another wait cycle can occur here,
+ * which is preferable to waiting until timeout if interrupt is lost.
*/
- if (cqspi->slow_sram)
- writel(0x0, reg_base + CQSPI_REG_IRQMASK);
+ if (use_irq)
+ reinit_completion(&cqspi->transfer_complete);
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
@@ -811,12 +816,6 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
remaining -= bytes_to_read;
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
}
-
- if (use_irq && 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 */
@@ -2001,8 +2000,10 @@ static int cqspi_probe(struct platform_device *pdev)
if (cqspi->use_direct_mode) {
ret = cqspi_request_mmap_dma(cqspi);
- if (ret == -EPROBE_DEFER)
+ if (ret == -EPROBE_DEFER) {
+ dev_err_probe(&pdev->dev, ret, "Failed to request mmap DMA\n");
goto probe_setup_failed;
+ }
}
ret = spi_register_controller(host);
@@ -2024,7 +2025,9 @@ probe_setup_failed:
probe_reset_failed:
if (cqspi->is_jh7110)
cqspi_jh7110_disable_clk(pdev, cqspi);
- clk_disable_unprepare(cqspi->clk);
+
+ if (pm_runtime_get_sync(&pdev->dev) >= 0)
+ clk_disable_unprepare(cqspi->clk);
probe_clk_failed:
return ret;
}
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 2f2082652a1a..481a7b28aacd 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -335,7 +335,7 @@ static int fsl_spi_prepare_message(struct spi_controller *ctlr,
if (t->bits_per_word == 16 || t->bits_per_word == 32)
t->bits_per_word = 8; /* pretend its 8 bits */
if (t->bits_per_word == 8 && t->len >= 256 &&
- (mpc8xxx_spi->flags & SPI_CPM1))
+ !(t->len & 1) && (mpc8xxx_spi->flags & SPI_CPM1))
t->bits_per_word = 16;
}
}
diff --git a/drivers/spi/spi-mpfs.c b/drivers/spi/spi-mpfs.c
index 9a14d1732a15..7e9e64d8e6c8 100644
--- a/drivers/spi/spi-mpfs.c
+++ b/drivers/spi/spi-mpfs.c
@@ -577,6 +577,7 @@ static int mpfs_spi_probe(struct platform_device *pdev)
ret = devm_spi_register_controller(&pdev->dev, host);
if (ret) {
+ mpfs_spi_disable_ints(spi);
mpfs_spi_disable(spi);
return dev_err_probe(&pdev->dev, ret,
"unable to register host for SPI controller\n");
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 4b40985af1ea..90e5813cfdc3 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -1320,7 +1320,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(dev, irq, mtk_spi_interrupt,
mtk_spi_interrupt_thread,
- IRQF_TRIGGER_NONE, dev_name(dev), host);
+ IRQF_ONESHOT, dev_name(dev), host);
if (ret)
return dev_err_probe(dev, ret, "failed to register irq\n");
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 871dfd3e77be..d1de6c99e762 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -795,10 +795,13 @@ static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
static const struct of_device_id sun6i_spi_match[] = {
{ .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg },
{ .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_cfg },
- {
- .compatible = "allwinner,sun50i-r329-spi",
- .data = &sun50i_r329_spi_cfg
- },
+ { .compatible = "allwinner,sun50i-r329-spi", .data = &sun50i_r329_spi_cfg },
+ /*
+ * A523's SPI controller has a combined RX buffer + FIFO counter
+ * at offset 0x400, instead of split buffer count in FIFO status
+ * register. But in practice we only care about the FIFO level.
+ */
+ { .compatible = "allwinner,sun55i-a523-spi", .data = &sun50i_r329_spi_cfg },
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
index 0d4dcc66e097..c693d934103a 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
@@ -503,7 +503,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, WCL_THERMAL, PROC_THERMAL_FEATURE_MSI_SUPPORT |
PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR |
PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_HINT |
- PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) },
+ PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC |
+ PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) },
{ PCI_DEVICE_DATA(INTEL, NVL_H_THERMAL, PROC_THERMAL_FEATURE_RAPL |
PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS |
PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT |
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 17ca5c082643..89758c9934ec 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -500,7 +500,7 @@ void thermal_zone_set_trip_hyst(struct thermal_zone_device *tz,
WRITE_ONCE(trip->hysteresis, hyst);
thermal_notify_tz_trip_change(tz, trip);
/*
- * If the zone temperature is above or at the trip tmperature, the trip
+ * If the zone temperature is above or at the trip temperature, the trip
* is in the trips_reached list and its threshold is equal to its low
* temperature. It needs to stay in that list, but its threshold needs
* to be updated and the list ordering may need to be restored.
@@ -1043,7 +1043,7 @@ static void thermal_cooling_device_init_complete(struct thermal_cooling_device *
* @np: a pointer to a device tree node.
* @type: the thermal cooling device type.
* @devdata: device private data.
- * @ops: standard thermal cooling devices callbacks.
+ * @ops: standard thermal cooling devices callbacks.
*
* This interface function adds a new thermal cooling device (fan/processor/...)
* to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
diff --git a/drivers/tty/serial/8250/8250_loongson.c b/drivers/tty/serial/8250/8250_loongson.c
index 53153a116c01..47df3c4c9d21 100644
--- a/drivers/tty/serial/8250/8250_loongson.c
+++ b/drivers/tty/serial/8250/8250_loongson.c
@@ -128,8 +128,8 @@ static int loongson_uart_probe(struct platform_device *pdev)
port->private_data = priv;
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &priv->res);
- if (!port->membase)
- return -ENOMEM;
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
port->mapbase = priv->res->start;
port->mapsize = resource_size(priv->res);
diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
index 22749ab0428a..1e1ad28d83fc 100644
--- a/drivers/tty/serial/serial_base_bus.c
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -13,7 +13,7 @@
#include <linux/device.h>
#include <linux/idr.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
#include <linux/serial_core.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -60,6 +60,7 @@ void serial_base_driver_unregister(struct device_driver *driver)
driver_unregister(driver);
}
+/* On failure the caller must put device @dev with put_device() */
static int serial_base_device_init(struct uart_port *port,
struct device *dev,
struct device *parent_dev,
@@ -73,7 +74,9 @@ static int serial_base_device_init(struct uart_port *port,
dev->parent = parent_dev;
dev->bus = &serial_base_bus_type;
dev->release = release;
- device_set_of_node_from_dev(dev, parent_dev);
+ dev->of_node_reused = true;
+
+ device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));
if (!serial_base_initialized) {
dev_dbg(port->dev, "uart_add_one_port() called before arch_initcall()?\n");
@@ -94,7 +97,7 @@ static void serial_base_ctrl_release(struct device *dev)
{
struct serial_ctrl_device *ctrl_dev = to_serial_base_ctrl_device(dev);
- of_node_put(dev->of_node);
+ fwnode_handle_put(dev_fwnode(dev));
kfree(ctrl_dev);
}
@@ -142,7 +145,7 @@ static void serial_base_port_release(struct device *dev)
{
struct serial_port_device *port_dev = to_serial_base_port_device(dev);
- of_node_put(dev->of_node);
+ fwnode_handle_put(dev_fwnode(dev));
kfree(port_dev);
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 53edbf1d8963..fbfe5575bd3c 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1914,7 +1914,7 @@ static void sci_dma_check_tx_occurred(struct sci_port *s)
struct dma_tx_state state;
enum dma_status status;
- if (!s->chan_tx)
+ if (!s->chan_tx || s->cookie_tx <= 0)
return;
status = dmaengine_tx_status(s->chan_tx, s->cookie_tx, &state);
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index c793fc74c26b..c593d20a1b5b 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -428,10 +428,17 @@ static void cdns_uart_handle_tx(void *dev_id)
struct tty_port *tport = &port->state->port;
unsigned int numbytes;
unsigned char ch;
+ ktime_t rts_delay;
if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {
/* Disable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR);
+ /* Set RTS line after delay */
+ if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED) {
+ cdns_uart->tx_timer.function = &cdns_rs485_rx_callback;
+ rts_delay = ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart));
+ hrtimer_start(&cdns_uart->tx_timer, rts_delay, HRTIMER_MODE_REL);
+ }
return;
}
@@ -448,13 +455,6 @@ static void cdns_uart_handle_tx(void *dev_id)
/* Enable the TX Empty interrupt */
writel(CDNS_UART_IXR_TXEMPTY, cdns_uart->port->membase + CDNS_UART_IER);
-
- if (cdns_uart->port->rs485.flags & SER_RS485_ENABLED &&
- (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port))) {
- hrtimer_update_function(&cdns_uart->tx_timer, cdns_rs485_rx_callback);
- hrtimer_start(&cdns_uart->tx_timer,
- ns_to_ktime(cdns_calc_after_tx_delay(cdns_uart)), HRTIMER_MODE_REL);
- }
}
/**
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 80c0b49f30b0..0babb7035200 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -10359,7 +10359,7 @@ static int ufshcd_suspend(struct ufs_hba *hba)
ret = ufshcd_setup_clocks(hba, false);
if (ret) {
ufshcd_enable_irq(hba);
- return ret;
+ goto out;
}
if (ufshcd_is_clkgating_allowed(hba)) {
hba->clk_gating.state = CLKS_OFF;
@@ -10371,6 +10371,9 @@ static int ufshcd_suspend(struct ufs_hba *hba)
/* Put the host controller in low power mode if possible */
ufshcd_hba_vreg_set_lpm(hba);
ufshcd_pm_qos_update(hba, false);
+out:
+ if (ret)
+ ufshcd_update_evt_hist(hba, UFS_EVT_SUSPEND_ERR, (u32)ret);
return ret;
}
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index a4954a21be93..c116143335d9 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -70,11 +70,11 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
simple->num_clocks = ret;
ret = clk_bulk_prepare_enable(simple->num_clocks, simple->clks);
if (ret)
- goto err_resetc_assert;
+ goto err_clk_put_all;
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret)
- goto err_clk_put;
+ goto err_clk_disable;
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -82,8 +82,9 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
return 0;
-err_clk_put:
+err_clk_disable:
clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
+err_clk_put_all:
clk_bulk_put_all(simple->num_clocks, simple->clks);
err_resetc_assert:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index bc3fe31638b9..8a35a6901db7 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -4826,7 +4826,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
if (!dwc->gadget)
return;
- dwc3_enable_susphy(dwc, false);
+ dwc3_enable_susphy(dwc, true);
usb_del_gadget(dwc->gadget);
dwc3_gadget_free_endpoints(dwc);
usb_put_gadget(dwc->gadget);
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index cf6512ed17a6..96b588bd08cd 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -227,7 +227,7 @@ void dwc3_host_exit(struct dwc3 *dwc)
if (dwc->sys_wakeup)
device_init_wakeup(&dwc->xhci->dev, false);
- dwc3_enable_susphy(dwc, false);
+ dwc3_enable_susphy(dwc, true);
platform_device_unregister(dwc->xhci);
dwc->xhci = NULL;
}
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 1a7d3c4f652f..83c7e243dcf9 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3020,7 +3020,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (retval)
- return retval;
+ goto err_put_client;
udc->board = &lpc32xx_usbddata;
@@ -3038,28 +3038,32 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
/* Get IRQs */
for (i = 0; i < 4; i++) {
udc->udp_irq[i] = platform_get_irq(pdev, i);
- if (udc->udp_irq[i] < 0)
- return udc->udp_irq[i];
+ if (udc->udp_irq[i] < 0) {
+ retval = udc->udp_irq[i];
+ goto err_put_client;
+ }
}
udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->udp_baseaddr)) {
dev_err(udc->dev, "IO map failure\n");
- return PTR_ERR(udc->udp_baseaddr);
+ retval = PTR_ERR(udc->udp_baseaddr);
+ goto err_put_client;
}
/* Get USB device clock */
udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(udc->usb_slv_clk)) {
dev_err(udc->dev, "failed to acquire USB device clock\n");
- return PTR_ERR(udc->usb_slv_clk);
+ retval = PTR_ERR(udc->usb_slv_clk);
+ goto err_put_client;
}
/* Enable USB device clock */
retval = clk_prepare_enable(udc->usb_slv_clk);
if (retval < 0) {
dev_err(udc->dev, "failed to start USB device clock\n");
- return retval;
+ goto err_put_client;
}
/* Setup deferred workqueue data */
@@ -3080,7 +3084,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (!udc->udca_v_base) {
dev_err(udc->dev, "error getting UDCA region\n");
retval = -ENOMEM;
- goto i2c_fail;
+ goto err_disable_clk;
}
udc->udca_p_base = dma_handle;
dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n",
@@ -3093,7 +3097,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (!udc->dd_cache) {
dev_err(udc->dev, "error getting DD DMA region\n");
retval = -ENOMEM;
- goto dma_alloc_fail;
+ goto err_free_dma;
}
/* Clear USB peripheral and initialize gadget endpoints */
@@ -3107,14 +3111,14 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(udc->dev, "LP request irq %d failed\n",
udc->udp_irq[IRQ_USB_LP]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_HP],
lpc32xx_usb_hp_irq, 0, "udc_hp", udc);
if (retval < 0) {
dev_err(udc->dev, "HP request irq %d failed\n",
udc->udp_irq[IRQ_USB_HP]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_DEVDMA],
@@ -3122,7 +3126,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(udc->dev, "DEV request irq %d failed\n",
udc->udp_irq[IRQ_USB_DEVDMA]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
/* The transceiver interrupt is used for VBUS detection and will
@@ -3133,7 +3137,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(udc->dev, "VBUS request irq %d failed\n",
udc->udp_irq[IRQ_USB_ATX]);
- goto irq_req_fail;
+ goto err_destroy_pool;
}
/* Initialize wait queue */
@@ -3142,7 +3146,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
retval = usb_add_gadget_udc(dev, &udc->gadget);
if (retval < 0)
- goto add_gadget_fail;
+ goto err_destroy_pool;
dev_set_drvdata(dev, udc);
device_init_wakeup(dev, 1);
@@ -3154,14 +3158,16 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION);
return 0;
-add_gadget_fail:
-irq_req_fail:
+err_destroy_pool:
dma_pool_destroy(udc->dd_cache);
-dma_alloc_fail:
+err_free_dma:
dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
udc->udca_v_base, udc->udca_p_base);
-i2c_fail:
+err_disable_clk:
clk_disable_unprepare(udc->usb_slv_clk);
+err_put_client:
+ put_device(&udc->isp1301_i2c_client->dev);
+
dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
return retval;
@@ -3190,6 +3196,8 @@ static void lpc32xx_udc_remove(struct platform_device *pdev)
udc->udca_v_base, udc->udca_p_base);
clk_disable_unprepare(udc->usb_slv_clk);
+
+ put_device(&udc->isp1301_i2c_client->dev);
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 24d5a1dc5056..7663f2aa35e9 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -169,13 +169,13 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
- goto fail_disable;
+ goto err_put_client;
dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name);
if (usb_disabled()) {
dev_err(&pdev->dev, "USB is disabled\n");
ret = -ENODEV;
- goto fail_disable;
+ goto err_put_client;
}
/* Enable USB host clock */
@@ -183,7 +183,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
if (IS_ERR(usb_host_clk)) {
dev_err(&pdev->dev, "failed to acquire and start USB OHCI clock\n");
ret = PTR_ERR(usb_host_clk);
- goto fail_disable;
+ goto err_put_client;
}
isp1301_configure();
@@ -192,13 +192,13 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
if (!hcd) {
dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
ret = -ENOMEM;
- goto fail_disable;
+ goto err_put_client;
}
hcd->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(hcd->regs)) {
ret = PTR_ERR(hcd->regs);
- goto fail_resource;
+ goto err_put_hcd;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
@@ -206,7 +206,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = -ENXIO;
- goto fail_resource;
+ goto err_put_hcd;
}
ohci_nxp_start_hc();
@@ -220,9 +220,10 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
}
ohci_nxp_stop_hc();
-fail_resource:
+err_put_hcd:
usb_put_hcd(hcd);
-fail_disable:
+err_put_client:
+ put_device(&isp1301_i2c_client->dev);
isp1301_i2c_client = NULL;
return ret;
}
@@ -234,6 +235,7 @@ static void ohci_hcd_nxp_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
ohci_nxp_stop_hc();
usb_put_hcd(hcd);
+ put_device(&isp1301_i2c_client->dev);
isp1301_i2c_client = NULL;
}
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index 57cdda4e09c8..90282e51e23e 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -554,7 +554,7 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
* Hang up the TTY. This wakes up any blocked
* writers and causes subsequent writes to fail.
*/
- tty_vhangup(port->port.tty);
+ tty_port_tty_vhangup(&port->port);
tty_unregister_device(dbc_tty_driver, port->minor);
xhci_dbc_tty_exit_port(port);
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 40ac68e52cee..e266a47c4d48 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -988,6 +988,7 @@ static void fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ disable_delayed_work_sync(&fsl_otg_dev->otg_event);
usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index f9b5c411aee4..2940f0c84e1b 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -149,7 +149,12 @@ struct i2c_client *isp1301_get_client(struct device_node *node)
return client;
/* non-DT: only one ISP1301 chip supported */
- return isp1301_i2c_client;
+ if (isp1301_i2c_client) {
+ get_device(&isp1301_i2c_client->dev);
+ return isp1301_i2c_client;
+ }
+
+ return NULL;
}
EXPORT_SYMBOL_GPL(isp1301_get_client);
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 75fff2e4cbc6..56fc3ff5016f 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -713,11 +713,13 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
/* make sure pipe is not busy */
ret = usbhsp_pipe_barrier(pipe);
if (ret < 0) {
+ usbhsp_put_pipe(pipe);
dev_err(dev, "pipe setup failed %d\n", usbhs_pipe_number(pipe));
return NULL;
}
if (usbhsp_setup_pipecfg(pipe, is_host, dir_in, &pipecfg)) {
+ usbhsp_put_pipe(pipe);
dev_err(dev, "can't setup pipe\n");
return NULL;
}
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
index b695f5ba9a40..939a98c2d3f7 100644
--- a/drivers/usb/storage/unusual_uas.h
+++ b/drivers/usb/storage/unusual_uas.h
@@ -98,7 +98,7 @@ UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160,
US_FL_NO_ATA_1X),
/* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
-UNUSUAL_DEV(0x13fd, 0x3940, 0x0309, 0x0309,
+UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x0309,
"Initio Corporation",
"INIC-3069",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 8d111ad3b71b..d96ab106a980 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -766,12 +766,16 @@ int dp_altmode_probe(struct typec_altmode *alt)
if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) &
DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) &&
!(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) &
- DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo)))
+ DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo))) {
+ typec_altmode_put_plug(plug);
return -ENODEV;
+ }
dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL);
- if (!dp)
+ if (!dp) {
+ typec_altmode_put_plug(plug);
return -ENOMEM;
+ }
INIT_WORK(&dp->work, dp_altmode_work);
mutex_init(&dp->lock);
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
index 7fcb1e1de5d6..b812be4d0e67 100644
--- a/drivers/usb/typec/ucsi/Kconfig
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -96,6 +96,7 @@ config UCSI_LENOVO_YOGA_C630
config UCSI_HUAWEI_GAOKUN
tristate "UCSI Interface Driver for Huawei Matebook E Go"
depends on EC_HUAWEI_GAOKUN
+ depends on DRM || !DRM
select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE && OF
help
This driver enables UCSI support on the Huawei Matebook E Go tablet,
diff --git a/drivers/usb/typec/ucsi/cros_ec_ucsi.c b/drivers/usb/typec/ucsi/cros_ec_ucsi.c
index d753f2188e25..eed2a7d0ebc6 100644
--- a/drivers/usb/typec/ucsi/cros_ec_ucsi.c
+++ b/drivers/usb/typec/ucsi/cros_ec_ucsi.c
@@ -105,12 +105,13 @@ static int cros_ucsi_async_control(struct ucsi *ucsi, u64 cmd)
return 0;
}
-static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci)
+static int cros_ucsi_sync_control(struct ucsi *ucsi, u64 cmd, u32 *cci,
+ void *data, size_t size)
{
struct cros_ucsi_data *udata = ucsi_get_drvdata(ucsi);
int ret;
- ret = ucsi_sync_control_common(ucsi, cmd, cci);
+ ret = ucsi_sync_control_common(ucsi, cmd, cci, data, size);
switch (ret) {
case -EBUSY:
/* EC may return -EBUSY if CCI.busy is set.
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c
index 174f4d53b777..f3684ab787fe 100644
--- a/drivers/usb/typec/ucsi/debugfs.c
+++ b/drivers/usb/typec/ucsi/debugfs.c
@@ -37,9 +37,7 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_SET_USB:
case UCSI_SET_POWER_LEVEL:
case UCSI_READ_POWER_LEVEL:
- case UCSI_SET_PDOS:
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, val);
+ ret = ucsi_send_command(ucsi, val, NULL, 0);
break;
case UCSI_GET_CAPABILITY:
case UCSI_GET_CONNECTOR_CAPABILITY:
@@ -54,9 +52,9 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_GET_ATTENTION_VDO:
case UCSI_GET_CAM_CS:
case UCSI_GET_LPM_PPM_INFO:
- ucsi->message_in_size = sizeof(ucsi->debugfs->response);
- ret = ucsi_send_command(ucsi, val);
- memcpy(&ucsi->debugfs->response, ucsi->message_in, sizeof(ucsi->debugfs->response));
+ ret = ucsi_send_command(ucsi, val,
+ &ucsi->debugfs->response,
+ sizeof(ucsi->debugfs->response));
break;
default:
ret = -EOPNOTSUPP;
@@ -111,30 +109,6 @@ static int ucsi_vbus_volt_show(struct seq_file *m, void *v)
}
DEFINE_SHOW_ATTRIBUTE(ucsi_vbus_volt);
-static ssize_t ucsi_message_out_write(struct file *file,
- const char __user *data, size_t count, loff_t *ppos)
-{
- struct ucsi *ucsi = file->private_data;
- int ret;
-
- char *buf __free(kfree) = memdup_user_nul(data, count);
- if (IS_ERR(buf))
- return PTR_ERR(buf);
-
- ucsi->message_out_size = min(count / 2, UCSI_MAX_MESSAGE_OUT_LENGTH);
- ret = hex2bin(ucsi->message_out, buf, ucsi->message_out_size);
- if (ret)
- return ret;
-
- return count;
-}
-
-static const struct file_operations ucsi_message_out_fops = {
- .open = simple_open,
- .write = ucsi_message_out_write,
- .llseek = generic_file_llseek,
-};
-
void ucsi_debugfs_register(struct ucsi *ucsi)
{
ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
@@ -147,8 +121,6 @@ void ucsi_debugfs_register(struct ucsi *ucsi)
debugfs_create_file("peak_current", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_peak_curr_fops);
debugfs_create_file("avg_current", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_avg_curr_fops);
debugfs_create_file("vbus_voltage", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_vbus_volt_fops);
- debugfs_create_file("message_out", 0200, ucsi->debugfs->dentry, ucsi,
- &ucsi_message_out_fops);
}
void ucsi_debugfs_unregister(struct ucsi *ucsi)
diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c
index a09b4900ec76..8aae80b457d7 100644
--- a/drivers/usb/typec/ucsi/displayport.c
+++ b/drivers/usb/typec/ucsi/displayport.c
@@ -67,14 +67,11 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
}
command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(dp->con->num);
- ucsi->message_in_size = sizeof(cur);
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, &cur, sizeof(cur));
if (ret < 0) {
if (ucsi->version > 0x0100)
goto err_unlock;
cur = 0xff;
- } else {
- memcpy(&cur, ucsi->message_in, ucsi->message_in_size);
}
if (cur != 0xff) {
@@ -129,8 +126,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
}
command = UCSI_CMD_SET_NEW_CAM(dp->con->num, 0, dp->offset, 0);
- dp->con->ucsi->message_in_size = 0;
- ret = ucsi_send_command(dp->con->ucsi, command);
+ ret = ucsi_send_command(dp->con->ucsi, command, NULL, 0);
if (ret < 0)
goto out_unlock;
@@ -197,8 +193,7 @@ static int ucsi_displayport_configure(struct ucsi_dp *dp)
command = UCSI_CMD_SET_NEW_CAM(dp->con->num, 1, dp->offset, pins);
- dp->con->ucsi->message_in_size = 0;
- return ucsi_send_command(dp->con->ucsi, command);
+ return ucsi_send_command(dp->con->ucsi, command, NULL, 0);
}
static int ucsi_displayport_vdm(struct typec_altmode *alt,
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 9b3df776137a..a7b388dc7fa0 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -55,7 +55,8 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
}
EXPORT_SYMBOL_GPL(ucsi_notify_common);
-int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci)
+int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size)
{
bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI;
int ret;
@@ -67,20 +68,6 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci)
reinit_completion(&ucsi->complete);
- if (ucsi->message_out_size > 0) {
- if (!ucsi->ops->write_message_out) {
- ucsi->message_out_size = 0;
- ret = -EOPNOTSUPP;
- goto out_clear_bit;
- }
-
- ret = ucsi->ops->write_message_out(ucsi, ucsi->message_out,
- ucsi->message_out_size);
- ucsi->message_out_size = 0;
- if (ret)
- goto out_clear_bit;
- }
-
ret = ucsi->ops->async_control(ucsi, command);
if (ret)
goto out_clear_bit;
@@ -97,10 +84,9 @@ out_clear_bit:
if (!ret && cci)
ret = ucsi->ops->read_cci(ucsi, cci);
- if (!ret && ucsi->message_in_size > 0 &&
+ if (!ret && data &&
(*cci & UCSI_CCI_COMMAND_COMPLETE))
- ret = ucsi->ops->read_message_in(ucsi, ucsi->message_in,
- ucsi->message_in_size);
+ ret = ucsi->ops->read_message_in(ucsi, data, size);
return ret;
}
@@ -117,25 +103,23 @@ static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack)
ctrl |= UCSI_ACK_CONNECTOR_CHANGE;
}
- ucsi->message_in_size = 0;
- return ucsi->ops->sync_control(ucsi, ctrl, NULL);
+ return ucsi->ops->sync_control(ucsi, ctrl, NULL, NULL, 0);
}
-static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci, bool conn_ack)
+static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size, bool conn_ack)
{
int ret, err;
*cci = 0;
- if (ucsi->message_in_size > UCSI_MAX_DATA_LENGTH(ucsi))
+ if (size > UCSI_MAX_DATA_LENGTH(ucsi))
return -EINVAL;
- ret = ucsi->ops->sync_control(ucsi, command, cci);
+ ret = ucsi->ops->sync_control(ucsi, command, cci, data, size);
- if (*cci & UCSI_CCI_BUSY) {
- ucsi->message_in_size = 0;
- return ucsi_run_command(ucsi, UCSI_CANCEL, cci, false) ?: -EBUSY;
- }
+ if (*cci & UCSI_CCI_BUSY)
+ return ucsi_run_command(ucsi, UCSI_CANCEL, cci, NULL, 0, false) ?: -EBUSY;
if (ret)
return ret;
@@ -167,13 +151,10 @@ static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num)
int ret;
command = UCSI_GET_ERROR_STATUS | UCSI_CONNECTOR_NUMBER(connector_num);
- ucsi->message_in_size = sizeof(error);
- ret = ucsi_run_command(ucsi, command, &cci, false);
+ ret = ucsi_run_command(ucsi, command, &cci, &error, sizeof(error), false);
if (ret < 0)
return ret;
- memcpy(&error, ucsi->message_in, sizeof(error));
-
switch (error) {
case UCSI_ERROR_INCOMPATIBLE_PARTNER:
return -EOPNOTSUPP;
@@ -219,7 +200,8 @@ static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num)
return -EIO;
}
-static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack)
+static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd,
+ void *data, size_t size, bool conn_ack)
{
u8 connector_num;
u32 cci;
@@ -247,7 +229,7 @@ static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack)
mutex_lock(&ucsi->ppm_lock);
- ret = ucsi_run_command(ucsi, cmd, &cci, conn_ack);
+ ret = ucsi_run_command(ucsi, cmd, &cci, data, size, conn_ack);
if (cci & UCSI_CCI_ERROR)
ret = ucsi_read_error(ucsi, connector_num);
@@ -256,9 +238,10 @@ static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd, bool conn_ack)
return ret;
}
-int ucsi_send_command(struct ucsi *ucsi, u64 command)
+int ucsi_send_command(struct ucsi *ucsi, u64 command,
+ void *data, size_t size)
{
- return ucsi_send_command_common(ucsi, command, false);
+ return ucsi_send_command_common(ucsi, command, data, size, false);
}
EXPORT_SYMBOL_GPL(ucsi_send_command);
@@ -336,8 +319,7 @@ void ucsi_altmode_update_active(struct ucsi_connector *con)
int i;
command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(con->num);
- con->ucsi->message_in_size = sizeof(cur);
- ret = ucsi_send_command(con->ucsi, command);
+ ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur));
if (ret < 0) {
if (con->ucsi->version > 0x0100) {
dev_err(con->ucsi->dev,
@@ -345,8 +327,6 @@ void ucsi_altmode_update_active(struct ucsi_connector *con)
return;
}
cur = 0xff;
- } else {
- memcpy(&cur, con->ucsi->message_in, sizeof(cur));
}
if (cur < UCSI_MAX_ALTMODES)
@@ -530,8 +510,7 @@ ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient)
command |= UCSI_GET_ALTMODE_RECIPIENT(recipient);
command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num);
command |= UCSI_GET_ALTMODE_OFFSET(i);
- ucsi->message_in_size = sizeof(alt);
- len = ucsi_send_command(con->ucsi, command);
+ len = ucsi_send_command(con->ucsi, command, &alt, sizeof(alt));
/*
* We are collecting all altmodes first and then registering.
* Some type-C device will return zero length data beyond last
@@ -540,8 +519,6 @@ ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient)
if (len < 0)
return len;
- memcpy(&alt, ucsi->message_in, sizeof(alt));
-
/* We got all altmodes, now break out and register them */
if (!len || !alt.svid)
break;
@@ -609,15 +586,12 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient)
command |= UCSI_GET_ALTMODE_RECIPIENT(recipient);
command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num);
command |= UCSI_GET_ALTMODE_OFFSET(i);
- con->ucsi->message_in_size = sizeof(alt);
- len = ucsi_send_command(con->ucsi, command);
+ len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt));
if (len == -EBUSY)
continue;
if (len <= 0)
return len;
- memcpy(&alt, con->ucsi->message_in, sizeof(alt));
-
/*
* This code is requesting one alt mode at a time, but some PPMs
* may still return two. If that happens both alt modes need be
@@ -685,9 +659,7 @@ static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
UCSI_MAX_DATA_LENGTH(con->ucsi));
int ret;
- con->ucsi->message_in_size = size;
- ret = ucsi_send_command_common(con->ucsi, command, conn_ack);
- memcpy(&con->status, con->ucsi->message_in, size);
+ ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);
return ret < 0 ? ret : 0;
}
@@ -710,9 +682,8 @@ static int ucsi_read_pdos(struct ucsi_connector *con,
command |= UCSI_GET_PDOS_PDO_OFFSET(offset);
command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1);
command |= is_source(role) ? UCSI_GET_PDOS_SRC_PDOS : 0;
- ucsi->message_in_size = num_pdos * sizeof(u32);
- ret = ucsi_send_command(ucsi, command);
- memcpy(pdos + offset, ucsi->message_in, num_pdos * sizeof(u32));
+ ret = ucsi_send_command(ucsi, command, pdos + offset,
+ num_pdos * sizeof(u32));
if (ret < 0 && ret != -ETIMEDOUT)
dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret);
@@ -799,9 +770,7 @@ static int ucsi_get_pd_message(struct ucsi_connector *con, u8 recipient,
command |= UCSI_GET_PD_MESSAGE_BYTES(len);
command |= UCSI_GET_PD_MESSAGE_TYPE(type);
- con->ucsi->message_in_size = len;
- ret = ucsi_send_command(con->ucsi, command);
- memcpy(data + offset, con->ucsi->message_in, len);
+ ret = ucsi_send_command(con->ucsi, command, data + offset, len);
if (ret < 0)
return ret;
}
@@ -966,9 +935,7 @@ static int ucsi_register_cable(struct ucsi_connector *con)
int ret;
command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num);
- con->ucsi->message_in_size = sizeof(cable_prop);
- ret = ucsi_send_command(con->ucsi, command);
- memcpy(&cable_prop, con->ucsi->message_in, sizeof(cable_prop));
+ ret = ucsi_send_command(con->ucsi, command, &cable_prop, sizeof(cable_prop));
if (ret < 0) {
dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n", ret);
return ret;
@@ -1029,9 +996,7 @@ static int ucsi_check_connector_capability(struct ucsi_connector *con)
return 0;
command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
- con->ucsi->message_in_size = sizeof(con->cap);
- ret = ucsi_send_command(con->ucsi, command);
- memcpy(&con->cap, con->ucsi->message_in, sizeof(con->cap));
+ ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
if (ret < 0) {
dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
return ret;
@@ -1415,8 +1380,7 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard)
else if (con->ucsi->version >= UCSI_VERSION_2_0)
command |= hard ? 0 : UCSI_CONNECTOR_RESET_DATA_VER_2_0;
- con->ucsi->message_in_size = 0;
- return ucsi_send_command(con->ucsi, command);
+ return ucsi_send_command(con->ucsi, command, NULL, 0);
}
static int ucsi_reset_ppm(struct ucsi *ucsi)
@@ -1497,8 +1461,7 @@ static int ucsi_role_cmd(struct ucsi_connector *con, u64 command)
{
int ret;
- con->ucsi->message_in_size = 0;
- ret = ucsi_send_command(con->ucsi, command);
+ ret = ucsi_send_command(con->ucsi, command, NULL, 0);
if (ret == -ETIMEDOUT) {
u64 c;
@@ -1506,8 +1469,7 @@ static int ucsi_role_cmd(struct ucsi_connector *con, u64 command)
ucsi_reset_ppm(con->ucsi);
c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy;
- con->ucsi->message_in_size = 0;
- ucsi_send_command(con->ucsi, c);
+ ucsi_send_command(con->ucsi, c, NULL, 0);
ucsi_reset_connector(con, true);
}
@@ -1660,13 +1622,10 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
/* Get connector capability */
command = UCSI_GET_CONNECTOR_CAPABILITY;
command |= UCSI_CONNECTOR_NUMBER(con->num);
- ucsi->message_in_size = sizeof(con->cap);
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap));
if (ret < 0)
goto out_unlock;
- memcpy(&con->cap, ucsi->message_in, sizeof(con->cap));
-
if (UCSI_CONCAP(con, OPMODE_DRP))
cap->data = TYPEC_PORT_DRD;
else if (UCSI_CONCAP(con, OPMODE_DFP))
@@ -1863,20 +1822,17 @@ static int ucsi_init(struct ucsi *ucsi)
/* Enable basic notifications */
ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
goto err_reset;
/* Get PPM capabilities */
command = UCSI_GET_CAPABILITY;
- ucsi->message_in_size = BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE);
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, &ucsi->cap,
+ BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE));
if (ret < 0)
goto err_reset;
- memcpy(&ucsi->cap, ucsi->message_in, BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE));
-
if (!ucsi->cap.num_connectors) {
ret = -ENODEV;
goto err_reset;
@@ -1906,8 +1862,7 @@ static int ucsi_init(struct ucsi *ucsi)
/* Enable all supported notifications */
ntfy = ucsi_get_supported_notifications(ucsi);
command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
goto err_unregister;
@@ -1958,8 +1913,7 @@ static void ucsi_resume_work(struct work_struct *work)
/* Restore UCSI notification enable mask after system resume */
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
- ucsi->message_in_size = 0;
- ret = ucsi_send_command(ucsi, command);
+ ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0) {
dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n", ret);
return;
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index f946b728c373..410389ef173a 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -29,10 +29,6 @@ struct dentry;
#define UCSI_MESSAGE_OUT 32
#define UCSIv2_MESSAGE_OUT 272
-/* Define maximum lengths for message buffers */
-#define UCSI_MAX_MESSAGE_IN_LENGTH 256
-#define UCSI_MAX_MESSAGE_OUT_LENGTH 256
-
/* UCSI versions */
#define UCSI_VERSION_1_0 0x0100
#define UCSI_VERSION_1_1 0x0110
@@ -69,7 +65,6 @@ struct dentry;
* @read_cci: Read CCI register
* @poll_cci: Read CCI register while polling with notifications disabled
* @read_message_in: Read message data from UCSI
- * @write_message_out: Write message data to UCSI
* @sync_control: Blocking control operation
* @async_control: Non-blocking control operation
* @update_altmodes: Squashes duplicate DP altmodes
@@ -85,8 +80,8 @@ struct ucsi_operations {
int (*read_cci)(struct ucsi *ucsi, u32 *cci);
int (*poll_cci)(struct ucsi *ucsi, u32 *cci);
int (*read_message_in)(struct ucsi *ucsi, void *val, size_t val_len);
- int (*write_message_out)(struct ucsi *ucsi, void *data, size_t data_len);
- int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci);
+ int (*sync_control)(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size);
int (*async_control)(struct ucsi *ucsi, u64 command);
bool (*update_altmodes)(struct ucsi *ucsi, u8 recipient,
struct ucsi_altmode *orig,
@@ -137,7 +132,6 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
#define UCSI_GET_PD_MESSAGE 0x15
#define UCSI_GET_CAM_CS 0x18
#define UCSI_SET_SINK_PATH 0x1c
-#define UCSI_SET_PDOS 0x1d
#define UCSI_READ_POWER_LEVEL 0x1e
#define UCSI_SET_USB 0x21
#define UCSI_GET_LPM_PPM_INFO 0x22
@@ -499,12 +493,6 @@ struct ucsi {
unsigned long quirks;
#define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */
#define UCSI_DELAY_DEVICE_PDOS BIT(1) /* Reading PDOs fails until the parter is in PD mode */
-
- /* Fixed-size buffers for incoming and outgoing messages */
- u8 message_in[UCSI_MAX_MESSAGE_IN_LENGTH];
- size_t message_in_size;
- u8 message_out[UCSI_MAX_MESSAGE_OUT_LENGTH];
- size_t message_out_size;
};
#define UCSI_MAX_DATA_LENGTH(u) (((u)->version < UCSI_VERSION_2_0) ? 0x10 : 0xff)
@@ -567,13 +555,15 @@ struct ucsi_connector {
struct usb_pd_identity cable_identity;
};
-int ucsi_send_command(struct ucsi *ucsi, u64 command);
+int ucsi_send_command(struct ucsi *ucsi, u64 command,
+ void *retval, size_t size);
void ucsi_altmode_update_active(struct ucsi_connector *con);
int ucsi_resume(struct ucsi *ucsi);
void ucsi_notify_common(struct ucsi *ucsi, u32 cci);
-int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci);
+int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size);
#if IS_ENABLED(CONFIG_POWER_SUPPLY)
int ucsi_register_port_psy(struct ucsi_connector *con);
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index f9beeb835238..6b92f296e985 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -86,21 +86,6 @@ static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_le
return 0;
}
-static int ucsi_acpi_write_message_out(struct ucsi *ucsi, void *data, size_t data_len)
-{
- struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
-
- if (!data || !data_len)
- return -EINVAL;
-
- if (ucsi->version <= UCSI_VERSION_1_2)
- memcpy(ua->base + UCSI_MESSAGE_OUT, data, data_len);
- else
- memcpy(ua->base + UCSIv2_MESSAGE_OUT, data, data_len);
-
- return 0;
-}
-
static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command)
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
@@ -116,19 +101,19 @@ static const struct ucsi_operations ucsi_acpi_ops = {
.read_cci = ucsi_acpi_read_cci,
.poll_cci = ucsi_acpi_poll_cci,
.read_message_in = ucsi_acpi_read_message_in,
- .write_message_out = ucsi_acpi_write_message_out,
.sync_control = ucsi_sync_control_common,
.async_control = ucsi_acpi_async_control
};
-static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
+static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *val, size_t len)
{
u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE |
UCSI_CONSTAT_PDOS_CHANGE;
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
- ret = ucsi_sync_control_common(ucsi, command, cci);
+ ret = ucsi_sync_control_common(ucsi, command, cci, val, len);
if (ret < 0)
return ret;
@@ -140,8 +125,8 @@ static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS &&
ua->check_bogus_event) {
/* Clear the bogus change */
- if (*(u16 *)ucsi->message_in == bogus_change)
- *(u16 *)ucsi->message_in = 0;
+ if (*(u16 *)val == bogus_change)
+ *(u16 *)val = 0;
ua->check_bogus_event = false;
}
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index ead1b2a25c79..d83a0051c737 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -606,7 +606,8 @@ static int ucsi_ccg_async_control(struct ucsi *ucsi, u64 command)
return ccg_write(uc, reg, (u8 *)&command, sizeof(command));
}
-static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
+static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci,
+ void *data, size_t size)
{
struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
struct ucsi_connector *con;
@@ -628,16 +629,16 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
ucsi_ccg_update_set_new_cam_cmd(uc, con, &command);
}
- ret = ucsi_sync_control_common(ucsi, command, cci);
+ ret = ucsi_sync_control_common(ucsi, command, cci, data, size);
switch (UCSI_COMMAND(command)) {
case UCSI_GET_CURRENT_CAM:
if (uc->has_multiple_dp)
- ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)ucsi->message_in);
+ ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)data);
break;
case UCSI_GET_ALTERNATE_MODES:
if (UCSI_ALTMODE_RECIPIENT(command) == UCSI_RECIPIENT_SOP) {
- struct ucsi_altmode *alt = (struct ucsi_altmode *)ucsi->message_in;
+ struct ucsi_altmode *alt = data;
if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID)
ucsi_ccg_nvidia_altmode(uc, alt, command);
@@ -645,7 +646,7 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command, u32 *cci)
break;
case UCSI_GET_CAPABILITY:
if (uc->fw_build == CCG_FW_BUILD_NVIDIA_TEGRA) {
- struct ucsi_capability *cap = (struct ucsi_capability *)ucsi->message_in;
+ struct ucsi_capability *cap = data;
cap->features &= ~UCSI_CAP_ALT_MODE_DETAILS;
}
diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
index 299081444caa..0187c1c4b21a 100644
--- a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
+++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c
@@ -88,7 +88,8 @@ static int yoga_c630_ucsi_async_control(struct ucsi *ucsi, u64 command)
static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi,
u64 command,
- u32 *cci)
+ u32 *cci,
+ void *data, size_t size)
{
int ret;
@@ -106,8 +107,8 @@ static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi,
};
dev_dbg(ucsi->dev, "faking DP altmode for con1\n");
- memset(ucsi->message_in, 0, ucsi->message_in_size);
- memcpy(ucsi->message_in, &alt, min(sizeof(alt), ucsi->message_in_size));
+ memset(data, 0, size);
+ memcpy(data, &alt, min(sizeof(alt), size));
*cci = UCSI_CCI_COMMAND_COMPLETE | UCSI_SET_CCI_LENGTH(sizeof(alt));
return 0;
}
@@ -120,18 +121,18 @@ static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi,
if (UCSI_COMMAND(command) == UCSI_GET_ALTERNATE_MODES &&
UCSI_GET_ALTMODE_GET_CONNECTOR_NUMBER(command) == 2) {
dev_dbg(ucsi->dev, "ignoring altmodes for con2\n");
- memset(ucsi->message_in, 0, ucsi->message_in_size);
+ memset(data, 0, size);
*cci = UCSI_CCI_COMMAND_COMPLETE;
return 0;
}
- ret = ucsi_sync_control_common(ucsi, command, cci);
+ ret = ucsi_sync_control_common(ucsi, command, cci, data, size);
if (ret < 0)
return ret;
/* UCSI_GET_CURRENT_CAM is off-by-one on all ports */
- if (UCSI_COMMAND(command) == UCSI_GET_CURRENT_CAM && ucsi->message_in_size > 0)
- ucsi->message_in[0]--;
+ if (UCSI_COMMAND(command) == UCSI_GET_CURRENT_CAM && data)
+ ((u8 *)data)[0]--;
return ret;
}
diff --git a/drivers/vfio/pci/nvgrace-gpu/main.c b/drivers/vfio/pci/nvgrace-gpu/main.c
index 84d142a47ec6..b45a24d00387 100644
--- a/drivers/vfio/pci/nvgrace-gpu/main.c
+++ b/drivers/vfio/pci/nvgrace-gpu/main.c
@@ -561,7 +561,7 @@ nvgrace_gpu_map_and_read(struct nvgrace_gpu_pci_core_device *nvdev,
ret = vfio_pci_core_do_io_rw(&nvdev->core_device, false,
nvdev->resmem.ioaddr,
buf, offset, mem_count,
- 0, 0, false);
+ 0, 0, false, VFIO_PCI_IO_WIDTH_8);
}
return ret;
@@ -693,7 +693,7 @@ nvgrace_gpu_map_and_write(struct nvgrace_gpu_pci_core_device *nvdev,
ret = vfio_pci_core_do_io_rw(&nvdev->core_device, false,
nvdev->resmem.ioaddr,
(char __user *)buf, pos, mem_count,
- 0, 0, true);
+ 0, 0, true, VFIO_PCI_IO_WIDTH_8);
}
return ret;
diff --git a/drivers/vfio/pci/pds/dirty.c b/drivers/vfio/pci/pds/dirty.c
index 481992142f79..4915a7c1c491 100644
--- a/drivers/vfio/pci/pds/dirty.c
+++ b/drivers/vfio/pci/pds/dirty.c
@@ -292,8 +292,11 @@ static int pds_vfio_dirty_enable(struct pds_vfio_pci_device *pds_vfio,
len = num_ranges * sizeof(*region_info);
node = interval_tree_iter_first(ranges, 0, ULONG_MAX);
- if (!node)
- return -EINVAL;
+ if (!node) {
+ err = -EINVAL;
+ goto out_free_region_info;
+ }
+
for (int i = 0; i < num_ranges; i++) {
struct pds_lm_dirty_region_info *ri = &region_info[i];
u64 region_size = node->last - node->start + 1;
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index 6192788c8ba3..b38627b35c35 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -135,7 +135,8 @@ VFIO_IORDWR(64)
ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
void __iomem *io, char __user *buf,
loff_t off, size_t count, size_t x_start,
- size_t x_end, bool iswrite)
+ size_t x_end, bool iswrite,
+ enum vfio_pci_io_width max_width)
{
ssize_t done = 0;
int ret;
@@ -150,20 +151,19 @@ ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
else
fillable = 0;
- if (fillable >= 8 && !(off % 8)) {
+ if (fillable >= 8 && !(off % 8) && max_width >= 8) {
ret = vfio_pci_iordwr64(vdev, iswrite, test_mem,
io, buf, off, &filled);
if (ret)
return ret;
- } else
- if (fillable >= 4 && !(off % 4)) {
+ } else if (fillable >= 4 && !(off % 4) && max_width >= 4) {
ret = vfio_pci_iordwr32(vdev, iswrite, test_mem,
io, buf, off, &filled);
if (ret)
return ret;
- } else if (fillable >= 2 && !(off % 2)) {
+ } else if (fillable >= 2 && !(off % 2) && max_width >= 2) {
ret = vfio_pci_iordwr16(vdev, iswrite, test_mem,
io, buf, off, &filled);
if (ret)
@@ -234,6 +234,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
void __iomem *io;
struct resource *res = &vdev->pdev->resource[bar];
ssize_t done;
+ enum vfio_pci_io_width max_width = VFIO_PCI_IO_WIDTH_8;
if (pci_resource_start(pdev, bar))
end = pci_resource_len(pdev, bar);
@@ -262,6 +263,16 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
if (!io)
return -ENOMEM;
x_end = end;
+
+ /*
+ * Certain devices (e.g. Intel X710) don't support qword
+ * access to the ROM bar. Otherwise PCI AER errors might be
+ * triggered.
+ *
+ * Disable qword access to the ROM bar universally, which
+ * worked reliably for years before qword access is enabled.
+ */
+ max_width = VFIO_PCI_IO_WIDTH_4;
} else {
int ret = vfio_pci_core_setup_barmap(vdev, bar);
if (ret) {
@@ -278,7 +289,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
}
done = vfio_pci_core_do_io_rw(vdev, res->flags & IORESOURCE_MEM, io, buf, pos,
- count, x_start, x_end, iswrite);
+ count, x_start, x_end, iswrite, max_width);
if (done >= 0)
*ppos += done;
@@ -352,7 +363,7 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
* to the memory enable bit in the command register.
*/
done = vfio_pci_core_do_io_rw(vdev, false, iomem, buf, off, count,
- 0, 0, iswrite);
+ 0, 0, iswrite, VFIO_PCI_IO_WIDTH_4);
vga_put(vdev->pdev, rsrc);
diff --git a/drivers/vfio/pci/xe/main.c b/drivers/vfio/pci/xe/main.c
index 0156b53c678b..2a5eb9260ec7 100644
--- a/drivers/vfio/pci/xe/main.c
+++ b/drivers/vfio/pci/xe/main.c
@@ -250,6 +250,7 @@ xe_vfio_pci_alloc_file(struct xe_vfio_pci_core_device *xe_vdev,
struct xe_vfio_pci_migration_file *migf;
const struct file_operations *fops;
int flags;
+ int ret;
migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
if (!migf)
@@ -259,8 +260,9 @@ xe_vfio_pci_alloc_file(struct xe_vfio_pci_core_device *xe_vdev,
flags = type == XE_VFIO_FILE_SAVE ? O_RDONLY : O_WRONLY;
migf->filp = anon_inode_getfile("xe_vfio_mig", fops, migf, flags);
if (IS_ERR(migf->filp)) {
+ ret = PTR_ERR(migf->filp);
kfree(migf);
- return ERR_CAST(migf->filp);
+ return ERR_PTR(ret);
}
mutex_init(&migf->lock);
@@ -504,6 +506,7 @@ static const struct vfio_device_ops xe_vfio_pci_ops = {
.open_device = xe_vfio_pci_open_device,
.close_device = xe_vfio_pci_close_device,
.ioctl = vfio_pci_core_ioctl,
+ .get_region_info_caps = vfio_pci_ioctl_get_region_info,
.device_feature = vfio_pci_core_ioctl_feature,
.read = vfio_pci_core_read,
.write = vfio_pci_core_write,
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 0298ddc34824..552cfb53498a 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -66,14 +66,15 @@ static u32 vhost_transport_get_local_cid(void)
return VHOST_VSOCK_DEFAULT_HOST_CID;
}
-/* Callers that dereference the return value must hold vhost_vsock_mutex or the
- * RCU read lock.
+/* Callers must be in an RCU read section or hold the vhost_vsock_mutex.
+ * The return value can only be dereferenced while within the section.
*/
static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
{
struct vhost_vsock *vsock;
- hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid) {
+ hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid,
+ lockdep_is_held(&vhost_vsock_mutex)) {
u32 other_cid = vsock->guest_cid;
/* Skip instances that have no CID yet */
@@ -709,9 +710,15 @@ static void vhost_vsock_reset_orphans(struct sock *sk)
* executing.
*/
+ rcu_read_lock();
+
/* If the peer is still valid, no need to reset connection */
- if (vhost_vsock_get(vsk->remote_addr.svm_cid))
+ if (vhost_vsock_get(vsk->remote_addr.svm_cid)) {
+ rcu_read_unlock();
return;
+ }
+
+ rcu_read_unlock();
/* If the close timeout is pending, let it expire. This avoids races
* with the timeout callback.
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 7a501e73d880..1abc7ed2990e 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2019,13 +2019,14 @@ out:
else
btrfs_delalloc_release_space(inode, data_reserved, page_start,
reserved_space, true);
- extent_changeset_free(data_reserved);
out_noreserve:
if (only_release_metadata)
btrfs_check_nocow_unlock(inode);
sb_end_pagefault(inode->vfs_inode.i_sb);
+ extent_changeset_free(data_reserved);
+
if (ret < 0)
return vmf_error(ret);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c4bee47829ed..317db7d10a21 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -256,6 +256,7 @@ static void print_data_reloc_error(const struct btrfs_inode *inode, u64 file_off
if (ret < 0) {
btrfs_err_rl(fs_info, "failed to lookup extent item for logical %llu: %d",
logical, ret);
+ btrfs_release_path(&path);
return;
}
eb = path.nodes[0];
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 9e2b53e90dcb..d9d8d9968a58 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1243,14 +1243,7 @@ out:
btrfs_end_transaction(trans);
else if (trans)
ret = btrfs_end_transaction(trans);
-
- /*
- * At this point we either failed at allocating prealloc, or we
- * succeeded and passed the ownership to it to add_qgroup_rb(). In any
- * case, this needs to be NULL or there is something wrong.
- */
- ASSERT(prealloc == NULL);
-
+ kfree(prealloc);
return ret;
}
@@ -1682,12 +1675,7 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
out:
mutex_unlock(&fs_info->qgroup_ioctl_lock);
- /*
- * At this point we either failed at allocating prealloc, or we
- * succeeded and passed the ownership to it to add_qgroup_rb(). In any
- * case, this needs to be NULL or there is something wrong.
- */
- ASSERT(prealloc == NULL);
+ kfree(prealloc);
return ret;
}
@@ -3279,7 +3267,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
struct btrfs_root *quota_root;
struct btrfs_qgroup *srcgroup;
struct btrfs_qgroup *dstgroup;
- struct btrfs_qgroup *prealloc = NULL;
+ struct btrfs_qgroup *prealloc;
struct btrfs_qgroup_list **qlist_prealloc = NULL;
bool free_inherit = false;
bool need_rescan = false;
@@ -3520,14 +3508,7 @@ out:
}
if (free_inherit)
kfree(inherit);
-
- /*
- * At this point we either failed at allocating prealloc, or we
- * succeeded and passed the ownership to it to add_qgroup_rb(). In any
- * case, this needs to be NULL or there is something wrong.
- */
- ASSERT(prealloc == NULL);
-
+ kfree(prealloc);
return ret;
}
diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c
index 05cfda8af422..e9124605974b 100644
--- a/fs/btrfs/tests/qgroup-tests.c
+++ b/fs/btrfs/tests/qgroup-tests.c
@@ -187,7 +187,6 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
if (ret) {
test_err("couldn't find backref %d", ret);
- btrfs_free_path(path);
return ret;
}
btrfs_del_item(&trans, root, path);
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index fff37c8d96a4..31edc93a383e 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -5865,14 +5865,6 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
struct btrfs_inode *curr_inode = start_inode;
int ret = 0;
- /*
- * If we are logging a new name, as part of a link or rename operation,
- * don't bother logging new dentries, as we just want to log the names
- * of an inode and that any new parents exist.
- */
- if (ctx->logging_new_name)
- return 0;
-
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
@@ -6051,6 +6043,33 @@ static int conflicting_inode_is_dir(struct btrfs_root *root, u64 ino,
return ret;
}
+static bool can_log_conflicting_inode(const struct btrfs_trans_handle *trans,
+ const struct btrfs_inode *inode)
+{
+ if (!S_ISDIR(inode->vfs_inode.i_mode))
+ return true;
+
+ if (inode->last_unlink_trans < trans->transid)
+ return true;
+
+ /*
+ * If this is a directory and its unlink_trans is not from a past
+ * transaction then we must fallback to a transaction commit in order
+ * to avoid getting a directory with 2 hard links after log replay.
+ *
+ * This happens if a directory A is renamed, moved from one parent
+ * directory to another one, a new file is created in the old parent
+ * directory with the old name of our directory A, the new file is
+ * fsynced, then we moved the new file to some other parent directory
+ * and fsync again the new file. This results in a log tree where we
+ * logged that directory A existed, with the INODE_REF item for the
+ * new location but without having logged its old parent inode, so
+ * that on log replay we add a new link for the new location but the
+ * old link remains, resulting in a link count of 2.
+ */
+ return false;
+}
+
static int add_conflicting_inode(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path,
@@ -6154,6 +6173,11 @@ static int add_conflicting_inode(struct btrfs_trans_handle *trans,
return 0;
}
+ if (!can_log_conflicting_inode(trans, inode)) {
+ btrfs_add_delayed_iput(inode);
+ return BTRFS_LOG_FORCE_COMMIT;
+ }
+
btrfs_add_delayed_iput(inode);
ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS);
@@ -6218,6 +6242,12 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
break;
}
+ if (!can_log_conflicting_inode(trans, inode)) {
+ btrfs_add_delayed_iput(inode);
+ ret = BTRFS_LOG_FORCE_COMMIT;
+ break;
+ }
+
/*
* Always log the directory, we cannot make this
* conditional on need_log_inode() because the directory
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index ae1742a35e76..13c514684cfb 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -7128,6 +7128,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
fs_devices->seeding = true;
fs_devices->opened = 1;
+ list_add(&fs_devices->seed_list, &fs_info->fs_devices->seed_list);
return fs_devices;
}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 4b263c328ed2..4005d21cf009 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -841,8 +841,10 @@ int __printf(2, 3) debugfs_change_name(struct dentry *dentry, const char *fmt, .
rd.new_parent = rd.old_parent;
rd.flags = RENAME_NOREPLACE;
target = lookup_noperm_unlocked(&QSTR(new_name), rd.new_parent);
- if (IS_ERR(target))
- return PTR_ERR(target);
+ if (IS_ERR(target)) {
+ error = PTR_ERR(target);
+ goto out_free;
+ }
error = start_renaming_two_dentries(&rd, dentry, target);
if (error) {
@@ -862,6 +864,7 @@ int __printf(2, 3) debugfs_change_name(struct dentry *dentry, const char *fmt, .
out:
dput(rd.old_parent);
dput(target);
+out_free:
kfree_const(new_name);
return error;
}
diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
index 65da21504632..3d31f7840ca0 100644
--- a/fs/erofs/zdata.c
+++ b/fs/erofs/zdata.c
@@ -1262,7 +1262,7 @@ static int z_erofs_parse_in_bvecs(struct z_erofs_backend *be, bool *overlapped)
return err;
}
-static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err)
+static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, bool eio)
{
struct erofs_sb_info *const sbi = EROFS_SB(be->sb);
struct z_erofs_pcluster *pcl = be->pcl;
@@ -1270,7 +1270,7 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err)
const struct z_erofs_decompressor *alg =
z_erofs_decomp[pcl->algorithmformat];
bool try_free = true;
- int i, j, jtop, err2;
+ int i, j, jtop, err2, err = eio ? -EIO : 0;
struct page *page;
bool overlapped;
const char *reason;
@@ -1413,12 +1413,12 @@ static int z_erofs_decompress_queue(const struct z_erofs_decompressqueue *io,
.pcl = io->head,
};
struct z_erofs_pcluster *next;
- int err = io->eio ? -EIO : 0;
+ int err = 0;
for (; be.pcl != Z_EROFS_PCLUSTER_TAIL; be.pcl = next) {
DBG_BUGON(!be.pcl);
next = READ_ONCE(be.pcl->next);
- err = z_erofs_decompress_pcluster(&be, err) ?: err;
+ err = z_erofs_decompress_pcluster(&be, io->eio) ?: err;
}
return err;
}
diff --git a/fs/file_attr.c b/fs/file_attr.c
index 4c4916632f11..13cdb31a3e94 100644
--- a/fs/file_attr.c
+++ b/fs/file_attr.c
@@ -2,6 +2,7 @@
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/fscrypt.h>
+#include <linux/fsnotify.h>
#include <linux/fileattr.h>
#include <linux/export.h>
#include <linux/syscalls.h>
@@ -298,6 +299,7 @@ int vfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
err = inode->i_op->fileattr_set(idmap, dentry, fa);
if (err)
goto out;
+ fsnotify_xattr(dentry);
}
out:
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 5c0efd6b239f..29baeeb97871 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -681,8 +681,10 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
return kn;
err_out4:
- simple_xattrs_free(&kn->iattr->xattrs, NULL);
- kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
+ if (kn->iattr) {
+ simple_xattrs_free(&kn->iattr->xattrs, NULL);
+ kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
+ }
err_out3:
spin_lock(&root->kernfs_idr_lock);
idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
diff --git a/fs/libfs.c b/fs/libfs.c
index 9264523be85c..591eb649ebba 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -346,22 +346,22 @@ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry)
* User space expects the directory offset value of the replaced
* (new) directory entry to be unchanged after a rename.
*
- * Returns zero on success, a negative errno value on failure.
+ * Caller must have grabbed a slot for new_dentry in the maple_tree
+ * associated with new_dir, even if dentry is negative.
*/
-int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+void simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir);
struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir);
long new_offset = dentry2offset(new_dentry);
- simple_offset_remove(old_ctx, old_dentry);
+ if (WARN_ON(!new_offset))
+ return;
- if (new_offset) {
- offset_set(new_dentry, 0);
- return simple_offset_replace(new_ctx, old_dentry, new_offset);
- }
- return simple_offset_add(new_ctx, old_dentry);
+ simple_offset_remove(old_ctx, old_dentry);
+ offset_set(new_dentry, 0);
+ WARN_ON(simple_offset_replace(new_ctx, old_dentry, new_offset));
}
/**
@@ -388,31 +388,23 @@ int simple_offset_rename_exchange(struct inode *old_dir,
long new_index = dentry2offset(new_dentry);
int ret;
- simple_offset_remove(old_ctx, old_dentry);
- simple_offset_remove(new_ctx, new_dentry);
+ if (WARN_ON(!old_index || !new_index))
+ return -EINVAL;
- ret = simple_offset_replace(new_ctx, old_dentry, new_index);
- if (ret)
- goto out_restore;
+ ret = mtree_store(&new_ctx->mt, new_index, old_dentry, GFP_KERNEL);
+ if (WARN_ON(ret))
+ return ret;
- ret = simple_offset_replace(old_ctx, new_dentry, old_index);
- if (ret) {
- simple_offset_remove(new_ctx, old_dentry);
- goto out_restore;
+ ret = mtree_store(&old_ctx->mt, old_index, new_dentry, GFP_KERNEL);
+ if (WARN_ON(ret)) {
+ mtree_store(&new_ctx->mt, new_index, new_dentry, GFP_KERNEL);
+ return ret;
}
- ret = simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);
- if (ret) {
- simple_offset_remove(new_ctx, old_dentry);
- simple_offset_remove(old_ctx, new_dentry);
- goto out_restore;
- }
+ offset_set(old_dentry, new_index);
+ offset_set(new_dentry, old_index);
+ simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);
return 0;
-
-out_restore:
- (void)simple_offset_replace(old_ctx, old_dentry, old_index);
- (void)simple_offset_replace(new_ctx, new_dentry, new_index);
- return ret;
}
/**
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 109e5caae8c7..4b6f18d97734 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -97,7 +97,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_host *host;
struct nlm_file *file;
- struct nlm_lockowner *test_owner;
__be32 rc = rpc_success;
dprintk("lockd: TEST4 called\n");
@@ -107,7 +106,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
- test_owner = argp->lock.fl.c.flc_owner;
/* Now check for conflicting locks */
resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock,
&resp->lock);
@@ -116,7 +114,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
else
dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
- nlmsvc_put_lockowner(test_owner);
+ nlmsvc_release_lockowner(&argp->lock);
nlmsvc_release_host(host);
nlm_release_file(file);
return rc;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 3a3d05cfe09a..6bce19fd024c 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -633,7 +633,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
}
mode = lock_to_openmode(&lock->fl);
- error = vfs_test_lock(file->f_file[mode], &lock->fl);
+ locks_init_lock(&conflock->fl);
+ /* vfs_test_lock only uses start, end, and owner, but tests flc_file */
+ conflock->fl.c.flc_file = lock->fl.c.flc_file;
+ conflock->fl.fl_start = lock->fl.fl_start;
+ conflock->fl.fl_end = lock->fl.fl_end;
+ conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
+ error = vfs_test_lock(file->f_file[mode], &conflock->fl);
if (error) {
/* We can't currently deal with deferred test requests */
if (error == FILE_LOCK_DEFERRED)
@@ -643,22 +649,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
}
- if (lock->fl.c.flc_type == F_UNLCK) {
+ if (conflock->fl.c.flc_type == F_UNLCK) {
ret = nlm_granted;
goto out;
}
dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
- lock->fl.c.flc_type, (long long)lock->fl.fl_start,
- (long long)lock->fl.fl_end);
+ conflock->fl.c.flc_type, (long long)conflock->fl.fl_start,
+ (long long)conflock->fl.fl_end);
conflock->caller = "somehost"; /* FIXME */
conflock->len = strlen(conflock->caller);
conflock->oh.len = 0; /* don't return OH info */
- conflock->svid = lock->fl.c.flc_pid;
- conflock->fl.c.flc_type = lock->fl.c.flc_type;
- conflock->fl.fl_start = lock->fl.fl_start;
- conflock->fl.fl_end = lock->fl.fl_end;
- locks_release_private(&lock->fl);
+ conflock->svid = conflock->fl.c.flc_pid;
+ locks_release_private(&conflock->fl);
ret = nlm_lck_denied;
out:
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index f53d5177f267..5817ef272332 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_host *host;
struct nlm_file *file;
- struct nlm_lockowner *test_owner;
__be32 rc = rpc_success;
dprintk("lockd: TEST called\n");
@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
- test_owner = argp->lock.fl.c.flc_owner;
-
/* Now check for conflicting locks */
resp->status = cast_status(nlmsvc_testlock(rqstp, file, host,
&argp->lock, &resp->lock));
@@ -138,7 +135,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
dprintk("lockd: TEST status %d vers %d\n",
ntohl(resp->status), rqstp->rq_vers);
- nlmsvc_put_lockowner(test_owner);
+ nlmsvc_release_lockowner(&argp->lock);
nlmsvc_release_host(host);
nlm_release_file(file);
return rc;
diff --git a/fs/locks.c b/fs/locks.c
index 9f565802a88c..e2036aa4bd37 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2236,13 +2236,21 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
/**
* vfs_test_lock - test file byte range lock
* @filp: The file to test lock for
- * @fl: The lock to test; also used to hold result
+ * @fl: The byte-range in the file to test; also used to hold result
*
+ * On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end)
+ * in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks
+ * should be ignored. c.flc_type and c.flc_flags are ignored.
+ * Both fl_lmops and fl_ops in @fl must be NULL.
* Returns -ERRNO on failure. Indicates presence of conflicting lock by
- * setting conf->fl_type to something other than F_UNLCK.
+ * setting fl->fl_type to something other than F_UNLCK.
+ *
+ * If vfs_test_lock() does find a lock and return it, the caller must
+ * use locks_free_lock() or locks_release_private() on the returned lock.
*/
int vfs_test_lock(struct file *filp, struct file_lock *fl)
{
+ WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops);
WARN_ON_ONCE(filp != fl->c.flc_file);
if (filp->f_op->lock)
return filp->f_op->lock(filp, F_GETLK, fl);
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 9d55512d0cc9..2a1499f2ad19 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1024,7 +1024,7 @@ exp_rootfh(struct net *net, struct auth_domain *clp, char *name,
{
struct svc_export *exp;
struct path path;
- struct inode *inode;
+ struct inode *inode __maybe_unused;
struct svc_fh fh;
int err;
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 808c24fb5c9a..a6e8a1f27133 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1218,13 +1218,15 @@ static void put_deleg_file(struct nfs4_file *fp)
if (nf)
nfsd_file_put(nf);
- if (rnf)
+ if (rnf) {
+ nfsd_file_put(rnf);
nfs4_file_put_access(fp, NFS4_SHARE_ACCESS_READ);
+ }
}
static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f)
{
- struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME };
+ struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME | ATTR_DELEG };
struct inode *inode = file_inode(f);
int ret;
@@ -3097,8 +3099,10 @@ static int client_states_open(struct inode *inode, struct file *file)
return -ENXIO;
ret = seq_open(file, &states_seq_ops);
- if (ret)
+ if (ret) {
+ drop_client(clp);
return ret;
+ }
s = file->private_data;
s->private = clp;
return 0;
@@ -6231,10 +6235,14 @@ nfsd4_add_rdaccess_to_wrdeleg(struct svc_rqst *rqstp, struct nfsd4_open *open,
fp = stp->st_stid.sc_file;
spin_lock(&fp->fi_lock);
__nfs4_file_get_access(fp, NFS4_SHARE_ACCESS_READ);
- fp = stp->st_stid.sc_file;
- fp->fi_fds[O_RDONLY] = nf;
- fp->fi_rdeleg_file = nf;
+ if (!fp->fi_fds[O_RDONLY]) {
+ fp->fi_fds[O_RDONLY] = nf;
+ nf = NULL;
+ }
+ fp->fi_rdeleg_file = nfsd_file_get(fp->fi_fds[O_RDONLY]);
spin_unlock(&fp->fi_lock);
+ if (nf)
+ nfsd_file_put(nf);
}
return true;
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 30ce5851fe4c..51ef97c25456 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3375,6 +3375,11 @@ static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr,
u32 supp[3];
memcpy(supp, nfsd_suppattrs[resp->cstate.minorversion], sizeof(supp));
+ if (!IS_POSIXACL(d_inode(args->dentry)))
+ supp[0] &= ~FATTR4_WORD0_ACL;
+ if (!args->contextsupport)
+ supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+
supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index e4263326ca4a..50be785f1d2c 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -547,8 +547,14 @@ static inline bool nfsd_attrs_supported(u32 minorversion, const u32 *bmval)
#define NFSD_SUPPATTR_EXCLCREAT_WORD1 \
(NFSD_WRITEABLE_ATTRS_WORD1 & \
~(FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET))
+/*
+ * The FATTR4_WORD2_TIME_DELEG attributes are not to be allowed for
+ * OPEN(create) with EXCLUSIVE4_1. It doesn't make sense to set a
+ * delegated timestamp on a new file.
+ */
#define NFSD_SUPPATTR_EXCLCREAT_WORD2 \
- NFSD_WRITEABLE_ATTRS_WORD2
+ (NFSD_WRITEABLE_ATTRS_WORD2 & \
+ ~(FATTR4_WORD2_TIME_DELEG_ACCESS | FATTR4_WORD2_TIME_DELEG_MODIFY))
extern int nfsd4_is_junction(struct dentry *dentry);
extern int register_cld_notifier(void);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index b08ae85d53ef..f6cae4430ba4 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -615,12 +615,15 @@ int nfsd_create_serv(struct net *net)
serv = svc_create_pooled(nfsd_programs, ARRAY_SIZE(nfsd_programs),
&nn->nfsd_svcstats,
nfsd_max_blksize, nfsd);
- if (serv == NULL)
+ if (serv == NULL) {
+ percpu_ref_exit(&nn->nfsd_net_ref);
return -ENOMEM;
+ }
error = svc_bind(serv, net);
if (error < 0) {
svc_destroy(&serv);
+ percpu_ref_exit(&nn->nfsd_net_ref);
return error;
}
spin_lock(&nfsd_notifier_lock);
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index ded2900d423f..e192dca4a679 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -67,7 +67,8 @@ static inline bool nfsd_attrs_valid(struct nfsd_attrs *attrs)
struct iattr *iap = attrs->na_iattr;
return (iap->ia_valid || (attrs->na_seclabel &&
- attrs->na_seclabel->len));
+ attrs->na_seclabel->len) ||
+ attrs->na_pacl || attrs->na_dpacl);
}
__be32 nfserrno (int errno);
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index d27ff5e5f165..71bd44e5ab6d 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -270,8 +270,15 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
/*
* Include parent/name in notification either if some notification
* groups require parent info or the parent is interested in this event.
+ * The parent interest in ACCESS/MODIFY events does not apply to special
+ * files, where read/write are not on the filesystem of the parent and
+ * events can provide an undesirable side-channel for information
+ * exfiltration.
*/
- parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
+ parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS &&
+ !(data_type == FSNOTIFY_EVENT_PATH &&
+ d_is_special(dentry) &&
+ (mask & (FS_ACCESS | FS_MODIFY)));
if (parent_needed || parent_interested) {
/* When notifying parent, child should be passed as data */
WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
index e9534258d1ef..75d372ceb655 100644
--- a/fs/smb/client/cifsfs.h
+++ b/fs/smb/client/cifsfs.h
@@ -145,6 +145,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 57
-#define CIFS_VERSION "2.57"
+#define SMB3_PRODUCT_BUILD 58
+#define CIFS_VERSION "2.58"
#endif /* _CIFSFS_H */
diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h
index eeb4011cb217..fdd84369e7b8 100644
--- a/fs/smb/client/cifspdu.h
+++ b/fs/smb/client/cifspdu.h
@@ -12,7 +12,7 @@
#include <net/sock.h>
#include <linux/unaligned.h>
#include "../common/smbfsctl.h"
-#include "../common/smb2pdu.h"
+#include "../common/smb1pdu.h"
#define CIFS_PROT 0
#define POSIX_PROT (CIFS_PROT+1)
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index c2de97e4ad59..d4291d3a9a48 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -1139,6 +1139,8 @@ static int smb3_reconfigure(struct fs_context *fc)
rc = smb3_sync_session_ctx_passwords(cifs_sb, ses);
if (rc) {
mutex_unlock(&ses->session_mutex);
+ kfree_sensitive(new_password);
+ kfree_sensitive(new_password2);
return rc;
}
diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c
index 0a9935ce05a5..d1b153209424 100644
--- a/fs/smb/client/ioctl.c
+++ b/fs/smb/client/ioctl.c
@@ -588,6 +588,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
break;
default:
cifs_dbg(FYI, "unsupported ioctl\n");
+ trace_smb3_unsupported_ioctl(xid,
+ pSMBFile ? pSMBFile->fid.persistent_fid : 0,
+ command);
break;
}
cifs_ioc_exit:
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index a16ded46b5a2..c1aaf77e187b 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -1905,6 +1905,12 @@ retry:
src_off_prev = src_off;
dst_off_prev = dst_off;
+ /*
+ * __counted_by_le(ChunkCount): set to allocated chunks before
+ * populating Chunks[]
+ */
+ cc_req->ChunkCount = cpu_to_le32(chunk_count);
+
chunks = 0;
copy_bytes = 0;
copy_bytes_left = umin(total_bytes_left, tcon->max_bytes_copy);
diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h
index b0fbc2df642e..a584a7743113 100644
--- a/fs/smb/client/trace.h
+++ b/fs/smb/client/trace.h
@@ -1579,6 +1579,7 @@ DEFINE_EVENT(smb3_ioctl_class, smb3_##name, \
TP_ARGS(xid, fid, command))
DEFINE_SMB3_IOCTL_EVENT(ioctl);
+DEFINE_SMB3_IOCTL_EVENT(unsupported_ioctl);
DECLARE_EVENT_CLASS(smb3_shutdown_class,
TP_PROTO(__u32 flags,
diff --git a/fs/smb/common/smb1pdu.h b/fs/smb/common/smb1pdu.h
new file mode 100644
index 000000000000..df6d4e11ae92
--- /dev/null
+++ b/fs/smb/common/smb1pdu.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2009
+ * 2018 Samsung Electronics Co., Ltd.
+ * Author(s): Steve French <sfrench@us.ibm.com>
+ * Namjae Jeon <linkinjeon@kernel.org>
+ *
+ */
+
+#ifndef _COMMON_SMB1_PDU_H
+#define _COMMON_SMB1_PDU_H
+
+#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
+
+/*
+ * See MS-CIFS 2.2.3.1
+ * MS-SMB 2.2.3.1
+ */
+struct smb_hdr {
+ __u8 Protocol[4];
+ __u8 Command;
+ union {
+ struct {
+ __u8 ErrorClass;
+ __u8 Reserved;
+ __le16 Error;
+ } __packed DosError;
+ __le32 CifsError;
+ } __packed Status;
+ __u8 Flags;
+ __le16 Flags2; /* note: le */
+ __le16 PidHigh;
+ union {
+ struct {
+ __le32 SequenceNumber; /* le */
+ __u32 Reserved; /* zero */
+ } __packed Sequence;
+ __u8 SecuritySignature[8]; /* le */
+ } __packed Signature;
+ __u8 pad[2];
+ __u16 Tid;
+ __le16 Pid;
+ __u16 Uid;
+ __le16 Mid;
+ __u8 WordCount;
+} __packed;
+
+/* See MS-CIFS 2.2.4.52.1 */
+typedef struct smb_negotiate_req {
+ struct smb_hdr hdr; /* wct = 0 */
+ __le16 ByteCount;
+ unsigned char DialectsArray[];
+} __packed SMB_NEGOTIATE_REQ;
+
+#endif /* _COMMON_SMB1_PDU_H */
diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
index 3c8d8a4e7439..f5ebbe31384a 100644
--- a/fs/smb/common/smb2pdu.h
+++ b/fs/smb/common/smb2pdu.h
@@ -1293,6 +1293,7 @@ struct create_durable_handle_reconnect_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
struct durable_reconnect_context_v2 dcontext;
+ __u8 Pad[4];
} __packed;
/* See MS-SMB2 2.2.14.2.12 */
@@ -1985,39 +1986,6 @@ struct smb2_lease_ack {
__le64 LeaseDuration;
} __packed;
-/*
- * See MS-CIFS 2.2.3.1
- * MS-SMB 2.2.3.1
- */
-struct smb_hdr {
- __u8 Protocol[4];
- __u8 Command;
- union {
- struct {
- __u8 ErrorClass;
- __u8 Reserved;
- __le16 Error;
- } __packed DosError;
- __le32 CifsError;
- } __packed Status;
- __u8 Flags;
- __le16 Flags2; /* note: le */
- __le16 PidHigh;
- union {
- struct {
- __le32 SequenceNumber; /* le */
- __u32 Reserved; /* zero */
- } __packed Sequence;
- __u8 SecuritySignature[8]; /* le */
- } __packed Signature;
- __u8 pad[2];
- __u16 Tid;
- __le16 Pid;
- __u16 Uid;
- __le16 Mid;
- __u8 WordCount;
-} __packed;
-
#define OP_BREAK_STRUCT_SIZE_20 24
#define OP_BREAK_STRUCT_SIZE_21 36
@@ -2122,11 +2090,4 @@ struct smb_hdr {
#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
| READ_CONTROL | SYNCHRONIZE)
-/* See MS-CIFS 2.2.4.52.1 */
-typedef struct smb_negotiate_req {
- struct smb_hdr hdr; /* wct = 0 */
- __le16 ByteCount;
- unsigned char DialectsArray[];
-} __packed SMB_NEGOTIATE_REQ;
-
#endif /* _COMMON_SMB2PDU_H */
diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
index 384b19177e1c..ee4c2726771a 100644
--- a/fs/smb/common/smbdirect/smbdirect_socket.h
+++ b/fs/smb/common/smbdirect/smbdirect_socket.h
@@ -133,6 +133,14 @@ struct smbdirect_socket {
struct smbdirect_socket_parameters parameters;
/*
+ * The state for connect/negotiation
+ */
+ struct {
+ spinlock_t lock;
+ struct work_struct work;
+ } connect;
+
+ /*
* The state for keepalive and timeout handling
*/
struct {
@@ -353,6 +361,10 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
INIT_WORK(&sc->disconnect_work, __smbdirect_socket_disabled_work);
disable_work_sync(&sc->disconnect_work);
+ spin_lock_init(&sc->connect.lock);
+ INIT_WORK(&sc->connect.work, __smbdirect_socket_disabled_work);
+ disable_work_sync(&sc->connect.work);
+
INIT_WORK(&sc->idle.immediate_work, __smbdirect_socket_disabled_work);
disable_work_sync(&sc->idle.immediate_work);
INIT_DELAYED_WORK(&sc->idle.timer_work, __smbdirect_socket_disabled_work);
diff --git a/fs/smb/common/smbglob.h b/fs/smb/common/smbglob.h
index 9562845a5617..4e33d91cdc9d 100644
--- a/fs/smb/common/smbglob.h
+++ b/fs/smb/common/smbglob.h
@@ -11,8 +11,6 @@
#ifndef _COMMON_SMB_GLOB_H
#define _COMMON_SMB_GLOB_H
-#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
-
struct smb_version_values {
char *version_string;
__u16 protocol_id;
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
index f2767c4b5132..09af55b71153 100644
--- a/fs/smb/server/auth.c
+++ b/fs/smb/server/auth.c
@@ -714,7 +714,7 @@ void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
__u8 *pi_hash)
{
- struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
+ struct smb2_hdr *rcv_hdr = smb_get_msg(buf);
char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
int msg_size = get_rfc1002_len(buf);
struct sha512_ctx sha_ctx;
@@ -841,7 +841,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
unsigned int nvec, int enc)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
+ struct smb2_transform_hdr *tr_hdr = smb_get_msg(iov[0].iov_base);
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int rc;
struct scatterlist *sg;
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index b6b4f1286b9c..6cac48c8fbe8 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -295,8 +295,9 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)
return true;
}
-#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
-#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
+/* "+2" for BCC field (ByteCount, 2 bytes) */
+#define SMB1_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb_hdr) + 2)
+#define SMB2_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb2_pdu))
/**
* ksmbd_conn_handler_loop() - session thread to listen on new smb requests
@@ -363,7 +364,7 @@ recheck:
if (pdu_size > MAX_STREAM_PROT_LEN)
break;
- if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
+ if (pdu_size < SMB1_MIN_SUPPORTED_PDU_SIZE)
break;
/* 4 for rfc1002 length field */
@@ -394,9 +395,9 @@ recheck:
if (!ksmbd_smb_request(conn))
break;
- if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
+ if (((struct smb2_hdr *)smb_get_msg(conn->request_buf))->ProtocolId ==
SMB2_PROTO_NUMBER) {
- if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
+ if (pdu_size < SMB2_MIN_SUPPORTED_PDU_SIZE)
break;
}
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 1c181ef99929..7d880ff34402 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -325,8 +325,10 @@ struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
sess = ksmbd_session_lookup(conn, id);
if (!sess && conn->binding)
sess = ksmbd_session_lookup_slowpath(id);
- if (sess && sess->state != SMB2_SESSION_VALID)
+ if (sess && sess->state != SMB2_SESSION_VALID) {
+ ksmbd_user_session_put(sess);
sess = NULL;
+ }
return sess;
}
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index 1f07ebf431d7..a5967ac46604 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -637,7 +637,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
goto out;
}
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = smb_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -651,7 +651,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
- rsp = smb2_get_msg(work->response_buf);
+ rsp = smb_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(24);
if (!br_info->open_trunc &&
@@ -744,7 +744,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
goto out;
}
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = smb_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -758,7 +758,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
- rsp = smb2_get_msg(work->response_buf);
+ rsp = smb_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(44);
rsp->Epoch = br_info->epoch;
rsp->Flags = 0;
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
index 3cea16050e4f..554ae90df906 100644
--- a/fs/smb/server/server.c
+++ b/fs/smb/server/server.c
@@ -95,7 +95,7 @@ static inline int check_conn_state(struct ksmbd_work *work)
if (ksmbd_conn_exiting(work->conn) ||
ksmbd_conn_need_reconnect(work->conn)) {
- rsp_hdr = work->response_buf;
+ rsp_hdr = smb_get_msg(work->response_buf);
rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
return 1;
}
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 27f87a13f20a..2fcd0d4d1fb0 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -47,8 +47,8 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
*req = ksmbd_req_buf_next(work);
*rsp = ksmbd_resp_buf_next(work);
} else {
- *req = smb2_get_msg(work->request_buf);
- *rsp = smb2_get_msg(work->response_buf);
+ *req = smb_get_msg(work->request_buf);
+ *rsp = smb_get_msg(work->response_buf);
}
}
@@ -146,7 +146,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off)
err_rsp = ksmbd_resp_buf_next(work);
else
- err_rsp = smb2_get_msg(work->response_buf);
+ err_rsp = smb_get_msg(work->response_buf);
if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
int err;
@@ -172,7 +172,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
*/
bool is_smb2_neg_cmd(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
/* is it SMB2 header ? */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -196,7 +196,7 @@ bool is_smb2_neg_cmd(struct ksmbd_work *work)
*/
bool is_smb2_rsp(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = smb2_get_msg(work->response_buf);
+ struct smb2_hdr *hdr = smb_get_msg(work->response_buf);
/* is it SMB2 header ? */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -222,7 +222,7 @@ u16 get_smb2_cmd_val(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off)
rcv_hdr = ksmbd_req_buf_next(work);
else
- rcv_hdr = smb2_get_msg(work->request_buf);
+ rcv_hdr = smb_get_msg(work->request_buf);
return le16_to_cpu(rcv_hdr->Command);
}
@@ -235,7 +235,7 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
{
struct smb2_hdr *rsp_hdr;
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = smb_get_msg(work->response_buf);
rsp_hdr->Status = err;
work->iov_idx = 0;
@@ -258,7 +258,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
int err;
- rsp_hdr = smb2_get_msg(work->response_buf);
+ rsp_hdr = smb_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -272,7 +272,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
- rsp = smb2_get_msg(work->response_buf);
+ rsp = smb_get_msg(work->response_buf);
WARN_ON(ksmbd_conn_good(conn));
@@ -446,7 +446,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
*/
bool is_chained_smb2_message(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
unsigned int len, next_cmd;
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -497,8 +497,8 @@ bool is_chained_smb2_message(struct ksmbd_work *work)
*/
int init_smb2_rsp_hdr(struct ksmbd_work *work)
{
- struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
- struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *rsp_hdr = smb_get_msg(work->response_buf);
+ struct smb2_hdr *rcv_hdr = smb_get_msg(work->request_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
@@ -527,7 +527,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
*/
int smb2_allocate_rsp_buf(struct ksmbd_work *work)
{
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
size_t large_sz = small_sz + work->conn->vals->max_trans_size;
size_t sz = small_sz;
@@ -543,7 +543,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
offsetof(struct smb2_query_info_req, OutputBufferLength))
return -EINVAL;
- req = smb2_get_msg(work->request_buf);
+ req = smb_get_msg(work->request_buf);
if ((req->InfoType == SMB2_O_INFO_FILE &&
(req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
req->FileInfoClass == FILE_ALL_INFORMATION)) ||
@@ -712,10 +712,10 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
}
in_work->conn = work->conn;
- memcpy(smb2_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work),
+ memcpy(smb_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work),
__SMB2_HEADER_STRUCTURE_SIZE);
- rsp_hdr = smb2_get_msg(in_work->response_buf);
+ rsp_hdr = smb_get_msg(in_work->response_buf);
rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id);
smb2_set_err_rsp(in_work);
@@ -1093,8 +1093,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
int smb2_handle_negotiate(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
- struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_negotiate_req *req = smb_get_msg(work->request_buf);
+ struct smb2_negotiate_rsp *rsp = smb_get_msg(work->response_buf);
int rc = 0;
unsigned int smb2_buf_len, smb2_neg_size, neg_ctxt_len = 0;
__le32 status;
@@ -2281,7 +2281,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
{
struct smb2_create_rsp *rsp;
struct smb2_create_req *req;
- int id;
+ int id = -1;
int err;
char *name;
@@ -2338,6 +2338,9 @@ out:
break;
}
+ if (id >= 0)
+ ksmbd_session_rpc_close(work->sess, id);
+
if (!IS_ERR(name))
kfree(name);
@@ -2363,7 +2366,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
int rc = 0;
unsigned int next = 0;
- if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
+ if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 +
le16_to_cpu(eabuf->EaValueLength))
return -EINVAL;
@@ -2440,7 +2443,7 @@ next:
break;
}
- if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
+ if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 +
le16_to_cpu(eabuf->EaValueLength)) {
rc = -EINVAL;
break;
@@ -2809,6 +2812,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
SMB2_CLIENT_GUID_SIZE)) {
if (!(req->hdr.Flags & SMB2_FLAGS_REPLAY_OPERATION)) {
err = -ENOEXEC;
+ ksmbd_put_durable_fd(dh_info->fp);
goto out;
}
@@ -3006,10 +3010,10 @@ int smb2_open(struct ksmbd_work *work)
file_info = FILE_OPENED;
rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat);
+ ksmbd_put_durable_fd(fp);
if (rc)
goto err_out2;
- ksmbd_put_durable_fd(fp);
goto reconnected_fp;
}
} else if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
@@ -4923,8 +4927,10 @@ static int get_file_all_info(struct ksmbd_work *work,
ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
- if (ret)
+ if (ret) {
+ kfree(filename);
return ret;
+ }
ksmbd_debug(SMB, "filename = %s\n", filename);
delete_pending = ksmbd_inode_pending_delete(fp);
@@ -5967,7 +5973,7 @@ out:
*/
int smb2_echo(struct ksmbd_work *work)
{
- struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_echo_rsp *rsp = smb_get_msg(work->response_buf);
ksmbd_debug(SMB, "Received smb2 echo request\n");
@@ -6520,8 +6526,8 @@ int smb2_set_info(struct ksmbd_work *work)
pid = work->compound_pfid;
}
} else {
- req = smb2_get_msg(work->request_buf);
- rsp = smb2_get_msg(work->response_buf);
+ req = smb_get_msg(work->request_buf);
+ rsp = smb_get_msg(work->response_buf);
}
if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
@@ -6754,8 +6760,8 @@ int smb2_read(struct ksmbd_work *work)
pid = work->compound_pfid;
}
} else {
- req = smb2_get_msg(work->request_buf);
- rsp = smb2_get_msg(work->response_buf);
+ req = smb_get_msg(work->request_buf);
+ rsp = smb_get_msg(work->response_buf);
}
if (!has_file_id(id)) {
@@ -7183,7 +7189,7 @@ out:
int smb2_cancel(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
- struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
struct smb2_hdr *chdr;
struct ksmbd_work *iter;
struct list_head *command_list;
@@ -7200,7 +7206,7 @@ int smb2_cancel(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
list_for_each_entry(iter, command_list,
async_request_entry) {
- chdr = smb2_get_msg(iter->request_buf);
+ chdr = smb_get_msg(iter->request_buf);
if (iter->async_id !=
le64_to_cpu(hdr->Id.AsyncId))
@@ -7221,7 +7227,7 @@ int smb2_cancel(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
list_for_each_entry(iter, command_list, request_entry) {
- chdr = smb2_get_msg(iter->request_buf);
+ chdr = smb_get_msg(iter->request_buf);
if (chdr->MessageId != hdr->MessageId ||
iter == work)
@@ -8151,8 +8157,8 @@ int smb2_ioctl(struct ksmbd_work *work)
id = work->compound_fid;
}
} else {
- req = smb2_get_msg(work->request_buf);
- rsp = smb2_get_msg(work->response_buf);
+ req = smb_get_msg(work->request_buf);
+ rsp = smb_get_msg(work->response_buf);
}
if (!has_file_id(id))
@@ -8817,7 +8823,7 @@ int smb2_notify(struct ksmbd_work *work)
*/
bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
{
- struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
+ struct smb2_hdr *rcv_hdr2 = smb_get_msg(work->request_buf);
if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
command != SMB2_NEGOTIATE_HE &&
@@ -8842,7 +8848,7 @@ int smb2_check_sign_req(struct ksmbd_work *work)
struct kvec iov[1];
size_t len;
- hdr = smb2_get_msg(work->request_buf);
+ hdr = smb_get_msg(work->request_buf);
if (work->next_smb2_rcv_hdr_off)
hdr = ksmbd_req_buf_next(work);
@@ -8916,7 +8922,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
struct kvec iov[1];
size_t len;
- hdr = smb2_get_msg(work->request_buf);
+ hdr = smb_get_msg(work->request_buf);
if (work->next_smb2_rcv_hdr_off)
hdr = ksmbd_req_buf_next(work);
@@ -9049,7 +9055,7 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
{
struct smb2_transform_hdr *tr_hdr = tr_buf + 4;
- struct smb2_hdr *hdr = smb2_get_msg(old_buf);
+ struct smb2_hdr *hdr = smb_get_msg(old_buf);
unsigned int orig_len = get_rfc1002_len(old_buf);
/* tr_buf must be cleared by the caller */
@@ -9088,7 +9094,7 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
bool smb3_is_transform_hdr(void *buf)
{
- struct smb2_transform_hdr *trhdr = smb2_get_msg(buf);
+ struct smb2_transform_hdr *trhdr = smb_get_msg(buf);
return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
}
@@ -9100,7 +9106,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
unsigned int pdu_length = get_rfc1002_len(buf);
struct kvec iov[2];
int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
- struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
+ struct smb2_transform_hdr *tr_hdr = smb_get_msg(buf);
int rc = 0;
if (pdu_length < sizeof(struct smb2_transform_hdr) ||
@@ -9141,7 +9147,7 @@ bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
- struct smb2_hdr *rsp = smb2_get_msg(work->response_buf);
+ struct smb2_hdr *rsp = smb_get_msg(work->response_buf);
if (conn->dialect < SMB30_PROT_ID)
return false;
diff --git a/fs/smb/server/smb2pdu.h b/fs/smb/server/smb2pdu.h
index 66cdc8e4a648..257c6d26df26 100644
--- a/fs/smb/server/smb2pdu.h
+++ b/fs/smb/server/smb2pdu.h
@@ -383,15 +383,6 @@ int smb2_ioctl(struct ksmbd_work *work);
int smb2_oplock_break(struct ksmbd_work *work);
int smb2_notify(struct ksmbd_work *ksmbd_work);
-/*
- * Get the body of the smb2 message excluding the 4 byte rfc1002 headers
- * from request/response buffer.
- */
-static inline void *smb2_get_msg(void *buf)
-{
- return buf + 4;
-}
-
#define POSIX_TYPE_FILE 0
#define POSIX_TYPE_DIR 1
#define POSIX_TYPE_SYMLINK 2
diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c
index b23203a1c286..1cd7e738434d 100644
--- a/fs/smb/server/smb_common.c
+++ b/fs/smb/server/smb_common.c
@@ -140,7 +140,7 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work)
if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
return ksmbd_smb2_check_message(work);
- hdr = work->request_buf;
+ hdr = smb_get_msg(work->request_buf);
if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER &&
hdr->Command == SMB_COM_NEGOTIATE) {
work->conn->outstanding_credits++;
@@ -163,7 +163,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn)
if (conn->request_buf[0] != 0)
return false;
- proto = (__le32 *)smb2_get_msg(conn->request_buf);
+ proto = (__le32 *)smb_get_msg(conn->request_buf);
if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
pr_err_ratelimited("smb2 compression not support yet");
return false;
@@ -259,14 +259,14 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
static int ksmbd_negotiate_smb_dialect(void *buf)
{
int smb_buf_length = get_rfc1002_len(buf);
- __le32 proto = ((struct smb2_hdr *)smb2_get_msg(buf))->ProtocolId;
+ __le32 proto = ((struct smb2_hdr *)smb_get_msg(buf))->ProtocolId;
if (proto == SMB2_PROTO_NUMBER) {
struct smb2_negotiate_req *req;
int smb2_neg_size =
offsetof(struct smb2_negotiate_req, Dialects);
- req = (struct smb2_negotiate_req *)smb2_get_msg(buf);
+ req = (struct smb2_negotiate_req *)smb_get_msg(buf);
if (smb2_neg_size > smb_buf_length)
goto err_out;
@@ -278,15 +278,14 @@ static int ksmbd_negotiate_smb_dialect(void *buf)
req->DialectCount);
}
- proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
if (proto == SMB1_PROTO_NUMBER) {
struct smb_negotiate_req *req;
- req = (struct smb_negotiate_req *)buf;
+ req = (struct smb_negotiate_req *)smb_get_msg(buf);
if (le16_to_cpu(req->ByteCount) < 2)
goto err_out;
- if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 +
+ if (offsetof(struct smb_negotiate_req, DialectsArray) +
le16_to_cpu(req->ByteCount) > smb_buf_length) {
goto err_out;
}
@@ -320,8 +319,8 @@ static u16 get_smb1_cmd_val(struct ksmbd_work *work)
*/
static int init_smb1_rsp_hdr(struct ksmbd_work *work)
{
- struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
- struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
+ struct smb_hdr *rsp_hdr = (struct smb_hdr *)smb_get_msg(work->response_buf);
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)smb_get_msg(work->request_buf);
rsp_hdr->Command = SMB_COM_NEGOTIATE;
*(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
@@ -412,9 +411,10 @@ static int init_smb1_server(struct ksmbd_conn *conn)
int ksmbd_init_smb_server(struct ksmbd_conn *conn)
{
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)smb_get_msg(conn->request_buf);
__le32 proto;
- proto = *(__le32 *)((struct smb_hdr *)conn->request_buf)->Protocol;
+ proto = *(__le32 *)rcv_hdr->Protocol;
if (conn->need_neg == false) {
if (proto == SMB1_PROTO_NUMBER)
return -EINVAL;
@@ -572,12 +572,12 @@ static int __smb2_negotiate(struct ksmbd_conn *conn)
static int smb_handle_negotiate(struct ksmbd_work *work)
{
- struct smb_negotiate_rsp *neg_rsp = work->response_buf;
+ struct smb_negotiate_rsp *neg_rsp = smb_get_msg(work->response_buf);
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp + 4,
- sizeof(struct smb_negotiate_rsp) - 4))
+ if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp,
+ sizeof(struct smb_negotiate_rsp)))
return -ENOMEM;
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
diff --git a/fs/smb/server/smb_common.h b/fs/smb/server/smb_common.h
index 067b45048c73..ddd6867c50b2 100644
--- a/fs/smb/server/smb_common.h
+++ b/fs/smb/server/smb_common.h
@@ -10,6 +10,7 @@
#include "glob.h"
#include "../common/smbglob.h"
+#include "../common/smb1pdu.h"
#include "../common/smb2pdu.h"
#include "../common/fscc.h"
#include "smb2pdu.h"
@@ -202,4 +203,13 @@ unsigned int ksmbd_server_side_copy_max_chunk_size(void);
unsigned int ksmbd_server_side_copy_max_total_size(void);
bool is_asterisk(char *p);
__le32 smb_map_generic_desired_access(__le32 daccess);
+
+/*
+ * Get the body of the smb message excluding the 4 byte rfc1002 headers
+ * from request/response buffer.
+ */
+static inline void *smb_get_msg(void *buf)
+{
+ return buf + 4;
+}
#endif /* __SMB_SERVER_COMMON_H__ */
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 5aa7a66334d9..05598d994a68 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -1307,9 +1307,6 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
granted |= le32_to_cpu(ace->access_req);
ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
}
-
- if (!pdacl->num_aces)
- granted = GENERIC_ALL_FLAGS;
}
if (!uid)
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 4e7ab8d9314f..f585359684d4 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -242,6 +242,7 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
* disable[_delayed]_work_sync()
*/
disable_work(&sc->disconnect_work);
+ disable_work(&sc->connect.work);
disable_work(&sc->recv_io.posted.refill_work);
disable_delayed_work(&sc->idle.timer_work);
disable_work(&sc->idle.immediate_work);
@@ -297,6 +298,7 @@ smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
* not queued again but here we don't block and avoid
* disable[_delayed]_work_sync()
*/
+ disable_work(&sc->connect.work);
disable_work(&sc->recv_io.posted.refill_work);
disable_work(&sc->idle.immediate_work);
disable_delayed_work(&sc->idle.timer_work);
@@ -467,6 +469,7 @@ static void free_transport(struct smb_direct_transport *t)
*/
smb_direct_disconnect_wake_up_all(sc);
+ disable_work_sync(&sc->connect.work);
disable_work_sync(&sc->recv_io.posted.refill_work);
disable_delayed_work_sync(&sc->idle.timer_work);
disable_work_sync(&sc->idle.immediate_work);
@@ -635,28 +638,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
switch (sc->recv_io.expected) {
case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
- if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
- put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
- return;
- }
- sc->recv_io.reassembly.full_packet_received = true;
- /*
- * Some drivers (at least mlx5_ib) might post a
- * recv completion before RDMA_CM_EVENT_ESTABLISHED,
- * we need to adjust our expectation in that case.
- */
- if (!sc->first_error && sc->status == SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
- if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) {
- put_recvmsg(sc, recvmsg);
- smb_direct_disconnect_rdma_connection(sc);
- return;
- }
- sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
- enqueue_reassembly(sc, recvmsg, 0);
- wake_up(&sc->status_wait);
- return;
+ /* see smb_direct_negotiate_recv_done */
+ break;
case SMBDIRECT_EXPECT_DATA_TRANSFER: {
struct smbdirect_data_transfer *data_transfer =
(struct smbdirect_data_transfer *)recvmsg->packet;
@@ -742,6 +725,126 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
smb_direct_disconnect_rdma_connection(sc);
}
+static void smb_direct_negotiate_recv_work(struct work_struct *work);
+
+static void smb_direct_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct smbdirect_recv_io *recv_io =
+ container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
+ struct smbdirect_socket *sc = recv_io->socket;
+ unsigned long flags;
+
+ /*
+ * reset the common recv_done for later reuse.
+ */
+ recv_io->cqe.done = recv_done;
+
+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
+ put_recvmsg(sc, recv_io);
+ if (wc->status != IB_WC_WR_FLUSH_ERR) {
+ pr_err("Negotiate Recv error. status='%s (%d)' opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
+ smb_direct_disconnect_rdma_connection(sc);
+ }
+ return;
+ }
+
+ ksmbd_debug(RDMA, "Negotiate Recv completed. status='%s (%d)', opcode=%d\n",
+ ib_wc_status_msg(wc->status), wc->status,
+ wc->opcode);
+
+ ib_dma_sync_single_for_cpu(sc->ib.dev,
+ recv_io->sge.addr,
+ recv_io->sge.length,
+ DMA_FROM_DEVICE);
+
+ /*
+ * This is an internal error!
+ */
+ if (WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_NEGOTIATE_REQ)) {
+ put_recvmsg(sc, recv_io);
+ smb_direct_disconnect_rdma_connection(sc);
+ return;
+ }
+
+ /*
+ * Don't reset timer to the keepalive interval in
+ * this will be done in smb_direct_negotiate_recv_work.
+ */
+
+ /*
+ * Only remember the recv_io if it has enough bytes,
+ * this gives smb_direct_negotiate_recv_work enough
+ * information in order to disconnect if it was not
+ * valid.
+ */
+ sc->recv_io.reassembly.full_packet_received = true;
+ if (wc->byte_len >= sizeof(struct smbdirect_negotiate_req))
+ enqueue_reassembly(sc, recv_io, 0);
+ else
+ put_recvmsg(sc, recv_io);
+
+ /*
+ * Some drivers (at least mlx5_ib and irdma in roce mode)
+ * might post a recv completion before RDMA_CM_EVENT_ESTABLISHED,
+ * we need to adjust our expectation in that case.
+ *
+ * So we defer further processing of the negotiation
+ * to smb_direct_negotiate_recv_work().
+ *
+ * If we are already in SMBDIRECT_SOCKET_NEGOTIATE_NEEDED
+ * we queue the work directly otherwise
+ * smb_direct_cm_handler() will do it, when
+ * RDMA_CM_EVENT_ESTABLISHED arrived.
+ */
+ spin_lock_irqsave(&sc->connect.lock, flags);
+ if (!sc->first_error) {
+ INIT_WORK(&sc->connect.work, smb_direct_negotiate_recv_work);
+ if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)
+ queue_work(sc->workqueue, &sc->connect.work);
+ }
+ spin_unlock_irqrestore(&sc->connect.lock, flags);
+}
+
+static void smb_direct_negotiate_recv_work(struct work_struct *work)
+{
+ struct smbdirect_socket *sc =
+ container_of(work, struct smbdirect_socket, connect.work);
+ const struct smbdirect_socket_parameters *sp = &sc->parameters;
+ struct smbdirect_recv_io *recv_io;
+
+ if (sc->first_error)
+ return;
+
+ ksmbd_debug(RDMA, "Negotiate Recv Work running\n");
+
+ /*
+ * Reset timer to the keepalive interval in
+ * order to trigger our next keepalive message.
+ */
+ sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
+ mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
+ msecs_to_jiffies(sp->keepalive_interval_msec));
+
+ /*
+ * If smb_direct_negotiate_recv_done() detected an
+ * invalid request we want to disconnect.
+ */
+ recv_io = get_first_reassembly(sc);
+ if (!recv_io) {
+ smb_direct_disconnect_rdma_connection(sc);
+ return;
+ }
+
+ if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) {
+ smb_direct_disconnect_rdma_connection(sc);
+ return;
+ }
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
+ wake_up(&sc->status_wait);
+}
+
static int smb_direct_post_recv(struct smbdirect_socket *sc,
struct smbdirect_recv_io *recvmsg)
{
@@ -758,7 +861,6 @@ static int smb_direct_post_recv(struct smbdirect_socket *sc,
return ret;
recvmsg->sge.length = sp->max_recv_size;
recvmsg->sge.lkey = sc->ib.pd->local_dma_lkey;
- recvmsg->cqe.done = recv_done;
wr.wr_cqe = &recvmsg->cqe;
wr.next = NULL;
@@ -1732,6 +1834,7 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event)
{
struct smbdirect_socket *sc = cm_id->context;
+ unsigned long flags;
ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n",
cm_id, rdma_event_msg(event->event), event->event);
@@ -1739,18 +1842,27 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
switch (event->event) {
case RDMA_CM_EVENT_ESTABLISHED: {
/*
- * Some drivers (at least mlx5_ib) might post a
- * recv completion before RDMA_CM_EVENT_ESTABLISHED,
+ * Some drivers (at least mlx5_ib and irdma in roce mode)
+ * might post a recv completion before RDMA_CM_EVENT_ESTABLISHED,
* we need to adjust our expectation in that case.
*
- * As we already started the negotiation, we just
- * ignore RDMA_CM_EVENT_ESTABLISHED here.
+ * If smb_direct_negotiate_recv_done was called first
+ * it initialized sc->connect.work only for us to
+ * start, so that we turned into
+ * SMBDIRECT_SOCKET_NEGOTIATE_NEEDED, before
+ * smb_direct_negotiate_recv_work() runs.
+ *
+ * If smb_direct_negotiate_recv_done didn't happen
+ * yet. sc->connect.work is still be disabled and
+ * queue_work() is a no-op.
*/
- if (!sc->first_error && sc->status > SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)
- break;
if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING))
break;
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
+ spin_lock_irqsave(&sc->connect.lock, flags);
+ if (!sc->first_error)
+ queue_work(sc->workqueue, &sc->connect.work);
+ spin_unlock_irqrestore(&sc->connect.lock, flags);
wake_up(&sc->status_wait);
break;
}
@@ -1921,6 +2033,7 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
recvmsg = get_free_recvmsg(sc);
if (!recvmsg)
return -ENOMEM;
+ recvmsg->cqe.done = smb_direct_negotiate_recv_done;
ret = smb_direct_post_recv(sc, recvmsg);
if (ret) {
@@ -2339,6 +2452,7 @@ respond:
static int smb_direct_connect(struct smbdirect_socket *sc)
{
+ struct smbdirect_recv_io *recv_io;
int ret;
ret = smb_direct_init_params(sc);
@@ -2353,6 +2467,9 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
return ret;
}
+ list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
+ recv_io->cqe.done = recv_done;
+
ret = smb_direct_create_qpair(sc);
if (ret) {
pr_err("Can't accept RDMA client: %d\n", ret);
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index 98b0eb966d91..f891344bd76b 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -702,7 +702,7 @@ retry:
rd.old_parent = NULL;
rd.new_parent = new_path.dentry;
rd.flags = flags;
- rd.delegated_inode = NULL,
+ rd.delegated_inode = NULL;
err = start_renaming_dentry(&rd, lookup_flags, old_child, &new_last);
if (err)
goto out_drop_write;
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index cdd16dd805d7..94c272a2ae26 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -301,6 +301,21 @@ xfs_validate_rt_geometry(
sbp->sb_rbmblocks != xfs_expected_rbmblocks(sbp))
return false;
+ if (xfs_sb_is_v5(sbp) &&
+ (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_ZONED)) {
+ uint32_t mod;
+
+ /*
+ * Zoned RT devices must be aligned to the RT group size,
+ * because garbage collection assumes that all zones have the
+ * same size to avoid insane complexity if that weren't the
+ * case.
+ */
+ div_u64_rem(sbp->sb_rextents, sbp->sb_rgextents, &mod);
+ if (mod)
+ return false;
+ }
+
return true;
}
diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c
index c7eb94069caf..09d63aa10314 100644
--- a/fs/xfs/scrub/attr_repair.c
+++ b/fs/xfs/scrub/attr_repair.c
@@ -333,7 +333,6 @@ xrep_xattr_salvage_remote_attr(
.attr_filter = ent->flags & XFS_ATTR_NSP_ONDISK_MASK,
.namelen = rentry->namelen,
.name = rentry->name,
- .value = ab->value,
.valuelen = be32_to_cpu(rentry->valuelen),
};
unsigned int namesize;
@@ -363,6 +362,7 @@ xrep_xattr_salvage_remote_attr(
error = -EDEADLOCK;
if (error)
return error;
+ args.value = ab->value;
/* Look up the remote value and stash it for reconstruction. */
error = xfs_attr3_leaf_getvalue(leaf_bp, &args);
diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c
index c3a593319bee..e8fa326ac995 100644
--- a/fs/xfs/xfs_attr_item.c
+++ b/fs/xfs/xfs_attr_item.c
@@ -737,7 +737,7 @@ xfs_attr_recover_work(
struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
struct xfs_attr_intent *attr;
struct xfs_mount *mp = lip->li_log->l_mp;
- struct xfs_inode *ip;
+ struct xfs_inode *ip = NULL;
struct xfs_da_args *args;
struct xfs_trans *tp;
struct xfs_trans_res resv;
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 8d85b5eee444..f4c5be67826e 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -896,6 +896,7 @@ xfs_buf_item_init(
map_size = DIV_ROUND_UP(chunks, NBWORD);
if (map_size > XFS_BLF_DATAMAP_SIZE) {
+ xfs_buf_item_free_format(bip);
kmem_cache_free(xfs_buf_item_cache, bip);
xfs_err(mp,
"buffer item dirty bitmap (%u uints) too small to reflect %u bytes!",
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 6917de832191..b6ffe4807a11 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -108,7 +108,7 @@ xfs_discard_endio(
* list. We plug and chain the bios so that we only need a single completion
* call to clear all the busy extents once the discards are complete.
*/
-int
+void
xfs_discard_extents(
struct xfs_mount *mp,
struct xfs_busy_extents *extents)
@@ -116,7 +116,6 @@ xfs_discard_extents(
struct xfs_extent_busy *busyp;
struct bio *bio = NULL;
struct blk_plug plug;
- int error = 0;
blk_start_plug(&plug);
list_for_each_entry(busyp, &extents->extent_list, list) {
@@ -126,18 +125,10 @@ xfs_discard_extents(
trace_xfs_discard_extent(xg, busyp->bno, busyp->length);
- error = __blkdev_issue_discard(btp->bt_bdev,
+ __blkdev_issue_discard(btp->bt_bdev,
xfs_gbno_to_daddr(xg, busyp->bno),
XFS_FSB_TO_BB(mp, busyp->length),
GFP_KERNEL, &bio);
- if (error && error != -EOPNOTSUPP) {
- xfs_info(mp,
- "discard failed for extent [0x%llx,%u], error %d",
- (unsigned long long)busyp->bno,
- busyp->length,
- error);
- break;
- }
}
if (bio) {
@@ -148,8 +139,6 @@ xfs_discard_extents(
xfs_discard_endio_work(&extents->endio_work);
}
blk_finish_plug(&plug);
-
- return error;
}
/*
@@ -385,9 +374,7 @@ xfs_trim_perag_extents(
* list after this function call, as it may have been freed by
* the time control returns to us.
*/
- error = xfs_discard_extents(pag_mount(pag), extents);
- if (error)
- break;
+ xfs_discard_extents(pag_mount(pag), extents);
if (xfs_trim_should_stop())
break;
@@ -496,12 +483,10 @@ xfs_discard_rtdev_extents(
trace_xfs_discard_rtextent(mp, busyp->bno, busyp->length);
- error = __blkdev_issue_discard(bdev,
+ __blkdev_issue_discard(bdev,
xfs_rtb_to_daddr(mp, busyp->bno),
XFS_FSB_TO_BB(mp, busyp->length),
GFP_NOFS, &bio);
- if (error)
- break;
}
xfs_discard_free_rtdev_extents(tr);
@@ -741,9 +726,7 @@ xfs_trim_rtgroup_extents(
* list after this function call, as it may have been freed by
* the time control returns to us.
*/
- error = xfs_discard_extents(rtg_mount(rtg), tr.extents);
- if (error)
- break;
+ xfs_discard_extents(rtg_mount(rtg), tr.extents);
low = tr.restart_rtx;
} while (!xfs_trim_should_stop() && low <= high);
diff --git a/fs/xfs/xfs_discard.h b/fs/xfs/xfs_discard.h
index 2b1a85223a56..8c5cc4af6a07 100644
--- a/fs/xfs/xfs_discard.h
+++ b/fs/xfs/xfs_discard.h
@@ -6,7 +6,7 @@ struct fstrim_range;
struct xfs_mount;
struct xfs_busy_extents;
-int xfs_discard_extents(struct xfs_mount *mp, struct xfs_busy_extents *busy);
+void xfs_discard_extents(struct xfs_mount *mp, struct xfs_busy_extents *busy);
int xfs_ioc_trim(struct xfs_mount *mp, struct fstrim_range __user *fstrim);
#endif /* XFS_DISCARD_H */
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 6108612182e2..7874cf745af3 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1241,6 +1241,38 @@ xfs_falloc_insert_range(
}
/*
+ * For various operations we need to zero up to one block at each end of
+ * the affected range. For zoned file systems this will require a space
+ * allocation, for which we need a reservation ahead of time.
+ */
+#define XFS_ZONED_ZERO_EDGE_SPACE_RES 2
+
+/*
+ * Zero range implements a full zeroing mechanism but is only used in limited
+ * situations. It is more efficient to allocate unwritten extents than to
+ * perform zeroing here, so use an errortag to randomly force zeroing on DEBUG
+ * kernels for added test coverage.
+ *
+ * On zoned file systems, the error is already injected by
+ * xfs_file_zoned_fallocate, which then reserves the additional space needed.
+ * We only check for this extra space reservation here.
+ */
+static inline bool
+xfs_falloc_force_zero(
+ struct xfs_inode *ip,
+ struct xfs_zone_alloc_ctx *ac)
+{
+ if (xfs_is_zoned_inode(ip)) {
+ if (ac->reserved_blocks > XFS_ZONED_ZERO_EDGE_SPACE_RES) {
+ ASSERT(IS_ENABLED(CONFIG_XFS_DEBUG));
+ return true;
+ }
+ return false;
+ }
+ return XFS_TEST_ERROR(ip->i_mount, XFS_ERRTAG_FORCE_ZERO_RANGE);
+}
+
+/*
* Punch a hole and prealloc the range. We use a hole punch rather than
* unwritten extent conversion for two reasons:
*
@@ -1268,14 +1300,7 @@ xfs_falloc_zero_range(
if (error)
return error;
- /*
- * Zero range implements a full zeroing mechanism but is only used in
- * limited situations. It is more efficient to allocate unwritten
- * extents than to perform zeroing here, so use an errortag to randomly
- * force zeroing on DEBUG kernels for added test coverage.
- */
- if (XFS_TEST_ERROR(ip->i_mount,
- XFS_ERRTAG_FORCE_ZERO_RANGE)) {
+ if (xfs_falloc_force_zero(ip, ac)) {
error = xfs_zero_range(ip, offset, len, ac, NULL);
} else {
error = xfs_free_file_space(ip, offset, len, ac);
@@ -1423,13 +1448,26 @@ xfs_file_zoned_fallocate(
{
struct xfs_zone_alloc_ctx ac = { };
struct xfs_inode *ip = XFS_I(file_inode(file));
+ struct xfs_mount *mp = ip->i_mount;
+ xfs_filblks_t count_fsb;
int error;
- error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac);
+ /*
+ * If full zeroing is forced by the error injection knob, we need a
+ * space reservation that covers the entire range. See the comment in
+ * xfs_zoned_write_space_reserve for the rationale for the calculation.
+ * Otherwise just reserve space for the two boundary blocks.
+ */
+ count_fsb = XFS_ZONED_ZERO_EDGE_SPACE_RES;
+ if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE &&
+ XFS_TEST_ERROR(mp, XFS_ERRTAG_FORCE_ZERO_RANGE))
+ count_fsb += XFS_B_TO_FSB(mp, len) + 1;
+
+ error = xfs_zoned_space_reserve(mp, count_fsb, XFS_ZR_RESERVED, &ac);
if (error)
return error;
error = __xfs_file_fallocate(file, mode, offset, len, &ac);
- xfs_zoned_space_unreserve(ip->i_mount, &ac);
+ xfs_zoned_space_unreserve(mp, &ac);
return error;
}
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 6907e871fa15..e063f4f2f2e6 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1255,12 +1255,10 @@ xfs_growfs_check_rtgeom(
min_logfsbs = min_t(xfs_extlen_t, xfs_log_calc_minimum_size(nmp),
nmp->m_rsumblocks * 2);
- kfree(nmp);
-
trace_xfs_growfs_check_rtgeom(mp, min_logfsbs);
if (min_logfsbs > mp->m_sb.sb_logblocks)
- return -EINVAL;
+ goto out_inval;
if (xfs_has_zoned(mp)) {
uint32_t gblocks = mp->m_groups[XG_TYPE_RTG].blocks;
@@ -1268,16 +1266,20 @@ xfs_growfs_check_rtgeom(
if (rextsize != 1)
return -EINVAL;
- div_u64_rem(mp->m_sb.sb_rblocks, gblocks, &rem);
+ div_u64_rem(nmp->m_sb.sb_rblocks, gblocks, &rem);
if (rem) {
xfs_warn(mp,
"new RT volume size (%lld) not aligned to RT group size (%d)",
- mp->m_sb.sb_rblocks, gblocks);
- return -EINVAL;
+ nmp->m_sb.sb_rblocks, gblocks);
+ goto out_inval;
}
}
+ kfree(nmp);
return 0;
+out_inval:
+ kfree(nmp);
+ return -EINVAL;
}
/*
diff --git a/include/drm/drm_pagemap.h b/include/drm/drm_pagemap.h
index f6e7e234c089..70a7991f784f 100644
--- a/include/drm/drm_pagemap.h
+++ b/include/drm/drm_pagemap.h
@@ -8,6 +8,7 @@
#define NR_PAGES(order) (1U << (order))
+struct dma_fence;
struct drm_pagemap;
struct drm_pagemap_zdd;
struct device;
@@ -174,6 +175,8 @@ struct drm_pagemap_devmem_ops {
* @pages: Pointer to array of device memory pages (destination)
* @pagemap_addr: Pointer to array of DMA information (source)
* @npages: Number of pages to copy
+ * @pre_migrate_fence: dma-fence to wait for before migration start.
+ * May be NULL.
*
* Copy pages to device memory. If the order of a @pagemap_addr entry
* is greater than 0, the entry is populated but subsequent entries
@@ -183,13 +186,16 @@ struct drm_pagemap_devmem_ops {
*/
int (*copy_to_devmem)(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages);
+ unsigned long npages,
+ struct dma_fence *pre_migrate_fence);
/**
* @copy_to_ram: Copy to system RAM (required for migration)
* @pages: Pointer to array of device memory pages (source)
* @pagemap_addr: Pointer to array of DMA information (destination)
* @npages: Number of pages to copy
+ * @pre_migrate_fence: dma-fence to wait for before migration start.
+ * May be NULL.
*
* Copy pages to system RAM. If the order of a @pagemap_addr entry
* is greater than 0, the entry is populated but subsequent entries
@@ -199,7 +205,8 @@ struct drm_pagemap_devmem_ops {
*/
int (*copy_to_ram)(struct page **pages,
struct drm_pagemap_addr *pagemap_addr,
- unsigned long npages);
+ unsigned long npages,
+ struct dma_fence *pre_migrate_fence);
};
/**
@@ -212,6 +219,8 @@ struct drm_pagemap_devmem_ops {
* @dpagemap: The struct drm_pagemap of the pages this allocation belongs to.
* @size: Size of device memory allocation
* @timeslice_expiration: Timeslice expiration in jiffies
+ * @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
+ * (May be NULL).
*/
struct drm_pagemap_devmem {
struct device *dev;
@@ -221,6 +230,7 @@ struct drm_pagemap_devmem {
struct drm_pagemap *dpagemap;
size_t size;
u64 timeslice_expiration;
+ struct dma_fence *pre_migrate_fence;
};
int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
@@ -238,7 +248,8 @@ struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page);
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
struct device *dev, struct mm_struct *mm,
const struct drm_pagemap_devmem_ops *ops,
- struct drm_pagemap *dpagemap, size_t size);
+ struct drm_pagemap *dpagemap, size_t size,
+ struct dma_fence *pre_migrate_fence);
int drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
unsigned long start, unsigned long end,
diff --git a/include/kunit/run-in-irq-context.h b/include/kunit/run-in-irq-context.h
index 108e96433ea4..c89b1b1b12dd 100644
--- a/include/kunit/run-in-irq-context.h
+++ b/include/kunit/run-in-irq-context.h
@@ -20,8 +20,8 @@ struct kunit_irq_test_state {
bool task_func_reported_failure;
bool hardirq_func_reported_failure;
bool softirq_func_reported_failure;
- unsigned long hardirq_func_calls;
- unsigned long softirq_func_calls;
+ atomic_t hardirq_func_calls;
+ atomic_t softirq_func_calls;
struct hrtimer timer;
struct work_struct bh_work;
};
@@ -32,7 +32,7 @@ static enum hrtimer_restart kunit_irq_test_timer_func(struct hrtimer *timer)
container_of(timer, typeof(*state), timer);
WARN_ON_ONCE(!in_hardirq());
- state->hardirq_func_calls++;
+ atomic_inc(&state->hardirq_func_calls);
if (!state->func(state->test_specific_state))
state->hardirq_func_reported_failure = true;
@@ -48,7 +48,7 @@ static void kunit_irq_test_bh_work_func(struct work_struct *work)
container_of(work, typeof(*state), bh_work);
WARN_ON_ONCE(!in_serving_softirq());
- state->softirq_func_calls++;
+ atomic_inc(&state->softirq_func_calls);
if (!state->func(state->test_specific_state))
state->softirq_func_reported_failure = true;
@@ -59,7 +59,10 @@ static void kunit_irq_test_bh_work_func(struct work_struct *work)
* hardirq context concurrently, and reports a failure to KUnit if any
* invocation of @func in any context returns false. @func is passed
* @test_specific_state as its argument. At most 3 invocations of @func will
- * run concurrently: one in each of task, softirq, and hardirq context.
+ * run concurrently: one in each of task, softirq, and hardirq context. @func
+ * will continue running until either @max_iterations calls have been made (so
+ * long as at least one each runs in task, softirq, and hardirq contexts), or
+ * one second has passed.
*
* The main purpose of this interrupt context testing is to validate fallback
* code paths that run in contexts where the normal code path cannot be used,
@@ -85,6 +88,8 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
.test_specific_state = test_specific_state,
};
unsigned long end_jiffies;
+ int hardirq_calls, softirq_calls;
+ bool allctx = false;
/*
* Set up a hrtimer (the way we access hardirq context) and a work
@@ -94,14 +99,25 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
INIT_WORK_ONSTACK(&state.bh_work, kunit_irq_test_bh_work_func);
- /* Run for up to max_iterations or 1 second, whichever comes first. */
+ /*
+ * Run for up to max_iterations (including at least one task, softirq,
+ * and hardirq), or 1 second, whichever comes first.
+ */
end_jiffies = jiffies + HZ;
hrtimer_start(&state.timer, KUNIT_IRQ_TEST_HRTIMER_INTERVAL,
HRTIMER_MODE_REL_HARD);
- for (int i = 0; i < max_iterations && !time_after(jiffies, end_jiffies);
- i++) {
+ for (int task_calls = 0, calls = 0;
+ ((calls < max_iterations) || !allctx) &&
+ !time_after(jiffies, end_jiffies);
+ task_calls++) {
if (!func(test_specific_state))
state.task_func_reported_failure = true;
+
+ hardirq_calls = atomic_read(&state.hardirq_func_calls);
+ softirq_calls = atomic_read(&state.softirq_func_calls);
+ calls = task_calls + hardirq_calls + softirq_calls;
+ allctx = (task_calls > 0) && (hardirq_calls > 0) &&
+ (softirq_calls > 0);
}
/* Cancel the timer and work. */
@@ -109,21 +125,18 @@ static inline void kunit_run_irq_test(struct kunit *test, bool (*func)(void *),
flush_work(&state.bh_work);
/* Sanity check: the timer and BH functions should have been run. */
- KUNIT_EXPECT_GT_MSG(test, state.hardirq_func_calls, 0,
+ KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.hardirq_func_calls), 0,
"Timer function was not called");
- KUNIT_EXPECT_GT_MSG(test, state.softirq_func_calls, 0,
+ KUNIT_EXPECT_GT_MSG(test, atomic_read(&state.softirq_func_calls), 0,
"BH work function was not called");
- /* Check for incorrect hash values reported from any context. */
- KUNIT_EXPECT_FALSE_MSG(
- test, state.task_func_reported_failure,
- "Incorrect hash values reported from task context");
- KUNIT_EXPECT_FALSE_MSG(
- test, state.hardirq_func_reported_failure,
- "Incorrect hash values reported from hardirq context");
- KUNIT_EXPECT_FALSE_MSG(
- test, state.softirq_func_reported_failure,
- "Incorrect hash values reported from softirq context");
+ /* Check for failure reported from any context. */
+ KUNIT_EXPECT_FALSE_MSG(test, state.task_func_reported_failure,
+ "Failure reported from task context");
+ KUNIT_EXPECT_FALSE_MSG(test, state.hardirq_func_reported_failure,
+ "Failure reported from hardirq context");
+ KUNIT_EXPECT_FALSE_MSG(test, state.softirq_func_reported_failure,
+ "Failure reported from softirq context");
}
#endif /* _KUNIT_RUN_IN_IRQ_CONTEXT_H */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index ad2d57908c1c..c75a9b3672aa 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -46,6 +46,21 @@ static inline unsigned int bio_max_segs(unsigned int nr_segs)
#define bio_data_dir(bio) \
(op_is_write(bio_op(bio)) ? WRITE : READ)
+static inline bool bio_flagged(const struct bio *bio, unsigned int bit)
+{
+ return bio->bi_flags & (1U << bit);
+}
+
+static inline void bio_set_flag(struct bio *bio, unsigned int bit)
+{
+ bio->bi_flags |= (1U << bit);
+}
+
+static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
+{
+ bio->bi_flags &= ~(1U << bit);
+}
+
/*
* Check whether this bio carries any data or not. A NULL bio is allowed.
*/
@@ -225,21 +240,6 @@ static inline void bio_cnt_set(struct bio *bio, unsigned int count)
atomic_set(&bio->__bi_cnt, count);
}
-static inline bool bio_flagged(struct bio *bio, unsigned int bit)
-{
- return bio->bi_flags & (1U << bit);
-}
-
-static inline void bio_set_flag(struct bio *bio, unsigned int bit)
-{
- bio->bi_flags |= (1U << bit);
-}
-
-static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
-{
- bio->bi_flags &= ~(1U << bit);
-}
-
static inline struct bio_vec *bio_first_bvec_all(struct bio *bio)
{
WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED));
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 6498be4c44f8..e5be698256d1 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1283,6 +1283,8 @@ struct bpf_ksym {
struct list_head lnode;
struct latch_tree_node tnode;
bool prog;
+ u32 fp_start;
+ u32 fp_end;
};
enum bpf_tramp_prog_type {
@@ -1511,6 +1513,7 @@ void bpf_image_ksym_add(struct bpf_ksym *ksym);
void bpf_image_ksym_del(struct bpf_ksym *ksym);
void bpf_ksym_add(struct bpf_ksym *ksym);
void bpf_ksym_del(struct bpf_ksym *ksym);
+bool bpf_has_frame_pointer(unsigned long ip);
int bpf_jit_charge_modmem(u32 size);
void bpf_jit_uncharge_modmem(u32 size);
bool bpf_prog_has_trampoline(const struct bpf_prog *prog);
diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
index 107ce05bd16e..7edf1a07b535 100644
--- a/include/linux/compiler-clang.h
+++ b/include/linux/compiler-clang.h
@@ -145,6 +145,7 @@
*/
#define ASM_INPUT_G "ir"
#define ASM_INPUT_RM "r"
+#define ASM_OUTPUT_RM "=r"
/*
* Declare compiler support for __typeof_unqual__() operator.
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 1280693766b9..d3318a3c2577 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -548,11 +548,12 @@ struct ftrace_likely_data {
/*
* Clang has trouble with constraints with multiple
- * alternative behaviors (mainly "g" and "rm").
+ * alternative behaviors ("g" , "rm" and "=rm").
*/
#ifndef ASM_INPUT_G
#define ASM_INPUT_G "g"
#define ASM_INPUT_RM "rm"
+ #define ASM_OUTPUT_RM "=rm"
#endif
#ifdef CONFIG_CC_HAS_ASM_INLINE
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 04ceeca12a0d..f5c9cf28c4dc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3247,7 +3247,7 @@ struct offset_ctx {
void simple_offset_init(struct offset_ctx *octx);
int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry);
void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry);
-int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
+void simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
int simple_offset_rename_exchange(struct inode *old_dir,
struct dentry *old_dentry,
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
index 0bd581003cd5..60de63e46b33 100644
--- a/include/linux/genalloc.h
+++ b/include/linux/genalloc.h
@@ -44,6 +44,7 @@ struct gen_pool;
* @nr: The number of zeroed bits we're looking for
* @data: optional additional data used by the callback
* @pool: the pool being allocated from
+ * @start_addr: start address of memory chunk
*/
typedef unsigned long (*genpool_algo_t)(unsigned long *map,
unsigned long size,
diff --git a/include/linux/intel_rapl.h b/include/linux/intel_rapl.h
index e9ade2ff4af6..f479ef5b3341 100644
--- a/include/linux/intel_rapl.h
+++ b/include/linux/intel_rapl.h
@@ -214,10 +214,14 @@ void rapl_remove_package(struct rapl_package *rp);
#ifdef CONFIG_PERF_EVENTS
int rapl_package_add_pmu(struct rapl_package *rp);
+int rapl_package_add_pmu_locked(struct rapl_package *rp);
void rapl_package_remove_pmu(struct rapl_package *rp);
+void rapl_package_remove_pmu_locked(struct rapl_package *rp);
#else
static inline int rapl_package_add_pmu(struct rapl_package *rp) { return 0; }
+static inline int rapl_package_add_pmu_locked(struct rapl_package *rp) { return 0; }
static inline void rapl_package_remove_pmu(struct rapl_package *rp) { }
+static inline void rapl_package_remove_pmu_locked(struct rapl_package *rp) { }
#endif
#endif /* __INTEL_RAPL_H__ */
diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h
index 53f6fe88e369..1a0f357c2427 100644
--- a/include/linux/intel_vsec.h
+++ b/include/linux/intel_vsec.h
@@ -80,13 +80,13 @@ enum intel_vsec_quirks {
/**
* struct pmt_callbacks - Callback infrastructure for PMT devices
- * ->read_telem() when specified, called by client driver to access PMT data (instead
- * of direct copy).
- * @pdev: PCI device reference for the callback's use
- * @guid: ID of data to acccss
- * @data: buffer for the data to be copied
- * @off: offset into the requested buffer
- * @count: size of buffer
+ * @read_telem: when specified, called by client driver to access PMT
+ * data (instead of direct copy).
+ * * pdev: PCI device reference for the callback's use
+ * * guid: ID of data to acccss
+ * * data: buffer for the data to be copied
+ * * off: offset into the requested buffer
+ * * count: size of buffer
*/
struct pmt_callbacks {
int (*read_telem)(struct pci_dev *pdev, u32 guid, u64 *data, loff_t off, u32 count);
@@ -120,7 +120,7 @@ struct intel_vsec_platform_info {
};
/**
- * struct intel_sec_device - Auxbus specific device information
+ * struct intel_vsec_device - Auxbus specific device information
* @auxdev: auxbus device struct for auxbus access
* @pcidev: pci device associated with the device
* @resource: any resources shared by the parent
@@ -128,6 +128,7 @@ struct intel_vsec_platform_info {
* @num_resources: number of resources
* @id: xarray id
* @priv_data: any private data needed
+ * @priv_data_size: size of private data area
* @quirks: specified quirks
* @base_addr: base address of entries (if specified)
* @cap_id: the enumerated id of the vsec feature
diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
index e1adb0d20a0a..a3e8ddc9b380 100644
--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -424,11 +424,17 @@ struct io_ring_ctx {
struct user_struct *user;
struct mm_struct *mm_account;
+ /*
+ * List of tctx nodes for this ctx, protected by tctx_lock. For
+ * cancelation purposes, nests under uring_lock.
+ */
+ struct list_head tctx_list;
+ struct mutex tctx_lock;
+
/* ctx exit and cancelation */
struct llist_head fallback_llist;
struct delayed_work fallback_work;
struct work_struct exit_work;
- struct list_head tctx_list;
struct completion ref_comp;
/* io-wq management, e.g. thread count */
diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
index 6ab913e57da0..d26d1b1bcbfb 100644
--- a/include/linux/irq-entry-common.h
+++ b/include/linux/irq-entry-common.h
@@ -110,7 +110,7 @@ static __always_inline void enter_from_user_mode(struct pt_regs *regs)
static inline void local_irq_enable_exit_to_user(unsigned long ti_work);
#ifndef local_irq_enable_exit_to_user
-static inline void local_irq_enable_exit_to_user(unsigned long ti_work)
+static __always_inline void local_irq_enable_exit_to_user(unsigned long ti_work)
{
local_irq_enable();
}
@@ -125,7 +125,7 @@ static inline void local_irq_enable_exit_to_user(unsigned long ti_work)
static inline void local_irq_disable_exit_to_user(void);
#ifndef local_irq_disable_exit_to_user
-static inline void local_irq_disable_exit_to_user(void)
+static __always_inline void local_irq_disable_exit_to_user(void)
{
local_irq_disable();
}
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index f335c1d7b61d..9c6ac4b62eb9 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -28,6 +28,7 @@ typedef unsigned int __bitwise kasan_vmalloc_flags_t;
#define KASAN_VMALLOC_INIT ((__force kasan_vmalloc_flags_t)0x01u)
#define KASAN_VMALLOC_VM_ALLOC ((__force kasan_vmalloc_flags_t)0x02u)
#define KASAN_VMALLOC_PROT_NORMAL ((__force kasan_vmalloc_flags_t)0x04u)
+#define KASAN_VMALLOC_KEEP_TAG ((__force kasan_vmalloc_flags_t)0x08u)
#define KASAN_VMALLOC_PAGE_RANGE 0x1 /* Apply exsiting page range */
#define KASAN_VMALLOC_TLB_FLUSH 0x2 /* TLB flush */
@@ -630,6 +631,16 @@ static __always_inline void kasan_poison_vmalloc(const void *start,
__kasan_poison_vmalloc(start, size);
}
+void __kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms,
+ kasan_vmalloc_flags_t flags);
+static __always_inline void
+kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms,
+ kasan_vmalloc_flags_t flags)
+{
+ if (kasan_enabled())
+ __kasan_unpoison_vmap_areas(vms, nr_vms, flags);
+}
+
#else /* CONFIG_KASAN_VMALLOC */
static inline void kasan_populate_early_vm_area_shadow(void *start,
@@ -654,6 +665,11 @@ static inline void *kasan_unpoison_vmalloc(const void *start,
static inline void kasan_poison_vmalloc(const void *start, unsigned long size)
{ }
+static __always_inline void
+kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms,
+ kasan_vmalloc_flags_t flags)
+{ }
+
#endif /* CONFIG_KASAN_VMALLOC */
#if (defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) && \
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index ff7e231b0485..8a22bc9b8c6c 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -530,7 +530,7 @@ extern bool kexec_file_dbg_print;
#define kexec_dprintk(fmt, arg...) \
do { if (kexec_file_dbg_print) pr_info(fmt, ##arg); } while (0)
-extern void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size);
+extern void *kimage_map_segment(struct kimage *image, int idx);
extern void kimage_unmap_segment(void *buffer);
#else /* !CONFIG_KEXEC_CORE */
struct pt_regs;
@@ -540,7 +540,7 @@ static inline void __crash_kexec(struct pt_regs *regs) { }
static inline void crash_kexec(struct pt_regs *regs) { }
static inline int kexec_should_crash(struct task_struct *p) { return 0; }
static inline int kexec_crash_loaded(void) { return 0; }
-static inline void *kimage_map_segment(struct kimage *image, unsigned long addr, unsigned long size)
+static inline void *kimage_map_segment(struct kimage *image, int idx)
{ return NULL; }
static inline void kimage_unmap_segment(void *buffer) { }
#define kexec_in_progress false
diff --git a/include/linux/leafops.h b/include/linux/leafops.h
index cfafe7a5e7b1..a9ff94b744f2 100644
--- a/include/linux/leafops.h
+++ b/include/linux/leafops.h
@@ -133,7 +133,7 @@ static inline bool softleaf_is_none(softleaf_t entry)
/**
* softleaf_type() - Identify the type of leaf entry.
- * @enntry: Leaf entry.
+ * @entry: Leaf entry.
*
* Returns: the leaf entry type associated with @entry.
*/
@@ -534,7 +534,7 @@ static inline bool pte_is_uffd_wp_marker(pte_t pte)
/**
* pte_is_uffd_marker() - Does this PTE entry encode a userfault-specific marker
* leaf entry?
- * @entry: Leaf entry.
+ * @pte: PTE entry.
*
* It's useful to be able to determine which leaf entries encode UFFD-specific
* markers so we can handle these correctly.
diff --git a/include/linux/memory-failure.h b/include/linux/memory-failure.h
index bc326503d2d2..7b5e11cf905f 100644
--- a/include/linux/memory-failure.h
+++ b/include/linux/memory-failure.h
@@ -9,6 +9,8 @@ struct pfn_address_space;
struct pfn_address_space {
struct interval_tree_node node;
struct address_space *mapping;
+ int (*pfn_to_vma_pgoff)(struct vm_area_struct *vma,
+ unsigned long pfn, pgoff_t *pgoff);
};
int register_pfn_address_space(struct pfn_address_space *pfn_space);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 15076261d0c2..6f959d8ca4b4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2459,10 +2459,10 @@ static inline int folio_expected_ref_count(const struct folio *folio)
if (WARN_ON_ONCE(page_has_type(&folio->page) && !folio_test_hugetlb(folio)))
return 0;
- if (folio_test_anon(folio)) {
- /* One reference per page from the swapcache. */
- ref_count += folio_test_swapcache(folio) << order;
- } else {
+ /* One reference per page from the swapcache. */
+ ref_count += folio_test_swapcache(folio) << order;
+
+ if (!folio_test_anon(folio)) {
/* One reference per page from the pagecache. */
ref_count += !!folio->mapping << order;
/* One reference from PG_private. */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 9f6de068295d..42af2292951d 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -1631,7 +1631,6 @@ enum tlb_flush_reason {
TLB_LOCAL_MM_SHOOTDOWN,
TLB_REMOTE_SEND_IPI,
TLB_REMOTE_WRONG_CPU,
- NR_TLB_FLUSH_REASONS,
};
/**
diff --git a/include/linux/property.h b/include/linux/property.h
index 272bfbdea7bf..e30ef23a9af3 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -371,6 +371,7 @@ struct software_node_ref_args {
(const struct software_node_ref_args) { \
.swnode = _Generic(_ref_, \
const struct software_node *: _ref_, \
+ struct software_node *: _ref_, \
default: NULL), \
.fwnode = _Generic(_ref_, \
struct fwnode_handle *: _ref_, \
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 978cf593b662..09f3b67638f9 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -635,6 +635,7 @@ struct regulator_dev {
int ref_cnt;
struct module *owner;
struct device dev;
+ struct device bdev;
struct regulation_constraints *constraints;
struct regulator *supply; /* for tree */
const char *supply_name;
@@ -649,6 +650,7 @@ struct regulator_dev {
struct regulator_enable_gpio *ena_pin;
unsigned int ena_gpio_state:1;
+ unsigned int constraints_pending:1;
unsigned int is_switch:1;
/* time when this regulator was disabled last time */
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 706877f998ff..1ac86896875c 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -145,6 +145,13 @@ struct vfio_pci_core_device {
struct list_head dmabufs;
};
+enum vfio_pci_io_width {
+ VFIO_PCI_IO_WIDTH_1 = 1,
+ VFIO_PCI_IO_WIDTH_2 = 2,
+ VFIO_PCI_IO_WIDTH_4 = 4,
+ VFIO_PCI_IO_WIDTH_8 = 8,
+};
+
/* Will be exported for vfio pci drivers usage */
int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev,
unsigned int type, unsigned int subtype,
@@ -188,7 +195,8 @@ pci_ers_result_t vfio_pci_core_aer_err_detected(struct pci_dev *pdev,
ssize_t vfio_pci_core_do_io_rw(struct vfio_pci_core_device *vdev, bool test_mem,
void __iomem *io, char __user *buf,
loff_t off, size_t count, size_t x_start,
- size_t x_end, bool iswrite);
+ size_t x_end, bool iswrite,
+ enum vfio_pci_io_width max_width);
bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev);
bool vfio_pci_core_range_intersect_range(loff_t buf_start, size_t buf_cnt,
loff_t reg_start, size_t reg_cnt,
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 132a474e5914..3626eb694728 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -13,6 +13,8 @@
#include <linux/completion.h>
#include <linux/virtio_features.h>
+struct module;
+
/**
* struct virtqueue - a queue to register buffers for sending or receiving.
* @list: the chain of virtqueues for this device
diff --git a/include/linux/virtio_features.h b/include/linux/virtio_features.h
index ea2ad8717882..ce59ea91f474 100644
--- a/include/linux/virtio_features.h
+++ b/include/linux/virtio_features.h
@@ -3,6 +3,8 @@
#define _LINUX_VIRTIO_FEATURES_H
#include <linux/bits.h>
+#include <linux/bug.h>
+#include <linux/string.h>
#define VIRTIO_FEATURES_U64S 2
#define VIRTIO_FEATURES_BITS (VIRTIO_FEATURES_U64S * 64)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index cced1a866757..6b2b5ed64ea4 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -302,6 +302,7 @@ struct dsa_port {
struct devlink_port devlink_port;
struct phylink *pl;
struct phylink_config pl_config;
+ netdevice_tracker conduit_tracker;
struct dsa_lag *lag;
struct net_device *hsr_dev;
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 0eccd9c3a883..365925c9d262 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -123,27 +123,15 @@ void inet_frags_fini(struct inet_frags *);
int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net);
-static inline void fqdir_pre_exit(struct fqdir *fqdir)
-{
- /* Prevent creation of new frags.
- * Pairs with READ_ONCE() in inet_frag_find().
- */
- WRITE_ONCE(fqdir->high_thresh, 0);
-
- /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
- * and ip6frag_expire_frag_queue().
- */
- WRITE_ONCE(fqdir->dead, true);
-}
+void fqdir_pre_exit(struct fqdir *fqdir);
void fqdir_exit(struct fqdir *fqdir);
void inet_frag_kill(struct inet_frag_queue *q, int *refs);
void inet_frag_destroy(struct inet_frag_queue *q);
struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key);
-/* Free all skbs in the queue; return the sum of their truesizes. */
-unsigned int inet_frag_rbtree_purge(struct rb_root *root,
- enum skb_drop_reason reason);
+void inet_frag_queue_flush(struct inet_frag_queue *q,
+ enum skb_drop_reason reason);
static inline void inet_frag_putn(struct inet_frag_queue *q, int refs)
{
diff --git a/include/net/ipv6_frag.h b/include/net/ipv6_frag.h
index 38ef66826939..41d9fc6965f9 100644
--- a/include/net/ipv6_frag.h
+++ b/include/net/ipv6_frag.h
@@ -69,9 +69,6 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
int refs = 1;
rcu_read_lock();
- /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
- if (READ_ONCE(fq->q.fqdir->dead))
- goto out_rcu_unlock;
spin_lock(&fq->q.lock);
if (fq->q.flags & INET_FRAG_COMPLETE)
@@ -80,6 +77,12 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
fq->q.flags |= INET_FRAG_DROP;
inet_frag_kill(&fq->q, &refs);
+ /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
+ if (READ_ONCE(fq->q.fqdir->dead)) {
+ inet_frag_queue_flush(&fq->q, 0);
+ goto out;
+ }
+
dev = dev_get_by_index_rcu(net, fq->iif);
if (!dev)
goto out;
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index fab7dc73f738..0e266c2d0e7f 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1091,6 +1091,29 @@ struct nft_rule_blob {
__attribute__((aligned(__alignof__(struct nft_rule_dp))));
};
+enum nft_chain_types {
+ NFT_CHAIN_T_DEFAULT = 0,
+ NFT_CHAIN_T_ROUTE,
+ NFT_CHAIN_T_NAT,
+ NFT_CHAIN_T_MAX
+};
+
+/**
+ * struct nft_chain_validate_state - validation state
+ *
+ * If a chain is encountered again during table validation it is
+ * possible to avoid revalidation provided the calling context is
+ * compatible. This structure stores relevant calling context of
+ * previous validations.
+ *
+ * @hook_mask: the hook numbers and locations the chain is linked to
+ * @depth: the deepest call chain level the chain is linked to
+ */
+struct nft_chain_validate_state {
+ u8 hook_mask[NFT_CHAIN_T_MAX];
+ u8 depth;
+};
+
/**
* struct nft_chain - nf_tables chain
*
@@ -1109,6 +1132,7 @@ struct nft_rule_blob {
* @udlen: user data length
* @udata: user data in the chain
* @blob_next: rule blob pointer to the next in the chain
+ * @vstate: validation state
*/
struct nft_chain {
struct nft_rule_blob __rcu *blob_gen_0;
@@ -1128,9 +1152,10 @@ struct nft_chain {
/* Only used during control plane commit phase: */
struct nft_rule_blob *blob_next;
+ struct nft_chain_validate_state vstate;
};
-int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain);
+int nft_chain_validate(const struct nft_ctx *ctx, struct nft_chain *chain);
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
const struct nft_set_iter *iter,
struct nft_elem_priv *elem_priv);
@@ -1138,13 +1163,6 @@ int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
-enum nft_chain_types {
- NFT_CHAIN_T_DEFAULT = 0,
- NFT_CHAIN_T_ROUTE,
- NFT_CHAIN_T_NAT,
- NFT_CHAIN_T_MAX
-};
-
/**
* struct nft_chain_type - nf_tables chain type info
*
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index 90d73b9bddab..0519afd7217f 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -203,6 +203,8 @@ struct snd_soc_acpi_link_adr {
* @mach: the pointer of the machine driver
* @prefix: the prefix of the topology file name. Typically, it is the path.
* @tplg_files: the pointer of the array of the topology file names.
+ * @best_effort: ignore non supported links and try to build the card in best effort
+ * with supported links
*/
/* Descriptor for SST ASoC machine driver */
struct snd_soc_acpi_mach {
@@ -224,7 +226,8 @@ struct snd_soc_acpi_mach {
const u32 tplg_quirk_mask;
int (*get_function_tplg_files)(struct snd_soc_card *card,
const struct snd_soc_acpi_mach *mach,
- const char *prefix, const char ***tplg_files);
+ const char *prefix, const char ***tplg_files,
+ bool best_effort);
};
#define SND_SOC_ACPI_MAX_CODECS 3
diff --git a/include/trace/events/tlb.h b/include/trace/events/tlb.h
index b4d8e7dc38f8..fb8369511685 100644
--- a/include/trace/events/tlb.h
+++ b/include/trace/events/tlb.h
@@ -12,8 +12,9 @@
EM( TLB_FLUSH_ON_TASK_SWITCH, "flush on task switch" ) \
EM( TLB_REMOTE_SHOOTDOWN, "remote shootdown" ) \
EM( TLB_LOCAL_SHOOTDOWN, "local shootdown" ) \
- EM( TLB_LOCAL_MM_SHOOTDOWN, "local mm shootdown" ) \
- EMe( TLB_REMOTE_SEND_IPI, "remote ipi send" )
+ EM( TLB_LOCAL_MM_SHOOTDOWN, "local MM shootdown" ) \
+ EM( TLB_REMOTE_SEND_IPI, "remote IPI send" ) \
+ EMe( TLB_REMOTE_WRONG_CPU, "remote wrong CPU" )
/*
* First define the enums in TLB_FLUSH_REASON to be exported to userspace
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 47853659a705..f64dc0eff0e6 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -1463,6 +1463,7 @@ struct drm_xe_exec {
/** @exec_queue_id: Exec queue ID for the batch buffer */
__u32 exec_queue_id;
+#define DRM_XE_MAX_SYNCS 1024
/** @num_syncs: Amount of struct drm_xe_sync in array. */
__u32 num_syncs;
diff --git a/include/uapi/linux/energy_model.h b/include/uapi/linux/energy_model.h
index 4ec4c0eabbbb..0bcad967854f 100644
--- a/include/uapi/linux/energy_model.h
+++ b/include/uapi/linux/energy_model.h
@@ -2,6 +2,7 @@
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/em.yaml */
/* YNL-GEN uapi header */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
#ifndef _UAPI_LINUX_ENERGY_MODEL_H
#define _UAPI_LINUX_ENERGY_MODEL_H
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 30f3c9eaafaa..4bdb6a165987 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -891,6 +891,7 @@
#define ABS_VOLUME 0x20
#define ABS_PROFILE 0x21
+#define ABS_SND_PROFILE 0x22
#define ABS_MISC 0x28
@@ -1000,4 +1001,12 @@
#define SND_MAX 0x07
#define SND_CNT (SND_MAX+1)
+/*
+ * ABS_SND_PROFILE values
+ */
+
+#define SND_PROFILE_SILENT 0x00
+#define SND_PROFILE_VIBRATE 0x01
+#define SND_PROFILE_RING 0x02
+
#endif
diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
index 04eea6d1d0a9..72a5d030154e 100644
--- a/include/uapi/linux/mptcp.h
+++ b/include/uapi/linux/mptcp.h
@@ -40,6 +40,7 @@
#define MPTCP_PM_ADDR_FLAG_FULLMESH _BITUL(3)
#define MPTCP_PM_ADDR_FLAG_IMPLICIT _BITUL(4)
#define MPTCP_PM_ADDR_FLAG_LAMINAR _BITUL(5)
+#define MPTCP_PM_ADDR_FLAGS_MASK GENMASK(5, 0)
struct mptcp_info {
__u8 mptcpi_subflows;
diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h
index 847f3051057a..f0ecb1677317 100644
--- a/include/uapi/linux/pr.h
+++ b/include/uapi/linux/pr.h
@@ -79,4 +79,6 @@ struct pr_read_reservation {
#define IOC_PR_READ_KEYS _IOWR('p', 206, struct pr_read_keys)
#define IOC_PR_READ_RESERVATION _IOR('p', 207, struct pr_read_reservation)
+#define PR_KEYS_MAX (1u << 16)
+
#endif /* _UAPI_PR_H */
diff --git a/include/uapi/rdma/irdma-abi.h b/include/uapi/rdma/irdma-abi.h
index f7788d33376b..36f20802bcc8 100644
--- a/include/uapi/rdma/irdma-abi.h
+++ b/include/uapi/rdma/irdma-abi.h
@@ -57,8 +57,8 @@ struct irdma_alloc_ucontext_resp {
__u8 rsvd2;
__aligned_u64 comp_mask;
__u16 min_hw_wq_size;
+ __u8 revd3[2];
__u32 max_hw_srq_quanta;
- __u8 rsvd3[2];
};
struct irdma_alloc_pd_resp {
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h
index 5ded174687ee..838f8d460256 100644
--- a/include/uapi/rdma/rdma_user_cm.h
+++ b/include/uapi/rdma/rdma_user_cm.h
@@ -192,6 +192,7 @@ struct rdma_ucm_query_path_resp {
struct rdma_ucm_query_ib_service_resp {
__u32 num_service_recs;
+ __u32 reserved;
struct ib_user_service_rec recs[];
};
@@ -354,7 +355,7 @@ enum {
#define RDMA_USER_CM_IB_SERVICE_NAME_SIZE 64
struct rdma_ucm_ib_service {
- __u64 service_id;
+ __aligned_u64 service_id;
__u8 service_name[RDMA_USER_CM_IB_SERVICE_NAME_SIZE];
__u32 flags;
__u32 reserved;
@@ -362,6 +363,7 @@ struct rdma_ucm_ib_service {
struct rdma_ucm_resolve_ib_service {
__u32 id;
+ __u32 reserved;
struct rdma_ucm_ib_service ibs;
};
diff --git a/include/uapi/regulator/regulator.h b/include/uapi/regulator/regulator.h
index 71bf71a22e7f..c4f2d1c19828 100644
--- a/include/uapi/regulator/regulator.h
+++ b/include/uapi/regulator/regulator.h
@@ -8,11 +8,7 @@
#ifndef _UAPI_REGULATOR_H
#define _UAPI_REGULATOR_H
-#ifdef __KERNEL__
#include <linux/types.h>
-#else
-#include <stdint.h>
-#endif
/*
* Regulator notifier events.
@@ -62,7 +58,7 @@
struct reg_genl_event {
char reg_name[32];
- uint64_t event;
+ __u64 event;
};
/* attributes of reg_genl_family */
diff --git a/io_uring/cancel.c b/io_uring/cancel.c
index ca12ac10c0ae..07b8d852218b 100644
--- a/io_uring/cancel.c
+++ b/io_uring/cancel.c
@@ -184,7 +184,9 @@ static int __io_async_cancel(struct io_cancel_data *cd,
} while (1);
/* slow path, try all io-wq's */
+ __set_current_state(TASK_RUNNING);
io_ring_submit_lock(ctx, issue_flags);
+ mutex_lock(&ctx->tctx_lock);
ret = -ENOENT;
list_for_each_entry(node, &ctx->tctx_list, ctx_node) {
ret = io_async_cancel_one(node->task->io_uring, cd);
@@ -194,6 +196,7 @@ static int __io_async_cancel(struct io_cancel_data *cd,
nr++;
}
}
+ mutex_unlock(&ctx->tctx_lock);
io_ring_submit_unlock(ctx, issue_flags);
return all ? nr : ret;
}
@@ -484,6 +487,7 @@ static __cold bool io_uring_try_cancel_iowq(struct io_ring_ctx *ctx)
bool ret = false;
mutex_lock(&ctx->uring_lock);
+ mutex_lock(&ctx->tctx_lock);
list_for_each_entry(node, &ctx->tctx_list, ctx_node) {
struct io_uring_task *tctx = node->task->io_uring;
@@ -496,6 +500,7 @@ static __cold bool io_uring_try_cancel_iowq(struct io_ring_ctx *ctx)
cret = io_wq_cancel_cb(tctx->io_wq, io_cancel_ctx_cb, ctx, true);
ret |= (cret != IO_WQ_CANCEL_NOTFOUND);
}
+ mutex_unlock(&ctx->tctx_lock);
mutex_unlock(&ctx->uring_lock);
return ret;
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 6cb24cdf8e68..87a87396e940 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -340,6 +340,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
INIT_LIST_HEAD(&ctx->ltimeout_list);
init_llist_head(&ctx->work_llist);
INIT_LIST_HEAD(&ctx->tctx_list);
+ mutex_init(&ctx->tctx_lock);
ctx->submit_state.free_list.next = NULL;
INIT_HLIST_HEAD(&ctx->waitid_list);
xa_init_flags(&ctx->zcrx_ctxs, XA_FLAGS_ALLOC);
@@ -864,7 +865,7 @@ static __cold bool io_cqe_overflow_locked(struct io_ring_ctx *ctx,
{
struct io_overflow_cqe *ocqe;
- ocqe = io_alloc_ocqe(ctx, cqe, big_cqe, GFP_ATOMIC);
+ ocqe = io_alloc_ocqe(ctx, cqe, big_cqe, GFP_NOWAIT);
return io_cqring_add_overflow(ctx, ocqe);
}
@@ -3045,6 +3046,7 @@ static __cold void io_ring_exit_work(struct work_struct *work)
exit.ctx = ctx;
mutex_lock(&ctx->uring_lock);
+ mutex_lock(&ctx->tctx_lock);
while (!list_empty(&ctx->tctx_list)) {
WARN_ON_ONCE(time_after(jiffies, timeout));
@@ -3056,6 +3058,7 @@ static __cold void io_ring_exit_work(struct work_struct *work)
if (WARN_ON_ONCE(ret))
continue;
+ mutex_unlock(&ctx->tctx_lock);
mutex_unlock(&ctx->uring_lock);
/*
* See comment above for
@@ -3064,7 +3067,9 @@ static __cold void io_ring_exit_work(struct work_struct *work)
*/
wait_for_completion_interruptible(&exit.completion);
mutex_lock(&ctx->uring_lock);
+ mutex_lock(&ctx->tctx_lock);
}
+ mutex_unlock(&ctx->tctx_lock);
mutex_unlock(&ctx->uring_lock);
spin_lock(&ctx->completion_lock);
spin_unlock(&ctx->completion_lock);
diff --git a/io_uring/memmap.c b/io_uring/memmap.c
index 18e574776ef6..7d3c5eb58480 100644
--- a/io_uring/memmap.c
+++ b/io_uring/memmap.c
@@ -268,8 +268,7 @@ static void *io_region_validate_mmap(struct io_ring_ctx *ctx,
return io_region_get_ptr(mr);
}
-static void *io_uring_validate_mmap_request(struct file *file, loff_t pgoff,
- size_t sz)
+static void *io_uring_validate_mmap_request(struct file *file, loff_t pgoff)
{
struct io_ring_ctx *ctx = file->private_data;
struct io_mapped_region *region;
@@ -304,7 +303,7 @@ __cold int io_uring_mmap(struct file *file, struct vm_area_struct *vma)
guard(mutex)(&ctx->mmap_lock);
- ptr = io_uring_validate_mmap_request(file, vma->vm_pgoff, sz);
+ ptr = io_uring_validate_mmap_request(file, vma->vm_pgoff);
if (IS_ERR(ptr))
return PTR_ERR(ptr);
@@ -336,7 +335,7 @@ unsigned long io_uring_get_unmapped_area(struct file *filp, unsigned long addr,
guard(mutex)(&ctx->mmap_lock);
- ptr = io_uring_validate_mmap_request(filp, pgoff, len);
+ ptr = io_uring_validate_mmap_request(filp, pgoff);
if (IS_ERR(ptr))
return -ENOMEM;
@@ -386,7 +385,7 @@ unsigned long io_uring_get_unmapped_area(struct file *file, unsigned long addr,
guard(mutex)(&ctx->mmap_lock);
- ptr = io_uring_validate_mmap_request(file, pgoff, len);
+ ptr = io_uring_validate_mmap_request(file, pgoff);
if (IS_ERR(ptr))
return PTR_ERR(ptr);
diff --git a/io_uring/openclose.c b/io_uring/openclose.c
index bfeb91b31bba..15dde9bd6ff6 100644
--- a/io_uring/openclose.c
+++ b/io_uring/openclose.c
@@ -73,13 +73,13 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
open->filename = NULL;
return ret;
}
+ req->flags |= REQ_F_NEED_CLEANUP;
open->file_slot = READ_ONCE(sqe->file_index);
if (open->file_slot && (open->how.flags & O_CLOEXEC))
return -EINVAL;
open->nofile = rlimit(RLIMIT_NOFILE);
- req->flags |= REQ_F_NEED_CLEANUP;
if (io_openat_force_async(open))
req->flags |= REQ_F_FORCE_ASYNC;
return 0;
diff --git a/io_uring/register.c b/io_uring/register.c
index 62d39b3ff317..3d3822ff3fd9 100644
--- a/io_uring/register.c
+++ b/io_uring/register.c
@@ -320,6 +320,7 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
return 0;
/* now propagate the restriction to all registered users */
+ mutex_lock(&ctx->tctx_lock);
list_for_each_entry(node, &ctx->tctx_list, ctx_node) {
tctx = node->task->io_uring;
if (WARN_ON_ONCE(!tctx->io_wq))
@@ -330,6 +331,7 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
/* ignore errors, it always returns zero anyway */
(void)io_wq_max_workers(tctx->io_wq, new_count);
}
+ mutex_unlock(&ctx->tctx_lock);
return 0;
err:
if (sqd) {
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index a63474b331bf..41c89f5c616d 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -1059,6 +1059,7 @@ static int io_import_kbuf(int ddir, struct iov_iter *iter,
if (count < imu->len) {
const struct bio_vec *bvec = iter->bvec;
+ len += iter->iov_offset;
while (len > bvec->bv_len) {
len -= bvec->bv_len;
bvec++;
diff --git a/io_uring/tctx.c b/io_uring/tctx.c
index 5b66755579c0..6d6f44215ec8 100644
--- a/io_uring/tctx.c
+++ b/io_uring/tctx.c
@@ -136,9 +136,9 @@ int __io_uring_add_tctx_node(struct io_ring_ctx *ctx)
return ret;
}
- mutex_lock(&ctx->uring_lock);
+ mutex_lock(&ctx->tctx_lock);
list_add(&node->ctx_node, &ctx->tctx_list);
- mutex_unlock(&ctx->uring_lock);
+ mutex_unlock(&ctx->tctx_lock);
}
return 0;
}
@@ -176,9 +176,9 @@ __cold void io_uring_del_tctx_node(unsigned long index)
WARN_ON_ONCE(current != node->task);
WARN_ON_ONCE(list_empty(&node->ctx_node));
- mutex_lock(&node->ctx->uring_lock);
+ mutex_lock(&node->ctx->tctx_lock);
list_del(&node->ctx_node);
- mutex_unlock(&node->ctx->uring_lock);
+ mutex_unlock(&node->ctx->tctx_lock);
if (tctx->last == node->ctx)
tctx->last = NULL;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index c8ae6ab31651..1b9b18e5b03c 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -760,6 +760,22 @@ struct bpf_prog *bpf_prog_ksym_find(unsigned long addr)
NULL;
}
+bool bpf_has_frame_pointer(unsigned long ip)
+{
+ struct bpf_ksym *ksym;
+ unsigned long offset;
+
+ guard(rcu)();
+
+ ksym = bpf_ksym_find(ip);
+ if (!ksym || !ksym->fp_start || !ksym->fp_end)
+ return false;
+
+ offset = ip - ksym->start;
+
+ return offset >= ksym->fp_start && offset < ksym->fp_end;
+}
+
const struct exception_table_entry *search_bpf_extables(unsigned long addr)
{
const struct exception_table_entry *e = NULL;
diff --git a/kernel/bpf/dmabuf_iter.c b/kernel/bpf/dmabuf_iter.c
index 4dd7ef7c145c..cd500248abd9 100644
--- a/kernel/bpf/dmabuf_iter.c
+++ b/kernel/bpf/dmabuf_iter.c
@@ -6,10 +6,33 @@
#include <linux/kernel.h>
#include <linux/seq_file.h>
+struct dmabuf_iter_priv {
+ /*
+ * If this pointer is non-NULL, the buffer's refcount is elevated to
+ * prevent destruction between stop/start. If reading is not resumed and
+ * start is never called again, then dmabuf_iter_seq_fini drops the
+ * reference when the iterator is released.
+ */
+ struct dma_buf *dmabuf;
+};
+
static void *dmabuf_iter_seq_start(struct seq_file *seq, loff_t *pos)
{
- if (*pos)
- return NULL;
+ struct dmabuf_iter_priv *p = seq->private;
+
+ if (*pos) {
+ struct dma_buf *dmabuf = p->dmabuf;
+
+ if (!dmabuf)
+ return NULL;
+
+ /*
+ * Always resume from where we stopped, regardless of the value
+ * of pos.
+ */
+ p->dmabuf = NULL;
+ return dmabuf;
+ }
return dma_buf_iter_begin();
}
@@ -54,8 +77,11 @@ static void dmabuf_iter_seq_stop(struct seq_file *seq, void *v)
{
struct dma_buf *dmabuf = v;
- if (dmabuf)
- dma_buf_put(dmabuf);
+ if (dmabuf) {
+ struct dmabuf_iter_priv *p = seq->private;
+
+ p->dmabuf = dmabuf;
+ }
}
static const struct seq_operations dmabuf_iter_seq_ops = {
@@ -71,11 +97,27 @@ static void bpf_iter_dmabuf_show_fdinfo(const struct bpf_iter_aux_info *aux,
seq_puts(seq, "dmabuf iter\n");
}
+static int dmabuf_iter_seq_init(void *priv, struct bpf_iter_aux_info *aux)
+{
+ struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv;
+
+ p->dmabuf = NULL;
+ return 0;
+}
+
+static void dmabuf_iter_seq_fini(void *priv)
+{
+ struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv;
+
+ if (p->dmabuf)
+ dma_buf_put(p->dmabuf);
+}
+
static const struct bpf_iter_seq_info dmabuf_iter_seq_info = {
.seq_ops = &dmabuf_iter_seq_ops,
- .init_seq_private = NULL,
- .fini_seq_private = NULL,
- .seq_priv_size = 0,
+ .init_seq_private = dmabuf_iter_seq_init,
+ .fini_seq_private = dmabuf_iter_seq_fini,
+ .seq_priv_size = sizeof(struct dmabuf_iter_priv),
};
static struct bpf_iter_reg bpf_dmabuf_reg_info = {
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 6e6eb09b8db6..3e8cc34d8d50 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1668,7 +1668,14 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
{
WARN_ON_ONCE(!is_remote_partition(cs));
- WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus));
+ /*
+ * When a CPU is offlined, top_cpuset may end up with no available CPUs,
+ * which should clear subpartitions_cpus. We should not emit a warning for this
+ * scenario: the hierarchy is updated from top to bottom, so subpartitions_cpus
+ * may already be cleared when disabling the partition.
+ */
+ WARN_ON_ONCE(!cpumask_subset(cs->effective_xcpus, subpartitions_cpus) &&
+ !cpumask_empty(subpartitions_cpus));
spin_lock_irq(&callback_lock);
cs->remote_partition = false;
@@ -3976,8 +3983,9 @@ retry:
if (remote || (is_partition_valid(cs) && is_partition_valid(parent)))
compute_partition_effective_cpumask(cs, &new_cpus);
- if (remote && cpumask_empty(&new_cpus) &&
- partition_is_populated(cs, NULL)) {
+ if (remote && (cpumask_empty(subpartitions_cpus) ||
+ (cpumask_empty(&new_cpus) &&
+ partition_is_populated(cs, NULL)))) {
cs->prs_err = PERR_HOTPLUG;
remote_partition_disable(cs, tmp);
compute_effective_cpumask(&new_cpus, cs, parent);
@@ -3990,9 +3998,12 @@ retry:
* 1) empty effective cpus but not valid empty partition.
* 2) parent is invalid or doesn't grant any cpus to child
* partitions.
+ * 3) subpartitions_cpus is empty.
*/
- if (is_local_partition(cs) && (!is_partition_valid(parent) ||
- tasks_nocpu_error(parent, cs, &new_cpus)))
+ if (is_local_partition(cs) &&
+ (!is_partition_valid(parent) ||
+ tasks_nocpu_error(parent, cs, &new_cpus) ||
+ cpumask_empty(subpartitions_cpus)))
partcmd = partcmd_invalidate;
/*
* On the other hand, an invalid partition root may be transitioned
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index a198e40c799b..150e5871e66f 100644
--- a/kernel/cgroup/rstat.c
+++ b/kernel/cgroup/rstat.c
@@ -71,7 +71,6 @@ __bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu)
{
struct llist_head *lhead;
struct css_rstat_cpu *rstatc;
- struct css_rstat_cpu __percpu *rstatc_pcpu;
struct llist_node *self;
/*
@@ -104,18 +103,22 @@ __bpf_kfunc void css_rstat_updated(struct cgroup_subsys_state *css, int cpu)
/*
* This function can be renentered by irqs and nmis for the same cgroup
* and may try to insert the same per-cpu lnode into the llist. Note
- * that llist_add() does not protect against such scenarios.
+ * that llist_add() does not protect against such scenarios. In addition
+ * this same per-cpu lnode can be modified through init_llist_node()
+ * from css_rstat_flush() running on a different CPU.
*
* To protect against such stacked contexts of irqs/nmis, we use the
* fact that lnode points to itself when not on a list and then use
- * this_cpu_cmpxchg() to atomically set to NULL to select the winner
+ * try_cmpxchg() to atomically set to NULL to select the winner
* which will call llist_add(). The losers can assume the insertion is
* successful and the winner will eventually add the per-cpu lnode to
* the llist.
+ *
+ * Please note that we can not use this_cpu_cmpxchg() here as on some
+ * archs it is not safe against modifications from multiple CPUs.
*/
self = &rstatc->lnode;
- rstatc_pcpu = css->rstat_cpu;
- if (this_cpu_cmpxchg(rstatc_pcpu->lnode.next, self, NULL) != self)
+ if (!try_cmpxchg(&rstatc->lnode.next, &self, NULL))
return;
lhead = ss_lhead_cpu(css->ss, cpu);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8b1b4c8a4f54..349ae7979da0 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1414,7 +1414,7 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary)
* Ensure the thread adjusts the affinity once it reaches the
* thread function.
*/
- new->thread_flags = BIT(IRQTF_AFFINITY);
+ set_bit(IRQTF_AFFINITY, &new->thread_flags);
return 0;
}
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 0f92acdd354d..95c585c6ddc3 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -953,17 +953,24 @@ int kimage_load_segment(struct kimage *image, int idx)
return result;
}
-void *kimage_map_segment(struct kimage *image,
- unsigned long addr, unsigned long size)
+void *kimage_map_segment(struct kimage *image, int idx)
{
+ unsigned long addr, size, eaddr;
unsigned long src_page_addr, dest_page_addr = 0;
- unsigned long eaddr = addr + size;
kimage_entry_t *ptr, entry;
struct page **src_pages;
unsigned int npages;
+ struct page *cma;
void *vaddr = NULL;
int i;
+ cma = image->segment_cma[idx];
+ if (cma)
+ return page_address(cma);
+
+ addr = image->segment[idx].mem;
+ size = image->segment[idx].memsz;
+ eaddr = addr + size;
/*
* Collect the source pages and map them in a contiguous VA range.
*/
@@ -1004,7 +1011,8 @@ void *kimage_map_segment(struct kimage *image,
void kimage_unmap_segment(void *segment_buffer)
{
- vunmap(segment_buffer);
+ if (is_vmalloc_addr(segment_buffer))
+ vunmap(segment_buffer);
}
struct kexec_load_limit {
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 99a3808d086f..39511dd2abc9 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -1599,6 +1599,7 @@ void kthread_use_mm(struct mm_struct *mm)
WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
WARN_ON_ONCE(tsk->mm);
+ WARN_ON_ONCE(!mm->user_ns);
/*
* It is possible for mm to be the same as tsk->active_mm, but
diff --git a/kernel/power/em_netlink_autogen.c b/kernel/power/em_netlink_autogen.c
index a7a09ab1d1c2..ceb3b2bb6ebe 100644
--- a/kernel/power/em_netlink_autogen.c
+++ b/kernel/power/em_netlink_autogen.c
@@ -2,6 +2,7 @@
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/em.yaml */
/* YNL-GEN kernel source */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
#include <net/netlink.h>
#include <net/genetlink.h>
diff --git a/kernel/power/em_netlink_autogen.h b/kernel/power/em_netlink_autogen.h
index 78ce609641f1..140ab548103c 100644
--- a/kernel/power/em_netlink_autogen.h
+++ b/kernel/power/em_netlink_autogen.h
@@ -2,6 +2,7 @@
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/em.yaml */
/* YNL-GEN kernel header */
+/* To regenerate run: tools/net/ynl/ynl-regen.sh */
#ifndef _LINUX_EM_GEN_H
#define _LINUX_EM_GEN_H
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 2da4482bb6eb..57c44268698f 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -349,9 +349,12 @@ static int suspend_test(int level)
if (pm_test_level == level) {
pr_info("suspend debug: Waiting for %d second(s).\n",
pm_test_delay);
- for (i = 0; i < pm_test_delay && !pm_wakeup_pending(); i++)
- msleep(1000);
-
+ for (i = 0; i < pm_test_delay && !pm_wakeup_pending(); i++) {
+ if (level > TEST_CORE)
+ msleep(1000);
+ else
+ mdelay(1000);
+ }
return 1;
}
#endif /* !CONFIG_PM_DEBUG */
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 05f5a49e9649..8f6d8d7f895c 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -41,6 +41,13 @@ static bool scx_init_task_enabled;
static bool scx_switching_all;
DEFINE_STATIC_KEY_FALSE(__scx_switched_all);
+/*
+ * Tracks whether scx_enable() called scx_bypass(true). Used to balance bypass
+ * depth on enable failure. Will be removed when bypass depth is moved into the
+ * sched instance.
+ */
+static bool scx_bypassed_for_enable;
+
static atomic_long_t scx_nr_rejected = ATOMIC_LONG_INIT(0);
static atomic_long_t scx_hotplug_seq = ATOMIC_LONG_INIT(0);
@@ -975,6 +982,30 @@ static void refill_task_slice_dfl(struct scx_sched *sch, struct task_struct *p)
__scx_add_event(sch, SCX_EV_REFILL_SLICE_DFL, 1);
}
+static void local_dsq_post_enq(struct scx_dispatch_q *dsq, struct task_struct *p,
+ u64 enq_flags)
+{
+ struct rq *rq = container_of(dsq, struct rq, scx.local_dsq);
+ bool preempt = false;
+
+ /*
+ * If @rq is in balance, the CPU is already vacant and looking for the
+ * next task to run. No need to preempt or trigger resched after moving
+ * @p into its local DSQ.
+ */
+ if (rq->scx.flags & SCX_RQ_IN_BALANCE)
+ return;
+
+ if ((enq_flags & SCX_ENQ_PREEMPT) && p != rq->curr &&
+ rq->curr->sched_class == &ext_sched_class) {
+ rq->curr->scx.slice = 0;
+ preempt = true;
+ }
+
+ if (preempt || sched_class_above(&ext_sched_class, rq->curr->sched_class))
+ resched_curr(rq);
+}
+
static void dispatch_enqueue(struct scx_sched *sch, struct scx_dispatch_q *dsq,
struct task_struct *p, u64 enq_flags)
{
@@ -1086,22 +1117,10 @@ static void dispatch_enqueue(struct scx_sched *sch, struct scx_dispatch_q *dsq,
if (enq_flags & SCX_ENQ_CLEAR_OPSS)
atomic_long_set_release(&p->scx.ops_state, SCX_OPSS_NONE);
- if (is_local) {
- struct rq *rq = container_of(dsq, struct rq, scx.local_dsq);
- bool preempt = false;
-
- if ((enq_flags & SCX_ENQ_PREEMPT) && p != rq->curr &&
- rq->curr->sched_class == &ext_sched_class) {
- rq->curr->scx.slice = 0;
- preempt = true;
- }
-
- if (preempt || sched_class_above(&ext_sched_class,
- rq->curr->sched_class))
- resched_curr(rq);
- } else {
+ if (is_local)
+ local_dsq_post_enq(dsq, p, enq_flags);
+ else
raw_spin_unlock(&dsq->lock);
- }
}
static void task_unlink_from_dsq(struct task_struct *p,
@@ -1558,7 +1577,7 @@ static bool dequeue_task_scx(struct rq *rq, struct task_struct *p, int deq_flags
*
* @p may go through multiple stopping <-> running transitions between
* here and put_prev_task_scx() if task attribute changes occur while
- * balance_scx() leaves @rq unlocked. However, they don't contain any
+ * balance_one() leaves @rq unlocked. However, they don't contain any
* information meaningful to the BPF scheduler and can be suppressed by
* skipping the callbacks if the task is !QUEUED.
*/
@@ -1625,6 +1644,8 @@ static void move_local_task_to_local_dsq(struct task_struct *p, u64 enq_flags,
dsq_mod_nr(dst_dsq, 1);
p->scx.dsq = dst_dsq;
+
+ local_dsq_post_enq(dst_dsq, p, enq_flags);
}
/**
@@ -2351,7 +2372,7 @@ static void switch_class(struct rq *rq, struct task_struct *next)
* preempted, and it regaining control of the CPU.
*
* ->cpu_release() complements ->cpu_acquire(), which is emitted the
- * next time that balance_scx() is invoked.
+ * next time that balance_one() is invoked.
*/
if (!rq->scx.cpu_released) {
if (SCX_HAS_OP(sch, cpu_release)) {
@@ -2402,7 +2423,7 @@ static void put_prev_task_scx(struct rq *rq, struct task_struct *p,
* ops.enqueue() that @p is the only one available for this cpu,
* which should trigger an explicit follow-up scheduling event.
*/
- if (sched_class_above(&ext_sched_class, next->sched_class)) {
+ if (next && sched_class_above(&ext_sched_class, next->sched_class)) {
WARN_ON_ONCE(!(sch->ops.flags & SCX_OPS_ENQ_LAST));
do_enqueue_task(rq, p, SCX_ENQ_LAST, -1);
} else {
@@ -2425,7 +2446,7 @@ static struct task_struct *
do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
{
struct task_struct *prev = rq->curr;
- bool keep_prev, kick_idle = false;
+ bool keep_prev;
struct task_struct *p;
/* see kick_cpus_irq_workfn() */
@@ -2457,7 +2478,7 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
}
/*
- * If balance_scx() is telling us to keep running @prev, replenish slice
+ * If balance_one() is telling us to keep running @prev, replenish slice
* if necessary and keep running @prev. Otherwise, pop the first one
* from the local DSQ.
*/
@@ -2467,12 +2488,8 @@ do_pick_task_scx(struct rq *rq, struct rq_flags *rf, bool force_scx)
refill_task_slice_dfl(rcu_dereference_sched(scx_root), p);
} else {
p = first_local_task(rq);
- if (!p) {
- if (kick_idle)
- scx_kick_cpu(rcu_dereference_sched(scx_root),
- cpu_of(rq), SCX_KICK_IDLE);
+ if (!p)
return NULL;
- }
if (unlikely(!p->scx.slice)) {
struct scx_sched *sch = rcu_dereference_sched(scx_root);
@@ -3575,7 +3592,7 @@ static void scx_sched_free_rcu_work(struct work_struct *work)
int node;
irq_work_sync(&sch->error_irq_work);
- kthread_stop(sch->helper->task);
+ kthread_destroy_worker(sch->helper);
free_percpu(sch->pcpu);
@@ -3939,13 +3956,8 @@ static void bypass_lb_node(struct scx_sched *sch, int node)
nr_donor_target, nr_target);
}
- for_each_cpu(cpu, resched_mask) {
- struct rq *rq = cpu_rq(cpu);
-
- raw_spin_rq_lock_irq(rq);
- resched_curr(rq);
- raw_spin_rq_unlock_irq(rq);
- }
+ for_each_cpu(cpu, resched_mask)
+ resched_cpu(cpu);
for_each_cpu_and(cpu, cpu_online_mask, node_mask) {
u32 nr = READ_ONCE(cpu_rq(cpu)->scx.bypass_dsq.nr);
@@ -4008,7 +4020,7 @@ static DEFINE_TIMER(scx_bypass_lb_timer, scx_bypass_lb_timerfn);
*
* - ops.dispatch() is ignored.
*
- * - balance_scx() does not set %SCX_RQ_BAL_KEEP on non-zero slice as slice
+ * - balance_one() does not set %SCX_RQ_BAL_KEEP on non-zero slice as slice
* can't be trusted. Whenever a tick triggers, the running task is rotated to
* the tail of the queue with core_sched_at touched.
*
@@ -4318,6 +4330,11 @@ static void scx_disable_workfn(struct kthread_work *work)
scx_dsp_max_batch = 0;
free_kick_syncs();
+ if (scx_bypassed_for_enable) {
+ scx_bypassed_for_enable = false;
+ scx_bypass(false);
+ }
+
mutex_unlock(&scx_enable_mutex);
WARN_ON_ONCE(scx_set_enable_state(SCX_DISABLED) != SCX_DISABLING);
@@ -4761,8 +4778,10 @@ static struct scx_sched *scx_alloc_and_add_sched(struct sched_ext_ops *ops)
}
sch->pcpu = alloc_percpu(struct scx_sched_pcpu);
- if (!sch->pcpu)
+ if (!sch->pcpu) {
+ ret = -ENOMEM;
goto err_free_gdsqs;
+ }
sch->helper = kthread_run_worker(0, "sched_ext_helper");
if (IS_ERR(sch->helper)) {
@@ -4786,7 +4805,7 @@ static struct scx_sched *scx_alloc_and_add_sched(struct sched_ext_ops *ops)
return sch;
err_stop_helper:
- kthread_stop(sch->helper->task);
+ kthread_destroy_worker(sch->helper);
err_free_pcpu:
free_percpu(sch->pcpu);
err_free_gdsqs:
@@ -4970,6 +4989,7 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link)
* Init in bypass mode to guarantee forward progress.
*/
scx_bypass(true);
+ scx_bypassed_for_enable = true;
for (i = SCX_OPI_NORMAL_BEGIN; i < SCX_OPI_NORMAL_END; i++)
if (((void (**)(void))ops)[i])
@@ -5067,6 +5087,7 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link)
scx_task_iter_stop(&sti);
percpu_up_write(&scx_fork_rwsem);
+ scx_bypassed_for_enable = false;
scx_bypass(false);
if (!scx_tryset_enable_state(SCX_ENABLED, SCX_ENABLING)) {
@@ -6043,7 +6064,7 @@ __bpf_kfunc bool scx_bpf_dsq_move_to_local(u64 dsq_id)
/*
* A successfully consumed task can be dequeued before it starts
* running while the CPU is trying to migrate other dispatched
- * tasks. Bump nr_tasks to tell balance_scx() to retry on empty
+ * tasks. Bump nr_tasks to tell balance_one() to retry on empty
* local DSQ.
*/
dspc->nr_tasks++;
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index d57727abaade..fe28d86f7c35 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -965,7 +965,7 @@ static const struct bpf_func_proto bpf_d_path_proto = {
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_BTF_ID,
.arg1_btf_id = &bpf_d_path_btf_ids[0],
- .arg2_type = ARG_PTR_TO_MEM,
+ .arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
.allowed = bpf_d_path_allowed,
};
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 3ec2033c0774..ef2d5dca6f70 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4518,8 +4518,11 @@ static int t_show(struct seq_file *m, void *v)
unsigned long direct;
direct = ftrace_find_rec_direct(rec->ip);
- if (direct)
- seq_printf(m, "\n\tdirect-->%pS", (void *)direct);
+ if (direct) {
+ seq_printf(m, "\n\tdirect%s-->%pS",
+ ftrace_is_jmp(direct) ? "(jmp)" : "",
+ (void *)ftrace_jmp_get(direct));
+ }
}
}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index e575956ef9b5..6f2148df14d9 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -10507,7 +10507,7 @@ static int __remove_instance(struct trace_array *tr)
/* Disable all the flags that were enabled coming in */
for (i = 0; i < TRACE_FLAGS_MAX_SIZE; i++) {
- if ((1 << i) & ZEROED_TRACE_FLAGS)
+ if ((1ULL << i) & ZEROED_TRACE_FLAGS)
set_tracer_flag(tr, 1ULL << i, 0);
}
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index b16a5a158040..76067529db61 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -700,6 +700,8 @@ int trace_event_reg(struct trace_event_call *call,
#ifdef CONFIG_PERF_EVENTS
case TRACE_REG_PERF_REGISTER:
+ if (!call->class->perf_probe)
+ return -ENODEV;
return tracepoint_probe_register(call->tp,
call->class->perf_probe,
call);
diff --git a/lib/crypto/riscv/.gitignore b/lib/crypto/riscv/.gitignore
new file mode 100644
index 000000000000..0d47d4f21c6d
--- /dev/null
+++ b/lib/crypto/riscv/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+poly1305-core.S
diff --git a/lib/idr.c b/lib/idr.c
index e2adc457abb4..457430cff8c5 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -40,6 +40,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid,
if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR)))
idr->idr_rt.xa_flags |= IDR_RT_MARKER;
+ if (max < base)
+ return -ENOSPC;
id = (id < base) ? 0 : id - base;
radix_tree_iter_init(&iter, id);
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index 50ecf55d2b9c..498cc51e493d 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -28,7 +28,7 @@ config KUNIT_FAULT_TEST
bool "Enable KUnit tests which print BUG stacktraces"
depends on KUNIT_TEST
depends on !UML
- default y
+ default !PANIC_ON_OOPS
help
Enables fault handling tests for the KUnit framework. These tests may
trigger a kernel BUG(), and the associated stack trace, even when they
diff --git a/lib/kunit/device.c b/lib/kunit/device.c
index 520c1fccee8a..f201aaacd4cf 100644
--- a/lib/kunit/device.c
+++ b/lib/kunit/device.c
@@ -106,8 +106,7 @@ EXPORT_SYMBOL_GPL(kunit_driver_create);
/* Helper which creates a kunit_device, attaches it to the kunit_bus*/
static struct kunit_device *kunit_device_register_internal(struct kunit *test,
- const char *name,
- const struct device_driver *drv)
+ const char *name)
{
struct kunit_device *kunit_dev;
int err = -ENOMEM;
@@ -150,7 +149,7 @@ struct device *kunit_device_register_with_driver(struct kunit *test,
const char *name,
const struct device_driver *drv)
{
- struct kunit_device *kunit_dev = kunit_device_register_internal(test, name, drv);
+ struct kunit_device *kunit_dev = kunit_device_register_internal(test, name);
if (IS_ERR_OR_NULL(kunit_dev))
return ERR_CAST(kunit_dev);
@@ -172,7 +171,7 @@ struct device *kunit_device_register(struct kunit *test, const char *name)
if (IS_ERR(drv))
return ERR_CAST(drv);
- dev = kunit_device_register_internal(test, name, drv);
+ dev = kunit_device_register_internal(test, name);
if (IS_ERR(dev)) {
kunit_release_action(test, driver_unregister_wrapper, (void *)drv);
return ERR_CAST(dev);
diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
index 2750c88e7225..23ed738a0bd6 100644
--- a/mm/damon/vaddr.c
+++ b/mm/damon/vaddr.c
@@ -743,7 +743,7 @@ huge_out:
if (!folio)
continue;
if (damos_va_filter_out(s, folio, walk->vma, addr, pte, NULL))
- return 0;
+ continue;
damos_va_migrate_dests_add(folio, walk->vma, addr, dests,
migration_lists);
nr = folio_nr_pages(folio);
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 1d27f1bd260b..ed489a14dddf 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -28,6 +28,7 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/bug.h>
+#include <linux/vmalloc.h>
#include "kasan.h"
#include "../slab.h"
@@ -575,3 +576,34 @@ bool __kasan_check_byte(const void *address, unsigned long ip)
}
return true;
}
+
+#ifdef CONFIG_KASAN_VMALLOC
+void __kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms,
+ kasan_vmalloc_flags_t flags)
+{
+ unsigned long size;
+ void *addr;
+ int area;
+ u8 tag;
+
+ /*
+ * If KASAN_VMALLOC_KEEP_TAG was set at this point, all vms[] pointers
+ * would be unpoisoned with the KASAN_TAG_KERNEL which would disable
+ * KASAN checks down the line.
+ */
+ if (WARN_ON_ONCE(flags & KASAN_VMALLOC_KEEP_TAG))
+ return;
+
+ size = vms[0]->size;
+ addr = vms[0]->addr;
+ vms[0]->addr = __kasan_unpoison_vmalloc(addr, size, flags);
+ tag = get_tag(vms[0]->addr);
+
+ for (area = 1 ; area < nr_vms ; area++) {
+ size = vms[area]->size;
+ addr = set_tag(vms[area]->addr, tag);
+ vms[area]->addr =
+ __kasan_unpoison_vmalloc(addr, size, flags | KASAN_VMALLOC_KEEP_TAG);
+ }
+}
+#endif
diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c
index 1c373cc4b3fa..cbef5e450954 100644
--- a/mm/kasan/hw_tags.c
+++ b/mm/kasan/hw_tags.c
@@ -361,7 +361,7 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size,
return (void *)start;
}
- tag = kasan_random_tag();
+ tag = (flags & KASAN_VMALLOC_KEEP_TAG) ? get_tag(start) : kasan_random_tag();
start = set_tag(start, tag);
/* Unpoison and initialize memory up to size. */
diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c
index 29a751a8a08d..32fbdf759ea2 100644
--- a/mm/kasan/shadow.c
+++ b/mm/kasan/shadow.c
@@ -631,7 +631,9 @@ void *__kasan_unpoison_vmalloc(const void *start, unsigned long size,
!(flags & KASAN_VMALLOC_PROT_NORMAL))
return (void *)start;
- start = set_tag(start, kasan_random_tag());
+ if (unlikely(!(flags & KASAN_VMALLOC_KEEP_TAG)))
+ start = set_tag(start, kasan_random_tag());
+
kasan_unpoison(start, size, false);
return (void *)start;
}
diff --git a/mm/ksm.c b/mm/ksm.c
index cfc182255c7b..2d89a7c8b4eb 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -650,7 +650,7 @@ static int break_ksm_pmd_entry(pmd_t *pmdp, unsigned long addr, unsigned long en
}
}
out_unlock:
- pte_unmap_unlock(ptep, ptl);
+ pte_unmap_unlock(start_ptep, ptl);
return found;
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index be810c1fbfc3..86f43b7e5f71 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5638,6 +5638,6 @@ void mem_cgroup_show_protected_memory(struct mem_cgroup *memcg)
memcg = root_mem_cgroup;
pr_warn("Memory cgroup min protection %lukB -- low protection %lukB",
- K(atomic_long_read(&memcg->memory.children_min_usage)*PAGE_SIZE),
- K(atomic_long_read(&memcg->memory.children_low_usage)*PAGE_SIZE));
+ K(atomic_long_read(&memcg->memory.children_min_usage)),
+ K(atomic_long_read(&memcg->memory.children_low_usage)));
}
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index fbc5a01260c8..c80c2907da33 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -2161,6 +2161,9 @@ int register_pfn_address_space(struct pfn_address_space *pfn_space)
{
guard(mutex)(&pfn_space_lock);
+ if (!pfn_space->pfn_to_vma_pgoff)
+ return -EINVAL;
+
if (interval_tree_iter_first(&pfn_space_itree,
pfn_space->node.start,
pfn_space->node.last))
@@ -2183,10 +2186,10 @@ void unregister_pfn_address_space(struct pfn_address_space *pfn_space)
}
EXPORT_SYMBOL_GPL(unregister_pfn_address_space);
-static void add_to_kill_pfn(struct task_struct *tsk,
- struct vm_area_struct *vma,
- struct list_head *to_kill,
- unsigned long pfn)
+static void add_to_kill_pgoff(struct task_struct *tsk,
+ struct vm_area_struct *vma,
+ struct list_head *to_kill,
+ pgoff_t pgoff)
{
struct to_kill *tk;
@@ -2197,12 +2200,12 @@ static void add_to_kill_pfn(struct task_struct *tsk,
}
/* Check for pgoff not backed by struct page */
- tk->addr = vma_address(vma, pfn, 1);
+ tk->addr = vma_address(vma, pgoff, 1);
tk->size_shift = PAGE_SHIFT;
if (tk->addr == -EFAULT)
pr_info("Unable to find address %lx in %s\n",
- pfn, tsk->comm);
+ pgoff, tsk->comm);
get_task_struct(tsk);
tk->tsk = tsk;
@@ -2212,11 +2215,12 @@ static void add_to_kill_pfn(struct task_struct *tsk,
/*
* Collect processes when the error hit a PFN not backed by struct page.
*/
-static void collect_procs_pfn(struct address_space *mapping,
+static void collect_procs_pfn(struct pfn_address_space *pfn_space,
unsigned long pfn, struct list_head *to_kill)
{
struct vm_area_struct *vma;
struct task_struct *tsk;
+ struct address_space *mapping = pfn_space->mapping;
i_mmap_lock_read(mapping);
rcu_read_lock();
@@ -2226,9 +2230,12 @@ static void collect_procs_pfn(struct address_space *mapping,
t = task_early_kill(tsk, true);
if (!t)
continue;
- vma_interval_tree_foreach(vma, &mapping->i_mmap, pfn, pfn) {
- if (vma->vm_mm == t->mm)
- add_to_kill_pfn(t, vma, to_kill, pfn);
+ vma_interval_tree_foreach(vma, &mapping->i_mmap, 0, ULONG_MAX) {
+ pgoff_t pgoff;
+
+ if (vma->vm_mm == t->mm &&
+ !pfn_space->pfn_to_vma_pgoff(vma, pfn, &pgoff))
+ add_to_kill_pgoff(t, vma, to_kill, pgoff);
}
}
rcu_read_unlock();
@@ -2264,7 +2271,7 @@ static int memory_failure_pfn(unsigned long pfn, int flags)
struct pfn_address_space *pfn_space =
container_of(node, struct pfn_address_space, node);
- collect_procs_pfn(pfn_space->mapping, pfn, &tokill);
+ collect_procs_pfn(pfn_space, pfn, &tokill);
mf_handled = true;
}
diff --git a/mm/memremap.c b/mm/memremap.c
index 4c2e0d68eb27..63c6ab4fdf08 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -427,8 +427,6 @@ void free_zone_device_folio(struct folio *folio)
if (folio_test_anon(folio)) {
for (i = 0; i < nr; i++)
__ClearPageAnonExclusive(folio_page(folio, i));
- } else {
- VM_WARN_ON_ONCE(folio_test_large(folio));
}
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 822e05f1a964..c380f063e8b7 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -914,6 +914,17 @@ buddy_merge_likely(unsigned long pfn, unsigned long buddy_pfn,
NULL) != NULL;
}
+static void change_pageblock_range(struct page *pageblock_page,
+ int start_order, int migratetype)
+{
+ int nr_pageblocks = 1 << (start_order - pageblock_order);
+
+ while (nr_pageblocks--) {
+ set_pageblock_migratetype(pageblock_page, migratetype);
+ pageblock_page += pageblock_nr_pages;
+ }
+}
+
/*
* Freeing function for a buddy system allocator.
*
@@ -1000,7 +1011,7 @@ static inline void __free_one_page(struct page *page,
* expand() down the line puts the sub-blocks
* on the right freelists.
*/
- set_pageblock_migratetype(buddy, migratetype);
+ change_pageblock_range(buddy, order, migratetype);
}
combined_pfn = buddy_pfn & pfn;
@@ -2147,17 +2158,6 @@ bool pageblock_unisolate_and_move_free_pages(struct zone *zone, struct page *pag
#endif /* CONFIG_MEMORY_ISOLATION */
-static void change_pageblock_range(struct page *pageblock_page,
- int start_order, int migratetype)
-{
- int nr_pageblocks = 1 << (start_order - pageblock_order);
-
- while (nr_pageblocks--) {
- set_pageblock_migratetype(pageblock_page, migratetype);
- pageblock_page += pageblock_nr_pages;
- }
-}
-
static inline bool boost_watermark(struct zone *zone)
{
unsigned long max_boost;
@@ -5924,7 +5924,7 @@ static int zone_batchsize(struct zone *zone)
* recycled, this leads to the once large chunks of space being
* fragmented and becoming unavailable for high-order allocations.
*/
- return 0;
+ return 1;
#endif
}
diff --git a/mm/page_owner.c b/mm/page_owner.c
index a70245684206..b3260f0c17ba 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -952,7 +952,7 @@ static const struct file_operations page_owner_stack_fops = {
.open = page_owner_stack_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_private,
};
static int page_owner_threshold_get(void *data, u64 *val)
diff --git a/mm/shmem.c b/mm/shmem.c
index b329b5302c48..ec6c01378e9d 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -4019,22 +4019,10 @@ static int shmem_whiteout(struct mnt_idmap *idmap,
whiteout = d_alloc(old_dentry->d_parent, &old_dentry->d_name);
if (!whiteout)
return -ENOMEM;
-
error = shmem_mknod(idmap, old_dir, whiteout,
S_IFCHR | WHITEOUT_MODE, WHITEOUT_DEV);
dput(whiteout);
- if (error)
- return error;
-
- /*
- * Cheat and hash the whiteout while the old dentry is still in
- * place, instead of playing games with FS_RENAME_DOES_D_MOVE.
- *
- * d_lookup() will consistently find one of them at this point,
- * not sure which one, but that isn't even important.
- */
- d_rehash(whiteout);
- return 0;
+ return error;
}
/*
@@ -4050,6 +4038,7 @@ static int shmem_rename2(struct mnt_idmap *idmap,
{
struct inode *inode = d_inode(old_dentry);
int they_are_dirs = S_ISDIR(inode->i_mode);
+ bool had_offset = false;
int error;
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
@@ -4062,16 +4051,23 @@ static int shmem_rename2(struct mnt_idmap *idmap,
if (!simple_empty(new_dentry))
return -ENOTEMPTY;
+ error = simple_offset_add(shmem_get_offset_ctx(new_dir), new_dentry);
+ if (error == -EBUSY)
+ had_offset = true;
+ else if (unlikely(error))
+ return error;
+
if (flags & RENAME_WHITEOUT) {
error = shmem_whiteout(idmap, old_dir, old_dentry);
- if (error)
+ if (error) {
+ if (!had_offset)
+ simple_offset_remove(shmem_get_offset_ctx(new_dir),
+ new_dentry);
return error;
+ }
}
- error = simple_offset_rename(old_dir, old_dentry, new_dir, new_dentry);
- if (error)
- return error;
-
+ simple_offset_rename(old_dir, old_dentry, new_dir, new_dentry);
if (d_really_is_positive(new_dentry)) {
(void) shmem_unlink(new_dir, new_dentry);
if (they_are_dirs) {
diff --git a/mm/slub.c b/mm/slub.c
index f21b2f0c6f5a..861592ac5425 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -6539,6 +6539,8 @@ static void defer_free(struct kmem_cache *s, void *head)
guard(preempt)();
+ head = kasan_reset_tag(head);
+
df = this_cpu_ptr(&defer_free_objects);
if (llist_add(head + s->offset, &df->objects))
irq_work_queue(&df->work);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ecbac900c35f..41dd01e8430c 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -4331,7 +4331,9 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
*/
if (size <= alloced_size) {
kasan_unpoison_vmalloc(p + old_size, size - old_size,
- KASAN_VMALLOC_PROT_NORMAL);
+ KASAN_VMALLOC_PROT_NORMAL |
+ KASAN_VMALLOC_VM_ALLOC |
+ KASAN_VMALLOC_KEEP_TAG);
/*
* No need to zero memory here, as unused memory will have
* already been zeroed at initial allocation time or during
@@ -5025,9 +5027,7 @@ retry:
* With hardware tag-based KASAN, marking is skipped for
* non-VM_ALLOC mappings, see __kasan_unpoison_vmalloc().
*/
- for (area = 0; area < nr_vms; area++)
- vms[area]->addr = kasan_unpoison_vmalloc(vms[area]->addr,
- vms[area]->size, KASAN_VMALLOC_PROT_NORMAL);
+ kasan_unpoison_vmap_areas(vms, nr_vms, KASAN_VMALLOC_PROT_NORMAL);
kfree(vas);
return vms;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c11cdef42b6f..5be9b8c91949 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -849,6 +849,12 @@ static u32 get_supported_settings(struct hci_dev *hdev)
if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL;
+ if (bis_capable(hdev))
+ settings |= MGMT_SETTING_ISO_BROADCASTER;
+
+ if (sync_recv_capable(hdev))
+ settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
+
if (ll_privacy_capable(hdev))
settings |= MGMT_SETTING_LL_PRIVACY;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 7280c4e9305f..b9b2981c4841 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -247,6 +247,7 @@ struct net_bridge_vlan {
* struct net_bridge_vlan_group
*
* @vlan_hash: VLAN entry rhashtable
+ * @tunnel_hash: Hash table to map from tunnel key ID (e.g. VXLAN VNI) to VLAN
* @vlan_list: sorted VLAN entry list
* @num_vlans: number of total VLAN entries
* @pvid: PVID VLAN id
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index 6651a8dc62e0..d4d63586053a 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
len = le16_to_cpu(tmp);
/* Subtract for FCS on length if FCS is not used. */
- if (!this->dofcs)
+ if (!this->dofcs) {
+ if (len < 2) {
+ ++cffrml_rcv_error;
+ pr_err("Invalid frame length (%d)\n", len);
+ cfpkt_destroy(pkt);
+ return -EPROTO;
+ }
len -= 2;
+ }
if (cfpkt_setlen(pkt, len) < 0) {
++cffrml_rcv_error;
diff --git a/net/can/Kconfig b/net/can/Kconfig
index e4ccf731a24c..af64a6f76458 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -5,7 +5,6 @@
menuconfig CAN
tristate "CAN bus subsystem support"
- select CAN_DEV
help
Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial
communications protocol. Development of the CAN bus started in
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index 6272326dd614..ff9c4fd7b433 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -482,6 +482,12 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr_unsized *uaddr, in
goto out_release_sock;
}
+ if (ndev->reg_state != NETREG_REGISTERED) {
+ dev_put(ndev);
+ ret = -ENODEV;
+ goto out_release_sock;
+ }
+
can_ml = can_get_ml_priv(ndev);
if (!can_ml) {
dev_put(ndev);
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index fbf5c8001c9d..613a911dda10 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -1567,6 +1567,8 @@ int j1939_session_activate(struct j1939_session *session)
if (active) {
j1939_session_put(active);
ret = -EAGAIN;
+ } else if (priv->ndev->reg_state != NETREG_REGISTERED) {
+ ret = -ENODEV;
} else {
WARN_ON_ONCE(session->state != J1939_SESSION_NEW);
list_add_tail(&session->active_session_list_entry,
diff --git a/net/core/dev.c b/net/core/dev.c
index 9094c0fb8c68..36dc5199037e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4241,9 +4241,11 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
int count = 0;
llist_for_each_entry_safe(skb, next, ll_list, ll_node) {
- prefetch(next);
- prefetch(&next->priority);
- skb_mark_not_on_list(skb);
+ if (next) {
+ prefetch(next);
+ prefetch(&next->priority);
+ skb_mark_not_on_list(skb);
+ }
rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
count++;
}
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index a20efabe778f..99ede37698ac 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -367,16 +367,10 @@ static struct dsa_port *dsa_tree_find_first_cpu(struct dsa_switch_tree *dst)
struct net_device *dsa_tree_find_first_conduit(struct dsa_switch_tree *dst)
{
- struct device_node *ethernet;
- struct net_device *conduit;
struct dsa_port *cpu_dp;
cpu_dp = dsa_tree_find_first_cpu(dst);
- ethernet = of_parse_phandle(cpu_dp->dn, "ethernet", 0);
- conduit = of_find_net_device_by_node(ethernet);
- of_node_put(ethernet);
-
- return conduit;
+ return cpu_dp->conduit;
}
/* Assign the default CPU port (the first one in the tree) to all ports of the
@@ -1253,14 +1247,25 @@ static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
if (ethernet) {
struct net_device *conduit;
const char *user_protocol;
+ int err;
+ rtnl_lock();
conduit = of_find_net_device_by_node(ethernet);
of_node_put(ethernet);
- if (!conduit)
+ if (!conduit) {
+ rtnl_unlock();
return -EPROBE_DEFER;
+ }
+
+ netdev_hold(conduit, &dp->conduit_tracker, GFP_KERNEL);
+ put_device(&conduit->dev);
+ rtnl_unlock();
user_protocol = of_get_property(dn, "dsa-tag-protocol", NULL);
- return dsa_port_parse_cpu(dp, conduit, user_protocol);
+ err = dsa_port_parse_cpu(dp, conduit, user_protocol);
+ if (err)
+ netdev_put(conduit, &dp->conduit_tracker);
+ return err;
}
if (link)
@@ -1393,37 +1398,30 @@ static struct device *dev_find_class(struct device *parent, char *class)
return device_find_child(parent, class, dev_is_class);
}
-static struct net_device *dsa_dev_to_net_device(struct device *dev)
-{
- struct device *d;
-
- d = dev_find_class(dev, "net");
- if (d != NULL) {
- struct net_device *nd;
-
- nd = to_net_dev(d);
- dev_hold(nd);
- put_device(d);
-
- return nd;
- }
-
- return NULL;
-}
-
static int dsa_port_parse(struct dsa_port *dp, const char *name,
struct device *dev)
{
if (!strcmp(name, "cpu")) {
struct net_device *conduit;
+ struct device *d;
+ int err;
- conduit = dsa_dev_to_net_device(dev);
- if (!conduit)
+ rtnl_lock();
+ d = dev_find_class(dev, "net");
+ if (!d) {
+ rtnl_unlock();
return -EPROBE_DEFER;
+ }
- dev_put(conduit);
+ conduit = to_net_dev(d);
+ netdev_hold(conduit, &dp->conduit_tracker, GFP_KERNEL);
+ put_device(d);
+ rtnl_unlock();
- return dsa_port_parse_cpu(dp, conduit, NULL);
+ err = dsa_port_parse_cpu(dp, conduit, NULL);
+ if (err)
+ netdev_put(conduit, &dp->conduit_tracker);
+ return err;
}
if (!strcmp(name, "dsa"))
@@ -1491,6 +1489,9 @@ static void dsa_switch_release_ports(struct dsa_switch *ds)
struct dsa_vlan *v, *n;
dsa_switch_for_each_port_safe(dp, next, ds) {
+ if (dsa_port_is_cpu(dp) && dp->conduit)
+ netdev_put(dp->conduit, &dp->conduit_tracker);
+
/* These are either entries that upper layers lost track of
* (probably due to bugs), or installed through interfaces
* where one does not necessarily have to remove them, like
@@ -1635,8 +1636,10 @@ void dsa_switch_shutdown(struct dsa_switch *ds)
/* Disconnect from further netdevice notifiers on the conduit,
* since netdev_uses_dsa() will now return false.
*/
- dsa_switch_for_each_cpu_port(dp, ds)
+ dsa_switch_for_each_cpu_port(dp, ds) {
dp->conduit->dsa_ptr = NULL;
+ netdev_put(dp->conduit, &dp->conduit_tracker);
+ }
rtnl_unlock();
out:
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index fa83ddade4f8..9431e305b233 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -2383,7 +2383,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
return -ENOMEM;
WARN_ON_ONCE(!ret);
- gstrings.len = ret;
+ if (gstrings.len && gstrings.len != ret)
+ gstrings.len = 0;
+ else
+ gstrings.len = ret;
if (gstrings.len) {
data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN));
@@ -2509,10 +2512,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
if (copy_from_user(&stats, useraddr, sizeof(stats)))
return -EFAULT;
- stats.n_stats = n_stats;
+ if (stats.n_stats && stats.n_stats != n_stats)
+ stats.n_stats = 0;
+ else
+ stats.n_stats = n_stats;
- if (n_stats) {
- data = vzalloc(array_size(n_stats, sizeof(u64)));
+ if (stats.n_stats) {
+ data = vzalloc(array_size(stats.n_stats, sizeof(u64)));
if (!data)
return -ENOMEM;
ops->get_ethtool_stats(dev, &stats, data);
@@ -2524,7 +2530,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
if (copy_to_user(useraddr, &stats, sizeof(stats)))
goto out;
useraddr += sizeof(stats);
- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64))))
+ if (stats.n_stats &&
+ copy_to_user(useraddr, data,
+ array_size(stats.n_stats, sizeof(u64))))
goto out;
ret = 0;
@@ -2560,6 +2568,10 @@ static int ethtool_get_phy_stats_phydev(struct phy_device *phydev,
return -EOPNOTSUPP;
n_stats = phy_ops->get_sset_count(phydev);
+ if (stats->n_stats && stats->n_stats != n_stats) {
+ stats->n_stats = 0;
+ return 0;
+ }
ret = ethtool_vzalloc_stats_array(n_stats, data);
if (ret)
@@ -2580,6 +2592,10 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev,
return -EOPNOTSUPP;
n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
+ if (stats->n_stats && stats->n_stats != n_stats) {
+ stats->n_stats = 0;
+ return 0;
+ }
ret = ethtool_vzalloc_stats_array(n_stats, data);
if (ret)
@@ -2616,7 +2632,9 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
}
useraddr += sizeof(stats);
- if (copy_to_user(useraddr, data, array_size(stats.n_stats, sizeof(u64))))
+ if (stats.n_stats &&
+ copy_to_user(useraddr, data,
+ array_size(stats.n_stats, sizeof(u64))))
ret = -EFAULT;
out:
diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
index 1d33a4675a48..b989456fc4c5 100644
--- a/net/handshake/netlink.c
+++ b/net/handshake/netlink.c
@@ -126,7 +126,8 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
}
out_complete:
- handshake_complete(req, -EIO, NULL);
+ if (req)
+ handshake_complete(req, -EIO, NULL);
out_status:
trace_handshake_cmd_accept_err(net, req, NULL, err);
return err;
diff --git a/net/handshake/request.c b/net/handshake/request.c
index 274d2c89b6b2..6b7e3e0bf399 100644
--- a/net/handshake/request.c
+++ b/net/handshake/request.c
@@ -276,6 +276,8 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
out_unlock:
spin_unlock(&hn->hn_lock);
out_err:
+ /* Restore original destructor so socket teardown still runs on failure */
+ req->hr_sk->sk_destruct = req->hr_odestruct;
trace_handshake_submit_err(net, req, req->hr_sk, ret);
handshake_req_destroy(req);
return ret;
@@ -324,7 +326,11 @@ bool handshake_req_cancel(struct sock *sk)
hn = handshake_pernet(net);
if (hn && remove_pending(hn, req)) {
- /* Request hadn't been accepted */
+ /* Request hadn't been accepted - mark cancelled */
+ if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
+ trace_handshake_cancel_busy(net, req, sk);
+ return false;
+ }
goto out_true;
}
if (test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
index 339f0d220212..aefc9b6936ba 100644
--- a/net/hsr/hsr_forward.c
+++ b/net/hsr/hsr_forward.c
@@ -205,6 +205,8 @@ struct sk_buff *prp_get_untagged_frame(struct hsr_frame_info *frame,
__pskb_copy(frame->skb_prp,
skb_headroom(frame->skb_prp),
GFP_ATOMIC);
+ if (!frame->skb_std)
+ return NULL;
} else {
/* Unexpected */
WARN_ONCE(1, "%s:%d: Unexpected frame received (port_src %s)\n",
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index a5f3c8459758..0caf38e44c73 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -2167,8 +2167,8 @@ void fib_select_multipath(struct fib_result *res, int hash,
{
struct fib_info *fi = res->fi;
struct net *net = fi->fib_net;
- bool found = false;
bool use_neigh;
+ int score = -1;
__be32 saddr;
if (unlikely(res->fi->nh)) {
@@ -2180,7 +2180,7 @@ void fib_select_multipath(struct fib_result *res, int hash,
saddr = fl4 ? fl4->saddr : 0;
change_nexthops(fi) {
- int nh_upper_bound;
+ int nh_upper_bound, nh_score = 0;
/* Nexthops without a carrier are assigned an upper bound of
* minus one when "ignore_routes_with_linkdown" is set.
@@ -2190,24 +2190,18 @@ void fib_select_multipath(struct fib_result *res, int hash,
(use_neigh && !fib_good_nh(nexthop_nh)))
continue;
- if (!found) {
+ if (saddr && nexthop_nh->nh_saddr == saddr)
+ nh_score += 2;
+ if (hash <= nh_upper_bound)
+ nh_score++;
+ if (score < nh_score) {
res->nh_sel = nhsel;
res->nhc = &nexthop_nh->nh_common;
- found = !saddr || nexthop_nh->nh_saddr == saddr;
+ if (nh_score == 3 || (!saddr && nh_score == 1))
+ return;
+ score = nh_score;
}
- if (hash > nh_upper_bound)
- continue;
-
- if (!saddr || nexthop_nh->nh_saddr == saddr) {
- res->nh_sel = nhsel;
- res->nhc = &nexthop_nh->nh_common;
- return;
- }
-
- if (found)
- return;
-
} endfor_nexthops(fi);
}
#endif
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 59a6f0a9638f..7e2c17fec3fc 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2053,10 +2053,11 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
continue;
}
- /* Do not flush error routes if network namespace is
- * not being dismantled
+ /* When not flushing the entire table, skip error
+ * routes that are not marked for deletion.
*/
- if (!flush_all && fib_props[fa->fa_type].error) {
+ if (!flush_all && fib_props[fa->fa_type].error &&
+ !(fi->fib_flags & RTNH_F_DEAD)) {
slen = fa->fa_slen;
continue;
}
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 025895eb6ec5..001ee5c4d962 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -218,6 +218,41 @@ static int __init inet_frag_wq_init(void)
pure_initcall(inet_frag_wq_init);
+void fqdir_pre_exit(struct fqdir *fqdir)
+{
+ struct inet_frag_queue *fq;
+ struct rhashtable_iter hti;
+
+ /* Prevent creation of new frags.
+ * Pairs with READ_ONCE() in inet_frag_find().
+ */
+ WRITE_ONCE(fqdir->high_thresh, 0);
+
+ /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
+ * and ip6frag_expire_frag_queue().
+ */
+ WRITE_ONCE(fqdir->dead, true);
+
+ rhashtable_walk_enter(&fqdir->rhashtable, &hti);
+ rhashtable_walk_start(&hti);
+
+ while ((fq = rhashtable_walk_next(&hti))) {
+ if (IS_ERR(fq)) {
+ if (PTR_ERR(fq) != -EAGAIN)
+ break;
+ continue;
+ }
+ spin_lock_bh(&fq->lock);
+ if (!(fq->flags & INET_FRAG_COMPLETE))
+ inet_frag_queue_flush(fq, 0);
+ spin_unlock_bh(&fq->lock);
+ }
+
+ rhashtable_walk_stop(&hti);
+ rhashtable_walk_exit(&hti);
+}
+EXPORT_SYMBOL(fqdir_pre_exit);
+
void fqdir_exit(struct fqdir *fqdir)
{
INIT_WORK(&fqdir->destroy_work, fqdir_work_fn);
@@ -263,8 +298,8 @@ static void inet_frag_destroy_rcu(struct rcu_head *head)
kmem_cache_free(f->frags_cachep, q);
}
-unsigned int inet_frag_rbtree_purge(struct rb_root *root,
- enum skb_drop_reason reason)
+static unsigned int
+inet_frag_rbtree_purge(struct rb_root *root, enum skb_drop_reason reason)
{
struct rb_node *p = rb_first(root);
unsigned int sum = 0;
@@ -284,7 +319,17 @@ unsigned int inet_frag_rbtree_purge(struct rb_root *root,
}
return sum;
}
-EXPORT_SYMBOL(inet_frag_rbtree_purge);
+
+void inet_frag_queue_flush(struct inet_frag_queue *q,
+ enum skb_drop_reason reason)
+{
+ unsigned int sum;
+
+ reason = reason ?: SKB_DROP_REASON_FRAG_REASM_TIMEOUT;
+ sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
+ sub_frag_mem_limit(q->fqdir, sum);
+}
+EXPORT_SYMBOL(inet_frag_queue_flush);
void inet_frag_destroy(struct inet_frag_queue *q)
{
@@ -327,7 +372,9 @@ static struct inet_frag_queue *inet_frag_alloc(struct fqdir *fqdir,
timer_setup(&q->timer, f->frag_expire, 0);
spin_lock_init(&q->lock);
- /* One reference for the timer, one for the hash table. */
+ /* One reference for the timer, one for the hash table.
+ * We never take any extra references, only decrement this field.
+ */
refcount_set(&q->refcnt, 2);
return q;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index f7012479713b..56b0f738d2f2 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -134,11 +134,6 @@ static void ip_expire(struct timer_list *t)
net = qp->q.fqdir->net;
rcu_read_lock();
-
- /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
- if (READ_ONCE(qp->q.fqdir->dead))
- goto out_rcu_unlock;
-
spin_lock(&qp->q.lock);
if (qp->q.flags & INET_FRAG_COMPLETE)
@@ -146,6 +141,13 @@ static void ip_expire(struct timer_list *t)
qp->q.flags |= INET_FRAG_DROP;
inet_frag_kill(&qp->q, &refs);
+
+ /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
+ if (READ_ONCE(qp->q.fqdir->dead)) {
+ inet_frag_queue_flush(&qp->q, 0);
+ goto out;
+ }
+
__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);
@@ -240,16 +242,10 @@ static int ip_frag_too_far(struct ipq *qp)
static int ip_frag_reinit(struct ipq *qp)
{
- unsigned int sum_truesize = 0;
-
- if (!mod_timer(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) {
- refcount_inc(&qp->q.refcnt);
+ if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout))
return -ETIMEDOUT;
- }
- sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments,
- SKB_DROP_REASON_FRAG_TOO_FAR);
- sub_frag_mem_limit(qp->q.fqdir, sum_truesize);
+ inet_frag_queue_flush(&qp->q, SKB_DROP_REASON_FRAG_TOO_FAR);
qp->q.flags = 0;
qp->q.len = 0;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 761a53c6a89a..8178c44a3cdd 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -330,6 +330,10 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
if (!tun_dst)
return PACKET_REJECT;
+ /* MUST set options_len before referencing options */
+ info = &tun_dst->u.tun_info;
+ info->options_len = sizeof(*md);
+
/* skb can be uncloned in __iptunnel_pull_header, so
* old pkt_md is no longer valid and we need to reset
* it
@@ -344,10 +348,8 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
ERSPAN_V2_MDSIZE);
- info = &tun_dst->u.tun_info;
__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
info->key.tun_flags);
- info->options_len = sizeof(*md);
}
skb_reset_mac_header(skb);
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index df1986973430..21f6ed126253 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -1342,7 +1342,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
/* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */
pad = ((new_end & 4) + (end & 7)) & 7;
len_delta = new_end - (int)end + pad;
- ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
+ ret_val = skb_cow(skb,
+ skb_headroom(skb) + (len_delta > 0 ? len_delta : 0));
if (ret_val < 0)
return ret_val;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c82a75510c0e..d19d86ed4376 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -535,6 +535,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,
if (!tun_dst)
return PACKET_REJECT;
+ /* MUST set options_len before referencing options */
+ info = &tun_dst->u.tun_info;
+ info->options_len = sizeof(*md);
+
/* skb can be uncloned in __iptunnel_pull_header, so
* old pkt_md is no longer valid and we need to reset
* it
@@ -543,7 +547,6 @@ static int ip6erspan_rcv(struct sk_buff *skb,
skb_network_header_len(skb);
pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
sizeof(*ershdr));
- info = &tun_dst->u.tun_info;
md = ip_tunnel_info_opts(info);
md->version = ver;
md2 = &md->u.md2;
@@ -551,7 +554,6 @@ static int ip6erspan_rcv(struct sk_buff *skb,
ERSPAN_V2_MDSIZE);
__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
info->key.tun_flags);
- info->options_len = sizeof(*md);
ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
@@ -1366,9 +1368,16 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
{
struct ip6_tnl *t = netdev_priv(dev);
struct ipv6hdr *ipv6h;
+ int needed;
__be16 *p;
- ipv6h = skb_push(skb, t->hlen + sizeof(*ipv6h));
+ needed = t->hlen + sizeof(*ipv6h);
+ if (skb_headroom(skb) < needed &&
+ pskb_expand_head(skb, HH_DATA_ALIGN(needed - skb_headroom(skb)),
+ 0, GFP_ATOMIC))
+ return -needed;
+
+ ipv6h = skb_push(skb, needed);
ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb,
t->fl.u.ip6.flowlabel,
true, &t->fl.u.ip6));
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index aee6a10b112a..a3e051dc66ee 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1470,7 +1470,18 @@ static struct rt6_info *rt6_make_pcpu_route(struct net *net,
p = this_cpu_ptr(res->nh->rt6i_pcpu);
prev = cmpxchg(p, NULL, pcpu_rt);
- BUG_ON(prev);
+ if (unlikely(prev)) {
+ /*
+ * Another task on this CPU already installed a pcpu_rt.
+ * This can happen on PREEMPT_RT where preemption is possible.
+ * Free our allocation and return the existing one.
+ */
+ WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT_RT));
+
+ dst_dev_put(&pcpu_rt->dst);
+ dst_release(&pcpu_rt->dst);
+ return prev;
+ }
if (res->f6i->fib6_destroying) {
struct fib6_info *from;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b51c2c8584ae..c81091a5cc3a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1345,7 +1345,6 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
size = sizeof(*new) + new_head_len + new_tail_len;
- /* new or old multiple BSSID elements? */
if (params->mbssid_ies) {
mbssid = params->mbssid_ies;
size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
@@ -1355,15 +1354,6 @@ ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
}
size += ieee80211_get_mbssid_beacon_len(mbssid, rnr,
mbssid->cnt);
- } else if (old && old->mbssid_ies) {
- mbssid = old->mbssid_ies;
- size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
- if (old && old->rnr_ies) {
- rnr = old->rnr_ies;
- size += struct_size(new->rnr_ies, elem, rnr->cnt);
- }
- size += ieee80211_get_mbssid_beacon_len(mbssid, rnr,
- mbssid->cnt);
}
new = kzalloc(size, GFP_KERNEL);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 4f04d95c19d4..7b0aa24c1f97 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1251,7 +1251,7 @@ configure_monitor:
if (!creator_sdata) {
struct ieee80211_sub_if_data *other;
- list_for_each_entry(other, &local->mon_list, list) {
+ list_for_each_entry_rcu(other, &local->mon_list, u.mntr.list) {
if (!other->vif.bss_conf.mu_mimo_owner)
continue;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e56ad4b9330f..ad53dedd929c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1126,7 +1126,10 @@ again:
while (!ieee80211_chandef_usable(sdata, &chanreq->oper,
IEEE80211_CHAN_DISABLED)) {
- if (WARN_ON(chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT)) {
+ if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT) {
+ link_id_info(sdata, link_id,
+ "unusable channel (%d MHz) for connection\n",
+ chanreq->oper.chan->center_freq);
ret = -EINVAL;
goto free;
}
diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c
index a5d4358f122a..ebb4f4d88c23 100644
--- a/net/mac80211/ocb.c
+++ b/net/mac80211/ocb.c
@@ -47,6 +47,9 @@ void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
int band;
+ if (!ifocb->joined)
+ return;
+
/* XXX: Consider removing the least recently used entry and
* allow new one to be added.
*/
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6a1899512d07..e0ccd9749853 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3511,6 +3511,11 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
return RX_DROP_U_RUNT_ACTION;
+ /* Drop non-broadcast Beacon frames */
+ if (ieee80211_is_beacon(mgmt->frame_control) &&
+ !is_broadcast_ether_addr(mgmt->da))
+ return RX_DROP;
+
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
ieee80211_is_beacon(mgmt->frame_control) &&
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig
index 20328920f6ed..be71fc9b4638 100644
--- a/net/mptcp/Kconfig
+++ b/net/mptcp/Kconfig
@@ -4,7 +4,7 @@ config MPTCP
depends on INET
select SKB_EXTENSIONS
select CRYPTO_LIB_SHA256
- select CRYPTO
+ select CRYPTO_LIB_UTILS
help
Multipath TCP (MPTCP) connections send and receive data over multiple
subflows in order to utilize multiple network paths. Each subflow
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index f24ae7d40e88..43df4293f58b 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -408,6 +408,16 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
*/
subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
if (subflow->request_mptcp) {
+ if (unlikely(subflow_simultaneous_connect(sk))) {
+ WARN_ON_ONCE(!mptcp_try_fallback(sk, MPTCP_MIB_SIMULTCONNFALLBACK));
+
+ /* Ensure mptcp_finish_connect() will not process the
+ * MPC handshake.
+ */
+ subflow->request_mptcp = 0;
+ return false;
+ }
+
opts->suboptions = OPTION_MPTCP_MPC_SYN;
opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk));
opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk));
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index d5b383870f79..7aa42de9c47b 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -119,7 +119,8 @@ int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
}
if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
- entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]);
+ entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]) &
+ MPTCP_PM_ADDR_FLAGS_MASK;
if (tb[MPTCP_PM_ADDR_ATTR_PORT])
entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index e212c1374bd0..f505b780f713 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1623,7 +1623,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
struct mptcp_sendmsg_info info = {
.flags = flags,
};
- bool do_check_data_fin = false;
+ bool copied = false;
int push_count = 1;
while (mptcp_send_head(sk) && (push_count > 0)) {
@@ -1665,7 +1665,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
push_count--;
continue;
}
- do_check_data_fin = true;
+ copied = true;
}
}
}
@@ -1674,11 +1674,14 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
if (ssk)
mptcp_push_release(ssk, &info);
- /* ensure the rtx timer is running */
- if (!mptcp_rtx_timer_pending(sk))
- mptcp_reset_rtx_timer(sk);
- if (do_check_data_fin)
+ /* Avoid scheduling the rtx timer if no data has been pushed; the timer
+ * will be updated on positive acks by __mptcp_cleanup_una().
+ */
+ if (copied) {
+ if (!mptcp_rtx_timer_pending(sk))
+ mptcp_reset_rtx_timer(sk);
mptcp_check_send_data_fin(sk);
+ }
}
static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool first)
@@ -2464,10 +2467,10 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
*/
static void __mptcp_subflow_disconnect(struct sock *ssk,
struct mptcp_subflow_context *subflow,
- unsigned int flags)
+ bool fastclosing)
{
if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
- subflow->send_fastclose) {
+ fastclosing) {
/* The MPTCP code never wait on the subflow sockets, TCP-level
* disconnect should never fail
*/
@@ -2535,7 +2538,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
if (!dispose_it) {
- __mptcp_subflow_disconnect(ssk, subflow, flags);
+ __mptcp_subflow_disconnect(ssk, subflow, msk->fastclosing);
release_sock(ssk);
goto out;
@@ -2766,10 +2769,13 @@ static void __mptcp_retrans(struct sock *sk)
/*
* make the whole retrans decision, xmit, disallow
- * fallback atomic
+ * fallback atomic, note that we can't retrans even
+ * when an infinite fallback is in progress, i.e. new
+ * subflows are disallowed.
*/
spin_lock_bh(&msk->fallback_lock);
- if (__mptcp_check_fallback(msk)) {
+ if (__mptcp_check_fallback(msk) ||
+ !msk->allow_subflows) {
spin_unlock_bh(&msk->fallback_lock);
release_sock(ssk);
goto clear_scheduled;
@@ -2878,6 +2884,7 @@ static void mptcp_do_fastclose(struct sock *sk)
mptcp_set_state(sk, TCP_CLOSE);
mptcp_backlog_purge(sk);
+ msk->fastclosing = 1;
/* Explicitly send the fastclose reset as need */
if (__mptcp_check_fallback(msk))
@@ -3412,6 +3419,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
msk->bytes_sent = 0;
msk->bytes_retrans = 0;
msk->rcvspace_init = 0;
+ msk->fastclosing = 0;
/* for fallback's sake */
WRITE_ONCE(msk->ack_seq, 0);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 9c0d17876b22..66e973500791 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -320,7 +320,8 @@ struct mptcp_sock {
fastopening:1,
in_accept_queue:1,
free_first:1,
- rcvspace_init:1;
+ rcvspace_init:1,
+ fastclosing:1;
u32 notsent_lowat;
int keepalive_cnt;
int keepalive_idle;
@@ -1337,10 +1338,8 @@ static inline bool subflow_simultaneous_connect(struct sock *sk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
- return (1 << sk->sk_state) &
- (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING) &&
- is_active_ssk(subflow) &&
- !subflow->conn_finished;
+ /* Note that the sk state implies !subflow->conn_finished. */
+ return sk->sk_state == TCP_SYN_RECV && is_active_ssk(subflow);
}
#ifdef CONFIG_SYN_COOKIES
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 86ce58ae533d..96d54cb2cd93 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1878,12 +1878,6 @@ static void subflow_state_change(struct sock *sk)
__subflow_state_change(sk);
- if (subflow_simultaneous_connect(sk)) {
- WARN_ON_ONCE(!mptcp_try_fallback(sk, MPTCP_MIB_SIMULTCONNFALLBACK));
- subflow->conn_finished = 1;
- mptcp_propagate_state(parent, sk, subflow, NULL);
- }
-
/* as recvmsg() does not acquire the subflow socket for ssk selection
* a fin packet carrying a DSS can be unnoticed if we don't trigger
* the data available machinery here.
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 3162ce3c2640..64c697212578 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -408,6 +408,9 @@ err_put:
return -1;
err_unreach:
+ if (!skb->dev)
+ skb->dev = skb_dst(skb)->dev;
+
dst_link_failure(skb);
return -1;
}
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index f1be4dd5cf85..3654f1e8976c 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net,
struct nf_conn *found_ct;
unsigned int collect = 0;
bool refcounted = false;
+ int err = 0;
if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted))
return -ENOENT;
if (ct && nf_ct_is_confirmed(ct)) {
- if (refcounted)
- nf_ct_put(ct);
- return -EEXIST;
+ err = -EEXIST;
+ goto out_put;
}
if ((u32)jiffies == list->last_gc)
@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net,
}
add_new_node:
- if (WARN_ON_ONCE(list->count > INT_MAX))
- return -EOVERFLOW;
+ if (WARN_ON_ONCE(list->count > INT_MAX)) {
+ err = -EOVERFLOW;
+ goto out_put;
+ }
conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
- if (conn == NULL)
- return -ENOMEM;
+ if (conn == NULL) {
+ err = -ENOMEM;
+ goto out_put;
+ }
conn->tuple = tuple;
conn->zone = *zone;
@@ -249,7 +253,7 @@ add_new_node:
out_put:
if (refcounted)
nf_ct_put(ct);
- return 0;
+ return err;
}
int nf_conncount_add_skb(struct net *net,
@@ -456,11 +460,10 @@ restart:
rb_link_node_rcu(&rbconn->node, parent, rbnode);
rb_insert_color(&rbconn->node, root);
-
- if (refcounted)
- nf_ct_put(ct);
}
out_unlock:
+ if (refcounted)
+ nf_ct_put(ct);
spin_unlock_bh(&nf_conncount_locks[hash]);
return count;
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0b95f226f211..d1f8eb725d42 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -2487,6 +2487,7 @@ void nf_conntrack_cleanup_net(struct net *net)
void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
{
struct nf_ct_iter_data iter_data = {};
+ unsigned long start = jiffies;
struct net *net;
int busy;
@@ -2507,6 +2508,8 @@ i_see_dead_people:
busy = 1;
}
if (busy) {
+ DEBUG_NET_WARN_ONCE(time_after(jiffies, start + 60 * HZ),
+ "conntrack cleanup blocked for 60s");
schedule();
goto i_see_dead_people;
}
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index f0984cf69a09..eb24fe2715dc 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -250,6 +250,9 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
nft_dev_path_info(&stack, &info, ha, &ft->data);
+ if (info.outdev)
+ route->tuple[dir].out.ifindex = info.outdev->ifindex;
+
if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
return;
@@ -269,7 +272,6 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
route->tuple[!dir].in.num_encaps = info.num_encaps;
route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
- route->tuple[dir].out.ifindex = info.outdev->ifindex;
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 78a61dac4ade..e6b24586d2fe 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -294,25 +294,13 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple,
ct = nf_ct_tuplehash_to_ctrack(thash);
- /* NB: IP_CT_DIR_ORIGINAL should be impossible because
- * nf_nat_used_tuple() handles origin collisions.
- *
- * Handle remote chance other CPU confirmed its ct right after.
- */
- if (thash->tuple.dst.dir != IP_CT_DIR_REPLY)
- goto out;
-
/* clashing connection subject to NAT? Retry with new tuple. */
if (READ_ONCE(ct->status) & uses_nat)
goto out;
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
- &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple) &&
- nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
- &ignored_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) {
+ &ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple))
taken = false;
- goto out;
- }
out:
nf_ct_put(ct);
return taken;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index f3de2f9bbebf..618af6e90773 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -123,6 +123,29 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
table->validate_state = new_validate_state;
}
+
+static bool nft_chain_vstate_valid(const struct nft_ctx *ctx,
+ const struct nft_chain *chain)
+{
+ const struct nft_base_chain *base_chain;
+ enum nft_chain_types type;
+ u8 hooknum;
+
+ if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain)))
+ return false;
+
+ base_chain = nft_base_chain(ctx->chain);
+ hooknum = base_chain->ops.hooknum;
+ type = base_chain->type->type;
+
+ /* chain is already validated for this call depth */
+ if (chain->vstate.depth >= ctx->level &&
+ chain->vstate.hook_mask[type] & BIT(hooknum))
+ return true;
+
+ return false;
+}
+
static void nf_tables_trans_destroy_work(struct work_struct *w);
static void nft_trans_gc_work(struct work_struct *work);
@@ -4079,6 +4102,29 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
nf_tables_rule_destroy(ctx, rule);
}
+static void nft_chain_vstate_update(const struct nft_ctx *ctx, struct nft_chain *chain)
+{
+ const struct nft_base_chain *base_chain;
+ enum nft_chain_types type;
+ u8 hooknum;
+
+ /* ctx->chain must hold the calling base chain. */
+ if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain))) {
+ memset(&chain->vstate, 0, sizeof(chain->vstate));
+ return;
+ }
+
+ base_chain = nft_base_chain(ctx->chain);
+ hooknum = base_chain->ops.hooknum;
+ type = base_chain->type->type;
+
+ BUILD_BUG_ON(BIT(NF_INET_NUMHOOKS) > U8_MAX);
+
+ chain->vstate.hook_mask[type] |= BIT(hooknum);
+ if (chain->vstate.depth < ctx->level)
+ chain->vstate.depth = ctx->level;
+}
+
/** nft_chain_validate - loop detection and hook validation
*
* @ctx: context containing call depth and base chain
@@ -4088,15 +4134,25 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
* and set lookups until either the jump limit is hit or all reachable
* chains have been validated.
*/
-int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
+int nft_chain_validate(const struct nft_ctx *ctx, struct nft_chain *chain)
{
struct nft_expr *expr, *last;
struct nft_rule *rule;
int err;
+ BUILD_BUG_ON(NFT_JUMP_STACK_SIZE > 255);
if (ctx->level == NFT_JUMP_STACK_SIZE)
return -EMLINK;
+ if (ctx->level > 0) {
+ /* jumps to base chains are not allowed. */
+ if (nft_is_base_chain(chain))
+ return -ELOOP;
+
+ if (nft_chain_vstate_valid(ctx, chain))
+ return 0;
+ }
+
list_for_each_entry(rule, &chain->rules, list) {
if (fatal_signal_pending(current))
return -EINTR;
@@ -4115,8 +4171,11 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
if (err < 0)
return err;
}
+
+ cond_resched();
}
+ nft_chain_vstate_update(ctx, chain);
return 0;
}
EXPORT_SYMBOL_GPL(nft_chain_validate);
@@ -4128,7 +4187,7 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
.net = net,
.family = table->family,
};
- int err;
+ int err = 0;
list_for_each_entry(chain, &table->chains, list) {
if (!nft_is_base_chain(chain))
@@ -4137,12 +4196,14 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
ctx.chain = chain;
err = nft_chain_validate(&ctx, chain);
if (err < 0)
- return err;
-
- cond_resched();
+ goto err;
}
- return 0;
+err:
+ list_for_each_entry(chain, &table->chains, list)
+ memset(&chain->vstate, 0, sizeof(chain->vstate));
+
+ return err;
}
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
@@ -11676,21 +11737,10 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_data_types type,
unsigned int len)
{
- int err;
-
switch (reg) {
case NFT_REG_VERDICT:
if (type != NFT_DATA_VERDICT)
return -EINVAL;
-
- if (data != NULL &&
- (data->verdict.code == NFT_GOTO ||
- data->verdict.code == NFT_JUMP)) {
- err = nft_chain_validate(ctx, data->verdict.chain);
- if (err < 0)
- return err;
- }
-
break;
default:
if (type != NFT_DATA_VALUE)
diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
index 5e531394a724..2b3cbceb0b52 100644
--- a/net/netrom/nr_out.c
+++ b/net/netrom/nr_out.c
@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb)
frontlen = skb_headroom(skb);
while (skb->len > 0) {
- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL)
+ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) {
+ kfree_skb(skb);
return;
+ }
skb_reserve(skbn, frontlen);
diff --git a/net/nfc/core.c b/net/nfc/core.c
index ae1c842f9c64..82f023f37754 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -1154,6 +1154,7 @@ EXPORT_SYMBOL(nfc_register_device);
void nfc_unregister_device(struct nfc_dev *dev)
{
int rc;
+ struct rfkill *rfk = NULL;
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
@@ -1164,13 +1165,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
device_lock(&dev->dev);
if (dev->rfkill) {
- rfkill_unregister(dev->rfkill);
- rfkill_destroy(dev->rfkill);
+ rfk = dev->rfkill;
dev->rfkill = NULL;
}
dev->shutting_down = true;
device_unlock(&dev->dev);
+ if (rfk) {
+ rfkill_unregister(rfk);
+ rfkill_destroy(rfk);
+ }
+
if (dev->ops->check_presence) {
timer_delete_sync(&dev->check_pres_timer);
cancel_work_sync(&dev->check_pres_work);
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 1cb4f97335d8..2d536901309e 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -2802,13 +2802,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
return err;
}
-static bool validate_push_nsh(const struct nlattr *attr, bool log)
+static bool validate_push_nsh(const struct nlattr *a, bool log)
{
+ struct nlattr *nsh_key = nla_data(a);
struct sw_flow_match match;
struct sw_flow_key key;
+ /* There must be one and only one NSH header. */
+ if (!nla_ok(nsh_key, nla_len(a)) ||
+ nla_total_size(nla_len(nsh_key)) != nla_len(a) ||
+ nla_type(nsh_key) != OVS_KEY_ATTR_NSH)
+ return false;
+
ovs_match_init(&match, &key, true, NULL);
- return !nsh_key_put_from_nlattr(attr, &match, false, true, log);
+ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log);
}
/* Return false if there are any non-masked bits set.
@@ -3389,7 +3396,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
return -EINVAL;
}
mac_proto = MAC_PROTO_NONE;
- if (!validate_push_nsh(nla_data(a), log))
+ if (!validate_push_nsh(a, log))
return -EINVAL;
break;
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 91a11067e458..6574f9bcdc02 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -160,10 +160,19 @@ void ovs_netdev_detach_dev(struct vport *vport)
static void netdev_destroy(struct vport *vport)
{
- rtnl_lock();
- if (netif_is_ovs_port(vport->dev))
- ovs_netdev_detach_dev(vport);
- rtnl_unlock();
+ /* When called from ovs_db_notify_wq() after a dp_device_event(), the
+ * port has already been detached, so we can avoid taking the RTNL by
+ * checking this first.
+ */
+ if (netif_is_ovs_port(vport->dev)) {
+ rtnl_lock();
+ /* Check again while holding the lock to ensure we don't race
+ * with the netdev notifier and detach twice.
+ */
+ if (netif_is_ovs_port(vport->dev))
+ ovs_netdev_detach_dev(vport);
+ rtnl_unlock();
+ }
call_rcu(&vport->rcu, vport_netdev_free);
}
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index fd67494f2815..c0f5a515a8ce 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -205,7 +205,7 @@ start:
spin_unlock_bh(&rose_list_lock);
for (i = 0; i < cnt; i++) {
- sk = array[cnt];
+ sk = array[i];
rose = rose_sk(sk);
lock_sock(sk);
spin_lock_bh(&rose_list_lock);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index f27b583def78..91c96cc625bd 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -281,6 +281,15 @@ static int tcf_mirred_to_dev(struct sk_buff *skb, struct tcf_mirred *m,
want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
+ if (dev == skb->dev && want_ingress == at_ingress) {
+ pr_notice_once("tc mirred: Loop (%s:%s --> %s:%s)\n",
+ netdev_name(skb->dev),
+ at_ingress ? "ingress" : "egress",
+ netdev_name(dev),
+ want_ingress ? "ingress" : "egress");
+ goto err_cant_do;
+ }
+
/* All mirred/redirected skbs should clear previous ct info */
nf_reset_ct(skb_to_send);
if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */
diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c
index 82635dd2cfa5..306e046276d4 100644
--- a/net/sched/sch_ets.c
+++ b/net/sched/sch_ets.c
@@ -652,7 +652,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
sch_tree_lock(sch);
for (i = nbands; i < oldbands; i++) {
- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen)
+ if (cl_is_active(&q->classes[i]))
list_del_init(&q->classes[i].alist);
qdisc_purge_queue(q->classes[i].qdisc);
}
@@ -664,6 +664,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
q->classes[i].deficit = quanta[i];
}
}
+ for (i = q->nstrict; i < nstrict; i++) {
+ if (cl_is_active(&q->classes[i]))
+ list_del_init(&q->classes[i].alist);
+ }
WRITE_ONCE(q->nstrict, nstrict);
memcpy(q->prio2band, priomap, sizeof(priomap));
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 069b7e45d8bd..531cb0690007 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -492,6 +492,8 @@ static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct ipv6_txoptions *opt;
+ inet_sk(newsk)->inet_opt = NULL;
+
newnp = inet6_sk(newsk);
rcu_read_lock();
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index d808096f5ab1..2493a5b1fa3c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4863,8 +4863,6 @@ static struct sock *sctp_clone_sock(struct sock *sk,
newsp->pf->to_sk_daddr(&asoc->peer.primary_addr, newsk);
newinet->inet_dport = htons(asoc->peer.port);
-
- newsp->pf->copy_ip_options(sk, newsk);
atomic_set(&newinet->inet_id, get_random_u16());
inet_set_bit(MC_LOOP, newsk);
@@ -4874,17 +4872,20 @@ static struct sock *sctp_clone_sock(struct sock *sk,
#if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == AF_INET6) {
- struct ipv6_pinfo *newnp = inet6_sk(newsk);
+ struct ipv6_pinfo *newnp;
newinet->pinet6 = &((struct sctp6_sock *)newsk)->inet6;
newinet->ipv6_fl_list = NULL;
+ newnp = inet6_sk(newsk);
memcpy(newnp, inet6_sk(sk), sizeof(struct ipv6_pinfo));
newnp->ipv6_mc_list = NULL;
newnp->ipv6_ac_list = NULL;
}
#endif
+ newsp->pf->copy_ip_options(sk, newsk);
+
newsp->do_auto_asconf = 0;
skb_queue_head_init(&newsp->pd_lobby);
diff --git a/net/smc/Kconfig b/net/smc/Kconfig
index 325addf83cc6..277ef504bc26 100644
--- a/net/smc/Kconfig
+++ b/net/smc/Kconfig
@@ -22,10 +22,10 @@ config SMC_DIAG
config SMC_HS_CTRL_BPF
bool "Generic eBPF hook for SMC handshake flow"
- depends on SMC && BPF_SYSCALL
+ depends on SMC && BPF_JIT && BPF_SYSCALL
default y
help
SMC_HS_CTRL_BPF enables support to register generic eBPF hook for SMC
handshake flow, which offer much greater flexibility in modifying the behavior
of the SMC protocol stack compared to a complete kernel-based approach. Select
- this option if you want filtring the handshake process via eBPF programs. \ No newline at end of file
+ this option if you want filtring the handshake process via eBPF programs.
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index a8ec30759a18..e2f0df8cdaa6 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1083,7 +1083,8 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp,
}
length = min_t(unsigned int, inlen, (char *)xdr->end - (char *)xdr->p);
- memcpy(page_address(in_token->pages[0]), xdr->p, length);
+ if (length)
+ memcpy(page_address(in_token->pages[0]), xdr->p, length);
inlen -= length;
to_offs = length;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c
index 661b3fe2779f..310de7a80be5 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_rw.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c
@@ -841,6 +841,9 @@ static int svc_rdma_copy_inline_range(struct svc_rqst *rqstp,
for (page_no = 0; page_no < numpages; page_no++) {
unsigned int page_len;
+ if (head->rc_curpage >= rqstp->rq_maxpages)
+ return -EINVAL;
+
page_len = min_t(unsigned int, remaining,
PAGE_SIZE - head->rc_pageoff);
@@ -848,7 +851,7 @@ static int svc_rdma_copy_inline_range(struct svc_rqst *rqstp,
head->rc_page_count++;
dst = page_address(rqstp->rq_pages[head->rc_curpage]);
- memcpy(dst + head->rc_curpage, src + offset, page_len);
+ memcpy((unsigned char *)dst + head->rc_pageoff, src + offset, page_len);
head->rc_readbytes += page_len;
head->rc_pageoff += page_len;
@@ -860,7 +863,7 @@ static int svc_rdma_copy_inline_range(struct svc_rqst *rqstp,
offset += page_len;
}
- return -EINVAL;
+ return 0;
}
/**
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 55cdebfa0da0..a7ca74653d94 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2904,6 +2904,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
unsigned int last_len;
struct unix_sock *u;
int copied = 0;
+ bool do_cmsg;
int err = 0;
long timeo;
int target;
@@ -2929,6 +2930,9 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
u = unix_sk(sk);
+ do_cmsg = READ_ONCE(u->recvmsg_inq);
+ if (do_cmsg)
+ msg->msg_get_inq = 1;
redo:
/* Lock the socket to prevent queue disordering
* while sleeps in memcpy_tomsg
@@ -3088,10 +3092,11 @@ unlock:
if (msg) {
scm_recv_unix(sock, msg, &scm, flags);
- if (READ_ONCE(u->recvmsg_inq) || msg->msg_get_inq) {
+ if (msg->msg_get_inq && (copied ?: err) >= 0) {
msg->msg_inq = READ_ONCE(u->inq_len);
- put_cmsg(msg, SOL_SOCKET, SCM_INQ,
- sizeof(msg->msg_inq), &msg->msg_inq);
+ if (do_cmsg)
+ put_cmsg(msg, SOL_SOCKET, SCM_INQ,
+ sizeof(msg->msg_inq), &msg->msg_inq);
}
} else {
scm_destroy(&scm);
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 78323d43e63e..25f65817faab 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -199,7 +199,7 @@ static void unix_free_vertices(struct scm_fp_list *fpl)
}
}
-static DEFINE_SPINLOCK(unix_gc_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(unix_gc_lock);
void unix_add_edges(struct scm_fp_list *fpl, struct unix_sock *receiver)
{
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 3a028ff287fb..4e629ca305bc 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -910,7 +910,7 @@ void __cfg80211_connect_result(struct net_device *dev,
ssid_len = min(ssid->datalen, IEEE80211_MAX_SSID_LEN);
memcpy(wdev->u.client.ssid, ssid->data, ssid_len);
- wdev->u.client.ssid_len = ssid->datalen;
+ wdev->u.client.ssid_len = ssid_len;
break;
}
rcu_read_unlock();
diff --git a/rust/helpers/dma.c b/rust/helpers/dma.c
index 6e741c197242..2afa32c21c94 100644
--- a/rust/helpers/dma.c
+++ b/rust/helpers/dma.c
@@ -19,3 +19,24 @@ int rust_helper_dma_set_mask_and_coherent(struct device *dev, u64 mask)
{
return dma_set_mask_and_coherent(dev, mask);
}
+
+int rust_helper_dma_set_mask(struct device *dev, u64 mask)
+{
+ return dma_set_mask(dev, mask);
+}
+
+int rust_helper_dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+ return dma_set_coherent_mask(dev, mask);
+}
+
+int rust_helper_dma_map_sgtable(struct device *dev, struct sg_table *sgt,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ return dma_map_sgtable(dev, sgt, dir, attrs);
+}
+
+size_t rust_helper_dma_max_mapping_size(struct device *dev)
+{
+ return dma_max_mapping_size(dev);
+}
diff --git a/rust/kernel/maple_tree.rs b/rust/kernel/maple_tree.rs
index e72eec56bf57..265d6396a78a 100644
--- a/rust/kernel/maple_tree.rs
+++ b/rust/kernel/maple_tree.rs
@@ -265,7 +265,16 @@ impl<T: ForeignOwnable> MapleTree<T> {
loop {
// This uses the raw accessor because we're destroying pointers without removing them
// from the maple tree, which is only valid because this is the destructor.
- let ptr = ma_state.mas_find_raw(usize::MAX);
+ //
+ // Take the rcu lock because mas_find_raw() requires that you hold either the spinlock
+ // or the rcu read lock. This is only really required if memory reclaim might
+ // reallocate entries in the tree, as we otherwise have exclusive access. That feature
+ // doesn't exist yet, so for now, taking the rcu lock only serves the purpose of
+ // silencing lockdep.
+ let ptr = {
+ let _rcu = kernel::sync::rcu::Guard::new();
+ ma_state.mas_find_raw(usize::MAX)
+ };
if ptr.is_null() {
break;
}
diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c
index da3a9f2091f5..1ba1927b548e 100644
--- a/samples/ftrace/ftrace-direct-modify.c
+++ b/samples/ftrace/ftrace-direct-modify.c
@@ -176,8 +176,8 @@ asm (
" st.d $t0, $sp, 0\n"
" st.d $ra, $sp, 8\n"
" bl my_direct_func1\n"
-" ld.d $t0, $sp, 0\n"
-" ld.d $ra, $sp, 8\n"
+" ld.d $ra, $sp, 0\n"
+" ld.d $t0, $sp, 8\n"
" addi.d $sp, $sp, 16\n"
" jr $t0\n"
" .size my_tramp1, .-my_tramp1\n"
@@ -189,8 +189,8 @@ asm (
" st.d $t0, $sp, 0\n"
" st.d $ra, $sp, 8\n"
" bl my_direct_func2\n"
-" ld.d $t0, $sp, 0\n"
-" ld.d $ra, $sp, 8\n"
+" ld.d $ra, $sp, 0\n"
+" ld.d $t0, $sp, 8\n"
" addi.d $sp, $sp, 16\n"
" jr $t0\n"
" .size my_tramp2, .-my_tramp2\n"
diff --git a/samples/ftrace/ftrace-direct-multi-modify.c b/samples/ftrace/ftrace-direct-multi-modify.c
index 8f7986d698d8..7a7822dfeb50 100644
--- a/samples/ftrace/ftrace-direct-multi-modify.c
+++ b/samples/ftrace/ftrace-direct-multi-modify.c
@@ -199,8 +199,8 @@ asm (
" move $a0, $t0\n"
" bl my_direct_func1\n"
" ld.d $a0, $sp, 0\n"
-" ld.d $t0, $sp, 8\n"
-" ld.d $ra, $sp, 16\n"
+" ld.d $ra, $sp, 8\n"
+" ld.d $t0, $sp, 16\n"
" addi.d $sp, $sp, 32\n"
" jr $t0\n"
" .size my_tramp1, .-my_tramp1\n"
@@ -215,8 +215,8 @@ asm (
" move $a0, $t0\n"
" bl my_direct_func2\n"
" ld.d $a0, $sp, 0\n"
-" ld.d $t0, $sp, 8\n"
-" ld.d $ra, $sp, 16\n"
+" ld.d $ra, $sp, 8\n"
+" ld.d $t0, $sp, 16\n"
" addi.d $sp, $sp, 32\n"
" jr $t0\n"
" .size my_tramp2, .-my_tramp2\n"
diff --git a/samples/ftrace/ftrace-direct-multi.c b/samples/ftrace/ftrace-direct-multi.c
index db326c81a27d..3fe6ddaf0b69 100644
--- a/samples/ftrace/ftrace-direct-multi.c
+++ b/samples/ftrace/ftrace-direct-multi.c
@@ -131,8 +131,8 @@ asm (
" move $a0, $t0\n"
" bl my_direct_func\n"
" ld.d $a0, $sp, 0\n"
-" ld.d $t0, $sp, 8\n"
-" ld.d $ra, $sp, 16\n"
+" ld.d $ra, $sp, 8\n"
+" ld.d $t0, $sp, 16\n"
" addi.d $sp, $sp, 32\n"
" jr $t0\n"
" .size my_tramp, .-my_tramp\n"
diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c
index 3d0fa260332d..bf2411aa6fd7 100644
--- a/samples/ftrace/ftrace-direct-too.c
+++ b/samples/ftrace/ftrace-direct-too.c
@@ -143,8 +143,8 @@ asm (
" ld.d $a0, $sp, 0\n"
" ld.d $a1, $sp, 8\n"
" ld.d $a2, $sp, 16\n"
-" ld.d $t0, $sp, 24\n"
-" ld.d $ra, $sp, 32\n"
+" ld.d $ra, $sp, 24\n"
+" ld.d $t0, $sp, 32\n"
" addi.d $sp, $sp, 48\n"
" jr $t0\n"
" .size my_tramp, .-my_tramp\n"
diff --git a/samples/ftrace/ftrace-direct.c b/samples/ftrace/ftrace-direct.c
index 956834b0d19a..5368c8c39cbb 100644
--- a/samples/ftrace/ftrace-direct.c
+++ b/samples/ftrace/ftrace-direct.c
@@ -124,8 +124,8 @@ asm (
" st.d $ra, $sp, 16\n"
" bl my_direct_func\n"
" ld.d $a0, $sp, 0\n"
-" ld.d $t0, $sp, 8\n"
-" ld.d $ra, $sp, 16\n"
+" ld.d $ra, $sp, 8\n"
+" ld.d $t0, $sp, 16\n"
" addi.d $sp, $sp, 32\n"
" jr $t0\n"
" .size my_tramp, .-my_tramp\n"
diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci.rs
index 5823787bea8e..fa677991a5c4 100644
--- a/samples/rust/rust_driver_pci.rs
+++ b/samples/rust/rust_driver_pci.rs
@@ -48,7 +48,7 @@ impl SampleDriver {
// Select the test.
bar.write8(index.0, Regs::TEST);
- let offset = u32::from_le(bar.read32(Regs::OFFSET)) as usize;
+ let offset = bar.read32(Regs::OFFSET) as usize;
let data = bar.read8(Regs::DATA);
// Write `data` to `offset` to increase `count` by one.
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 52c08c4eb0b9..5037f4715d74 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -527,18 +527,6 @@ ifneq ($(userprogs),)
include $(srctree)/scripts/Makefile.userprogs
endif
-ifneq ($(need-dtbslist)$(dtb-y)$(dtb-)$(filter %.dtb %.dtb.o %.dtbo.o,$(targets)),)
-include $(srctree)/scripts/Makefile.dtbs
-endif
-
-# Build
-# ---------------------------------------------------------------------------
-
-$(obj)/: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \
- $(if $(KBUILD_MODULES), $(targets-for-modules)) \
- $(subdir-ym) $(always-y)
- @:
-
# Single targets
# ---------------------------------------------------------------------------
@@ -568,6 +556,20 @@ FORCE:
targets += $(filter-out $(single-subdir-goals), $(MAKECMDGOALS))
targets := $(filter-out $(PHONY), $(targets))
+# Now that targets is fully known, include dtb rules if needed
+ifneq ($(need-dtbslist)$(dtb-y)$(dtb-)$(filter %.dtb %.dtb.o %.dtbo.o,$(targets)),)
+include $(srctree)/scripts/Makefile.dtbs
+endif
+
+# Build
+# Needs to be after the include of Makefile.dtbs, which updates always-y
+# ---------------------------------------------------------------------------
+
+$(obj)/: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \
+ $(if $(KBUILD_MODULES), $(targets-for-modules)) \
+ $(subdir-ym) $(always-y)
+ @:
+
# Read all saved command lines and dependencies for the $(targets) we
# may be building above, using $(if_changed{,_dep}). As an
# optimization, we don't need to read them if the target does not
diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py
index 6f4afa92a466..96e6e46ad1a7 100755
--- a/scripts/clang-tools/gen_compile_commands.py
+++ b/scripts/clang-tools/gen_compile_commands.py
@@ -21,12 +21,6 @@ _DEFAULT_LOG_LEVEL = 'WARNING'
_FILENAME_PATTERN = r'^\..*\.cmd$'
_LINE_PATTERN = r'^(saved)?cmd_[^ ]*\.o := (?P<command_prefix>.* )(?P<file_path>[^ ]*\.[cS]) *(;|$)'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
-
-# Pre-compiled regexes for better performance
-_INCLUDE_PATTERN = re.compile(r'^\s*#\s*include\s*[<"]([^>"]*)[>"]')
-_C_INCLUDE_PATTERN = re.compile(r'^\s*#\s*include\s*"([^"]*\.c)"\s*$')
-_FILENAME_MATCHER = re.compile(_FILENAME_PATTERN)
-
# The tools/ directory adopts a different build system, and produces .cmd
# files in a different format. Do not support it.
_EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools']
@@ -88,6 +82,7 @@ def cmdfiles_in_dir(directory):
The path to a .cmd file.
"""
+ filename_matcher = re.compile(_FILENAME_PATTERN)
exclude_dirs = [ os.path.join(directory, d) for d in _EXCLUDE_DIRS ]
for dirpath, dirnames, filenames in os.walk(directory, topdown=True):
@@ -97,7 +92,7 @@ def cmdfiles_in_dir(directory):
continue
for filename in filenames:
- if _FILENAME_MATCHER.match(filename):
+ if filename_matcher.match(filename):
yield os.path.join(dirpath, filename)
@@ -154,87 +149,8 @@ def cmdfiles_for_modorder(modorder):
yield to_cmdfile(mod_line.rstrip())
-def extract_includes_from_file(source_file, root_directory):
- """Extract #include statements from a C file.
-
- Args:
- source_file: Path to the source .c file to analyze
- root_directory: Root directory for resolving relative paths
-
- Returns:
- List of header files that should be included (without quotes/brackets)
- """
- includes = []
- if not os.path.exists(source_file):
- return includes
-
- try:
- with open(source_file, 'r') as f:
- for line in f:
- line = line.strip()
- # Look for #include statements.
- # Match both #include "header.h" and #include <header.h>.
- match = _INCLUDE_PATTERN.match(line)
- if match:
- header = match.group(1)
- # Skip including other .c files to avoid circular includes.
- if not header.endswith('.c'):
- # For relative includes (quoted), resolve path relative to source file.
- if '"' in line:
- src_dir = os.path.dirname(source_file)
- header_path = os.path.join(src_dir, header)
- if os.path.exists(header_path):
- rel_header = os.path.relpath(header_path, root_directory)
- includes.append(rel_header)
- else:
- includes.append(header)
- else:
- # System include like <linux/sched.h>.
- includes.append(header)
- except IOError:
- pass
-
- return includes
-
-
-def find_included_c_files(source_file, root_directory):
- """Find .c files that are included by the given source file.
-
- Args:
- source_file: Path to the source .c file
- root_directory: Root directory for resolving relative paths
-
- Yields:
- Full paths to included .c files
- """
- if not os.path.exists(source_file):
- return
-
- try:
- with open(source_file, 'r') as f:
- for line in f:
- line = line.strip()
- # Look for #include "*.c" patterns.
- match = _C_INCLUDE_PATTERN.match(line)
- if match:
- included_file = match.group(1)
- # Handle relative paths.
- if not os.path.isabs(included_file):
- src_dir = os.path.dirname(source_file)
- included_file = os.path.join(src_dir, included_file)
-
- # Normalize the path.
- included_file = os.path.normpath(included_file)
-
- # Check if the file exists.
- if os.path.exists(included_file):
- yield included_file
- except IOError:
- pass
-
-
def process_line(root_directory, command_prefix, file_path):
- """Extracts information from a .cmd line and creates entries from it.
+ """Extracts information from a .cmd line and creates an entry from it.
Args:
root_directory: The directory that was searched for .cmd files. Usually
@@ -244,8 +160,7 @@ def process_line(root_directory, command_prefix, file_path):
Usually relative to root_directory, but sometimes absolute.
Returns:
- A list of entries to append to compile_commands (may include multiple
- entries if the source file includes other .c files).
+ An entry to append to compile_commands.
Raises:
ValueError: Could not find the extracted file based on file_path and
@@ -261,47 +176,11 @@ def process_line(root_directory, command_prefix, file_path):
abs_path = os.path.realpath(os.path.join(root_directory, file_path))
if not os.path.exists(abs_path):
raise ValueError('File %s not found' % abs_path)
-
- entries = []
-
- # Create entry for the main source file.
- main_entry = {
+ return {
'directory': root_directory,
'file': abs_path,
'command': prefix + file_path,
}
- entries.append(main_entry)
-
- # Find and create entries for included .c files.
- for included_c_file in find_included_c_files(abs_path, root_directory):
- # For included .c files, create a compilation command that:
- # 1. Uses the same compilation flags as the parent file
- # 2. But compiles the included file directly (not the parent)
- # 3. Includes necessary headers from the parent file for proper macro resolution
-
- # Convert absolute path to relative for the command.
- rel_path = os.path.relpath(included_c_file, root_directory)
-
- # Extract includes from the parent file to provide proper compilation context.
- extra_includes = ''
- try:
- parent_includes = extract_includes_from_file(abs_path, root_directory)
- if parent_includes:
- extra_includes = ' ' + ' '.join('-include ' + inc for inc in parent_includes)
- except IOError:
- pass
-
- included_entry = {
- 'directory': root_directory,
- 'file': included_c_file,
- # Use the same compilation prefix but target the included file directly.
- # Add extra headers for proper macro resolution.
- 'command': prefix + extra_includes + ' ' + rel_path,
- }
- entries.append(included_entry)
- logging.debug('Added entry for included file: %s', included_c_file)
-
- return entries
def main():
@@ -334,9 +213,9 @@ def main():
result = line_matcher.match(f.readline())
if result:
try:
- entries = process_line(directory, result.group('command_prefix'),
+ entry = process_line(directory, result.group('command_prefix'),
result.group('file_path'))
- compile_commands.extend(entries)
+ compile_commands.append(entry)
except ValueError as err:
logging.info('Could not add line from %s: %s',
cmdfile, err)
diff --git a/scripts/coccicheck b/scripts/coccicheck
index 0e6bc5a10320..89d591af5f3e 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -270,7 +270,11 @@ fi
if [ "$COCCI" = "" ] ; then
for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do
- coccinelle $f
+ if grep -q "virtual[[:space:]]\+$MODE" "$f"; then
+ coccinelle $f
+ else
+ echo "warning: Skipping $f as it does not match mode '$MODE'"
+ fi
done
else
coccinelle $COCCI
diff --git a/scripts/coccinelle/api/pm_runtime.cocci b/scripts/coccinelle/api/pm_runtime.cocci
index bf128ccae921..b720489418fa 100644
--- a/scripts/coccinelle/api/pm_runtime.cocci
+++ b/scripts/coccinelle/api/pm_runtime.cocci
@@ -109,5 +109,5 @@ p2 << r.p2;
pm_runtime_api << r.pm_runtime_api;
@@
-msg = "%s returns < 0 as error. Unecessary IS_ERR_VALUE at line %s" % (pm_runtime_api, p2[0].line)
+msg = "%s returns < 0 as error. Unnecessary IS_ERR_VALUE at line %s" % (pm_runtime_api, p2[0].line)
coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index ef2ffb68f69d..b4178c42d08f 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -199,6 +199,9 @@ int main(void)
DEVID(cpu_feature);
DEVID_FIELD(cpu_feature, feature);
+ DEVID(mcb_device_id);
+ DEVID_FIELD(mcb_device_id, device);
+
DEVID(mei_cl_device_id);
DEVID_FIELD(mei_cl_device_id, name);
DEVID_FIELD(mei_cl_device_id, uuid);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index b3333560b95e..4e99393a35f1 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1110,6 +1110,14 @@ static void do_cpu_entry(struct module *mod, void *symval)
module_alias_printf(mod, false, "cpu:type:*:feature:*%04X*", feature);
}
+/* Looks like: mcb:16zN */
+static void do_mcb_entry(struct module *mod, void *symval)
+{
+ DEF_FIELD(symval, mcb_device_id, device);
+
+ module_alias_printf(mod, false, "mcb:16z%03d", device);
+}
+
/* Looks like: mei:S:uuid:N:* */
static void do_mei_entry(struct module *mod, void *symval)
{
@@ -1444,6 +1452,7 @@ static const struct devtable devtable[] = {
{"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
{"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
{"cpu", SIZE_cpu_feature, do_cpu_entry},
+ {"mcb", SIZE_mcb_device_id, do_mcb_entry},
{"mei", SIZE_mei_cl_device_id, do_mei_entry},
{"rapidio", SIZE_rio_device_id, do_rio_entry},
{"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 7362f68f2d8b..5beb69edd12f 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -250,9 +250,7 @@ void ima_kexec_post_load(struct kimage *image)
if (!image->ima_buffer_addr)
return;
- ima_kexec_buffer = kimage_map_segment(image,
- image->ima_buffer_addr,
- image->ima_buffer_size);
+ ima_kexec_buffer = kimage_map_segment(image, image->ima_segment_index);
if (!ima_kexec_buffer) {
pr_err("Could not map measurements buffer.\n");
return;
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 171a71457ec3..1de46c06f8c2 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -1656,6 +1656,18 @@ static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
alc236_fixup_hp_micmute_led_vref(codec, fix, action);
}
+static void alc236_fixup_hp_mute_led_micmute_gpio(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (action == HDA_FIXUP_ACT_PRE_PROBE)
+ spec->micmute_led_polarity = 1;
+
+ alc236_fixup_hp_mute_led_coefbit2(codec, fix, action);
+ alc_fixup_hp_gpio_led(codec, action, 0x00, 0x01);
+}
+
static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
const unsigned short coefs[2])
{
@@ -3753,6 +3765,7 @@ enum {
ALC295_FIXUP_DELL_TAS2781_I2C,
ALC245_FIXUP_TAS2781_SPI_2,
ALC287_FIXUP_TXNW2781_I2C,
+ ALC287_FIXUP_TXNW2781_I2C_ASUS,
ALC287_FIXUP_YOGA7_14ARB7_I2C,
ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT,
@@ -5326,9 +5339,7 @@ static const struct hda_fixup alc269_fixups[] = {
},
[ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO] = {
.type = HDA_FIXUP_FUNC,
- .v.func = alc236_fixup_hp_mute_led_coefbit2,
- .chained = true,
- .chain_id = ALC236_FIXUP_HP_GPIO_LED,
+ .v.func = alc236_fixup_hp_mute_led_micmute_gpio,
},
[ALC236_FIXUP_LENOVO_INV_DMIC] = {
.type = HDA_FIXUP_FUNC,
@@ -6053,6 +6064,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK,
},
+ [ALC287_FIXUP_TXNW2781_I2C_ASUS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = tas2781_fixup_txnw_i2c,
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_SPK,
+ },
[ALC287_FIXUP_YOGA7_14ARB7_I2C] = {
.type = HDA_FIXUP_FUNC,
.v.func = yoga7_14arb7_fixup_i2c,
@@ -6771,10 +6788,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8e61, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e62, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e8a, "HP NexusX", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x8e9c, "HP 16 Clipper OmniBook X X360", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e9d, "HP 17 Turbine OmniBook X UMA", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e9e, "HP 17 Turbine OmniBook X UMA", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8eb6, "HP Abe A6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
- SND_PCI_QUIRK(0x103c, 0x8eb7, "HP Abe A6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
SND_PCI_QUIRK(0x103c, 0x8eb8, "HP Abe A6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
SND_PCI_QUIRK(0x103c, 0x8ec1, "HP 200 G2i", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
SND_PCI_QUIRK(0x103c, 0x8ec4, "HP Bantie I6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
@@ -6790,11 +6807,13 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8eda, "HP ZBook Firefly 16W", ALC245_FIXUP_HP_TAS2781_SPI_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8ee4, "HP Bantie A6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
SND_PCI_QUIRK(0x103c, 0x8ee5, "HP Bantie A6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x8ee7, "HP Abe A6U", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
SND_PCI_QUIRK(0x103c, 0x8f0c, "HP ZBook X G2i 16W", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8f0e, "HP ZBook X G2i 16W", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8f40, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8f41, "HP ZBook 8 G2a 16", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8f42, "HP ZBook 8 G2a 14W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x8f57, "HP Trekker G7JC", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8f62, "HP ZBook 8 G2a 16W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
SND_PCI_QUIRK(0x1043, 0x1032, "ASUS VivoBook X513EA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1034, "ASUS GU605C", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
@@ -6827,8 +6846,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1314, "ASUS GA605K", ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC),
- SND_PCI_QUIRK(0x1043, 0x1384, "ASUS RC73XA", ALC287_FIXUP_TXNW2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x1394, "ASUS RC73YA", ALC287_FIXUP_TXNW2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x1384, "ASUS RC73XA", ALC287_FIXUP_TXNW2781_I2C_ASUS),
+ SND_PCI_QUIRK(0x1043, 0x1394, "ASUS RC73YA", ALC287_FIXUP_TXNW2781_I2C_ASUS),
SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650PY/PZ/PV/PU/PYV/PZV/PIV/PVV", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC),
@@ -7296,6 +7315,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),
SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
diff --git a/sound/hda/controllers/cix-ipbloq.c b/sound/hda/controllers/cix-ipbloq.c
index 99f9f48e91d4..c1084a915c13 100644
--- a/sound/hda/controllers/cix-ipbloq.c
+++ b/sound/hda/controllers/cix-ipbloq.c
@@ -115,10 +115,8 @@ static int cix_ipbloq_hda_init(struct cix_ipbloq_hda *hda,
bus->addr = res->start;
irq_id = platform_get_irq(pdev, 0);
- if (irq_id < 0) {
- dev_err(hda->dev, "failed to get the irq, err = %d\n", irq_id);
+ if (irq_id < 0)
return irq_id;
- }
err = devm_request_irq(hda->dev, irq_id, azx_interrupt,
0, KBUILD_MODNAME, chip);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 13419837dfb7..a3291e626440 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -131,7 +131,13 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
link->config_index = 1;
link->config_regs = PRESENT_OPTION;
- return pdacf_config(link);
+ err = pdacf_config(link);
+ if (err < 0) {
+ card_list[i] = NULL;
+ snd_card_free(card);
+ return err;
+ }
+ return 0;
}
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 2e09f2a513a6..9a5c9aa8eec4 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -284,7 +284,13 @@ static int vxpocket_probe(struct pcmcia_device *p_dev)
vxp->p_dev = p_dev;
- return vxpocket_config(p_dev);
+ err = vxpocket_config(p_dev);
+ if (err < 0) {
+ card_alloc &= ~(1 << i);
+ snd_card_free(card);
+ return err;
+ }
+ return 0;
}
static void vxpocket_detach(struct pcmcia_device *link)
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index f210a253da9f..bf4d9d336561 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -661,6 +661,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7UCX"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HONOR"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "GOH-X"),
+ }
+ },
{}
};
diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 783d2ef21c11..f81cd8cebdd8 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -783,16 +783,12 @@ static int ak4458_i2c_probe(struct i2c_client *i2c)
pm_runtime_enable(&i2c->dev);
regcache_cache_only(ak4458->regmap, true);
- ak4458_reset(ak4458, false);
return 0;
}
static void ak4458_i2c_remove(struct i2c_client *i2c)
{
- struct ak4458_priv *ak4458 = i2c_get_clientdata(i2c);
-
- ak4458_reset(ak4458, true);
pm_runtime_disable(&i2c->dev);
}
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index e3f9b03df3aa..feecef258b65 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -115,7 +115,8 @@ static const struct reg_sequence rt1320_blind_write[] = {
static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0xc003, 0xe0 },
{ 0xe80a, 0x01 },
- { 0xc5c3, 0xf3 },
+ { 0xc5c3, 0xf2 },
+ { 0xc5c8, 0x03 },
{ 0xc057, 0x51 },
{ 0xc054, 0x35 },
{ 0xca05, 0xd6 },
@@ -126,8 +127,6 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0xc609, 0x40 },
{ 0xc046, 0xff },
{ 0xc045, 0xff },
- { 0xda81, 0x14 },
- { 0xda8d, 0x14 },
{ 0xc044, 0xff },
{ 0xc043, 0xff },
{ 0xc042, 0xff },
@@ -136,8 +135,8 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0xcc10, 0x01 },
{ 0xc700, 0xf0 },
{ 0xc701, 0x13 },
- { 0xc901, 0x09 },
- { 0xc900, 0xd0 },
+ { 0xc901, 0x04 },
+ { 0xc900, 0x73 },
{ 0xde03, 0x05 },
{ 0xdd0b, 0x0d },
{ 0xdd0a, 0xff },
@@ -153,6 +152,7 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0xf082, 0xff },
{ 0xf081, 0xff },
{ 0xf080, 0xff },
+ { 0xe801, 0x01 },
{ 0xe802, 0xf8 },
{ 0xe803, 0xbe },
{ 0xc003, 0xc0 },
@@ -202,7 +202,7 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0x3fc2bfc3, 0x00 },
{ 0x3fc2bfc2, 0x00 },
{ 0x3fc2bfc1, 0x00 },
- { 0x3fc2bfc0, 0x03 },
+ { 0x3fc2bfc0, 0x07 },
{ 0x0000d486, 0x43 },
{ SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x00 },
{ 0x1000db00, 0x07 },
@@ -241,9 +241,7 @@ static const struct reg_sequence rt1320_vc_blind_write[] = {
{ 0x1000db21, 0x00 },
{ 0x1000db22, 0x00 },
{ 0x1000db23, 0x00 },
- { 0x0000d540, 0x01 },
- { 0x0000c081, 0xfc },
- { 0x0000f01e, 0x80 },
+ { 0x0000d540, 0x21 },
{ 0xc01b, 0xfc },
{ 0xc5d1, 0x89 },
{ 0xc5d8, 0x0a },
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 2c7eb0baa0f3..70a6159430ed 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -1045,8 +1045,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
* The notifier is initialized in snd_soc_card_jack_new(), then
* snd_soc_jack_notifier_register can be called.
*/
- if (of_property_read_bool(np, "hp-det-gpios") ||
- of_property_read_bool(np, "hp-det-gpio") /* deprecated */) {
+ if (of_property_present(np, "hp-det-gpios") ||
+ of_property_present(np, "hp-det-gpio") /* deprecated */) {
ret = simple_util_init_jack(&priv->card, &priv->hp_jack,
1, NULL, "Headphone Jack");
if (ret)
@@ -1055,8 +1055,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb);
}
- if (of_property_read_bool(np, "mic-det-gpios") ||
- of_property_read_bool(np, "mic-det-gpio") /* deprecated */) {
+ if (of_property_present(np, "mic-det-gpios") ||
+ of_property_present(np, "mic-det-gpio") /* deprecated */) {
ret = simple_util_init_jack(&priv->card, &priv->mic_jack,
0, NULL, "Mic Jack");
if (ret)
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index 1bba48318e2d..7dacc06b2f02 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -473,5 +473,8 @@ struct snd_soc_component_driver fsl_asrc_component = {
.pointer = fsl_asrc_dma_pcm_pointer,
.pcm_construct = fsl_asrc_dma_pcm_new,
.legacy_dai_naming = 1,
+#ifdef CONFIG_DEBUG_FS
+ .debugfs_prefix = "asrc",
+#endif
};
EXPORT_SYMBOL_GPL(fsl_asrc_component);
diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index f404a39009e1..e64a0d97afd0 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1577,6 +1577,9 @@ static const struct snd_soc_component_driver fsl_easrc_component = {
.controls = fsl_easrc_snd_controls,
.num_controls = ARRAY_SIZE(fsl_easrc_snd_controls),
.legacy_dai_naming = 1,
+#ifdef CONFIG_DEBUG_FS
+ .debugfs_prefix = "easrc",
+#endif
};
static const struct reg_default fsl_easrc_reg_defaults[] = {
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 72bfc91e21b9..2fa14fbdfe1a 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -917,8 +917,14 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
tx ? sai->dma_params_tx.maxburst :
sai->dma_params_rx.maxburst);
- ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE, &sai->constraint_rates);
+ if (sai->is_consumer_mode[tx])
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &fsl_sai_rate_constraints);
+ else
+ ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &sai->constraint_rates);
return ret;
}
@@ -1075,6 +1081,7 @@ static const struct reg_default fsl_sai_reg_defaults_ofs0[] = {
{FSL_SAI_TDR6, 0},
{FSL_SAI_TDR7, 0},
{FSL_SAI_TMR, 0},
+ {FSL_SAI_TTCTL, 0},
{FSL_SAI_RCR1(0), 0},
{FSL_SAI_RCR2(0), 0},
{FSL_SAI_RCR3(0), 0},
@@ -1098,12 +1105,14 @@ static const struct reg_default fsl_sai_reg_defaults_ofs8[] = {
{FSL_SAI_TDR6, 0},
{FSL_SAI_TDR7, 0},
{FSL_SAI_TMR, 0},
+ {FSL_SAI_TTCTL, 0},
{FSL_SAI_RCR1(8), 0},
{FSL_SAI_RCR2(8), 0},
{FSL_SAI_RCR3(8), 0},
{FSL_SAI_RCR4(8), 0},
{FSL_SAI_RCR5(8), 0},
{FSL_SAI_RMR, 0},
+ {FSL_SAI_RTCTL, 0},
{FSL_SAI_MCTL, 0},
{FSL_SAI_MDIV, 0},
};
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index 06434b2c9a0f..a268fb81a2f8 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -1323,6 +1323,7 @@ static const struct reg_default fsl_xcvr_phy_reg_defaults[] = {
};
static const struct regmap_config fsl_xcvr_regmap_phy_cfg = {
+ .name = "phy",
.reg_bits = 8,
.reg_stride = 4,
.val_bits = 32,
@@ -1335,6 +1336,7 @@ static const struct regmap_config fsl_xcvr_regmap_phy_cfg = {
};
static const struct regmap_config fsl_xcvr_regmap_pllv0_cfg = {
+ .name = "pllv0",
.reg_bits = 8,
.reg_stride = 4,
.val_bits = 32,
@@ -1345,6 +1347,7 @@ static const struct regmap_config fsl_xcvr_regmap_pllv0_cfg = {
};
static const struct regmap_config fsl_xcvr_regmap_pllv1_cfg = {
+ .name = "pllv1",
.reg_bits = 8,
.reg_stride = 4,
.val_bits = 32,
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index ec9fd8486c05..1270ee21ee72 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -699,6 +699,69 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_fb_adr[] = {
},
};
+static const struct snd_soc_acpi_adr_device cs35l56_6amp_1_fb_adr[] = {
+ {
+ .adr = 0x00013701FA355601ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_r_fb_endpoints),
+ .endpoints = cs35l56_r_fb_endpoints,
+ .name_prefix = "AMP6"
+ },
+ {
+ .adr = 0x00013601FA355601ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_3_fb_endpoints),
+ .endpoints = cs35l56_3_fb_endpoints,
+ .name_prefix = "AMP5"
+ },
+ {
+ .adr = 0x00013501FA355601ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_5_fb_endpoints),
+ .endpoints = cs35l56_5_fb_endpoints,
+ .name_prefix = "AMP4"
+ },
+};
+
+static const struct snd_soc_acpi_adr_device cs35l63_6amp_3_fb_adr[] = {
+ {
+ .adr = 0x00033001FA356301ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_l_fb_endpoints),
+ .endpoints = cs35l56_l_fb_endpoints,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00033201FA356301ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_2_fb_endpoints),
+ .endpoints = cs35l56_2_fb_endpoints,
+ .name_prefix = "AMP3"
+ },
+ {
+ .adr = 0x00033401FA356301ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_4_fb_endpoints),
+ .endpoints = cs35l56_4_fb_endpoints,
+ .name_prefix = "AMP5"
+ },
+};
+
+static const struct snd_soc_acpi_adr_device cs35l63_6amp_2_fb_adr[] = {
+ {
+ .adr = 0x00023101FA356301ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_r_fb_endpoints),
+ .endpoints = cs35l56_r_fb_endpoints,
+ .name_prefix = "AMP2"
+ },
+ {
+ .adr = 0x00023301FA356301ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_3_fb_endpoints),
+ .endpoints = cs35l56_3_fb_endpoints,
+ .name_prefix = "AMP4"
+ },
+ {
+ .adr = 0x00023501FA356301ull,
+ .num_endpoints = ARRAY_SIZE(cs35l56_5_fb_endpoints),
+ .endpoints = cs35l56_5_fb_endpoints,
+ .name_prefix = "AMP6"
+ },
+};
+
static const struct snd_soc_acpi_adr_device cs35l56_2_r_adr[] = {
{
.adr = 0x00023201FA355601ull,
@@ -1069,6 +1132,35 @@ static const struct snd_soc_acpi_link_adr mtl_cs35l56_x8_link0_link1_fb[] = {
{}
};
+static const struct snd_soc_acpi_link_adr mtl_cs35l56_x6_link0_link1_fb[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(cs35l56_6amp_1_fb_adr),
+ .adr_d = cs35l56_6amp_1_fb_adr,
+ },
+ {
+ .mask = BIT(0),
+ /* First 3 amps in cs35l56_0_fb_adr */
+ .num_adr = 3,
+ .adr_d = cs35l56_0_fb_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr mtl_cs35l63_x6_link2_link3_fb[] = {
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l63_6amp_3_fb_adr),
+ .adr_d = cs35l63_6amp_3_fb_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l63_6amp_2_fb_adr),
+ .adr_d = cs35l63_6amp_2_fb_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr mtl_cs35l63_x2_link1_link3_fb[] = {
{
.mask = BIT(3),
@@ -1190,6 +1282,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
+ .link_mask = BIT(0) | BIT(1),
+ .links = mtl_cs35l56_x6_link0_link1_fb,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-cs35l56-l01-fb6.tplg"
+ },
+ {
.link_mask = BIT(0),
.links = mtl_cs42l43_l0,
.drv_name = "sof_sdw",
@@ -1203,6 +1301,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.sof_tplg_filename = "sof-mtl-cs35l56-l01-fb8.tplg",
},
{
+ .link_mask = BIT(2) | BIT(3),
+ .links = mtl_cs35l63_x6_link2_link3_fb,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-cs35l56-l01-fb6.tplg",
+ },
+ {
.link_mask = GENMASK(3, 0),
.links = mtl_3_in_1_sdca,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-nvl-match.c b/sound/soc/intel/common/soc-acpi-intel-nvl-match.c
index 2768dd10aaa0..b8695d47e55b 100644
--- a/sound/soc/intel/common/soc-acpi-intel-nvl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-nvl-match.c
@@ -15,49 +15,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_machines[] = {
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_nvl_machines);
-/*
- * Multi-function codecs with three endpoints created for
- * headset, amp and dmic functions.
- */
-static const struct snd_soc_acpi_endpoint rt_mf_endpoints[] = {
- {
- .num = 0,
- .aggregated = 0,
- .group_position = 0,
- .group_id = 0,
- },
- {
- .num = 1,
- .aggregated = 0,
- .group_position = 0,
- .group_id = 0,
- },
- {
- .num = 2,
- .aggregated = 0,
- .group_position = 0,
- .group_id = 0,
- },
-};
-
-static const struct snd_soc_acpi_adr_device rt722_3_single_adr[] = {
- {
- .adr = 0x000330025d072201ull,
- .num_endpoints = ARRAY_SIZE(rt_mf_endpoints),
- .endpoints = rt_mf_endpoints,
- .name_prefix = "rt722"
- }
-};
-
-static const struct snd_soc_acpi_link_adr nvl_rt722_l3[] = {
- {
- .mask = BIT(3),
- .num_adr = ARRAY_SIZE(rt722_3_single_adr),
- .adr_d = rt722_3_single_adr,
- },
- {}
-};
-
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_sdw_machines[] = {
/* mockup tests need to be first */
@@ -79,12 +36,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-nvl-rt715-rt711-rt1308-mono.tplg",
},
- {
- .link_mask = BIT(3),
- .links = nvl_rt722_l3,
- .drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-nvl-rt722.tplg",
- },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_nvl_sdw_machines);
diff --git a/sound/soc/intel/common/sof-function-topology-lib.c b/sound/soc/intel/common/sof-function-topology-lib.c
index b10d4794159a..0daa7d83808b 100644
--- a/sound/soc/intel/common/sof-function-topology-lib.c
+++ b/sound/soc/intel/common/sof-function-topology-lib.c
@@ -28,7 +28,7 @@ enum tplg_device_id {
#define SOF_INTEL_PLATFORM_NAME_MAX 4
int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
- const char *prefix, const char ***tplg_files)
+ const char *prefix, const char ***tplg_files, bool best_effort)
{
struct snd_soc_acpi_mach_params mach_params = mach->mach_params;
struct snd_soc_dai_link *dai_link;
@@ -87,6 +87,9 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_
dev_dbg(card->dev,
"dai_link %s is not supported by separated tplg yet\n",
dai_link->name);
+ if (best_effort)
+ continue;
+
return 0;
}
if (tplg_mask & BIT(tplg_dev))
diff --git a/sound/soc/intel/common/sof-function-topology-lib.h b/sound/soc/intel/common/sof-function-topology-lib.h
index e7d0c39d0788..f358f8c52d78 100644
--- a/sound/soc/intel/common/sof-function-topology-lib.h
+++ b/sound/soc/intel/common/sof-function-topology-lib.h
@@ -10,6 +10,6 @@
#define _SND_SOC_ACPI_INTEL_GET_TPLG_H
int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
- const char *prefix, const char ***tplg_files);
+ const char *prefix, const char ***tplg_files, bool best_effort);
#endif
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index e18a8e44f2db..0ce9dff4dc52 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -365,10 +365,12 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;
case QUATERNARY_MI2S_RX:
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
snd_soc_dai_set_sysclk(cpu_dai,
Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
snd_soc_dai_set_fmt(cpu_dai, fmt);
+ snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;
case QUATERNARY_TDM_RX_0:
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 6c656b2f7f3a..f169d95895ea 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -1534,8 +1534,10 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
* endpoint check is not necessary
*/
if (dai_info->quirk &&
- !(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk)))
+ !(dai_info->quirk_exclude ^ !!(dai_info->quirk & ctx->mc_quirk))) {
+ (*num_devs)--;
continue;
+ }
} else {
/* Check SDCA codec endpoint if there is no matching quirk */
ret = is_sdca_endpoint_present(dev, codec_info, adr_link, i, j);
@@ -1543,8 +1545,10 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
return ret;
/* The endpoint is not present, skip */
- if (!ret)
+ if (!ret) {
+ (*num_devs)--;
continue;
+ }
}
dev_dbg(dev,
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index ce86978c158d..624e9269fc25 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -111,7 +111,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
static int sdca_soc_q78_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val,
- unsigned int mask, unsigned int shift, int max)
+ unsigned int mask, unsigned int shift, int max,
+ bool sx)
{
int val = reg_val;
@@ -141,20 +142,26 @@ static unsigned int sdca_soc_q78_ctl_to_reg(struct soc_mixer_control *mc, int va
}
static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val,
- unsigned int mask, unsigned int shift, int max)
+ unsigned int mask, unsigned int shift, int max,
+ bool sx)
{
int val = (reg_val >> shift) & mask;
if (mc->sign_bit)
val = sign_extend32(val, mc->sign_bit);
- val = clamp(val, mc->min, mc->max);
- val -= mc->min;
+ if (sx) {
+ val -= mc->min; // SX controls intentionally can overflow here
+ val = min_t(unsigned int, val & mask, max);
+ } else {
+ val = clamp(val, mc->min, mc->max);
+ val -= mc->min;
+ }
if (mc->invert)
val = max - val;
- return val & mask;
+ return val;
}
static unsigned int soc_mixer_ctl_to_reg(struct soc_mixer_control *mc, int val,
@@ -280,9 +287,10 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
static int soc_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol,
- struct soc_mixer_control *mc, int mask, int max)
+ struct soc_mixer_control *mc, int mask, int max, bool sx)
{
- int (*reg_to_ctl)(struct soc_mixer_control *, unsigned int, unsigned int, unsigned int, int);
+ int (*reg_to_ctl)(struct soc_mixer_control *, unsigned int, unsigned int,
+ unsigned int, int, bool);
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
unsigned int reg_val;
int val;
@@ -293,16 +301,16 @@ static int soc_get_volsw(struct snd_kcontrol *kcontrol,
reg_to_ctl = soc_mixer_reg_to_ctl;
reg_val = snd_soc_component_read(component, mc->reg);
- val = reg_to_ctl(mc, reg_val, mask, mc->shift, max);
+ val = reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
ucontrol->value.integer.value[0] = val;
if (snd_soc_volsw_is_stereo(mc)) {
if (mc->reg == mc->rreg) {
- val = reg_to_ctl(mc, reg_val, mask, mc->rshift, max);
+ val = reg_to_ctl(mc, reg_val, mask, mc->rshift, max, sx);
} else {
reg_val = snd_soc_component_read(component, mc->rreg);
- val = reg_to_ctl(mc, reg_val, mask, mc->shift, max);
+ val = reg_to_ctl(mc, reg_val, mask, mc->shift, max, sx);
}
ucontrol->value.integer.value[1] = val;
@@ -371,7 +379,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int mask = soc_mixer_mask(mc);
- return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max - mc->min);
+ return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max - mc->min, false);
}
EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
@@ -413,7 +421,7 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int mask = soc_mixer_sx_mask(mc);
- return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max);
+ return soc_get_volsw(kcontrol, ucontrol, mc, mask, mc->max, true);
}
EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx);
diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c
index 7b2533999195..23adc5d765b4 100644
--- a/sound/soc/sof/intel/pci-mtl.c
+++ b/sound/soc/sof/intel/pci-mtl.c
@@ -47,7 +47,7 @@ static const struct sof_dev_desc mtl_desc = {
[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/mtl",
},
.default_tplg_path = {
- [SOF_IPC_TYPE_4] = "intel/sof-ace-tplg",
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
},
.default_fw_filename = {
[SOF_IPC_TYPE_4] = "sof-mtl.ri",
@@ -77,7 +77,7 @@ static const struct sof_dev_desc arl_desc = {
[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/arl",
},
.default_tplg_path = {
- [SOF_IPC_TYPE_4] = "intel/sof-ace-tplg",
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
},
.default_fw_filename = {
[SOF_IPC_TYPE_4] = "sof-arl.ri",
@@ -107,7 +107,7 @@ static const struct sof_dev_desc arl_s_desc = {
[SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/arl-s",
},
.default_tplg_path = {
- [SOF_IPC_TYPE_4] = "intel/sof-ace-tplg",
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
},
.default_fw_filename = {
[SOF_IPC_TYPE_4] = "sof-arl-s.ri",
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 221e9d4052b8..d621e7914a73 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -1752,11 +1752,9 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
channel_count = params_channels(params);
sample_rate = params_rate(params);
bit_depth = params_width(params);
- /*
- * Look for 32-bit blob first instead of 16-bit if copier
- * supports multiple formats
- */
- if (bit_depth == 16 && !single_bitdepth) {
+
+ /* Prefer 32-bit blob if copier supports multiple formats */
+ if (bit_depth <= 16 && !single_bitdepth) {
dev_dbg(sdev->dev, "Looking for 32-bit blob first for DMIC\n");
format_change = true;
bit_depth = 32;
@@ -1799,10 +1797,18 @@ snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai
if (format_change) {
/*
* The 32-bit blob was not found in NHLT table, try to
- * look for one based on the params
+ * look for 16-bit for DMIC or based on the params for
+ * SSP
*/
- bit_depth = params_width(params);
- format_change = false;
+ if (linktype == SOF_DAI_INTEL_DMIC) {
+ bit_depth = 16;
+ if (params_width(params) == 16)
+ format_change = false;
+ } else {
+ bit_depth = params_width(params);
+ format_change = false;
+ }
+
get_new_blob = true;
} else if (linktype == SOF_DAI_INTEL_DMIC && !single_bitdepth) {
/*
@@ -1837,7 +1843,7 @@ out:
*len = cfg->size >> 2;
*dst = (u32 *)cfg->caps;
- if (format_change) {
+ if (format_change || params_format(params) == SNDRV_PCM_FORMAT_FLOAT_LE) {
/*
* Update the params to reflect that different blob was loaded
* instead of the requested bit depth (16 -> 32 or 32 -> 16).
@@ -2280,8 +2286,19 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
ch_map >>= 4;
}
- step = ch_count / blob->alh_cfg.device_count;
- mask = GENMASK(step - 1, 0);
+ if (swidget->id == snd_soc_dapm_dai_in && ch_count == out_ref_channels) {
+ /*
+ * For playback DAI widgets where the channel number is equal to
+ * the output reference channels, set the step = 0 to ensure all
+ * the ch_mask is applied to all alh mappings.
+ */
+ mask = ch_mask;
+ step = 0;
+ } else {
+ step = ch_count / blob->alh_cfg.device_count;
+ mask = GENMASK(step - 1, 0);
+ }
+
/*
* Set each gtw_cfg.node_id to blob->alh_cfg.mapping[]
* for all widgets with the same stream name
@@ -2316,8 +2333,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
}
/*
- * Set the same channel mask for playback as the audio data is
- * duplicated for all speakers. For capture, split the channels
+ * Set the same channel mask if the widget channel count is the same
+ * as the FE channels for playback as the audio data is duplicated
+ * for all speakers in this case. Otherwise, split the channels
* among the aggregated DAIs. For example, with 4 channels on 2
* aggregated DAIs, the channel_mask should be 0x3 and 0xc for the
* two DAI's.
@@ -2326,10 +2344,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
* the tables in soc_acpi files depending on the _ADR and devID
* registers for each codec.
*/
- if (w->id == snd_soc_dapm_dai_in)
- blob->alh_cfg.mapping[i].channel_mask = ch_mask;
- else
- blob->alh_cfg.mapping[i].channel_mask = mask << (step * i);
+ blob->alh_cfg.mapping[i].channel_mask = mask << (step * i);
i++;
}
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index c1083ea4624a..9bf8ab610a7e 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -2106,8 +2106,8 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
/* source component */
source_swidget = snd_sof_find_swidget(scomp, (char *)route->source);
if (!source_swidget) {
- dev_err(scomp->dev, "error: source %s not found\n",
- route->source);
+ dev_err(scomp->dev, "source %s for sink %s is not found\n",
+ route->source, route->sink);
ret = -EINVAL;
goto err;
}
@@ -2125,8 +2125,8 @@ static int sof_route_load(struct snd_soc_component *scomp, int index,
/* sink component */
sink_swidget = snd_sof_find_swidget(scomp, (char *)route->sink);
if (!sink_swidget) {
- dev_err(scomp->dev, "error: sink %s not found\n",
- route->sink);
+ dev_err(scomp->dev, "sink %s for source %s is not found\n",
+ route->sink, route->source);
ret = -EINVAL;
goto err;
}
@@ -2506,12 +2506,28 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
if (!tplg_files)
return -ENOMEM;
+ /* Try to use function topologies if possible */
if (!sof_pdata->disable_function_topology && !disable_function_topology &&
sof_pdata->machine && sof_pdata->machine->get_function_tplg_files) {
+ /*
+ * When the topology name contains 'dummy' word, it means that
+ * there is no fallback option to monolithic topology in case
+ * any of the function topologies might be missing.
+ * In this case we should use best effort to form the card,
+ * ignoring functionalities that we are missing a fragment for.
+ *
+ * Note: monolithic topologies also ignore these possibly
+ * missing functions, so the functionality of the card would be
+ * identical to the case if there would be a fallback monolithic
+ * topology created for the configuration.
+ */
+ bool no_fallback = strstr(file, "dummy");
+
tplg_cnt = sof_pdata->machine->get_function_tplg_files(scomp->card,
sof_pdata->machine,
tplg_filename_prefix,
- &tplg_files);
+ &tplg_files,
+ no_fallback);
if (tplg_cnt < 0) {
kfree(tplg_files);
return tplg_cnt;
diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c
index e795907a3963..261d9067d27b 100644
--- a/sound/soc/tegra/tegra210_ahub.c
+++ b/sound/soc/tegra/tegra210_ahub.c
@@ -2077,7 +2077,7 @@ static const struct regmap_config tegra210_ahub_regmap_config = {
.val_bits = 32,
.reg_stride = 4,
.max_register = TEGRA210_MAX_REGISTER_ADDR,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_FLAT_S,
};
static const struct regmap_config tegra186_ahub_regmap_config = {
@@ -2085,7 +2085,7 @@ static const struct regmap_config tegra186_ahub_regmap_config = {
.val_bits = 32,
.reg_stride = 4,
.max_register = TEGRA186_MAX_REGISTER_ADDR,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_FLAT_S,
};
static const struct regmap_config tegra264_ahub_regmap_config = {
@@ -2094,7 +2094,7 @@ static const struct regmap_config tegra264_ahub_regmap_config = {
.reg_stride = 4,
.writeable_reg = tegra264_ahub_wr_reg,
.max_register = TEGRA264_MAX_REGISTER_ADDR,
- .cache_type = REGCACHE_FLAT,
+ .cache_type = REGCACHE_FLAT_S,
};
static const struct tegra_ahub_soc_data soc_data_tegra210 = {
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index cc15624ecaff..8f9313857ee9 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1481,15 +1481,15 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
return err;
}
- err = snd_usb_init_pitch(chip, ep->cur_audiofmt);
+ err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
if (err < 0)
return err;
- err = init_sample_rate(chip, ep);
+ err = snd_usb_init_pitch(chip, ep->cur_audiofmt);
if (err < 0)
return err;
- err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
+ err = init_sample_rate(chip, ep);
if (err < 0)
return err;
diff --git a/sound/usb/format.c b/sound/usb/format.c
index ec95a063beb1..64cfe4a9d8cd 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -34,6 +34,7 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
{
int sample_width, sample_bytes;
u64 pcm_formats = 0;
+ u64 dsd_formats = 0;
switch (fp->protocol) {
case UAC_VERSION_1:
@@ -154,7 +155,9 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
fp->iface, fp->altsetting, format);
}
- pcm_formats |= snd_usb_interface_dsd_format_quirks(chip, fp, sample_bytes);
+ dsd_formats |= snd_usb_interface_dsd_format_quirks(chip, fp, sample_bytes);
+ if (dsd_formats && !fp->dsd_dop)
+ pcm_formats = dsd_formats;
return pcm_formats;
}
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index 1c5712c31f5e..f9df40730eff 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -655,17 +655,25 @@ static void get_meter_levels_from_urb(int s,
u8 *meter_urb)
{
int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
+ int ch = MUB2(meter_urb, s) - 1;
+
+ if (ch < 0)
+ return;
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
- if (MUC0(meter_urb, s) == 0x72)
- store->meter_level[MUB2(meter_urb, s) - 1] = val;
- if (MUC0(meter_urb, s) == 0xb2)
- store->comp_level[MUB2(meter_urb, s) - 1] = val;
+ if (ch < SND_US16X08_MAX_CHANNELS) {
+ if (MUC0(meter_urb, s) == 0x72)
+ store->meter_level[ch] = val;
+ if (MUC0(meter_urb, s) == 0xb2)
+ store->comp_level[ch] = val;
+ }
}
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
- MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62)
- store->master_level[MUB2(meter_urb, s) - 1] = val;
+ MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62) {
+ if (ch < ARRAY_SIZE(store->master_level))
+ store->master_level[ch] = val;
+ }
}
/* Function to retrieve current meter values from the device.
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 61bd61ffb1b2..f38330b095e9 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2221,7 +2221,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
- QUIRK_FLAG_IFACE_DELAY),
+ QUIRK_FLAG_IFACE_DELAY | QUIRK_FLAG_FORCE_IFACE_RESET),
DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
QUIRK_FLAG_IFACE_DELAY),
@@ -2229,7 +2229,13 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_FORCE_IFACE_RESET),
DEVICE_FLG(0x0644, 0x806b, /* TEAC UD-701 */
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
- QUIRK_FLAG_IFACE_DELAY),
+ QUIRK_FLAG_IFACE_DELAY | QUIRK_FLAG_FORCE_IFACE_RESET),
+ DEVICE_FLG(0x0644, 0x807d, /* TEAC UD-507 */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+ QUIRK_FLAG_IFACE_DELAY | QUIRK_FLAG_FORCE_IFACE_RESET),
+ DEVICE_FLG(0x0644, 0x806c, /* Esoteric XD */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+ QUIRK_FLAG_IFACE_DELAY | QUIRK_FLAG_FORCE_IFACE_RESET),
DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
@@ -2388,6 +2394,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */
QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x3255, 0x0000, /* Luxman D-10X */
+ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
DEVICE_FLG(0x339b, 0x3a07, /* Synaptics HONOR USB-C HEADSET */
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
@@ -2431,6 +2439,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DSD_RAW),
VENDOR_FLG(0x2622, /* IAG Limited devices */
QUIRK_FLAG_DSD_RAW),
+ VENDOR_FLG(0x2772, /* Musical Fidelity devices */
+ QUIRK_FLAG_DSD_RAW),
VENDOR_FLG(0x278b, /* Rotel? */
QUIRK_FLAG_DSD_RAW),
VENDOR_FLG(0x292b, /* Gustard/Ess based devices */
diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h
index f898c47e551f..9b73c1aa3ad7 100644
--- a/tools/arch/arm64/include/asm/cputype.h
+++ b/tools/arch/arm64/include/asm/cputype.h
@@ -81,7 +81,6 @@
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
#define ARM_CPU_PART_CORTEX_X1 0xD44
#define ARM_CPU_PART_CORTEX_A510 0xD46
-#define ARM_CPU_PART_CORTEX_X1C 0xD4C
#define ARM_CPU_PART_CORTEX_A520 0xD80
#define ARM_CPU_PART_CORTEX_A710 0xD47
#define ARM_CPU_PART_CORTEX_A715 0xD4D
@@ -93,6 +92,7 @@
#define ARM_CPU_PART_NEOVERSE_V2 0xD4F
#define ARM_CPU_PART_CORTEX_A720 0xD81
#define ARM_CPU_PART_CORTEX_X4 0xD82
+#define ARM_CPU_PART_NEOVERSE_V3AE 0xD83
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
#define ARM_CPU_PART_CORTEX_X925 0xD85
#define ARM_CPU_PART_CORTEX_A725 0xD87
@@ -130,6 +130,7 @@
#define NVIDIA_CPU_PART_DENVER 0x003
#define NVIDIA_CPU_PART_CARMEL 0x004
+#define NVIDIA_CPU_PART_OLYMPUS 0x010
#define FUJITSU_CPU_PART_A64FX 0x001
@@ -171,7 +172,6 @@
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
-#define MIDR_CORTEX_X1C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
#define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520)
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
@@ -183,6 +183,7 @@
#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2)
#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720)
#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4)
+#define MIDR_NEOVERSE_V3AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3AE)
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
@@ -222,6 +223,7 @@
#define MIDR_NVIDIA_DENVER MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER)
#define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
+#define MIDR_NVIDIA_OLYMPUS MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_OLYMPUS)
#define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)
#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09)
@@ -245,7 +247,7 @@
/* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
#define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX
#define MIDR_FUJITSU_ERRATUM_010001_MASK (~MIDR_CPU_VAR_REV(1, 0))
-#define TCR_CLEAR_FUJITSU_ERRATUM_010001 (TCR_NFD1 | TCR_NFD0)
+#define TCR_CLEAR_FUJITSU_ERRATUM_010001 (TCR_EL1_NFD1 | TCR_EL1_NFD0)
#ifndef __ASSEMBLER__
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index ccc01ad6ff7c..c3b53beb1300 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -314,6 +314,7 @@
#define X86_FEATURE_SM4 (12*32+ 2) /* SM4 instructions */
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* "avx_vnni" AVX VNNI instructions */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* "avx512_bf16" AVX512 BFLOAT16 instructions */
+#define X86_FEATURE_LASS (12*32+ 6) /* "lass" Linear Address Space Separation */
#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* CMPccXADD instructions */
#define X86_FEATURE_ARCH_PERFMON_EXT (12*32+ 8) /* Intel Architectural PerfMon Extension */
#define X86_FEATURE_FZRM (12*32+10) /* Fast zero-length REP MOVSB */
@@ -338,6 +339,7 @@
#define X86_FEATURE_AMD_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */
#define X86_FEATURE_AMD_STIBP_ALWAYS_ON (13*32+17) /* Single Thread Indirect Branch Predictors always-on preferred */
#define X86_FEATURE_AMD_IBRS_SAME_MODE (13*32+19) /* Indirect Branch Restricted Speculation same mode protection*/
+#define X86_FEATURE_EFER_LMSLE_MBZ (13*32+20) /* EFER.LMSLE must be zero */
#define X86_FEATURE_AMD_PPIN (13*32+23) /* "amd_ppin" Protected Processor Inventory Number */
#define X86_FEATURE_AMD_SSBD (13*32+24) /* Speculative Store Bypass Disable */
#define X86_FEATURE_VIRT_SSBD (13*32+25) /* "virt_ssbd" Virtualized Speculative Store Bypass Disable */
@@ -502,6 +504,15 @@
#define X86_FEATURE_IBPB_EXIT_TO_USER (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */
#define X86_FEATURE_ABMC (21*32+15) /* Assignable Bandwidth Monitoring Counters */
#define X86_FEATURE_MSR_IMM (21*32+16) /* MSR immediate form instructions */
+#define X86_FEATURE_SGX_EUPDATESVN (21*32+17) /* Support for ENCLS[EUPDATESVN] instruction */
+
+#define X86_FEATURE_SDCIAE (21*32+18) /* L3 Smart Data Cache Injection Allocation Enforcement */
+#define X86_FEATURE_CLEAR_CPU_BUF_VM_MMIO (21*32+19) /*
+ * Clear CPU buffers before VM-Enter if the vCPU
+ * can access host MMIO (ignored for all intents
+ * and purposes if CLEAR_CPU_BUF_VM is set).
+ */
+#define X86_FEATURE_X2AVIC_EXT (21*32+20) /* AMD SVM x2AVIC support for 4k vCPUs */
/*
* BUG word(s)
diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h
index 9e1720d73244..3d0a0950d20a 100644
--- a/tools/arch/x86/include/asm/msr-index.h
+++ b/tools/arch/x86/include/asm/msr-index.h
@@ -166,6 +166,10 @@
* Processor MMIO stale data
* vulnerabilities.
*/
+#define ARCH_CAP_MCU_ENUM BIT(16) /*
+ * Indicates the presence of microcode update
+ * feature enumeration and status information.
+ */
#define ARCH_CAP_FB_CLEAR BIT(17) /*
* VERW clears CPU fill buffer
* even on MDS_NO CPUs.
@@ -327,6 +331,26 @@
PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE | \
PERF_CAP_PEBS_TIMING_INFO)
+/* Arch PEBS */
+#define MSR_IA32_PEBS_BASE 0x000003f4
+#define MSR_IA32_PEBS_INDEX 0x000003f5
+#define ARCH_PEBS_OFFSET_MASK 0x7fffff
+#define ARCH_PEBS_INDEX_WR_SHIFT 4
+
+#define ARCH_PEBS_RELOAD 0xffffffff
+#define ARCH_PEBS_CNTR_ALLOW BIT_ULL(35)
+#define ARCH_PEBS_CNTR_GP BIT_ULL(36)
+#define ARCH_PEBS_CNTR_FIXED BIT_ULL(37)
+#define ARCH_PEBS_CNTR_METRICS BIT_ULL(38)
+#define ARCH_PEBS_LBR_SHIFT 40
+#define ARCH_PEBS_LBR (0x3ull << ARCH_PEBS_LBR_SHIFT)
+#define ARCH_PEBS_VECR_XMM BIT_ULL(49)
+#define ARCH_PEBS_GPR BIT_ULL(61)
+#define ARCH_PEBS_AUX BIT_ULL(62)
+#define ARCH_PEBS_EN BIT_ULL(63)
+#define ARCH_PEBS_CNTR_MASK (ARCH_PEBS_CNTR_GP | ARCH_PEBS_CNTR_FIXED | \
+ ARCH_PEBS_CNTR_METRICS)
+
#define MSR_IA32_RTIT_CTL 0x00000570
#define RTIT_CTL_TRACEEN BIT(0)
#define RTIT_CTL_CYCLEACC BIT(1)
@@ -929,6 +953,10 @@
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
#define MSR_IA32_UCODE_WRITE 0x00000079
+
+#define MSR_IA32_MCU_ENUMERATION 0x0000007b
+#define MCU_STAGING BIT(4)
+
#define MSR_IA32_UCODE_REV 0x0000008b
/* Intel SGX Launch Enclave Public Key Hash MSRs */
@@ -1226,6 +1254,8 @@
#define MSR_IA32_VMX_VMFUNC 0x00000491
#define MSR_IA32_VMX_PROCBASED_CTLS3 0x00000492
+#define MSR_IA32_MCU_STAGING_MBOX_ADDR 0x000007a5
+
/* Resctrl MSRs: */
/* - Intel: */
#define MSR_IA32_L3_QOS_CFG 0xc81
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index d420c9c066d4..7ceff6583652 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -502,6 +502,7 @@ struct kvm_sync_regs {
/* vendor-specific groups and attributes for system fd */
#define KVM_X86_GRP_SEV 1
# define KVM_X86_SEV_VMSA_FEATURES 0
+# define KVM_X86_SNP_POLICY_BITS 1
struct kvm_vmx_nested_state_data {
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 586d1b2595d1..5442073a2e42 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -224,6 +224,8 @@ endif
$(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF_BOOTSTRAP)
$(QUIET_CLANG)$(CLANG) \
+ -Wno-microsoft-anon-tag \
+ -fms-extensions \
-I$(or $(OUTPUT),.) \
-I$(srctree)/tools/include/uapi/ \
-I$(LIBBPF_BOOTSTRAP_INCLUDE) \
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index a7f030fc5e83..362cf8f4a0a0 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -99,7 +99,8 @@ FEATURE_TESTS_BASIC := \
libzstd \
disassembler-four-args \
disassembler-init-styled \
- file-handle
+ file-handle \
+ libopenssl
# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
# of all feature tests
@@ -147,7 +148,8 @@ FEATURE_DISPLAY ?= \
lzma \
bpf \
libaio \
- libzstd
+ libzstd \
+ libopenssl
#
# Declare group members of a feature to display the logical OR of the detection
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 87a5a908d6fa..0d5a15654b17 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -67,12 +67,13 @@ FILES= \
test-libopencsd.bin \
test-clang.bin \
test-llvm.bin \
- test-llvm-perf.bin \
+ test-llvm-perf.bin \
test-libaio.bin \
test-libzstd.bin \
test-clang-bpf-co-re.bin \
test-file-handle.bin \
- test-libpfm4.bin
+ test-libpfm4.bin \
+ test-libopenssl.bin
FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -106,7 +107,7 @@ all: $(FILES)
__BUILD = $(CC) $(CFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1
BUILD_BFD = $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
- BUILD_ALL = $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -lslang $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -ldl -lz -llzma -lzstd
+ BUILD_ALL = $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -lslang $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -ldl -lz -llzma -lzstd -lssl
__BUILDXX = $(CXX) $(CXXFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS)
BUILDXX = $(__BUILDXX) > $(@:.bin=.make.output) 2>&1
@@ -381,6 +382,9 @@ $(OUTPUT)test-file-handle.bin:
$(OUTPUT)test-libpfm4.bin:
$(BUILD) -lpfm
+$(OUTPUT)test-libopenssl.bin:
+ $(BUILD) -lssl
+
$(OUTPUT)test-bpftool-skeletons.bin:
$(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \
> $(@:.bin=.make.output) 2>&1
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index eb346160d0ba..1488bf6e6078 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -142,6 +142,10 @@
# include "test-libtraceevent.c"
#undef main
+#define main main_test_libopenssl
+# include "test-libopenssl.c"
+#undef main
+
int main(int argc, char *argv[])
{
main_test_libpython();
@@ -173,6 +177,7 @@ int main(int argc, char *argv[])
main_test_reallocarray();
main_test_libzstd();
main_test_libtraceevent();
+ main_test_libopenssl();
return 0;
}
diff --git a/tools/build/feature/test-libopenssl.c b/tools/build/feature/test-libopenssl.c
new file mode 100644
index 000000000000..168c45894e8b
--- /dev/null
+++ b/tools/build/feature/test-libopenssl.c
@@ -0,0 +1,7 @@
+#include <openssl/ssl.h>
+#include <openssl/opensslv.h>
+
+int main(void)
+{
+ return SSL_library_init();
+}
diff --git a/tools/include/linux/gfp_types.h b/tools/include/linux/gfp_types.h
index 65db9349f905..3de43b12209e 100644
--- a/tools/include/linux/gfp_types.h
+++ b/tools/include/linux/gfp_types.h
@@ -55,9 +55,7 @@ enum {
#ifdef CONFIG_LOCKDEP
___GFP_NOLOCKDEP_BIT,
#endif
-#ifdef CONFIG_SLAB_OBJ_EXT
___GFP_NO_OBJ_EXT_BIT,
-#endif
___GFP_LAST_BIT
};
@@ -98,11 +96,7 @@ enum {
#else
#define ___GFP_NOLOCKDEP 0
#endif
-#ifdef CONFIG_SLAB_OBJ_EXT
#define ___GFP_NO_OBJ_EXT BIT(___GFP_NO_OBJ_EXT_BIT)
-#else
-#define ___GFP_NO_OBJ_EXT 0
-#endif
/*
* Physical address zone modifiers (see linux/mmzone.h - low four bits)
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index 4928e33d44ac..d41f8a261bce 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -88,6 +88,14 @@ typedef struct {
# define __aligned_u64 __u64 __attribute__((aligned(8)))
#endif
+#ifndef __aligned_be64
+# define __aligned_be64 __be64 __attribute__((aligned(8)))
+#endif
+
+#ifndef __aligned_le64
+# define __aligned_le64 __le64 __attribute__((aligned(8)))
+#endif
+
struct list_head {
struct list_head *next, *prev;
};
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index 04e0077fb4c9..942370b3f5d2 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h
@@ -857,9 +857,11 @@ __SYSCALL(__NR_open_tree_attr, sys_open_tree_attr)
__SYSCALL(__NR_file_getattr, sys_file_getattr)
#define __NR_file_setattr 469
__SYSCALL(__NR_file_setattr, sys_file_setattr)
+#define __NR_listns 470
+__SYSCALL(__NR_listns, sys_listns)
#undef __NR_syscalls
-#define __NR_syscalls 470
+#define __NR_syscalls 471
/*
* 32 bit systems traditionally used different
diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h
index 3cd5cf15e3c9..27cc159c1d27 100644
--- a/tools/include/uapi/drm/drm.h
+++ b/tools/include/uapi/drm/drm.h
@@ -906,6 +906,21 @@ struct drm_get_cap {
*/
#define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 6
+/**
+ * DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
+ *
+ * If set to 1 the DRM core will allow setting the COLOR_PIPELINE
+ * property on a &drm_plane, as well as drm_colorop properties.
+ *
+ * Setting of these plane properties will be rejected when this client
+ * cap is set:
+ * - COLOR_ENCODING
+ * - COLOR_RANGE
+ *
+ * The client must enable &DRM_CLIENT_CAP_ATOMIC first.
+ */
+#define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE 7
+
/* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
struct drm_set_client_cap {
__u64 capability;
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 52f6000ab020..dddb781b0507 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -179,6 +179,7 @@ struct kvm_xen_exit {
#define KVM_EXIT_LOONGARCH_IOCSR 38
#define KVM_EXIT_MEMORY_FAULT 39
#define KVM_EXIT_TDX 40
+#define KVM_EXIT_ARM_SEA 41
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -473,6 +474,14 @@ struct kvm_run {
} setup_event_notify;
};
} tdx;
+ /* KVM_EXIT_ARM_SEA */
+ struct {
+#define KVM_EXIT_ARM_SEA_FLAG_GPA_VALID (1ULL << 0)
+ __u64 flags;
+ __u64 esr;
+ __u64 gva;
+ __u64 gpa;
+ } arm_sea;
/* Fix the size of the union. */
char padding[256];
};
@@ -963,6 +972,8 @@ struct kvm_enable_cap {
#define KVM_CAP_RISCV_MP_STATE_RESET 242
#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
#define KVM_CAP_GUEST_MEMFD_FLAGS 244
+#define KVM_CAP_ARM_SEA_TO_USER 245
+#define KVM_CAP_S390_USER_OPEREXEC 246
struct kvm_irq_routing_irqchip {
__u32 irqchip;
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 3dc8a8078815..f4dfd23148a5 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -8484,7 +8484,7 @@ static int kallsyms_cb(unsigned long long sym_addr, char sym_type,
struct bpf_object *obj = ctx;
const struct btf_type *t;
struct extern_desc *ext;
- char *res;
+ const char *res;
res = strstr(sym_name, ".llvm.");
if (sym_type == 'd' && res)
@@ -11818,7 +11818,8 @@ static int avail_kallsyms_cb(unsigned long long sym_addr, char sym_type,
*
* [0] fb6a421fb615 ("kallsyms: Match symbols exactly with CONFIG_LTO_CLANG")
*/
- char sym_trim[256], *psym_trim = sym_trim, *sym_sfx;
+ char sym_trim[256], *psym_trim = sym_trim;
+ const char *sym_sfx;
if (!(sym_sfx = strstr(sym_name, ".llvm.")))
return 0;
@@ -12401,7 +12402,7 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz)
if (!search_paths[i])
continue;
for (s = search_paths[i]; s != NULL; s = strchr(s, ':')) {
- char *next_path;
+ const char *next_path;
int seg_len;
if (s[0] == ':')
diff --git a/tools/mm/page_owner_sort.c b/tools/mm/page_owner_sort.c
index 14c67e9e84c4..e6954909401c 100644
--- a/tools/mm/page_owner_sort.c
+++ b/tools/mm/page_owner_sort.c
@@ -181,7 +181,11 @@ static int compare_ts(const void *p1, const void *p2)
{
const struct block_list *l1 = p1, *l2 = p2;
- return l1->ts_nsec < l2->ts_nsec ? -1 : 1;
+ if (l1->ts_nsec < l2->ts_nsec)
+ return -1;
+ if (l1->ts_nsec > l2->ts_nsec)
+ return 1;
+ return 0;
}
static int compare_cull_condition(const void *p1, const void *p2)
diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps
index 865fd2e8519e..08205f9fc525 100644
--- a/tools/net/ynl/Makefile.deps
+++ b/tools/net/ynl/Makefile.deps
@@ -13,6 +13,7 @@ UAPI_PATH:=../../../../include/uapi/
# need the explicit -D matching what's in /usr, to avoid multiple definitions.
get_hdr_inc=-D$(1) -include $(UAPI_PATH)/linux/$(2)
+get_hdr_inc2=-D$(1) -D$(2) -include $(UAPI_PATH)/linux/$(3)
CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h)
CFLAGS_dpll:=$(call get_hdr_inc,_LINUX_DPLL_H,dpll.h)
@@ -48,3 +49,4 @@ CFLAGS_tc:= $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
$(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \
$(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h)
CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h)
+CFLAGS_wireguard:=$(call get_hdr_inc2,_LINUX_WIREGUARD_H,_WG_UAPI_WIREGUARD_H,wireguard.h)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index bd9f4804d56b..d8d25f62aaad 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -701,6 +701,11 @@ ifndef NO_LIBBPF
endif
endif
+ifeq ($(feature-libopenssl), 1)
+ $(call detected,CONFIG_LIBOPENSSL)
+ CFLAGS += -DHAVE_LIBOPENSSL_SUPPORT
+endif
+
ifndef BUILD_BPF_SKEL
# BPF skeletons control a large number of perf features, by default
# they are enabled.
@@ -717,6 +722,9 @@ ifeq ($(BUILD_BPF_SKEL),1)
else ifeq ($(filter -DHAVE_LIBBPF_SUPPORT, $(CFLAGS)),)
$(warning Warning: Disabled BPF skeletons as libbpf is required)
BUILD_BPF_SKEL := 0
+ else ifeq ($(filter -DHAVE_LIBOPENSSL_SUPPORT, $(CFLAGS)),)
+ $(warning Warning: Disabled BPF skeletons as libopenssl is required)
+ BUILD_BPF_SKEL := 0
else ifeq ($(call get-executable,$(CLANG)),)
$(warning Warning: Disabled BPF skeletons as clang ($(CLANG)) is missing)
BUILD_BPF_SKEL := 0
diff --git a/tools/perf/arch/arm/entry/syscalls/syscall.tbl b/tools/perf/arch/arm/entry/syscalls/syscall.tbl
index b07e699aaa3c..fd09afae72a2 100644
--- a/tools/perf/arch/arm/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/arm/entry/syscalls/syscall.tbl
@@ -484,3 +484,4 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
diff --git a/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl b/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
index 7a7049c2c307..9b92bddf06b5 100644
--- a/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
+++ b/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
@@ -384,3 +384,4 @@
467 n64 open_tree_attr sys_open_tree_attr
468 n64 file_getattr sys_file_getattr
469 n64 file_setattr sys_file_setattr
+470 n64 listns sys_listns
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index b453e80dfc00..ec4458cdb97b 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -560,3 +560,4 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
diff --git a/tools/perf/arch/s390/entry/syscalls/syscall.tbl b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
index 8a6744d658db..5863787ab036 100644
--- a/tools/perf/arch/s390/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
@@ -472,3 +472,4 @@
467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr sys_file_setattr
+470 common listns sys_listns sys_listns
diff --git a/tools/perf/arch/sh/entry/syscalls/syscall.tbl b/tools/perf/arch/sh/entry/syscalls/syscall.tbl
index 5e9c9eff5539..969c11325ade 100644
--- a/tools/perf/arch/sh/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/sh/entry/syscalls/syscall.tbl
@@ -473,3 +473,4 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
diff --git a/tools/perf/arch/sparc/entry/syscalls/syscall.tbl b/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
index ebb7d06d1044..39aa26b6a50b 100644
--- a/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/sparc/entry/syscalls/syscall.tbl
@@ -515,3 +515,4 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl
index 4877e16da69a..e979a3eac7a3 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl
@@ -475,3 +475,4 @@
467 i386 open_tree_attr sys_open_tree_attr
468 i386 file_getattr sys_file_getattr
469 i386 file_setattr sys_file_setattr
+470 i386 listns sys_listns
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index ced2a1deecd7..8a4ac4841be6 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -394,6 +394,7 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl b/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
index 374e4cb788d8..438a3b170402 100644
--- a/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/xtensa/entry/syscalls/syscall.tbl
@@ -440,3 +440,4 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index c98104481c8a..539e779e3268 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -276,12 +276,14 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
{
char filename[PATH_MAX];
struct build_id bid = { .size = 0, };
+ int err;
if (!dso__build_id_filename(dso, filename, sizeof(filename), false))
return true;
- if (filename__read_build_id(filename, &bid) == -1) {
- if (errno == ENOENT)
+ err = filename__read_build_id(filename, &bid);
+ if (err < 0) {
+ if (err == -ENOENT)
return false;
pr_warning("Problems with %s file, consider removing it from the cache\n",
diff --git a/tools/perf/tests/shell/kvm.sh b/tools/perf/tests/shell/kvm.sh
index 2fafde1a29cc..2a399b83fe80 100755
--- a/tools/perf/tests/shell/kvm.sh
+++ b/tools/perf/tests/shell/kvm.sh
@@ -118,7 +118,7 @@ setup_qemu() {
skip "/dev/kvm not accessible"
fi
- if ! perf kvm stat record -a sleep 0.01 >/dev/null 2>&1; then
+ if ! perf kvm stat record -o /dev/null -a sleep 0.01 >/dev/null 2>&1; then
skip "No permission to record kvm events"
fi
diff --git a/tools/perf/tests/shell/top.sh b/tools/perf/tests/shell/top.sh
index 768ebcf7a89c..ad7fccd09025 100755
--- a/tools/perf/tests/shell/top.sh
+++ b/tools/perf/tests/shell/top.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# perf top tests
+# perf top tests (exclusive)
# SPDX-License-Identifier: GPL-2.0
set -e
diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h
index 77d7c59f5d8b..ec715ad4bf25 100644
--- a/tools/perf/trace/beauty/include/linux/socket.h
+++ b/tools/perf/trace/beauty/include/linux/socket.h
@@ -32,11 +32,29 @@ typedef __kernel_sa_family_t sa_family_t;
* 1003.1g requires sa_family_t and that sa_data is char.
*/
+/* Deprecated for in-kernel use. Use struct sockaddr_unsized instead. */
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
+/**
+ * struct sockaddr_unsized - Unspecified size sockaddr for callbacks
+ * @sa_family: Address family (AF_UNIX, AF_INET, AF_INET6, etc.)
+ * @sa_data: Flexible array for address data
+ *
+ * This structure is designed for callback interfaces where the
+ * total size is known via the sockaddr_len parameter. Unlike struct
+ * sockaddr which has a fixed 14-byte sa_data limit or struct
+ * sockaddr_storage which has a fixed 128-byte sa_data limit, this
+ * structure can accommodate addresses of any size, but must be used
+ * carefully.
+ */
+struct sockaddr_unsized {
+ __kernel_sa_family_t sa_family; /* address family, AF_xxx */
+ char sa_data[]; /* flexible address data */
+};
+
struct linger {
int l_onoff; /* Linger active */
int l_linger; /* How long to linger for */
@@ -450,10 +468,10 @@ extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,
int addrlen);
extern int __sys_listen(int fd, int backlog);
extern int __sys_listen_socket(struct socket *sock, int backlog);
+extern int do_getsockname(struct socket *sock, int peer,
+ struct sockaddr __user *usockaddr, int __user *usockaddr_len);
extern int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
- int __user *usockaddr_len);
-extern int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
- int __user *usockaddr_len);
+ int __user *usockaddr_len, int peer);
extern int __sys_socketpair(int family, int type, int protocol,
int __user *usockvec);
extern int __sys_shutdown_sock(struct socket *sock, int how);
diff --git a/tools/perf/trace/beauty/include/uapi/linux/fcntl.h b/tools/perf/trace/beauty/include/uapi/linux/fcntl.h
index 3741ea1b73d8..aadfbf6e0cb3 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/fcntl.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/fcntl.h
@@ -4,6 +4,7 @@
#include <asm/fcntl.h>
#include <linux/openat2.h>
+#include <linux/types.h>
#define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
#define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
@@ -79,6 +80,17 @@
*/
#define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET
+/* Set/Get delegations */
+#define F_GETDELEG (F_LINUX_SPECIFIC_BASE + 15)
+#define F_SETDELEG (F_LINUX_SPECIFIC_BASE + 16)
+
+/* Argument structure for F_GETDELEG and F_SETDELEG */
+struct delegation {
+ __u32 d_flags; /* Must be 0 */
+ __u16 d_type; /* F_RDLCK, F_WRLCK, F_UNLCK */
+ __u16 __pad; /* Must be 0 */
+};
+
/*
* Types of directory notifications that may be requested.
*/
diff --git a/tools/perf/trace/beauty/include/uapi/linux/fs.h b/tools/perf/trace/beauty/include/uapi/linux/fs.h
index beb4c2d1e41c..66ca526cf786 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/fs.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/fs.h
@@ -298,8 +298,9 @@ struct file_attr {
#define BLKROTATIONAL _IO(0x12,126)
#define BLKZEROOUT _IO(0x12,127)
#define BLKGETDISKSEQ _IOR(0x12,128,__u64)
-/* 130-136 are used by zoned block device ioctls (uapi/linux/blkzoned.h) */
+/* 130-136 and 142 are used by zoned block device ioctls (uapi/linux/blkzoned.h) */
/* 137-141 are used by blk-crypto ioctls (uapi/linux/blk-crypto.h) */
+#define BLKTRACESETUP2 _IOWR(0x12, 142, struct blk_user_trace_setup2)
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
diff --git a/tools/perf/trace/beauty/include/uapi/linux/mount.h b/tools/perf/trace/beauty/include/uapi/linux/mount.h
index 7fa67c2031a5..5d3f8c9e3a62 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/mount.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/mount.h
@@ -197,7 +197,7 @@ struct statmount {
*/
struct mnt_id_req {
__u32 size;
- __u32 spare;
+ __u32 mnt_ns_fd;
__u64 mnt_id;
__u64 param;
__u64 mnt_ns_id;
diff --git a/tools/perf/trace/beauty/include/uapi/sound/asound.h b/tools/perf/trace/beauty/include/uapi/sound/asound.h
index 5a049eeaecce..d3ce75ba938a 100644
--- a/tools/perf/trace/beauty/include/uapi/sound/asound.h
+++ b/tools/perf/trace/beauty/include/uapi/sound/asound.h
@@ -60,7 +60,7 @@ struct snd_cea_861_aud_if {
unsigned char db2_sf_ss; /* sample frequency and size */
unsigned char db3; /* not used, all zeros */
unsigned char db4_ca; /* channel allocation code */
- unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+ unsigned char db5_dminh_lsv; /* downmix inhibit & level-shift values */
};
/****************************************************************************
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index dc19e72258f3..70dd9bee47c7 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -587,6 +587,7 @@ static const struct midr_range common_ds_encoding_cpus[] = {
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
+ MIDR_ALL_VERSIONS(MIDR_NVIDIA_OLYMPUS),
{},
};
diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c
index cc0c474cbfaa..79f4528234a9 100644
--- a/tools/perf/util/libbfd.c
+++ b/tools/perf/util/libbfd.c
@@ -426,8 +426,10 @@ int libbfd__read_build_id(const char *filename, struct build_id *bid)
if (!filename)
return -EFAULT;
+
+ errno = 0;
if (!is_regular_file(filename))
- return -EWOULDBLOCK;
+ return errno == 0 ? -EWOULDBLOCK : -errno;
fd = open(filename, O_RDONLY);
if (fd < 0)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 957143fbf8a0..d1dcafa4b3b8 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -902,8 +902,10 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
if (!filename)
return -EFAULT;
+
+ errno = 0;
if (!is_regular_file(filename))
- return -EWOULDBLOCK;
+ return errno == 0 ? -EWOULDBLOCK : -errno;
err = kmod_path__parse(&m, filename);
if (err)
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index c6b17c14a2e9..8221dc9868f7 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -104,8 +104,10 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
if (!filename)
return -EFAULT;
+
+ errno = 0;
if (!is_regular_file(filename))
- return -EWOULDBLOCK;
+ return errno == 0 ? -EWOULDBLOCK : -errno;
fd = open(filename, O_RDONLY);
if (fd < 0)
diff --git a/tools/sched_ext/scx_show_state.py b/tools/sched_ext/scx_show_state.py
index 7cdcc6729ea4..02e43c184d43 100644
--- a/tools/sched_ext/scx_show_state.py
+++ b/tools/sched_ext/scx_show_state.py
@@ -27,16 +27,18 @@ def read_static_key(name):
def state_str(state):
return prog['scx_enable_state_str'][state].string_().decode()
-ops = prog['scx_ops']
+root = prog['scx_root']
enable_state = read_atomic("scx_enable_state_var")
-print(f'ops : {ops.name.string_().decode()}')
+if root:
+ print(f'ops : {root.ops.name.string_().decode()}')
+else:
+ print('ops : ')
print(f'enabled : {read_static_key("__scx_enabled")}')
print(f'switching_all : {read_int("scx_switching_all")}')
print(f'switched_all : {read_static_key("__scx_switched_all")}')
print(f'enable_state : {state_str(enable_state)} ({enable_state})')
-print(f'in_softlockup : {prog["scx_in_softlockup"].value_()}')
-print(f'breather_depth: {read_atomic("scx_breather_depth")}')
+print(f'aborting : {prog["scx_aborting"].value_()}')
print(f'bypass_depth : {prog["scx_bypass_depth"].value_()}')
print(f'nr_rejected : {read_atomic("scx_nr_rejected")}')
print(f'enable_seq : {read_atomic("scx_enable_seq")}')
diff --git a/tools/scripts/syscall.tbl b/tools/scripts/syscall.tbl
index d1ae5e92c615..e74868be513c 100644
--- a/tools/scripts/syscall.tbl
+++ b/tools/scripts/syscall.tbl
@@ -410,3 +410,4 @@
467 common open_tree_attr sys_open_tree_attr
468 common file_getattr sys_file_getattr
469 common file_setattr sys_file_setattr
+470 common listns sys_listns
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c
index 2f830ff8396c..945144e98507 100644
--- a/tools/testing/radix-tree/idr-test.c
+++ b/tools/testing/radix-tree/idr-test.c
@@ -57,6 +57,26 @@ void idr_alloc_test(void)
idr_destroy(&idr);
}
+void idr_alloc2_test(void)
+{
+ int id;
+ struct idr idr = IDR_INIT_BASE(idr, 1);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 0, 1, GFP_KERNEL);
+ assert(id == -ENOSPC);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 1, 2, GFP_KERNEL);
+ assert(id == 1);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 0, 1, GFP_KERNEL);
+ assert(id == -ENOSPC);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 0, 2, GFP_KERNEL);
+ assert(id == -ENOSPC);
+
+ idr_destroy(&idr);
+}
+
void idr_replace_test(void)
{
DEFINE_IDR(idr);
@@ -409,6 +429,7 @@ void idr_checks(void)
idr_replace_test();
idr_alloc_test();
+ idr_alloc2_test();
idr_null_test();
idr_nowait_test();
idr_get_next_test(0);
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index b7030a6e2e76..4aa60e83ff19 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -437,6 +437,8 @@ BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
-I$(abspath $(OUTPUT)/../usr/include) \
-std=gnu11 \
-fno-strict-aliasing \
+ -Wno-microsoft-anon-tag \
+ -fms-extensions \
-Wno-compare-distinct-pointer-types \
-Wno-initializer-overrides \
#
diff --git a/tools/testing/selftests/bpf/prog_tests/d_path.c b/tools/testing/selftests/bpf/prog_tests/d_path.c
index ccc768592e66..1a2a2f1abf03 100644
--- a/tools/testing/selftests/bpf/prog_tests/d_path.c
+++ b/tools/testing/selftests/bpf/prog_tests/d_path.c
@@ -38,6 +38,14 @@ static int set_pathname(int fd, pid_t pid)
return readlink(buf, src.paths[src.cnt++], MAX_PATH_LEN);
}
+static inline long syscall_close(int fd)
+{
+ return syscall(__NR_close_range,
+ (unsigned int)fd,
+ (unsigned int)fd,
+ 0u);
+}
+
static int trigger_fstat_events(pid_t pid)
{
int sockfd = -1, procfd = -1, devfd = -1;
@@ -104,18 +112,34 @@ out_close:
/* sys_close no longer triggers filp_close, but we can
* call sys_close_range instead which still does
*/
-#define close(fd) syscall(__NR_close_range, fd, fd, 0)
+ syscall_close(pipefd[0]);
+ syscall_close(pipefd[1]);
+ syscall_close(sockfd);
+ syscall_close(procfd);
+ syscall_close(devfd);
+ syscall_close(localfd);
+ syscall_close(indicatorfd);
+ return ret;
+}
- close(pipefd[0]);
- close(pipefd[1]);
- close(sockfd);
- close(procfd);
- close(devfd);
- close(localfd);
- close(indicatorfd);
+static void attach_and_load(struct test_d_path **skel)
+{
+ int err;
-#undef close
- return ret;
+ *skel = test_d_path__open_and_load();
+ if (CHECK(!*skel, "setup", "d_path skeleton failed\n"))
+ goto cleanup;
+
+ err = test_d_path__attach(*skel);
+ if (CHECK(err, "setup", "attach failed: %d\n", err))
+ goto cleanup;
+
+ (*skel)->bss->my_pid = getpid();
+ return;
+
+cleanup:
+ test_d_path__destroy(*skel);
+ *skel = NULL;
}
static void test_d_path_basic(void)
@@ -124,16 +148,11 @@ static void test_d_path_basic(void)
struct test_d_path *skel;
int err;
- skel = test_d_path__open_and_load();
- if (CHECK(!skel, "setup", "d_path skeleton failed\n"))
- goto cleanup;
-
- err = test_d_path__attach(skel);
- if (CHECK(err, "setup", "attach failed: %d\n", err))
+ attach_and_load(&skel);
+ if (!skel)
goto cleanup;
bss = skel->bss;
- bss->my_pid = getpid();
err = trigger_fstat_events(bss->my_pid);
if (err < 0)
@@ -195,6 +214,39 @@ static void test_d_path_check_types(void)
test_d_path_check_types__destroy(skel);
}
+/* Check if the verifier correctly generates code for
+ * accessing the memory modified by d_path helper.
+ */
+static void test_d_path_mem_access(void)
+{
+ int localfd = -1;
+ char path_template[] = "/dev/shm/d_path_loadgen.XXXXXX";
+ struct test_d_path__bss *bss;
+ struct test_d_path *skel;
+
+ attach_and_load(&skel);
+ if (!skel)
+ goto cleanup;
+
+ bss = skel->bss;
+
+ localfd = mkstemp(path_template);
+ if (CHECK(localfd < 0, "trigger", "mkstemp failed\n"))
+ goto cleanup;
+
+ if (CHECK(fallocate(localfd, 0, 0, 1024) < 0, "trigger", "fallocate failed\n"))
+ goto cleanup;
+ remove(path_template);
+
+ if (CHECK(!bss->path_match_fallocate, "check",
+ "failed to read fallocate path"))
+ goto cleanup;
+
+cleanup:
+ syscall_close(localfd);
+ test_d_path__destroy(skel);
+}
+
void test_d_path(void)
{
if (test__start_subtest("basic"))
@@ -205,4 +257,7 @@ void test_d_path(void)
if (test__start_subtest("check_alloc_mem"))
test_d_path_check_types();
+
+ if (test__start_subtest("check_mem_access"))
+ test_d_path_mem_access();
}
diff --git a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
index 6c2b0c3dbcd8..e442be9dde7e 100644
--- a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
@@ -73,12 +73,10 @@ close_memfd:
return -1;
}
-static int create_sys_heap_dmabuf(void)
+static int create_sys_heap_dmabuf(size_t bytes)
{
- sysheap_test_buffer_size = 20 * getpagesize();
-
struct dma_heap_allocation_data data = {
- .len = sysheap_test_buffer_size,
+ .len = bytes,
.fd = 0,
.fd_flags = O_RDWR | O_CLOEXEC,
.heap_flags = 0,
@@ -110,7 +108,9 @@ close_sysheap_dmabuf:
static int create_test_buffers(void)
{
udmabuf = create_udmabuf();
- sysheap_dmabuf = create_sys_heap_dmabuf();
+
+ sysheap_test_buffer_size = 20 * getpagesize();
+ sysheap_dmabuf = create_sys_heap_dmabuf(sysheap_test_buffer_size);
if (udmabuf < 0 || sysheap_dmabuf < 0)
return -1;
@@ -219,6 +219,26 @@ close_iter_fd:
close(iter_fd);
}
+static void subtest_dmabuf_iter_check_lots_of_buffers(struct dmabuf_iter *skel)
+{
+ int iter_fd;
+ char buf[1024];
+ size_t total_bytes_read = 0;
+ ssize_t bytes_read;
+
+ iter_fd = bpf_iter_create(bpf_link__fd(skel->links.dmabuf_collector));
+ if (!ASSERT_OK_FD(iter_fd, "iter_create"))
+ return;
+
+ while ((bytes_read = read(iter_fd, buf, sizeof(buf))) > 0)
+ total_bytes_read += bytes_read;
+
+ ASSERT_GT(total_bytes_read, getpagesize(), "total_bytes_read");
+
+ close(iter_fd);
+}
+
+
static void subtest_dmabuf_iter_check_open_coded(struct dmabuf_iter *skel, int map_fd)
{
LIBBPF_OPTS(bpf_test_run_opts, topts);
@@ -275,6 +295,23 @@ void test_dmabuf_iter(void)
subtest_dmabuf_iter_check_no_infinite_reads(skel);
if (test__start_subtest("default_iter"))
subtest_dmabuf_iter_check_default_iter(skel);
+ if (test__start_subtest("lots_of_buffers")) {
+ size_t NUM_BUFS = 100;
+ int buffers[NUM_BUFS];
+ int i;
+
+ for (i = 0; i < NUM_BUFS; ++i) {
+ buffers[i] = create_sys_heap_dmabuf(getpagesize());
+ if (!ASSERT_OK_FD(buffers[i], "dmabuf_fd"))
+ goto cleanup_bufs;
+ }
+
+ subtest_dmabuf_iter_check_lots_of_buffers(skel);
+
+cleanup_bufs:
+ for (--i; i >= 0; --i)
+ close(buffers[i]);
+ }
if (test__start_subtest("open_coded"))
subtest_dmabuf_iter_check_open_coded(skel, map_fd);
diff --git a/tools/testing/selftests/bpf/progs/test_d_path.c b/tools/testing/selftests/bpf/progs/test_d_path.c
index 84e1f883f97b..561b2f861808 100644
--- a/tools/testing/selftests/bpf/progs/test_d_path.c
+++ b/tools/testing/selftests/bpf/progs/test_d_path.c
@@ -17,6 +17,7 @@ int rets_close[MAX_FILES] = {};
int called_stat = 0;
int called_close = 0;
+int path_match_fallocate = 0;
SEC("fentry/security_inode_getattr")
int BPF_PROG(prog_stat, struct path *path, struct kstat *stat,
@@ -62,4 +63,26 @@ int BPF_PROG(prog_close, struct file *file, void *id)
return 0;
}
+SEC("fentry/vfs_fallocate")
+int BPF_PROG(prog_fallocate, struct file *file, int mode, loff_t offset, loff_t len)
+{
+ pid_t pid = bpf_get_current_pid_tgid() >> 32;
+ int ret = 0;
+ char path_fallocate[MAX_PATH_LEN] = {};
+
+ if (pid != my_pid)
+ return 0;
+
+ ret = bpf_d_path(&file->f_path,
+ path_fallocate, MAX_PATH_LEN);
+ if (ret < 0)
+ return 0;
+
+ if (!path_fallocate[0])
+ return 0;
+
+ path_match_fallocate = 1;
+ return 0;
+}
+
char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index 06559ef49b9a..52523bdad240 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -573,8 +573,9 @@ def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
"""Build test cases for each combo of PSP version and IP version"""
def test_case(cfg):
cfg.require_ipver(ipver)
- test_case.__name__ = f"{name}_v{psp_ver}_ip{ipver}"
test_func(cfg, psp_ver, ipver)
+
+ test_case.__name__ = f"{name}_v{psp_ver}_ip{ipver}"
return test_case
@@ -582,8 +583,9 @@ def ipver_test_builder(name, test_func, ipver):
"""Build test cases for each IP version"""
def test_case(cfg):
cfg.require_ipver(ipver)
- test_case.__name__ = f"{name}_ip{ipver}"
test_func(cfg, ipver)
+
+ test_case.__name__ = f"{name}_ip{ipver}"
return test_case
diff --git a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
index 93c10ea42a68..8b8e1aea985b 100644
--- a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
@@ -1,7 +1,8 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: event tracing - enable/disable with top level files
-# requires: available_events set_event events/enable
+# requires: set_event events/enable
+# flags: instance
do_reset() {
echo > set_event
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
index aee22289536b..1b57771dbfdf 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
@@ -90,9 +90,10 @@ if [ $on != "0" ]; then
fail "Tracing is not off"
fi
-csum1=`md5sum trace`
+# Cannot rely on names being around as they are only cached, strip them
+csum1=`cat trace | sed -e 's/^ *[^ ]*\(-[0-9][0-9]*\)/\1/' | md5sum`
sleep $SLEEP_TIME
-csum2=`md5sum trace`
+csum2=`cat trace | sed -e 's/^ *[^ ]*\(-[0-9][0-9]*\)/\1/' | md5sum`
if [ "$csum1" != "$csum2" ]; then
fail "Tracing file is still changing"
diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index 10e051b6f592..dadad277f4eb 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -755,9 +755,6 @@ TEST_F(iommufd_ioas, get_hw_info)
struct iommu_test_hw_info info;
uint64_t trailing_bytes;
} buffer_larger;
- struct iommu_test_hw_info_buffer_smaller {
- __u32 flags;
- } buffer_smaller;
if (self->device_id) {
uint8_t max_pasid = 0;
@@ -789,8 +786,9 @@ TEST_F(iommufd_ioas, get_hw_info)
* the fields within the size range still gets updated.
*/
test_cmd_get_hw_info(self->device_id,
- IOMMU_HW_INFO_TYPE_DEFAULT,
- &buffer_smaller, sizeof(buffer_smaller));
+ IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact,
+ offsetofend(struct iommu_test_hw_info,
+ flags));
test_cmd_get_hw_info_pasid(self->device_id, &max_pasid);
ASSERT_EQ(0, max_pasid);
if (variant->pasid_capable) {
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index baae6b7ded41..16a119a4656c 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -70,6 +70,12 @@
#include "kselftest.h"
+static inline void __kselftest_memset_safe(void *s, int c, size_t n)
+{
+ if (n > 0)
+ memset(s, c, n);
+}
+
#define TEST_TIMEOUT_DEFAULT 30
/* Utilities exposed to the test definitions */
@@ -416,7 +422,7 @@
self = mmap(NULL, sizeof(*self), PROT_READ | PROT_WRITE, \
MAP_SHARED | MAP_ANONYMOUS, -1, 0); \
} else { \
- memset(&self_private, 0, sizeof(self_private)); \
+ __kselftest_memset_safe(&self_private, 0, sizeof(self_private)); \
self = &self_private; \
} \
} \
diff --git a/tools/testing/selftests/kvm/rseq_test.c b/tools/testing/selftests/kvm/rseq_test.c
index 1375fca80bcd..f80ad6b47d16 100644
--- a/tools/testing/selftests/kvm/rseq_test.c
+++ b/tools/testing/selftests/kvm/rseq_test.c
@@ -215,6 +215,7 @@ int main(int argc, char *argv[])
switch (opt) {
case 'u':
skip_sanity_check = true;
+ break;
case 'l':
latency = atoi_paranoid(optarg);
break;
diff --git a/tools/testing/selftests/kvm/x86/cpuid_test.c b/tools/testing/selftests/kvm/x86/cpuid_test.c
index 7b3fda6842bc..f9ed14996977 100644
--- a/tools/testing/selftests/kvm/x86/cpuid_test.c
+++ b/tools/testing/selftests/kvm/x86/cpuid_test.c
@@ -155,6 +155,7 @@ struct kvm_cpuid2 *vcpu_alloc_cpuid(struct kvm_vm *vm, vm_vaddr_t *p_gva, struct
static void set_cpuid_after_run(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *ent;
+ struct kvm_sregs sregs;
int rc;
u32 eax, ebx, x;
@@ -162,6 +163,20 @@ static void set_cpuid_after_run(struct kvm_vcpu *vcpu)
rc = __vcpu_set_cpuid(vcpu);
TEST_ASSERT(!rc, "Setting unmodified CPUID after KVM_RUN failed: %d", rc);
+ /*
+ * Toggle CR4 bits that affect dynamic CPUID feature flags to verify
+ * setting unmodified CPUID succeeds with runtime CPUID updates.
+ */
+ vcpu_sregs_get(vcpu, &sregs);
+ if (kvm_cpu_has(X86_FEATURE_XSAVE))
+ sregs.cr4 ^= X86_CR4_OSXSAVE;
+ if (kvm_cpu_has(X86_FEATURE_PKU))
+ sregs.cr4 ^= X86_CR4_PKE;
+ vcpu_sregs_set(vcpu, &sregs);
+
+ rc = __vcpu_set_cpuid(vcpu);
+ TEST_ASSERT(!rc, "Setting unmodified CPUID after KVM_RUN failed: %d", rc);
+
/* Changing CPU features is forbidden */
ent = vcpu_get_cpuid_entry(vcpu, 0x7);
ebx = ent->ebx;
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
index cff124c1eddd..67cd53715d93 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/tools/testing/selftests/lkdtm/tests.txt
@@ -1,6 +1,8 @@
#PANIC
#PANIC_STOP_IRQOFF Crashes entire system
+#PANIC_IN_HARDIRQ Crashes entire system
BUG kernel BUG at
+#BUG_IN_HARDIRQ Crashes entire system
WARNING WARNING:
WARNING_MESSAGE message trigger
EXCEPTION
diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c
index f4807242c5b2..6f5e404a446c 100644
--- a/tools/testing/selftests/mm/uffd-unit-tests.c
+++ b/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -1317,7 +1317,7 @@ static thread_state thread_state_get(pid_t tid)
p = strstr(tmp, header);
if (p) {
/* For example, "State:\tD (disk sleep)" */
- c = *(p + sizeof(header) - 1);
+ c = *(p + strlen(header));
return c == 'D' ?
THR_STATE_UNINTERRUPTIBLE : THR_STATE_UNKNOWN;
}
diff --git a/tools/testing/selftests/net/af_unix/Makefile b/tools/testing/selftests/net/af_unix/Makefile
index 3cd677b72072..4c0375e28bbe 100644
--- a/tools/testing/selftests/net/af_unix/Makefile
+++ b/tools/testing/selftests/net/af_unix/Makefile
@@ -1,4 +1,9 @@
-CFLAGS += $(KHDR_INCLUDES) -Wall -Wflex-array-member-not-at-end
+top_srcdir := ../../../../..
+include $(top_srcdir)/scripts/Makefile.compiler
+
+cc-option = $(call __cc-option, $(CC),,$(1),$(2))
+
+CFLAGS += $(KHDR_INCLUDES) -Wall $(call cc-option,-Wflex-array-member-not-at-end)
TEST_GEN_PROGS := \
diag_uid \
diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
index 2b0a90581e2f..21026b667667 100755
--- a/tools/testing/selftests/net/fib_nexthops.sh
+++ b/tools/testing/selftests/net/fib_nexthops.sh
@@ -800,6 +800,14 @@ ipv6_fcnal()
set +e
check_nexthop "dev veth1" ""
log_test $? 0 "Nexthops removed on admin down"
+
+ # error routes should be deleted when their nexthop is deleted
+ run_cmd "$IP li set dev veth1 up"
+ run_cmd "$IP -6 nexthop add id 58 dev veth1"
+ run_cmd "$IP ro add blackhole 2001:db8:101::1/128 nhid 58"
+ run_cmd "$IP nexthop del id 58"
+ check_route6 "2001:db8:101::1" ""
+ log_test $? 0 "Error route removed on nexthop deletion"
}
ipv6_grp_refs()
@@ -1459,6 +1467,13 @@ ipv4_fcnal()
run_cmd "$IP ro del 172.16.102.0/24"
log_test $? 0 "Delete route when not specifying nexthop attributes"
+
+ # error routes should be deleted when their nexthop is deleted
+ run_cmd "$IP nexthop add id 23 dev veth1"
+ run_cmd "$IP ro add blackhole 172.16.102.100/32 nhid 23"
+ run_cmd "$IP nexthop del id 23"
+ check_route "172.16.102.100" ""
+ log_test $? 0 "Error route removed on nexthop deletion"
}
ipv4_grp_fcnal()
diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
index a88f797c549a..c5694cc4ddd2 100755
--- a/tools/testing/selftests/net/fib_tests.sh
+++ b/tools/testing/selftests/net/fib_tests.sh
@@ -12,7 +12,7 @@ TESTS="unregister down carrier nexthop suppress ipv6_notify ipv4_notify \
ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \
ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test \
ipv4_mpath_list ipv6_mpath_list ipv4_mpath_balance ipv6_mpath_balance \
- fib6_ra_to_static"
+ ipv4_mpath_balance_preferred fib6_ra_to_static"
VERBOSE=0
PAUSE_ON_FAIL=no
@@ -2751,6 +2751,73 @@ ipv4_mpath_balance_test()
forwarding_cleanup
}
+get_route_dev_src()
+{
+ local pfx="$1"
+ local src="$2"
+ local out
+
+ if out=$($IP -j route get "$pfx" from "$src" | jq -re ".[0].dev"); then
+ echo "$out"
+ fi
+}
+
+ipv4_mpath_preferred()
+{
+ local src_ip=$1
+ local pref_dev=$2
+ local dev routes
+ local route0=0
+ local route1=0
+ local pref_route=0
+ num_routes=254
+
+ for i in $(seq 1 $num_routes) ; do
+ dev=$(get_route_dev_src 172.16.105.$i $src_ip)
+ if [ "$dev" = "$pref_dev" ]; then
+ pref_route=$((pref_route+1))
+ elif [ "$dev" = "veth1" ]; then
+ route0=$((route0+1))
+ elif [ "$dev" = "veth3" ]; then
+ route1=$((route1+1))
+ fi
+ done
+
+ routes=$((route0+route1))
+
+ [ "$VERBOSE" = "1" ] && echo "multipath: routes seen: ($route0,$route1,$pref_route)"
+
+ if [ x"$pref_dev" = x"" ]; then
+ [[ $routes -ge $num_routes ]] && [[ $route0 -gt 0 ]] && [[ $route1 -gt 0 ]]
+ else
+ [[ $pref_route -ge $num_routes ]]
+ fi
+
+}
+
+ipv4_mpath_balance_preferred_test()
+{
+ echo
+ echo "IPv4 multipath load balance preferred route"
+
+ forwarding_setup
+
+ $IP route add 172.16.105.0/24 \
+ nexthop via 172.16.101.2 \
+ nexthop via 172.16.103.2
+
+ ipv4_mpath_preferred 172.16.101.1 veth1
+ log_test $? 0 "IPv4 multipath loadbalance from veth1"
+
+ ipv4_mpath_preferred 172.16.103.1 veth3
+ log_test $? 0 "IPv4 multipath loadbalance from veth3"
+
+ ipv4_mpath_preferred 198.51.100.1
+ log_test $? 0 "IPv4 multipath loadbalance from dummy"
+
+ forwarding_cleanup
+}
+
ipv6_mpath_balance_test()
{
echo
@@ -2861,6 +2928,7 @@ do
ipv6_mpath_list) ipv6_mpath_list_test;;
ipv4_mpath_balance) ipv4_mpath_balance_test;;
ipv6_mpath_balance) ipv6_mpath_balance_test;;
+ ipv4_mpath_balance_preferred) ipv4_mpath_balance_preferred_test;;
fib6_ra_to_static) fib6_ra_to_static;;
help) echo "Test names: $TESTS"; exit 0;;
diff --git a/tools/testing/selftests/net/forwarding/config b/tools/testing/selftests/net/forwarding/config
index ce64518aaa11..75a6c3d3c1da 100644
--- a/tools/testing/selftests/net/forwarding/config
+++ b/tools/testing/selftests/net/forwarding/config
@@ -29,6 +29,7 @@ CONFIG_NET_ACT_VLAN=m
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_FLOWER=m
CONFIG_NET_CLS_MATCHALL=m
+CONFIG_NET_CLS_U32=m
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_META=m
CONFIG_NETFILTER=y
diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_mc_ul.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_mc_ul.sh
index 6a570d256e07..2cf4c6d9245b 100755
--- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_mc_ul.sh
+++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_mc_ul.sh
@@ -138,13 +138,18 @@ install_capture()
defer tc qdisc del dev "$dev" clsact
tc filter add dev "$dev" ingress proto ip pref 104 \
- flower skip_hw ip_proto udp dst_port "$VXPORT" \
- action pass
+ u32 match ip protocol 0x11 0xff \
+ match u16 "$VXPORT" 0xffff at 0x16 \
+ match u16 0x0800 0xffff at 0x30 \
+ action pass
defer tc filter del dev "$dev" ingress proto ip pref 104
tc filter add dev "$dev" ingress proto ipv6 pref 106 \
- flower skip_hw ip_proto udp dst_port "$VXPORT" \
- action pass
+ u32 match ip6 protocol 0x11 0xff \
+ match u16 "$VXPORT" 0xffff at 0x2a \
+ match u16 0x86dd 0xffff at 0x44 \
+ match u8 0x11 0xff at 0x4c \
+ action pass
defer tc filter del dev "$dev" ingress proto ipv6 pref 106
}
@@ -248,13 +253,6 @@ vx_create()
}
export -f vx_create
-vx_wait()
-{
- # Wait for all the ARP, IGMP etc. noise to settle down so that the
- # tunnel is clear for measurements.
- sleep 10
-}
-
vx10_create()
{
vx_create vx10 10 id 1000 "$@"
@@ -267,18 +265,6 @@ vx20_create()
}
export -f vx20_create
-vx10_create_wait()
-{
- vx10_create "$@"
- vx_wait
-}
-
-vx20_create_wait()
-{
- vx20_create "$@"
- vx_wait
-}
-
ns_init_common()
{
local ns=$1; shift
@@ -554,7 +540,7 @@ ipv4_nomcroute()
# Install a misleading (S,G) rule to attempt to trick the system into
# pushing the packets elsewhere.
adf_install_broken_sg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$swp2"
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$swp2"
do_test 4 10 0 "IPv4 nomcroute"
}
@@ -562,7 +548,7 @@ ipv6_nomcroute()
{
# Like for IPv4, install a misleading (S,G).
adf_install_broken_sg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$swp2"
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$swp2"
do_test 6 10 0 "IPv6 nomcroute"
}
@@ -581,35 +567,35 @@ ipv6_nomcroute_rx()
ipv4_mcroute()
{
adf_install_sg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
do_test 4 10 10 "IPv4 mcroute"
}
ipv6_mcroute()
{
adf_install_sg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
do_test 6 10 10 "IPv6 mcroute"
}
ipv4_mcroute_rx()
{
adf_install_sg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
ipv4_do_test_rx 0 "IPv4 mcroute ping"
}
ipv6_mcroute_rx()
{
adf_install_sg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
ipv6_do_test_rx 0 "IPv6 mcroute ping"
}
ipv4_mcroute_changelink()
{
adf_install_sg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR"
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR"
ip link set dev vx10 type vxlan mcroute
sleep 1
do_test 4 10 10 "IPv4 mcroute changelink"
@@ -618,7 +604,7 @@ ipv4_mcroute_changelink()
ipv6_mcroute_changelink()
{
adf_install_sg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
ip link set dev vx20 type vxlan mcroute
sleep 1
do_test 6 10 10 "IPv6 mcroute changelink"
@@ -627,47 +613,47 @@ ipv6_mcroute_changelink()
ipv4_mcroute_starg()
{
adf_install_starg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
do_test 4 10 10 "IPv4 mcroute (*,G)"
}
ipv6_mcroute_starg()
{
adf_install_starg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
do_test 6 10 10 "IPv6 mcroute (*,G)"
}
ipv4_mcroute_starg_rx()
{
adf_install_starg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
ipv4_do_test_rx 0 "IPv4 mcroute (*,G) ping"
}
ipv6_mcroute_starg_rx()
{
adf_install_starg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
ipv6_do_test_rx 0 "IPv6 mcroute (*,G) ping"
}
ipv4_mcroute_noroute()
{
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
do_test 4 0 0 "IPv4 mcroute, no route"
}
ipv6_mcroute_noroute()
{
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
do_test 6 0 0 "IPv6 mcroute, no route"
}
ipv4_mcroute_fdb()
{
adf_install_sg
- vx10_create_wait local 192.0.2.100 dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 dev "$IPMR" mcroute
bridge fdb add dev vx10 \
00:00:00:00:00:00 self static dst "$GROUP4" via "$IPMR"
do_test 4 10 10 "IPv4 mcroute FDB"
@@ -676,7 +662,7 @@ ipv4_mcroute_fdb()
ipv6_mcroute_fdb()
{
adf_install_sg
- vx20_create_wait local 2001:db8:4::1 dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 dev "$IPMR" mcroute
bridge -6 fdb add dev vx20 \
00:00:00:00:00:00 self static dst "$GROUP6" via "$IPMR"
do_test 6 10 10 "IPv6 mcroute FDB"
@@ -686,7 +672,7 @@ ipv6_mcroute_fdb()
ipv4_mcroute_fdb_oif0()
{
adf_install_sg
- vx10_create_wait local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.100 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4"
do_test 4 10 10 "IPv4 mcroute oif=0"
@@ -703,7 +689,7 @@ ipv6_mcroute_fdb_oif0()
defer ip -6 route del table local multicast "$GROUP6/128" dev "$IPMR"
adf_install_sg
- vx20_create_wait local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:4::1 group "$GROUP6" dev "$IPMR" mcroute
bridge -6 fdb del dev vx20 00:00:00:00:00:00
bridge -6 fdb add dev vx20 00:00:00:00:00:00 self static dst "$GROUP6"
do_test 6 10 10 "IPv6 mcroute oif=0"
@@ -716,7 +702,7 @@ ipv4_mcroute_fdb_oif0_sep()
adf_install_sg_sep
adf_ip_addr_add lo 192.0.2.120/28
- vx10_create_wait local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4"
do_test 4 10 10 "IPv4 mcroute TX!=RX oif=0"
@@ -727,7 +713,7 @@ ipv4_mcroute_fdb_oif0_sep_rx()
adf_install_sg_sep_rx lo
adf_ip_addr_add lo 192.0.2.120/28
- vx10_create_wait local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add dev vx10 00:00:00:00:00:00 self static dst "$GROUP4"
ipv4_do_test_rx 0 "IPv4 mcroute TX!=RX oif=0 ping"
@@ -738,7 +724,7 @@ ipv4_mcroute_fdb_sep_rx()
adf_install_sg_sep_rx lo
adf_ip_addr_add lo 192.0.2.120/28
- vx10_create_wait local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
+ vx10_create local 192.0.2.120 group "$GROUP4" dev "$IPMR" mcroute
bridge fdb del dev vx10 00:00:00:00:00:00
bridge fdb add \
dev vx10 00:00:00:00:00:00 self static dst "$GROUP4" via lo
@@ -750,7 +736,7 @@ ipv6_mcroute_fdb_sep_rx()
adf_install_sg_sep_rx "X$IPMR"
adf_ip_addr_add "X$IPMR" 2001:db8:5::1/64
- vx20_create_wait local 2001:db8:5::1 group "$GROUP6" dev "$IPMR" mcroute
+ vx20_create local 2001:db8:5::1 group "$GROUP6" dev "$IPMR" mcroute
bridge -6 fdb del dev vx20 00:00:00:00:00:00
bridge -6 fdb add dev vx20 00:00:00:00:00:00 \
self static dst "$GROUP6" via "X$IPMR"
diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh
index f448bafb3f20..0ec131b339bc 100644
--- a/tools/testing/selftests/net/lib.sh
+++ b/tools/testing/selftests/net/lib.sh
@@ -280,7 +280,8 @@ tc_rule_stats_get()
local selector=${1:-.packets}; shift
tc -j -s filter show dev $dev $dir pref $pref \
- | jq ".[1].options.actions[].stats$selector"
+ | jq ".[] | select(.options.actions) |
+ .options.actions[].stats$selector"
}
tc_rule_handle_stats_get()
diff --git a/tools/testing/selftests/net/lib/ksft.h b/tools/testing/selftests/net/lib/ksft.h
index 17dc34a612c6..03912902a6d3 100644
--- a/tools/testing/selftests/net/lib/ksft.h
+++ b/tools/testing/selftests/net/lib/ksft.h
@@ -24,7 +24,8 @@ static inline void ksft_ready(void)
fd = STDOUT_FILENO;
}
- write(fd, msg, sizeof(msg));
+ if (write(fd, msg, sizeof(msg)) < 0)
+ perror("write()");
if (fd != STDOUT_FILENO)
close(fd);
}
@@ -48,7 +49,8 @@ static inline void ksft_wait(void)
fd = STDIN_FILENO;
}
- read(fd, &byte, sizeof(byte));
+ if (read(fd, &byte, sizeof(byte)) < 0)
+ perror("read()");
if (fd != STDIN_FILENO)
close(fd);
}
diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh
index ec6a87588191..123d9d7a0278 100755
--- a/tools/testing/selftests/net/mptcp/pm_netlink.sh
+++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh
@@ -192,6 +192,10 @@ check "show_endpoints" \
flush_endpoint
check "show_endpoints" "" "flush addrs"
+add_endpoint 10.0.1.1 flags unknown
+check "show_endpoints" "$(format_endpoints "1,10.0.1.1")" "ignore unknown flags"
+flush_endpoint
+
set_limits 9 1 2>/dev/null
check "get_limits" "${default_limits}" "rcv addrs above hard limit"
diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
index 65b374232ff5..99eecccbf0c8 100644
--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
@@ -24,6 +24,8 @@
#define IPPROTO_MPTCP 262
#endif
+#define MPTCP_PM_ADDR_FLAG_UNKNOWN _BITUL(7)
+
static void syntax(char *argv[])
{
fprintf(stderr, "%s add|ann|rem|csf|dsf|get|set|del|flush|dump|events|listen|accept [<args>]\n", argv[0]);
@@ -836,6 +838,8 @@ int add_addr(int fd, int pm_family, int argc, char *argv[])
flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
else if (!strcmp(tok, "fullmesh"))
flags |= MPTCP_PM_ADDR_FLAG_FULLMESH;
+ else if (!strcmp(tok, "unknown"))
+ flags |= MPTCP_PM_ADDR_FLAG_UNKNOWN;
else
error(1, errno,
"unknown flag %s", argv[arg]);
@@ -1048,6 +1052,13 @@ static void print_addr(struct rtattr *attrs, int len)
printf(",");
}
+ if (flags & MPTCP_PM_ADDR_FLAG_UNKNOWN) {
+ printf("unknown");
+ flags &= ~MPTCP_PM_ADDR_FLAG_UNKNOWN;
+ if (flags)
+ printf(",");
+ }
+
/* bump unknown flags, if any */
if (flags)
printf("0x%x", flags);
diff --git a/tools/testing/selftests/net/netfilter/conntrack_clash.sh b/tools/testing/selftests/net/netfilter/conntrack_clash.sh
index 7fc6c5dbd551..84b8eb12143a 100755
--- a/tools/testing/selftests/net/netfilter/conntrack_clash.sh
+++ b/tools/testing/selftests/net/netfilter/conntrack_clash.sh
@@ -116,7 +116,7 @@ run_one_clash_test()
# not a failure: clash resolution logic did not trigger.
# With right timing, xmit completed sequentially and
# no parallel insertion occurs.
- return $ksft_skip
+ return $ksft_xfail
}
run_clash_test()
@@ -133,12 +133,12 @@ run_clash_test()
if [ $rv -eq 0 ];then
echo "PASS: clash resolution test for $daddr:$dport on attempt $i"
return 0
- elif [ $rv -eq $ksft_skip ]; then
+ elif [ $rv -eq $ksft_xfail ]; then
softerr=1
fi
done
- [ $softerr -eq 1 ] && echo "SKIP: clash resolution for $daddr:$dport did not trigger"
+ [ $softerr -eq 1 ] && echo "XFAIL: clash resolution for $daddr:$dport did not trigger"
}
ip link add veth0 netns "$nsclient1" type veth peer name veth0 netns "$nsrouter"
@@ -167,8 +167,7 @@ load_simple_ruleset "$nsclient2"
run_clash_test "$nsclient2" "$nsclient2" 127.0.0.1 9001
if [ $clash_resolution_active -eq 0 ];then
- [ "$ret" -eq 0 ] && ret=$ksft_skip
- echo "SKIP: Clash resolution did not trigger"
+ [ "$ret" -eq 0 ] && ret=$ksft_xfail
fi
exit $ret
diff --git a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c
index 507930cee8cb..462d628cc3bd 100644
--- a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c
+++ b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.c
@@ -33,9 +33,14 @@ static void die(const char *e)
exit(111);
}
-static void die_port(uint16_t got, uint16_t want)
+static void die_port(const struct sockaddr_in *sin, uint16_t want)
{
- fprintf(stderr, "Port number changed, wanted %d got %d\n", want, ntohs(got));
+ uint16_t got = ntohs(sin->sin_port);
+ char str[INET_ADDRSTRLEN];
+
+ inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str));
+
+ fprintf(stderr, "Port number changed, wanted %d got %d from %s\n", want, got, str);
exit(1);
}
@@ -100,7 +105,7 @@ int main(int argc, char *argv[])
die("child recvfrom");
if (peer.sin_port != htons(PORT))
- die_port(peer.sin_port, PORT);
+ die_port(&peer, PORT);
} else {
if (sendto(s2, buf, LEN, 0, (struct sockaddr *)&sa1, sizeof(sa1)) != LEN)
continue;
@@ -109,7 +114,7 @@ int main(int argc, char *argv[])
die("parent recvfrom");
if (peer.sin_port != htons((PORT + 1)))
- die_port(peer.sin_port, PORT + 1);
+ die_port(&peer, PORT + 1);
}
}
diff --git a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh
index a24c896347a8..dc7e9d6da062 100755
--- a/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh
+++ b/tools/testing/selftests/net/netfilter/conntrack_reverse_clash.sh
@@ -45,6 +45,8 @@ if ip netns exec "$ns0" ./conntrack_reverse_clash; then
echo "PASS: No SNAT performed for null bindings"
else
echo "ERROR: SNAT performed without any matching snat rule"
+ ip netns exec "$ns0" conntrack -L
+ ip netns exec "$ns0" conntrack -S
exit 1
fi
diff --git a/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt b/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt
index 3442cd29bc93..cdb3910af95b 100644
--- a/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt
+++ b/tools/testing/selftests/net/netfilter/packetdrill/conntrack_syn_challenge_ack.pkt
@@ -26,7 +26,7 @@
+0.01 > R 643160523:643160523(0) win 0
-+0.01 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT`
++0.1 `conntrack -f $NFCT_IP_VERSION -L -p tcp --dport 8080 2>/dev/null | grep UNREPLIED | grep -q SYN_SENT`
// Must go through.
+0.01 > S 0:0(0) win 65535 <mss 1460,sackOK,TS val 1 ecr 0,nop,wscale 8>
diff --git a/tools/testing/selftests/net/tap.c b/tools/testing/selftests/net/tap.c
index 9ec1c9b50e77..a0c9418132c8 100644
--- a/tools/testing/selftests/net/tap.c
+++ b/tools/testing/selftests/net/tap.c
@@ -56,18 +56,12 @@ static void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr)
static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short type,
const char *s)
{
- struct rtattr *rta = rtattr_add(nh, type, strlen(s));
+ unsigned int strsz = strlen(s) + 1;
+ struct rtattr *rta;
- memcpy(RTA_DATA(rta), s, strlen(s));
- return rta;
-}
-
-static struct rtattr *rtattr_add_strsz(struct nlmsghdr *nh, unsigned short type,
- const char *s)
-{
- struct rtattr *rta = rtattr_add(nh, type, strlen(s) + 1);
+ rta = rtattr_add(nh, type, strsz);
- strcpy(RTA_DATA(rta), s);
+ memcpy(RTA_DATA(rta), s, strsz);
return rta;
}
@@ -119,7 +113,7 @@ static int dev_create(const char *dev, const char *link_type,
link_info = rtattr_begin(&req.nh, IFLA_LINKINFO);
- rtattr_add_strsz(&req.nh, IFLA_INFO_KIND, link_type);
+ rtattr_add_str(&req.nh, IFLA_INFO_KIND, link_type);
if (fill_info_data) {
info_data = rtattr_begin(&req.nh, IFLA_INFO_DATA);
diff --git a/tools/testing/selftests/net/tfo.c b/tools/testing/selftests/net/tfo.c
index eb3cac5e583c..8d82140f0f76 100644
--- a/tools/testing/selftests/net/tfo.c
+++ b/tools/testing/selftests/net/tfo.c
@@ -81,7 +81,8 @@ static void run_server(void)
if (getsockopt(connfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &opt, &len) < 0)
error(1, errno, "getsockopt(SO_INCOMING_NAPI_ID)");
- read(connfd, buf, 64);
+ if (read(connfd, buf, 64) < 0)
+ perror("read()");
fprintf(outfile, "%d\n", opt);
fclose(outfile);
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index a3ef4b57eb5f..a4d16a460fbe 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -2786,10 +2786,10 @@ TEST_F(tls_err, epoll_partial_rec)
TEST_F(tls_err, poll_partial_rec_async)
{
struct pollfd pfd = { };
+ char token = '\0';
ssize_t rec_len;
char rec[256];
char buf[128];
- char token;
int p[2];
int ret;
diff --git a/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore b/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore
index f93b4c7c3a8a..ea29228334e8 100644
--- a/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore
+++ b/tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore
@@ -1,5 +1,6 @@
bhrb_filter_map_test
bhrb_no_crash_wo_pmu_test
+check_extended_reg_test
intr_regs_no_crash_wo_pmu_test
mmcr0_cc56run_test
mmcr0_exceptionbits_test
diff --git a/tools/testing/selftests/sched_ext/runner.c b/tools/testing/selftests/sched_ext/runner.c
index aa2d7d32dda9..5748d2c69903 100644
--- a/tools/testing/selftests/sched_ext/runner.c
+++ b/tools/testing/selftests/sched_ext/runner.c
@@ -46,6 +46,14 @@ static void print_test_preamble(const struct scx_test *test, bool quiet)
if (!quiet)
printf("DESCRIPTION: %s\n", test->description);
printf("OUTPUT:\n");
+
+ /*
+ * The tests may fork with the preamble buffered
+ * in the children's stdout. Flush before the test
+ * to avoid printing the message multiple times.
+ */
+ fflush(stdout);
+ fflush(stderr);
}
static const char *status_to_result(enum scx_test_status status)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
index b73bd255ea36..da156feabcbf 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/mirred.json
@@ -1052,5 +1052,51 @@
"$TC qdisc del dev $DEV1 ingress_block 21 clsact",
"$TC actions flush action mirred"
]
+ },
+ {
+ "id": "7eba",
+ "name": "Redirect multiport: dummy egress -> dummy egress (Loop)",
+ "category": [
+ "filter",
+ "mirred"
+ ],
+ "plugins": {
+ "requires": [
+ "nsPlugin"
+ ]
+ },
+ "setup": [
+ "$IP link set dev $DUMMY up || true",
+ "$IP addr add 10.10.10.10/24 dev $DUMMY || true",
+ "$TC qdisc add dev $DUMMY handle 1: root drr",
+ "$TC filter add dev $DUMMY parent 1: protocol ip prio 10 matchall action mirred egress redirect dev $DUMMY index 1"
+ ],
+ "cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.10.1",
+ "expExitCode": "1",
+ "verifyCmd": "$TC -j -s actions get action mirred index 1",
+ "matchJSON": [
+ {
+ "total acts": 0
+ },
+ {
+ "actions": [
+ {
+ "order": 1,
+ "kind": "mirred",
+ "mirred_action": "redirect",
+ "direction": "egress",
+ "index": 1,
+ "stats": {
+ "packets": 1,
+ "overlimits": 1
+ },
+ "not_in_hw": true
+ }
+ ]
+ }
+ ],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY root"
+ ]
}
]
diff --git a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
index 47de27fd4f90..6a39640aa2a8 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
@@ -1033,5 +1033,83 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "6e4f",
+ "name": "Try to delete ets drr class' qdisc while still keeping it in the active list",
+ "category": [
+ "qdisc",
+ "ets",
+ "tbf"
+ ],
+ "plugins": {
+ "requires": [
+ "nsPlugin",
+ "scapyPlugin"
+ ]
+ },
+ "setup": [
+ "$IP link set dev $DUMMY up || true",
+ "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+ "$TC qdisc add dev $DUMMY root handle 1: ets bands 2 strict 1",
+ "$TC qdisc add dev $DUMMY parent 1:2 handle 20: tbf rate 8bit burst 100b latency 1s",
+ "$TC filter add dev $DUMMY parent 1: basic classid 1:2",
+ "ping -c2 -W0.01 -s 56 -I $DUMMY 10.10.11.11 || true",
+ "$TC qdisc change dev $DUMMY root handle 1: ets bands 2 strict 2",
+ "$TC qdisc change dev $DUMMY root handle 1: ets bands 1 strict 1"
+ ],
+ "cmdUnderTest": "ping -c1 -W0.01 -s 56 -I $DUMMY 10.10.11.11",
+ "expExitCode": "1",
+ "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY root",
+ "matchJSON": [
+ {
+ "kind": "ets",
+ "handle": "1:",
+ "bytes": 196,
+ "packets": 2
+ }
+ ],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY root handle 1:"
+ ]
+ },
+ {
+ "id": "0b8f",
+ "name": "Try to add ets class to the active list twice",
+ "category": [
+ "qdisc",
+ "ets",
+ "tbf"
+ ],
+ "plugins": {
+ "requires": [
+ "nsPlugin",
+ "scapyPlugin"
+ ]
+ },
+ "setup": [
+ "$IP link set dev $DUMMY up || true",
+ "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+ "$TC qdisc add dev $DUMMY root handle 1: ets bands 2 strict 1",
+ "$TC qdisc add dev $DUMMY parent 1:2 handle 20: tbf rate 8bit burst 100b latency 1s",
+ "$TC filter add dev $DUMMY parent 1: basic classid 1:2",
+ "ping -c2 -W0.01 -s 56 -I $DUMMY 10.10.11.11 || true",
+ "$TC qdisc change dev $DUMMY root handle 1: ets bands 2 strict 2",
+ "$TC qdisc change dev $DUMMY root handle 1: ets bands 2 strict 1"
+ ],
+ "cmdUnderTest": "ping -c1 -W0.01 -s 56 -I $DUMMY 10.10.11.11",
+ "expExitCode": "1",
+ "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY root",
+ "matchJSON": [
+ {
+ "kind": "ets",
+ "handle": "1:",
+ "bytes": 98,
+ "packets": 1
+ }
+ ],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY root handle 1:"
+ ]
}
]
diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
index 770269efe42a..06ba6fde098d 100644
--- a/tools/testing/selftests/ublk/Makefile
+++ b/tools/testing/selftests/ublk/Makefile
@@ -21,31 +21,40 @@ TEST_PROGS += test_generic_10.sh
TEST_PROGS += test_generic_11.sh
TEST_PROGS += test_generic_12.sh
TEST_PROGS += test_generic_13.sh
+TEST_PROGS += test_generic_14.sh
+TEST_PROGS += test_generic_15.sh
TEST_PROGS += test_null_01.sh
TEST_PROGS += test_null_02.sh
+TEST_PROGS += test_null_03.sh
TEST_PROGS += test_loop_01.sh
TEST_PROGS += test_loop_02.sh
TEST_PROGS += test_loop_03.sh
TEST_PROGS += test_loop_04.sh
TEST_PROGS += test_loop_05.sh
+TEST_PROGS += test_loop_06.sh
+TEST_PROGS += test_loop_07.sh
TEST_PROGS += test_stripe_01.sh
TEST_PROGS += test_stripe_02.sh
TEST_PROGS += test_stripe_03.sh
TEST_PROGS += test_stripe_04.sh
+TEST_PROGS += test_stripe_05.sh
+TEST_PROGS += test_stripe_06.sh
TEST_PROGS += test_stress_01.sh
TEST_PROGS += test_stress_02.sh
TEST_PROGS += test_stress_03.sh
TEST_PROGS += test_stress_04.sh
TEST_PROGS += test_stress_05.sh
+TEST_PROGS += test_stress_06.sh
+TEST_PROGS += test_stress_07.sh
TEST_GEN_PROGS_EXTENDED = kublk
+LOCAL_HDRS += $(wildcard *.h)
include ../lib.mk
-$(TEST_GEN_PROGS_EXTENDED): kublk.c null.c file_backed.c common.c stripe.c \
- fault_inject.c
+$(TEST_GEN_PROGS_EXTENDED): $(wildcard *.c)
check:
shellcheck -x -f gcc *.sh
diff --git a/tools/testing/selftests/ublk/file_backed.c b/tools/testing/selftests/ublk/file_backed.c
index cd9fe69ecce2..269d5f124e06 100644
--- a/tools/testing/selftests/ublk/file_backed.c
+++ b/tools/testing/selftests/ublk/file_backed.c
@@ -34,8 +34,9 @@ static int loop_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
unsigned zc = ublk_queue_use_zc(q);
unsigned auto_zc = ublk_queue_use_auto_zc(q);
enum io_uring_op op = ublk_to_uring_op(iod, zc | auto_zc);
+ struct ublk_io *io = ublk_get_io(q, tag);
struct io_uring_sqe *sqe[3];
- void *addr = (zc | auto_zc) ? NULL : (void *)iod->addr;
+ void *addr = io->buf_addr;
if (!zc || auto_zc) {
ublk_io_alloc_sqes(t, sqe, 1);
@@ -56,7 +57,7 @@ static int loop_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
ublk_io_alloc_sqes(t, sqe, 3);
- io_uring_prep_buf_register(sqe[0], q, tag, q->q_id, ublk_get_io(q, tag)->buf_index);
+ io_uring_prep_buf_register(sqe[0], q, tag, q->q_id, io->buf_index);
sqe[0]->flags |= IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_HARDLINK;
sqe[0]->user_data = build_user_data(tag,
ublk_cmd_op_nr(sqe[0]->cmd_op), 0, q->q_id, 1);
@@ -68,7 +69,7 @@ static int loop_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
sqe[1]->flags |= IOSQE_FIXED_FILE | IOSQE_IO_HARDLINK;
sqe[1]->user_data = build_user_data(tag, ublk_op, 0, q->q_id, 1);
- io_uring_prep_buf_unregister(sqe[2], q, tag, q->q_id, ublk_get_io(q, tag)->buf_index);
+ io_uring_prep_buf_unregister(sqe[2], q, tag, q->q_id, io->buf_index);
sqe[2]->user_data = build_user_data(tag, ublk_cmd_op_nr(sqe[2]->cmd_op), 0, q->q_id, 1);
return 2;
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index f8fa102a627f..185ba553686a 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -596,6 +596,38 @@ static void ublk_set_auto_buf_reg(const struct ublk_queue *q,
sqe->addr = ublk_auto_buf_reg_to_sqe_addr(&buf);
}
+/* Copy in pieces to test the buffer offset logic */
+#define UBLK_USER_COPY_LEN 2048
+
+static void ublk_user_copy(const struct ublk_io *io, __u8 match_ublk_op)
+{
+ const struct ublk_queue *q = ublk_io_to_queue(io);
+ const struct ublksrv_io_desc *iod = ublk_get_iod(q, io->tag);
+ __u64 off = ublk_user_copy_offset(q->q_id, io->tag);
+ __u8 ublk_op = ublksrv_get_op(iod);
+ __u32 len = iod->nr_sectors << 9;
+ void *addr = io->buf_addr;
+
+ if (ublk_op != match_ublk_op)
+ return;
+
+ while (len) {
+ __u32 copy_len = min(len, UBLK_USER_COPY_LEN);
+ ssize_t copied;
+
+ if (ublk_op == UBLK_IO_OP_WRITE)
+ copied = pread(q->ublk_fd, addr, copy_len, off);
+ else if (ublk_op == UBLK_IO_OP_READ)
+ copied = pwrite(q->ublk_fd, addr, copy_len, off);
+ else
+ assert(0);
+ assert(copied == (ssize_t)copy_len);
+ addr += copy_len;
+ off += copy_len;
+ len -= copy_len;
+ }
+}
+
int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
{
struct ublk_queue *q = ublk_io_to_queue(io);
@@ -618,9 +650,12 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
if (io->flags & UBLKS_IO_NEED_GET_DATA)
cmd_op = UBLK_U_IO_NEED_GET_DATA;
- else if (io->flags & UBLKS_IO_NEED_COMMIT_RQ_COMP)
+ else if (io->flags & UBLKS_IO_NEED_COMMIT_RQ_COMP) {
+ if (ublk_queue_use_user_copy(q))
+ ublk_user_copy(io, UBLK_IO_OP_READ);
+
cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
- else if (io->flags & UBLKS_IO_NEED_FETCH_RQ)
+ } else if (io->flags & UBLKS_IO_NEED_FETCH_RQ)
cmd_op = UBLK_U_IO_FETCH_REQ;
if (io_uring_sq_space_left(&t->ring) < 1)
@@ -649,7 +684,7 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
sqe[0]->rw_flags = 0;
cmd->tag = io->tag;
cmd->q_id = q->q_id;
- if (!ublk_queue_no_buf(q))
+ if (!ublk_queue_no_buf(q) && !ublk_queue_use_user_copy(q))
cmd->addr = (__u64) (uintptr_t) io->buf_addr;
else
cmd->addr = 0;
@@ -751,6 +786,10 @@ static void ublk_handle_uring_cmd(struct ublk_thread *t,
if (cqe->res == UBLK_IO_RES_OK) {
assert(tag < q->q_depth);
+
+ if (ublk_queue_use_user_copy(q))
+ ublk_user_copy(io, UBLK_IO_OP_WRITE);
+
if (q->tgt_ops->queue_io)
q->tgt_ops->queue_io(t, q, tag);
} else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
@@ -1507,7 +1546,7 @@ static void __cmd_create_help(char *exe, bool recovery)
printf("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n",
exe, recovery ? "recover" : "add");
- printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1 ] [-g]\n");
+ printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1] [-g] [-u]\n");
printf("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd]\n");
printf("\t[--nthreads threads] [--per_io_tasks]\n");
printf("\t[target options] [backfile1] [backfile2] ...\n");
@@ -1568,6 +1607,7 @@ int main(int argc, char *argv[])
{ "get_data", 1, NULL, 'g'},
{ "auto_zc", 0, NULL, 0 },
{ "auto_zc_fallback", 0, NULL, 0 },
+ { "user_copy", 0, NULL, 'u'},
{ "size", 1, NULL, 's'},
{ "nthreads", 1, NULL, 0 },
{ "per_io_tasks", 0, NULL, 0 },
@@ -1593,7 +1633,7 @@ int main(int argc, char *argv[])
opterr = 0;
optind = 2;
- while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:s:gaz",
+ while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:s:gazu",
longopts, &option_idx)) != -1) {
switch (opt) {
case 'a':
@@ -1613,7 +1653,7 @@ int main(int argc, char *argv[])
ctx.queue_depth = strtol(optarg, NULL, 10);
break;
case 'z':
- ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_USER_COPY;
+ ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY;
break;
case 'r':
value = strtol(optarg, NULL, 10);
@@ -1633,6 +1673,9 @@ int main(int argc, char *argv[])
case 'g':
ctx.flags |= UBLK_F_NEED_GET_DATA;
break;
+ case 'u':
+ ctx.flags |= UBLK_F_USER_COPY;
+ break;
case 's':
ctx.size = strtoull(optarg, NULL, 10);
break;
@@ -1686,6 +1729,15 @@ int main(int argc, char *argv[])
return -EINVAL;
}
+ if (!!(ctx.flags & UBLK_F_NEED_GET_DATA) +
+ !!(ctx.flags & UBLK_F_USER_COPY) +
+ (ctx.flags & UBLK_F_SUPPORT_ZERO_COPY && !ctx.auto_zc_fallback) +
+ (ctx.flags & UBLK_F_AUTO_BUF_REG && !ctx.auto_zc_fallback) +
+ ctx.auto_zc_fallback > 1) {
+ fprintf(stderr, "too many data copy modes specified\n");
+ return -EINVAL;
+ }
+
i = optind;
while (i < argc && ctx.nr_files < MAX_BACK_FILES) {
ctx.files[ctx.nr_files++] = argv[i++];
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index fe42705c6d42..8a83b90ec603 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -208,6 +208,12 @@ static inline int ublk_io_auto_zc_fallback(const struct ublksrv_io_desc *iod)
return !!(iod->op_flags & UBLK_IO_F_NEED_REG_BUF);
}
+static inline __u64 ublk_user_copy_offset(unsigned q_id, unsigned tag)
+{
+ return UBLKSRV_IO_BUF_OFFSET +
+ ((__u64)q_id << UBLK_QID_OFF | (__u64)tag << UBLK_TAG_OFF);
+}
+
static inline int is_target_io(__u64 user_data)
{
return (user_data & (1ULL << 63)) != 0;
@@ -390,19 +396,24 @@ static inline int ublk_completed_tgt_io(struct ublk_thread *t,
return --io->tgt_ios == 0;
}
-static inline int ublk_queue_use_zc(const struct ublk_queue *q)
+static inline bool ublk_queue_use_zc(const struct ublk_queue *q)
+{
+ return !!(q->flags & UBLK_F_SUPPORT_ZERO_COPY);
+}
+
+static inline bool ublk_queue_use_auto_zc(const struct ublk_queue *q)
{
- return q->flags & UBLK_F_SUPPORT_ZERO_COPY;
+ return !!(q->flags & UBLK_F_AUTO_BUF_REG);
}
-static inline int ublk_queue_use_auto_zc(const struct ublk_queue *q)
+static inline bool ublk_queue_auto_zc_fallback(const struct ublk_queue *q)
{
- return q->flags & UBLK_F_AUTO_BUF_REG;
+ return !!(q->flags & UBLKS_Q_AUTO_BUF_REG_FALLBACK);
}
-static inline int ublk_queue_auto_zc_fallback(const struct ublk_queue *q)
+static inline bool ublk_queue_use_user_copy(const struct ublk_queue *q)
{
- return q->flags & UBLKS_Q_AUTO_BUF_REG_FALLBACK;
+ return !!(q->flags & UBLK_F_USER_COPY);
}
static inline int ublk_queue_no_buf(const struct ublk_queue *q)
diff --git a/tools/testing/selftests/ublk/stripe.c b/tools/testing/selftests/ublk/stripe.c
index 791fa8dc1651..fd412e1f01c0 100644
--- a/tools/testing/selftests/ublk/stripe.c
+++ b/tools/testing/selftests/ublk/stripe.c
@@ -134,7 +134,7 @@ static int stripe_queue_tgt_rw_io(struct ublk_thread *t, struct ublk_queue *q,
struct stripe_array *s = alloc_stripe_array(conf, iod);
struct ublk_io *io = ublk_get_io(q, tag);
int i, extra = zc ? 2 : 0;
- void *base = (zc | auto_zc) ? NULL : (void *)iod->addr;
+ void *base = io->buf_addr;
io->private_data = s;
calculate_stripe_array(conf, iod, s, base);
diff --git a/tools/testing/selftests/ublk/test_common.sh b/tools/testing/selftests/ublk/test_common.sh
index 8a4dbd09feb0..ea9a5f3eb70a 100755
--- a/tools/testing/selftests/ublk/test_common.sh
+++ b/tools/testing/selftests/ublk/test_common.sh
@@ -178,8 +178,9 @@ _have_feature()
_create_ublk_dev() {
local dev_id;
local cmd=$1
+ local settle=$2
- shift 1
+ shift 2
if [ ! -c /dev/ublk-control ]; then
return ${UBLK_SKIP_CODE}
@@ -194,7 +195,10 @@ _create_ublk_dev() {
echo "fail to add ublk dev $*"
return 255
fi
- udevadm settle
+
+ if [ "$settle" = "yes" ]; then
+ udevadm settle
+ fi
if [[ "$dev_id" =~ ^[0-9]+$ ]]; then
echo "${dev_id}"
@@ -204,14 +208,18 @@ _create_ublk_dev() {
}
_add_ublk_dev() {
- _create_ublk_dev "add" "$@"
+ _create_ublk_dev "add" "yes" "$@"
+}
+
+_add_ublk_dev_no_settle() {
+ _create_ublk_dev "add" "no" "$@"
}
_recover_ublk_dev() {
local dev_id
local state
- dev_id=$(_create_ublk_dev "recover" "$@")
+ dev_id=$(_create_ublk_dev "recover" "yes" "$@")
for ((j=0;j<20;j++)); do
state=$(_get_ublk_dev_state "${dev_id}")
[ "$state" == "LIVE" ] && break
@@ -333,11 +341,12 @@ run_io_and_kill_daemon()
run_io_and_recover()
{
- local action=$1
+ local size=$1
+ local action=$2
local state
local dev_id
- shift 1
+ shift 2
dev_id=$(_add_ublk_dev "$@")
_check_add_dev "$TID" $?
diff --git a/tools/testing/selftests/ublk/test_generic_04.sh b/tools/testing/selftests/ublk/test_generic_04.sh
index 8b533217d4a1..baf5b156193d 100755
--- a/tools/testing/selftests/ublk/test_generic_04.sh
+++ b/tools/testing/selftests/ublk/test_generic_04.sh
@@ -8,7 +8,7 @@ ERR_CODE=0
ublk_run_recover_test()
{
- run_io_and_recover "kill_daemon" "$@"
+ run_io_and_recover 256M "kill_daemon" "$@"
ERR_CODE=$?
if [ ${ERR_CODE} -ne 0 ]; then
echo "$TID failure: $*"
diff --git a/tools/testing/selftests/ublk/test_generic_05.sh b/tools/testing/selftests/ublk/test_generic_05.sh
index 398e9e2b58e1..7b5083afc02a 100755
--- a/tools/testing/selftests/ublk/test_generic_05.sh
+++ b/tools/testing/selftests/ublk/test_generic_05.sh
@@ -8,7 +8,7 @@ ERR_CODE=0
ublk_run_recover_test()
{
- run_io_and_recover "kill_daemon" "$@"
+ run_io_and_recover 256M "kill_daemon" "$@"
ERR_CODE=$?
if [ ${ERR_CODE} -ne 0 ]; then
echo "$TID failure: $*"
diff --git a/tools/testing/selftests/ublk/test_generic_11.sh b/tools/testing/selftests/ublk/test_generic_11.sh
index a00357a5ec6b..d1f973c8c645 100755
--- a/tools/testing/selftests/ublk/test_generic_11.sh
+++ b/tools/testing/selftests/ublk/test_generic_11.sh
@@ -8,7 +8,7 @@ ERR_CODE=0
ublk_run_quiesce_recover()
{
- run_io_and_recover "quiesce_dev" "$@"
+ run_io_and_recover 256M "quiesce_dev" "$@"
ERR_CODE=$?
if [ ${ERR_CODE} -ne 0 ]; then
echo "$TID failure: $*"
diff --git a/tools/testing/selftests/ublk/test_generic_14.sh b/tools/testing/selftests/ublk/test_generic_14.sh
new file mode 100755
index 000000000000..cd9b44b97c24
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_generic_14.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="generic_14"
+ERR_CODE=0
+
+ublk_run_recover_test()
+{
+ run_io_and_recover 256M "kill_daemon" "$@"
+ ERR_CODE=$?
+ if [ ${ERR_CODE} -ne 0 ]; then
+ echo "$TID failure: $*"
+ _show_result $TID $ERR_CODE
+ fi
+}
+
+if ! _have_program fio; then
+ exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "recover" "basic recover function verification (user copy)"
+
+_create_backfile 0 256M
+_create_backfile 1 128M
+_create_backfile 2 128M
+
+ublk_run_recover_test -t null -q 2 -r 1 -u &
+ublk_run_recover_test -t loop -q 2 -r 1 -u "${UBLK_BACKFILES[0]}" &
+ublk_run_recover_test -t stripe -q 2 -r 1 -u "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
+
+ublk_run_recover_test -t null -q 2 -r 1 -u -i 1 &
+ublk_run_recover_test -t loop -q 2 -r 1 -u -i 1 "${UBLK_BACKFILES[0]}" &
+ublk_run_recover_test -t stripe -q 2 -r 1 -u -i 1 "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
+
+_cleanup_test "recover"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_generic_15.sh b/tools/testing/selftests/ublk/test_generic_15.sh
new file mode 100755
index 000000000000..76379362e0a2
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_generic_15.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="generic_15"
+ERR_CODE=0
+
+_test_partition_scan_no_hang()
+{
+ local recovery_flag=$1
+ local expected_state=$2
+ local dev_id
+ local state
+ local daemon_pid
+ local start_time
+ local elapsed
+
+ # Create ublk device with fault_inject target and very large delay
+ # to simulate hang during partition table read
+ # --delay_us 60000000 = 60 seconds delay
+ # Use _add_ublk_dev_no_settle to avoid udevadm settle hang waiting
+ # for partition scan events to complete
+ if [ "$recovery_flag" = "yes" ]; then
+ echo "Testing partition scan with recovery support..."
+ dev_id=$(_add_ublk_dev_no_settle -t fault_inject -q 1 -d 1 --delay_us 60000000 -r 1)
+ else
+ echo "Testing partition scan without recovery..."
+ dev_id=$(_add_ublk_dev_no_settle -t fault_inject -q 1 -d 1 --delay_us 60000000)
+ fi
+
+ _check_add_dev "$TID" $?
+
+ # The add command should return quickly because partition scan is async.
+ # Now sleep briefly to let the async partition scan work start and hit
+ # the delay in the fault_inject handler.
+ sleep 1
+
+ # Kill the ublk daemon while partition scan is potentially blocked
+ # And check state transitions properly
+ start_time=${SECONDS}
+ daemon_pid=$(_get_ublk_daemon_pid "${dev_id}")
+ state=$(__ublk_kill_daemon "${dev_id}" "${expected_state}")
+ elapsed=$((SECONDS - start_time))
+
+ # Verify the device transitioned to expected state
+ if [ "$state" != "${expected_state}" ]; then
+ echo "FAIL: Device state is $state, expected ${expected_state}"
+ ERR_CODE=255
+ ${UBLK_PROG} del -n "${dev_id}" > /dev/null 2>&1
+ return
+ fi
+ echo "PASS: Device transitioned to ${expected_state} in ${elapsed}s without hanging"
+
+ # Clean up the device
+ ${UBLK_PROG} del -n "${dev_id}" > /dev/null 2>&1
+}
+
+_prep_test "partition_scan" "verify async partition scan prevents IO hang"
+
+# Test 1: Without recovery support - should transition to DEAD
+_test_partition_scan_no_hang "no" "DEAD"
+
+# Test 2: With recovery support - should transition to QUIESCED
+_test_partition_scan_no_hang "yes" "QUIESCED"
+
+_cleanup_test "partition_scan"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_loop_06.sh b/tools/testing/selftests/ublk/test_loop_06.sh
new file mode 100755
index 000000000000..1d1a8a725502
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_loop_06.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="loop_06"
+ERR_CODE=0
+
+if ! _have_program fio; then
+ exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "loop" "write and verify over user copy"
+
+_create_backfile 0 256M
+dev_id=$(_add_ublk_dev -t loop -u "${UBLK_BACKFILES[0]}")
+_check_add_dev $TID $?
+
+# run fio over the ublk disk
+_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M
+ERR_CODE=$?
+
+_cleanup_test "loop"
+
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_loop_07.sh b/tools/testing/selftests/ublk/test_loop_07.sh
new file mode 100755
index 000000000000..493f3fb611a5
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_loop_07.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="loop_07"
+ERR_CODE=0
+
+_prep_test "loop" "mkfs & mount & umount with user copy"
+
+_create_backfile 0 256M
+
+dev_id=$(_add_ublk_dev -t loop -u "${UBLK_BACKFILES[0]}")
+_check_add_dev $TID $?
+
+_mkfs_mount_test /dev/ublkb"${dev_id}"
+ERR_CODE=$?
+
+_cleanup_test "loop"
+
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_null_03.sh b/tools/testing/selftests/ublk/test_null_03.sh
new file mode 100755
index 000000000000..0051067b4686
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_null_03.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="null_03"
+ERR_CODE=0
+
+if ! _have_program fio; then
+ exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "null" "basic IO test with user copy"
+
+dev_id=$(_add_ublk_dev -t null -u)
+_check_add_dev $TID $?
+
+# run fio over the two disks
+fio --name=job1 --filename=/dev/ublkb"${dev_id}" --ioengine=libaio --rw=readwrite --iodepth=32 --size=256M > /dev/null 2>&1
+ERR_CODE=$?
+
+_cleanup_test "null"
+
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stress_04.sh b/tools/testing/selftests/ublk/test_stress_04.sh
index 3f901db4d09d..efa8dc33234b 100755
--- a/tools/testing/selftests/ublk/test_stress_04.sh
+++ b/tools/testing/selftests/ublk/test_stress_04.sh
@@ -31,21 +31,23 @@ _create_backfile 2 128M
ublk_io_and_kill_daemon 8G -t null -q 4 -z --no_ublk_fixed_fd &
ublk_io_and_kill_daemon 256M -t loop -q 4 -z --no_ublk_fixed_fd "${UBLK_BACKFILES[0]}" &
ublk_io_and_kill_daemon 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
if _have_feature "AUTO_BUF_REG"; then
ublk_io_and_kill_daemon 8G -t null -q 4 --auto_zc &
ublk_io_and_kill_daemon 256M -t loop -q 4 --auto_zc "${UBLK_BACKFILES[0]}" &
ublk_io_and_kill_daemon 256M -t stripe -q 4 --auto_zc --no_ublk_fixed_fd "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
ublk_io_and_kill_daemon 8G -t null -q 4 -z --auto_zc --auto_zc_fallback &
+ wait
fi
if _have_feature "PER_IO_DAEMON"; then
- ublk_io_and_kill_daemon 8G -t null -q 4 --nthreads 8 --per_io_tasks &
- ublk_io_and_kill_daemon 256M -t loop -q 4 --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
- ublk_io_and_kill_daemon 256M -t stripe -q 4 --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
- ublk_io_and_kill_daemon 8G -t null -q 4 --nthreads 8 --per_io_tasks &
+ ublk_io_and_kill_daemon 8G -t null -q 4 --auto_zc --nthreads 8 --per_io_tasks &
+ ublk_io_and_kill_daemon 256M -t loop -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
+ ublk_io_and_kill_daemon 256M -t stripe -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+ ublk_io_and_kill_daemon 8G -t null -q 4 -z --auto_zc --auto_zc_fallback --nthreads 8 --per_io_tasks &
+ wait
fi
-wait
_cleanup_test "stress"
_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stress_05.sh b/tools/testing/selftests/ublk/test_stress_05.sh
index 274295061042..68a194144302 100755
--- a/tools/testing/selftests/ublk/test_stress_05.sh
+++ b/tools/testing/selftests/ublk/test_stress_05.sh
@@ -58,17 +58,17 @@ done
if _have_feature "ZERO_COPY"; then
for reissue in $(seq 0 1); do
- ublk_io_and_remove 8G -t null -q 4 -g -z -r 1 -i "$reissue" &
- ublk_io_and_remove 256M -t loop -q 4 -g -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
+ ublk_io_and_remove 8G -t null -q 4 -z -r 1 -i "$reissue" &
+ ublk_io_and_remove 256M -t loop -q 4 -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
wait
done
fi
if _have_feature "AUTO_BUF_REG"; then
for reissue in $(seq 0 1); do
- ublk_io_and_remove 8G -t null -q 4 -g --auto_zc -r 1 -i "$reissue" &
- ublk_io_and_remove 256M -t loop -q 4 -g --auto_zc -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
- ublk_io_and_remove 8G -t null -q 4 -g -z --auto_zc --auto_zc_fallback -r 1 -i "$reissue" &
+ ublk_io_and_remove 8G -t null -q 4 --auto_zc -r 1 -i "$reissue" &
+ ublk_io_and_remove 256M -t loop -q 4 --auto_zc -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
+ ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback -r 1 -i "$reissue" &
wait
done
fi
diff --git a/tools/testing/selftests/ublk/test_stress_06.sh b/tools/testing/selftests/ublk/test_stress_06.sh
new file mode 100755
index 000000000000..37188ec2e1f7
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_stress_06.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+TID="stress_06"
+ERR_CODE=0
+
+ublk_io_and_remove()
+{
+ run_io_and_remove "$@"
+ ERR_CODE=$?
+ if [ ${ERR_CODE} -ne 0 ]; then
+ echo "$TID failure: $*"
+ _show_result $TID $ERR_CODE
+ fi
+}
+
+if ! _have_program fio; then
+ exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "stress" "run IO and remove device (user copy)"
+
+_create_backfile 0 256M
+_create_backfile 1 128M
+_create_backfile 2 128M
+
+ublk_io_and_remove 8G -t null -q 4 -u &
+ublk_io_and_remove 256M -t loop -q 4 -u "${UBLK_BACKFILES[0]}" &
+ublk_io_and_remove 256M -t stripe -q 4 -u "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
+
+ublk_io_and_remove 8G -t null -q 4 -u --nthreads 8 --per_io_tasks &
+ublk_io_and_remove 256M -t loop -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
+ublk_io_and_remove 256M -t stripe -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
+
+_cleanup_test "stress"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stress_07.sh b/tools/testing/selftests/ublk/test_stress_07.sh
new file mode 100755
index 000000000000..fb061fc26d36
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_stress_07.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+TID="stress_07"
+ERR_CODE=0
+
+ublk_io_and_kill_daemon()
+{
+ run_io_and_kill_daemon "$@"
+ ERR_CODE=$?
+ if [ ${ERR_CODE} -ne 0 ]; then
+ echo "$TID failure: $*"
+ _show_result $TID $ERR_CODE
+ fi
+}
+
+if ! _have_program fio; then
+ exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "stress" "run IO and kill ublk server (user copy)"
+
+_create_backfile 0 256M
+_create_backfile 1 128M
+_create_backfile 2 128M
+
+ublk_io_and_kill_daemon 8G -t null -q 4 -u --no_ublk_fixed_fd &
+ublk_io_and_kill_daemon 256M -t loop -q 4 -u --no_ublk_fixed_fd "${UBLK_BACKFILES[0]}" &
+ublk_io_and_kill_daemon 256M -t stripe -q 4 -u "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
+
+ublk_io_and_kill_daemon 8G -t null -q 4 -u --nthreads 8 --per_io_tasks &
+ublk_io_and_kill_daemon 256M -t loop -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" &
+ublk_io_and_kill_daemon 256M -t stripe -q 4 -u --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" &
+wait
+
+_cleanup_test "stress"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stripe_05.sh b/tools/testing/selftests/ublk/test_stripe_05.sh
new file mode 100755
index 000000000000..05d71951d710
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_stripe_05.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="stripe_05"
+ERR_CODE=0
+
+if ! _have_program fio; then
+ exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "stripe" "write and verify test on user copy"
+
+_create_backfile 0 256M
+_create_backfile 1 256M
+
+dev_id=$(_add_ublk_dev -t stripe -q 2 -u "${UBLK_BACKFILES[0]}" "${UBLK_BACKFILES[1]}")
+_check_add_dev $TID $?
+
+# run fio over the ublk disk
+_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=512M
+ERR_CODE=$?
+
+_cleanup_test "stripe"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stripe_06.sh b/tools/testing/selftests/ublk/test_stripe_06.sh
new file mode 100755
index 000000000000..d06cac7626e2
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_stripe_06.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="stripe_06"
+ERR_CODE=0
+
+_prep_test "stripe" "mkfs & mount & umount on user copy"
+
+_create_backfile 0 256M
+_create_backfile 1 256M
+
+dev_id=$(_add_ublk_dev -t stripe -u -q 2 "${UBLK_BACKFILES[0]}" "${UBLK_BACKFILES[1]}")
+_check_add_dev $TID $?
+
+_mkfs_mount_test /dev/ublkb"${dev_id}"
+ERR_CODE=$?
+
+_cleanup_test "stripe"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/trace/seq_io.bt b/tools/testing/selftests/ublk/trace/seq_io.bt
index 272ac54c9d5f..b2f60a92b118 100644
--- a/tools/testing/selftests/ublk/trace/seq_io.bt
+++ b/tools/testing/selftests/ublk/trace/seq_io.bt
@@ -4,7 +4,7 @@
$3: strlen($2)
*/
BEGIN {
- @last_rw[$1, str($2)] = 0;
+ @last_rw[$1, str($2)] = (uint64)0;
}
tracepoint:block:block_rq_complete
{
@@ -17,7 +17,6 @@ tracepoint:block:block_rq_complete
}
@last_rw[$dev, str($2)] = (args.sector + args.nr_sector);
}
- @ios = count();
}
END {
diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/iova_allocator.h b/tools/testing/selftests/vfio/lib/include/libvfio/iova_allocator.h
index 8f1d994e9ea2..c7c0796a757f 100644
--- a/tools/testing/selftests/vfio/lib/include/libvfio/iova_allocator.h
+++ b/tools/testing/selftests/vfio/lib/include/libvfio/iova_allocator.h
@@ -2,7 +2,6 @@
#ifndef SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_IOVA_ALLOCATOR_H
#define SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_IOVA_ALLOCATOR_H
-#include <uapi/linux/types.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/iommufd.h>
diff --git a/tools/testing/selftests/vfio/lib/iommu.c b/tools/testing/selftests/vfio/lib/iommu.c
index 8079d43523f3..58b7fb7430d4 100644
--- a/tools/testing/selftests/vfio/lib/iommu.c
+++ b/tools/testing/selftests/vfio/lib/iommu.c
@@ -11,7 +11,6 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <uapi/linux/types.h>
#include <linux/limits.h>
#include <linux/mman.h>
#include <linux/types.h>
diff --git a/tools/testing/selftests/vfio/lib/iova_allocator.c b/tools/testing/selftests/vfio/lib/iova_allocator.c
index a12b0a51e9e6..8c1cc86b70cd 100644
--- a/tools/testing/selftests/vfio/lib/iova_allocator.c
+++ b/tools/testing/selftests/vfio/lib/iova_allocator.c
@@ -11,7 +11,6 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <uapi/linux/types.h>
#include <linux/iommufd.h>
#include <linux/limits.h>
#include <linux/mman.h>
diff --git a/tools/testing/selftests/vfio/lib/vfio_pci_device.c b/tools/testing/selftests/vfio/lib/vfio_pci_device.c
index 8e34b9bfc96b..fac4c0ecadef 100644
--- a/tools/testing/selftests/vfio/lib/vfio_pci_device.c
+++ b/tools/testing/selftests/vfio/lib/vfio_pci_device.c
@@ -11,7 +11,6 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <uapi/linux/types.h>
#include <linux/iommufd.h>
#include <linux/limits.h>
#include <linux/mman.h>
diff --git a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
index 16eba2ecca47..3bf984b337ac 100644
--- a/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
+++ b/tools/testing/selftests/vfio/vfio_dma_mapping_test.c
@@ -3,7 +3,6 @@
#include <sys/mman.h>
#include <unistd.h>
-#include <uapi/linux/types.h>
#include <linux/iommufd.h>
#include <linux/limits.h>
#include <linux/mman.h>
diff --git a/tools/testing/selftests/vfio/vfio_iommufd_setup_test.c b/tools/testing/selftests/vfio/vfio_iommufd_setup_test.c
index 17017ed3beac..ec1e5633e080 100644
--- a/tools/testing/selftests/vfio/vfio_iommufd_setup_test.c
+++ b/tools/testing/selftests/vfio/vfio_iommufd_setup_test.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include <uapi/linux/types.h>
#include <linux/limits.h>
#include <linux/sizes.h>
#include <linux/vfio.h>
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
index e25e99c1c3b7..2cac5fd4b979 100644
--- a/tools/virtio/Makefile
+++ b/tools/virtio/Makefile
@@ -20,8 +20,9 @@ CFLAGS += -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../
CFLAGS += -pthread
LDFLAGS += -pthread
vpath %.c ../../drivers/virtio ../../drivers/vhost
+BUILD=KCFLAGS="-I "`pwd`/../../drivers/vhost ${MAKE} -C `pwd`/../.. V=${V}
mod:
- ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
+ ${BUILD} M=`pwd`/vhost_test
#oot: build vhost as an out of tree module for a distro kernel
#no effort is taken to make it actually build or work, but tends to mostly work
@@ -37,8 +38,9 @@ OOT_CONFIGS=\
CONFIG_VHOST_NET=n \
CONFIG_VHOST_SCSI=n \
CONFIG_VHOST_VSOCK=n \
- CONFIG_VHOST_RING=n
-OOT_BUILD=KCFLAGS="-I "${OOT_VHOST} ${MAKE} -C ${OOT_KSRC} V=${V}
+ CONFIG_VHOST_RING=n \
+ CONFIG_VHOST_VDPA=n
+OOT_BUILD=KCFLAGS="-include "`pwd`"/oot-stubs.h -I "${OOT_VHOST} ${MAKE} -C ${OOT_KSRC} V=${V}
oot-build:
echo "UNSUPPORTED! Don't use the resulting modules in production!"
${OOT_BUILD} M=`pwd`/vhost_test
diff --git a/tools/virtio/linux/compiler.h b/tools/virtio/linux/compiler.h
index 725b93bfeee1..0f25db473f55 100644
--- a/tools/virtio/linux/compiler.h
+++ b/tools/virtio/linux/compiler.h
@@ -2,7 +2,11 @@
#ifndef LINUX_COMPILER_H
#define LINUX_COMPILER_H
+/* Avoid redefinition warnings */
+#undef __user
#include "../../../include/linux/compiler_types.h"
+#undef __user
+#define __user
#define WRITE_ONCE(var, val) \
(*((volatile typeof(val) *)(&(var))) = (val))
@@ -35,4 +39,6 @@
__v; \
})
+#define __must_check
+
#endif
diff --git a/tools/virtio/linux/cpumask.h b/tools/virtio/linux/cpumask.h
index 307da69d6b26..38ffc00e149d 100644
--- a/tools/virtio/linux/cpumask.h
+++ b/tools/virtio/linux/cpumask.h
@@ -4,4 +4,8 @@
#include <linux/kernel.h>
+struct cpumask {
+ unsigned long bits[1];
+};
+
#endif /* _LINUX_CPUMASK_H */
diff --git a/tools/virtio/linux/device.h b/tools/virtio/linux/device.h
index 4ad7e1df0db5..075c2140d975 100644
--- a/tools/virtio/linux/device.h
+++ b/tools/virtio/linux/device.h
@@ -1,2 +1,10 @@
#ifndef LINUX_DEVICE_H
+
+struct device {
+ void *parent;
+};
+
+struct device_driver {
+ const char *name;
+};
#endif
diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h
index 095958461788..fddfa2fbb276 100644
--- a/tools/virtio/linux/dma-mapping.h
+++ b/tools/virtio/linux/dma-mapping.h
@@ -22,6 +22,7 @@ enum dma_data_direction {
#define dma_free_coherent(d, s, p, h) kfree(p)
#define dma_map_page(d, p, o, s, dir) (page_to_phys(p) + (o))
+#define dma_map_page_attrs(d, p, o, s, dir, a) (page_to_phys(p) + (o))
#define dma_map_single(d, p, s, dir) (virt_to_phys(p))
#define dma_map_single_attrs(d, p, s, dir, a) (virt_to_phys(p))
@@ -29,6 +30,9 @@ enum dma_data_direction {
#define dma_unmap_single(d, a, s, r) do { (void)(d); (void)(a); (void)(s); (void)(r); } while (0)
#define dma_unmap_page(d, a, s, r) do { (void)(d); (void)(a); (void)(s); (void)(r); } while (0)
+#define dma_unmap_page_attrs(d, a, s, r, t) do { \
+ (void)(d); (void)(a); (void)(s); (void)(r); (void)(t); \
+} while (0)
#define sg_dma_address(sg) (0)
#define sg_dma_len(sg) (0)
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index 6702008f7f5c..416d02703f61 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -14,6 +14,7 @@
#include <linux/log2.h>
#include <linux/types.h>
#include <linux/overflow.h>
+#include <linux/limits.h>
#include <linux/list.h>
#include <linux/printk.h>
#include <linux/bug.h>
@@ -135,6 +136,21 @@ static inline void *krealloc_array(void *p, size_t new_n, size_t new_size, gfp_t
#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
#define dev_warn_once(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#define dev_WARN_ONCE(dev, condition, format...) \
+ WARN_ONCE(condition, format)
+
+static inline bool is_vmalloc_addr(const void *x)
+{
+ return false;
+}
+
+#define might_sleep() do { } while (0)
+
+static inline void synchronize_rcu(void)
+{
+ assert(0);
+}
+
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h
index b91681fc1571..b842ae9d870c 100644
--- a/tools/virtio/linux/module.h
+++ b/tools/virtio/linux/module.h
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/export.h>
+struct module;
+
#define MODULE_LICENSE(__MODULE_LICENSE_value) \
static __attribute__((unused)) const char *__MODULE_LICENSE_name = \
__MODULE_LICENSE_value
diff --git a/tools/virtio/linux/ucopysize.h b/tools/virtio/linux/ucopysize.h
new file mode 100644
index 000000000000..8beb7755d060
--- /dev/null
+++ b/tools/virtio/linux/ucopysize.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_UCOPYSIZE_H__
+#define __LINUX_UCOPYSIZE_H__
+
+#include <linux/bug.h>
+
+static inline void check_object_size(const void *ptr, unsigned long n,
+ bool to_user)
+{ }
+
+static inline void copy_overflow(int size, unsigned long count)
+{
+}
+
+static __always_inline __must_check bool
+check_copy_size(const void *addr, size_t bytes, bool is_source)
+{
+ return true;
+}
+
+#endif /* __LINUX_UCOPYSIZE_H__ */
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index 5d3440f474dd..d3029c944589 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -1,72 +1 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LINUX_VIRTIO_H
-#define LINUX_VIRTIO_H
-#include <linux/scatterlist.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-
-struct device {
- void *parent;
-};
-
-struct virtio_device {
- struct device dev;
- u64 features;
- struct list_head vqs;
- spinlock_t vqs_list_lock;
- const struct virtio_config_ops *config;
-};
-
-struct virtqueue {
- struct list_head list;
- void (*callback)(struct virtqueue *vq);
- const char *name;
- struct virtio_device *vdev;
- unsigned int index;
- unsigned int num_free;
- unsigned int num_max;
- void *priv;
- bool reset;
-};
-
-/* Interfaces exported by virtio_ring. */
-int virtqueue_add_sgs(struct virtqueue *vq,
- struct scatterlist *sgs[],
- unsigned int out_sgs,
- unsigned int in_sgs,
- void *data,
- gfp_t gfp);
-
-int virtqueue_add_outbuf(struct virtqueue *vq,
- struct scatterlist sg[], unsigned int num,
- void *data,
- gfp_t gfp);
-
-int virtqueue_add_inbuf(struct virtqueue *vq,
- struct scatterlist sg[], unsigned int num,
- void *data,
- gfp_t gfp);
-
-bool virtqueue_kick(struct virtqueue *vq);
-
-void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
-
-void virtqueue_disable_cb(struct virtqueue *vq);
-
-bool virtqueue_enable_cb(struct virtqueue *vq);
-bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
-
-void *virtqueue_detach_unused_buf(struct virtqueue *vq);
-struct virtqueue *vring_new_virtqueue(unsigned int index,
- unsigned int num,
- unsigned int vring_align,
- struct virtio_device *vdev,
- bool weak_barriers,
- bool ctx,
- void *pages,
- bool (*notify)(struct virtqueue *vq),
- void (*callback)(struct virtqueue *vq),
- const char *name);
-void vring_del_virtqueue(struct virtqueue *vq);
-
-#endif
+#include <../../include/linux/virtio.h>
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
index 42a564f22f2d..a0cd3f9a3111 100644
--- a/tools/virtio/linux/virtio_config.h
+++ b/tools/virtio/linux/virtio_config.h
@@ -1,101 +1 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LINUX_VIRTIO_CONFIG_H
-#define LINUX_VIRTIO_CONFIG_H
-#include <linux/virtio_byteorder.h>
-#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,
- * which includes more checks.
- * @vdev: the device
- * @fbit: the feature bit
- */
-static inline bool __virtio_test_bit(const struct virtio_device *vdev,
- unsigned int fbit)
-{
- return vdev->features & (1ULL << fbit);
-}
-
-/**
- * __virtio_set_bit - helper to set feature bits. For use by transports.
- * @vdev: the device
- * @fbit: the feature bit
- */
-static inline void __virtio_set_bit(struct virtio_device *vdev,
- unsigned int fbit)
-{
- vdev->features |= (1ULL << fbit);
-}
-
-/**
- * __virtio_clear_bit - helper to clear feature bits. For use by transports.
- * @vdev: the device
- * @fbit: the feature bit
- */
-static inline void __virtio_clear_bit(struct virtio_device *vdev,
- unsigned int fbit)
-{
- vdev->features &= ~(1ULL << fbit);
-}
-
-#define virtio_has_feature(dev, feature) \
- (__virtio_test_bit((dev), feature))
-
-/**
- * virtio_has_dma_quirk - determine whether this device has the DMA quirk
- * @vdev: the device
- */
-static inline bool virtio_has_dma_quirk(const struct virtio_device *vdev)
-{
- /*
- * Note the reverse polarity of the quirk feature (compared to most
- * other features), this is for compatibility with legacy systems.
- */
- return !virtio_has_feature(vdev, VIRTIO_F_ACCESS_PLATFORM);
-}
-
-static inline bool virtio_is_little_endian(struct virtio_device *vdev)
-{
- return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
- virtio_legacy_is_little_endian();
-}
-
-/* Memory accessors */
-static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
-{
- return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
-}
-
-static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
-{
- return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
-}
-
-static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
-{
- return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
-}
-
-static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
-{
- return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
-}
-
-static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
-{
- return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
-}
-
-static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
-{
- return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
-}
-
-#endif
+#include "../../include/linux/virtio_config.h"
diff --git a/tools/virtio/oot-stubs.h b/tools/virtio/oot-stubs.h
new file mode 100644
index 000000000000..69e059cd14d6
--- /dev/null
+++ b/tools/virtio/oot-stubs.h
@@ -0,0 +1,10 @@
+#include <linux/bug.h>
+#include <linux/string.h>
+#include <linux/virtio_features.h>
+
+#ifndef VIRTIO_FEATURES_BITS
+#define VIRTIO_FEATURES_BITS 128
+#endif
+#ifndef VIRTIO_U64
+#define VIRTIO_U64(b) ((b) >> 6)
+#endif
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5fcd401a5897..5b5b69c97665 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1749,6 +1749,12 @@ static void kvm_commit_memory_region(struct kvm *kvm,
kvm_free_memslot(kvm, old);
break;
case KVM_MR_MOVE:
+ /*
+ * Moving a guest_memfd memslot isn't supported, and will never
+ * be supported.
+ */
+ WARN_ON_ONCE(old->flags & KVM_MEM_GUEST_MEMFD);
+ fallthrough;
case KVM_MR_FLAGS_ONLY:
/*
* Free the dirty bitmap as needed; the below check encompasses
@@ -1758,6 +1764,15 @@ static void kvm_commit_memory_region(struct kvm *kvm,
kvm_destroy_dirty_bitmap(old);
/*
+ * Unbind the guest_memfd instance as needed; the @new slot has
+ * already created its own binding. TODO: Drop the WARN when
+ * dirty logging guest_memfd memslots is supported. Until then,
+ * flags-only changes on guest_memfd slots should be impossible.
+ */
+ if (WARN_ON_ONCE(old->flags & KVM_MEM_GUEST_MEMFD))
+ kvm_gmem_unbind(old);
+
+ /*
* The final quirk. Free the detached, old slot, but only its
* memory, not any metadata. Metadata, including arch specific
* data, may be reused by @new.
@@ -2086,7 +2101,7 @@ static int kvm_set_memory_region(struct kvm *kvm,
return -EINVAL;
if ((mem->userspace_addr != old->userspace_addr) ||
(npages != old->npages) ||
- ((mem->flags ^ old->flags) & KVM_MEM_READONLY))
+ ((mem->flags ^ old->flags) & (KVM_MEM_READONLY | KVM_MEM_GUEST_MEMFD)))
return -EINVAL;
if (base_gfn != old->base_gfn)