Merge branches 'acpi-processor', 'acpi-tables', 'acpi-pnp' and 'acpi-maintainers'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 15 Feb 2023 14:25:26 +0000 (15:25 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 15 Feb 2023 14:25:26 +0000 (15:25 +0100)
Merge ACPI processor driver changes, ACPI table parser changes, ACPI
device enumeration changes related to PNP and a MAINTAINERS update
related to ACPI for 6.3-rc1:

 - Drop an unnecessary (void *) conversion from the ACPI processor
   driver (Zhou jie).

 - Modify the ACPI processor performance library code to use the "no
   limit" frequency QoS as appropriate and adjust the intel_pstate
   driver accordingly (Rafael Wysocki).

 - Add support for NBFT to the ACPI table parser (Stuart Hayes).

 - Introduce list of known non-PNP devices to avoid enumerating some of
   them as PNP devices (Rafael Wysocki).

 - Add x86 ACPI paths to the ACPI entry in MAINTAINERS to allow scripts
   to report the actual maintainers information (Rafael Wysocki).

* acpi-processor:
  cpufreq: intel_pstate: Drop ACPI _PSS states table patching
  ACPI: processor: perflib: Avoid updating frequency QoS unnecessarily
  ACPI: processor: perflib: Use the "no limit" frequency QoS
  ACPI: processor: idle: Drop unnecessary (void *) conversion

* acpi-tables:
  ACPI: tables: Add support for NBFT

* acpi-pnp:
  ACPI: PNP: Introduce list of known non-PNP devices

* acpi-maintainers:
  MAINTAINERS: Add x86 ACPI paths to the ACPI entry

868 files changed:
.mailmap
CREDITS
Documentation/admin-guide/cgroup-v2.rst
Documentation/admin-guide/mm/zswap.rst
Documentation/devicetree/bindings/i2c/renesas,rzv2m.yaml
Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml
Documentation/devicetree/bindings/phy/amlogic,g12a-usb2-phy.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/amlogic,g12a-usb3-pcie-phy.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb2-phy.yaml [deleted file]
Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml [deleted file]
Documentation/devicetree/bindings/phy/qcom,usb-hs-28nm.yaml
Documentation/devicetree/bindings/regulator/samsung,s2mps14.yaml
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/devicetree/bindings/rtc/qcom-pm8xxx-rtc.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
Documentation/devicetree/bindings/sound/everest,es8326.yaml [changed mode: 0755->0644]
Documentation/filesystems/erofs.rst
Documentation/kbuild/makefiles.rst
Documentation/networking/bridge.rst
Documentation/networking/device_drivers/ethernet/intel/ice.rst
Documentation/networking/nf_conntrack-sysctl.rst
Documentation/virt/kvm/api.rst
Documentation/x86/amd-memory-encryption.rst
MAINTAINERS
Makefile
arch/arm/Makefile
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/armada-39x.dtsi
arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts
arch/arm/boot/dts/imx53-ppd.dts
arch/arm/boot/dts/imx6qdl-gw560x.dtsi
arch/arm/boot/dts/imx6ul-pico-dwarf.dts
arch/arm/boot/dts/imx7d-pico-dwarf.dts
arch/arm/boot/dts/imx7d-pico-nymph.dts
arch/arm/boot/dts/imx7d-smegw01.dts
arch/arm/boot/dts/nuvoton-wpcm450.dtsi
arch/arm/boot/dts/qcom-apq8084-ifc6540.dts
arch/arm/boot/dts/qcom-apq8084.dtsi
arch/arm/boot/dts/sam9x60.dtsi
arch/arm/boot/dts/stm32mp151a-prtt1l.dtsi
arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
arch/arm/crypto/Makefile
arch/arm/mach-footbridge/isa-rtc.c
arch/arm/mach-imx/cpu-imx25.c
arch/arm/mach-imx/cpu-imx27.c
arch/arm/mach-imx/cpu-imx31.c
arch/arm/mach-imx/cpu-imx35.c
arch/arm/mach-imx/cpu-imx5.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/gpio15xx.c
arch/arm/mach-omap1/io.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap1/pm.h
arch/arm/mach-pxa/Kconfig
arch/arm/mm/nommu.c
arch/arm/mm/proc-macros.S
arch/arm64/boot/dts/amlogic/meson-sm1-odroid-hc4.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts
arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi
arch/arm64/boot/dts/freescale/imx8dxl.dtsi
arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi
arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts
arch/arm64/boot/dts/freescale/imx8mm-nitrogen-r2.dts
arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso
arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
arch/arm64/boot/dts/freescale/imx8mm-verdin-dahlia.dtsi
arch/arm64/boot/dts/freescale/imx8mm-verdin-dev.dtsi
arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
arch/arm64/boot/dts/freescale/imx8mp-evk.dts
arch/arm64/boot/dts/freescale/imx8mp-phycore-som.dtsi
arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts
arch/arm64/boot/dts/freescale/imx8mq-thor96.dts
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts
arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi
arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
arch/arm64/boot/dts/qcom/msm8992.dtsi
arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts
arch/arm64/boot/dts/qcom/sc8280xp.dtsi
arch/arm64/boot/dts/qcom/sm8250.dtsi
arch/arm64/boot/dts/qcom/sm8350.dtsi
arch/arm64/include/asm/efi.h
arch/arm64/include/asm/stacktrace.h
arch/arm64/kernel/efi-rt-wrapper.S
arch/arm64/kernel/efi.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kvm/guest.c
arch/arm64/kvm/vgic/vgic-its.c
arch/arm64/kvm/vgic/vgic-v3.c
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/kvm/vgic/vgic.h
arch/ia64/kernel/sys_ia64.c
arch/loongarch/include/asm/ftrace.h
arch/loongarch/include/asm/inst.h
arch/loongarch/include/asm/unwind.h
arch/loongarch/kernel/Makefile
arch/loongarch/kernel/alternative.c
arch/loongarch/kernel/cpu-probe.c
arch/loongarch/kernel/genex.S
arch/loongarch/kernel/inst.c
arch/loongarch/kernel/process.c
arch/loongarch/kernel/traps.c
arch/loongarch/kernel/unwind.c [new file with mode: 0644]
arch/loongarch/kernel/unwind_guess.c
arch/loongarch/kernel/unwind_prologue.c
arch/loongarch/mm/tlb.c
arch/parisc/kernel/firmware.c
arch/parisc/kernel/ptrace.c
arch/powerpc/include/asm/book3s/64/tlbflush.h
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/kernel/dbell.c
arch/powerpc/kernel/head_85xx.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/time.c
arch/powerpc/kexec/file_load_64.c
arch/powerpc/kvm/booke.c
arch/powerpc/mm/book3s64/radix_pgtable.c
arch/powerpc/perf/imc-pmu.c
arch/riscv/Makefile
arch/riscv/boot/dts/sifive/fu740-c000.dtsi
arch/riscv/include/asm/alternative-macros.h
arch/riscv/include/asm/hwcap.h
arch/riscv/include/asm/vdso/processor.h
arch/riscv/kernel/head.S
arch/riscv/kernel/probes/kprobes.c
arch/riscv/kernel/probes/simulate-insn.c
arch/riscv/kernel/smpboot.c
arch/s390/boot/decompressor.c
arch/s390/kernel/setup.c
arch/sh/kernel/vmlinux.lds.S
arch/x86/Makefile
arch/x86/boot/compressed/ident_map_64.c
arch/x86/boot/compressed/misc.h
arch/x86/boot/compressed/sev.c
arch/x86/events/intel/core.c
arch/x86/events/intel/cstate.c
arch/x86/include/asm/acpi.h
arch/x86/include/asm/debugreg.h
arch/x86/include/asm/msr-index.h
arch/x86/include/uapi/asm/svm.h
arch/x86/kernel/cpu/aperfmperf.c
arch/x86/kernel/i8259.c
arch/x86/kernel/irqinit.c
arch/x86/kvm/vmx/vmx.c
arch/x86/pci/xen.c
block/bfq-cgroup.c
block/bfq-iosched.c
block/bfq-iosched.h
block/blk-cgroup.c
block/blk-mq.c
certs/Makefile
drivers/accessibility/speakup/spk_ttyio.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/cppc_acpi.c
drivers/acpi/prmt.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/sleep.c
drivers/acpi/tables.c
drivers/acpi/video_detect.c
drivers/ata/libata-core.c
drivers/base/property.c
drivers/base/test/test_async_driver_probe.c
drivers/block/pktcdvd.c
drivers/block/rnbd/rnbd-clt.c
drivers/block/ublk_drv.c
drivers/bluetooth/hci_qca.c
drivers/bus/sunxi-rsb.c
drivers/comedi/drivers/adv_pci1760.c
drivers/cpufreq/intel_pstate.c
drivers/cxl/acpi.c
drivers/cxl/core/pmem.c
drivers/cxl/pci.c
drivers/cxl/pmem.c
drivers/dma-buf/dma-fence.c
drivers/dma/dmaengine.c
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
drivers/dma/idxd/device.c
drivers/dma/imx-sdma.c
drivers/dma/lgm/lgm-dma.c
drivers/dma/ptdma/ptdma-dev.c
drivers/dma/ptdma/ptdma.h
drivers/dma/qcom/gpi.c
drivers/dma/tegra186-gpc-dma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/k3-udma.c
drivers/dma/xilinx/xilinx_dma.c
drivers/edac/edac_device.c
drivers/edac/qcom_edac.c
drivers/firewire/core-cdev.c
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/shmem.c
drivers/firmware/arm_scmi/virtio.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/memattr.c
drivers/firmware/google/gsmi.c
drivers/fpga/intel-m10-bmc-sec-update.c
drivers/fpga/stratix10-soc.c
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpiolib-acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
drivers/gpu/drm/amd/amdgpu/nbio_v4_3.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
drivers/gpu/drm/display/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fbdev_generic.c
drivers/gpu/drm/drm_vma_manager.c
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/display/skl_universal_plane.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_mman.c
drivers/gpu/drm/i915/gem/i915_gem_tiling.c
drivers/gpu/drm/i915/gem/selftests/huge_pages.c
drivers/gpu/drm/i915/gt/intel_context.c
drivers/gpu/drm/i915/gt/intel_context.h
drivers/gpu/drm/i915/gt/intel_engine.h
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/gpu/drm/i915/gt/intel_execlists_submission.h
drivers/gpu/drm/i915/gt/intel_gt_regs.h
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
drivers/gpu/drm/i915/i915_driver.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_switcheroo.c
drivers/gpu/drm/i915/selftests/intel_scheduler_helpers.c
drivers/gpu/drm/msm/adreno/adreno_device.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
drivers/gpu/drm/nouveau/nvkm/core/firmware.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
drivers/gpu/drm/panfrost/Kconfig
drivers/gpu/drm/solomon/ssd130x.c
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h [changed mode: 0755->0644]
drivers/hid/amd-sfh-hid/amd_sfh_client.c
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
drivers/hid/hid-betopff.c
drivers/hid/hid-bigbenff.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-playstation.c
drivers/hid/hid-quirks.c
drivers/hid/hid-uclogic-core.c
drivers/hid/hid-uclogic-params.c
drivers/hid/intel-ish-hid/ishtp/dma-if.c
drivers/hv/hv_balloon.c
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-rk3x.c
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/adc/berlin2-adc.c
drivers/iio/adc/imx8qxp-adc.c
drivers/iio/adc/stm32-dfsdm-adc.c
drivers/iio/adc/twl6030-gpadc.c
drivers/iio/adc/xilinx-ams.c
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/imu/fxos8700_core.c
drivers/iio/imu/st_lsm6dsx/Kconfig
drivers/iio/light/cm32181.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/hfi1/user_exp_rcv.c
drivers/infiniband/hw/hfi1/user_exp_rcv.h
drivers/infiniband/sw/rxe/rxe_param.h
drivers/infiniband/sw/rxe/rxe_pool.c
drivers/input/mouse/synaptics.c
drivers/input/serio/i8042-acpipnpio.h
drivers/interconnect/qcom/icc-rpm.c
drivers/interconnect/qcom/msm8996.c
drivers/md/bcache/bcache_ondisk.h
drivers/md/bcache/journal.c
drivers/md/md.c
drivers/media/common/videobuf2/videobuf2-core.c
drivers/media/v4l2-core/v4l2-ctrls-api.c
drivers/memory/atmel-sdramc.c
drivers/memory/mvebu-devbus.c
drivers/memory/omap-gpmc.c
drivers/memory/tegra/tegra186.c
drivers/misc/fastrpc.c
drivers/misc/mei/bus.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/vmw_vmci/vmci_guest.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sunxi-mmc.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
drivers/net/dsa/Kconfig
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/microchip/ksz9477_i2c.c
drivers/net/ethernet/adi/adin1110.c
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
drivers/net/ethernet/amd/xgbe/xgbe.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/engleder/tsnep_main.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
drivers/net/ethernet/freescale/enetc/enetc.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fman/fman_memac.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_dcb_lib.c
drivers/net/ethernet/intel/ice/ice_dcb_lib.h
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/igc/igc_ptp.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h
drivers/net/ethernet/mediatek/mtk_ppe.c
drivers/net/ethernet/mediatek/mtk_ppe.h
drivers/net/ethernet/mediatek/mtk_sgmii.c
drivers/net/ethernet/mellanox/mlx5/core/en/htb.c
drivers/net/ethernet/mellanox/mlx5/core/en/params.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/qos.c
drivers/net/ethernet/mellanox/mlx5/core/qos.h
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microsoft/mana/gdma_main.c
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
drivers/net/ethernet/qlogic/qede/qede_fp.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/rswitch.c
drivers/net/ethernet/renesas/rswitch.h
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
drivers/net/ethernet/stmicro/stmmac/dwmac5.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/hyperv/netvsc.c
drivers/net/ipa/ipa_interrupt.c
drivers/net/ipa/ipa_interrupt.h
drivers/net/ipa/ipa_power.c
drivers/net/mdio/mdio-mux-meson-g12a.c
drivers/net/phy/dp83822.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/meson-gxl.c
drivers/net/phy/phy_device.c
drivers/net/team/team.c
drivers/net/usb/sr9700.c
drivers/net/virtio_net.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
drivers/net/wireless/mediatek/mt76/tx.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wwan/t7xx/t7xx_hif_dpmaif.c
drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
drivers/net/wwan/t7xx/t7xx_netdev.c
drivers/net/wwan/t7xx/t7xx_pci.c
drivers/nvme/host/apple.c
drivers/nvme/host/auth.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/pci.c
drivers/nvme/target/fc.c
drivers/nvmem/brcm_nvram.c
drivers/nvmem/core.c
drivers/nvmem/qcom-spmi-sdam.c
drivers/nvmem/sunxi_sid.c
drivers/of/fdt.c
drivers/parisc/pdc_stable.c
drivers/perf/arm-cmn.c
drivers/phy/freescale/phy-fsl-imx8m-pcie.c
drivers/phy/phy-can-transceiver.c
drivers/phy/qualcomm/phy-qcom-usb-hs-28nm.c
drivers/phy/renesas/r8a779f0-ether-serdes.c
drivers/phy/rockchip/phy-rockchip-inno-usb2.c
drivers/phy/sunplus/phy-sunplus-usb2.c
drivers/phy/ti/Kconfig
drivers/pinctrl/nomadik/pinctrl-ab8500.c
drivers/pinctrl/nomadik/pinctrl-ab8505.c
drivers/pinctrl/nomadik/pinctrl-abx500.c
drivers/pinctrl/nomadik/pinctrl-abx500.h
drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
drivers/pinctrl/nomadik/pinctrl-nomadik.h
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/sunplus/sppctl.c
drivers/platform/x86/amd/Kconfig
drivers/platform/x86/amd/pmc.c
drivers/platform/x86/amd/pmf/auto-mode.c
drivers/platform/x86/amd/pmf/cnqf.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/amd/pmf/sps.c
drivers/platform/x86/apple-gmux.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/dell/dell-wmi-base.c
drivers/platform/x86/gigabyte-wmi.c
drivers/platform/x86/hp/hp-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/reset/Kconfig
drivers/reset/reset-uniphier-glue.c
drivers/rtc/rtc-efi.c
drivers/rtc/rtc-sunplus.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/hpsa.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/libiscsi.c
drivers/scsi/scsi.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/soc/imx/imx8mp-blk-ctrl.c
drivers/soc/imx/soc-imx8m.c
drivers/soc/qcom/apr.c
drivers/soc/qcom/cpr.c
drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
drivers/target/target_core_tmr.c
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.h
drivers/thermal/thermal_core.c
drivers/thunderbolt/retimer.c
drivers/thunderbolt/tb.c
drivers/thunderbolt/tunnel.c
drivers/thunderbolt/xdomain.c
drivers/tty/serial/8250/8250_dma.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/kgdboc.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/stm32-usart.c
drivers/tty/vt/vc_screen.c
drivers/ufs/core/ufshcd.c
drivers/usb/cdns3/cdns3-gadget.c
drivers/usb/chipidea/core.c
drivers/usb/core/hub.c
drivers/usb/core/usb-acpi.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/dwc3-qcom.c
drivers/usb/fotg210/fotg210-udc.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/legacy/webcam.c
drivers/usb/gadget/udc/bcm63xx_udc.c
drivers/usb/gadget/udc/fsl_qe_udc.c
drivers/usb/gadget/udc/fsl_udc_core.c
drivers/usb/gadget/udc/fusb300_udc.c
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/gadget/udc/gr_udc.c
drivers/usb/gadget/udc/m66592-udc.c
drivers/usb/gadget/udc/max3420_udc.c
drivers/usb/gadget/udc/mv_u3d_core.c
drivers/usb/gadget/udc/mv_udc_core.c
drivers/usb/gadget/udc/net2272.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/omap_udc.c
drivers/usb/gadget/udc/pch_udc.c
drivers/usb/gadget/udc/snps_udc_core.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/iowarrior.c
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/musb/omap2430.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/option.c
drivers/usb/storage/uas-detect.h
drivers/usb/storage/unusual_uas.h
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi.h
drivers/vdpa/ifcvf/ifcvf_main.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/fbdev/atmel_lcdfb.c
drivers/video/fbdev/aty/aty128fb.c
drivers/video/fbdev/aty/atyfb_base.c
drivers/video/fbdev/aty/radeon_backlight.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmon.c
drivers/video/fbdev/mx3fb.c
drivers/video/fbdev/nvidia/nv_backlight.c
drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
drivers/video/fbdev/riva/fbdev.c
drivers/w1/w1.c
drivers/w1/w1_int.c
drivers/watchdog/diag288_wdt.c
fs/affs/file.c
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/fs.h
fs/btrfs/qgroup.c
fs/btrfs/space-info.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/ceph/super.h
fs/cifs/dfs_cache.c
fs/cifs/dfs_cache.h
fs/cifs/smb2pdu.c
fs/cifs/smbdirect.c
fs/erofs/super.c
fs/erofs/zdata.c
fs/erofs/zmap.c
fs/ext4/xattr.c
fs/freevxfs/Kconfig
fs/fscache/volume.c
fs/fuse/acl.c
fs/fuse/dir.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/fuse/xattr.c
fs/gfs2/log.c
fs/ksmbd/connection.c
fs/ksmbd/ksmbd_netlink.h
fs/ksmbd/ndr.c
fs/ksmbd/server.h
fs/ksmbd/smb2pdu.c
fs/ksmbd/smb2pdu.h
fs/ksmbd/transport_ipc.c
fs/ksmbd/transport_tcp.c
fs/nfsd/filecache.c
fs/nfsd/netns.h
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nilfs2/btree.c
fs/overlayfs/copy_up.c
fs/proc/task_mmu.c
fs/squashfs/squashfs_fs.h
fs/squashfs/squashfs_fs_sb.h
fs/squashfs/xattr.h
fs/squashfs/xattr_id.c
fs/userfaultfd.c
fs/zonefs/super.c
include/acpi/acpixf.h
include/acpi/actbl1.h
include/drm/drm_fb_helper.h
include/drm/drm_vma_manager.h
include/kunit/test.h
include/kvm/arm_vgic.h
include/linux/apple-gmux.h
include/linux/bpf.h
include/linux/ceph/libceph.h
include/linux/efi.h
include/linux/firmware/xlnx-zynqmp.h
include/linux/highmem-internal.h
include/linux/hugetlb.h
include/linux/memcontrol.h
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mm_types.h
include/linux/nvmem-provider.h
include/linux/page_ref.h
include/linux/soc/ti/omap1-io.h
include/linux/spinlock.h
include/linux/stmmac.h
include/linux/swap.h
include/linux/usb.h
include/linux/util_macros.h
include/net/mac80211.h
include/net/mana/gdma.h
include/net/sch_generic.h
include/scsi/libiscsi.h
include/soc/bcm2835/raspberrypi-firmware.h
include/uapi/linux/netfilter/nf_conntrack_sctp.h
include/uapi/linux/netfilter/nfnetlink_cttimeout.h
include/ufs/ufshcd.h
init/Kconfig
init/version-timestamp.c
io_uring/io_uring.c
io_uring/msg_ring.c
io_uring/net.c
io_uring/poll.c
kernel/bpf/bpf_lsm.c
kernel/bpf/btf.c
kernel/bpf/hashtab.c
kernel/bpf/memalloc.c
kernel/bpf/offload.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cpuset.c
kernel/events/core.c
kernel/gen_kheaders.sh
kernel/irq/irqdomain.c
kernel/irq/msi.c
kernel/module/main.c
kernel/printk/printk.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sys.c
kernel/trace/Kconfig
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/rv/rv.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_filter.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_osnoise.c
kernel/trace/trace_output.c
lib/Kconfig.debug
lib/Kconfig.kcsan
lib/dec_and_lock.c
lib/kunit/assert.c
lib/kunit/test.c
lib/maple_tree.c
lib/memcpy_kunit.c
lib/nlattr.c
lib/scatterlist.c
lib/test_maple_tree.c
lib/win_minmax.c
mm/compaction.c
mm/hugetlb.c
mm/kasan/report.c
mm/khugepaged.c
mm/kmemleak.c
mm/madvise.c
mm/memcontrol.c
mm/memory.c
mm/mempolicy.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/nommu.c
mm/shmem.c
mm/slab.c
mm/swapfile.c
mm/vmscan.c
mm/zsmalloc.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/mgmt_util.h
net/bluetooth/rfcomm/sock.c
net/bridge/br_netfilter_hooks.c
net/can/isotp.c
net/can/j1939/transport.c
net/can/raw.c
net/core/gro.c
net/core/net_namespace.c
net/core/skbuff.c
net/core/sock_map.c
net/ethtool/rss.c
net/ipv4/fib_semantics.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c
net/ipv4/metrics.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_ulp.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/l2tp/l2tp_core.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs_sta.c
net/mac80211/driver-ops.c
net/mac80211/driver-ops.h
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac802154/rx.c
net/mctp/af_mctp.c
net/mctp/route.c
net/mptcp/pm.c
net/mptcp/pm_userspace.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/ipset/ip_set_bitmap_ip.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nft_payload.c
net/netfilter/nft_set_rbtree.c
net/netlink/af_netlink.c
net/netrom/af_netrom.c
net/netrom/nr_timer.c
net/nfc/llcp_core.c
net/openvswitch/datapath.c
net/qrtr/ns.c
net/rose/af_rose.c
net/rxrpc/call_object.c
net/sched/sch_gred.c
net/sched/sch_htb.c
net/sched/sch_taprio.c
net/sctp/bind_addr.c
net/sctp/transport.c
net/tls/tls_sw.c
net/x25/af_x25.c
rust/kernel/print.rs
samples/ftrace/ftrace-direct-multi-modify.c
samples/ftrace/ftrace-direct-multi.c
scripts/Makefile.modinst
scripts/atomic/atomics.tbl [changed mode: 0755->0644]
scripts/gcc-plugins/gcc-common.h
scripts/jobserver-exec
scripts/kconfig/.gitignore
scripts/kconfig/Makefile
scripts/package/mkspec
scripts/tracing/ftrace-bisect.sh
security/tomoyo/Kconfig
security/tomoyo/Makefile
sound/core/memalloc.c
sound/firewire/motu/motu-hwdep.c
sound/pci/hda/hda_bind.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/soc/amd/acp-es8336.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/cs42l56.c
sound/soc/codecs/es8326.c [changed mode: 0755->0644]
sound/soc/codecs/es8326.h [changed mode: 0755->0644]
sound/soc/codecs/wsa883x.c
sound/soc/intel/avs/core.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/bytcr_rt5651.c
sound/soc/intel/boards/bytcr_wm5102.c
sound/soc/intel/boards/sof_cs42l42.c
sound/soc/intel/boards/sof_es8336.c
sound/soc/intel/boards/sof_nau8825.c
sound/soc/intel/boards/sof_rt5682.c
sound/soc/intel/boards/sof_ssp_amp.c
sound/soc/sof/ipc4-mtrace.c
sound/soc/sof/sof-audio.c
sound/usb/quirks.c
tools/arch/arm64/include/asm/cputype.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/gpio/gpio-event-mon.c
tools/include/linux/build_bug.h
tools/include/uapi/linux/kvm.h
tools/perf/tests/shell/buildid.sh
tools/perf/trace/beauty/include/linux/socket.h
tools/perf/util/build-id.c
tools/perf/util/expr.l
tools/testing/selftests/amd-pstate/Makefile
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
tools/testing/selftests/bpf/verifier/search_pruning.c
tools/testing/selftests/cgroup/test_cpuset_prs.sh
tools/testing/selftests/filesystems/fat/run_fat_tests.sh [changed mode: 0644->0755]
tools/testing/selftests/kvm/aarch64/page_fault_test.c
tools/testing/selftests/kvm/x86_64/nx_huge_pages_test.c
tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
tools/testing/selftests/lib.mk
tools/testing/selftests/net/cmsg_ipv6.sh
tools/testing/selftests/net/mptcp/userspace_pm.sh
tools/testing/selftests/net/toeplitz.c
tools/testing/selftests/net/udpgso_bench.sh
tools/testing/selftests/net/udpgso_bench_rx.c
tools/testing/selftests/net/udpgso_bench_tx.c
tools/testing/selftests/netfilter/nft_trans_stress.sh
tools/testing/selftests/netfilter/settings [new file with mode: 0644]
tools/testing/selftests/proc/proc-empty-vm.c
tools/testing/selftests/proc/proc-pid-vm.c
tools/testing/selftests/vm/hugetlb-madvise.c
tools/virtio/linux/bug.h
tools/virtio/linux/build_bug.h [new file with mode: 0644]
tools/virtio/linux/cpumask.h [new file with mode: 0644]
tools/virtio/linux/gfp.h [new file with mode: 0644]
tools/virtio/linux/kernel.h
tools/virtio/linux/kmsan.h [new file with mode: 0644]
tools/virtio/linux/scatterlist.h
tools/virtio/linux/topology.h [new file with mode: 0644]
virt/kvm/vfio.c

index 562f70d3b6a5496db9b0c9cd98a39ca2fabe6ce7..318e63f338b16eb7e2eea6964a16d1f984ce3915 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -130,6 +130,7 @@ Domen Puncer <domen@coderock.org>
 Douglas Gilbert <dougg@torque.net>
 Ed L. Cashin <ecashin@coraid.com>
 Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com>
+Eugen Hristev <eugen.hristev@collabora.com> <eugen.hristev@microchip.com>
 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> <ezequiel@collabora.com>
 Felipe W Damasio <felipewd@terra.com.br>
@@ -214,6 +215,7 @@ Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com>
 Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
 Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
 Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
+John Crispin <john@phrozen.org> <blogic@openwrt.org>
 John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
 John Stultz <johnstul@us.ibm.com>
 Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>
@@ -371,6 +373,7 @@ Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
 Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
+Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
 Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
 Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
 Roman Gushchin <roman.gushchin@linux.dev> <klamm@yandex-team.ru>
diff --git a/CREDITS b/CREDITS
index 4e302a459ddf069ce3b59b3dd7bbebcd8476ef46..5f5d70c9c03892b428e73a71f3fd97fec0fef511 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1173,6 +1173,10 @@ D: Future Domain TMC-16x0 SCSI driver (author)
 D: APM driver (early port)
 D: DRM drivers (author of several)
 
+N: Veaceslav Falico
+E: vfalico@gmail.com
+D: Co-maintainer and co-author of the network bonding driver.
+
 N: János Farkas
 E: chexum@shadow.banki.hu
 D: romfs, various (mostly networking) fixes
@@ -2489,6 +2493,13 @@ D: XF86_Mach8
 D: XF86_8514
 D: cfdisk (curses based disk partitioning program)
 
+N: Mat Martineau
+E: mat@martineau.name
+D: MPTCP subsystem co-maintainer 2020-2023
+D: Keyctl restricted keyring and Diffie-Hellman UAPI
+D: Bluetooth L2CAP ERTM mode and AMP
+S: USA
+
 N: John S. Marvin
 E: jsm@fc.hp.com
 D: PA-RISC port
@@ -4172,6 +4183,10 @@ S: B-1206 Jingmao Guojigongyu
 S: 16 Baliqiao Nanjie, Beijing 101100
 S: People's Repulic of China
 
+N: Vlad Yasevich
+E: vyasevich@gmail.com
+D: SCTP protocol maintainer.
+
 N: Aviad Yehezkel
 E: aviadye@nvidia.com
 D: Kernel TLS implementation and offload support.
index c8ae7c897f142a329e9f3ac6c496435460ef1c8b..74cec76be9f2c0a336a89756327e43742bd24528 100644 (file)
@@ -1245,13 +1245,17 @@ PAGE_SIZE multiple when read back.
        This is a simple interface to trigger memory reclaim in the
        target cgroup.
 
-       This file accepts a string which contains the number of bytes to
-       reclaim.
+       This file accepts a single key, the number of bytes to reclaim.
+       No nested keys are currently supported.
 
        Example::
 
          echo "1G" > memory.reclaim
 
+       The interface can be later extended with nested keys to
+       configure the reclaim behavior. For example, specify the
+       type of memory to reclaim from (anon, file, ..).
+
        Please note that the kernel can over or under reclaim from
        the target cgroup. If less bytes are reclaimed than the
        specified amount, -EAGAIN is returned.
@@ -1263,13 +1267,6 @@ PAGE_SIZE multiple when read back.
        This means that the networking layer will not adapt based on
        reclaim induced by memory.reclaim.
 
-       This file also allows the user to specify the nodes to reclaim from,
-       via the 'nodes=' key, for example::
-
-         echo "1G nodes=0,1" > memory.reclaim
-
-       The above instructs the kernel to reclaim memory from nodes 0,1.
-
   memory.peak
        A read-only single value file which exists on non-root
        cgroups.
index f67de481c7f60559c169ac0ba7e8dcaff24b5da9..6dd74a18268baa6c74acfd55499ad769e04c12b2 100644 (file)
@@ -70,9 +70,7 @@ e.g. ``zswap.zpool=zbud``. It can also be changed at runtime using the sysfs
 The zbud type zpool allocates exactly 1 page to store 2 compressed pages, which
 means the compression ratio will always be 2:1 or worse (because of half-full
 zbud pages).  The zsmalloc type zpool has a more complex compressed page
-storage method, and it can achieve greater storage densities.  However,
-zsmalloc does not implement compressed page eviction, so once zswap fills it
-cannot evict the oldest page, it can only reject new pages.
+storage method, and it can achieve greater storage densities.
 
 When a swap page is passed from frontswap to zswap, zswap maintains a mapping
 of the swap entry, a combination of the swap type and swap offset, to the zpool
index c46378efc12399dda5b85ce961cfe8ea53453868..92e899905ef88915179a3a92d604cbc3149e8e51 100644 (file)
@@ -16,7 +16,7 @@ properties:
   compatible:
     items:
       - enum:
-          - renesas,i2c-r9a09g011  # RZ/V2M
+          - renesas,r9a09g011-i2c  # RZ/V2M
       - const: renesas,rzv2m-i2c
 
   reg:
@@ -66,7 +66,7 @@ examples:
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
     i2c0: i2c@a4030000 {
-        compatible = "renesas,i2c-r9a09g011", "renesas,rzv2m-i2c";
+        compatible = "renesas,r9a09g011-i2c", "renesas,rzv2m-i2c";
         reg = <0xa4030000 0x80>;
         interrupts = <GIC_SPI 232 IRQ_TYPE_EDGE_RISING>,
                      <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>;
index 4b37aa88a375b12ebffd09f43e6539a61cfb9c65..5e6be4e79201eeb09903ea8a1af78ffab305f44f 100644 (file)
@@ -84,7 +84,6 @@ allOf:
               - qcom,msm8939-pcnoc
               - qcom,msm8939-snoc
               - qcom,msm8996-a1noc
-              - qcom,msm8996-a2noc
               - qcom,msm8996-bimc
               - qcom,msm8996-cnoc
               - qcom,msm8996-pnoc
@@ -186,6 +185,29 @@ allOf:
       required:
         - power-domains
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,msm8996-a2noc
+
+    then:
+      properties:
+        clock-names:
+          items:
+            - const: bus
+            - const: bus_a
+            - const: aggre2_ufs_axi
+            - const: ufs_axi
+
+        clocks:
+          items:
+            - description: Bus Clock
+            - description: Bus A Clock
+            - description: Aggregate2 NoC UFS AXI Clock
+            - description: UFS AXI Clock
+
   - if:
       properties:
         compatible:
diff --git a/Documentation/devicetree/bindings/phy/amlogic,g12a-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/amlogic,g12a-usb2-phy.yaml
new file mode 100644 (file)
index 0000000..bb01c6b
--- /dev/null
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 BayLibre, SAS
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/amlogic,g12a-usb2-phy.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic G12A USB2 PHY
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,g12a-usb2-phy
+      - amlogic,a1-usb2-phy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: xtal
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: phy
+
+  "#phy-cells":
+    const: 0
+
+  phy-supply:
+    description:
+      Phandle to a regulator that provides power to the PHY. This
+      regulator will be managed during the PHY power on/off sequence.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - "#phy-cells"
+
+if:
+  properties:
+    compatible:
+      enum:
+        - amlogic,meson-a1-usb-ctrl
+
+then:
+  properties:
+    power-domains:
+      maxItems: 1
+  required:
+    - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+    phy@36000 {
+          compatible = "amlogic,g12a-usb2-phy";
+          reg = <0x36000 0x2000>;
+          clocks = <&xtal>;
+          clock-names = "xtal";
+          resets = <&phy_reset>;
+          reset-names = "phy";
+          #phy-cells = <0>;
+    };
diff --git a/Documentation/devicetree/bindings/phy/amlogic,g12a-usb3-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/amlogic,g12a-usb3-pcie-phy.yaml
new file mode 100644 (file)
index 0000000..129d26e
--- /dev/null
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 BayLibre, SAS
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/amlogic,g12a-usb3-pcie-phy.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic G12A USB3 + PCIE Combo PHY
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,g12a-usb3-pcie-phy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: ref_clk
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: phy
+
+  "#phy-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    phy@46000 {
+          compatible = "amlogic,g12a-usb3-pcie-phy";
+          reg = <0x46000 0x2000>;
+          clocks = <&ref_clk>;
+          clock-names = "ref_clk";
+          resets = <&phy_reset>;
+          reset-names = "phy";
+          #phy-cells = <1>;
+    };
diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb2-phy.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb2-phy.yaml
deleted file mode 100644 (file)
index f3a5fba..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-# Copyright 2019 BayLibre, SAS
-%YAML 1.2
----
-$id: "http://devicetree.org/schemas/phy/amlogic,meson-g12a-usb2-phy.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
-
-title: Amlogic G12A USB2 PHY
-
-maintainers:
-  - Neil Armstrong <neil.armstrong@linaro.org>
-
-properties:
-  compatible:
-    enum:
-      - amlogic,meson-g12a-usb2-phy
-      - amlogic,meson-a1-usb2-phy
-
-  reg:
-    maxItems: 1
-
-  clocks:
-    maxItems: 1
-
-  clock-names:
-    items:
-      - const: xtal
-
-  resets:
-    maxItems: 1
-
-  reset-names:
-    items:
-      - const: phy
-
-  "#phy-cells":
-    const: 0
-
-  phy-supply:
-    description:
-      Phandle to a regulator that provides power to the PHY. This
-      regulator will be managed during the PHY power on/off sequence.
-
-required:
-  - compatible
-  - reg
-  - clocks
-  - clock-names
-  - resets
-  - reset-names
-  - "#phy-cells"
-
-if:
-  properties:
-    compatible:
-      enum:
-        - amlogic,meson-a1-usb-ctrl
-
-then:
-  properties:
-    power-domains:
-      maxItems: 1
-  required:
-    - power-domains
-
-additionalProperties: false
-
-examples:
-  - |
-    phy@36000 {
-          compatible = "amlogic,meson-g12a-usb2-phy";
-          reg = <0x36000 0x2000>;
-          clocks = <&xtal>;
-          clock-names = "xtal";
-          resets = <&phy_reset>;
-          reset-names = "phy";
-          #phy-cells = <0>;
-    };
diff --git a/Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml
deleted file mode 100644 (file)
index 868b4e6..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-# Copyright 2019 BayLibre, SAS
-%YAML 1.2
----
-$id: "http://devicetree.org/schemas/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
-
-title: Amlogic G12A USB3 + PCIE Combo PHY
-
-maintainers:
-  - Neil Armstrong <neil.armstrong@linaro.org>
-
-properties:
-  compatible:
-    enum:
-      - amlogic,meson-g12a-usb3-pcie-phy
-
-  reg:
-    maxItems: 1
-
-  clocks:
-    maxItems: 1
-
-  clock-names:
-    items:
-      - const: ref_clk
-
-  resets:
-    maxItems: 1
-
-  reset-names:
-    items:
-      - const: phy
-
-  "#phy-cells":
-    const: 1
-
-required:
-  - compatible
-  - reg
-  - clocks
-  - clock-names
-  - resets
-  - reset-names
-  - "#phy-cells"
-
-additionalProperties: false
-
-examples:
-  - |
-    phy@46000 {
-          compatible = "amlogic,meson-g12a-usb3-pcie-phy";
-          reg = <0x46000 0x2000>;
-          clocks = <&ref_clk>;
-          clock-names = "ref_clk";
-          resets = <&phy_reset>;
-          reset-names = "phy";
-          #phy-cells = <1>;
-    };
index abcc4373f39e1898244abeca9f7308f4de357d51..ca6a0836b53c4168e29830b1a5591cfc9453ed70 100644 (file)
@@ -16,7 +16,6 @@ properties:
   compatible:
     enum:
       - qcom,usb-hs-28nm-femtophy
-      - qcom,usb-hs-28nm-mdm9607
 
   reg:
     maxItems: 1
index 01f9d4e236e94901e9eb6e7f2d731d00c06cb77a..a7feb497eb89bdc278b4c315df1aa8f499a8bf41 100644 (file)
@@ -19,8 +19,8 @@ description: |
   additional information and example.
 
 patternProperties:
-  # 25 LDOs
-  "^LDO([1-9]|[1][0-9]|2[0-5])$":
+  # 25 LDOs, without LDO10-12
+  "^LDO([1-9]|1[3-9]|2[0-5])$":
     type: object
     $ref: regulator.yaml#
     unevaluatedProperties: false
@@ -30,6 +30,23 @@ patternProperties:
     required:
       - regulator-name
 
+  "^LDO(1[0-2])$":
+    type: object
+    $ref: regulator.yaml#
+    unevaluatedProperties: false
+    description:
+      Properties for single LDO regulator.
+
+    properties:
+      samsung,ext-control-gpios:
+        maxItems: 1
+        description:
+          LDO10, LDO11 and LDO12 can be configured to external control over
+          GPIO.
+
+    required:
+      - regulator-name
+
   # 5 bucks
   "^BUCK[1-5]$":
     type: object
index c6720764e765c70af73cc0dffc6e837888c74a19..a2884e3113daded85e13b8a218b472bf5c61cf80 100644 (file)
@@ -83,7 +83,7 @@ properties:
       insensitive, letters in the riscv,isa string must be all
       lowercase to simplify parsing.
     $ref: "/schemas/types.yaml#/definitions/string"
-    pattern: ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$
+    pattern: ^rv(?:64|32)imaf?d?q?c?b?k?j?p?v?h?(?:[hsxz](?:[a-z])+)?(?:_[hsxz](?:[a-z])+)*$
 
   # RISC-V requires 'timebase-frequency' in /cpus, so disallow it here
   timebase-frequency: false
index 0a7aa29563c1c86d90aa31425beb4ba27963fc23..21c8ea08ff0a226c5d6a5d71dc4f3c64eb95f5b7 100644 (file)
@@ -40,6 +40,8 @@ properties:
     description:
       Indicates that the setting of RTC time is allowed by the host CPU.
 
+  wakeup-source: true
+
 required:
   - compatible
   - reg
index 290555426c39ca90ebeb087cce514f51c4cc92ff..bdf482db32aac1fc84f42aa9b72cf6d64c798933 100644 (file)
@@ -39,8 +39,8 @@ properties:
   qcom,protection-domain:
     $ref: /schemas/types.yaml#/definitions/string-array
     description: |
-      Protection domain service name and path for APR service
-      possible values are::
+      Protection domain service name and path for APR service (if supported).
+      Possible values are::
       "avs/audio", "msm/adsp/audio_pd".
       "kernel/elf_loader", "msm/modem/wlan_pd".
       "tms/servreg", "msm/adsp/audio_pd".
@@ -49,6 +49,5 @@ properties:
 
 required:
   - reg
-  - qcom,protection-domain
 
 additionalProperties: true
index 067fd1670b1f1d6937d214f33309c4fc55e29923..a43aacf1494e778585aea093fb4c099dc4459be7 100644 (file)
@@ -120,6 +120,8 @@ dax={always,never}     Use direct access (no page cache).  See
 dax                    A legacy option which is an alias for ``dax=always``.
 device=%s              Specify a path to an extra device to be used together.
 fsid=%s                Specify a filesystem image ID for Fscache back-end.
+domain_id=%s           Specify a domain ID in fscache mode so that different images
+                       with the same blobs under a given domain ID can share storage.
 ===================    =========================================================
 
 Sysfs Entries
index 6b7368d1f51639c016e4be5f4c3c4f51b0f29991..38bc74eaa547403935a2ae645cb0ec875a1a0279 100644 (file)
@@ -1042,7 +1042,7 @@ $(clean-files).
 
 When executing "make clean", the file "crc32table.h" will be deleted.
 Kbuild will assume files to be in the same relative directory as the
-Makefile, except if prefixed with $(objtree).
+Makefile.
 
 To exclude certain files or directories from make clean, use the
 $(no-clean-files) variable.
index 4aef9cddde2fd68bf75a1ec8c3453ad6cb88237c..c859f3c1636edfa30a4f2cde792608fb949a58b3 100644 (file)
@@ -8,7 +8,7 @@ In order to use the Ethernet bridging functionality, you'll need the
 userspace tools.
 
 Documentation for Linux bridging is on:
-   http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
+   https://wiki.linuxfoundation.org/networking/bridge
 
 The bridge-utilities are maintained at:
    git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/bridge-utils.git
index dc2e60ced927c378b4c91b1eadb52085e5c7d46e..b481b81f3be5ba6ee35af1e46ce3f44589efa22a 100644 (file)
@@ -819,7 +819,7 @@ NAPI
 ----
 This driver supports NAPI (Rx polling mode).
 For more information on NAPI, see
-https://www.linuxfoundation.org/collaborate/workgroups/networking/napi
+https://wiki.linuxfoundation.org/networking/napi
 
 
 MACVLAN
index 49db1d11d7c4a8788f5068e4ac97a420202044f7..8b1045c3b59e0ef0675d0ed113139b4e84b8b81d 100644 (file)
@@ -173,7 +173,9 @@ nf_conntrack_sctp_timeout_cookie_echoed - INTEGER (seconds)
        default 3
 
 nf_conntrack_sctp_timeout_established - INTEGER (seconds)
-       default 432000 (5 days)
+       default 210
+
+       Default is set to (hb_interval * path_max_retrans + rto_max)
 
 nf_conntrack_sctp_timeout_shutdown_sent - INTEGER (seconds)
        default 0.3
@@ -190,12 +192,6 @@ nf_conntrack_sctp_timeout_heartbeat_sent - INTEGER (seconds)
        This timeout is used to setup conntrack entry on secondary paths.
        Default is set to hb_interval.
 
-nf_conntrack_sctp_timeout_heartbeat_acked - INTEGER (seconds)
-       default 210
-
-       This timeout is used to setup conntrack entry on secondary paths.
-       Default is set to (hb_interval * path_max_retrans + rto_max)
-
 nf_conntrack_udp_timeout - INTEGER (seconds)
        default 30
 
index 9807b05a1b57109f1051ac5fb24823cdf13fed12..0a67cb738013e6e2419e17b5ce91e211bf422d30 100644 (file)
@@ -8070,9 +8070,13 @@ considering the state as complete. VMM needs to ensure that the dirty
 state is final and avoid missing dirty pages from another ioctl ordered
 after the bitmap collection.
 
-NOTE: One example of using the backup bitmap is saving arm64 vgic/its
-tables through KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} command on
-KVM device "kvm-arm-vgic-its" when dirty ring is enabled.
+NOTE: Multiple examples of using the backup bitmap: (1) save vgic/its
+tables through command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_SAVE_TABLES} on
+KVM device "kvm-arm-vgic-its". (2) restore vgic/its tables through
+command KVM_DEV_ARM_{VGIC_GRP_CTRL, ITS_RESTORE_TABLES} on KVM device
+"kvm-arm-vgic-its". VGICv3 LPI pending status is restored. (3) save
+vgic3 pending table through KVM_DEV_ARM_VGIC_{GRP_CTRL, SAVE_PENDING_TABLES}
+command on KVM device "kvm-arm-vgic-v3".
 
 8.30 KVM_CAP_XEN_HVM
 --------------------
index a1940ebe7be50cb17260b240a3ce78ec4f6a2242..934310ce7258298008e4c6ba5be611105993e1c1 100644 (file)
@@ -95,3 +95,39 @@ by supplying mem_encrypt=on on the kernel command line.  However, if BIOS does
 not enable SME, then Linux will not be able to activate memory encryption, even
 if configured to do so by default or the mem_encrypt=on command line parameter
 is specified.
+
+Secure Nested Paging (SNP)
+==========================
+
+SEV-SNP introduces new features (SEV_FEATURES[1:63]) which can be enabled
+by the hypervisor for security enhancements. Some of these features need
+guest side implementation to function correctly. The below table lists the
+expected guest behavior with various possible scenarios of guest/hypervisor
+SNP feature support.
+
++-----------------+---------------+---------------+------------------+
+| Feature Enabled | Guest needs   | Guest has     | Guest boot       |
+| by the HV       | implementation| implementation| behaviour        |
++=================+===============+===============+==================+
+|      No         |      No       |      No       |     Boot         |
+|                 |               |               |                  |
++-----------------+---------------+---------------+------------------+
+|      No         |      Yes      |      No       |     Boot         |
+|                 |               |               |                  |
++-----------------+---------------+---------------+------------------+
+|      No         |      Yes      |      Yes      |     Boot         |
+|                 |               |               |                  |
++-----------------+---------------+---------------+------------------+
+|      Yes        |      No       |      No       | Boot with        |
+|                 |               |               | feature enabled  |
++-----------------+---------------+---------------+------------------+
+|      Yes        |      Yes      |      No       | Graceful boot    |
+|                 |               |               | failure          |
++-----------------+---------------+---------------+------------------+
+|      Yes        |      Yes      |      Yes      | Boot with        |
+|                 |               |               | feature enabled  |
++-----------------+---------------+---------------+------------------+
+
+More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR
+
+[1] https://www.amd.com/system/files/TechDocs/40332.pdf
index 42fc47c6edfd7af1485c972a730ffa92c70e839e..cf86459b28605443b53e66451a70d0edb9933928 100644 (file)
@@ -361,6 +361,8 @@ T:  git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 F:     Documentation/ABI/testing/configfs-acpi
 F:     Documentation/ABI/testing/sysfs-bus-acpi
 F:     Documentation/firmware-guide/acpi/
+F:     arch/x86/kernel/acpi/
+F:     arch/x86/pci/acpi.c
 F:     drivers/acpi/
 F:     drivers/pci/*/*acpi*
 F:     drivers/pci/*acpi*
@@ -383,7 +385,7 @@ ACPI COMPONENT ARCHITECTURE (ACPICA)
 M:     Robert Moore <robert.moore@intel.com>
 M:     "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
 L:     linux-acpi@vger.kernel.org
-L:     devel@acpica.org
+L:     acpica-devel@lists.linuxfoundation.org
 S:     Supported
 W:     https://acpica.org/
 W:     https://github.com/acpica/acpica/
@@ -1097,14 +1099,12 @@ S:      Maintained
 F:     drivers/dma/ptdma/
 
 AMD SEATTLE DEVICE TREE SUPPORT
-M:     Brijesh Singh <brijeshkumar.singh@amd.com>
 M:     Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
 M:     Tom Lendacky <thomas.lendacky@amd.com>
 S:     Supported
 F:     arch/arm64/boot/dts/amd/
 
 AMD XGBE DRIVER
-M:     Tom Lendacky <thomas.lendacky@amd.com>
 M:     "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -2213,6 +2213,9 @@ L:        linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
 X:     drivers/media/i2c/
+F:     arch/arm64/boot/dts/freescale/
+X:     arch/arm64/boot/dts/freescale/fsl-*
+X:     arch/arm64/boot/dts/freescale/qoriq-*
 N:     imx
 N:     mxs
 
@@ -2451,11 +2454,14 @@ F:      drivers/rtc/rtc-mt7622.c
 
 ARM/Mediatek SoC support
 M:     Matthias Brugger <matthias.bgg@gmail.com>
+R:     AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+L:     linux-kernel@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 W:     https://mtk.wiki.kernel.org/
-C:     irc://chat.freenode.net/linux-mediatek
+C:     irc://irc.libera.chat/linux-mediatek
+F:     arch/arm/boot/dts/mt2*
 F:     arch/arm/boot/dts/mt6*
 F:     arch/arm/boot/dts/mt7*
 F:     arch/arm/boot/dts/mt8*
@@ -2463,7 +2469,7 @@ F:        arch/arm/mach-mediatek/
 F:     arch/arm64/boot/dts/mediatek/
 F:     drivers/soc/mediatek/
 N:     mtk
-N:     mt[678]
+N:     mt[2678]
 K:     mediatek
 
 ARM/Mediatek USB3 PHY DRIVER
@@ -3767,7 +3773,6 @@ F:        net/bluetooth/
 
 BONDING DRIVER
 M:     Jay Vosburgh <j.vosburgh@gmail.com>
-M:     Veaceslav Falico <vfalico@gmail.com>
 M:     Andy Gospodarek <andy@greyhouse.net>
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -6948,7 +6953,7 @@ F:        drivers/gpu/drm/atmel-hlcdc/
 DRM DRIVERS FOR BRIDGE CHIPS
 M:     Andrzej Hajda <andrzej.hajda@intel.com>
 M:     Neil Armstrong <neil.armstrong@linaro.org>
-M:     Robert Foss <robert.foss@linaro.org>
+M:     Robert Foss <rfoss@kernel.org>
 R:     Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
 R:     Jonas Karlman <jonas@kwiboo.se>
 R:     Jernej Skrabec <jernej.skrabec@gmail.com>
@@ -7616,7 +7621,6 @@ S:        Maintained
 F:     drivers/firmware/efi/test/
 
 EFI VARIABLE FILESYSTEM
-M:     Matthew Garrett <matthew.garrett@nebula.com>
 M:     Jeremy Kerr <jk@ozlabs.org>
 M:     Ard Biesheuvel <ardb@kernel.org>
 L:     linux-efi@vger.kernel.org
@@ -7895,7 +7899,11 @@ F:       include/linux/extcon/
 
 EXTRA BOOT CONFIG
 M:     Masami Hiramatsu <mhiramat@kernel.org>
+L:     linux-kernel@vger.kernel.org
+L:     linux-trace-kernel@vger.kernel.org
+Q:     https://patchwork.kernel.org/project/linux-trace-kernel/list/
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
 F:     Documentation/admin-guide/bootconfig.rst
 F:     fs/proc/bootconfig.c
 F:     include/linux/bootconfig.h
@@ -8468,16 +8476,16 @@ F:      fs/fscache/
 F:     include/linux/fscache*.h
 
 FSCRYPT: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
+M:     Eric Biggers <ebiggers@kernel.org>
 M:     Theodore Y. Ts'o <tytso@mit.edu>
 M:     Jaegeuk Kim <jaegeuk@kernel.org>
-M:     Eric Biggers <ebiggers@kernel.org>
 L:     linux-fscrypt@vger.kernel.org
 S:     Supported
 Q:     https://patchwork.kernel.org/project/linux-fscrypt/list/
-T:     git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git
+T:     git https://git.kernel.org/pub/scm/fs/fscrypt/linux.git
 F:     Documentation/filesystems/fscrypt.rst
 F:     fs/crypto/
-F:     include/linux/fscrypt*.h
+F:     include/linux/fscrypt.h
 F:     include/uapi/linux/fscrypt.h
 
 FSI SUBSYSTEM
@@ -8520,10 +8528,10 @@ F:      include/linux/fsnotify*.h
 FSVERITY: READ-ONLY FILE-BASED AUTHENTICITY PROTECTION
 M:     Eric Biggers <ebiggers@kernel.org>
 M:     Theodore Y. Ts'o <tytso@mit.edu>
-L:     linux-fscrypt@vger.kernel.org
+L:     fsverity@lists.linux.dev
 S:     Supported
-Q:     https://patchwork.kernel.org/project/linux-fscrypt/list/
-T:     git git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git fsverity
+Q:     https://patchwork.kernel.org/project/fsverity/list/
+T:     git https://git.kernel.org/pub/scm/fs/fsverity/linux.git
 F:     Documentation/filesystems/fsverity.rst
 F:     fs/verity/
 F:     include/linux/fsverity.h
@@ -8571,6 +8579,7 @@ F:        kernel/trace/fgraph.c
 F:     arch/*/*/*/*ftrace*
 F:     arch/*/*/*ftrace*
 F:     include/*/ftrace.h
+F:     samples/ftrace
 
 FUNGIBLE ETHERNET DRIVERS
 M:     Dimitris Michailidis <dmichail@fungible.com>
@@ -9299,7 +9308,7 @@ F:        net/dsa/tag_hellcreek.c
 
 HISILICON DMA DRIVER
 M:     Zhou Wang <wangzhou1@hisilicon.com>
-M:     Jie Hai <haijie1@hisilicon.com>
+M:     Jie Hai <haijie1@huawei.com>
 L:     dmaengine@vger.kernel.org
 S:     Maintained
 F:     drivers/dma/hisi_dma.c
@@ -14601,7 +14610,6 @@ F:      tools/testing/selftests/net/ipsec.c
 
 NETWORKING [IPv4/IPv6]
 M:     "David S. Miller" <davem@davemloft.net>
-M:     Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
 M:     David Ahern <dsahern@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -14634,7 +14642,6 @@ F:      net/netfilter/xt_SECMARK.c
 F:     net/netlabel/
 
 NETWORKING [MPTCP]
-M:     Mat Martineau <mathew.j.martineau@linux.intel.com>
 M:     Matthieu Baerts <matthieu.baerts@tessares.net>
 L:     netdev@vger.kernel.org
 L:     mptcp@lists.linux.dev
@@ -15659,7 +15666,7 @@ OPENRISC ARCHITECTURE
 M:     Jonas Bonn <jonas@southpole.se>
 M:     Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
 M:     Stafford Horne <shorne@gmail.com>
-L:     openrisc@lists.librecores.org
+L:     linux-openrisc@vger.kernel.org
 S:     Maintained
 W:     http://openrisc.io
 T:     git https://github.com/openrisc/linux.git
@@ -15750,6 +15757,12 @@ S:     Maintained
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/p54
 F:     drivers/net/wireless/intersil/p54/
 
+PACKET SOCKETS
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+S:     Maintained
+F:     include/uapi/linux/if_packet.h
+F:     net/packet/af_packet.c
+
 PACKING
 M:     Vladimir Oltean <olteanv@gmail.com>
 L:     netdev@vger.kernel.org
@@ -17238,7 +17251,7 @@ F:      Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
 F:     drivers/net/wwan/qcom_bam_dmux.c
 
 QUALCOMM CAMERA SUBSYSTEM DRIVER
-M:     Robert Foss <robert.foss@linaro.org>
+M:     Robert Foss <rfoss@kernel.org>
 M:     Todor Tomov <todor.too@gmail.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
@@ -17318,7 +17331,7 @@ F:      drivers/dma/qcom/hidma*
 
 QUALCOMM I2C CCI DRIVER
 M:     Loic Poulain <loic.poulain@linaro.org>
-M:     Robert Foss <robert.foss@linaro.org>
+M:     Robert Foss <rfoss@kernel.org>
 L:     linux-i2c@vger.kernel.org
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
@@ -17957,6 +17970,7 @@ M:      Albert Ou <aou@eecs.berkeley.edu>
 L:     linux-riscv@lists.infradead.org
 S:     Supported
 Q:     https://patchwork.kernel.org/project/linux-riscv/list/
+C:     irc://irc.libera.chat/riscv
 P:     Documentation/riscv/patch-acceptance.rst
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
 F:     arch/riscv/
@@ -18678,9 +18692,9 @@ F:      drivers/target/
 F:     include/target/
 
 SCTP PROTOCOL
-M:     Vlad Yasevich <vyasevich@gmail.com>
 M:     Neil Horman <nhorman@tuxdriver.com>
 M:     Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+M:     Xin Long <lucien.xin@gmail.com>
 L:     linux-sctp@vger.kernel.org
 S:     Maintained
 W:     http://lksctp.sourceforge.net
@@ -19326,6 +19340,13 @@ L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Orphan
 F:     sound/soc/uniphier/
 
+SOCKET TIMESTAMPING
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+S:     Maintained
+F:     Documentation/networking/timestamping.rst
+F:     include/uapi/linux/net_tstamp.h
+F:     tools/testing/selftests/net/so_txtime.c
+
 SOEKRIS NET48XX LED SUPPORT
 M:     Chris Boot <bootc@bootc.net>
 S:     Maintained
@@ -20086,7 +20107,8 @@ L:      linux-pm@vger.kernel.org
 S:     Supported
 B:     https://bugzilla.kernel.org
 F:     Documentation/power/
-F:     arch/x86/kernel/acpi/
+F:     arch/x86/kernel/acpi/sleep*
+F:     arch/x86/kernel/acpi/wakeup*
 F:     drivers/base/power/
 F:     include/linux/freezer.h
 F:     include/linux/pm.h
@@ -21711,6 +21733,7 @@ F:      include/uapi/linux/uvcvideo.h
 
 USB WEBCAM GADGET
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+M:     Daniel Scally <dan.scally@ideasonboard.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/gadget/function/*uvc*
@@ -21746,6 +21769,13 @@ T:     git git://linuxtv.org/media_tree.git
 F:     Documentation/admin-guide/media/zr364xx*
 F:     drivers/staging/media/deprecated/zr364xx/
 
+USER DATAGRAM PROTOCOL (UDP)
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+S:     Maintained
+F:     include/linux/udp.h
+F:     net/ipv4/udp.c
+F:     net/ipv6/udp.c
+
 USER-MODE LINUX (UML)
 M:     Richard Weinberger <richard@nod.at>
 M:     Anton Ivanov <anton.ivanov@cambridgegreys.com>
index e09fe100efb214524dc04e9bc27f39541a3f2fd5..80afd9fb9f7595851385d2b37312c6e3f88932c5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc7
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
@@ -549,7 +549,7 @@ LDFLAGS_MODULE  =
 CFLAGS_KERNEL  =
 RUSTFLAGS_KERNEL =
 AFLAGS_KERNEL  =
-export LDFLAGS_vmlinux =
+LDFLAGS_vmlinux =
 
 # Use USERINCLUDE when you must reference the UAPI directories only.
 USERINCLUDE    := \
@@ -1248,6 +1248,18 @@ vmlinux.o modules.builtin.modinfo modules.builtin: vmlinux_o
        @:
 
 PHONY += vmlinux
+# LDFLAGS_vmlinux in the top Makefile defines linker flags for the top vmlinux,
+# not for decompressors. LDFLAGS_vmlinux in arch/*/boot/compressed/Makefile is
+# unrelated; the decompressors just happen to have the same base name,
+# arch/*/boot/compressed/vmlinux.
+# Export LDFLAGS_vmlinux only to scripts/Makefile.vmlinux.
+#
+# _LDFLAGS_vmlinux is a workaround for the 'private export' bug:
+#   https://savannah.gnu.org/bugs/?61463
+# For Make > 4.4, the following simple code will work:
+#  vmlinux: private export LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
+vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
+vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
 vmlinux: vmlinux.o $(KBUILD_LDS) modpost
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux
 
@@ -1533,6 +1545,7 @@ endif
 # *.ko are usually independent of vmlinux, but CONFIG_DEBUG_INFOBTF_MODULES
 # is an exception.
 ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+KBUILD_BUILTIN := 1
 modules: vmlinux
 endif
 
index 4067f5169144246b22e96e734d9af369a32b1e45..955b0362cdfb7a4736a901a7cc63a8c7a289f95f 100644 (file)
@@ -132,7 +132,7 @@ AFLAGS_NOWARN       :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
 
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
 CFLAGS_ISA     :=-Wa,-mimplicit-it=always $(AFLAGS_NOWARN)
-AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb -D__thumb2__=2
+AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
 CFLAGS_ISA     +=-mthumb
 else
 CFLAGS_ISA     :=$(call cc-option,-marm,) $(AFLAGS_NOWARN)
index 12933eff419ff877366f804e0488b666a5121230..446861b6b17b2ae628a42a4a32dca94a0b5b1f21 100644 (file)
                        };
 
                        gpio0: gpio@18100 {
-                               compatible = "marvell,armadaxp-gpio",
+                               compatible = "marvell,armada-370-gpio",
                                             "marvell,orion-gpio";
                                reg = <0x18100 0x40>, <0x181c0 0x08>;
                                reg-names = "gpio", "pwm";
                        };
 
                        gpio1: gpio@18140 {
-                               compatible = "marvell,armadaxp-gpio",
+                               compatible = "marvell,armada-370-gpio",
                                             "marvell,orion-gpio";
                                reg = <0x18140 0x40>, <0x181c8 0x08>;
                                reg-names = "gpio", "pwm";
index 1e05208d9f3415f3ee5cd72084a69bf4460d9f8c..9d1cac49c022f07c315efabc57c5f08158c2833a 100644 (file)
                        };
 
                        gpio0: gpio@18100 {
-                               compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio";
+                               compatible = "marvell,orion-gpio";
                                reg = <0x18100 0x40>;
                                ngpios = <32>;
                                gpio-controller;
                        };
 
                        gpio1: gpio@18140 {
-                               compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio";
+                               compatible = "marvell,orion-gpio";
                                reg = <0x18140 0x40>;
                                ngpios = <28>;
                                gpio-controller;
index d1971ddf06a5d4e18b2e80dffe2b8fb4c7bce8b1..7f755e5a4624df2b3a85966b3a0bd269478b6c9a 100644 (file)
        };
 
        pca9849@75 {
-               compatible = "nxp,pca849";
+               compatible = "nxp,pca9849";
                reg = <0x75>;
                #address-cells = <1>;
                #size-cells = <0>;
index 37d0cffea99c56ec7e47bd817fe99eb366fc8375..70c4a4852256c4ef2321e25b878eb3b01e2780df 100644 (file)
        scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
        status = "okay";
 
-       i2c-switch@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9547";
                #address-cells = <1>;
                #size-cells = <0>;
index 4bc4371e6bae56e02ee910b98f0f03656a3b4441..4b81a975c979ded3024fdb87d984a29490ebdc96 100644 (file)
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1>;
-       uart-has-rtscts;
        rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
index 162dc259edc8c5cb0c14b5c2b7dd9b948c861b61..5a74c7f68eb62dbf03b1af91a3b83241b5137717 100644 (file)
@@ -32,7 +32,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 5162fe227d1ea3eedd035577970f01ce70e69f54..fdc10563f1473eed1f9cd7aaec7d7c59820db1f1 100644 (file)
@@ -32,7 +32,7 @@
 };
 
 &i2c1 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
@@ -52,7 +52,7 @@
 };
 
 &i2c4 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
index 104a85254adbbd8688f5294205e08b6250972bca..5afb1674e012518add059d5936fd438977c5a7e8 100644 (file)
@@ -43,7 +43,7 @@
 };
 
 &i2c1 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
@@ -64,7 +64,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 546268b8d0b13b665d71fdfcf76a0e01e31b9ce4..c0f00f5db11e15004405675494eb5a1ed46262f8 100644 (file)
 &usbotg2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usbotg2>;
+       over-current-active-low;
        dr_mode = "host";
        status = "okay";
 };
 
        pinctrl_usbotg2: usbotg2grp {
                fsl,pins = <
-                       MX7D_PAD_UART3_RTS_B__USB_OTG2_OC       0x04
+                       MX7D_PAD_UART3_RTS_B__USB_OTG2_OC       0x5c
                >;
        };
 
index b637241316bb4314ea6237fb8daef69124f4dd3b..fd671c7a1e5d64c6eafb0a7434c7d14b19f4d1b6 100644 (file)
                        reg = <0xc8000000 0x1000>, <0xc0000000 0x4000000>;
                        reg-names = "control", "memory";
                        clocks = <&clk 0>;
+                       nuvoton,shm = <&shm>;
                        status = "disabled";
                };
 
index 44cd72f1b1be4795e391d63c5088d8f00b54fa92..116e59a3b76d01e54306ced831dfbc2019b05754 100644 (file)
                serial@f995e000 {
                        status = "okay";
                };
+       };
+};
 
-               sdhci@f9824900 {
-                       bus-width = <8>;
-                       non-removable;
-                       status = "okay";
-               };
+&sdhc_1 {
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
+};
 
-               sdhci@f98a4900 {
-                       cd-gpios = <&tlmm 122 GPIO_ACTIVE_LOW>;
-                       bus-width = <4>;
-               };
-       };
+&sdhc_2 {
+       cd-gpios = <&tlmm 122 GPIO_ACTIVE_LOW>;
+       bus-width = <4>;
 };
index fe30abfff90a77d10f51ca48105da0bbb7ca5944..4b0d2b4f4b6a9017352eb0b847126c3b723151d2 100644 (file)
                        status = "disabled";
                };
 
-               mmc@f9824900 {
+               sdhc_1: mmc@f9824900 {
                        compatible = "qcom,apq8084-sdhci", "qcom,sdhci-msm-v4";
                        reg = <0xf9824900 0x11c>, <0xf9824000 0x800>;
                        reg-names = "hc", "core";
                        status = "disabled";
                };
 
-               mmc@f98a4900 {
+               sdhc_2: mmc@f98a4900 {
                        compatible = "qcom,apq8084-sdhci", "qcom,sdhci-msm-v4";
                        reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>;
                        reg-names = "hc", "core";
index 8f5477e307dd49e444d66289663f03048b59b5e2..37a5d96aaf6421a854b96a7d04efc1b54bd11254 100644 (file)
                        mpddrc: mpddrc@ffffe800 {
                                compatible = "microchip,sam9x60-ddramc", "atmel,sama5d3-ddramc";
                                reg = <0xffffe800 0x200>;
-                               clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_CORE PMC_MCK>;
+                               clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_PERIPHERAL 49>;
                                clock-names = "ddrck", "mpddr";
                        };
 
index d865ab5d866b93bf16eac00e33080cecf40041cc..dd23de85100c483386d35307fc93f1e03c987982 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
        #address-cells = <1>;
        #size-cells = <0>;
index aef02e6421a36ddf93a975b0798fb92c4326b5d1..7d11c50b9e4087afa226adc052449c3a38b3dd6e 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
        #address-cells = <1>;
        #size-cells = <0>;
index 002f221f1694c79c70aba0d9d9e120c006de0a64..c06edd2eacb0cd3f35850f0247bda1dedab4f718 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
        #address-cells = <1>;
        #size-cells = <0>;
index 134a798ad3f23f628e8673fadaf58b777cf64e41..bb40fb46da81d559084f680c11c5c072efa83073 100644 (file)
 
 &qspi {
        pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
-       pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>;
+       pinctrl-0 = <&qspi_clk_pins_a
+                    &qspi_bk1_pins_a
+                    &qspi_cs1_pins_a>;
+       pinctrl-1 = <&qspi_clk_sleep_pins_a
+                    &qspi_bk1_sleep_pins_a
+                    &qspi_cs1_sleep_pins_a>;
        reg = <0x58003000 0x1000>, <0x70000000 0x200000>;
        #address-cells = <1>;
        #size-cells = <0>;
index 42ed4a04a12e250b3e4d3421d221658397560ead..6280c5e86a124e2f1547a2a7b74f7f4628db878d 100644 (file)
 };
 
 &i2c2 {
-       tca9548@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9548";
                pinctrl-0 = <&pinctrl_i2c_mux_reset>;
                pinctrl-names = "default";
index f892977da9e4e0311fd1e3dda5308a8b2811a2f6..c00d39562a10bb9487785b8f77f5fb181fc0cb90 100644 (file)
 };
 
 &i2c2 {
-       tca9548@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9548";
                pinctrl-0 = <&pinctrl_i2c_mux_reset>;
                pinctrl-names = "default";
index 971e74546fb1bf31d6c25f3c74a326b3a51a0e2a..13e62c7c25dca8e103527f776f9fb094b7b350e7 100644 (file)
@@ -53,7 +53,12 @@ $(obj)/%-core.S: $(src)/%-armv4.pl
 
 clean-files += poly1305-core.S sha256-core.S sha512-core.S
 
+aflags-thumb2-$(CONFIG_THUMB2_KERNEL)  := -U__thumb2__ -D__thumb2__=1
+
+AFLAGS_sha256-core.o += $(aflags-thumb2-y)
+AFLAGS_sha512-core.o += $(aflags-thumb2-y)
+
 # massage the perlasm code a bit so we only get the NEON routine if we need it
 poly1305-aflags-$(CONFIG_CPU_V7) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=5
 poly1305-aflags-$(CONFIG_KERNEL_MODE_NEON) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=7
-AFLAGS_poly1305-core.o += $(poly1305-aflags-y)
+AFLAGS_poly1305-core.o += $(poly1305-aflags-y) $(aflags-thumb2-y)
index b8f741a3a37ea02cee2558f951eb9bf297936168..237b828dd2f10a7d99f910edb262e14e90c3e050 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
 #include <linux/io.h>
 
 #include "common.h"
index 3e63445cde062e08b68865707689da1f9f09b0c1..cc86977d0a3407aa13a8068a91eaebd436e997df 100644 (file)
@@ -23,6 +23,7 @@ static int mx25_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx25-iim");
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!iim_base);
        rev = readl(iim_base + MXC_IIMSREV);
        iounmap(iim_base);
index bf70e13bbe9ee0ad41155a407006becf8f51d9f2..1d2893908368380499119e4ab30d955c32245053 100644 (file)
@@ -28,6 +28,7 @@ static int mx27_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
        ccm_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!ccm_base);
        /*
         * now we have access to the IO registers. As we need
index b9c24b851d1abd1fd18a7e30199b048335addc85..35c544924e509593759a1f59abca62173bea1c1b 100644 (file)
@@ -39,6 +39,7 @@ static int mx31_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx31-iim");
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!iim_base);
 
        /* read SREV register from IIM module */
index 80e7d8ab9f1bb81ad4a70fb8805a45bb170ff01f..1fe75b39c2d995d2aeca9ff923f561e0ba3c8bbd 100644 (file)
@@ -21,6 +21,7 @@ static int mx35_read_cpu_rev(void)
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx35-iim");
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        BUG_ON(!iim_base);
 
        rev = imx_readl(iim_base + MXC_IIMSREV);
index ad56263778f936d2e1f0f9a2e6a548b201da7d1a..a67c89bf155dd3723a7406caac6ed3bf82ad0f98 100644 (file)
@@ -28,6 +28,7 @@ static u32 imx5_read_srev_reg(const char *compat)
 
        np = of_find_compatible_node(NULL, NULL, compat);
        iim_base = of_iomap(np, 0);
+       of_node_put(np);
        WARN_ON(!iim_base);
 
        srev = readl(iim_base + IIM_SREV) & 0xff;
index 538a960257cc70602f59ee7a07215d7adb838e10..7ec7ada287e050692ee7421a87a1c3b7865cd8c9 100644 (file)
@@ -4,6 +4,7 @@ menuconfig ARCH_OMAP1
        depends on ARCH_MULTI_V4T || ARCH_MULTI_V5
        depends on CPU_LITTLE_ENDIAN
        depends on ATAGS
+       select ARCH_OMAP
        select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_OMAP
        select CLKSRC_MMIO
@@ -45,10 +46,6 @@ config ARCH_OMAP16XX
        select CPU_ARM926T
        select OMAP_DM_TIMER
 
-config ARCH_OMAP1_ANY
-       select ARCH_OMAP
-       def_bool ARCH_OMAP730 || ARCH_OMAP850 || ARCH_OMAP15XX || ARCH_OMAP16XX
-
 config ARCH_OMAP
        bool
 
index 506074b86333fd67d0a705378eea2eab89a4b8b3..0615cb0ba580b03b57c78887dcf24e02e37b0e85 100644 (file)
@@ -3,8 +3,6 @@
 # Makefile for the linux kernel.
 #
 
-ifdef CONFIG_ARCH_OMAP1_ANY
-
 # Common support
 obj-y := io.o id.o sram-init.o sram.o time.o irq.o mux.o flash.o \
         serial.o devices.o dma.o omap-dma.o fb.o
@@ -59,5 +57,3 @@ obj-$(CONFIG_ARCH_OMAP730)            += gpio7xx.o
 obj-$(CONFIG_ARCH_OMAP850)             += gpio7xx.o
 obj-$(CONFIG_ARCH_OMAP15XX)            += gpio15xx.o
 obj-$(CONFIG_ARCH_OMAP16XX)            += gpio16xx.o
-
-endif
index c675f11de99dbdf5e30da119bcc53098e18a5f6d..61fa26efd865340312e12b6fc914c85fbcb6df17 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/soc/ti/omap1-soc.h>
+#include <asm/irq.h>
 
 #include "irqs.h"
 
index d2db9b8aed3fb016b6cbecda12a0ace8c351bf13..0074b011a05a46b34c56ddc0a72e301c9b602aef 100644 (file)
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
  */
-static struct map_desc omap_io_desc[] __initdata = {
+#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
+static struct map_desc omap7xx_io_desc[] __initdata = {
        {
                .virtual        = OMAP1_IO_VIRT,
                .pfn            = __phys_to_pfn(OMAP1_IO_PHYS),
                .length         = OMAP1_IO_SIZE,
                .type           = MT_DEVICE
-       }
-};
-
-#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
-static struct map_desc omap7xx_io_desc[] __initdata = {
+       },
        {
                .virtual        = OMAP7XX_DSP_BASE,
                .pfn            = __phys_to_pfn(OMAP7XX_DSP_START),
@@ -49,6 +46,12 @@ static struct map_desc omap7xx_io_desc[] __initdata = {
 
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct map_desc omap1510_io_desc[] __initdata = {
+       {
+               .virtual        = OMAP1_IO_VIRT,
+               .pfn            = __phys_to_pfn(OMAP1_IO_PHYS),
+               .length         = OMAP1_IO_SIZE,
+               .type           = MT_DEVICE
+       },
        {
                .virtual        = OMAP1510_DSP_BASE,
                .pfn            = __phys_to_pfn(OMAP1510_DSP_START),
@@ -65,6 +68,12 @@ static struct map_desc omap1510_io_desc[] __initdata = {
 
 #if defined(CONFIG_ARCH_OMAP16XX)
 static struct map_desc omap16xx_io_desc[] __initdata = {
+       {
+               .virtual        = OMAP1_IO_VIRT,
+               .pfn            = __phys_to_pfn(OMAP1_IO_PHYS),
+               .length         = OMAP1_IO_SIZE,
+               .type           = MT_DEVICE
+       },
        {
                .virtual        = OMAP16XX_DSP_BASE,
                .pfn            = __phys_to_pfn(OMAP16XX_DSP_START),
@@ -79,18 +88,9 @@ static struct map_desc omap16xx_io_desc[] __initdata = {
 };
 #endif
 
-/*
- * Maps common IO regions for omap1
- */
-static void __init omap1_map_common_io(void)
-{
-       iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
-}
-
 #if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
 void __init omap7xx_map_io(void)
 {
-       omap1_map_common_io();
        iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
 }
 #endif
@@ -98,7 +98,6 @@ void __init omap7xx_map_io(void)
 #ifdef CONFIG_ARCH_OMAP15XX
 void __init omap15xx_map_io(void)
 {
-       omap1_map_common_io();
        iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 }
 #endif
@@ -106,7 +105,6 @@ void __init omap15xx_map_io(void)
 #if defined(CONFIG_ARCH_OMAP16XX)
 void __init omap16xx_map_io(void)
 {
-       omap1_map_common_io();
        iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
 }
 #endif
index 05c25c432449fd8f2a0f609ae644d16aecf3e379..b1632cbe37e6f93d327ad79cbba1c62ce6687d86 100644 (file)
@@ -89,7 +89,6 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 #define OMAP1610_MCBSP2_BASE   0xfffb1000
 #define OMAP1610_MCBSP3_BASE   0xe1017000
 
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 struct resource omap7xx_mcbsp_res[][6] = {
        {
                {
@@ -159,14 +158,7 @@ static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
 };
 #define OMAP7XX_MCBSP_RES_SZ           ARRAY_SIZE(omap7xx_mcbsp_res[1])
 #define OMAP7XX_MCBSP_COUNT            ARRAY_SIZE(omap7xx_mcbsp_res)
-#else
-#define omap7xx_mcbsp_res_0            NULL
-#define omap7xx_mcbsp_pdata            NULL
-#define OMAP7XX_MCBSP_RES_SZ           0
-#define OMAP7XX_MCBSP_COUNT            0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP15XX
 struct resource omap15xx_mcbsp_res[][6] = {
        {
                {
@@ -266,14 +258,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 };
 #define OMAP15XX_MCBSP_RES_SZ          ARRAY_SIZE(omap15xx_mcbsp_res[1])
 #define OMAP15XX_MCBSP_COUNT           ARRAY_SIZE(omap15xx_mcbsp_res)
-#else
-#define omap15xx_mcbsp_res_0           NULL
-#define omap15xx_mcbsp_pdata           NULL
-#define OMAP15XX_MCBSP_RES_SZ          0
-#define OMAP15XX_MCBSP_COUNT           0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP16XX
 struct resource omap16xx_mcbsp_res[][6] = {
        {
                {
@@ -373,12 +358,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 };
 #define OMAP16XX_MCBSP_RES_SZ          ARRAY_SIZE(omap16xx_mcbsp_res[1])
 #define OMAP16XX_MCBSP_COUNT           ARRAY_SIZE(omap16xx_mcbsp_res)
-#else
-#define omap16xx_mcbsp_res_0           NULL
-#define omap16xx_mcbsp_pdata           NULL
-#define OMAP16XX_MCBSP_RES_SZ          0
-#define OMAP16XX_MCBSP_COUNT           0
-#endif
 
 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
                        struct omap_mcbsp_platform_data *config, int size)
index d9165709c532388316d2a351a2dc9c9f02b6da95..0d1f092821ff8ff7a8c0a57c759db31879b2c9b0 100644 (file)
 #define OMAP7XX_IDLECT3                0xfffece24
 #define OMAP7XX_IDLE_LOOP_REQUEST      0x0C00
 
-#if     !defined(CONFIG_ARCH_OMAP730) && \
-       !defined(CONFIG_ARCH_OMAP850) && \
-       !defined(CONFIG_ARCH_OMAP15XX) && \
-       !defined(CONFIG_ARCH_OMAP16XX)
-#warning "Power management for this processor not implemented yet"
-#endif
-
 #ifndef __ASSEMBLER__
 
 #include <linux/clk.h>
index b90d98bae68d74b12eac0eba44f9fc49c1df6871..03e25af6f48c97ff4db9b06063836de3b82ce206 100644 (file)
@@ -45,6 +45,8 @@ config MACH_PXA27X_DT
 config MACH_PXA3XX_DT
        bool "Support PXA3xx platforms from device tree"
        select CPU_PXA300
+       select CPU_PXA310
+       select CPU_PXA320
        select PINCTRL
        select POWER_SUPPLY
        select PXA3xx
index c1494a4dee25b535f9153be56050520eb6c3521b..53f2d8774fdb9aaaeb04fe818da08ccfc0bc4803 100644 (file)
@@ -161,7 +161,7 @@ void __init paging_init(const struct machine_desc *mdesc)
        mpu_setup();
 
        /* allocate the zero page. */
-       zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+       zero_page = (void *)memblock_alloc(PAGE_SIZE, PAGE_SIZE);
        if (!zero_page)
                panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
                      __func__, PAGE_SIZE, PAGE_SIZE);
index fa6999e24b074a16ca69ac53cedcf1d583f04893..e43f6d716b4b877bff461385a940cff9957a3a6f 100644 (file)
@@ -6,6 +6,7 @@
  *  VM_EXEC
  */
 #include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
 #include <asm/thread_info.h>
 
 #ifdef CONFIG_CPU_V7M
index e3486f60645a41726e6c9594986e363e02ded05c..a1f0c38ccaddad76baad2efd7e7865830f737c38 100644 (file)
 };
 
 &usb {
-       phys = <&usb2_phy1>;
-       phy-names = "usb2-phy1";
-};
-
-&usb2_phy0 {
-       status = "disabled";
+       phys = <&usb2_phy0>, <&usb2_phy1>;
+       phy-names = "usb2-phy0", "usb2-phy1";
 };
index 5a8d85a7d1612d44ce0fcc3ffeb31e731f50a811..bbdf989058ff7795f3ba514d667630f514bc8b53 100644 (file)
 &i2c0 {
        status = "okay";
 
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 9b726c2a4842671a5a8cdb0db49e1c5eccdf5c2d..dda27ed7aaf2b15cda135c5c1b3e9a4e8f4cdaff 100644 (file)
@@ -89,7 +89,7 @@
 &i2c0 {
        status = "okay";
 
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index b2fcbba60d3accdf03ef8fe51d7de98e6f0818a8..3b0ed9305f2bd4558d9c51d64ce40b421797997d 100644 (file)
@@ -88,7 +88,7 @@
 &i2c0 {
        status = "okay";
 
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 41d8b15f25a540ba087e70d67558932768404d81..aa52ff73ff9e027208a2e1df6ef1c5937edd4c02 100644 (file)
@@ -53,7 +53,7 @@
 &i2c0 {
        status = "okay";
 
-       i2c-switch@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 1bfbce69cc8b77bb5cb25680cc3d57baf9cfe5a8..ee8e932628d17f1928a5bed57bbb871566ed291d 100644 (file)
 &i2c0 {
        status = "okay";
 
-       i2c-switch@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index ef6c8967533efa45216dde21fe07063507d5b2fb..d4867d6cf47cdc79a8a8ebf507b96e7e0683717d 100644 (file)
 &i2c3 {
        status = "okay";
 
-       i2c-switch@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9540";
                #address-cells = <1>;
                #size-cells = <0>;
index f598669e742fc940d444683f0ecaba5235e65331..52c5a43b30a0fb22b4c1f43fe7a7af0b30a68daf 100644 (file)
 
 &i2c0 {
        status = "okay";
-       pca9547@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
index 3d9647b3da14731420f72c4678aae20b3aedf5eb..537cecb13dd08a0fc997c42563feda7326f3757c 100644 (file)
@@ -44,7 +44,7 @@
 
 &i2c0 {
        status = "okay";
-       pca9547@75 {
+       i2c-mux@75 {
                compatible = "nxp,pca9547";
                reg = <0x75>;
                #address-cells = <1>;
index afb455210bd07ed68319890c6fed3549d63f38e7..d32a52ab00a42a28fdb339f1805ae722ed759a04 100644 (file)
@@ -54,7 +54,7 @@
 &i2c0 {
        status = "okay";
 
-       i2c-switch@77 {
+       i2c-mux@77 {
                compatible = "nxp,pca9547";
                #address-cells = <1>;
                #size-cells = <0>;
index 0c64b919462125c65cf81ba1d323f1e996c55436..214f21bd0cb49e04461be973e2a1d42e4a9e77eb 100644 (file)
 
                sc_pwrkey: keys {
                        compatible = "fsl,imx8qxp-sc-key", "fsl,imx-sc-key";
-                       linux,keycode = <KEY_POWER>;
+                       linux,keycodes = <KEY_POWER>;
                        wakeup-source;
                };
 
index 03266bd90a06baa86204491021f6b08a9806a3c8..169f047fbca50e5d443f12a5f46412a9b18d30d7 100644 (file)
 &ecspi2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_espi2>;
-       cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+       cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
        status = "okay";
 
        eeprom@0 {
                        MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK            0x82
                        MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI            0x82
                        MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO            0x82
-                       MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9               0x41
+                       MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13              0x41
                >;
        };
 
index 24f61db33eba2a7b0f14adc55e87466a0dae0213..9889319d4f04530fa30dbce4e9e190e7c3679009 100644 (file)
@@ -88,6 +88,7 @@
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_watchdog_gpio>;
                compatible = "linux,wdt-gpio";
+               always-running;
                gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
                hw_algo = "level";
                /* Reset triggers in 2..3 seconds */
                compatible = "rohm,bd71847";
                reg = <0x4b>;
                #clock-cells = <0>;
-               clocks = <&clk_xtal32k 0>;
+               clocks = <&clk_xtal32k>;
                clock-output-names = "clk-32k-out";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pmic>;
index 74c09891600f2525928321e13dbae633a9517560..6357078185eddb44d64d4ce0cbb4b89231a55111 100644 (file)
        pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 
-       i2cmux@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9540";
                reg = <0x70>;
                #address-cells = <1>;
index 83c8f715cd9019065285345b10aa4572c7f5aad1..b1f11098d248ed5fc8ac42daed808beebe3bf7bc 100644 (file)
 #define MX8MM_IOMUXC_UART1_RXD_GPIO5_IO22                                   0x234 0x49C 0x000 0x5 0x0
 #define MX8MM_IOMUXC_UART1_RXD_TPSMP_HDATA24                                0x234 0x49C 0x000 0x7 0x0
 #define MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX                                 0x238 0x4A0 0x000 0x0 0x0
-#define MX8MM_IOMUXC_UART1_TXD_UART1_DTE_RX                                 0x238 0x4A0 0x4F4 0x0 0x0
+#define MX8MM_IOMUXC_UART1_TXD_UART1_DTE_RX                                 0x238 0x4A0 0x4F4 0x0 0x1
 #define MX8MM_IOMUXC_UART1_TXD_ECSPI3_MOSI                                  0x238 0x4A0 0x000 0x1 0x0
 #define MX8MM_IOMUXC_UART1_TXD_GPIO5_IO23                                   0x238 0x4A0 0x000 0x5 0x0
 #define MX8MM_IOMUXC_UART1_TXD_TPSMP_HDATA25                                0x238 0x4A0 0x000 0x7 0x0
index 3ea73a6886ff405b6e49fc0fb939064ed3abf7f3..f6ad1a4b8b6659f2b71c50a76ac572002bcbe0cd 100644 (file)
@@ -33,7 +33,6 @@
        pinctrl-0 = <&pinctrl_uart2>;
        rts-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
        cts-gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
index 2fa635e1c1a82a86db699129f2437f98b5d89654..1f8ea20dfafcb970b284bdd875292c1ef1ac92e5 100644 (file)
@@ -33,7 +33,6 @@
        pinctrl-0 = <&pinctrl_uart2>;
        rts-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
        cts-gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
index 244ef8d6cc688ccd0211820df60bf65e4b1320ce..7761d5671cb133f23358f11f489699015635c8ca 100644 (file)
        pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_bten>;
        cts-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
        rts-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 
        bluetooth {
index 750a1f07ecb7a67ff17b4dc69a11e5d5424ad1b3..64b366e83fa14f5eae76540ba412625ebd16c877 100644 (file)
        dtr-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
        dsr-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
        dcd-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
        pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
        cts-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
        rts-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
        pinctrl-0 = <&pinctrl_uart4>, <&pinctrl_uart4_gpio>;
        cts-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
        rts-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
 &usbotg2 {
        dr_mode = "host";
        vbus-supply = <&reg_usb2_vbus>;
+       over-current-active-low;
        status = "okay";
 };
 
index 32872b0b1aaf33c30ce1eb1e24cd58eedcc50017..e8bc1fccc47be50c56b2a0d29f0335af41b14d40 100644 (file)
        pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart1_gpio>;
        rts-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
        cts-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
        pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
        rts-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
        cts-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 
        bluetooth {
        dtr-gpios = <&gpio4 3 GPIO_ACTIVE_LOW>;
        dsr-gpios = <&gpio4 4 GPIO_ACTIVE_LOW>;
        dcd-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
index 8ce562246a08ecfbb4d2fabf96520f43993998cd..acc2ba8e00a880be86944bd5e9eff63915c0924d 100644 (file)
        dtr-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
        dsr-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
        dcd-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 };
 
index c2a5c2f7b204b9f41f193375201b996b38e5c1c1..7c3f5c54f04006a0284ce206a9f48ab3743073c7 100644 (file)
@@ -9,6 +9,7 @@
                simple-audio-card,bitclock-master = <&dailink_master>;
                simple-audio-card,format = "i2s";
                simple-audio-card,frame-master = <&dailink_master>;
+               simple-audio-card,mclk-fs = <256>;
                simple-audio-card,name = "imx8mm-wm8904";
                simple-audio-card,routing =
                        "Headphone Jack", "HPOUTL",
index 73cc3fafa01808bb49ffb51a6eb8f7debb7e162e..b2bcd22821702073ae513e394ddb1422bb9d7514 100644 (file)
@@ -11,6 +11,7 @@
                simple-audio-card,bitclock-master = <&dailink_master>;
                simple-audio-card,format = "i2s";
                simple-audio-card,frame-master = <&dailink_master>;
+               simple-audio-card,mclk-fs = <256>;
                simple-audio-card,name = "imx8mm-nau8822";
                simple-audio-card,routing =
                        "Headphones", "LHP",
index 0d454e0e2f7c8b2f24f5d789e328eeb98b5b5321..702d87621bb43daa09d0a460cea65d51aa19e23b 100644 (file)
@@ -98,6 +98,7 @@
                off-on-delay = <500000>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_reg_eth>;
+               regulator-always-on;
                regulator-boot-on;
                regulator-max-microvolt = <3300000>;
                regulator-min-microvolt = <3300000>;
index b9444e4a3d2d6fec4b6ab03437e2db8b83215d19..7c12518dbc96371ce1eeefb6238455322f8da247 100644 (file)
        pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
        rts-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
        cts-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 
        bluetooth {
index d4c7ca16abd057cc6bc6ff45de0404c9d51d5bae..f2d93437084be815a14c764f7f327ff975cf37df 100644 (file)
@@ -36,8 +36,8 @@
 
        pcie0_refclk: pcie0-refclk {
                compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <100000000>;
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
        };
 
        reg_can1_stby: regulator-can1-stby {
index 79b290a002c19e8b201921247c73967a1d860bb4..ecc4bce6db97c0b5a8672c57bd4709337a347bf3 100644 (file)
@@ -99,7 +99,6 @@
 
                regulators {
                        buck1: BUCK1 {
-                               regulator-compatible = "BUCK1";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <2187500>;
                                regulator-boot-on;
                        };
 
                        buck2: BUCK2 {
-                               regulator-compatible = "BUCK2";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <2187500>;
                                regulator-boot-on;
                        };
 
                        buck4: BUCK4 {
-                               regulator-compatible = "BUCK4";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <3400000>;
                                regulator-boot-on;
                        };
 
                        buck5: BUCK5 {
-                               regulator-compatible = "BUCK5";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <3400000>;
                                regulator-boot-on;
                        };
 
                        buck6: BUCK6 {
-                               regulator-compatible = "BUCK6";
                                regulator-min-microvolt = <600000>;
                                regulator-max-microvolt = <3400000>;
                                regulator-boot-on;
                        };
 
                        ldo1: LDO1 {
-                               regulator-compatible = "LDO1";
                                regulator-min-microvolt = <1600000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                        };
 
                        ldo2: LDO2 {
-                               regulator-compatible = "LDO2";
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <1150000>;
                                regulator-boot-on;
                        };
 
                        ldo3: LDO3 {
-                               regulator-compatible = "LDO3";
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                        };
 
                        ldo4: LDO4 {
-                               regulator-compatible = "LDO4";
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
                        ldo5: LDO5 {
-                               regulator-compatible = "LDO5";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
index ceeca4966fc5c8a06694f38527691b2564f409db..8eb7d5ee38daacdee61a650a9a02592fe5c07a5e 100644 (file)
        pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
        cts-gpios = <&gpio3 21 GPIO_ACTIVE_LOW>;
        rts-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
-       uart-has-rtscts;
        status = "okay";
 
        bluetooth {
index 7a6e6221f4219cb87624e567f9578b1804366e64..03034b439c1f79ed7ea1a3094f0a0c42f8369297 100644 (file)
                                compatible = "fsl,imx8mp-gpc";
                                reg = <0x303a0000 0x1000>;
                                interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <3>;
 
                                                reg = <IMX8MP_POWER_DOMAIN_MIPI_PHY2>;
                                        };
 
-                                       pgc_hsiomix: power-domains@17 {
+                                       pgc_hsiomix: power-domain@17 {
                                                #power-domain-cells = <0>;
                                                reg = <IMX8MP_POWER_DOMAIN_HSIOMIX>;
                                                clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
                        reg = <0x32f10100 0x8>,
                              <0x381f0000 0x20>;
                        clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
-                                <&clk IMX8MP_CLK_USB_ROOT>;
+                                <&clk IMX8MP_CLK_USB_SUSP>;
                        clock-names = "hsio", "suspend";
                        interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
                        power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
                        usb_dwc3_0: usb@38100000 {
                                compatible = "snps,dwc3";
                                reg = <0x38100000 0x10000>;
-                               clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
+                               clocks = <&clk IMX8MP_CLK_USB_ROOT>,
                                         <&clk IMX8MP_CLK_USB_CORE_REF>,
-                                        <&clk IMX8MP_CLK_USB_ROOT>;
+                                        <&clk IMX8MP_CLK_USB_SUSP>;
                                clock-names = "bus_early", "ref", "suspend";
                                interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb3_phy0>, <&usb3_phy0>;
                        reg = <0x32f10108 0x8>,
                              <0x382f0000 0x20>;
                        clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
-                                <&clk IMX8MP_CLK_USB_ROOT>;
+                                <&clk IMX8MP_CLK_USB_SUSP>;
                        clock-names = "hsio", "suspend";
                        interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
                        power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
                        usb_dwc3_1: usb@38200000 {
                                compatible = "snps,dwc3";
                                reg = <0x38200000 0x10000>;
-                               clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
+                               clocks = <&clk IMX8MP_CLK_USB_ROOT>,
                                         <&clk IMX8MP_CLK_USB_CORE_REF>,
-                                        <&clk IMX8MP_CLK_USB_ROOT>;
+                                        <&clk IMX8MP_CLK_USB_SUSP>;
                                clock-names = "bus_early", "ref", "suspend";
                                interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb3_phy1>, <&usb3_phy1>;
index 9dda2a1554c3284890cf56ef62e8a3449225418f..8614c18b5998c242d7638b7cb3381f726d8c6a86 100644 (file)
        pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
-       i2cmux@70 {
+       i2c-mux@70 {
                compatible = "nxp,pca9546";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_i2c1_pca9546>;
        pinctrl-0 = <&pinctrl_i2c4>;
        status = "okay";
 
-       pca9546: i2cmux@70 {
+       pca9546: i2c-mux@70 {
                compatible = "nxp,pca9546";
                reg = <0x70>;
                #address-cells = <1>;
index 5d5aa6537225fe79b0c270e6e00bbc34d5f682d5..6e6182709d2201c0155c9c0ef9085355956d90ee 100644 (file)
        bus-width = <4>;
        non-removable;
        no-sd;
-       no-emmc;
+       no-mmc;
        status = "okay";
 
        brcmf: wifi@1 {
        cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
        bus-width = <4>;
        no-sdio;
-       no-emmc;
+       no-mmc;
        disable-wp;
        status = "okay";
 };
index 07d8dd8160f68169001722cb3ca72ab8955c91ad..afa883389456ce772fb489eeb7dbd144820d0618 100644 (file)
@@ -61,7 +61,7 @@
        pinctrl-0 = <&pinctrl_lpi2c1 &pinctrl_ioexp_rst>;
        status = "okay";
 
-       i2c-switch@71 {
+       i2c-mux@71 {
                compatible = "nxp,pca9646", "nxp,pca9546";
                #address-cells = <1>;
                #size-cells = <0>;
index 69786c326db000c64590e2bd3af55f6e3afe9bf7..27f9a9f3313466a9b6b9b9d61a7fe7e5aea38862 100644 (file)
@@ -74,7 +74,7 @@
 
        pinctrl_usdhc1: usdhc1grp {
                fsl,pins = <
-                       MX93_PAD_SD1_CLK__USDHC1_CLK            0x17fe
+                       MX93_PAD_SD1_CLK__USDHC1_CLK            0x15fe
                        MX93_PAD_SD1_CMD__USDHC1_CMD            0x13fe
                        MX93_PAD_SD1_DATA0__USDHC1_DATA0        0x13fe
                        MX93_PAD_SD1_DATA1__USDHC1_DATA1        0x13fe
@@ -84,7 +84,7 @@
                        MX93_PAD_SD1_DATA5__USDHC1_DATA5        0x13fe
                        MX93_PAD_SD1_DATA6__USDHC1_DATA6        0x13fe
                        MX93_PAD_SD1_DATA7__USDHC1_DATA7        0x13fe
-                       MX93_PAD_SD1_STROBE__USDHC1_STROBE      0x17fe
+                       MX93_PAD_SD1_STROBE__USDHC1_STROBE      0x15fe
                >;
        };
 
 
        pinctrl_usdhc2: usdhc2grp {
                fsl,pins = <
-                       MX93_PAD_SD2_CLK__USDHC2_CLK            0x17fe
+                       MX93_PAD_SD2_CLK__USDHC2_CLK            0x15fe
                        MX93_PAD_SD2_CMD__USDHC2_CMD            0x13fe
                        MX93_PAD_SD2_DATA0__USDHC2_DATA0        0x13fe
                        MX93_PAD_SD2_DATA1__USDHC2_DATA1        0x13fe
index 7308f7b6b22c94e72d7336ee6ccf0c41050b18d4..8bce6406913875d38b7d2759561ac8c7db786726 100644 (file)
@@ -98,7 +98,7 @@
 
                        uart1: serial@12100 {
                                compatible = "snps,dw-apb-uart";
-                               reg = <0x11000 0x100>;
+                               reg = <0x12100 0x100>;
                                reg-shift = <2>;
                                interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
                                reg-io-width = <1>;
index 87c90e93667f73c65035e649f70f448f16f7d3ca..79de9cc395c4cfe3527943c5117b3b9861ca8735 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2015, LGE Inc. All rights reserved.
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  * Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
+ * Copyright (c) 2022, Dominik Kobinski <dominikkobinski314@gmail.com>
  */
 
 /dts-v1/;
                        reg = <0 0x03400000 0 0x1200000>;
                        no-map;
                };
+
+               removed_region: reserved@5000000 {
+                       reg = <0 0x05000000 0 0x2200000>;
+                       no-map;
+               };
        };
 };
 
index b242c272d2af14ee5b5607c8280de48cb06fa006..fcca1ba94da699d0917a6c9fae9fdf09193259b6 100644 (file)
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/gpio-keys.h>
 
+/delete-node/ &adsp_mem;
+/delete-node/ &audio_mem;
+/delete-node/ &mpss_mem;
+/delete-node/ &peripheral_region;
+/delete-node/ &rmtfs_mem;
+
 / {
        model = "Xiaomi Mi 4C";
        compatible = "xiaomi,libra", "qcom,msm8992";
                #size-cells = <2>;
                ranges;
 
-               /* This is for getting crash logs using Android downstream kernels */
-               ramoops@dfc00000 {
-                       compatible = "ramoops";
-                       reg = <0x0 0xdfc00000 0x0 0x40000>;
-                       console-size = <0x10000>;
-                       record-size = <0x10000>;
-                       ftrace-size = <0x10000>;
-                       pmsg-size = <0x20000>;
+               memory_hole: hole@6400000 {
+                       reg = <0 0x06400000 0 0x600000>;
+                       no-map;
+               };
+
+               memory_hole2: hole2@6c00000 {
+                       reg = <0 0x06c00000 0 0x2400000>;
+                       no-map;
+               };
+
+               mpss_mem: mpss@9000000 {
+                       reg = <0 0x09000000 0 0x5a00000>;
+                       no-map;
+               };
+
+               tzapp: tzapp@ea00000 {
+                       reg = <0 0x0ea00000 0 0x1900000>;
+                       no-map;
+               };
+
+               mdm_rfsa_mem: mdm-rfsa@ca0b0000 {
+                       reg = <0 0xca0b0000 0 0x10000>;
+                       no-map;
+               };
+
+               rmtfs_mem: rmtfs@ca100000 {
+                       compatible = "qcom,rmtfs-mem";
+                       reg = <0 0xca100000 0 0x180000>;
+                       no-map;
+
+                       qcom,client-id = <1>;
                };
 
-               modem_region: modem_region@9000000 {
-                       reg = <0x0 0x9000000 0x0 0x5a00000>;
+               audio_mem: audio@cb400000 {
+                       reg = <0 0xcb000000 0 0x400000>;
+                       no-mem;
+               };
+
+               qseecom_mem: qseecom@cb400000 {
+                       reg = <0 0xcb400000 0 0x1c00000>;
+                       no-mem;
+               };
+
+               adsp_rfsa_mem: adsp-rfsa@cd000000 {
+                       reg = <0 0xcd000000 0 0x10000>;
                        no-map;
                };
 
-               tzapp: modem_region@ea00000 {
-                       reg = <0x0 0xea00000 0x0 0x1900000>;
+               sensor_rfsa_mem: sensor-rfsa@cd010000 {
+                       reg = <0 0xcd010000 0 0x10000>;
                        no-map;
                };
+
+               ramoops@dfc00000 {
+                       compatible = "ramoops";
+                       reg = <0 0xdfc00000 0 0x40000>;
+                       console-size = <0x10000>;
+                       record-size = <0x10000>;
+                       ftrace-size = <0x10000>;
+                       pmsg-size = <0x20000>;
+               };
        };
 };
 
        status = "okay";
 };
 
-&peripheral_region {
-       reg = <0x0 0x7400000 0x0 0x1c00000>;
-       no-map;
-};
-
 &pm8994_spmi_regulators {
        VDD_APC0: s8 {
                regulator-min-microvolt = <680000>;
index 10adb4986ef1b97d79e12bbd0a2925dd6ae96ed2..02fc3795dbfd73a5c2905f630a88e42b520e7a2e 100644 (file)
        compatible = "qcom,rpmcc-msm8992", "qcom,rpmcc";
 };
 
-&tcsr_mutex {
-       compatible = "qcom,sfpb-mutex";
-};
-
 &timer {
        interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
index 85abff0e9b3f7c6913f26cbbf42d53d3725b7b85..7b0f62144c3eeafa473c12a61fac8293fa7fe793 100644 (file)
@@ -9,9 +9,6 @@
 
 #include "msm8994.dtsi"
 
-/* Angler's firmware does not report where the memory is allocated */
-/delete-node/ &cont_splash_mem;
-
 / {
        model = "Huawei Nexus 6P";
        compatible = "huawei,angler", "qcom,msm8994";
        chosen {
                stdout-path = "serial0:115200n8";
        };
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               tzapp_mem: tzapp@4800000 {
+                       reg = <0 0x04800000 0 0x1900000>;
+                       no-map;
+               };
+
+               removed_region: reserved@6300000 {
+                       reg = <0 0x06300000 0 0xD00000>;
+                       no-map;
+               };
+       };
 };
 
 &blsp1_uart2 {
index 109c9d2b684d115235c895093b7154386bf3e898..71cf81a8eb4da67e0724a5ea36a6f69c93265f42 100644 (file)
@@ -10,6 +10,7 @@
 #include <dt-bindings/interconnect/qcom,sc8280xp.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/qcom-ipcc.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
 #include <dt-bindings/power/qcom-rpmpd.h>
 #include <dt-bindings/soc/qcom,rpmh-rsc.h>
 #include <dt-bindings/thermal/thermal.h>
                                 <0>,
                                 <0>,
                                 <0>,
-                                <&usb_0_ssphy>,
+                                <&usb_0_qmpphy QMP_USB43DP_USB3_PIPE_CLK>,
                                 <0>,
                                 <0>,
                                 <0>,
                                 <0>,
                                 <0>,
                                 <0>,
-                                <&usb_1_ssphy>,
+                                <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>,
                                 <0>,
                                 <0>,
                                 <0>,
                        };
                };
 
-               usb_0_qmpphy: phy-wrapper@88ec000 {
+               usb_0_qmpphy: phy@88eb000 {
                        compatible = "qcom,sc8280xp-qmp-usb43dp-phy";
-                       reg = <0 0x088ec000 0 0x1e4>,
-                             <0 0x088eb000 0 0x40>,
-                             <0 0x088ed000 0 0x1c8>;
-                       #address-cells = <2>;
-                       #size-cells = <2>;
-                       ranges;
+                       reg = <0 0x088eb000 0 0x4000>;
 
                        clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
-                                <&rpmhcc RPMH_CXO_CLK>,
                                 <&gcc GCC_USB4_EUD_CLKREF_CLK>,
-                                <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
-                       clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+                                <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+                                <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+                       clock-names = "aux", "ref", "com_aux", "usb3_pipe";
+
+                       power-domains = <&gcc USB30_PRIM_GDSC>;
 
                        resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
-                                <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
+                                <&gcc GCC_USB4_DP_PHY_PRIM_BCR>;
                        reset-names = "phy", "common";
 
-                       power-domains = <&gcc USB30_PRIM_GDSC>;
+                       #clock-cells = <1>;
+                       #phy-cells = <1>;
 
                        status = "disabled";
-
-                       usb_0_ssphy: usb3-phy@88eb400 {
-                               reg = <0 0x088eb400 0 0x100>,
-                                     <0 0x088eb600 0 0x3ec>,
-                                     <0 0x088ec400 0 0x364>,
-                                     <0 0x088eba00 0 0x100>,
-                                     <0 0x088ebc00 0 0x3ec>,
-                                     <0 0x088ec200 0 0x18>;
-                               #phy-cells = <0>;
-                               #clock-cells = <0>;
-                               clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
-                               clock-names = "pipe0";
-                               clock-output-names = "usb0_phy_pipe_clk_src";
-                       };
                };
 
                usb_1_hsphy: phy@8902000 {
                        status = "disabled";
                };
 
-               usb_1_qmpphy: phy-wrapper@8904000 {
+               usb_1_qmpphy: phy@8903000 {
                        compatible = "qcom,sc8280xp-qmp-usb43dp-phy";
-                       reg = <0 0x08904000 0 0x1e4>,
-                             <0 0x08903000 0 0x40>,
-                             <0 0x08905000 0 0x1c8>;
-                       #address-cells = <2>;
-                       #size-cells = <2>;
-                       ranges;
+                       reg = <0 0x08903000 0 0x4000>;
 
                        clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
-                                <&rpmhcc RPMH_CXO_CLK>,
                                 <&gcc GCC_USB4_CLKREF_CLK>,
-                                <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
-                       clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+                                <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
+                                <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
+                       clock-names = "aux", "ref", "com_aux", "usb3_pipe";
+
+                       power-domains = <&gcc USB30_SEC_GDSC>;
 
                        resets = <&gcc GCC_USB3_PHY_SEC_BCR>,
                                 <&gcc GCC_USB4_1_DP_PHY_PRIM_BCR>;
                        reset-names = "phy", "common";
 
-                       power-domains = <&gcc USB30_SEC_GDSC>;
+                       #clock-cells = <1>;
+                       #phy-cells = <1>;
 
                        status = "disabled";
-
-                       usb_1_ssphy: usb3-phy@8903400 {
-                               reg = <0 0x08903400 0 0x100>,
-                                     <0 0x08903600 0 0x3ec>,
-                                     <0 0x08904400 0 0x364>,
-                                     <0 0x08903a00 0 0x100>,
-                                     <0 0x08903c00 0 0x3ec>,
-                                     <0 0x08904200 0 0x18>;
-                               #phy-cells = <0>;
-                               #clock-cells = <0>;
-                               clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
-                               clock-names = "pipe0";
-                               clock-output-names = "usb1_phy_pipe_clk_src";
-                       };
                };
 
                pmu@9091000 {
                                reg = <0 0x0a600000 0 0xcd00>;
                                interrupts = <GIC_SPI 803 IRQ_TYPE_LEVEL_HIGH>;
                                iommus = <&apps_smmu 0x820 0x0>;
-                               phys = <&usb_0_hsphy>, <&usb_0_ssphy>;
+                               phys = <&usb_0_hsphy>, <&usb_0_qmpphy QMP_USB43DP_USB3_PHY>;
                                phy-names = "usb2-phy", "usb3-phy";
                        };
                };
                                reg = <0 0x0a800000 0 0xcd00>;
                                interrupts = <GIC_SPI 810 IRQ_TYPE_LEVEL_HIGH>;
                                iommus = <&apps_smmu 0x860 0x0>;
-                               phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
+                               phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
                                phy-names = "usb2-phy", "usb3-phy";
                        };
                };
index dab5579946f351f1a43314f121fc5682556f29ff..927032863e2f15e9d63b57a3b66956d6243ea9ed 100644 (file)
                                exit-latency-us = <6562>;
                                min-residency-us = <9987>;
                                local-timer-stop;
-                               status = "disabled";
                        };
                };
        };
index 245dce24ec599c0d8b062f9953a234a792508616..fb3cd20a82b5eea676ccadcfa108031a747fd957 100644 (file)
                                 <&rpmhcc RPMH_CXO_CLK>;
                        clock-names = "iface", "core", "xo";
                        resets = <&gcc GCC_SDCC2_BCR>;
-                       interconnects = <&aggre2_noc MASTER_SDCC_2 0 &mc_virt SLAVE_EBI1 0>,
-                                       <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_SDCC_2 0>;
+                       interconnects = <&aggre2_noc MASTER_SDCC_2 &mc_virt SLAVE_EBI1>,
+                                       <&gem_noc MASTER_APPSS_PROC &config_noc SLAVE_SDCC_2>;
                        interconnect-names = "sdhc-ddr","cpu-sdhc";
                        iommus = <&apps_smmu 0x4a0 0x0>;
                        power-domains = <&rpmhpd SM8350_CX>;
index 31d13a6001df49c482a6bd426d0a8718288746ad..de4ff90785b2c96a15ad08484dedbda289951fae 100644 (file)
@@ -48,8 +48,17 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
 })
 
 extern spinlock_t efi_rt_lock;
+extern u64 *efi_rt_stack_top;
 efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
 
+/*
+ * efi_rt_stack_top[-1] contains the value the stack pointer had before
+ * switching to the EFI runtime stack.
+ */
+#define current_in_efi()                                               \
+       (!preemptible() && efi_rt_stack_top != NULL &&                  \
+        on_task_stack(current, READ_ONCE(efi_rt_stack_top[-1]), 1))
+
 #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
 
 /*
index 4e5354beafb01bac900f854ea7cfecbbf068ab5c..66ec8caa6ac07fa0d70865e40b594bdd7079d585 100644 (file)
@@ -106,4 +106,19 @@ static inline struct stack_info stackinfo_get_sdei_critical(void)
 #define stackinfo_get_sdei_critical()  stackinfo_get_unknown()
 #endif
 
+#ifdef CONFIG_EFI
+extern u64 *efi_rt_stack_top;
+
+static inline struct stack_info stackinfo_get_efi(void)
+{
+       unsigned long high = (u64)efi_rt_stack_top;
+       unsigned long low = high - THREAD_SIZE;
+
+       return (struct stack_info) {
+               .low = low,
+               .high = high,
+       };
+}
+#endif
+
 #endif /* __ASM_STACKTRACE_H */
index d872d18101d837508d1a4dd2cef742cc7c83e241..e8ae803662cf14d1de635e2f89fe062d3a72209d 100644 (file)
@@ -46,7 +46,10 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
        mov     x4, x6
        blr     x8
 
+       mov     x16, sp
        mov     sp, x29
+       str     xzr, [x16, #8]                  // clear recorded task SP value
+
        ldp     x1, x2, [sp, #16]
        cmp     x2, x18
        ldp     x29, x30, [sp], #112
@@ -71,6 +74,9 @@ SYM_FUNC_END(__efi_rt_asm_wrapper)
 SYM_CODE_START(__efi_rt_asm_recover)
        mov     sp, x30
 
+       ldr_l   x16, efi_rt_stack_top           // clear recorded task SP value
+       str     xzr, [x16, #-8]
+
        ldp     x19, x20, [sp, #32]
        ldp     x21, x22, [sp, #48]
        ldp     x23, x24, [sp, #64]
index fab05de2e12dd5d8ad28b1a647fea66c6ac1651e..b273900f4566858710bee8d427721accc55fa4b4 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 
 #include <asm/efi.h>
+#include <asm/stacktrace.h>
 
 static bool region_is_misaligned(const efi_memory_desc_t *md)
 {
@@ -154,7 +155,7 @@ asmlinkage efi_status_t __efi_rt_asm_recover(void);
 bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
 {
         /* Check whether the exception occurred while running the firmware */
-       if (current_work() != &efi_rts_work.work || regs->pc >= TASK_SIZE_64)
+       if (!current_in_efi() || regs->pc >= TASK_SIZE_64)
                return false;
 
        pr_err(FW_BUG "Unable to handle %s in EFI runtime service\n", msg);
index 117e2c180f3c77d8f65af2ca51012c2ba075212a..83154303e682c8b69aa78fa37f3e63d150bd1470 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2012 ARM Ltd.
  */
 #include <linux/kernel.h>
+#include <linux/efi.h>
 #include <linux/export.h>
 #include <linux/ftrace.h>
 #include <linux/sched.h>
@@ -12,6 +13,7 @@
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
 
+#include <asm/efi.h>
 #include <asm/irq.h>
 #include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
@@ -186,6 +188,13 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
                        : stackinfo_get_unknown();              \
        })
 
+#define STACKINFO_EFI                                          \
+       ({                                                      \
+               ((task == current) && current_in_efi())         \
+                       ? stackinfo_get_efi()                   \
+                       : stackinfo_get_unknown();              \
+       })
+
 noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
                              void *cookie, struct task_struct *task,
                              struct pt_regs *regs)
@@ -199,6 +208,9 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
 #if defined(CONFIG_VMAP_STACK) && defined(CONFIG_ARM_SDE_INTERFACE)
                STACKINFO_SDEI(normal),
                STACKINFO_SDEI(critical),
+#endif
+#ifdef CONFIG_EFI
+               STACKINFO_EFI,
 #endif
        };
        struct unwind_state state = {
index 5626ddb540ce3333d561f9e61c13d3a695f859fe..cf4c495a4321332b7bc5a1979fc84d3084da355e 100644 (file)
@@ -1079,7 +1079,7 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
 
                        /* uaccess failed, don't leave stale tags */
                        if (num_tags != MTE_GRANULES_PER_PAGE)
-                               mte_clear_page_tags(page);
+                               mte_clear_page_tags(maddr);
                        set_page_mte_tagged(page);
 
                        kvm_release_pfn_dirty(pfn);
index 94a666dd1443d1310aadf35a1267e26d04709eca..2642e9ce28199c871190fa15888c1b1a9f93a2ba 100644 (file)
@@ -2187,7 +2187,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
               ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
                ite->collection->collection_id;
        val = cpu_to_le64(val);
-       return kvm_write_guest_lock(kvm, gpa, &val, ite_esz);
+       return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
 }
 
 /**
@@ -2339,7 +2339,7 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
               (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
                (dev->num_eventid_bits - 1));
        val = cpu_to_le64(val);
-       return kvm_write_guest_lock(kvm, ptr, &val, dte_esz);
+       return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
 }
 
 /**
@@ -2526,7 +2526,7 @@ static int vgic_its_save_cte(struct vgic_its *its,
               ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
               collection->collection_id);
        val = cpu_to_le64(val);
-       return kvm_write_guest_lock(its->dev->kvm, gpa, &val, esz);
+       return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
 }
 
 /*
@@ -2607,7 +2607,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
         */
        val = 0;
        BUG_ON(cte_esz > sizeof(val));
-       ret = kvm_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
+       ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
        return ret;
 }
 
@@ -2743,7 +2743,6 @@ static int vgic_its_has_attr(struct kvm_device *dev,
 static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
 {
        const struct vgic_its_abi *abi = vgic_its_get_abi(its);
-       struct vgic_dist *dist = &kvm->arch.vgic;
        int ret = 0;
 
        if (attr == KVM_DEV_ARM_VGIC_CTRL_INIT) /* Nothing to do */
@@ -2763,9 +2762,7 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
                vgic_its_reset(kvm, its);
                break;
        case KVM_DEV_ARM_ITS_SAVE_TABLES:
-               dist->save_its_tables_in_progress = true;
                ret = abi->save_tables(its);
-               dist->save_its_tables_in_progress = false;
                break;
        case KVM_DEV_ARM_ITS_RESTORE_TABLES:
                ret = abi->restore_tables(its);
@@ -2792,7 +2789,7 @@ bool kvm_arch_allow_write_without_running_vcpu(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
 
-       return dist->save_its_tables_in_progress;
+       return dist->table_write_in_progress;
 }
 
 static int vgic_its_set_attr(struct kvm_device *dev,
index 2074521d4a8ce57ba5e4d73abe03e8b43223d487..684bdfaad4a9de9b10bbb6e80be54a7c8a994318 100644 (file)
@@ -339,7 +339,7 @@ retry:
        if (status) {
                /* clear consumed data */
                val &= ~(1 << bit_nr);
-               ret = kvm_write_guest_lock(kvm, ptr, &val, 1);
+               ret = vgic_write_guest_lock(kvm, ptr, &val, 1);
                if (ret)
                        return ret;
        }
@@ -350,26 +350,23 @@ retry:
  * The deactivation of the doorbell interrupt will trigger the
  * unmapping of the associated vPE.
  */
-static void unmap_all_vpes(struct vgic_dist *dist)
+static void unmap_all_vpes(struct kvm *kvm)
 {
-       struct irq_desc *desc;
+       struct vgic_dist *dist = &kvm->arch.vgic;
        int i;
 
-       for (i = 0; i < dist->its_vm.nr_vpes; i++) {
-               desc = irq_to_desc(dist->its_vm.vpes[i]->irq);
-               irq_domain_deactivate_irq(irq_desc_get_irq_data(desc));
-       }
+       for (i = 0; i < dist->its_vm.nr_vpes; i++)
+               free_irq(dist->its_vm.vpes[i]->irq, kvm_get_vcpu(kvm, i));
 }
 
-static void map_all_vpes(struct vgic_dist *dist)
+static void map_all_vpes(struct kvm *kvm)
 {
-       struct irq_desc *desc;
+       struct vgic_dist *dist = &kvm->arch.vgic;
        int i;
 
-       for (i = 0; i < dist->its_vm.nr_vpes; i++) {
-               desc = irq_to_desc(dist->its_vm.vpes[i]->irq);
-               irq_domain_activate_irq(irq_desc_get_irq_data(desc), false);
-       }
+       for (i = 0; i < dist->its_vm.nr_vpes; i++)
+               WARN_ON(vgic_v4_request_vpe_irq(kvm_get_vcpu(kvm, i),
+                                               dist->its_vm.vpes[i]->irq));
 }
 
 /**
@@ -394,7 +391,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
         * and enabling of the doorbells have already been done.
         */
        if (kvm_vgic_global_state.has_gicv4_1) {
-               unmap_all_vpes(dist);
+               unmap_all_vpes(kvm);
                vlpi_avail = true;
        }
 
@@ -437,14 +434,14 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
                else
                        val &= ~(1 << bit_nr);
 
-               ret = kvm_write_guest_lock(kvm, ptr, &val, 1);
+               ret = vgic_write_guest_lock(kvm, ptr, &val, 1);
                if (ret)
                        goto out;
        }
 
 out:
        if (vlpi_avail)
-               map_all_vpes(dist);
+               map_all_vpes(kvm);
 
        return ret;
 }
index ad06ba6c9b0091c911c84903d455cfa53e056b8e..a413718be92b8703c18ef8dacfe3dcfb1e3027a0 100644 (file)
@@ -222,6 +222,11 @@ void vgic_v4_get_vlpi_state(struct vgic_irq *irq, bool *val)
        *val = !!(*ptr & mask);
 }
 
+int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq)
+{
+       return request_irq(irq, vgic_v4_doorbell_handler, 0, "vcpu", vcpu);
+}
+
 /**
  * vgic_v4_init - Initialize the GICv4 data structures
  * @kvm:       Pointer to the VM being initialized
@@ -283,8 +288,7 @@ int vgic_v4_init(struct kvm *kvm)
                        irq_flags &= ~IRQ_NOAUTOEN;
                irq_set_status_flags(irq, irq_flags);
 
-               ret = request_irq(irq, vgic_v4_doorbell_handler,
-                                 0, "vcpu", vcpu);
+               ret = vgic_v4_request_vpe_irq(vcpu, irq);
                if (ret) {
                        kvm_err("failed to allocate vcpu IRQ%d\n", irq);
                        /*
index 0c8da72953f06bf97b67ed69e20a560fd641171e..7f7f3c5ed85a0f157613a6fa9fd86c44e7dd05d3 100644 (file)
@@ -6,6 +6,7 @@
 #define __KVM_ARM_VGIC_NEW_H__
 
 #include <linux/irqchip/arm-gic-common.h>
+#include <asm/kvm_mmu.h>
 
 #define PRODUCT_ID_KVM         0x4b    /* ASCII code K */
 #define IMPLEMENTER_ARM                0x43b
@@ -131,6 +132,19 @@ static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq)
        return vgic_irq_get_lr_count(irq) > 1;
 }
 
+static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
+                                       const void *data, unsigned long len)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+       int ret;
+
+       dist->table_write_in_progress = true;
+       ret = kvm_write_guest_lock(kvm, gpa, data, len);
+       dist->table_write_in_progress = false;
+
+       return ret;
+}
+
 /*
  * This struct provides an intermediate representation of the fields contained
  * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
@@ -331,5 +345,6 @@ int vgic_v4_init(struct kvm *kvm);
 void vgic_v4_teardown(struct kvm *kvm);
 void vgic_v4_configure_vsgis(struct kvm *kvm);
 void vgic_v4_get_vlpi_state(struct vgic_irq *irq, bool *val);
+int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq);
 
 #endif
index f6a502e8f02c5bd0ef5bcd25abfd7c04c7b3cbf9..6e948d015332abc02b6e73501a64b26042da8b38 100644 (file)
@@ -170,6 +170,9 @@ ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, u
 asmlinkage long
 ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user *tp)
 {
+       struct timespec64 rtn_tp;
+       s64 tick_ns;
+
        /*
         * ia64's clock_gettime() syscall is implemented as a vdso call
         * fsys_clock_gettime(). Currently it handles only
@@ -185,8 +188,8 @@ ia64_clock_getres(const clockid_t which_clock, struct __kernel_timespec __user *
        switch (which_clock) {
        case CLOCK_REALTIME:
        case CLOCK_MONOTONIC:
-               s64 tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq);
-               struct timespec64 rtn_tp = ns_to_timespec64(tick_ns);
+               tick_ns = DIV_ROUND_UP(NSEC_PER_SEC, local_cpu_data->itc_freq);
+               rtn_tp = ns_to_timespec64(tick_ns);
                return put_timespec64(&rtn_tp, tp);
        }
 
index 90f9d3399b2aafe62a495e93f0735898d4b28715..3418d32d4fc7d2d24a96563132d42f2bcc012d38 100644 (file)
@@ -10,8 +10,6 @@
 #define FTRACE_REGS_PLT_IDX    1
 #define NR_FTRACE_PLTS         2
 
-#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
-
 #ifdef CONFIG_FUNCTION_TRACER
 
 #define MCOUNT_INSN_SIZE 4             /* sizeof mcount call */
index c00e1512d4fa33e49bf4b6c4627460938510de75..7eedd83fd0d72127fc570cd87dc759f1d8b6b12f 100644 (file)
@@ -377,14 +377,6 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
        return val < (1UL << bit);
 }
 
-static inline unsigned long sign_extend(unsigned long val, unsigned int idx)
-{
-       if (!is_imm_negative(val, idx + 1))
-               return ((1UL << idx) - 1) & val;
-       else
-               return ~((1UL << idx) - 1) | val;
-}
-
 #define DEF_EMIT_REG0I26_FORMAT(NAME, OP)                              \
 static inline void emit_##NAME(union loongarch_instruction *insn,      \
                               int offset)                              \
@@ -401,6 +393,7 @@ static inline void emit_##NAME(union loongarch_instruction *insn,   \
 }
 
 DEF_EMIT_REG0I26_FORMAT(b, b_op)
+DEF_EMIT_REG0I26_FORMAT(bl, bl_op)
 
 #define DEF_EMIT_REG1I20_FORMAT(NAME, OP)                              \
 static inline void emit_##NAME(union loongarch_instruction *insn,      \
index f2b52b9ea93d2862d69e9e7f1075f6e1bcfee619..b9dce87afd2e058a3dd786ccbb513a3bbbff637c 100644 (file)
@@ -8,7 +8,9 @@
 #define _ASM_UNWIND_H
 
 #include <linux/sched.h>
+#include <linux/ftrace.h>
 
+#include <asm/ptrace.h>
 #include <asm/stacktrace.h>
 
 enum unwinder_type {
@@ -20,11 +22,13 @@ struct unwind_state {
        char type; /* UNWINDER_XXX */
        struct stack_info stack_info;
        struct task_struct *task;
-       bool first, error, is_ftrace;
+       bool first, error, reset;
        int graph_idx;
        unsigned long sp, pc, ra;
 };
 
+bool default_next_frame(struct unwind_state *state);
+
 void unwind_start(struct unwind_state *state,
                  struct task_struct *task, struct pt_regs *regs);
 bool unwind_next_frame(struct unwind_state *state);
@@ -40,4 +44,39 @@ static inline bool unwind_error(struct unwind_state *state)
        return state->error;
 }
 
+#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
+
+static inline unsigned long unwind_graph_addr(struct unwind_state *state,
+                                       unsigned long pc, unsigned long cfa)
+{
+       return ftrace_graph_ret_addr(state->task, &state->graph_idx,
+                                    pc, (unsigned long *)(cfa - GRAPH_FAKE_OFFSET));
+}
+
+static __always_inline void __unwind_start(struct unwind_state *state,
+                                       struct task_struct *task, struct pt_regs *regs)
+{
+       memset(state, 0, sizeof(*state));
+       if (regs) {
+               state->sp = regs->regs[3];
+               state->pc = regs->csr_era;
+               state->ra = regs->regs[1];
+       } else if (task && task != current) {
+               state->sp = thread_saved_fp(task);
+               state->pc = thread_saved_ra(task);
+               state->ra = 0;
+       } else {
+               state->sp = (unsigned long)__builtin_frame_address(0);
+               state->pc = (unsigned long)__builtin_return_address(0);
+               state->ra = 0;
+       }
+       state->task = task;
+       get_stack_info(state->sp, state->task, &state->stack_info);
+       state->pc = unwind_graph_addr(state, state->pc, state->sp);
+}
+
+static __always_inline unsigned long __unwind_get_return_address(struct unwind_state *state)
+{
+       return unwind_done(state) ? 0 : state->pc;
+}
 #endif /* _ASM_UNWIND_H */
index fcaa024a685ec6df4a983daa59dbf2f967b038af..c8cfbd562921d63fe2a15aa6fb8a6940ff356fd4 100644 (file)
@@ -8,7 +8,7 @@ extra-y         := vmlinux.lds
 obj-y          += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
                   traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \
                   elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \
-                  alternative.o unaligned.o
+                  alternative.o unaligned.o unwind.o
 
 obj-$(CONFIG_ACPI)             += acpi.o
 obj-$(CONFIG_EFI)              += efi.o
index c5aebeac960b6e19908550185a49363c54f0768e..4ad13847e9626eab6dfa5022b0d51ff5a40459ad 100644 (file)
@@ -74,7 +74,7 @@ static void __init_or_module recompute_jump(union loongarch_instruction *buf,
        switch (src->reg0i26_format.opcode) {
        case b_op:
        case bl_op:
-               jump_addr = cur_pc + sign_extend((si_h << 16 | si_l) << 2, 27);
+               jump_addr = cur_pc + sign_extend64((si_h << 16 | si_l) << 2, 27);
                if (in_alt_jump(jump_addr, start, end))
                        return;
                offset = jump_addr - pc;
@@ -93,7 +93,7 @@ static void __init_or_module recompute_jump(union loongarch_instruction *buf,
                fallthrough;
        case beqz_op:
        case bnez_op:
-               jump_addr = cur_pc + sign_extend((si_h << 16 | si_l) << 2, 22);
+               jump_addr = cur_pc + sign_extend64((si_h << 16 | si_l) << 2, 22);
                if (in_alt_jump(jump_addr, start, end))
                        return;
                offset = jump_addr - pc;
@@ -112,7 +112,7 @@ static void __init_or_module recompute_jump(union loongarch_instruction *buf,
        case bge_op:
        case bltu_op:
        case bgeu_op:
-               jump_addr = cur_pc + sign_extend(si << 2, 17);
+               jump_addr = cur_pc + sign_extend64(si << 2, 17);
                if (in_alt_jump(jump_addr, start, end))
                        return;
                offset = jump_addr - pc;
index 255a09876ef28d1b10c67fd1b9f8ca4814f8aefc..3a3fce2d784611e1118e6a6d5dab1b509501dd9c 100644 (file)
@@ -94,7 +94,7 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
        c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR |
                     LOONGARCH_CPU_TLB | LOONGARCH_CPU_VINT | LOONGARCH_CPU_WATCH;
 
-       elf_hwcap |= HWCAP_LOONGARCH_CRC32;
+       elf_hwcap = HWCAP_LOONGARCH_CPUCFG | HWCAP_LOONGARCH_CRC32;
 
        config = read_cpucfg(LOONGARCH_CPUCFG1);
        if (config & CPUCFG1_UAL) {
index 75e5be807a0d5004feb5f1e6eb42f8bcc9efef5f..7e5c293ed89f70c4872d54dfcad422673dc65112 100644 (file)
@@ -67,14 +67,17 @@ SYM_FUNC_END(except_vec_cex)
        .macro  BUILD_HANDLER exception handler prep
        .align  5
        SYM_FUNC_START(handle_\exception)
+       666:
        BACKUP_T0T1
        SAVE_ALL
        build_prep_\prep
        move    a0, sp
        la.abs  t0, do_\handler
        jirl    ra, t0, 0
+       668:
        RESTORE_ALL_AND_RET
        SYM_FUNC_END(handle_\exception)
+       SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
        .endm
 
        BUILD_HANDLER ade ade badv
index 512579d79b221ccb632cbff1c3140233e3a5dda0..badc590870423433495616c47e53022e4cf96f35 100644 (file)
@@ -58,7 +58,6 @@ u32 larch_insn_gen_nop(void)
 u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
 {
        long offset = dest - pc;
-       unsigned int immediate_l, immediate_h;
        union loongarch_instruction insn;
 
        if ((offset & 3) || offset < -SZ_128M || offset >= SZ_128M) {
@@ -66,15 +65,7 @@ u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
                return INSN_BREAK;
        }
 
-       offset >>= 2;
-
-       immediate_l = offset & 0xffff;
-       offset >>= 16;
-       immediate_h = offset & 0x3ff;
-
-       insn.reg0i26_format.opcode = b_op;
-       insn.reg0i26_format.immediate_l = immediate_l;
-       insn.reg0i26_format.immediate_h = immediate_h;
+       emit_b(&insn, offset >> 2);
 
        return insn.word;
 }
@@ -82,7 +73,6 @@ u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
 u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
 {
        long offset = dest - pc;
-       unsigned int immediate_l, immediate_h;
        union loongarch_instruction insn;
 
        if ((offset & 3) || offset < -SZ_128M || offset >= SZ_128M) {
@@ -90,15 +80,7 @@ u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
                return INSN_BREAK;
        }
 
-       offset >>= 2;
-
-       immediate_l = offset & 0xffff;
-       offset >>= 16;
-       immediate_h = offset & 0x3ff;
-
-       insn.reg0i26_format.opcode = bl_op;
-       insn.reg0i26_format.immediate_l = immediate_l;
-       insn.reg0i26_format.immediate_h = immediate_h;
+       emit_bl(&insn, offset >> 2);
 
        return insn.word;
 }
@@ -107,10 +89,7 @@ u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongar
 {
        union loongarch_instruction insn;
 
-       insn.reg3_format.opcode = or_op;
-       insn.reg3_format.rd = rd;
-       insn.reg3_format.rj = rj;
-       insn.reg3_format.rk = rk;
+       emit_or(&insn, rd, rj, rk);
 
        return insn.word;
 }
@@ -124,9 +103,7 @@ u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm)
 {
        union loongarch_instruction insn;
 
-       insn.reg1i20_format.opcode = lu12iw_op;
-       insn.reg1i20_format.rd = rd;
-       insn.reg1i20_format.immediate = imm;
+       emit_lu12iw(&insn, rd, imm);
 
        return insn.word;
 }
@@ -135,9 +112,7 @@ u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm)
 {
        union loongarch_instruction insn;
 
-       insn.reg1i20_format.opcode = lu32id_op;
-       insn.reg1i20_format.rd = rd;
-       insn.reg1i20_format.immediate = imm;
+       emit_lu32id(&insn, rd, imm);
 
        return insn.word;
 }
@@ -146,10 +121,7 @@ u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
 {
        union loongarch_instruction insn;
 
-       insn.reg2i12_format.opcode = lu52id_op;
-       insn.reg2i12_format.rd = rd;
-       insn.reg2i12_format.rj = rj;
-       insn.reg2i12_format.immediate = imm;
+       emit_lu52id(&insn, rd, rj, imm);
 
        return insn.word;
 }
@@ -158,10 +130,7 @@ u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned l
 {
        union loongarch_instruction insn;
 
-       insn.reg2i16_format.opcode = jirl_op;
-       insn.reg2i16_format.rd = rd;
-       insn.reg2i16_format.rj = rj;
-       insn.reg2i16_format.immediate = (dest - pc) >> 2;
+       emit_jirl(&insn, rj, rd, (dest - pc) >> 2);
 
        return insn.word;
 }
index c583b1ef1f44cefaada16d0d9c450b2019515ec9..edfd220a3737aadad190d43a2ecaf91fdcaf44e5 100644 (file)
@@ -191,20 +191,14 @@ out:
 
 unsigned long __get_wchan(struct task_struct *task)
 {
-       unsigned long pc;
+       unsigned long pc = 0;
        struct unwind_state state;
 
        if (!try_get_task_stack(task))
                return 0;
 
-       unwind_start(&state, task, NULL);
-       state.sp = thread_saved_fp(task);
-       get_stack_info(state.sp, state.task, &state.stack_info);
-       state.pc = thread_saved_ra(task);
-#ifdef CONFIG_UNWINDER_PROLOGUE
-       state.type = UNWINDER_PROLOGUE;
-#endif
-       for (; !unwind_done(&state); unwind_next_frame(&state)) {
+       for (unwind_start(&state, task, NULL);
+            !unwind_done(&state); unwind_next_frame(&state)) {
                pc = unwind_get_return_address(&state);
                if (!pc)
                        break;
index 7ea62faeeadb561362b0228d4937bedcb7466e51..c38a146a973b45beafc0e984bdff77631fbea0bb 100644 (file)
@@ -72,9 +72,6 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
        if (!task)
                task = current;
 
-       if (user_mode(regs))
-               state.type = UNWINDER_GUESS;
-
        printk("%sCall Trace:", loglvl);
        for (unwind_start(&state, task, pregs);
              !unwind_done(&state); unwind_next_frame(&state)) {
diff --git a/arch/loongarch/kernel/unwind.c b/arch/loongarch/kernel/unwind.c
new file mode 100644 (file)
index 0000000..a463d69
--- /dev/null
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
+ */
+#include <linux/kernel.h>
+#include <linux/ftrace.h>
+
+#include <asm/unwind.h>
+
+bool default_next_frame(struct unwind_state *state)
+{
+       struct stack_info *info = &state->stack_info;
+       unsigned long addr;
+
+       if (unwind_done(state))
+               return false;
+
+       do {
+               for (state->sp += sizeof(unsigned long);
+                    state->sp < info->end; state->sp += sizeof(unsigned long)) {
+                       addr = *(unsigned long *)(state->sp);
+                       state->pc = unwind_graph_addr(state, addr, state->sp + 8);
+                       if (__kernel_text_address(state->pc))
+                               return true;
+               }
+
+               state->sp = info->next_sp;
+
+       } while (!get_stack_info(state->sp, state->task, info));
+
+       return false;
+}
index e2d2e4f3001f490a76762ad336fbcf696c4bbfe3..98379b7d41475b89bb85f1c4d32be29343612cc8 100644 (file)
@@ -2,37 +2,18 @@
 /*
  * Copyright (C) 2022 Loongson Technology Corporation Limited
  */
-#include <linux/kernel.h>
-#include <linux/ftrace.h>
-
 #include <asm/unwind.h>
 
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
-       if (unwind_done(state))
-               return 0;
-       else if (state->first)
-               return state->pc;
-
-       return *(unsigned long *)(state->sp);
+       return __unwind_get_return_address(state);
 }
 EXPORT_SYMBOL_GPL(unwind_get_return_address);
 
 void unwind_start(struct unwind_state *state, struct task_struct *task,
                    struct pt_regs *regs)
 {
-       memset(state, 0, sizeof(*state));
-
-       if (regs) {
-               state->sp = regs->regs[3];
-               state->pc = regs->csr_era;
-       }
-
-       state->task = task;
-       state->first = true;
-
-       get_stack_info(state->sp, state->task, &state->stack_info);
-
+       __unwind_start(state, task, regs);
        if (!unwind_done(state) && !__kernel_text_address(state->pc))
                unwind_next_frame(state);
 }
@@ -40,30 +21,6 @@ EXPORT_SYMBOL_GPL(unwind_start);
 
 bool unwind_next_frame(struct unwind_state *state)
 {
-       struct stack_info *info = &state->stack_info;
-       unsigned long addr;
-
-       if (unwind_done(state))
-               return false;
-
-       if (state->first)
-               state->first = false;
-
-       do {
-               for (state->sp += sizeof(unsigned long);
-                    state->sp < info->end;
-                    state->sp += sizeof(unsigned long)) {
-                       addr = *(unsigned long *)(state->sp);
-                       state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                                       addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-                       if (__kernel_text_address(addr))
-                               return true;
-               }
-
-               state->sp = info->next_sp;
-
-       } while (!get_stack_info(state->sp, state->task, info));
-
-       return false;
+       return default_next_frame(state);
 }
 EXPORT_SYMBOL_GPL(unwind_next_frame);
index 0f8d1451ebb848d8a88f8a5c9405903a8d4c93c0..9095fde8e55d5c57177c83ab0548ab888c348f16 100644 (file)
 /*
  * Copyright (C) 2022 Loongson Technology Corporation Limited
  */
+#include <linux/cpumask.h>
 #include <linux/ftrace.h>
 #include <linux/kallsyms.h>
 
 #include <asm/inst.h>
+#include <asm/loongson.h>
 #include <asm/ptrace.h>
+#include <asm/setup.h>
 #include <asm/unwind.h>
 
-static inline void unwind_state_fixup(struct unwind_state *state)
-{
-#ifdef CONFIG_DYNAMIC_FTRACE
-       static unsigned long ftrace = (unsigned long)ftrace_call + 4;
-
-       if (state->pc == ftrace)
-               state->is_ftrace = true;
+extern const int unwind_hint_ade;
+extern const int unwind_hint_ale;
+extern const int unwind_hint_bp;
+extern const int unwind_hint_fpe;
+extern const int unwind_hint_fpu;
+extern const int unwind_hint_lsx;
+extern const int unwind_hint_lasx;
+extern const int unwind_hint_lbt;
+extern const int unwind_hint_ri;
+extern const int unwind_hint_watch;
+extern unsigned long eentry;
+#ifdef CONFIG_NUMA
+extern unsigned long pcpu_handlers[NR_CPUS];
 #endif
-}
 
-unsigned long unwind_get_return_address(struct unwind_state *state)
+static inline bool scan_handlers(unsigned long entry_offset)
 {
+       int idx, offset;
 
-       if (unwind_done(state))
-               return 0;
-       else if (state->type)
-               return state->pc;
-       else if (state->first)
-               return state->pc;
-
-       return *(unsigned long *)(state->sp);
+       if (entry_offset >= EXCCODE_INT_START * VECSIZE)
+               return false;
 
+       idx = entry_offset / VECSIZE;
+       offset = entry_offset % VECSIZE;
+       switch (idx) {
+       case EXCCODE_ADE:
+               return offset == unwind_hint_ade;
+       case EXCCODE_ALE:
+               return offset == unwind_hint_ale;
+       case EXCCODE_BP:
+               return offset == unwind_hint_bp;
+       case EXCCODE_FPE:
+               return offset == unwind_hint_fpe;
+       case EXCCODE_FPDIS:
+               return offset == unwind_hint_fpu;
+       case EXCCODE_LSXDIS:
+               return offset == unwind_hint_lsx;
+       case EXCCODE_LASXDIS:
+               return offset == unwind_hint_lasx;
+       case EXCCODE_BTDIS:
+               return offset == unwind_hint_lbt;
+       case EXCCODE_INE:
+               return offset == unwind_hint_ri;
+       case EXCCODE_WATCH:
+               return offset == unwind_hint_watch;
+       default:
+               return false;
+       }
 }
-EXPORT_SYMBOL_GPL(unwind_get_return_address);
 
-static bool unwind_by_guess(struct unwind_state *state)
+static inline bool fix_exception(unsigned long pc)
 {
-       struct stack_info *info = &state->stack_info;
-       unsigned long addr;
-
-       for (state->sp += sizeof(unsigned long);
-            state->sp < info->end;
-            state->sp += sizeof(unsigned long)) {
-               addr = *(unsigned long *)(state->sp);
-               state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                               addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-               if (__kernel_text_address(addr))
+#ifdef CONFIG_NUMA
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               if (!pcpu_handlers[cpu])
+                       continue;
+               if (scan_handlers(pc - pcpu_handlers[cpu]))
                        return true;
        }
+#endif
+       return scan_handlers(pc - eentry);
+}
 
+/*
+ * As we meet ftrace_regs_entry, reset first flag like first doing
+ * tracing. Prologue analysis will stop soon because PC is at entry.
+ */
+static inline bool fix_ftrace(unsigned long pc)
+{
+#ifdef CONFIG_DYNAMIC_FTRACE
+       return pc == (unsigned long)ftrace_call + LOONGARCH_INSN_SIZE;
+#else
        return false;
+#endif
 }
 
+static inline bool unwind_state_fixup(struct unwind_state *state)
+{
+       if (!fix_exception(state->pc) && !fix_ftrace(state->pc))
+               return false;
+
+       state->reset = true;
+       return true;
+}
+
+/*
+ * LoongArch function prologue is like follows,
+ *     [instructions not use stack var]
+ *     addi.d sp, sp, -imm
+ *     st.d   xx, sp, offset <- save callee saved regs and
+ *     st.d   yy, sp, offset    save ra if function is nest.
+ *     [others instructions]
+ */
 static bool unwind_by_prologue(struct unwind_state *state)
 {
        long frame_ra = -1;
        unsigned long frame_size = 0;
-       unsigned long size, offset, pc = state->pc;
+       unsigned long size, offset, pc;
        struct pt_regs *regs;
        struct stack_info *info = &state->stack_info;
        union loongarch_instruction *ip, *ip_end;
@@ -64,20 +119,21 @@ static bool unwind_by_prologue(struct unwind_state *state)
        if (state->sp >= info->end || state->sp < info->begin)
                return false;
 
-       if (state->is_ftrace) {
-               /*
-                * As we meet ftrace_regs_entry, reset first flag like first doing
-                * tracing. Prologue analysis will stop soon because PC is at entry.
-                */
+       if (state->reset) {
                regs = (struct pt_regs *)state->sp;
                state->first = true;
-               state->is_ftrace = false;
+               state->reset = false;
                state->pc = regs->csr_era;
                state->ra = regs->regs[1];
                state->sp = regs->regs[3];
                return true;
        }
 
+       /*
+        * When first is not set, the PC is a return address in the previous frame.
+        * We need to adjust its value in case overflow to the next symbol.
+        */
+       pc = state->pc - (state->first ? 0 : LOONGARCH_INSN_SIZE);
        if (!kallsyms_lookup_size_offset(pc, &size, &offset))
                return false;
 
@@ -93,6 +149,10 @@ static bool unwind_by_prologue(struct unwind_state *state)
                ip++;
        }
 
+       /*
+        * Can't find stack alloc action, PC may be in a leaf function. Only the
+        * first being true is reasonable, otherwise indicate analysis is broken.
+        */
        if (!frame_size) {
                if (state->first)
                        goto first;
@@ -110,6 +170,7 @@ static bool unwind_by_prologue(struct unwind_state *state)
                ip++;
        }
 
+       /* Can't find save $ra action, PC may be in a leaf function, too. */
        if (frame_ra < 0) {
                if (state->first) {
                        state->sp = state->sp + frame_size;
@@ -118,88 +179,47 @@ static bool unwind_by_prologue(struct unwind_state *state)
                return false;
        }
 
-       if (state->first)
-               state->first = false;
-
        state->pc = *(unsigned long *)(state->sp + frame_ra);
        state->sp = state->sp + frame_size;
        goto out;
 
 first:
-       state->first = false;
-       if (state->pc == state->ra)
-               return false;
-
        state->pc = state->ra;
 
 out:
-       unwind_state_fixup(state);
-       return !!__kernel_text_address(state->pc);
-}
-
-void unwind_start(struct unwind_state *state, struct task_struct *task,
-                   struct pt_regs *regs)
-{
-       memset(state, 0, sizeof(*state));
-
-       if (regs &&  __kernel_text_address(regs->csr_era)) {
-               state->pc = regs->csr_era;
-               state->sp = regs->regs[3];
-               state->ra = regs->regs[1];
-               state->type = UNWINDER_PROLOGUE;
-       }
-
-       state->task = task;
-       state->first = true;
-
-       get_stack_info(state->sp, state->task, &state->stack_info);
-
-       if (!unwind_done(state) && !__kernel_text_address(state->pc))
-               unwind_next_frame(state);
+       state->first = false;
+       return unwind_state_fixup(state) || __kernel_text_address(state->pc);
 }
-EXPORT_SYMBOL_GPL(unwind_start);
 
-bool unwind_next_frame(struct unwind_state *state)
+static bool next_frame(struct unwind_state *state)
 {
-       struct stack_info *info = &state->stack_info;
-       struct pt_regs *regs;
        unsigned long pc;
+       struct pt_regs *regs;
+       struct stack_info *info = &state->stack_info;
 
        if (unwind_done(state))
                return false;
 
        do {
-               switch (state->type) {
-               case UNWINDER_GUESS:
-                       state->first = false;
-                       if (unwind_by_guess(state))
-                               return true;
-                       break;
+               if (unwind_by_prologue(state)) {
+                       state->pc = unwind_graph_addr(state, state->pc, state->sp);
+                       return true;
+               }
+
+               if (info->type == STACK_TYPE_IRQ && info->end == state->sp) {
+                       regs = (struct pt_regs *)info->next_sp;
+                       pc = regs->csr_era;
+
+                       if (user_mode(regs) || !__kernel_text_address(pc))
+                               return false;
+
+                       state->first = true;
+                       state->pc = pc;
+                       state->ra = regs->regs[1];
+                       state->sp = regs->regs[3];
+                       get_stack_info(state->sp, state->task, info);
 
-               case UNWINDER_PROLOGUE:
-                       if (unwind_by_prologue(state)) {
-                               state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                                               state->pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-                               return true;
-                       }
-
-                       if (info->type == STACK_TYPE_IRQ &&
-                               info->end == state->sp) {
-                               regs = (struct pt_regs *)info->next_sp;
-                               pc = regs->csr_era;
-
-                               if (user_mode(regs) || !__kernel_text_address(pc))
-                                       return false;
-
-                               state->first = true;
-                               state->ra = regs->regs[1];
-                               state->sp = regs->regs[3];
-                               state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
-                                               pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
-                               get_stack_info(state->sp, state->task, info);
-
-                               return true;
-                       }
+                       return true;
                }
 
                state->sp = info->next_sp;
@@ -208,4 +228,36 @@ bool unwind_next_frame(struct unwind_state *state)
 
        return false;
 }
+
+unsigned long unwind_get_return_address(struct unwind_state *state)
+{
+       return __unwind_get_return_address(state);
+}
+EXPORT_SYMBOL_GPL(unwind_get_return_address);
+
+void unwind_start(struct unwind_state *state, struct task_struct *task,
+                   struct pt_regs *regs)
+{
+       __unwind_start(state, task, regs);
+       state->type = UNWINDER_PROLOGUE;
+       state->first = true;
+
+       /*
+        * The current PC is not kernel text address, we cannot find its
+        * relative symbol. Thus, prologue analysis will be broken. Luckily,
+        * we can use the default_next_frame().
+        */
+       if (!__kernel_text_address(state->pc)) {
+               state->type = UNWINDER_GUESS;
+               if (!unwind_done(state))
+                       unwind_next_frame(state);
+       }
+}
+EXPORT_SYMBOL_GPL(unwind_start);
+
+bool unwind_next_frame(struct unwind_state *state)
+{
+       return state->type == UNWINDER_PROLOGUE ?
+                       next_frame(state) : default_next_frame(state);
+}
 EXPORT_SYMBOL_GPL(unwind_next_frame);
index da3681f131c8d8a722b7f479775f7a48be47fc0a..8bad6b0cff59b96b2ebdda34214fdc1e4758e27e 100644 (file)
@@ -251,7 +251,7 @@ static void output_pgtable_bits_defines(void)
 }
 
 #ifdef CONFIG_NUMA
-static unsigned long pcpu_handlers[NR_CPUS];
+unsigned long pcpu_handlers[NR_CPUS];
 #endif
 extern long exception_handlers[VECSIZE * 128 / sizeof(long)];
 
index 4dfe1f49c5c8b2ffd884b0b806afb7b7b77bb89f..6817892a2c58577e5cf009df19e4d384f1d43af4 100644 (file)
@@ -1303,7 +1303,7 @@ static char iodc_dbuf[4096] __page_aligned_bss;
  */
 int pdc_iodc_print(const unsigned char *str, unsigned count)
 {
-       unsigned int i;
+       unsigned int i, found = 0;
        unsigned long flags;
 
        count = min_t(unsigned int, count, sizeof(iodc_dbuf));
@@ -1315,6 +1315,7 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
                        iodc_dbuf[i+0] = '\r';
                        iodc_dbuf[i+1] = '\n';
                        i += 2;
+                       found = 1;
                        goto print;
                default:
                        iodc_dbuf[i] = str[i];
@@ -1330,7 +1331,7 @@ print:
                __pa(pdc_result), 0, __pa(iodc_dbuf), i, 0);
        spin_unlock_irqrestore(&pdc_lock, flags);
 
-       return i;
+       return i - found;
 }
 
 #if !defined(BOOTLOADER)
index 69c62933e9525d0680302698fc4682e0dedd91b7..ceb45f51d52e982832b2788f02382824b3d1fd38 100644 (file)
@@ -126,6 +126,12 @@ long arch_ptrace(struct task_struct *child, long request,
        unsigned long tmp;
        long ret = -EIO;
 
+       unsigned long user_regs_struct_size = sizeof(struct user_regs_struct);
+#ifdef CONFIG_64BIT
+       if (is_compat_task())
+               user_regs_struct_size /= 2;
+#endif
+
        switch (request) {
 
        /* Read the word at location addr in the USER area.  For ptraced
@@ -166,7 +172,7 @@ long arch_ptrace(struct task_struct *child, long request,
                     addr >= sizeof(struct pt_regs))
                        break;
                if (addr == PT_IAOQ0 || addr == PT_IAOQ1) {
-                       data |= 3; /* ensure userspace privilege */
+                       data |= PRIV_USER; /* ensure userspace privilege */
                }
                if ((addr >= PT_GR1 && addr <= PT_GR31) ||
                                addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
@@ -181,14 +187,14 @@ long arch_ptrace(struct task_struct *child, long request,
                return copy_regset_to_user(child,
                                           task_user_regset_view(current),
                                           REGSET_GENERAL,
-                                          0, sizeof(struct user_regs_struct),
+                                          0, user_regs_struct_size,
                                           datap);
 
        case PTRACE_SETREGS:    /* Set all gp regs in the child. */
                return copy_regset_from_user(child,
                                             task_user_regset_view(current),
                                             REGSET_GENERAL,
-                                            0, sizeof(struct user_regs_struct),
+                                            0, user_regs_struct_size,
                                             datap);
 
        case PTRACE_GETFPREGS:  /* Get the child FPU state. */
@@ -285,7 +291,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        if (addr >= sizeof(struct pt_regs))
                                break;
                        if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) {
-                               data |= 3; /* ensure userspace privilege */
+                               data |= PRIV_USER; /* ensure userspace privilege */
                        }
                        if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
                                /* Special case, fp regs are 64 bits anyway */
@@ -302,6 +308,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        }
                }
                break;
+       case PTRACE_GETREGS:
+       case PTRACE_SETREGS:
+       case PTRACE_GETFPREGS:
+       case PTRACE_SETFPREGS:
+               return arch_ptrace(child, request, addr, data);
 
        default:
                ret = compat_ptrace_request(child, request, addr, data);
@@ -484,7 +495,7 @@ static void set_reg(struct pt_regs *regs, int num, unsigned long val)
        case RI(iaoq[0]):
        case RI(iaoq[1]):
                        /* set 2 lowest bits to ensure userspace privilege: */
-                       regs->iaoq[num - RI(iaoq[0])] = val | 3;
+                       regs->iaoq[num - RI(iaoq[0])] = val | PRIV_USER;
                        return;
        case RI(sar):   regs->sar = val;
                        return;
index dd39313242b4d964e9badbaca4a167e5ec56f4f3..d5cd16270c5d5791b4d30bb3950f53aabe5b0cb1 100644 (file)
@@ -97,6 +97,8 @@ static inline void tlb_flush(struct mmu_gather *tlb)
 {
        if (radix_enabled())
                radix__tlb_flush(tlb);
+
+       return hash__tlb_flush(tlb);
 }
 
 #ifdef CONFIG_SMP
index 77fa88c2aed0dc0febfe52073e7cba464821a4e7..eb6d094083fd684efb5065684b0781604de70aac 100644 (file)
@@ -173,6 +173,15 @@ static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
        return flags;
 }
 
+static inline notrace unsigned long irq_soft_mask_andc_return(unsigned long mask)
+{
+       unsigned long flags = irq_soft_mask_return();
+
+       irq_soft_mask_set(flags & ~mask);
+
+       return flags;
+}
+
 static inline unsigned long arch_local_save_flags(void)
 {
        return irq_soft_mask_return();
@@ -192,7 +201,7 @@ static inline void arch_local_irq_enable(void)
 
 static inline unsigned long arch_local_irq_save(void)
 {
-       return irq_soft_mask_set_return(IRQS_DISABLED);
+       return irq_soft_mask_or_return(IRQS_DISABLED);
 }
 
 static inline bool arch_irqs_disabled_flags(unsigned long flags)
@@ -331,10 +340,11 @@ bool power_pmu_wants_prompt_pmi(void);
  * is a different soft-masked interrupt pending that requires hard
  * masking.
  */
-static inline bool should_hard_irq_enable(void)
+static inline bool should_hard_irq_enable(struct pt_regs *regs)
 {
        if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
-               WARN_ON(irq_soft_mask_return() == IRQS_ENABLED);
+               WARN_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
+               WARN_ON(!(get_paca()->irq_happened & PACA_IRQ_HARD_DIS));
                WARN_ON(mfmsr() & MSR_EE);
        }
 
@@ -347,8 +357,17 @@ static inline bool should_hard_irq_enable(void)
         *
         * TODO: Add test for 64e
         */
-       if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !power_pmu_wants_prompt_pmi())
-               return false;
+       if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
+               if (!power_pmu_wants_prompt_pmi())
+                       return false;
+               /*
+                * If PMIs are disabled then IRQs should be disabled as well,
+                * so we shouldn't see this condition, check for it just in
+                * case because we are about to enable PMIs.
+                */
+               if (WARN_ON_ONCE(regs->softe & IRQS_PMI_DISABLED))
+                       return false;
+       }
 
        if (get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK)
                return false;
@@ -358,18 +377,16 @@ static inline bool should_hard_irq_enable(void)
 
 /*
  * Do the hard enabling, only call this if should_hard_irq_enable is true.
+ * This allows PMI interrupts to profile irq handlers.
  */
 static inline void do_hard_irq_enable(void)
 {
-       if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
-               WARN_ON(irq_soft_mask_return() == IRQS_ENABLED);
-               WARN_ON(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK);
-               WARN_ON(mfmsr() & MSR_EE);
-       }
        /*
-        * This allows PMI interrupts (and watchdog soft-NMIs) through.
-        * There is no other reason to enable this way.
+        * Asynch interrupts come in with IRQS_ALL_DISABLED,
+        * PACA_IRQ_HARD_DIS, and MSR[EE]=0.
         */
+       if (IS_ENABLED(CONFIG_PPC_BOOK3S_64))
+               irq_soft_mask_andc_return(IRQS_PMI_DISABLED);
        get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
        __hard_irq_enable();
 }
@@ -452,7 +469,7 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
        return !(regs->msr & MSR_EE);
 }
 
-static __always_inline bool should_hard_irq_enable(void)
+static __always_inline bool should_hard_irq_enable(struct pt_regs *regs)
 {
        return false;
 }
index f55c6fb34a3a03b3d48c4d52a6e1d6492d8fec62..5712dd846263c5014f74236549cebe8d9c5e0348 100644 (file)
@@ -27,7 +27,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(doorbell_exception)
 
        ppc_msgsync();
 
-       if (should_hard_irq_enable())
+       if (should_hard_irq_enable(regs))
                do_hard_irq_enable();
 
        kvmppc_clear_host_ipi(smp_processor_id());
index d438ca74e96cc9756735a3d934fedc96c3f3aa8c..fdbee1093e2baadc82ad7860a2860d282722d41d 100644 (file)
@@ -864,7 +864,7 @@ _GLOBAL(load_up_spe)
  * SPE unavailable trap from kernel - print a message, but let
  * the task use SPE in the kernel until it returns to user mode.
  */
-KernelSPE:
+SYM_FUNC_START_LOCAL(KernelSPE)
        lwz     r3,_MSR(r1)
        oris    r3,r3,MSR_SPE@h
        stw     r3,_MSR(r1)     /* enable use of SPE after return */
@@ -881,6 +881,7 @@ KernelSPE:
 #endif
        .align  4,0
 
+SYM_FUNC_END(KernelSPE)
 #endif /* CONFIG_SPE */
 
 /*
index c5b9ce8874834afccf3c822af51313cf5e544dcd..c9535f2760b5b73fafa49147e4633e8372b98f7f 100644 (file)
@@ -238,7 +238,7 @@ static void __do_irq(struct pt_regs *regs, unsigned long oldsp)
        irq = static_call(ppc_get_irq)();
 
        /* We can hard enable interrupts now to allow perf interrupts */
-       if (should_hard_irq_enable())
+       if (should_hard_irq_enable(regs))
                do_hard_irq_enable();
 
        /* And finally process it */
index d68de3618741e19b3b9eb3d90b5ff97ddbc09c26..e26eb6618ae5d2992a7043476d6d4843ab0341c3 100644 (file)
@@ -515,7 +515,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
        }
 
        /* Conditionally hard-enable interrupts. */
-       if (should_hard_irq_enable()) {
+       if (should_hard_irq_enable(regs)) {
                /*
                 * Ensure a positive value is written to the decrementer, or
                 * else some CPUs will continue to take decrementer exceptions.
index af8854f9eae3c85645a8482cadbaf84524b017e4..52085751f5f4cdace8f17727e4cc23340adb41b0 100644 (file)
@@ -989,10 +989,13 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image)
         * linux,drconf-usable-memory properties. Get an approximate on the
         * number of usable memory entries and use for FDT size estimation.
         */
-       usm_entries = ((memblock_end_of_DRAM() / drmem_lmb_size()) +
-                      (2 * (resource_size(&crashk_res) / drmem_lmb_size())));
-
-       extra_size = (unsigned int)(usm_entries * sizeof(u64));
+       if (drmem_lmb_size()) {
+               usm_entries = ((memory_hotplug_max() / drmem_lmb_size()) +
+                              (2 * (resource_size(&crashk_res) / drmem_lmb_size())));
+               extra_size = (unsigned int)(usm_entries * sizeof(u64));
+       } else {
+               extra_size = 0;
+       }
 
        /*
         * Get the number of CPU nodes in the current DT. This allows to
index 0dce93ccaadfa23a81dde9ae98f8de92ee76f07a..e89281d3ba281940e2693c2cd741befb672ae174 100644 (file)
@@ -912,16 +912,15 @@ static int kvmppc_handle_debug(struct kvm_vcpu *vcpu)
 
 static void kvmppc_fill_pt_regs(struct pt_regs *regs)
 {
-       ulong r1, ip, msr, lr;
+       ulong r1, msr, lr;
 
        asm("mr %0, 1" : "=r"(r1));
        asm("mflr %0" : "=r"(lr));
        asm("mfmsr %0" : "=r"(msr));
-       asm("bl 1f; 1: mflr %0" : "=r"(ip));
 
        memset(regs, 0, sizeof(*regs));
        regs->gpr[1] = r1;
-       regs->nip = ip;
+       regs->nip = _THIS_IP_;
        regs->msr = msr;
        regs->link = lr;
 }
index cac727b0179990706fd1dd235a6e3928fc55a024..26245aaf12b8bddb8f6082ce5b2b3c093f2e00cc 100644 (file)
@@ -234,6 +234,14 @@ void radix__mark_rodata_ro(void)
        end = (unsigned long)__end_rodata;
 
        radix__change_memory_range(start, end, _PAGE_WRITE);
+
+       for (start = PAGE_OFFSET; start < (unsigned long)_stext; start += PAGE_SIZE) {
+               end = start + PAGE_SIZE;
+               if (overlaps_interrupt_vector_text(start, end))
+                       radix__change_memory_range(start, end, _PAGE_WRITE);
+               else
+                       break;
+       }
 }
 
 void radix__mark_initmem_nx(void)
@@ -262,6 +270,22 @@ print_mapping(unsigned long start, unsigned long end, unsigned long size, bool e
 static unsigned long next_boundary(unsigned long addr, unsigned long end)
 {
 #ifdef CONFIG_STRICT_KERNEL_RWX
+       unsigned long stext_phys;
+
+       stext_phys = __pa_symbol(_stext);
+
+       // Relocatable kernel running at non-zero real address
+       if (stext_phys != 0) {
+               // The end of interrupts code at zero is a rodata boundary
+               unsigned long end_intr = __pa_symbol(__end_interrupts) - stext_phys;
+               if (addr < end_intr)
+                       return end_intr;
+
+               // Start of relocated kernel text is a rodata boundary
+               if (addr < stext_phys)
+                       return stext_phys;
+       }
+
        if (addr < __pa_symbol(__srwx_boundary))
                return __pa_symbol(__srwx_boundary);
 #endif
index 100e97daf76ba140de318eb029cc9f69cba2df3d..9d229ef7f86efa3b085cba41931f4b4c544f51d3 100644 (file)
@@ -22,7 +22,7 @@
  * Used to avoid races in counting the nest-pmu units during hotplug
  * register and unregister
  */
-static DEFINE_SPINLOCK(nest_init_lock);
+static DEFINE_MUTEX(nest_init_lock);
 static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc);
 static struct imc_pmu **per_nest_pmu_arr;
 static cpumask_t nest_imc_cpumask;
@@ -1629,7 +1629,7 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr)
 static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
 {
        if (pmu_ptr->domain == IMC_DOMAIN_NEST) {
-               spin_lock(&nest_init_lock);
+               mutex_lock(&nest_init_lock);
                if (nest_pmus == 1) {
                        cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
                        kfree(nest_imc_refc);
@@ -1639,7 +1639,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
 
                if (nest_pmus > 0)
                        nest_pmus--;
-               spin_unlock(&nest_init_lock);
+               mutex_unlock(&nest_init_lock);
        }
 
        /* Free core_imc memory */
@@ -1796,11 +1796,11 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
                * rest. To handle the cpuhotplug callback unregister, we track
                * the number of nest pmus in "nest_pmus".
                */
-               spin_lock(&nest_init_lock);
+               mutex_lock(&nest_init_lock);
                if (nest_pmus == 0) {
                        ret = init_nest_pmu_ref();
                        if (ret) {
-                               spin_unlock(&nest_init_lock);
+                               mutex_unlock(&nest_init_lock);
                                kfree(per_nest_pmu_arr);
                                per_nest_pmu_arr = NULL;
                                goto err_free_mem;
@@ -1808,7 +1808,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
                        /* Register for cpu hotplug notification. */
                        ret = nest_pmu_cpumask_init();
                        if (ret) {
-                               spin_unlock(&nest_init_lock);
+                               mutex_unlock(&nest_init_lock);
                                kfree(nest_imc_refc);
                                kfree(per_nest_pmu_arr);
                                per_nest_pmu_arr = NULL;
@@ -1816,7 +1816,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
                        }
                }
                nest_pmus++;
-               spin_unlock(&nest_init_lock);
+               mutex_unlock(&nest_init_lock);
                break;
        case IMC_DOMAIN_CORE:
                ret = core_imc_pmu_cpumask_init();
index faf2c2177094bbb835face6568088c447ddd092a..82153960ac001e1ffb4e2e9336ecc3d71c6fd0ee 100644 (file)
@@ -80,6 +80,9 @@ ifeq ($(CONFIG_PERF_EVENTS),y)
         KBUILD_CFLAGS += -fno-omit-frame-pointer
 endif
 
+# Avoid generating .eh_frame sections.
+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
+
 KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
 KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax)
 
index 43bed6c0a84fe81b10189f53842d739348b25f34..5235fd1c9cb6773d2f23562fe999ffa0ca21dc6b 100644 (file)
                        bus-range = <0x0 0xff>;
                        ranges = <0x81000000  0x0 0x60080000  0x0 0x60080000 0x0 0x10000>,      /* I/O */
                                 <0x82000000  0x0 0x60090000  0x0 0x60090000 0x0 0xff70000>,    /* mem */
-                                <0x82000000  0x0 0x70000000  0x0 0x70000000 0x0 0x1000000>,    /* mem */
+                                <0x82000000  0x0 0x70000000  0x0 0x70000000 0x0 0x10000000>,    /* mem */
                                 <0xc3000000 0x20 0x00000000 0x20 0x00000000 0x20 0x00000000>;  /* mem prefetchable */
                        num-lanes = <0x8>;
                        interrupts = <56>, <57>, <58>, <59>, <60>, <61>, <62>, <63>, <64>;
index 7226e2462584b65a78f7601c47e744ed7d6a54fc..2c0f4c887289a53dc457b356a1e754114aba4185 100644 (file)
@@ -46,7 +46,7 @@
 
 .macro ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1,   \
                                new_c_2, vendor_id_2, errata_id_2, enable_2
-       ALTERNATIVE_CFG \old_c, \new_c_1, \vendor_id_1, \errata_id_1, \enable_1
+       ALTERNATIVE_CFG "\old_c", "\new_c_1", \vendor_id_1, \errata_id_1, \enable_1
        ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2
 .endm
 
index 86328e3acb02ee3b5752642039c2cdd2806989a1..64ad1937e71494b17389697549fcec5cade84939 100644 (file)
@@ -70,7 +70,6 @@ static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX);
  */
 enum riscv_isa_ext_key {
        RISCV_ISA_EXT_KEY_FPU,          /* For 'F' and 'D' */
-       RISCV_ISA_EXT_KEY_ZIHINTPAUSE,
        RISCV_ISA_EXT_KEY_SVINVAL,
        RISCV_ISA_EXT_KEY_MAX,
 };
@@ -91,8 +90,6 @@ static __always_inline int riscv_isa_ext2key(int num)
                return RISCV_ISA_EXT_KEY_FPU;
        case RISCV_ISA_EXT_d:
                return RISCV_ISA_EXT_KEY_FPU;
-       case RISCV_ISA_EXT_ZIHINTPAUSE:
-               return RISCV_ISA_EXT_KEY_ZIHINTPAUSE;
        case RISCV_ISA_EXT_SVINVAL:
                return RISCV_ISA_EXT_KEY_SVINVAL;
        default:
index fa70cfe507aa118260d1d751cc1b7658fa739349..14f5d27783b85811a4f7e6e1d43c9b5ee9aca5a1 100644 (file)
@@ -4,30 +4,26 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/jump_label.h>
 #include <asm/barrier.h>
-#include <asm/hwcap.h>
 
 static inline void cpu_relax(void)
 {
-       if (!static_branch_likely(&riscv_isa_ext_keys[RISCV_ISA_EXT_KEY_ZIHINTPAUSE])) {
 #ifdef __riscv_muldiv
-               int dummy;
-               /* In lieu of a halt instruction, induce a long-latency stall. */
-               __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
+       int dummy;
+       /* In lieu of a halt instruction, induce a long-latency stall. */
+       __asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
 #endif
-       } else {
-               /*
-                * Reduce instruction retirement.
-                * This assumes the PC changes.
-                */
-#ifdef CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE
-               __asm__ __volatile__ ("pause");
+
+#ifdef __riscv_zihintpause
+       /*
+        * Reduce instruction retirement.
+        * This assumes the PC changes.
+        */
+       __asm__ __volatile__ ("pause");
 #else
-               /* Encoding of the pause instruction */
-               __asm__ __volatile__ (".4byte 0x100000F");
+       /* Encoding of the pause instruction */
+       __asm__ __volatile__ (".4byte 0x100000F");
 #endif
-       }
        barrier();
 }
 
index b865046e4dbbc489ff4ed3c21e231bfeeba45158..4bf6c449d78b6a0719bfb3c7e9bbed927b71deb2 100644 (file)
@@ -326,7 +326,7 @@ clear_bss_done:
        call soc_early_init
        tail start_kernel
 
-#if CONFIG_RISCV_BOOT_SPINWAIT
+#ifdef CONFIG_RISCV_BOOT_SPINWAIT
 .Lsecondary_start:
        /* Set trap vector to spin forever to help debug */
        la a3, .Lsecondary_park
index f21592d203062ac2f9db083364f2e7d526e0ba8e..41c7481afde368ce2bdc75475aa52345b79ad980 100644 (file)
@@ -48,6 +48,21 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
        post_kprobe_handler(p, kcb, regs);
 }
 
+static bool __kprobes arch_check_kprobe(struct kprobe *p)
+{
+       unsigned long tmp  = (unsigned long)p->addr - p->offset;
+       unsigned long addr = (unsigned long)p->addr;
+
+       while (tmp <= addr) {
+               if (tmp == addr)
+                       return true;
+
+               tmp += GET_INSN_LENGTH(*(u16 *)tmp);
+       }
+
+       return false;
+}
+
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        unsigned long probe_addr = (unsigned long)p->addr;
@@ -55,6 +70,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        if (probe_addr & 0x1)
                return -EILSEQ;
 
+       if (!arch_check_kprobe(p))
+               return -EILSEQ;
+
        /* copy instruction */
        p->opcode = *p->addr;
 
index d73e96f6ed7c59dafdaebb916598c69df9f15c1b..a20568bd1f1a885909009b4e14460ab73ada2b90 100644 (file)
@@ -71,11 +71,11 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
        u32 rd_index = (opcode >> 7) & 0x1f;
        u32 rs1_index = (opcode >> 15) & 0x1f;
 
-       ret = rv_insn_reg_set_val(regs, rd_index, addr + 4);
+       ret = rv_insn_reg_get_val(regs, rs1_index, &base_addr);
        if (!ret)
                return ret;
 
-       ret = rv_insn_reg_get_val(regs, rs1_index, &base_addr);
+       ret = rv_insn_reg_set_val(regs, rd_index, addr + 4);
        if (!ret)
                return ret;
 
index 3373df413c8820682ea4770f622b6fbbc0003865..ddb2afba6d25558c26748f8f63dd1dc1702b5e89 100644 (file)
@@ -39,7 +39,6 @@ static DECLARE_COMPLETION(cpu_running);
 
 void __init smp_prepare_boot_cpu(void)
 {
-       init_cpu_topology();
 }
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -48,6 +47,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        int ret;
        unsigned int curr_cpuid;
 
+       init_cpu_topology();
+
        curr_cpuid = smp_processor_id();
        store_cpu_topology(curr_cpuid);
        numa_store_cpu_info(curr_cpuid);
index 8dcd7af2911a07c36d792aa0366314579b512e28..b519a1f045d8f290251c3e810df60821f2134829 100644 (file)
@@ -80,6 +80,6 @@ void *decompress_kernel(void)
        void *output = (void *)decompress_offset;
 
        __decompress(_compressed_start, _compressed_end - _compressed_start,
-                    NULL, NULL, output, 0, NULL, error);
+                    NULL, NULL, output, vmlinux.image_size, NULL, error);
        return output;
 }
index 2b6091349daa2553c504a362ed1e7339aff8bd62..696c9e007a369d8df883317bdde15c1717a5bfef 100644 (file)
@@ -508,6 +508,7 @@ static void __init setup_lowcore_dat_on(void)
 {
        struct lowcore *abs_lc;
        unsigned long flags;
+       int i;
 
        __ctl_clear_bit(0, 28);
        S390_lowcore.external_new_psw.mask |= PSW_MASK_DAT;
@@ -523,8 +524,8 @@ static void __init setup_lowcore_dat_on(void)
        abs_lc = get_abs_lowcore(&flags);
        abs_lc->restart_flags = RESTART_FLAG_CTLREGS;
        abs_lc->program_new_psw = S390_lowcore.program_new_psw;
-       memcpy(abs_lc->cregs_save_area, S390_lowcore.cregs_save_area,
-              sizeof(abs_lc->cregs_save_area));
+       for (i = 0; i < 16; i++)
+               abs_lc->cregs_save_area[i] = S390_lowcore.cregs_save_area[i];
        put_abs_lowcore(abs_lc, flags);
 }
 
index 3161b9ccd2a5707e6c039c30c9f05c6708bd76b6..b6276a3521d73bcc716745b12284e0f748c4b4e4 100644 (file)
@@ -4,6 +4,7 @@
  * Written by Niibe Yutaka and Paul Mundt
  */
 OUTPUT_ARCH(sh)
+#define RUNTIME_DISCARD_EXIT
 #include <asm/thread_info.h>
 #include <asm/cache.h>
 #include <asm/vmlinux.lds.h>
index 9cf07322875a42f914f16505a16003250f02cceb..73ed982d41000059e6d0f7e78c90e87d7f7d0390 100644 (file)
@@ -14,13 +14,13 @@ endif
 
 ifdef CONFIG_CC_IS_GCC
 RETPOLINE_CFLAGS       := $(call cc-option,-mindirect-branch=thunk-extern -mindirect-branch-register)
-RETPOLINE_CFLAGS       += $(call cc-option,-mindirect-branch-cs-prefix)
 RETPOLINE_VDSO_CFLAGS  := $(call cc-option,-mindirect-branch=thunk-inline -mindirect-branch-register)
 endif
 ifdef CONFIG_CC_IS_CLANG
 RETPOLINE_CFLAGS       := -mretpoline-external-thunk
 RETPOLINE_VDSO_CFLAGS  := -mretpoline
 endif
+RETPOLINE_CFLAGS       += $(call cc-option,-mindirect-branch-cs-prefix)
 
 ifdef CONFIG_RETHUNK
 RETHUNK_CFLAGS         := -mfunction-return=thunk-extern
index d4a314cc50d6ee6ecaa7268f59bbb946c71fb916..321a5011042d40f51120ff910786f6c17e80aaef 100644 (file)
@@ -180,6 +180,12 @@ void initialize_identity_maps(void *rmode)
 
        /* Load the new page-table. */
        write_cr3(top_level_pgt);
+
+       /*
+        * Now that the required page table mappings are established and a
+        * GHCB can be used, check for SNP guest/HV feature compatibility.
+        */
+       snp_check_features();
 }
 
 static pte_t *split_large_pmd(struct x86_mapping_info *info,
index 62208ec04ca4b800e7cf3eb8949f6cf6a228fee2..20118fb7c53bbbec630a87cac129096a311ebef0 100644 (file)
@@ -126,6 +126,7 @@ static inline void console_init(void)
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 void sev_enable(struct boot_params *bp);
+void snp_check_features(void);
 void sev_es_shutdown_ghcb(void);
 extern bool sev_es_check_ghcb_fault(unsigned long address);
 void snp_set_page_private(unsigned long paddr);
@@ -143,6 +144,7 @@ static inline void sev_enable(struct boot_params *bp)
        if (bp)
                bp->cc_blob_address = 0;
 }
+static inline void snp_check_features(void) { }
 static inline void sev_es_shutdown_ghcb(void) { }
 static inline bool sev_es_check_ghcb_fault(unsigned long address)
 {
index c93930d5ccbd0f1b4894012e09c885e20ee1ba0a..d63ad8f99f83a3c616f3560cd12f3ea03acbe049 100644 (file)
@@ -208,6 +208,23 @@ void sev_es_shutdown_ghcb(void)
                error("Can't unmap GHCB page");
 }
 
+static void __noreturn sev_es_ghcb_terminate(struct ghcb *ghcb, unsigned int set,
+                                            unsigned int reason, u64 exit_info_2)
+{
+       u64 exit_info_1 = SVM_VMGEXIT_TERM_REASON(set, reason);
+
+       vc_ghcb_invalidate(ghcb);
+       ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_TERM_REQUEST);
+       ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
+       ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
+
+       sev_es_wr_ghcb_msr(__pa(ghcb));
+       VMGEXIT();
+
+       while (true)
+               asm volatile("hlt\n" : : : "memory");
+}
+
 bool sev_es_check_ghcb_fault(unsigned long address)
 {
        /* Check whether the fault was on the GHCB page */
@@ -270,6 +287,59 @@ static void enforce_vmpl0(void)
                sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
 }
 
+/*
+ * SNP_FEATURES_IMPL_REQ is the mask of SNP features that will need
+ * guest side implementation for proper functioning of the guest. If any
+ * of these features are enabled in the hypervisor but are lacking guest
+ * side implementation, the behavior of the guest will be undefined. The
+ * guest could fail in non-obvious way making it difficult to debug.
+ *
+ * As the behavior of reserved feature bits is unknown to be on the
+ * safe side add them to the required features mask.
+ */
+#define SNP_FEATURES_IMPL_REQ  (MSR_AMD64_SNP_VTOM |                   \
+                                MSR_AMD64_SNP_REFLECT_VC |             \
+                                MSR_AMD64_SNP_RESTRICTED_INJ |         \
+                                MSR_AMD64_SNP_ALT_INJ |                \
+                                MSR_AMD64_SNP_DEBUG_SWAP |             \
+                                MSR_AMD64_SNP_VMPL_SSS |               \
+                                MSR_AMD64_SNP_SECURE_TSC |             \
+                                MSR_AMD64_SNP_VMGEXIT_PARAM |          \
+                                MSR_AMD64_SNP_VMSA_REG_PROTECTION |    \
+                                MSR_AMD64_SNP_RESERVED_BIT13 |         \
+                                MSR_AMD64_SNP_RESERVED_BIT15 |         \
+                                MSR_AMD64_SNP_RESERVED_MASK)
+
+/*
+ * SNP_FEATURES_PRESENT is the mask of SNP features that are implemented
+ * by the guest kernel. As and when a new feature is implemented in the
+ * guest kernel, a corresponding bit should be added to the mask.
+ */
+#define SNP_FEATURES_PRESENT (0)
+
+void snp_check_features(void)
+{
+       u64 unsupported;
+
+       if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
+               return;
+
+       /*
+        * Terminate the boot if hypervisor has enabled any feature lacking
+        * guest side implementation. Pass on the unsupported features mask through
+        * EXIT_INFO_2 of the GHCB protocol so that those features can be reported
+        * as part of the guest boot failure.
+        */
+       unsupported = sev_status & SNP_FEATURES_IMPL_REQ & ~SNP_FEATURES_PRESENT;
+       if (unsupported) {
+               if (ghcb_version < 2 || (!boot_ghcb && !early_setup_ghcb()))
+                       sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+
+               sev_es_ghcb_terminate(boot_ghcb, SEV_TERM_SET_GEN,
+                                     GHCB_SNP_UNSUPPORTED, unsupported);
+       }
+}
+
 void sev_enable(struct boot_params *bp)
 {
        unsigned int eax, ebx, ecx, edx;
index dfd2c124cdf80a819570340caa2b886887d57890..bafdc2be479acedff68fac4fa9103cf83836ab36 100644 (file)
@@ -6339,6 +6339,7 @@ __init int intel_pmu_init(void)
                break;
 
        case INTEL_FAM6_SAPPHIRERAPIDS_X:
+       case INTEL_FAM6_EMERALDRAPIDS_X:
                pmem = true;
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, spr_hw_cache_event_ids, sizeof(hw_cache_event_ids));
index 3019fb1926e358ad12d50ba2fe1392bbbf235069..551741e79e038a20b2d7b519dd2a6a560b86d1f6 100644 (file)
@@ -677,6 +677,7 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,           &icx_cstates),
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,           &icx_cstates),
        X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,    &icx_cstates),
+       X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X,     &icx_cstates),
 
        X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L,         &icl_cstates),
        X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE,           &icl_cstates),
index 65064d9f7fa6ead3835194be565b10bf26cfb909..8eb74cf386dbe5cac24c25fca9422a99212ab9b7 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/mmu.h>
 #include <asm/mpspec.h>
 #include <asm/x86_init.h>
+#include <asm/cpufeature.h>
 
 #ifdef CONFIG_ACPI_APEI
 # include <asm/pgtable_types.h>
@@ -63,6 +64,13 @@ extern int (*acpi_suspend_lowlevel)(void);
 /* Physical address to resume after wakeup */
 unsigned long acpi_get_wakeup_address(void);
 
+static inline bool acpi_skip_set_wakeup_address(void)
+{
+       return cpu_feature_enabled(X86_FEATURE_XENPV);
+}
+
+#define acpi_skip_set_wakeup_address acpi_skip_set_wakeup_address
+
 /*
  * Check if the CPU can handle C2 and deeper
  */
index b049d950612fdd7c01b0508adcb9d8014ad9545f..ca97442e8d49fcc474fd846cda7b3acfb7cd5b24 100644 (file)
@@ -39,7 +39,20 @@ static __always_inline unsigned long native_get_debugreg(int regno)
                asm("mov %%db6, %0" :"=r" (val));
                break;
        case 7:
-               asm("mov %%db7, %0" :"=r" (val));
+               /*
+                * Apply __FORCE_ORDER to DR7 reads to forbid re-ordering them
+                * with other code.
+                *
+                * This is needed because a DR7 access can cause a #VC exception
+                * when running under SEV-ES. Taking a #VC exception is not a
+                * safe thing to do just anywhere in the entry code and
+                * re-ordering might place the access into an unsafe location.
+                *
+                * This happened in the NMI handler, where the DR7 read was
+                * re-ordered to happen before the call to sev_es_ist_enter(),
+                * causing stack recursion.
+                */
+               asm volatile("mov %%db7, %0" : "=r" (val) : __FORCE_ORDER);
                break;
        default:
                BUG();
@@ -66,7 +79,16 @@ static __always_inline void native_set_debugreg(int regno, unsigned long value)
                asm("mov %0, %%db6"     ::"r" (value));
                break;
        case 7:
-               asm("mov %0, %%db7"     ::"r" (value));
+               /*
+                * Apply __FORCE_ORDER to DR7 writes to forbid re-ordering them
+                * with other code.
+                *
+                * While is didn't happen with a DR7 write (see the DR7 read
+                * comment above which explains where it happened), add the
+                * __FORCE_ORDER here too to avoid similar problems in the
+                * future.
+                */
+               asm volatile("mov %0, %%db7"    ::"r" (value), __FORCE_ORDER);
                break;
        default:
                BUG();
index 37ff47552bcb7b57fdc75bc0246f2bb3876add4a..d3fe82c5d6b660d103788298d5f04a5a86a08104 100644 (file)
 #define MSR_AMD64_SEV_ES_ENABLED       BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT)
 #define MSR_AMD64_SEV_SNP_ENABLED      BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT)
 
+/* SNP feature bits enabled by the hypervisor */
+#define MSR_AMD64_SNP_VTOM                     BIT_ULL(3)
+#define MSR_AMD64_SNP_REFLECT_VC               BIT_ULL(4)
+#define MSR_AMD64_SNP_RESTRICTED_INJ           BIT_ULL(5)
+#define MSR_AMD64_SNP_ALT_INJ                  BIT_ULL(6)
+#define MSR_AMD64_SNP_DEBUG_SWAP               BIT_ULL(7)
+#define MSR_AMD64_SNP_PREVENT_HOST_IBS         BIT_ULL(8)
+#define MSR_AMD64_SNP_BTB_ISOLATION            BIT_ULL(9)
+#define MSR_AMD64_SNP_VMPL_SSS                 BIT_ULL(10)
+#define MSR_AMD64_SNP_SECURE_TSC               BIT_ULL(11)
+#define MSR_AMD64_SNP_VMGEXIT_PARAM            BIT_ULL(12)
+#define MSR_AMD64_SNP_IBS_VIRT                 BIT_ULL(14)
+#define MSR_AMD64_SNP_VMSA_REG_PROTECTION      BIT_ULL(16)
+#define MSR_AMD64_SNP_SMT_PROTECTION           BIT_ULL(17)
+
+/* SNP feature bits reserved for future use. */
+#define MSR_AMD64_SNP_RESERVED_BIT13           BIT_ULL(13)
+#define MSR_AMD64_SNP_RESERVED_BIT15           BIT_ULL(15)
+#define MSR_AMD64_SNP_RESERVED_MASK            GENMASK_ULL(63, 18)
+
 #define MSR_AMD64_VIRT_SPEC_CTRL       0xc001011f
 
 /* AMD Collaborative Processor Performance Control MSRs */
index f69c168391aa58cf280ba6fb5aca6630e3593d1a..80e1df482337dfe064d809966a309cecd0930070 100644 (file)
 #define SVM_VMGEXIT_AP_CREATE                  1
 #define SVM_VMGEXIT_AP_DESTROY                 2
 #define SVM_VMGEXIT_HV_FEATURES                        0x8000fffd
+#define SVM_VMGEXIT_TERM_REQUEST               0x8000fffe
+#define SVM_VMGEXIT_TERM_REASON(reason_set, reason_code)       \
+       /* SW_EXITINFO1[3:0] */                                 \
+       (((((u64)reason_set) & 0xf)) |                          \
+       /* SW_EXITINFO1[11:4] */                                \
+       ((((u64)reason_code) & 0xff) << 4))
 #define SVM_VMGEXIT_UNSUPPORTED_EVENT          0x8000ffff
 
 /* Exit code reserved for hypervisor/software use */
index 1f60a2b279368e94c79f64ea43f736baf966f39f..fdbb5f07448fad0dd267868fdfb0a6394d9e45b9 100644 (file)
@@ -330,7 +330,16 @@ static void __init bp_init_freq_invariance(void)
 
 static void disable_freq_invariance_workfn(struct work_struct *work)
 {
+       int cpu;
+
        static_branch_disable(&arch_scale_freq_key);
+
+       /*
+        * Set arch_freq_scale to a default value on all cpus
+        * This negates the effect of scaling
+        */
+       for_each_possible_cpu(cpu)
+               per_cpu(arch_freq_scale, cpu) = SCHED_CAPACITY_SCALE;
 }
 
 static DECLARE_WORK(disable_freq_invariance_work,
index 3aa5304200c5073d380ddcbe240d49b09129fab2..4d8aff05a509ec4ca413b08e3d26ca812f5d94e7 100644 (file)
@@ -114,6 +114,7 @@ static void make_8259A_irq(unsigned int irq)
        disable_irq_nosync(irq);
        io_apic_irqs &= ~(1<<irq);
        irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
+       irq_set_status_flags(irq, IRQ_LEVEL);
        enable_irq(irq);
        lapic_assign_legacy_vector(irq, true);
 }
index beb1bada1b0ab2da5c5bd6d6b6ddde8ee6245d4b..c683666876f1c7026acf5b4d63b93381181e1801 100644 (file)
@@ -65,8 +65,10 @@ void __init init_ISA_irqs(void)
 
        legacy_pic->init(0);
 
-       for (i = 0; i < nr_legacy_irqs(); i++)
+       for (i = 0; i < nr_legacy_irqs(); i++) {
                irq_set_chip_and_handler(i, chip, handle_level_irq);
+               irq_set_status_flags(i, IRQ_LEVEL);
+       }
 }
 
 void __init init_IRQ(void)
index fc9008dbed33487b472e4966a20b56cbcc4c4580..7eec0226d56a246681fa04236d12ecb5bdf0fada 100644 (file)
@@ -3440,18 +3440,15 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var)
 {
        u32 ar;
 
-       if (var->unusable || !var->present)
-               ar = 1 << 16;
-       else {
-               ar = var->type & 15;
-               ar |= (var->s & 1) << 4;
-               ar |= (var->dpl & 3) << 5;
-               ar |= (var->present & 1) << 7;
-               ar |= (var->avl & 1) << 12;
-               ar |= (var->l & 1) << 13;
-               ar |= (var->db & 1) << 14;
-               ar |= (var->g & 1) << 15;
-       }
+       ar = var->type & 15;
+       ar |= (var->s & 1) << 4;
+       ar |= (var->dpl & 3) << 5;
+       ar |= (var->present & 1) << 7;
+       ar |= (var->avl & 1) << 12;
+       ar |= (var->l & 1) << 13;
+       ar |= (var->db & 1) << 14;
+       ar |= (var->g & 1) << 15;
+       ar |= (var->unusable || !var->present) << 16;
 
        return ar;
 }
index b94f727251b6436d3101cb6d0abe04c7fc13a660..8babce71915fe514aa24cfdb25f36c98ddc90369 100644 (file)
@@ -392,6 +392,7 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
        msi_for_each_desc(msidesc, &dev->dev, MSI_DESC_ASSOCIATED) {
                for (i = 0; i < msidesc->nvec_used; i++)
                        xen_destroy_irq(msidesc->irq + i);
+               msidesc->irq = 0;
        }
 }
 
@@ -433,6 +434,7 @@ static struct msi_domain_ops xen_pci_msi_domain_ops = {
 };
 
 static struct msi_domain_info xen_pci_msi_domain_info = {
+       .flags                  = MSI_FLAG_PCI_MSIX | MSI_FLAG_FREE_MSI_DESCS | MSI_FLAG_DEV_SYSFS,
        .ops                    = &xen_pci_msi_domain_ops,
 };
 
index 1b2829e99dad02cab2b04a417d87f9481023053e..0fbde0fc06287ce150cc37125fbb31d103952d15 100644 (file)
@@ -316,14 +316,12 @@ struct bfq_group *bfqq_group(struct bfq_queue *bfqq)
 
 static void bfqg_get(struct bfq_group *bfqg)
 {
-       bfqg->ref++;
+       refcount_inc(&bfqg->ref);
 }
 
 static void bfqg_put(struct bfq_group *bfqg)
 {
-       bfqg->ref--;
-
-       if (bfqg->ref == 0)
+       if (refcount_dec_and_test(&bfqg->ref))
                kfree(bfqg);
 }
 
@@ -530,7 +528,7 @@ static struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, struct request_queue *q,
        }
 
        /* see comments in bfq_bic_update_cgroup for why refcounting */
-       bfqg_get(bfqg);
+       refcount_set(&bfqg->ref, 1);
        return &bfqg->pd;
 }
 
@@ -771,8 +769,8 @@ static void __bfq_bic_change_cgroup(struct bfq_data *bfqd,
                                 * request from the old cgroup.
                                 */
                                bfq_put_cooperator(sync_bfqq);
-                               bfq_release_process_ref(bfqd, sync_bfqq);
                                bic_set_bfqq(bic, NULL, true);
+                               bfq_release_process_ref(bfqd, sync_bfqq);
                        }
                }
        }
index ccf2204477a57b44a7522fa299dca123d9041278..380e9bda2e57c5652dfe5645504987f749101d36 100644 (file)
@@ -5425,9 +5425,11 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio)
 
        bfqq = bic_to_bfqq(bic, false);
        if (bfqq) {
-               bfq_release_process_ref(bfqd, bfqq);
+               struct bfq_queue *old_bfqq = bfqq;
+
                bfqq = bfq_get_queue(bfqd, bio, false, bic, true);
                bic_set_bfqq(bic, bfqq, false);
+               bfq_release_process_ref(bfqd, old_bfqq);
        }
 
        bfqq = bic_to_bfqq(bic, true);
index 41aa151ccc223457621abb30e24ec8a02701346b..466e4865ace63d1f12f897686442652da6e615a2 100644 (file)
@@ -928,7 +928,7 @@ struct bfq_group {
        char blkg_path[128];
 
        /* reference counter (see comments in bfq_bic_update_cgroup) */
-       int ref;
+       refcount_t ref;
        /* Is bfq_group still online? */
        bool online;
 
index ce6a2b7d3dfb2b405e013393ffe8e90e92be504e..9ac1efb053e08cca76d732b90989a219536bb802 100644 (file)
@@ -1455,6 +1455,10 @@ retry:
                list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
                        pol->pd_init_fn(blkg->pd[pol->plid]);
 
+       if (pol->pd_online_fn)
+               list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
+                       pol->pd_online_fn(blkg->pd[pol->plid]);
+
        __set_bit(pol->plid, q->blkcg_pols);
        ret = 0;
 
@@ -1997,6 +2001,10 @@ void blk_cgroup_bio_start(struct bio *bio)
        struct blkg_iostat_set *bis;
        unsigned long flags;
 
+       /* Root-level stats are sourced from system-wide IO stats */
+       if (!cgroup_parent(blkcg->css.cgroup))
+               return;
+
        cpu = get_cpu();
        bis = per_cpu_ptr(bio->bi_blkg->iostat_cpu, cpu);
        flags = u64_stats_update_begin_irqsave(&bis->sync);
index 2c49b4151da15d419cc16b4fec553ed6d1939e00..9c8dc70020bc9aef5c21eac14f37c42b817c271a 100644 (file)
@@ -2890,6 +2890,7 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
                struct blk_plug *plug, struct bio **bio, unsigned int nsegs)
 {
        struct request *rq;
+       enum hctx_type type, hctx_type;
 
        if (!plug)
                return NULL;
@@ -2902,7 +2903,10 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
                return NULL;
        }
 
-       if (blk_mq_get_hctx_type((*bio)->bi_opf) != rq->mq_hctx->type)
+       type = blk_mq_get_hctx_type((*bio)->bi_opf);
+       hctx_type = rq->mq_hctx->type;
+       if (type != hctx_type &&
+           !(type == HCTX_TYPE_READ && hctx_type == HCTX_TYPE_DEFAULT))
                return NULL;
        if (op_is_flush(rq->cmd_flags) != op_is_flush((*bio)->bi_opf))
                return NULL;
@@ -4065,8 +4069,9 @@ EXPORT_SYMBOL(blk_mq_init_queue);
  * blk_mq_destroy_queue - shutdown a request queue
  * @q: request queue to shutdown
  *
- * This shuts down a request queue allocated by blk_mq_init_queue() and drops
- * the initial reference.  All future requests will failed with -ENODEV.
+ * This shuts down a request queue allocated by blk_mq_init_queue(). All future
+ * requests will be failed with -ENODEV. The caller is responsible for dropping
+ * the reference from blk_mq_init_queue() by calling blk_put_queue().
  *
  * Context: can sleep
  */
index 9486ed924731b88fbb18fb08aa356bee62435296..799ad7b9e68a0f684794a472c77ffdd706eef292 100644 (file)
@@ -23,8 +23,8 @@ $(obj)/blacklist_hash_list: $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) FORCE
 targets += blacklist_hash_list
 
 quiet_cmd_extract_certs  = CERT    $@
-      cmd_extract_certs  = $(obj)/extract-cert $(extract-cert-in) $@
-extract-cert-in = $(or $(filter-out $(obj)/extract-cert, $(real-prereqs)),"")
+      cmd_extract_certs  = $(obj)/extract-cert "$(extract-cert-in)" $@
+extract-cert-in = $(filter-out $(obj)/extract-cert, $(real-prereqs))
 
 $(obj)/system_certificates.o: $(obj)/x509_certificate_list
 
index 08cf8a17754bb6147e85d5932a063efd446ed29a..07373b3debd1e61efd293d51598545769503f29f 100644 (file)
@@ -354,6 +354,9 @@ void spk_ttyio_release(struct spk_synth *in_synth)
 {
        struct tty_struct *tty = in_synth->dev;
 
+       if (tty == NULL)
+               return;
+
        tty_lock(tty);
 
        if (tty->ops->close)
index 915b26448d2c9114bba6a1155b5e53f78ab89d31..0d392e7b0747bb0899139616fef3b4b319072348 100644 (file)
@@ -23,8 +23,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width);
  *
  * The table is used to implement the Microsoft port access rules that
  * first appeared in Windows XP. Some ports are always illegal, and some
- * ports are only illegal if the BIOS calls _OSI with a win_XP string or
- * later (meaning that the BIOS itelf is post-XP.)
+ * ports are only illegal if the BIOS calls _OSI with nothing newer than
+ * the specific _OSI strings.
  *
  * This provides ACPICA with the desired port protections and
  * Microsoft compatibility.
@@ -145,7 +145,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
 
                        /* Port illegality may depend on the _OSI calls made by the BIOS */
 
-                       if (acpi_gbl_osi_data >= port_info->osi_dependency) {
+                       if (port_info->osi_dependency == ACPI_ALWAYS_ILLEGAL ||
+                           acpi_gbl_osi_data == port_info->osi_dependency) {
                                ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
                                                  "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)\n",
                                                  ACPI_FORMAT_UINT64(address),
index 367fcd201f96e3e2d193b86f4b7e9624dc7dcd83..ec512e06a48edea81ab9c56f2f98a8975a3cbda5 100644 (file)
@@ -181,8 +181,9 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info,
         * Try to fix if there was no return object. Warning if failed to fix.
         */
        if (!return_object) {
-               if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
-                       if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
+               if (expected_btypes) {
+                       if (!(expected_btypes & ACPI_RTYPE_NONE) &&
+                           package_index != ACPI_NOT_PACKAGE_ELEMENT) {
                                ACPI_WARN_PREDEFINED((AE_INFO,
                                                      info->full_pathname,
                                                      ACPI_WARN_ALWAYS,
@@ -196,14 +197,15 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info,
                                if (ACPI_SUCCESS(status)) {
                                        return (AE_OK); /* Repair was successful */
                                }
-                       } else {
+                       }
+
+                       if (expected_btypes != ACPI_RTYPE_NONE) {
                                ACPI_WARN_PREDEFINED((AE_INFO,
                                                      info->full_pathname,
                                                      ACPI_WARN_ALWAYS,
                                                      "Missing expected return value"));
+                               return (AE_AML_NO_RETURN_VALUE);
                        }
-
-                       return (AE_AML_NO_RETURN_VALUE);
                }
        }
 
index b2cfdfef319474842376fe792fc64b352ed960cc..a0592d15dd37c9eee9d115c63a80299bf3d8f479 100644 (file)
@@ -44,7 +44,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
 
 acpi_status
 acpi_get_handle(acpi_handle parent,
-               acpi_string pathname, acpi_handle *ret_handle)
+               const char *pathname, acpi_handle *ret_handle)
 {
        acpi_status status;
        struct acpi_namespace_node *node = NULL;
index 0f17b1c32718edb3d0f8c48597c54bbc6fc5f2f3..1d00a73fb51813b1a408006908beb2df09e71ef8 100644 (file)
@@ -595,6 +595,7 @@ bool __weak cpc_supported_by_cpu(void)
 
 /**
  * pcc_data_alloc() - Allocate the pcc_data memory for pcc subspace
+ * @pcc_ss_id: PCC Subspace index as in the PCC client ACPI package.
  *
  * Check and allocate the cppc_pcc_data memory.
  * In some processor configurations it is possible that same subspace
@@ -1536,6 +1537,7 @@ EXPORT_SYMBOL_GPL(cppc_set_perf);
 
 /**
  * cppc_get_transition_latency - returns frequency transition latency in ns
+ * @cpu_num: CPU number for per_cpu().
  *
  * ACPI CPPC does not explicitly specify how a platform can specify the
  * transition latency for performance change requests. The closest we have
index 998101cf16e4714552d3921681a7fe0c53338926..3d4c4620f9f953096dcf265ccf9c36c8c1cf15da 100644 (file)
@@ -236,6 +236,11 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
        efi_status_t status;
        struct prm_context_buffer context;
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES)) {
+               pr_err_ratelimited("PRM: EFI runtime services no longer available\n");
+               return AE_NO_HANDLER;
+       }
+
        /*
         * The returned acpi_status will always be AE_OK. Error values will be
         * saved in the first byte of the PRM message buffer to be used by ASL.
@@ -325,6 +330,11 @@ void __init init_prmt(void)
 
        pr_info("PRM: found %u modules\n", mc);
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES)) {
+               pr_err("PRM: EFI runtime services unavailable\n");
+               return;
+       }
+
        status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
                                                    ACPI_ADR_SPACE_PLATFORM_RT,
                                                    &acpi_platformrt_space_handler,
index 7bf882fcd64bd0cd3b3e6e73c6841eed21598d09..5a01c2a1567f69f57fcf89586070caf9c0fda3b5 100644 (file)
@@ -147,7 +147,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
 
 static void __lapic_timer_propagate_broadcast(void *arg)
 {
-       struct acpi_processor *pr = (struct acpi_processor *) arg;
+       struct acpi_processor *pr = arg;
 
        if (pr->power.timer_broadcast_on_state < INT_MAX)
                tick_broadcast_enable();
index 970f04a958cd220a2b6a826374ba90fb458aaad0..4265814c74f81aded00495856ae83cc9746b5979 100644 (file)
@@ -53,6 +53,8 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
 {
        acpi_status status = 0;
        unsigned long long ppc = 0;
+       s32 qos_value;
+       int index;
        int ret;
 
        if (!pr)
@@ -72,17 +74,30 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
                }
        }
 
+       index = ppc;
+
+       if (pr->performance_platform_limit == index ||
+           ppc >= pr->performance->state_count)
+               return 0;
+
        pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
-                      (int)ppc, ppc ? "" : "not");
+                index, index ? "is" : "is not");
 
-       pr->performance_platform_limit = (int)ppc;
+       pr->performance_platform_limit = index;
 
-       if (ppc >= pr->performance->state_count ||
-           unlikely(!freq_qos_request_active(&pr->perflib_req)))
+       if (unlikely(!freq_qos_request_active(&pr->perflib_req)))
                return 0;
 
-       ret = freq_qos_update_request(&pr->perflib_req,
-                       pr->performance->states[ppc].core_frequency * 1000);
+       /*
+        * If _PPC returns 0, it means that all of the available states can be
+        * used ("no limit").
+        */
+       if (index == 0)
+               qos_value = FREQ_QOS_MAX_DEFAULT_VALUE;
+       else
+               qos_value = pr->performance->states[index].core_frequency * 1000;
+
+       ret = freq_qos_update_request(&pr->perflib_req, qos_value);
        if (ret < 0) {
                pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n",
                        pr->id, ret);
@@ -166,9 +181,16 @@ void acpi_processor_ppc_init(struct cpufreq_policy *policy)
                if (!pr)
                        continue;
 
+               /*
+                * Reset performance_platform_limit in case there is a stale
+                * value in it, so as to make it match the "no limit" QoS value
+                * below.
+                */
+               pr->performance_platform_limit = 0;
+
                ret = freq_qos_add_request(&policy->constraints,
-                                          &pr->perflib_req,
-                                          FREQ_QOS_MAX, INT_MAX);
+                                          &pr->perflib_req, FREQ_QOS_MAX,
+                                          FREQ_QOS_MAX_DEFAULT_VALUE);
                if (ret < 0)
                        pr_err("Failed to add freq constraint for CPU%d (%d)\n",
                               cpu, ret);
index 0b557c0d405ef1945024374556ddaf7e831ea4a4..4ca667251272210ab1afe05b37f7caa43eec9fbe 100644 (file)
@@ -60,13 +60,17 @@ static struct notifier_block tts_notifier = {
        .priority       = 0,
 };
 
+#ifndef acpi_skip_set_wakeup_address
+#define acpi_skip_set_wakeup_address() false
+#endif
+
 static int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
        unsigned long acpi_wakeup_address;
 
        /* do we have a wakeup address for S2 and S3? */
-       if (acpi_state == ACPI_STATE_S3) {
+       if (acpi_state == ACPI_STATE_S3 && !acpi_skip_set_wakeup_address()) {
                acpi_wakeup_address = acpi_get_wakeup_address();
                if (!acpi_wakeup_address)
                        return -EFAULT;
index 5fbc32b802d018bddbdac05a4013e2302b5be045..7b4680da57d7c866f09aedeeb8b6f33d92e62edd 100644 (file)
@@ -555,7 +555,8 @@ static const char table_sigs[][ACPI_NAMESEG_SIZE] __initconst = {
        ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT,
        ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT,
        ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT,
-       ACPI_SIG_NHLT, ACPI_SIG_AEST, ACPI_SIG_CEDT, ACPI_SIG_AGDI };
+       ACPI_SIG_NHLT, ACPI_SIG_AEST, ACPI_SIG_CEDT, ACPI_SIG_AGDI,
+       ACPI_SIG_NBFT };
 
 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
 
index 8a541efc5675663afe636496a03c8f548b53823a..a8c02608dde4530ff3df98d610aba3a9927f7ecb 100644 (file)
@@ -110,26 +110,6 @@ static bool nvidia_wmi_ec_supported(void)
 }
 #endif
 
-static bool apple_gmux_backlight_present(void)
-{
-       struct acpi_device *adev;
-       struct device *dev;
-
-       adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
-       if (!adev)
-               return false;
-
-       dev = acpi_get_first_physical_node(adev);
-       if (!dev)
-               return false;
-
-       /*
-        * drivers/platform/x86/apple-gmux.c only supports old style
-        * Apple GMUX with an IO-resource.
-        */
-       return pnp_get_resource(to_pnp_dev(dev), IORESOURCE_IO, 0) != NULL;
-}
-
 /* Force to use vendor driver when the ACPI device is known to be
  * buggy */
 static int video_detect_force_vendor(const struct dmi_system_id *d)
@@ -515,6 +495,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
                },
        },
+       {
+        .callback = video_detect_force_native,
+        /* Acer Aspire 4810T */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 4810T"),
+               },
+       },
        {
         .callback = video_detect_force_native,
         /* Acer Aspire 5738z */
@@ -602,6 +590,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
                },
        },
+       {
+        .callback = video_detect_force_native,
+        /* Asus U46E */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "U46E"),
+               },
+       },
        {
         .callback = video_detect_force_native,
         /* Asus UX303UB */
@@ -610,6 +606,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"),
                },
        },
+       {
+        .callback = video_detect_force_native,
+        /* HP EliteBook 8460p */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8460p"),
+               },
+       },
+       {
+        .callback = video_detect_force_native,
+        /* HP Pavilion g6-1d80nr / B4U19UA */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion g6 Notebook PC"),
+               DMI_MATCH(DMI_PRODUCT_SKU, "B4U19UA"),
+               },
+       },
        {
         .callback = video_detect_force_native,
         /* Samsung N150P */
@@ -758,6 +771,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
 {
        static DEFINE_MUTEX(init_mutex);
        static bool nvidia_wmi_ec_present;
+       static bool apple_gmux_present;
        static bool native_available;
        static bool init_done;
        static long video_caps;
@@ -771,6 +785,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
                                    ACPI_UINT32_MAX, find_video, NULL,
                                    &video_caps, NULL);
                nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
+               apple_gmux_present = apple_gmux_detect(NULL, NULL);
                init_done = true;
        }
        if (native)
@@ -792,7 +807,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
        if (nvidia_wmi_ec_present)
                return acpi_backlight_nvidia_wmi_ec;
 
-       if (apple_gmux_backlight_present())
+       if (apple_gmux_present)
                return acpi_backlight_apple_gmux;
 
        /* Use ACPI video if available, except when native should be preferred. */
index 884ae73b11eac13659e4bd2efe6487d52440524b..2ea572628b1c8e8c0c27042f9d780d6af793f29d 100644 (file)
@@ -3109,7 +3109,7 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
         */
        if (spd > 1)
                mask &= (1 << (spd - 1)) - 1;
-       else
+       else if (link->sata_spd)
                return -EINVAL;
 
        /* were we already at the bottom? */
index bbb3e499ff4a5db3f7238959668f8642429b6487..083a95791d3b3ca0444bfa9390a6d66c3117e64a 100644 (file)
@@ -997,26 +997,32 @@ struct fwnode_handle *
 fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
                               struct fwnode_handle *prev)
 {
+       struct fwnode_handle *ep, *port_parent = NULL;
        const struct fwnode_handle *parent;
-       struct fwnode_handle *ep;
 
        /*
         * If this function is in a loop and the previous iteration returned
         * an endpoint from fwnode->secondary, then we need to use the secondary
         * as parent rather than @fwnode.
         */
-       if (prev)
-               parent = fwnode_graph_get_port_parent(prev);
-       else
+       if (prev) {
+               port_parent = fwnode_graph_get_port_parent(prev);
+               parent = port_parent;
+       } else {
                parent = fwnode;
+       }
        if (IS_ERR_OR_NULL(parent))
                return NULL;
 
        ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
        if (ep)
-               return ep;
+               goto out_put_port_parent;
+
+       ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
 
-       return fwnode_graph_get_next_endpoint(parent->secondary, NULL);
+out_put_port_parent:
+       fwnode_handle_put(port_parent);
+       return ep;
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
 
index 4d1976ca507271487235107b17a74226af6164b8..929410d0dd6fe2a726eff7094b7b63ff5cbd516c 100644 (file)
@@ -145,7 +145,7 @@ static int __init test_async_probe_init(void)
        calltime = ktime_get();
        for_each_online_cpu(cpu) {
                nid = cpu_to_node(cpu);
-               pdev = &sync_dev[sync_id];
+               pdev = &async_dev[async_id];
 
                *pdev = test_platform_device_register_node("test_async_driver",
                                                           async_id,
index 4cea3b08087ed027cf523e808a4593595edb77a2..2f1a92509271c406f59fd2bb4325737574285be6 100644 (file)
@@ -2400,6 +2400,8 @@ static void pkt_submit_bio(struct bio *bio)
        struct bio *split;
 
        bio = bio_split_to_limits(bio);
+       if (!bio)
+               return;
 
        pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
                (unsigned long long)bio->bi_iter.bi_sector,
index 78334da74d8bf90dcfd1f51d5ccd26f71a289a0c..5eb8c7855970d1ab277798056b0fb3db2ba151be 100644 (file)
@@ -1440,7 +1440,7 @@ 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),
+       ret = ida_alloc_max(&index_ida, (1 << (MINORBITS - RNBD_PART_BITS)) - 1,
                            GFP_KERNEL);
        if (ret < 0) {
                pr_err("Failed to initialize device '%s' from session %s, allocating idr failed, err: %d\n",
index 17b677b5d3b221fac658268958730dbc71dade52..6368b56eacf11a6ac67a089c14b1435ad830b39d 100644 (file)
@@ -137,7 +137,7 @@ struct ublk_device {
 
        char    *__queues;
 
-       unsigned short  queue_size;
+       unsigned int    queue_size;
        struct ublksrv_ctrl_dev_info    dev_info;
 
        struct blk_mq_tag_set   tag_set;
@@ -2092,13 +2092,12 @@ static void __exit ublk_exit(void)
        struct ublk_device *ub;
        int id;
 
-       class_destroy(ublk_chr_class);
-
-       misc_deregister(&ublk_misc);
-
        idr_for_each_entry(&ublk_index_idr, ub, id)
                ublk_remove(ub);
 
+       class_destroy(ublk_chr_class);
+       misc_deregister(&ublk_misc);
+
        idr_destroy(&ublk_index_idr);
        unregister_chrdev_region(ublk_chr_devt, UBLK_MINORS);
 }
index 6eddc23e49d9a7dc30eb24d6614e0402baa6bd91..bbe9cf1cae27f6088cea5cdd5cd71983fdded295 100644 (file)
@@ -2164,10 +2164,17 @@ static void qca_serdev_shutdown(struct device *dev)
        int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
        struct serdev_device *serdev = to_serdev_device(dev);
        struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
+       struct hci_uart *hu = &qcadev->serdev_hu;
+       struct hci_dev *hdev = hu->hdev;
+       struct qca_data *qca = hu->priv;
        const u8 ibs_wake_cmd[] = { 0xFD };
        const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 };
 
        if (qcadev->btsoc_type == QCA_QCA6390) {
+               if (test_bit(QCA_BT_OFF, &qca->flags) ||
+                   !test_bit(HCI_RUNNING, &hdev->flags))
+                       return;
+
                serdev_device_write_flush(serdev);
                ret = serdev_device_write_buf(serdev, ibs_wake_cmd,
                                              sizeof(ibs_wake_cmd));
index 3aa91aed3bf733a4876e5d36c8badf13150a771b..226e87b85116ea700efa5db36d89567cf89a97d0 100644 (file)
@@ -857,7 +857,13 @@ static int __init sunxi_rsb_init(void)
                return ret;
        }
 
-       return platform_driver_register(&sunxi_rsb_driver);
+       ret = platform_driver_register(&sunxi_rsb_driver);
+       if (ret) {
+               bus_unregister(&sunxi_rsb_bus);
+               return ret;
+       }
+
+       return 0;
 }
 module_init(sunxi_rsb_init);
 
index fcfc2e299110eddbb009969af8829bb859a49690..27f3890f471df7a78e7b8e27d0755a295ab8caad 100644 (file)
@@ -58,7 +58,7 @@
 #define PCI1760_CMD_CLR_IMB2           0x00    /* Clears IMB2 */
 #define PCI1760_CMD_SET_DO             0x01    /* Set output state */
 #define PCI1760_CMD_GET_DO             0x02    /* Read output status */
-#define PCI1760_CMD_GET_STATUS         0x03    /* Read current status */
+#define PCI1760_CMD_GET_STATUS         0x07    /* Read current status */
 #define PCI1760_CMD_GET_FW_VER         0x0e    /* Read firmware version */
 #define PCI1760_CMD_GET_HW_VER         0x0f    /* Read hardware version */
 #define PCI1760_CMD_SET_PWM_HI(x)      (0x10 + (x) * 2) /* Set "hi" period */
index fd73d6d2b808482a08ee83da2039897ee12e71e0..cb4beec27555a0bdef8f1ddd49e9361ab8a79295 100644 (file)
@@ -452,20 +452,6 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
                         (u32) cpu->acpi_perf_data.states[i].control);
        }
 
-       /*
-        * The _PSS table doesn't contain whole turbo frequency range.
-        * This just contains +1 MHZ above the max non turbo frequency,
-        * with control value corresponding to max turbo ratio. But
-        * when cpufreq set policy is called, it will call with this
-        * max frequency, which will cause a reduced performance as
-        * this driver uses real max turbo frequency as the max
-        * frequency. So correct this frequency in _PSS table to
-        * correct max turbo frequency based on the turbo state.
-        * Also need to convert to MHz as _PSS freq is in MHz.
-        */
-       if (!global.turbo_disabled)
-               cpu->acpi_perf_data.states[0].core_frequency =
-                                       policy->cpuinfo.max_freq / 1000;
        cpu->valid_pss_table = true;
        pr_debug("_PPC limits will be enforced\n");
 
index ad0849af42d790a528f9c4b2dec4b91c97e400ed..13cde44c608602268780f2e0af5763a4bc62a682 100644 (file)
@@ -736,4 +736,3 @@ module_exit(cxl_acpi_exit);
 MODULE_LICENSE("GPL v2");
 MODULE_IMPORT_NS(CXL);
 MODULE_IMPORT_NS(ACPI);
-MODULE_SOFTDEP("pre: cxl_pmem");
index f3d2169b673118acb729b010809a110929ee4888..c2e4b10937884a7ec3cc1266f395ce2dedcbe209 100644 (file)
@@ -227,34 +227,16 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_nvdimm_bridge *cxl_nvb,
        return cxl_nvd;
 }
 
-static void cxl_nvd_unregister(void *_cxl_nvd)
+static void cxlmd_release_nvdimm(void *_cxlmd)
 {
-       struct cxl_nvdimm *cxl_nvd = _cxl_nvd;
-       struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
+       struct cxl_memdev *cxlmd = _cxlmd;
+       struct cxl_nvdimm *cxl_nvd = cxlmd->cxl_nvd;
        struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
 
-       /*
-        * Either the bridge is in ->remove() context under the device_lock(),
-        * or cxlmd_release_nvdimm() is cancelling the bridge's release action
-        * for @cxl_nvd and doing it itself (while manually holding the bridge
-        * lock).
-        */
-       device_lock_assert(&cxl_nvb->dev);
        cxl_nvd->cxlmd = NULL;
        cxlmd->cxl_nvd = NULL;
+       cxlmd->cxl_nvb = NULL;
        device_unregister(&cxl_nvd->dev);
-}
-
-static void cxlmd_release_nvdimm(void *_cxlmd)
-{
-       struct cxl_memdev *cxlmd = _cxlmd;
-       struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
-
-       device_lock(&cxl_nvb->dev);
-       if (cxlmd->cxl_nvd)
-               devm_release_action(&cxl_nvb->dev, cxl_nvd_unregister,
-                                   cxlmd->cxl_nvd);
-       device_unlock(&cxl_nvb->dev);
        put_device(&cxl_nvb->dev);
 }
 
@@ -293,22 +275,6 @@ int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd)
 
        dev_dbg(&cxlmd->dev, "register %s\n", dev_name(dev));
 
-       /*
-        * The two actions below arrange for @cxl_nvd to be deleted when either
-        * the top-level PMEM bridge goes down, or the endpoint device goes
-        * through ->remove().
-        */
-       device_lock(&cxl_nvb->dev);
-       if (cxl_nvb->dev.driver)
-               rc = devm_add_action_or_reset(&cxl_nvb->dev, cxl_nvd_unregister,
-                                             cxl_nvd);
-       else
-               rc = -ENXIO;
-       device_unlock(&cxl_nvb->dev);
-
-       if (rc)
-               goto err_alloc;
-
        /* @cxlmd carries a reference on @cxl_nvb until cxlmd_release_nvdimm */
        return devm_add_action_or_reset(&cxlmd->dev, cxlmd_release_nvdimm, cxlmd);
 
index 33083a522fd1cc121b7b1a117364e19c88c04f53..258004f34281aea2384f712f7e9ee4f7313f1559 100644 (file)
@@ -554,8 +554,11 @@ static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
 
        /* If multiple errors, log header points to first error from ctrl reg */
        if (hweight32(status) > 1) {
-               addr = cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
-               fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, readl(addr)));
+               void __iomem *rcc_addr =
+                       cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
+
+               fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK,
+                                  readl(rcc_addr)));
        } else {
                fe = status;
        }
index eedefebc42839115869038ad64d31fc26e9abdec..08bbbac9a6d08a4388121e543b7e4e252cf458a9 100644 (file)
@@ -225,11 +225,35 @@ static int cxl_pmem_ctl(struct nvdimm_bus_descriptor *nd_desc,
        return cxl_pmem_nvdimm_ctl(nvdimm, cmd, buf, buf_len);
 }
 
+static int detach_nvdimm(struct device *dev, void *data)
+{
+       struct cxl_nvdimm *cxl_nvd;
+       bool release = false;
+
+       if (!is_cxl_nvdimm(dev))
+               return 0;
+
+       device_lock(dev);
+       if (!dev->driver)
+               goto out;
+
+       cxl_nvd = to_cxl_nvdimm(dev);
+       if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data)
+               release = true;
+out:
+       device_unlock(dev);
+       if (release)
+               device_release_driver(dev);
+       return 0;
+}
+
 static void unregister_nvdimm_bus(void *_cxl_nvb)
 {
        struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb;
        struct nvdimm_bus *nvdimm_bus = cxl_nvb->nvdimm_bus;
 
+       bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb, detach_nvdimm);
+
        cxl_nvb->nvdimm_bus = NULL;
        nvdimm_bus_unregister(nvdimm_bus);
 }
index 406b4e26f538fdbcb72bdcdd674ba6c77bf3106d..0de0482cd36e2355202bb322ce58b6d385a550fb 100644 (file)
@@ -167,7 +167,7 @@ struct dma_fence *dma_fence_allocate_private_stub(void)
                       0, 0);
 
        set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
-               &dma_fence_stub.flags);
+               &fence->flags);
 
        dma_fence_signal(fence);
 
index c741b6431958c20c5d46eb118fdbd46a42672e7a..8a6e6b60d66f377de23f570288c417f17f19aad2 100644 (file)
@@ -451,7 +451,8 @@ static int dma_chan_get(struct dma_chan *chan)
        /* The channel is already in use, update client count */
        if (chan->client_count) {
                __module_get(owner);
-               goto out;
+               chan->client_count++;
+               return 0;
        }
 
        if (!try_module_get(owner))
@@ -470,11 +471,11 @@ static int dma_chan_get(struct dma_chan *chan)
                        goto err_out;
        }
 
+       chan->client_count++;
+
        if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
                balance_ref_count(chan);
 
-out:
-       chan->client_count++;
        return 0;
 
 err_out:
index a183d93bd7e2986e6a4f385d62395cde2a5af834..bf85aa0979ecb8ecf62b83291c5bdbb19b24c2d7 100644 (file)
@@ -1018,6 +1018,11 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
 
        /* The bad descriptor currently is in the head of vc list */
        vd = vchan_next_desc(&chan->vc);
+       if (!vd) {
+               dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n",
+                       axi_chan_name(chan));
+               goto out;
+       }
        /* Remove the completed descriptor from issued list */
        list_del(&vd->node);
 
@@ -1032,6 +1037,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
        /* Try to restart the controller */
        axi_chan_start_first_queued(chan);
 
+out:
        spin_unlock_irqrestore(&chan->vc.lock, flags);
 }
 
index 06f5d3783d7719e01ad896818f5fa48a75cf945e..29dbb0f52e186c4ff5cb9948c3cfb0224b47d486 100644 (file)
@@ -1172,8 +1172,19 @@ static void idxd_flush_pending_descs(struct idxd_irq_entry *ie)
        spin_unlock(&ie->list_lock);
 
        list_for_each_entry_safe(desc, itr, &flist, list) {
+               struct dma_async_tx_descriptor *tx;
+
                list_del(&desc->list);
                ctype = desc->completion->status ? IDXD_COMPLETE_NORMAL : IDXD_COMPLETE_ABORT;
+               /*
+                * wq is being disabled. Any remaining descriptors are
+                * likely to be stuck and can be dropped. callback could
+                * point to code that is no longer accessible, for example
+                * if dmatest module has been unloaded.
+                */
+               tx = &desc->txd;
+               tx->callback = NULL;
+               tx->callback_result = NULL;
                idxd_dma_complete_txd(desc, ctype, true);
        }
 }
@@ -1390,8 +1401,7 @@ err_res_alloc:
 err_irq:
        idxd_wq_unmap_portal(wq);
 err_map_portal:
-       rc = idxd_wq_disable(wq, false);
-       if (rc < 0)
+       if (idxd_wq_disable(wq, false))
                dev_dbg(dev, "wq %s disable failed\n", dev_name(wq_confdev(wq)));
 err:
        return rc;
@@ -1408,11 +1418,11 @@ void drv_disable_wq(struct idxd_wq *wq)
                dev_warn(dev, "Clients has claim on wq %d: %d\n",
                         wq->id, idxd_wq_refcount(wq));
 
-       idxd_wq_free_resources(wq);
        idxd_wq_unmap_portal(wq);
        idxd_wq_drain(wq);
        idxd_wq_free_irq(wq);
        idxd_wq_reset(wq);
+       idxd_wq_free_resources(wq);
        percpu_ref_exit(&wq->wq_active);
        wq->type = IDXD_WQT_NONE;
        wq->client_count = 0;
index fbea5f62dd98b82f09be1c2a23fc36b54fc99db9..b926abe4fa43aca6ef00f6c1ec3405be824e6edb 100644 (file)
@@ -1521,10 +1521,12 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
                sdma_config_ownership(sdmac, false, true, false);
 
        if (sdma_load_context(sdmac))
-               goto err_desc_out;
+               goto err_bd_out;
 
        return desc;
 
+err_bd_out:
+       sdma_free_bd(desc);
 err_desc_out:
        kfree(desc);
 err_out:
index 9b9184f964be397a4f5f5b8a7a1c2410032d6456..1709d159af7e019e04fe015fa38690c55ef71fe4 100644 (file)
@@ -914,7 +914,7 @@ static void ldma_dev_init(struct ldma_dev *d)
        }
 }
 
-static int ldma_cfg_init(struct ldma_dev *d)
+static int ldma_parse_dt(struct ldma_dev *d)
 {
        struct fwnode_handle *fwnode = dev_fwnode(d->dev);
        struct ldma_port *p;
@@ -1661,10 +1661,6 @@ static int intel_ldma_probe(struct platform_device *pdev)
                p->ldev = d;
        }
 
-       ret = ldma_cfg_init(d);
-       if (ret)
-               return ret;
-
        dma_dev->dev = &pdev->dev;
 
        ch_mask = (unsigned long)d->channels_mask;
@@ -1675,6 +1671,10 @@ static int intel_ldma_probe(struct platform_device *pdev)
                        ldma_dma_init_v3X(j, d);
        }
 
+       ret = ldma_parse_dt(d);
+       if (ret)
+               return ret;
+
        dma_dev->device_alloc_chan_resources = ldma_alloc_chan_resources;
        dma_dev->device_free_chan_resources = ldma_free_chan_resources;
        dma_dev->device_terminate_all = ldma_terminate_all;
index 377da23012ac23e826234673c1095f8dc70aefa3..a2bf13ff18b6d2904b489f880c54563c8e12410d 100644 (file)
@@ -71,12 +71,13 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd
        bool soc = FIELD_GET(DWORD0_SOC, desc->dw0);
        u8 *q_desc = (u8 *)&cmd_q->qbase[cmd_q->qidx];
        u32 tail;
+       unsigned long flags;
 
        if (soc) {
                desc->dw0 |= FIELD_PREP(DWORD0_IOC, desc->dw0);
                desc->dw0 &= ~DWORD0_SOC;
        }
-       mutex_lock(&cmd_q->q_mutex);
+       spin_lock_irqsave(&cmd_q->q_lock, flags);
 
        /* Copy 32-byte command descriptor to hw queue. */
        memcpy(q_desc, desc, 32);
@@ -91,7 +92,7 @@ static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd
 
        /* Turn the queue back on using our cached control register */
        pt_start_queue(cmd_q);
-       mutex_unlock(&cmd_q->q_mutex);
+       spin_unlock_irqrestore(&cmd_q->q_lock, flags);
 
        return 0;
 }
@@ -199,7 +200,7 @@ int pt_core_init(struct pt_device *pt)
 
        cmd_q->pt = pt;
        cmd_q->dma_pool = dma_pool;
-       mutex_init(&cmd_q->q_mutex);
+       spin_lock_init(&cmd_q->q_lock);
 
        /* Page alignment satisfies our needs for N <= 128 */
        cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
index d093c43b7d1343b11227e14b815149085a32696f..21b4bf895200b5512ca91a54a19e2ce93623d46e 100644 (file)
@@ -196,7 +196,7 @@ struct pt_cmd_queue {
        struct ptdma_desc *qbase;
 
        /* Aligned queue start address (per requirement) */
-       struct mutex q_mutex ____cacheline_aligned;
+       spinlock_t q_lock ____cacheline_aligned;
        unsigned int qidx;
 
        unsigned int qsize;
index 061add83229512e07f6ed90701789e395f02522d..59a36cbf9b5f7f146d3d98b1d0f0eb127eede8e3 100644 (file)
@@ -1756,6 +1756,7 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc,
                tre->dword[3] = u32_encode_bits(TRE_TYPE_GO, TRE_FLAGS_TYPE);
                if (spi->cmd == SPI_RX) {
                        tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
+                       tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_LINK);
                } else if (spi->cmd == SPI_TX) {
                        tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN);
                } else { /* SPI_DUPLEX */
index 1d1180db6d4ecdca4e540da718fcf733aa42438f..8f67f453a4922c2434cbfc84d378f84db7d45557 100644 (file)
@@ -711,6 +711,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
                        return err;
                }
 
+               vchan_terminate_vdesc(&tdc->dma_desc->vd);
                tegra_dma_disable(tdc);
                tdc->dma_desc = NULL;
        }
index ae39b52012b2fb74e723637652b2e07ea718defe..79da93cc77b64b0f0893332f92448a53950db0f1 100644 (file)
@@ -221,7 +221,7 @@ static int tegra_adma_init(struct tegra_adma *tdma)
        int ret;
 
        /* Clear any interrupts */
-       tdma_write(tdma, tdma->cdata->global_int_clear, 0x1);
+       tdma_write(tdma, tdma->cdata->ch_base_offset + tdma->cdata->global_int_clear, 0x1);
 
        /* Assert soft reset */
        tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1);
index ce8b80bb34d7d1f2f0d1c537d776cda691590193..4c62274e0b33264e7246cff5468eadcc4f948692 100644 (file)
@@ -762,11 +762,12 @@ static void udma_decrement_byte_counters(struct udma_chan *uc, u32 val)
        if (uc->desc->dir == DMA_DEV_TO_MEM) {
                udma_rchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val);
                udma_rchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val);
-               udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val);
+               if (uc->config.ep_type != PSIL_EP_NATIVE)
+                       udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val);
        } else {
                udma_tchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val);
                udma_tchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val);
-               if (!uc->bchan)
+               if (!uc->bchan && uc->config.ep_type != PSIL_EP_NATIVE)
                        udma_tchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val);
        }
 }
index a8d23cdf883e5b825a3a66576903b1043280deae..ac09f0e5f58d88929a7dd9452b9044ce82e083d3 100644 (file)
@@ -3143,8 +3143,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
        /* Initialize the channels */
        for_each_child_of_node(node, child) {
                err = xilinx_dma_child_probe(xdev, child);
-               if (err < 0)
+               if (err < 0) {
+                       of_node_put(child);
                        goto error;
+               }
        }
 
        if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
index 878deb4880cdb4c3998f930cc69ffdffe9035b6d..0689e15107213c6a11b70b3460a78db17c3663b1 100644 (file)
@@ -34,6 +34,9 @@
 static DEFINE_MUTEX(device_ctls_mutex);
 static LIST_HEAD(edac_device_list);
 
+/* Default workqueue processing interval on this instance, in msecs */
+#define DEFAULT_POLL_INTERVAL 1000
+
 #ifdef CONFIG_EDAC_DEBUG
 static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
 {
@@ -336,7 +339,7 @@ static void edac_device_workq_function(struct work_struct *work_req)
         * whole one second to save timers firing all over the period
         * between integral seconds
         */
-       if (edac_dev->poll_msec == 1000)
+       if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
                edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
        else
                edac_queue_work(&edac_dev->work, edac_dev->delay);
@@ -366,7 +369,7 @@ static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
         * timers firing on sub-second basis, while they are happy
         * to fire together on the 1 second exactly
         */
-       if (edac_dev->poll_msec == 1000)
+       if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
                edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
        else
                edac_queue_work(&edac_dev->work, edac_dev->delay);
@@ -400,7 +403,7 @@ void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
        edac_dev->delay     = msecs_to_jiffies(msec);
 
        /* See comment in edac_device_workq_setup() above */
-       if (edac_dev->poll_msec == 1000)
+       if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
                edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
        else
                edac_mod_work(&edac_dev->work, edac_dev->delay);
@@ -442,11 +445,7 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
                /* This instance is NOW RUNNING */
                edac_dev->op_state = OP_RUNNING_POLL;
 
-               /*
-                * enable workq processing on this instance,
-                * default = 1000 msec
-                */
-               edac_device_workq_setup(edac_dev, 1000);
+               edac_device_workq_setup(edac_dev, edac_dev->poll_msec ?: DEFAULT_POLL_INTERVAL);
        } else {
                edac_dev->op_state = OP_RUNNING_INTERRUPT;
        }
index 97a27e42dd610db0d3cf656357bf7421e57b56ff..c45519f59dc11b5d4954a04390c321d28b57d114 100644 (file)
@@ -252,7 +252,7 @@ clear:
 static int
 dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
 {
-       struct llcc_drv_data *drv = edev_ctl->pvt_info;
+       struct llcc_drv_data *drv = edev_ctl->dev->platform_data;
        int ret;
 
        ret = dump_syn_reg_values(drv, bank, err_type);
@@ -289,7 +289,7 @@ static irqreturn_t
 llcc_ecc_irq_handler(int irq, void *edev_ctl)
 {
        struct edac_device_ctl_info *edac_dev_ctl = edev_ctl;
-       struct llcc_drv_data *drv = edac_dev_ctl->pvt_info;
+       struct llcc_drv_data *drv = edac_dev_ctl->dev->platform_data;
        irqreturn_t irq_rc = IRQ_NONE;
        u32 drp_error, trp_error, i;
        int ret;
@@ -358,7 +358,6 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev)
        edev_ctl->dev_name = dev_name(dev);
        edev_ctl->ctl_name = "llcc";
        edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
-       edev_ctl->pvt_info = llcc_driv_data;
 
        rc = edac_device_add_device(edev_ctl);
        if (rc)
index 9c89f7d53e99db123b4f553e49ab35aa3bfa18fe..958aa4662ccb0cc389097ddafc2ce28d7a056882 100644 (file)
@@ -819,8 +819,10 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
 
        r = container_of(resource, struct inbound_transaction_resource,
                         resource);
-       if (is_fcp_request(r->request))
+       if (is_fcp_request(r->request)) {
+               kfree(r->data);
                goto out;
+       }
 
        if (a->length != fw_get_response_length(r->request)) {
                ret = -EINVAL;
index f818d00bb2c69e700dc0ce5e70f1cf84df55953e..ffdad59ec81fcb5e438061aba98accede1cf7d5a 100644 (file)
@@ -910,6 +910,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
                              xfer->hdr.protocol_id, xfer->hdr.seq,
                              xfer->hdr.poll_completion);
 
+       /* Clear any stale status */
+       xfer->hdr.status = SCMI_SUCCESS;
        xfer->state = SCMI_XFER_SENT_OK;
        /*
         * Even though spinlocking is not needed here since no race is possible
index 1dfe534b85184528c31e849668bd38edd1bf4154..87b4f4d35f06230bc161fc4205c7b199e03c0015 100644 (file)
@@ -81,10 +81,11 @@ u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
 void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
                          struct scmi_xfer *xfer)
 {
+       size_t len = ioread32(&shmem->length);
+
        xfer->hdr.status = ioread32(shmem->msg_payload);
        /* Skip the length of header and status in shmem area i.e 8 bytes */
-       xfer->rx.len = min_t(size_t, xfer->rx.len,
-                            ioread32(&shmem->length) - 8);
+       xfer->rx.len = min_t(size_t, xfer->rx.len, len > 8 ? len - 8 : 0);
 
        /* Take a copy to the rx buffer.. */
        memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
@@ -93,8 +94,10 @@ void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
 void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem,
                              size_t max_len, struct scmi_xfer *xfer)
 {
+       size_t len = ioread32(&shmem->length);
+
        /* Skip only the length of header in shmem area i.e 4 bytes */
-       xfer->rx.len = min_t(size_t, max_len, ioread32(&shmem->length) - 4);
+       xfer->rx.len = min_t(size_t, max_len, len > 4 ? len - 4 : 0);
 
        /* Take a copy to the rx buffer.. */
        memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len);
index 33c9b81a55cd11926dad6426cd2e748052150f40..1db975c08896983f994be90fea6a361cc3099389 100644 (file)
@@ -160,7 +160,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
        }
 
        vioch->shutdown_done = &vioch_shutdown_done;
-       virtio_break_device(vioch->vqueue->vdev);
        if (!vioch->is_rx && vioch->deferred_tx_wq)
                /* Cannot be kicked anymore after this...*/
                vioch->deferred_tx_wq = NULL;
@@ -482,6 +481,12 @@ static int virtio_chan_free(int id, void *p, void *data)
        struct scmi_chan_info *cinfo = p;
        struct scmi_vio_channel *vioch = cinfo->transport_info;
 
+       /*
+        * Break device to inhibit further traffic flowing while shutting down
+        * the channels: doing it later holding vioch->lock creates unsafe
+        * locking dependency chains as reported by LOCKDEP.
+        */
+       virtio_break_device(vioch->vqueue->vdev);
        scmi_vio_channel_cleanup_sync(vioch);
 
        scmi_free_channel(cinfo, data, id);
index a2b0cbc8741c2ff1cf175c4d70a7eba6b7d37050..1e0b016fdc2b121722aab37f11a8d4da7c0a146d 100644 (file)
@@ -1007,6 +1007,8 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
        /* first try to find a slot in an existing linked list entry */
        for (prsv = efi_memreserve_root->next; prsv; ) {
                rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB);
+               if (!rsv)
+                       return -ENOMEM;
                index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
                if (index < rsv->size) {
                        rsv->entry[index].base = addr;
index 0a9aba5f9ceff0bff6c4507382afe487378afcd1..f178b2984dfb2a1c7d8bf4d4e68299b1de8f4ae7 100644 (file)
@@ -33,7 +33,7 @@ int __init efi_memattr_init(void)
                return -ENOMEM;
        }
 
-       if (tbl->version > 1) {
+       if (tbl->version > 2) {
                pr_warn("Unexpected EFI Memory Attributes table version %d\n",
                        tbl->version);
                goto unmap;
index 4e2575dfeb908ff50d37a1c6a5d7be4f6313ba5b..871bedf533a805f65975e1b94ae125d65f431a09 100644 (file)
@@ -361,9 +361,10 @@ static efi_status_t gsmi_get_variable(efi_char16_t *name,
                memcpy(data, gsmi_dev.data_buf->start, *data_size);
 
                /* All variables are have the following attributes */
-               *attr = EFI_VARIABLE_NON_VOLATILE |
-                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
-                       EFI_VARIABLE_RUNTIME_ACCESS;
+               if (attr)
+                       *attr = EFI_VARIABLE_NON_VOLATILE |
+                               EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                               EFI_VARIABLE_RUNTIME_ACCESS;
        }
 
        spin_unlock_irqrestore(&gsmi_dev.lock, flags);
index 79d48852825ef47b35d2400cd1b91c874f6a5677..03f1bd81c434d634d0418e34f136152c910f3ed4 100644 (file)
@@ -574,20 +574,27 @@ static int m10bmc_sec_probe(struct platform_device *pdev)
        len = scnprintf(buf, SEC_UPDATE_LEN_MAX, "secure-update%d",
                        sec->fw_name_id);
        sec->fw_name = kmemdup_nul(buf, len, GFP_KERNEL);
-       if (!sec->fw_name)
-               return -ENOMEM;
+       if (!sec->fw_name) {
+               ret = -ENOMEM;
+               goto fw_name_fail;
+       }
 
        fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name,
                                       &m10bmc_ops, sec);
        if (IS_ERR(fwl)) {
                dev_err(sec->dev, "Firmware Upload driver failed to start\n");
-               kfree(sec->fw_name);
-               xa_erase(&fw_upload_xa, sec->fw_name_id);
-               return PTR_ERR(fwl);
+               ret = PTR_ERR(fwl);
+               goto fw_uploader_fail;
        }
 
        sec->fwl = fwl;
        return 0;
+
+fw_uploader_fail:
+       kfree(sec->fw_name);
+fw_name_fail:
+       xa_erase(&fw_upload_xa, sec->fw_name_id);
+       return ret;
 }
 
 static int m10bmc_sec_remove(struct platform_device *pdev)
index 357cea58ec98ef4d5dc428379675ff69d80b88bb..f7f01982a512662007c805153988417dcdb7fdd1 100644 (file)
@@ -213,9 +213,9 @@ static int s10_ops_write_init(struct fpga_manager *mgr,
        /* Allocate buffers from the service layer's pool. */
        for (i = 0; i < NUM_SVC_BUFS; i++) {
                kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE);
-               if (!kbuf) {
+               if (IS_ERR(kbuf)) {
                        s10_free_buffers(mgr);
-                       ret = -ENOMEM;
+                       ret = PTR_ERR(kbuf);
                        goto init_done;
                }
 
index 2e17797091133119d093d590fbfe8e5e323e1a51..6cedf46efec6cbc2c1c737381d83ce22fae18007 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/gpio/driver.h>
 #include <linux/bitops.h>
+#include <linux/seq_file.h>
 
 #define EP93XX_GPIO_F_INT_STATUS 0x5c
 #define EP93XX_GPIO_A_INT_STATUS 0xa0
@@ -40,7 +41,6 @@
 #define EP93XX_GPIO_F_IRQ_BASE 80
 
 struct ep93xx_gpio_irq_chip {
-       struct irq_chip ic;
        u8 irq_offset;
        u8 int_unmasked;
        u8 int_enabled;
@@ -148,7 +148,7 @@ static void ep93xx_gpio_f_irq_handler(struct irq_desc *desc)
         */
        struct irq_chip *irqchip = irq_desc_get_chip(desc);
        unsigned int irq = irq_desc_get_irq(desc);
-       int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
+       int port_f_idx = (irq & 7) ^ 4; /* {20..23,48..51} -> {0..7} */
        int gpio_irq = EP93XX_GPIO_F_IRQ_BASE + port_f_idx;
 
        chained_irq_enter(irqchip, desc);
@@ -185,6 +185,7 @@ static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
        ep93xx_gpio_update_int_params(epg, eic);
 
        writeb(port_mask, epg->base + eic->irq_offset + EP93XX_INT_EOI_OFFSET);
+       gpiochip_disable_irq(gc, irqd_to_hwirq(d));
 }
 
 static void ep93xx_gpio_irq_mask(struct irq_data *d)
@@ -195,6 +196,7 @@ static void ep93xx_gpio_irq_mask(struct irq_data *d)
 
        eic->int_unmasked &= ~BIT(d->irq & 7);
        ep93xx_gpio_update_int_params(epg, eic);
+       gpiochip_disable_irq(gc, irqd_to_hwirq(d));
 }
 
 static void ep93xx_gpio_irq_unmask(struct irq_data *d)
@@ -203,6 +205,7 @@ static void ep93xx_gpio_irq_unmask(struct irq_data *d)
        struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
        struct ep93xx_gpio *epg = gpiochip_get_data(gc);
 
+       gpiochip_enable_irq(gc, irqd_to_hwirq(d));
        eic->int_unmasked |= BIT(d->irq & 7);
        ep93xx_gpio_update_int_params(epg, eic);
 }
@@ -320,15 +323,25 @@ static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset,
        return 0;
 }
 
-static void ep93xx_init_irq_chip(struct device *dev, struct irq_chip *ic)
+static void ep93xx_irq_print_chip(struct irq_data *data, struct seq_file *p)
 {
-       ic->irq_ack = ep93xx_gpio_irq_ack;
-       ic->irq_mask_ack = ep93xx_gpio_irq_mask_ack;
-       ic->irq_mask = ep93xx_gpio_irq_mask;
-       ic->irq_unmask = ep93xx_gpio_irq_unmask;
-       ic->irq_set_type = ep93xx_gpio_irq_type;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+
+       seq_printf(p, dev_name(gc->parent));
 }
 
+static const struct irq_chip gpio_eic_irq_chip = {
+       .name                   = "ep93xx-gpio-eic",
+       .irq_ack                = ep93xx_gpio_irq_ack,
+       .irq_mask               = ep93xx_gpio_irq_mask,
+       .irq_unmask             = ep93xx_gpio_irq_unmask,
+       .irq_mask_ack   = ep93xx_gpio_irq_mask_ack,
+       .irq_set_type   = ep93xx_gpio_irq_type,
+       .irq_print_chip = ep93xx_irq_print_chip,
+       .flags                  = IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
 static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc,
                                struct platform_device *pdev,
                                struct ep93xx_gpio *epg,
@@ -350,8 +363,6 @@ static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc,
 
        girq = &gc->irq;
        if (bank->has_irq || bank->has_hierarchical_irq) {
-               struct irq_chip *ic;
-
                gc->set_config = ep93xx_gpio_set_config;
                egc->eic = devm_kcalloc(dev, 1,
                                        sizeof(*egc->eic),
@@ -359,12 +370,7 @@ static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc,
                if (!egc->eic)
                        return -ENOMEM;
                egc->eic->irq_offset = bank->irq;
-               ic = &egc->eic->ic;
-               ic->name = devm_kasprintf(dev, GFP_KERNEL, "gpio-irq-%s", bank->label);
-               if (!ic->name)
-                       return -ENOMEM;
-               ep93xx_init_irq_chip(dev, ic);
-               girq->chip = ic;
+               gpio_irq_chip_set_chip(girq, &gpio_eic_irq_chip);
        }
 
        if (bank->has_irq) {
index d5626c572d24ecc095eace76ce733b703cddf2b9..9d0cec4b82a334676e0a9d7818f51394838168c7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
 #include <linux/gpio/driver.h>
 #include <linux/of.h>
@@ -159,6 +160,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mxc_gpio_port *port = gc->private;
+       unsigned long flags;
        u32 bit, val;
        u32 gpio_idx = d->hwirq;
        int edge;
@@ -197,6 +199,8 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                return -EINVAL;
        }
 
+       raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags);
+
        if (GPIO_EDGE_SEL >= 0) {
                val = readl(port->base + GPIO_EDGE_SEL);
                if (edge == GPIO_INT_BOTH_EDGES)
@@ -217,15 +221,20 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
        writel(1 << gpio_idx, port->base + GPIO_ISR);
        port->pad_type[gpio_idx] = type;
 
-       return 0;
+       raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
+
+       return port->gc.direction_input(&port->gc, gpio_idx);
 }
 
 static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
 {
        void __iomem *reg = port->base;
+       unsigned long flags;
        u32 bit, val;
        int edge;
 
+       raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags);
+
        reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
        bit = gpio & 0xf;
        val = readl(reg);
@@ -240,9 +249,12 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
        } else {
                pr_err("mxc: invalid configuration for GPIO %d: %x\n",
                       gpio, edge);
-               return;
+               goto unlock;
        }
        writel(val | (edge << (bit << 1)), reg);
+
+unlock:
+       raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags);
 }
 
 /* handle 32 interrupts in one status register */
index bed0380c51360a4e5e8cbd15959f685b4d2922fd..17c53f484280f086d46cb95bf2dd22a978cd96e8 100644 (file)
@@ -385,7 +385,7 @@ err:
 }
 
 static bool acpi_gpio_irq_is_wake(struct device *parent,
-                                 struct acpi_resource_gpio *agpio)
+                                 const struct acpi_resource_gpio *agpio)
 {
        unsigned int pin = agpio->pin_table[0];
 
@@ -778,7 +778,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
                lookup->info.pin_config = agpio->pin_config;
                lookup->info.debounce = agpio->debounce_timeout;
                lookup->info.gpioint = gpioint;
-               lookup->info.wake_capable = agpio->wake_capable == ACPI_WAKE_CAPABLE;
+               lookup->info.wake_capable = acpi_gpio_irq_is_wake(&lookup->info.adev->dev, agpio);
 
                /*
                 * Polarity and triggering are only specified for GpioInt
@@ -1104,7 +1104,8 @@ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, in
                                dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
                        }
 
-                       if (wake_capable)
+                       /* avoid suspend issues with GPIOs when systems are using S3 */
+                       if (wake_capable && acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)
                                *wake_capable = info.wake_capable;
 
                        return irq;
@@ -1623,6 +1624,19 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
                        .ignore_interrupt = "AMDI0030:00@18",
                },
        },
+       {
+               /*
+                * Spurious wakeups from TP_ATTN# pin
+                * Found in BIOS 1.7.8
+                * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
+                */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
+               },
+               .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+                       .ignore_wake = "ELAN0415:00@9",
+               },
+       },
        {} /* Terminating entry */
 };
 
index 23692e5d4d13b3d8b10fe5ad8502183a58dfb6ae..3380daf42da8af2a3884d3bf576ccbdbae846055 100644 (file)
@@ -156,6 +156,9 @@ static bool amdgpu_gfx_is_compute_multipipe_capable(struct amdgpu_device *adev)
                return amdgpu_compute_multipipe == 1;
        }
 
+       if (adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0))
+               return true;
+
        /* FIXME: spreading the queues across pipes causes perf regressions
         * on POLARIS11 compute workloads */
        if (adev->asic_type == CHIP_POLARIS11)
index fcb711a11a5b6bc4d4cff56289c97df89d1a70d4..3f07b1a2ce47f93e8e176e104e064fa6fbd36635 100644 (file)
@@ -497,6 +497,7 @@ void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
            !--id_mgr->reserved_use_count) {
                /* give the reserved ID back to normal round robin */
                list_add(&id_mgr->reserved->list, &id_mgr->ids_lru);
+               id_mgr->reserved = NULL;
        }
        vm->reserved_vmid[vmhub] = false;
        mutex_unlock(&id_mgr->lock);
index 9e549923622bd48b6dab1e11b2cbab8432f89b99..c3d9d75143f4ffb8d1a9b3ac6c53b9ce4b84211a 100644 (file)
@@ -161,8 +161,14 @@ void amdgpu_job_free_resources(struct amdgpu_job *job)
        struct dma_fence *f;
        unsigned i;
 
-       /* use sched fence if available */
-       f = job->base.s_fence ? &job->base.s_fence->finished :  &job->hw_fence;
+       /* Check if any fences where initialized */
+       if (job->base.s_fence && job->base.s_fence->finished.ops)
+               f = &job->base.s_fence->finished;
+       else if (job->hw_fence.ops)
+               f = &job->hw_fence;
+       else
+               f = NULL;
+
        for (i = 0; i < job->num_ibs; ++i)
                amdgpu_ib_free(ring->adev, &job->ibs[i], f);
 }
index a56c6e106d00df054da9c7e061fd07f902359a83..66eb102cd88fbdcb4c00dfb88a4574257eb47253 100644 (file)
@@ -790,8 +790,8 @@ static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd,
         * zero here */
        WARN_ON(simd != 0);
 
-       /* type 2 wave data */
-       dst[(*no_fields)++] = 2;
+       /* type 3 wave data */
+       dst[(*no_fields)++] = 3;
        dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_STATUS);
        dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_LO);
        dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_PC_HI);
@@ -1287,10 +1287,8 @@ static int gfx_v11_0_sw_init(void *handle)
 
        switch (adev->ip_versions[GC_HWIP][0]) {
        case IP_VERSION(11, 0, 0):
-       case IP_VERSION(11, 0, 1):
        case IP_VERSION(11, 0, 2):
        case IP_VERSION(11, 0, 3):
-       case IP_VERSION(11, 0, 4):
                adev->gfx.me.num_me = 1;
                adev->gfx.me.num_pipe_per_me = 1;
                adev->gfx.me.num_queue_per_pipe = 1;
@@ -1298,6 +1296,15 @@ static int gfx_v11_0_sw_init(void *handle)
                adev->gfx.mec.num_pipe_per_mec = 4;
                adev->gfx.mec.num_queue_per_pipe = 4;
                break;
+       case IP_VERSION(11, 0, 1):
+       case IP_VERSION(11, 0, 4):
+               adev->gfx.me.num_me = 1;
+               adev->gfx.me.num_pipe_per_me = 1;
+               adev->gfx.me.num_queue_per_pipe = 1;
+               adev->gfx.mec.num_mec = 1;
+               adev->gfx.mec.num_pipe_per_mec = 4;
+               adev->gfx.mec.num_queue_per_pipe = 4;
+               break;
        default:
                adev->gfx.me.num_me = 1;
                adev->gfx.me.num_pipe_per_me = 1;
index 95548c512f4fb7399b678264504024770388b75a..077c53c6cc08b063fe80203fe8f35450c23c918d 100644 (file)
@@ -35,6 +35,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_1_imu.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_2_imu.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_imu.bin");
 
 static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
 {
index 970b066b37bb917a0b99fdf54c8855bab86511e1..5dff79e8f3011010c85622a31bb48b1dc9453092 100644 (file)
@@ -40,6 +40,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_2_mes.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_2_mes1.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes.bin");
 MODULE_FIRMWARE("amdgpu/gc_11_0_3_mes1.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_mes1.bin");
 
 static int mes_v11_0_hw_fini(void *handle);
 static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev);
@@ -196,7 +198,6 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
        mes_add_queue_pkt.trap_handler_addr = input->tba_addr;
        mes_add_queue_pkt.tma_addr = input->tma_addr;
        mes_add_queue_pkt.is_kfd_process = input->is_kfd_process;
-       mes_add_queue_pkt.trap_en = 1;
 
        /* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
        mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
index 15eb3658d70e64ac31331b50e9b6efd42226b55a..09fdcd20cb9196595f9006d7a4309d2b62e7396f 100644 (file)
@@ -337,7 +337,13 @@ const struct nbio_hdp_flush_reg nbio_v4_3_hdp_flush_reg = {
 
 static void nbio_v4_3_init_registers(struct amdgpu_device *adev)
 {
-       return;
+       if (adev->ip_versions[NBIO_HWIP][0] == IP_VERSION(4, 3, 0)) {
+               uint32_t data;
+
+               data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2);
+               data &= ~RCC_DEV0_EPF2_STRAP2__STRAP_NO_SOFT_RESET_DEV0_F2_MASK;
+               WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF2_STRAP2, data);
+       }
 }
 
 static u32 nbio_v4_3_get_rom_offset(struct amdgpu_device *adev)
index 5562670b7b52193d01f61ad5fb5597f92ce32709..9eff5f41df9df7e2e8b7455b07d23d90329cdf04 100644 (file)
@@ -640,7 +640,8 @@ static int soc21_common_early_init(void *handle)
                        AMD_CG_SUPPORT_GFX_CGCG |
                        AMD_CG_SUPPORT_GFX_CGLS |
                        AMD_CG_SUPPORT_REPEATER_FGCG |
-                       AMD_CG_SUPPORT_GFX_MGCG;
+                       AMD_CG_SUPPORT_GFX_MGCG |
+                       AMD_CG_SUPPORT_HDP_SD;
                adev->pg_flags = AMD_PG_SUPPORT_VCN |
                        AMD_PG_SUPPORT_VCN_DPG |
                        AMD_PG_SUPPORT_JPEG;
index 1b7f20a9d4aeb970018f4ceb7b820f577ef4da85..31bce529f685010aa9b3751fafa1a91ec33749d4 100644 (file)
@@ -1503,8 +1503,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                case IP_VERSION(3, 0, 1):
                case IP_VERSION(3, 1, 2):
                case IP_VERSION(3, 1, 3):
-               case IP_VERSION(3, 1, 4):
-               case IP_VERSION(3, 1, 5):
                case IP_VERSION(3, 1, 6):
                        init_data.flags.gpu_vm_support = true;
                        break;
@@ -1730,10 +1728,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
                adev->dm.vblank_control_workqueue = NULL;
        }
 
-       for (i = 0; i < adev->dm.display_indexes_num; i++) {
-               drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
-       }
-
        amdgpu_dm_destroy_drm_device(&adev->dm);
 
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
@@ -4507,6 +4501,17 @@ DEVICE_ATTR_WO(s3_debug);
 static int dm_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       struct atom_context *ctx = mode_info->atom_context;
+       int index = GetIndexIntoMasterTable(DATA, Object_Header);
+       u16 data_offset;
+
+       /* if there is no object header, skip DM */
+       if (!amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
+               adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
+               dev_info(adev->dev, "No object header, skipping DM\n");
+               return -ENOENT;
+       }
 
        switch (adev->asic_type) {
 #if defined(CONFIG_DRM_AMD_DC_SI)
@@ -5311,8 +5316,6 @@ static void fill_stream_properties_from_drm_display_mode(
 
        timing_out->aspect_ratio = get_aspect_ratio(mode_in);
 
-       stream->output_color_space = get_output_color_space(timing_out);
-
        stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
        stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
        if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
@@ -5323,6 +5326,8 @@ static void fill_stream_properties_from_drm_display_mode(
                        adjust_colour_depth_from_display_info(timing_out, info);
                }
        }
+
+       stream->output_color_space = get_output_color_space(timing_out);
 }
 
 static void fill_audio_info(struct audio_info *audio_info,
@@ -8887,6 +8892,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                if (!dm_old_crtc_state->stream)
                        goto skip_modeset;
 
+               /* Unset freesync video if it was active before */
+               if (dm_old_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) {
+                       dm_new_crtc_state->freesync_config.state = VRR_STATE_INACTIVE;
+                       dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = 0;
+               }
+
+               /* Now check if we should set freesync video mode */
                if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
                    is_timing_unchanged_for_freesync(new_crtc_state,
                                                     old_crtc_state)) {
@@ -9503,6 +9515,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        bool lock_and_validation_needed = false;
        struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_topology_state *mst_state;
        struct dsc_mst_fairness_vars vars[MAX_PIPES];
 #endif
 
@@ -9530,8 +9544,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                        goto fail;
                }
 
-               if (dm_old_con_state->abm_level !=
-                   dm_new_con_state->abm_level)
+               if (dm_old_con_state->abm_level != dm_new_con_state->abm_level ||
+                   dm_old_con_state->scaling != dm_new_con_state->scaling)
                        new_crtc_state->connectors_changed = true;
        }
 
@@ -9751,6 +9765,28 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                lock_and_validation_needed = true;
        }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       /* set the slot info for each mst_state based on the link encoding format */
+       for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
+               struct amdgpu_dm_connector *aconnector;
+               struct drm_connector *connector;
+               struct drm_connector_list_iter iter;
+               u8 link_coding_cap;
+
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter) {
+                       if (connector->index == mst_state->mgr->conn_base_id) {
+                               aconnector = to_amdgpu_dm_connector(connector);
+                               link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
+                               drm_dp_mst_update_slots(mst_state, link_coding_cap);
+
+                               break;
+                       }
+               }
+               drm_connector_list_iter_end(&iter);
+       }
+#endif
+
        /**
         * Streams and planes are reset when there are changes that affect
         * bandwidth. Anything that affects bandwidth needs to go through
index 6994c9a1ed85885f6c0d531fedf5be1855bf4301..5cff56bb8f5602c77c65db8ddb156a1a19826d24 100644 (file)
@@ -120,23 +120,50 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
 }
 
 static void
-fill_dc_mst_payload_table_from_drm(struct drm_dp_mst_topology_state *mst_state,
-                                  struct amdgpu_dm_connector *aconnector,
+fill_dc_mst_payload_table_from_drm(struct dc_link *link,
+                                  bool enable,
+                                  struct drm_dp_mst_atomic_payload *target_payload,
                                   struct dc_dp_mst_stream_allocation_table *table)
 {
        struct dc_dp_mst_stream_allocation_table new_table = { 0 };
        struct dc_dp_mst_stream_allocation *sa;
-       struct drm_dp_mst_atomic_payload *payload;
+       struct link_mst_stream_allocation_table copy_of_link_table =
+                                                                               link->mst_stream_alloc_table;
+
+       int i;
+       int current_hw_table_stream_cnt = copy_of_link_table.stream_count;
+       struct link_mst_stream_allocation *dc_alloc;
+
+       /* TODO: refactor to set link->mst_stream_alloc_table directly if possible.*/
+       if (enable) {
+               dc_alloc =
+               &copy_of_link_table.stream_allocations[current_hw_table_stream_cnt];
+               dc_alloc->vcp_id = target_payload->vcpi;
+               dc_alloc->slot_count = target_payload->time_slots;
+       } else {
+               for (i = 0; i < copy_of_link_table.stream_count; i++) {
+                       dc_alloc =
+                       &copy_of_link_table.stream_allocations[i];
+
+                       if (dc_alloc->vcp_id == target_payload->vcpi) {
+                               dc_alloc->vcp_id = 0;
+                               dc_alloc->slot_count = 0;
+                               break;
+                       }
+               }
+               ASSERT(i != copy_of_link_table.stream_count);
+       }
 
        /* Fill payload info*/
-       list_for_each_entry(payload, &mst_state->payloads, next) {
-               if (payload->delete)
-                       continue;
-
-               sa = &new_table.stream_allocations[new_table.stream_count];
-               sa->slot_count = payload->time_slots;
-               sa->vcp_id = payload->vcpi;
-               new_table.stream_count++;
+       for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+               dc_alloc =
+                       &copy_of_link_table.stream_allocations[i];
+               if (dc_alloc->vcp_id > 0 && dc_alloc->slot_count > 0) {
+                       sa = &new_table.stream_allocations[new_table.stream_count];
+                       sa->slot_count = dc_alloc->slot_count;
+                       sa->vcp_id = dc_alloc->vcp_id;
+                       new_table.stream_count++;
+               }
        }
 
        /* Overwrite the old table */
@@ -185,7 +212,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
         * AUX message. The sequence is slot 1-63 allocated sequence for each
         * stream. AMD ASIC stream slot allocation should follow the same
         * sequence. copy DRM MST allocation to dc */
-       fill_dc_mst_payload_table_from_drm(mst_state, aconnector, proposed_table);
+       fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table);
 
        return true;
 }
index 1edf7385f8d89a6478c94a98a1e4e43075cc6461..abdbd4352f6f3cd02d5a6bb9bedbdcd58fc5320a 100644 (file)
@@ -468,7 +468,6 @@ static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs
 static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
 {
        drm_encoder_cleanup(encoder);
-       kfree(encoder);
 }
 
 static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
@@ -904,11 +903,6 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        if (IS_ERR(mst_state))
                return PTR_ERR(mst_state);
 
-       mst_state->pbn_div = dm_mst_get_pbn_divider(dc_link);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-       drm_dp_mst_update_slots(mst_state, dc_link_dp_mst_decide_link_encoding_format(dc_link));
-#endif
-
        /* Set up params */
        for (i = 0; i < dc_state->stream_count; i++) {
                struct dc_dsc_policy dsc_policy = {0};
index 471078fc3900d7377149ed3312841889b749b95b..652270a0b498ce45a9965d2761a8e18791c6dc51 100644 (file)
@@ -90,8 +90,8 @@ static const struct out_csc_color_matrix_type output_csc_matrix[] = {
                { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
                                0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
        { COLOR_SPACE_YCBCR2020_TYPE,
-               { 0x1000, 0xF149, 0xFEB7, 0x0000, 0x0868, 0x15B2,
-                               0x01E6, 0x0000, 0xFB88, 0xF478, 0x1000, 0x0000} },
+               { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
+                               0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
        { COLOR_SPACE_YCBCR709_BLACK_TYPE,
                { 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000,
                                0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x1000} },
index 342e906ae26e41498ef9a3f60c3da21f576c76ad..c88f044666fee624fc05c4ee0772cfdf1f2a05cd 100644 (file)
@@ -3995,10 +3995,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
        struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
        int i;
        bool mst_mode = (link->type == dc_connection_mst_branch);
+       /* adjust for drm changes*/
+       bool update_drm_mst_state = true;
        const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
        const struct dc_link_settings empty_link_settings = {0};
        DC_LOGGER_INIT(link->ctx->logger);
 
+
        /* deallocate_mst_payload is called before disable link. When mode or
         * disable/enable monitor, new stream is created which is not in link
         * stream[] yet. For this, payload is not allocated yet, so de-alloc
@@ -4014,7 +4017,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
                                &empty_link_settings,
                                avg_time_slots_per_mtp);
 
-       if (mst_mode) {
+       if (mst_mode || update_drm_mst_state) {
                /* when link is in mst mode, reply on mst manager to remove
                 * payload
                 */
@@ -4077,11 +4080,18 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
                        stream->ctx,
                        stream);
 
+               if (!update_drm_mst_state)
+                       dm_helpers_dp_mst_send_payload_allocation(
+                               stream->ctx,
+                               stream,
+                               false);
+       }
+
+       if (update_drm_mst_state)
                dm_helpers_dp_mst_send_payload_allocation(
                        stream->ctx,
                        stream,
                        false);
-       }
 
        return DC_OK;
 }
index f9ea1e86707f2a9ed23365340a3ed098b626afb5..79850a68f62ab0719e8c9c572f2f2e3c3f7aeb47 100644 (file)
@@ -874,8 +874,9 @@ static const struct dc_plane_cap plane_cap = {
        },
 
        // 6:1 downscaling ratio: 1000/6 = 166.666
+       // 4:1 downscaling ratio for ARGB888 to prevent underflow during P010 playback: 1000/4 = 250
        .max_downscale_factor = {
-                       .argb8888 = 167,
+                       .argb8888 = 250,
                        .nv12 = 167,
                        .fp16 = 167
        },
@@ -1763,7 +1764,7 @@ static bool dcn314_resource_construct(
        pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
        pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
        pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
-       dc->caps.max_downscale_ratio = 600;
+       dc->caps.max_downscale_ratio = 400;
        dc->caps.i2c_speed_in_khz = 100;
        dc->caps.i2c_speed_in_khz_hdcp = 100;
        dc->caps.max_cursor_size = 256;
index dc4649458567428e1c478f10092038fca55dae04..a4e9fd5307c63a72bbc8aae2bbce534f81b5e3d1 100644 (file)
@@ -94,7 +94,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
        .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
        .calc_vupdate_position = dcn10_calc_vupdate_position,
        .apply_idle_power_optimizations = dcn32_apply_idle_power_optimizations,
-       .does_plane_fit_in_mall = dcn30_does_plane_fit_in_mall,
+       .does_plane_fit_in_mall = NULL,
        .set_backlight_level = dcn21_set_backlight_level,
        .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
        .hardware_release = dcn30_hardware_release,
index 950669f2c10d77c5906f72f07f6fd6a488f33815..cb7c0c87842300c93c5e06475a617fbbb0257fdd 100644 (file)
@@ -3183,7 +3183,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
                } else {
                        v->MIN_DST_Y_NEXT_START[k] = v->VTotal[k] - v->VFrontPorch[k] + v->VTotal[k] - v->VActive[k] - v->VStartup[k];
                }
-               v->MIN_DST_Y_NEXT_START[k] += dml_floor(4.0 * v->TSetup[k] / (double)v->HTotal[k] / v->PixelClock[k], 1.0) / 4.0;
+               v->MIN_DST_Y_NEXT_START[k] += dml_floor(4.0 * v->TSetup[k] / ((double)v->HTotal[k] / v->PixelClock[k]), 1.0) / 4.0;
                if (((v->VUpdateOffsetPix[k] + v->VUpdateWidthPix[k] + v->VReadyOffsetPix[k]) / v->HTotal[k])
                                <= (isInterlaceTiming ?
                                                dml_floor((v->VTotal[k] - v->VActive[k] - v->VFrontPorch[k] - v->VStartup[k]) / 2.0, 1.0) :
index 4a122925c3ae96849c1c090e966ebb076935ed19..92c18bfb98b3badee51b02a0f2f8109971bda035 100644 (file)
@@ -532,6 +532,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
        if (dmub->hw_funcs.reset)
                dmub->hw_funcs.reset(dmub);
 
+       /* reset the cache of the last wptr as well now that hw is reset */
+       dmub->inbox1_last_wptr = 0;
+
        cw0.offset.quad_part = inst_fb->gpu_addr;
        cw0.region.base = DMUB_CW0_BASE;
        cw0.region.top = cw0.region.base + inst_fb->size - 1;
@@ -649,6 +652,15 @@ enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)
        if (dmub->hw_funcs.reset)
                dmub->hw_funcs.reset(dmub);
 
+       /* mailboxes have been reset in hw, so reset the sw state as well */
+       dmub->inbox1_last_wptr = 0;
+       dmub->inbox1_rb.wrpt = 0;
+       dmub->inbox1_rb.rptr = 0;
+       dmub->outbox0_rb.wrpt = 0;
+       dmub->outbox0_rb.rptr = 0;
+       dmub->outbox1_rb.wrpt = 0;
+       dmub->outbox1_rb.rptr = 0;
+
        dmub->hw_init = false;
 
        return DMUB_STATUS_OK;
index 236657eece4772f9fed32aaacf9ead556dece300..a9170360d7e854fb5e4007e31f8af45fc42bd398 100644 (file)
@@ -2007,14 +2007,16 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
                      gc_ver == IP_VERSION(10, 3, 0) ||
                      gc_ver == IP_VERSION(10, 1, 2) ||
                      gc_ver == IP_VERSION(11, 0, 0) ||
-                     gc_ver == IP_VERSION(11, 0, 2)))
+                     gc_ver == IP_VERSION(11, 0, 2) ||
+                     gc_ver == IP_VERSION(11, 0, 3)))
                        *states = ATTR_STATE_UNSUPPORTED;
        } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) {
                if (!(gc_ver == IP_VERSION(10, 3, 1) ||
                      gc_ver == IP_VERSION(10, 3, 0) ||
                      gc_ver == IP_VERSION(10, 1, 2) ||
                      gc_ver == IP_VERSION(11, 0, 0) ||
-                     gc_ver == IP_VERSION(11, 0, 2)))
+                     gc_ver == IP_VERSION(11, 0, 2) ||
+                     gc_ver == IP_VERSION(11, 0, 3)))
                        *states = ATTR_STATE_UNSUPPORTED;
        } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) {
                if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP)
index ca3beb5d8f2768459b1562488cf76de0c47cc95c..6ab155023592657855305d498d8d1c5a93c75d61 100644 (file)
@@ -1499,6 +1499,20 @@ static int smu_disable_dpms(struct smu_context *smu)
                }
        }
 
+       /*
+        * For SMU 13.0.4/11, PMFW will handle the features disablement properly
+        * for gpu reset case. Driver involvement is unnecessary.
+        */
+       if (amdgpu_in_reset(adev)) {
+               switch (adev->ip_versions[MP1_HWIP][0]) {
+               case IP_VERSION(13, 0, 4):
+               case IP_VERSION(13, 0, 11):
+                       return 0;
+               default:
+                       break;
+               }
+       }
+
        /*
         * For gpu reset, runpm and hibernation through BACO,
         * BACO feature has to be kept enabled.
index 85e22210963fc76de583d2139d3f76b0465eaf36..5cdc07165480b5a3be51ec46c722699d34d52b84 100644 (file)
@@ -1171,6 +1171,7 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu,
        int ret = 0;
        uint32_t apu_percent = 0;
        uint32_t dgpu_percent = 0;
+       struct amdgpu_device *adev = smu->adev;
 
 
        ret = smu_cmn_get_metrics_table(smu,
@@ -1196,7 +1197,11 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu,
                *value = metrics->AverageUvdActivity / 100;
                break;
        case METRICS_AVERAGE_SOCKETPOWER:
-               *value = (metrics->CurrentSocketPower << 8) / 1000;
+               if (((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(12, 0, 1)) && (adev->pm.fw_version >= 0x40000f)) ||
+               ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(12, 0, 0)) && (adev->pm.fw_version >= 0x373200)))
+                       *value = metrics->CurrentSocketPower << 8;
+               else
+                       *value = (metrics->CurrentSocketPower << 8) / 1000;
                break;
        case METRICS_TEMPERATURE_EDGE:
                *value = (metrics->GfxTemperature / 100) *
index 4c20d17e7416ee42e553e19f956b6145b18fb696..cf96c3f2affe4c807dec8a30cb6c5b20a9d4e67e 100644 (file)
@@ -145,6 +145,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel,
                            PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel,   0),
        MSG_MAP(AllowGpo,                       PPSMC_MSG_SetGpoAllow,           0),
+       MSG_MAP(AllowIHHostInterrupt,           PPSMC_MSG_AllowIHHostInterrupt,       0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
index a2f0860b20bb9a9993731953d74a3835ea567552..d751820c6da6ac304c725b22c121aadd8b0b0796 100644 (file)
@@ -193,6 +193,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
        struct hdmi_codec_pdata pdata;
        struct platform_device *platform;
 
+       memset(&pdata, 0, sizeof(pdata));
        pdata.ops               = &dw_hdmi_i2s_ops;
        pdata.i2s               = 1;
        pdata.max_i2s_channels  = 8;
index 51a46689cda70f0b7e2ae8471a6ec410546844b2..4ca37261584a945dcf3cc9575b692b1f8e1d0c32 100644 (file)
@@ -3372,6 +3372,9 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr,
 
        mgr->payload_count--;
        mgr->next_start_slot -= payload->time_slots;
+
+       if (payload->delete)
+               drm_dp_mst_put_port_malloc(payload->port);
 }
 EXPORT_SYMBOL(drm_dp_remove_payload);
 
@@ -4327,7 +4330,6 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state,
 
        drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots);
        if (!payload->delete) {
-               drm_dp_mst_put_port_malloc(port);
                payload->pbn = 0;
                payload->delete = true;
                topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
index b3a731b9170a6aa7919c5d1b24ef75f928561fd1..0d0c26ebab90696a297349af32314807ca5b6f9f 100644 (file)
@@ -30,7 +30,9 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/console.h>
+#include <linux/pci.h>
 #include <linux/sysrq.h>
+#include <linux/vga_switcheroo.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
@@ -1909,6 +1911,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                return ret;
 
        strcpy(fb_helper->fb->comm, "[fbcon]");
+
+       /* Set the fb info for vgaswitcheroo clients. Does nothing otherwise. */
+       if (dev_is_pci(dev->dev))
+               vga_switcheroo_client_fb_set(to_pci_dev(dev->dev), fb_helper->info);
+
        return 0;
 }
 
index ab869566927958108c0b220655c6cb45e2877bf6..593aa3283792b607066476c99c8c6c476ab3a22b 100644 (file)
@@ -171,11 +171,6 @@ static const struct fb_ops drm_fbdev_fb_ops = {
        .fb_imageblit   = drm_fbdev_fb_imageblit,
 };
 
-static struct fb_deferred_io drm_fbdev_defio = {
-       .delay          = HZ / 20,
-       .deferred_io    = drm_fb_helper_deferred_io,
-};
-
 /*
  * This function uses the client API to create a framebuffer backed by a dumb buffer.
  */
@@ -222,8 +217,14 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
                        return -ENOMEM;
                fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
 
-               fbi->fbdefio = &drm_fbdev_defio;
-               fb_deferred_io_init(fbi);
+               /* Set a default deferred I/O handler */
+               fb_helper->fbdefio.delay = HZ / 20;
+               fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
+
+               fbi->fbdefio = &fb_helper->fbdefio;
+               ret = fb_deferred_io_init(fbi);
+               if (ret)
+                       return ret;
        } else {
                /* buffer is mapped for HW framebuffer */
                ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
index 7de37f8c68fd0c76cb936c67f93152209cf4cb33..83229a031af0f829691934c8dae72d3ba6686853 100644 (file)
@@ -240,27 +240,8 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
 }
 EXPORT_SYMBOL(drm_vma_offset_remove);
 
-/**
- * drm_vma_node_allow - Add open-file to list of allowed users
- * @node: Node to modify
- * @tag: Tag of file to remove
- *
- * Add @tag to the list of allowed open-files for this node. If @tag is
- * already on this list, the ref-count is incremented.
- *
- * The list of allowed-users is preserved across drm_vma_offset_add() and
- * drm_vma_offset_remove() calls. You may even call it if the node is currently
- * not added to any offset-manager.
- *
- * You must remove all open-files the same number of times as you added them
- * before destroying the node. Otherwise, you will leak memory.
- *
- * This is locked against concurrent access internally.
- *
- * RETURNS:
- * 0 on success, negative error code on internal failure (out-of-mem)
- */
-int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
+static int vma_node_allow(struct drm_vma_offset_node *node,
+                         struct drm_file *tag, bool ref_counted)
 {
        struct rb_node **iter;
        struct rb_node *parent = NULL;
@@ -282,7 +263,8 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
                entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);
 
                if (tag == entry->vm_tag) {
-                       entry->vm_count++;
+                       if (ref_counted)
+                               entry->vm_count++;
                        goto unlock;
                } else if (tag > entry->vm_tag) {
                        iter = &(*iter)->rb_right;
@@ -307,8 +289,58 @@ unlock:
        kfree(new);
        return ret;
 }
+
+/**
+ * drm_vma_node_allow - Add open-file to list of allowed users
+ * @node: Node to modify
+ * @tag: Tag of file to remove
+ *
+ * Add @tag to the list of allowed open-files for this node. If @tag is
+ * already on this list, the ref-count is incremented.
+ *
+ * The list of allowed-users is preserved across drm_vma_offset_add() and
+ * drm_vma_offset_remove() calls. You may even call it if the node is currently
+ * not added to any offset-manager.
+ *
+ * You must remove all open-files the same number of times as you added them
+ * before destroying the node. Otherwise, you will leak memory.
+ *
+ * This is locked against concurrent access internally.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on internal failure (out-of-mem)
+ */
+int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
+{
+       return vma_node_allow(node, tag, true);
+}
 EXPORT_SYMBOL(drm_vma_node_allow);
 
+/**
+ * drm_vma_node_allow_once - Add open-file to list of allowed users
+ * @node: Node to modify
+ * @tag: Tag of file to remove
+ *
+ * Add @tag to the list of allowed open-files for this node.
+ *
+ * The list of allowed-users is preserved across drm_vma_offset_add() and
+ * drm_vma_offset_remove() calls. You may even call it if the node is currently
+ * not added to any offset-manager.
+ *
+ * This is not ref-counted unlike drm_vma_node_allow() hence drm_vma_node_revoke()
+ * should only be called once after this.
+ *
+ * This is locked against concurrent access internally.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on internal failure (out-of-mem)
+ */
+int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag)
+{
+       return vma_node_allow(node, tag, false);
+}
+EXPORT_SYMBOL(drm_vma_node_allow_once);
+
 /**
  * drm_vma_node_revoke - Remove open-file from list of allowed users
  * @node: Node to modify
index b74e36d76013863fee8abef434ea47ff2a5a9a24..407a477939e5329133f2c693e2fab66ed284da41 100644 (file)
@@ -1319,7 +1319,7 @@ static const struct intel_cdclk_vals adlp_cdclk_table[] = {
        { .refclk = 24000, .cdclk = 192000, .divider = 2, .ratio = 16 },
        { .refclk = 24000, .cdclk = 312000, .divider = 2, .ratio = 26 },
        { .refclk = 24000, .cdclk = 552000, .divider = 2, .ratio = 46 },
-       { .refclk = 24400, .cdclk = 648000, .divider = 2, .ratio = 54 },
+       { .refclk = 24000, .cdclk = 648000, .divider = 2, .ratio = 54 },
 
        { .refclk = 38400, .cdclk = 179200, .divider = 3, .ratio = 14 },
        { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 10 },
index 76490cc59d8f11df931e5c0a57691dcfe600357e..7d07fa3123ece747c046176f585a7091869fb15e 100644 (file)
@@ -1627,7 +1627,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
        u32 offset;
        int ret;
 
-       if (w > max_width || w < min_width || h > max_height) {
+       if (w > max_width || w < min_width || h > max_height || h < 1) {
                drm_dbg_kms(&dev_priv->drm,
                            "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
                            w, h, min_width, max_width, max_height);
index 6250de9b9196c5c5e17df3307d6def0428342112..e4b78ab4773b1f04770bfe189263c02efbb2c530 100644 (file)
@@ -1861,11 +1861,19 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv,
        vm = ctx->vm;
        GEM_BUG_ON(!vm);
 
+       /*
+        * Get a reference for the allocated handle.  Once the handle is
+        * visible in the vm_xa table, userspace could try to close it
+        * from under our feet, so we need to hold the extra reference
+        * first.
+        */
+       i915_vm_get(vm);
+
        err = xa_alloc(&file_priv->vm_xa, &id, vm, xa_limit_32b, GFP_KERNEL);
-       if (err)
+       if (err) {
+               i915_vm_put(vm);
                return err;
-
-       i915_vm_get(vm);
+       }
 
        GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */
        args->value = id;
index 0ad44f3868ded96b202afa569807a76c18c0549a..c7c252d4d366d449558b84f8c79071e6ea3f3144 100644 (file)
@@ -697,7 +697,7 @@ insert:
        GEM_BUG_ON(lookup_mmo(obj, mmap_type) != mmo);
 out:
        if (file)
-               drm_vma_node_allow(&mmo->vma_node, file);
+               drm_vma_node_allow_once(&mmo->vma_node, file);
        return mmo;
 
 err:
index fd42b89b7162b7e6e8210266ced13ba592da4920..bc21b1c2350a75d7a311eb002be57945cbc2020f 100644 (file)
@@ -305,10 +305,6 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
        spin_unlock(&obj->vma.lock);
 
        obj->tiling_and_stride = tiling | stride;
-       i915_gem_object_unlock(obj);
-
-       /* Force the fence to be reacquired for GTT access */
-       i915_gem_object_release_mmap_gtt(obj);
 
        /* Try to preallocate memory required to save swizzling on put-pages */
        if (i915_gem_object_needs_bit17_swizzle(obj)) {
@@ -321,6 +317,11 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
                obj->bit_17 = NULL;
        }
 
+       i915_gem_object_unlock(obj);
+
+       /* Force the fence to be reacquired for GTT access */
+       i915_gem_object_release_mmap_gtt(obj);
+
        return 0;
 }
 
index beaf27e09e8a9d6fdebe9046d242a303d43d6deb..977dead10ab57c857ae3ffa319fdfc69da0a2a76 100644 (file)
@@ -1847,7 +1847,7 @@ static int igt_shrink_thp(void *arg)
                        I915_SHRINK_ACTIVE);
        i915_vma_unpin(vma);
        if (err)
-               goto out_put;
+               goto out_wf;
 
        /*
         * Now that the pages are *unpinned* shrinking should invoke
@@ -1863,19 +1863,19 @@ static int igt_shrink_thp(void *arg)
                pr_err("unexpected pages mismatch, should_swap=%s\n",
                       str_yes_no(should_swap));
                err = -EINVAL;
-               goto out_put;
+               goto out_wf;
        }
 
        if (should_swap == (obj->mm.page_sizes.sg || obj->mm.page_sizes.phys)) {
                pr_err("unexpected residual page-size bits, should_swap=%s\n",
                       str_yes_no(should_swap));
                err = -EINVAL;
-               goto out_put;
+               goto out_wf;
        }
 
        err = i915_vma_pin(vma, 0, 0, flags);
        if (err)
-               goto out_put;
+               goto out_wf;
 
        while (n--) {
                err = cpu_check(obj, n, 0xdeadbeaf);
index e94365b08f1efc133c8b6e88f2ba43156f414fa9..2aa63ec521b89844df7bdea1dd399e04f8de7bce 100644 (file)
@@ -528,7 +528,7 @@ retry:
        return rq;
 }
 
-struct i915_request *intel_context_find_active_request(struct intel_context *ce)
+struct i915_request *intel_context_get_active_request(struct intel_context *ce)
 {
        struct intel_context *parent = intel_context_to_parent(ce);
        struct i915_request *rq, *active = NULL;
@@ -552,6 +552,8 @@ struct i915_request *intel_context_find_active_request(struct intel_context *ce)
 
                active = rq;
        }
+       if (active)
+               active = i915_request_get_rcu(active);
        spin_unlock_irqrestore(&parent->guc_state.lock, flags);
 
        return active;
index fb62b7b8cbcda6ef2bf5487c69a1ffd74ac99c34..0a8d553da3f439e0df0a05d10799049313175ef7 100644 (file)
@@ -268,8 +268,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce,
 
 struct i915_request *intel_context_create_request(struct intel_context *ce);
 
-struct i915_request *
-intel_context_find_active_request(struct intel_context *ce);
+struct i915_request *intel_context_get_active_request(struct intel_context *ce);
 
 static inline bool intel_context_is_barrier(const struct intel_context *ce)
 {
index cbc8b857d5f7a0948897b12e154564395a16f282..7a4504ea35c365ae18b610a908be51f86598307a 100644 (file)
@@ -248,8 +248,8 @@ void intel_engine_dump_active_requests(struct list_head *requests,
 ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine,
                                   ktime_t *now);
 
-struct i915_request *
-intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine);
+void intel_engine_get_hung_entity(struct intel_engine_cs *engine,
+                                 struct intel_context **ce, struct i915_request **rq);
 
 u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
 struct intel_context *
index c33e0d72d6702ba00115f305ebf9abf173d26231..d37931e16fd9b2ed856b50a7f0eb18810012be4b 100644 (file)
@@ -2094,17 +2094,6 @@ static void print_request_ring(struct drm_printer *m, struct i915_request *rq)
        }
 }
 
-static unsigned long list_count(struct list_head *list)
-{
-       struct list_head *pos;
-       unsigned long count = 0;
-
-       list_for_each(pos, list)
-               count++;
-
-       return count;
-}
-
 static unsigned long read_ul(void *p, size_t x)
 {
        return *(unsigned long *)(p + x);
@@ -2196,11 +2185,11 @@ void intel_engine_dump_active_requests(struct list_head *requests,
        }
 }
 
-static void engine_dump_active_requests(struct intel_engine_cs *engine, struct drm_printer *m)
+static void engine_dump_active_requests(struct intel_engine_cs *engine,
+                                       struct drm_printer *m)
 {
+       struct intel_context *hung_ce = NULL;
        struct i915_request *hung_rq = NULL;
-       struct intel_context *ce;
-       bool guc;
 
        /*
         * No need for an engine->irq_seqno_barrier() before the seqno reads.
@@ -2209,27 +2198,22 @@ static void engine_dump_active_requests(struct intel_engine_cs *engine, struct d
         * But the intention here is just to report an instantaneous snapshot
         * so that's fine.
         */
-       lockdep_assert_held(&engine->sched_engine->lock);
+       intel_engine_get_hung_entity(engine, &hung_ce, &hung_rq);
 
        drm_printf(m, "\tRequests:\n");
 
-       guc = intel_uc_uses_guc_submission(&engine->gt->uc);
-       if (guc) {
-               ce = intel_engine_get_hung_context(engine);
-               if (ce)
-                       hung_rq = intel_context_find_active_request(ce);
-       } else {
-               hung_rq = intel_engine_execlist_find_hung_request(engine);
-       }
-
        if (hung_rq)
                engine_dump_request(hung_rq, m, "\t\thung");
+       else if (hung_ce)
+               drm_printf(m, "\t\tGot hung ce but no hung rq!\n");
 
-       if (guc)
+       if (intel_uc_uses_guc_submission(&engine->gt->uc))
                intel_guc_dump_active_requests(engine, hung_rq, m);
        else
-               intel_engine_dump_active_requests(&engine->sched_engine->requests,
-                                                 hung_rq, m);
+               intel_execlists_dump_active_requests(engine, hung_rq, m);
+
+       if (hung_rq)
+               i915_request_put(hung_rq);
 }
 
 void intel_engine_dump(struct intel_engine_cs *engine,
@@ -2239,7 +2223,6 @@ void intel_engine_dump(struct intel_engine_cs *engine,
        struct i915_gpu_error * const error = &engine->i915->gpu_error;
        struct i915_request *rq;
        intel_wakeref_t wakeref;
-       unsigned long flags;
        ktime_t dummy;
 
        if (header) {
@@ -2276,13 +2259,8 @@ void intel_engine_dump(struct intel_engine_cs *engine,
                   i915_reset_count(error));
        print_properties(engine, m);
 
-       spin_lock_irqsave(&engine->sched_engine->lock, flags);
        engine_dump_active_requests(engine, m);
 
-       drm_printf(m, "\tOn hold?: %lu\n",
-                  list_count(&engine->sched_engine->hold));
-       spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
-
        drm_printf(m, "\tMMIO base:  0x%08x\n", engine->mmio_base);
        wakeref = intel_runtime_pm_get_if_in_use(engine->uncore->rpm);
        if (wakeref) {
@@ -2328,8 +2306,7 @@ intel_engine_create_virtual(struct intel_engine_cs **siblings,
        return siblings[0]->cops->create_virtual(siblings, count, flags);
 }
 
-struct i915_request *
-intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)
+static struct i915_request *engine_execlist_find_hung_request(struct intel_engine_cs *engine)
 {
        struct i915_request *request, *active = NULL;
 
@@ -2381,6 +2358,33 @@ intel_engine_execlist_find_hung_request(struct intel_engine_cs *engine)
        return active;
 }
 
+void intel_engine_get_hung_entity(struct intel_engine_cs *engine,
+                                 struct intel_context **ce, struct i915_request **rq)
+{
+       unsigned long flags;
+
+       *ce = intel_engine_get_hung_context(engine);
+       if (*ce) {
+               intel_engine_clear_hung_context(engine);
+
+               *rq = intel_context_get_active_request(*ce);
+               return;
+       }
+
+       /*
+        * Getting here with GuC enabled means it is a forced error capture
+        * with no actual hang. So, no need to attempt the execlist search.
+        */
+       if (intel_uc_uses_guc_submission(&engine->gt->uc))
+               return;
+
+       spin_lock_irqsave(&engine->sched_engine->lock, flags);
+       *rq = engine_execlist_find_hung_request(engine);
+       if (*rq)
+               *rq = i915_request_get_rcu(*rq);
+       spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
+}
+
 void xehp_enable_ccs_engines(struct intel_engine_cs *engine)
 {
        /*
index 2daffa7c7dfd00ea31e57b2461946065113960ec..21cb5b69d82ebccd4295e39e8b0606c2fc5436c9 100644 (file)
@@ -4148,6 +4148,33 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
        spin_unlock_irqrestore(&sched_engine->lock, flags);
 }
 
+static unsigned long list_count(struct list_head *list)
+{
+       struct list_head *pos;
+       unsigned long count = 0;
+
+       list_for_each(pos, list)
+               count++;
+
+       return count;
+}
+
+void intel_execlists_dump_active_requests(struct intel_engine_cs *engine,
+                                         struct i915_request *hung_rq,
+                                         struct drm_printer *m)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&engine->sched_engine->lock, flags);
+
+       intel_engine_dump_active_requests(&engine->sched_engine->requests, hung_rq, m);
+
+       drm_printf(m, "\tOn hold?: %lu\n",
+                  list_count(&engine->sched_engine->hold));
+
+       spin_unlock_irqrestore(&engine->sched_engine->lock, flags);
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftest_execlists.c"
 #endif
index a1aa92c983a51adacaf3f4b68f6ade944f386822..d2c7d45ea0623b4d113b128ff5b42f730fedcedf 100644 (file)
@@ -32,6 +32,10 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
                                                        int indent),
                                   unsigned int max);
 
+void intel_execlists_dump_active_requests(struct intel_engine_cs *engine,
+                                         struct i915_request *hung_rq,
+                                         struct drm_printer *m);
+
 bool
 intel_engine_in_execlists_submission_mode(const struct intel_engine_cs *engine);
 
index 4a14f87e441e56b162837363f9cf53bddb74cbe7..a5454af2a9cfdc380c8f23c6469c404a96ad2481 100644 (file)
 #define   RC_OP_FLUSH_ENABLE                   (1 << 0)
 #define   HIZ_RAW_STALL_OPT_DISABLE            (1 << 2)
 #define CACHE_MODE_1                           _MMIO(0x7004) /* IVB+ */
-#define   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE    (1 << 6)
-#define   GEN8_4x4_STC_OPTIMIZATION_DISABLE    (1 << 6)
-#define   GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE   (1 << 1)
+#define   MSAA_OPTIMIZATION_REDUC_DISABLE      REG_BIT(11)
+#define   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE    REG_BIT(6)
+#define   GEN8_4x4_STC_OPTIMIZATION_DISABLE    REG_BIT(6)
+#define   GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE   REG_BIT(1)
 
 #define GEN7_GT_MODE                           _MMIO(0x7008)
 #define   GEN9_IZ_HASHING_MASK(slice)          (0x3 << ((slice) * 2))
 #define GEN8_L3CNTLREG                         _MMIO(0x7034)
 #define   GEN8_ERRDETBCTRL                     (1 << 9)
 
+#define PSS_MODE2                              _MMIO(0x703c)
+#define   SCOREBOARD_STALL_FLUSH_CONTROL       REG_BIT(5)
+
 #define GEN7_SC_INSTDONE                       _MMIO(0x7100)
 #define GEN12_SC_INSTDONE_EXTRA                        _MMIO(0x7104)
 #define GEN12_SC_INSTDONE_EXTRA2               _MMIO(0x7108)
index 7771a19008c60459c89ea613caf15b255d0fc37f..bbeeb6dde7aee2d70737d1127d8284622a510b31 100644 (file)
@@ -288,39 +288,6 @@ static const u8 dg2_xcs_offsets[] = {
        END
 };
 
-static const u8 mtl_xcs_offsets[] = {
-       NOP(1),
-       LRI(13, POSTED),
-       REG16(0x244),
-       REG(0x034),
-       REG(0x030),
-       REG(0x038),
-       REG(0x03c),
-       REG(0x168),
-       REG(0x140),
-       REG(0x110),
-       REG(0x1c0),
-       REG(0x1c4),
-       REG(0x1c8),
-       REG(0x180),
-       REG16(0x2b4),
-       NOP(4),
-
-       NOP(1),
-       LRI(9, POSTED),
-       REG16(0x3a8),
-       REG16(0x28c),
-       REG16(0x288),
-       REG16(0x284),
-       REG16(0x280),
-       REG16(0x27c),
-       REG16(0x278),
-       REG16(0x274),
-       REG16(0x270),
-
-       END
-};
-
 static const u8 gen8_rcs_offsets[] = {
        NOP(1),
        LRI(14, POSTED),
@@ -739,9 +706,7 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
                else
                        return gen8_rcs_offsets;
        } else {
-               if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 70))
-                       return mtl_xcs_offsets;
-               else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
+               if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
                        return dg2_xcs_offsets;
                else if (GRAPHICS_VER(engine->i915) >= 12)
                        return gen12_xcs_offsets;
index 5be2f91801fbf39ebcf0aa5571a15320093a7704..949c19339015b074af9e75662edda4268dbc4912 100644 (file)
@@ -771,11 +771,19 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine,
 
        /* Wa_14014947963:dg2 */
        if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_B0, STEP_FOREVER) ||
-               IS_DG2_G11(engine->i915) || IS_DG2_G12(engine->i915))
+           IS_DG2_G11(engine->i915) || IS_DG2_G12(engine->i915))
                wa_masked_field_set(wal, VF_PREEMPTION, PREEMPTION_VERTEX_COUNT, 0x4000);
 
+       /* Wa_18018764978:dg2 */
+       if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_C0, STEP_FOREVER) ||
+           IS_DG2_G11(engine->i915) || IS_DG2_G12(engine->i915))
+               wa_masked_en(wal, PSS_MODE2, SCOREBOARD_STALL_FLUSH_CONTROL);
+
        /* Wa_15010599737:dg2 */
        wa_mcr_masked_en(wal, CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN);
+
+       /* Wa_18019271663:dg2 */
+       wa_masked_en(wal, CACHE_MODE_1, MSAA_OPTIMIZATION_REDUC_DISABLE);
 }
 
 static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine,
index 0a42f1807f52c3293254634eb14b20a778dbf4cf..c10977cb06b972e184083a9f812b79b73dc5f2d3 100644 (file)
@@ -1702,7 +1702,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st
                        goto next_context;
 
                guilty = false;
-               rq = intel_context_find_active_request(ce);
+               rq = intel_context_get_active_request(ce);
                if (!rq) {
                        head = ce->ring->tail;
                        goto out_replay;
@@ -1715,6 +1715,7 @@ static void __guc_reset_context(struct intel_context *ce, intel_engine_mask_t st
                head = intel_ring_wrap(ce->ring, rq->head);
 
                __i915_request_reset(rq, guilty);
+               i915_request_put(rq);
 out_replay:
                guc_reset_state(ce, head, guilty);
 next_context:
@@ -4817,6 +4818,8 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine)
 
        xa_lock_irqsave(&guc->context_lookup, flags);
        xa_for_each(&guc->context_lookup, index, ce) {
+               bool found;
+
                if (!kref_get_unless_zero(&ce->ref))
                        continue;
 
@@ -4833,10 +4836,18 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine)
                                goto next;
                }
 
+               found = false;
+               spin_lock(&ce->guc_state.lock);
                list_for_each_entry(rq, &ce->guc_state.requests, sched.link) {
                        if (i915_test_request_state(rq) != I915_REQUEST_ACTIVE)
                                continue;
 
+                       found = true;
+                       break;
+               }
+               spin_unlock(&ce->guc_state.lock);
+
+               if (found) {
                        intel_engine_set_hung_context(engine, ce);
 
                        /* Can only cope with one hang at a time... */
@@ -4844,6 +4855,7 @@ void intel_guc_find_hung_context(struct intel_engine_cs *engine)
                        xa_lock(&guc->context_lookup);
                        goto done;
                }
+
 next:
                intel_context_put(ce);
                xa_lock(&guc->context_lookup);
index 69103ae37779217bc4235383aad1c757c63cd57c..61c38fc734cfb65c2d2790dd0b86e5f8875ce2e3 100644 (file)
@@ -1069,12 +1069,9 @@ static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
  */
 static void i915_driver_lastclose(struct drm_device *dev)
 {
-       struct drm_i915_private *i915 = to_i915(dev);
-
        intel_fbdev_restore_mode(dev);
 
-       if (HAS_DISPLAY(i915))
-               vga_switcheroo_process_delayed_switch();
+       vga_switcheroo_process_delayed_switch();
 }
 
 static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
index 9d5d5a397b64e414d15371e0e1fbdc21c34ce607..b20bd6365615b5bce67973af6d265e37af320b41 100644 (file)
@@ -1596,43 +1596,20 @@ capture_engine(struct intel_engine_cs *engine,
 {
        struct intel_engine_capture_vma *capture = NULL;
        struct intel_engine_coredump *ee;
-       struct intel_context *ce;
+       struct intel_context *ce = NULL;
        struct i915_request *rq = NULL;
-       unsigned long flags;
 
        ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags);
        if (!ee)
                return NULL;
 
-       ce = intel_engine_get_hung_context(engine);
-       if (ce) {
-               intel_engine_clear_hung_context(engine);
-               rq = intel_context_find_active_request(ce);
-               if (!rq || !i915_request_started(rq))
-                       goto no_request_capture;
-       } else {
-               /*
-                * Getting here with GuC enabled means it is a forced error capture
-                * with no actual hang. So, no need to attempt the execlist search.
-                */
-               if (!intel_uc_uses_guc_submission(&engine->gt->uc)) {
-                       spin_lock_irqsave(&engine->sched_engine->lock, flags);
-                       rq = intel_engine_execlist_find_hung_request(engine);
-                       spin_unlock_irqrestore(&engine->sched_engine->lock,
-                                              flags);
-               }
-       }
-       if (rq)
-               rq = i915_request_get_rcu(rq);
-
-       if (!rq)
+       intel_engine_get_hung_entity(engine, &ce, &rq);
+       if (!rq || !i915_request_started(rq))
                goto no_request_capture;
 
        capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL);
-       if (!capture) {
-               i915_request_put(rq);
+       if (!capture)
                goto no_request_capture;
-       }
        if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)
                intel_guc_capture_get_matching_node(engine->gt, ee, ce);
 
@@ -1642,6 +1619,8 @@ capture_engine(struct intel_engine_cs *engine,
        return ee;
 
 no_request_capture:
+       if (rq)
+               i915_request_put(rq);
        kfree(ee);
        return NULL;
 }
index ccd1f864aa19686d52704c75e64a6c404b28c510..4fada7ebe8d8233df7d38958ff0f352466f3da68 100644 (file)
@@ -423,7 +423,8 @@ static const struct intel_device_info ilk_m_info = {
        .has_coherent_ggtt = true, \
        .has_llc = 1, \
        .has_rc6 = 1, \
-       .has_rc6p = 1, \
+       /* snb does support rc6p, but enabling it causes various issues */ \
+       .has_rc6p = 0, \
        .has_rps = true, \
        .dma_mask_size = 40, \
        .__runtime.ppgtt_type = INTEL_PPGTT_ALIASING, \
index 23777d500cdf95972dcc1b3f55a91eac7f5c5982..f45bd6b6cede45ca405929a0840f1d66fe13c75d 100644 (file)
@@ -19,6 +19,10 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev,
                dev_err(&pdev->dev, "DRM not initialized, aborting switch.\n");
                return;
        }
+       if (!HAS_DISPLAY(i915)) {
+               dev_err(&pdev->dev, "Device state not initialized, aborting switch.\n");
+               return;
+       }
 
        if (state == VGA_SWITCHEROO_ON) {
                drm_info(&i915->drm, "switched on\n");
@@ -44,7 +48,7 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
         * locking inversion with the driver load path. And the access here is
         * completely racy anyway. So don't bother with locking for now.
         */
-       return i915 && atomic_read(&i915->drm.open_count) == 0;
+       return i915 && HAS_DISPLAY(i915) && atomic_read(&i915->drm.open_count) == 0;
 }
 
 static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
index 310fb83c527ebcaddbf57dd09235f85758488a1f..2990dd4d4a0d8a84ad5794815dbb4661610314a2 100644 (file)
@@ -28,8 +28,7 @@ struct intel_engine_cs *intel_selftest_find_any_engine(struct intel_gt *gt)
 
 int intel_selftest_modify_policy(struct intel_engine_cs *engine,
                                 struct intel_selftest_saved_policy *saved,
-                                u32 modify_type)
-
+                                enum selftest_scheduler_modify modify_type)
 {
        int err;
 
index 628806423f7d2d162c4ffd6f1b34d61f1f94c1f0..36f062c7582f9a8ec7b7b54c6a3e8abb1804252a 100644 (file)
@@ -551,13 +551,14 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
        return 0;
 }
 
+static int adreno_system_suspend(struct device *dev);
 static void adreno_unbind(struct device *dev, struct device *master,
                void *data)
 {
        struct msm_drm_private *priv = dev_get_drvdata(master);
        struct msm_gpu *gpu = dev_to_gpu(dev);
 
-       pm_runtime_force_suspend(dev);
+       WARN_ON_ONCE(adreno_system_suspend(dev));
        gpu->funcs->destroy(gpu);
 
        priv->gpu_pdev = NULL;
@@ -609,7 +610,7 @@ static int adreno_remove(struct platform_device *pdev)
 
 static void adreno_shutdown(struct platform_device *pdev)
 {
-       pm_runtime_force_suspend(&pdev->dev);
+       WARN_ON_ONCE(adreno_system_suspend(&pdev->dev));
 }
 
 static const struct of_device_id dt_match[] = {
index 57586c794b84bde8c012594e1422a66dc5021e3d..3605f095b2de24bf20640a5b5efecba65b196b14 100644 (file)
@@ -352,6 +352,8 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
                /* Ensure string is null terminated: */
                str[len] = '\0';
 
+               mutex_lock(&gpu->lock);
+
                if (param == MSM_PARAM_COMM) {
                        paramp = &ctx->comm;
                } else {
@@ -361,6 +363,8 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
                kfree(*paramp);
                *paramp = str;
 
+               mutex_unlock(&gpu->lock);
+
                return 0;
        }
        case MSM_PARAM_SYSPROF:
index 30ed45af76ade1de740a1f3bfcc7f00bd09b619e..3802495003258a1258650a2c73c1a0572283dfc6 100644 (file)
@@ -335,6 +335,8 @@ static void get_comm_cmdline(struct msm_gem_submit *submit, char **comm, char **
        struct msm_file_private *ctx = submit->queue->ctx;
        struct task_struct *task;
 
+       WARN_ON(!mutex_is_locked(&submit->gpu->lock));
+
        /* Note that kstrdup will return NULL if argument is NULL: */
        *comm = kstrdup(ctx->comm, GFP_KERNEL);
        *cmd  = kstrdup(ctx->cmdline, GFP_KERNEL);
index 651786bc55e5a8a989a882840ac62857f1f41017..732295e2568345f1fc5a6d4e62da647e186ce104 100644 (file)
@@ -376,10 +376,18 @@ struct msm_file_private {
         */
        int sysprof;
 
-       /** comm: Overridden task comm, see MSM_PARAM_COMM */
+       /**
+        * comm: Overridden task comm, see MSM_PARAM_COMM
+        *
+        * Accessed under msm_gpu::lock
+        */
        char *comm;
 
-       /** cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE */
+       /**
+        * cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE
+        *
+        * Accessed under msm_gpu::lock
+        */
        char *cmdline;
 
        /**
index 40768373cdd90de752d157568135061ff4790310..c5a4f49ee2065416137af9fc64180b1b4ce9e570 100644 (file)
@@ -97,6 +97,7 @@ int gp100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n
 int gp102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
 int gp10b_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
 int gv100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
+int tu102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
 int ga100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
 int ga102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
 
index fcf2a002f6cb2d6e9868678d5dfbcf922e661f9a..91fb494d4009354d8c0380c74a73688c28625ed9 100644 (file)
@@ -151,6 +151,9 @@ nvkm_firmware_mem_page(struct nvkm_memory *memory)
 static enum nvkm_memory_target
 nvkm_firmware_mem_target(struct nvkm_memory *memory)
 {
+       if (nvkm_firmware_mem(memory)->device->func->tegra)
+               return NVKM_MEM_TARGET_NCOH;
+
        return NVKM_MEM_TARGET_HOST;
 }
 
index 364fea320cb37c28b34ebc1343e3b128b0e6ac08..1c81e5b34d29d871b35431c47b9d1ff651fc5245 100644 (file)
@@ -2405,7 +2405,7 @@ nv162_chipset = {
        .bus      = { 0x00000001, gf100_bus_new },
        .devinit  = { 0x00000001, tu102_devinit_new },
        .fault    = { 0x00000001, tu102_fault_new },
-       .fb       = { 0x00000001, gv100_fb_new },
+       .fb       = { 0x00000001, tu102_fb_new },
        .fuse     = { 0x00000001, gm107_fuse_new },
        .gpio     = { 0x00000001, gk104_gpio_new },
        .gsp      = { 0x00000001, gv100_gsp_new },
@@ -2440,7 +2440,7 @@ nv164_chipset = {
        .bus      = { 0x00000001, gf100_bus_new },
        .devinit  = { 0x00000001, tu102_devinit_new },
        .fault    = { 0x00000001, tu102_fault_new },
-       .fb       = { 0x00000001, gv100_fb_new },
+       .fb       = { 0x00000001, tu102_fb_new },
        .fuse     = { 0x00000001, gm107_fuse_new },
        .gpio     = { 0x00000001, gk104_gpio_new },
        .gsp      = { 0x00000001, gv100_gsp_new },
@@ -2475,7 +2475,7 @@ nv166_chipset = {
        .bus      = { 0x00000001, gf100_bus_new },
        .devinit  = { 0x00000001, tu102_devinit_new },
        .fault    = { 0x00000001, tu102_fault_new },
-       .fb       = { 0x00000001, gv100_fb_new },
+       .fb       = { 0x00000001, tu102_fb_new },
        .fuse     = { 0x00000001, gm107_fuse_new },
        .gpio     = { 0x00000001, gk104_gpio_new },
        .gsp      = { 0x00000001, gv100_gsp_new },
@@ -2510,7 +2510,7 @@ nv167_chipset = {
        .bus      = { 0x00000001, gf100_bus_new },
        .devinit  = { 0x00000001, tu102_devinit_new },
        .fault    = { 0x00000001, tu102_fault_new },
-       .fb       = { 0x00000001, gv100_fb_new },
+       .fb       = { 0x00000001, tu102_fb_new },
        .fuse     = { 0x00000001, gm107_fuse_new },
        .gpio     = { 0x00000001, gk104_gpio_new },
        .gsp      = { 0x00000001, gv100_gsp_new },
@@ -2545,7 +2545,7 @@ nv168_chipset = {
        .bus      = { 0x00000001, gf100_bus_new },
        .devinit  = { 0x00000001, tu102_devinit_new },
        .fault    = { 0x00000001, tu102_fault_new },
-       .fb       = { 0x00000001, gv100_fb_new },
+       .fb       = { 0x00000001, tu102_fb_new },
        .fuse     = { 0x00000001, gm107_fuse_new },
        .gpio     = { 0x00000001, gk104_gpio_new },
        .gsp      = { 0x00000001, gv100_gsp_new },
index 393ade9f7e6c48449a962c1b21f1bf7c7a950def..b7da3ab44c277d764e7f1551dcccc6232554a385 100644 (file)
@@ -48,6 +48,16 @@ gm200_flcn_pio_dmem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int l
                img += 4;
                len -= 4;
        }
+
+       /* Sigh.  Tegra PMU FW's init message... */
+       if (len) {
+               u32 data = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8));
+
+               while (len--) {
+                       *(u8 *)img++ = data & 0xff;
+                       data >>= 8;
+               }
+       }
 }
 
 static void
@@ -64,6 +74,8 @@ gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int l
                img += 4;
                len -= 4;
        }
+
+       WARN_ON(len);
 }
 
 static void
@@ -74,7 +86,7 @@ gm200_flcn_pio_dmem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 d
 
 const struct nvkm_falcon_func_pio
 gm200_flcn_dmem_pio = {
-       .min = 4,
+       .min = 1,
        .max = 0x100,
        .wr_init = gm200_flcn_pio_dmem_wr_init,
        .wr = gm200_flcn_pio_dmem_wr,
index 634f64f88fc8be391f3efba4e0ff8744eed9e94c..81a1ad2c88a7e2887f561f6eca81c68351eb0c62 100644 (file)
@@ -65,10 +65,33 @@ tu102_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
        return ret;
 }
 
+static int
+tu102_devinit_wait(struct nvkm_device *device)
+{
+       unsigned timeout = 50 + 2000;
+
+       do {
+               if (nvkm_rd32(device, 0x118128) & 0x00000001) {
+                       if ((nvkm_rd32(device, 0x118234) & 0x000000ff) == 0xff)
+                               return 0;
+               }
+
+               usleep_range(1000, 2000);
+       } while (timeout--);
+
+       return -ETIMEDOUT;
+}
+
 int
 tu102_devinit_post(struct nvkm_devinit *base, bool post)
 {
        struct nv50_devinit *init = nv50_devinit(base);
+       int ret;
+
+       ret = tu102_devinit_wait(init->base.subdev.device);
+       if (ret)
+               return ret;
+
        gm200_devinit_preos(init, post);
        return 0;
 }
index 5d0bab8ecb433d60dd28306048f4f7ca656ea483..6ba5120a2ebe1d8c6f7804f4cd17634c3deba887 100644 (file)
@@ -32,6 +32,7 @@ nvkm-y += nvkm/subdev/fb/gp100.o
 nvkm-y += nvkm/subdev/fb/gp102.o
 nvkm-y += nvkm/subdev/fb/gp10b.o
 nvkm-y += nvkm/subdev/fb/gv100.o
+nvkm-y += nvkm/subdev/fb/tu102.o
 nvkm-y += nvkm/subdev/fb/ga100.o
 nvkm-y += nvkm/subdev/fb/ga102.o
 
index 8b7c8ea5e8a5f3f887f20fb3c3a92b1b1b2b8e1c..5a21b0ae459580b1318727e00e1432a94f1abbeb 100644 (file)
@@ -40,12 +40,6 @@ ga102_fb_vpr_scrub(struct nvkm_fb *fb)
        return ret;
 }
 
-static bool
-ga102_fb_vpr_scrub_required(struct nvkm_fb *fb)
-{
-       return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0;
-}
-
 static const struct nvkm_fb_func
 ga102_fb = {
        .dtor = gf100_fb_dtor,
@@ -56,7 +50,7 @@ ga102_fb = {
        .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
        .ram_new = ga102_ram_new,
        .default_bigpage = 16,
-       .vpr.scrub_required = ga102_fb_vpr_scrub_required,
+       .vpr.scrub_required = tu102_fb_vpr_scrub_required,
        .vpr.scrub = ga102_fb_vpr_scrub,
 };
 
index 1f0126437c1aa1d0a1bb742b0376bae28379d38a..0e3c0a8f5d716e6796d0a40f790b6c312ccf479e 100644 (file)
@@ -49,8 +49,3 @@ gv100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, s
 }
 
 MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin");
-MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin");
-MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin");
-MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin");
-MODULE_FIRMWARE("nvidia/tu116/nvdec/scrubber.bin");
-MODULE_FIRMWARE("nvidia/tu117/nvdec/scrubber.bin");
index ac03eac0f2616950c38c3d88ea238352d4024b6a..f517751f94acddc5f4c1d585085cc644f72c931c 100644 (file)
@@ -89,4 +89,6 @@ bool gp102_fb_vpr_scrub_required(struct nvkm_fb *);
 int gp102_fb_vpr_scrub(struct nvkm_fb *);
 
 int gv100_fb_init_page(struct nvkm_fb *);
+
+bool tu102_fb_vpr_scrub_required(struct nvkm_fb *);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c
new file mode 100644 (file)
index 0000000..be82af0
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "gf100.h"
+#include "ram.h"
+
+bool
+tu102_fb_vpr_scrub_required(struct nvkm_fb *fb)
+{
+       return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0;
+}
+
+static const struct nvkm_fb_func
+tu102_fb = {
+       .dtor = gf100_fb_dtor,
+       .oneinit = gf100_fb_oneinit,
+       .init = gm200_fb_init,
+       .init_page = gv100_fb_init_page,
+       .init_unkn = gp100_fb_init_unkn,
+       .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
+       .vpr.scrub_required = tu102_fb_vpr_scrub_required,
+       .vpr.scrub = gp102_fb_vpr_scrub,
+       .ram_new = gp100_ram_new,
+       .default_bigpage = 16,
+};
+
+int
+tu102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
+{
+       return gp102_fb_new_(&tu102_fb, device, type, inst, pfb);
+}
+
+MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu116/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu117/nvdec/scrubber.bin");
index a72403777329ea00f26eb2c1b3f519ea16b77348..2ed04da3621d53dc2a58b6071444530aea58fec6 100644 (file)
@@ -225,7 +225,7 @@ gm20b_pmu_init(struct nvkm_pmu *pmu)
 
        pmu->initmsg_received = false;
 
-       nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
+       nvkm_falcon_pio_wr(falcon, (u8 *)&args, 0, 0, DMEM, addr_args, sizeof(args), 0, false);
        nvkm_falcon_start(falcon);
        return 0;
 }
index 857a2f0420d778731006b3b92754293de6726c7c..c924f1124ebca9c9a180a32fbe6be0b0ed1600e6 100644 (file)
@@ -1193,14 +1193,11 @@ static int boe_panel_enter_sleep_mode(struct boe_panel *boe)
        return 0;
 }
 
-static int boe_panel_unprepare(struct drm_panel *panel)
+static int boe_panel_disable(struct drm_panel *panel)
 {
        struct boe_panel *boe = to_boe_panel(panel);
        int ret;
 
-       if (!boe->prepared)
-               return 0;
-
        ret = boe_panel_enter_sleep_mode(boe);
        if (ret < 0) {
                dev_err(panel->dev, "failed to set panel off: %d\n", ret);
@@ -1209,6 +1206,16 @@ static int boe_panel_unprepare(struct drm_panel *panel)
 
        msleep(150);
 
+       return 0;
+}
+
+static int boe_panel_unprepare(struct drm_panel *panel)
+{
+       struct boe_panel *boe = to_boe_panel(panel);
+
+       if (!boe->prepared)
+               return 0;
+
        if (boe->desc->discharge_on_disable) {
                regulator_disable(boe->avee);
                regulator_disable(boe->avdd);
@@ -1528,6 +1535,7 @@ static enum drm_panel_orientation boe_panel_get_orientation(struct drm_panel *pa
 }
 
 static const struct drm_panel_funcs boe_panel_funcs = {
+       .disable = boe_panel_disable,
        .unprepare = boe_panel_unprepare,
        .prepare = boe_panel_prepare,
        .enable = boe_panel_enable,
index 079600328be18776adee49954d8d4705fca7296a..e6403a9d66adec323e3698aee16a8649ae51248b 100644 (file)
@@ -3,7 +3,8 @@
 config DRM_PANFROST
        tristate "Panfrost (DRM support for ARM Mali Midgard/Bifrost GPUs)"
        depends on DRM
-       depends on ARM || ARM64 || (COMPILE_TEST && !GENERIC_ATOMIC64)
+       depends on ARM || ARM64 || COMPILE_TEST
+       depends on !GENERIC_ATOMIC64    # for IOMMU_IO_PGTABLE_LPAE
        depends on MMU
        select DRM_SCHED
        select IOMMU_SUPPORT
index 53464afc2b9ac723e42028319d6348e0c2f1b9c1..91f69e62430bbcd02b672e319cc8132cc3d2d345 100644 (file)
@@ -656,18 +656,8 @@ static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = {
        .atomic_check = drm_crtc_helper_atomic_check,
 };
 
-static void ssd130x_crtc_reset(struct drm_crtc *crtc)
-{
-       struct drm_device *drm = crtc->dev;
-       struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
-
-       ssd130x_init(ssd130x);
-
-       drm_atomic_helper_crtc_reset(crtc);
-}
-
 static const struct drm_crtc_funcs ssd130x_crtc_funcs = {
-       .reset = ssd130x_crtc_reset,
+       .reset = drm_atomic_helper_crtc_reset,
        .destroy = drm_crtc_cleanup,
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
@@ -686,6 +676,12 @@ static void ssd130x_encoder_helper_atomic_enable(struct drm_encoder *encoder,
        if (ret)
                return;
 
+       ret = ssd130x_init(ssd130x);
+       if (ret) {
+               ssd130x_power_off(ssd130x);
+               return;
+       }
+
        ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
 
        backlight_enable(ssd130x->bl_dev);
index 43d9b3a6a352c1c451737ca06e84230176935322..c5947ed8cc812b65a63f2cf52078bee3a72ceee8 100644 (file)
@@ -179,6 +179,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
                bo->validated_shader = NULL;
        }
 
+       mutex_destroy(&bo->madv_lock);
        drm_gem_dma_free(&bo->base);
 }
 
@@ -394,7 +395,6 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct vc4_bo *bo;
-       int ret;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
                return ERR_PTR(-ENODEV);
@@ -406,9 +406,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
        bo->madv = VC4_MADV_WILLNEED;
        refcount_set(&bo->usecnt, 0);
 
-       ret = drmm_mutex_init(dev, &bo->madv_lock);
-       if (ret)
-               return ERR_PTR(ret);
+       mutex_init(&bo->madv_lock);
 
        mutex_lock(&vc4->bo_lock);
        bo->label = VC4_BO_TYPE_KERNEL;
index 12a00d644b61929808eb7a3842fbc8366ddae23d..55744216392b295a9861f789d395953704534764 100644 (file)
@@ -3018,7 +3018,8 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
        }
 
        vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-                                                 vc4_hdmi, "vc4",
+                                                 vc4_hdmi,
+                                                 vc4_hdmi->variant->card_name,
                                                  CEC_CAP_DEFAULTS |
                                                  CEC_CAP_CONNECTOR_INFO, 1);
        ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
old mode 100755 (executable)
new mode 100644 (file)
index ab125f79408f253c639eda94783a83994e630e41..1fb0f7105fb21ba3b68f0034b45b2db90fa6d37b 100644 (file)
@@ -282,7 +282,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
                }
                rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
                if (rc)
-                       return rc;
+                       goto cleanup;
                mp2_ops->start(privdata, info);
                status = amd_sfh_wait_for_response
                                (privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
index 4da2f9f62aba3828d31a5ed8135943178b7e59d1..a1d6e08fab7d4330334839bb83e7f45394612e9e 100644 (file)
@@ -160,7 +160,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
                }
                rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
                if (rc)
-                       return rc;
+                       goto cleanup;
 
                writel(0, privdata->mmio + AMD_P2C_MSG(0));
                mp2_ops->start(privdata, info);
index 467d789f9bc2d3a0d846c661b618d1b640a63188..25ed7b9a917e4f2e1b1828caf039d691b0a07fca 100644 (file)
@@ -60,7 +60,6 @@ static int betopff_init(struct hid_device *hid)
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev;
-       int field_count = 0;
        int error;
        int i, j;
 
@@ -86,19 +85,21 @@ static int betopff_init(struct hid_device *hid)
         * -----------------------------------------
         * Do init them with default value.
         */
+       if (report->maxfield < 4) {
+               hid_err(hid, "not enough fields in the report: %d\n",
+                               report->maxfield);
+               return -ENODEV;
+       }
        for (i = 0; i < report->maxfield; i++) {
+               if (report->field[i]->report_count < 1) {
+                       hid_err(hid, "no values in the field\n");
+                       return -ENODEV;
+               }
                for (j = 0; j < report->field[i]->report_count; j++) {
                        report->field[i]->value[j] = 0x00;
-                       field_count++;
                }
        }
 
-       if (field_count < 4) {
-               hid_err(hid, "not enough fields in the report: %d\n",
-                               field_count);
-               return -ENODEV;
-       }
-
        betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
        if (!betopff)
                return -ENOMEM;
index e8c5e3ac9fff1596b4962697cbf42be116c9d600..e8b16665860d6b04609d814f89bc048ec45274c8 100644 (file)
@@ -344,6 +344,11 @@ static int bigben_probe(struct hid_device *hid,
        }
 
        report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       if (list_empty(report_list)) {
+               hid_err(hid, "no output report found\n");
+               error = -ENODEV;
+               goto error_hw_stop;
+       }
        bigben->report = list_entry(report_list->next,
                struct hid_report, list);
 
index bd47628da6be0da0c9fa228727007f4c8a99b607..3e1803592bd4a224facc6111634fd7e34226ada1 100644 (file)
@@ -993,8 +993,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
                 * Validating on id 0 means we should examine the first
                 * report in the list.
                 */
-               report = list_entry(
-                               hid->report_enum[type].report_list.next,
+               report = list_first_entry_or_null(
+                               &hid->report_enum[type].report_list,
                                struct hid_report, list);
        } else {
                report = hid->report_enum[type].report_id_hash[id];
index 82713ef3aaa64c5c310700c615755c5dab3e4706..0f8c11842a3a588ab0c9ee87ec37720827b86d50 100644 (file)
 #define USB_DEVICE_ID_CH_AXIS_295      0x001c
 
 #define USB_VENDOR_ID_CHERRY           0x046a
-#define USB_DEVICE_ID_CHERRY_MOUSE_000C        0x000c
 #define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
 #define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR    0x0027
 
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540   0x0075
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640   0x0094
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
+#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2      0x0905
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S     0x0909
 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
index f399bf0d3c8cc33d117d0b060960e611619acc3c..27c40894acab40252da8f917b27902791ec6d176 100644 (file)
@@ -944,6 +944,7 @@ ATTRIBUTE_GROUPS(ps_device);
 
 static int dualsense_get_calibration_data(struct dualsense *ds)
 {
+       struct hid_device *hdev = ds->base.hdev;
        short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
        short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
        short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
@@ -954,6 +955,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
        int speed_2x;
        int range_2g;
        int ret = 0;
+       int i;
        uint8_t *buf;
 
        buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
@@ -1005,6 +1007,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
        ds->gyro_calib_data[2].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S;
        ds->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
 
+       /*
+        * Sanity check gyro calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing
+        * calibration data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds->gyro_calib_data); i++) {
+               if (ds->gyro_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
+                                       ds->gyro_calib_data[i].abs_code);
+                       ds->gyro_calib_data[i].bias = 0;
+                       ds->gyro_calib_data[i].sens_numer = DS_GYRO_RANGE;
+                       ds->gyro_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
        /*
         * Set accelerometer calibration and normalization parameters.
         * Data values will be normalized to 1/DS_ACC_RES_PER_G g.
@@ -1027,6 +1044,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
        ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G;
        ds->accel_calib_data[2].sens_denom = range_2g;
 
+       /*
+        * Sanity check accelerometer calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing calibration
+        * data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds->accel_calib_data); i++) {
+               if (ds->accel_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
+                                       ds->accel_calib_data[i].abs_code);
+                       ds->accel_calib_data[i].bias = 0;
+                       ds->accel_calib_data[i].sens_numer = DS_ACC_RANGE;
+                       ds->accel_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
 err_free:
        kfree(buf);
        return ret;
@@ -1737,6 +1769,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
        int speed_2x;
        int range_2g;
        int ret = 0;
+       int i;
        uint8_t *buf;
 
        if (ds4->base.hdev->bus == BUS_USB) {
@@ -1830,6 +1863,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
        ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
        ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
 
+       /*
+        * Sanity check gyro calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing
+        * calibration data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
+               if (ds4->gyro_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
+                                       ds4->gyro_calib_data[i].abs_code);
+                       ds4->gyro_calib_data[i].bias = 0;
+                       ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
+                       ds4->gyro_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
        /*
         * Set accelerometer calibration and normalization parameters.
         * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
@@ -1852,6 +1900,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
        ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
        ds4->accel_calib_data[2].sens_denom = range_2g;
 
+       /*
+        * Sanity check accelerometer calibration data. This is needed to prevent crashes
+        * during report handling of virtual, clone or broken devices not implementing calibration
+        * data properly.
+        */
+       for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
+               if (ds4->accel_calib_data[i].sens_denom == 0) {
+                       hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
+                                       ds4->accel_calib_data[i].abs_code);
+                       ds4->accel_calib_data[i].bias = 0;
+                       ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE;
+                       ds4->accel_calib_data[i].sens_denom = S16_MAX;
+               }
+       }
+
 err_free:
        kfree(buf);
        return ret;
index 0e9702c7f7d6c09613107fe46aba779e86de02dc..be3ad02573de816cde758cf2fd82f0d864386885 100644 (file)
@@ -54,7 +54,6 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_MOUSE_000C), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS },
index 7fa6fe04f1b262656186ccd7a4c9f5fcb52679c8..cfbbc39807a69f80bfe100ba04c96c297418220a 100644 (file)
@@ -525,6 +525,8 @@ static const struct hid_device_id uclogic_devices[] = {
                                USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
                                USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
+                               USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
                                USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
index cd1233d7e2535ff0926d09cb027bb6750a05595a..3c5eea3df3288bed9a51b3bb4daa9c803313d9a5 100644 (file)
@@ -1655,6 +1655,8 @@ int uclogic_params_init(struct uclogic_params *params,
                break;
        case VID_PID(USB_VENDOR_ID_UGEE,
                     USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
+       case VID_PID(USB_VENDOR_ID_UGEE,
+                    USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01_V2):
        case VID_PID(USB_VENDOR_ID_UGEE,
                     USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
        case VID_PID(USB_VENDOR_ID_UGEE,
index 40554c8daca07bf4e0d78b05c22d30ceff82e2c4..00046cbfd4ed07bef8e8893e1723c4d62c46ea16 100644 (file)
@@ -104,6 +104,11 @@ void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev,
        int required_slots = (size / DMA_SLOT_SIZE)
                + 1 * (size % DMA_SLOT_SIZE != 0);
 
+       if (!dev->ishtp_dma_tx_map) {
+               dev_err(dev->devc, "Fail to allocate Tx map\n");
+               return NULL;
+       }
+
        spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
        for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
                free = 1;
@@ -150,6 +155,11 @@ void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev,
                return;
        }
 
+       if (!dev->ishtp_dma_tx_map) {
+               dev_err(dev->devc, "Fail to allocate Tx map\n");
+               return;
+       }
+
        i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
        spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
        for (j = 0; j < acked_slots; j++) {
index cbe43e2567a7fb496a16899eece9a1efc6d2d5cc..64ac5bdee3a623cccaab9dd4cbfb5313ef74e6a3 100644 (file)
@@ -1963,7 +1963,7 @@ static void  hv_balloon_debugfs_init(struct hv_dynmem_device *b)
 
 static void  hv_balloon_debugfs_exit(struct hv_dynmem_device *b)
 {
-       debugfs_remove(debugfs_lookup("hv-balloon", NULL));
+       debugfs_lookup_and_remove("hv-balloon", NULL);
 }
 
 #else
index bdf3b50de8adbfa568680ed81a0ad72adf5e6646..c1c74ce084071c9f5a94d8cd0f05cb086b0419db 100644 (file)
 #define SDA_HOLD_TIME          0x90
 
 /**
- * axxia_i2c_dev - I2C device context
+ * struct axxia_i2c_dev - I2C device context
  * @base: pointer to register struct
  * @msg: pointer to current message
  * @msg_r: pointer to current read message (sequence transfer)
index a3240ece55b2b189433c7a0e09653a4ea5caece5..581e02cc979a06f9ec4700f4e0794ef2e7215082 100644 (file)
@@ -351,7 +351,8 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
                 *
                 * If your hardware is free from tHD;STA issue, try this one.
                 */
-               return DIV_ROUND_CLOSEST(ic_clk * tSYMBOL, MICRO) - 8 + offset;
+               return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * tSYMBOL, MICRO) -
+                      8 + offset;
        else
                /*
                 * Conditional expression:
@@ -367,7 +368,8 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
                 * The reason why we need to take into account "tf" here,
                 * is the same as described in i2c_dw_scl_lcnt().
                 */
-               return DIV_ROUND_CLOSEST(ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset;
+               return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tSYMBOL + tf), MICRO) -
+                      3 + offset;
 }
 
 u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
@@ -383,7 +385,8 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
         * account the fall time of SCL signal (tf).  Default tf value
         * should be 0.3 us, for safety.
         */
-       return DIV_ROUND_CLOSEST(ic_clk * (tLOW + tf), MICRO) - 1 + offset;
+       return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) -
+              1 + offset;
 }
 
 int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
index e499f96506c521ee1212ae87e2d5103e53b2f71e..782fe1ef3ca10ec26eae70c8a0386dff90881000 100644 (file)
@@ -396,6 +396,8 @@ static const struct pci_device_id i2_designware_pci_ids[] = {
        { PCI_VDEVICE(ATI,  0x73a4), navi_amd },
        { PCI_VDEVICE(ATI,  0x73e4), navi_amd },
        { PCI_VDEVICE(ATI,  0x73c4), navi_amd },
+       { PCI_VDEVICE(ATI,  0x7444), navi_amd },
+       { PCI_VDEVICE(ATI,  0x7464), navi_amd },
        { 0,}
 };
 MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
index ba043b5473936b67f135b0d34c24efa2518cc12e..74182db03a88b36946b6f897e5de1db62c32b222 100644 (file)
@@ -351,13 +351,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 
        if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
                dev_pm_set_driver_flags(&pdev->dev,
-                                       DPM_FLAG_SMART_PREPARE |
-                                       DPM_FLAG_MAY_SKIP_RESUME);
+                                       DPM_FLAG_SMART_PREPARE);
        } else {
                dev_pm_set_driver_flags(&pdev->dev,
                                        DPM_FLAG_SMART_PREPARE |
-                                       DPM_FLAG_SMART_SUSPEND |
-                                       DPM_FLAG_MAY_SKIP_RESUME);
+                                       DPM_FLAG_SMART_SUSPEND);
        }
 
        device_enable_async_suspend(&pdev->dev);
@@ -419,21 +417,8 @@ static int dw_i2c_plat_prepare(struct device *dev)
         */
        return !has_acpi_companion(dev);
 }
-
-static void dw_i2c_plat_complete(struct device *dev)
-{
-       /*
-        * The device can only be in runtime suspend at this point if it has not
-        * been resumed throughout the ending system suspend/resume cycle, so if
-        * the platform firmware might mess up with it, request the runtime PM
-        * framework to resume it.
-        */
-       if (pm_runtime_suspended(dev) && pm_resume_via_firmware())
-               pm_request_resume(dev);
-}
 #else
 #define dw_i2c_plat_prepare    NULL
-#define dw_i2c_plat_complete   NULL
 #endif
 
 #ifdef CONFIG_PM
@@ -483,7 +468,6 @@ static int __maybe_unused dw_i2c_plat_resume(struct device *dev)
 
 static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
        .prepare = dw_i2c_plat_prepare,
-       .complete = dw_i2c_plat_complete,
        SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
        SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, dw_i2c_plat_runtime_resume, NULL)
 };
index 5af5cffc444ef0cbbff5812f6bb67dace170744d..d113bed7954526e1cb9afff96b8df98be26d1f15 100644 (file)
@@ -826,8 +826,8 @@ static int mxs_i2c_probe(struct platform_device *pdev)
        /* Setup the DMA */
        i2c->dmach = dma_request_chan(dev, "rx-tx");
        if (IS_ERR(i2c->dmach)) {
-               dev_err(dev, "Failed to request dma\n");
-               return PTR_ERR(i2c->dmach);
+               return dev_err_probe(dev, PTR_ERR(i2c->dmach),
+                                    "Failed to request dma\n");
        }
 
        platform_set_drvdata(pdev, i2c);
index d1658ed76562b8817e401a977871da581e4796fc..b31cf4f18f8548571dc8f387ad8e3c29ebe6fdc1 100644 (file)
@@ -80,7 +80,7 @@ enum {
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
 /**
- * struct i2c_spec_values:
+ * struct i2c_spec_values - I2C specification values for various modes
  * @min_hold_start_ns: min hold time (repeated) START condition
  * @min_low_ns: min LOW period of the SCL clock
  * @min_high_ns: min HIGH period of the SCL cloc
@@ -136,7 +136,7 @@ static const struct i2c_spec_values fast_mode_plus_spec = {
 };
 
 /**
- * struct rk3x_i2c_calced_timings:
+ * struct rk3x_i2c_calced_timings - calculated V1 timings
  * @div_low: Divider output for low
  * @div_high: Divider output for high
  * @tuning: Used to adjust setup/hold data time,
@@ -159,7 +159,7 @@ enum rk3x_i2c_state {
 };
 
 /**
- * struct rk3x_i2c_soc_data:
+ * struct rk3x_i2c_soc_data - SOC-specific data
  * @grf_offset: offset inside the grf regmap for setting the i2c type
  * @calc_timings: Callback function for i2c timing information calculated
  */
@@ -239,7 +239,8 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
 }
 
 /**
- * Generate a START condition, which triggers a REG_INT_START interrupt.
+ * rk3x_i2c_start - Generate a START condition, which triggers a REG_INT_START interrupt.
+ * @i2c: target controller data
  */
 static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
@@ -258,8 +259,8 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 }
 
 /**
- * Generate a STOP condition, which triggers a REG_INT_STOP interrupt.
- *
+ * rk3x_i2c_stop - Generate a STOP condition, which triggers a REG_INT_STOP interrupt.
+ * @i2c: target controller data
  * @error: Error code to return in rk3x_i2c_xfer
  */
 static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)
@@ -298,7 +299,8 @@ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)
 }
 
 /**
- * Setup a read according to i2c->msg
+ * rk3x_i2c_prepare_read - Setup a read according to i2c->msg
+ * @i2c: target controller data
  */
 static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)
 {
@@ -329,7 +331,8 @@ static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)
 }
 
 /**
- * Fill the transmit buffer with data from i2c->msg
+ * rk3x_i2c_fill_transmit_buf - Fill the transmit buffer with data from i2c->msg
+ * @i2c: target controller data
  */
 static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c)
 {
@@ -532,11 +535,10 @@ out:
 }
 
 /**
- * Get timing values of I2C specification
- *
+ * rk3x_i2c_get_spec - Get timing values of I2C specification
  * @speed: Desired SCL frequency
  *
- * Returns: Matched i2c spec values.
+ * Return: Matched i2c_spec_values.
  */
 static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 {
@@ -549,13 +551,12 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 }
 
 /**
- * Calculate divider values for desired SCL frequency
- *
+ * rk3x_i2c_v0_calc_timings - Calculate divider values for desired SCL frequency
  * @clk_rate: I2C input clock rate
  * @t: Known I2C timing information
  * @t_calc: Caculated rk3x private timings that would be written into regs
  *
- * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
@@ -710,13 +711,12 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
 }
 
 /**
- * Calculate timing values for desired SCL frequency
- *
+ * rk3x_i2c_v1_calc_timings - Calculate timing values for desired SCL frequency
  * @clk_rate: I2C input clock rate
  * @t: Known I2C timing information
  * @t_calc: Caculated rk3x private timings that would be written into regs
  *
- * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  * The following formulas are v1's method to calculate timings.
@@ -960,14 +960,14 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 }
 
 /**
- * Setup I2C registers for an I2C operation specified by msgs, num.
- *
- * Must be called with i2c->lock held.
- *
+ * rk3x_i2c_setup - Setup I2C registers for an I2C operation specified by msgs, num.
+ * @i2c: target controller data
  * @msgs: I2C msgs to process
  * @num: Number of msgs
  *
- * returns: Number of I2C msgs processed or negative in case of error
+ * Must be called with i2c->lock held.
+ *
+ * Return: Number of I2C msgs processed or negative in case of error
  */
 static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)
 {
index a2def6f9380a3054a405dcd3f7e9b5375dc75618..5eac7ea199931253e3d280f1d986c42b15e9e788 100644 (file)
@@ -280,6 +280,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
                        hid_sensor_convert_timestamp(
                                        &accel_state->common_attributes,
                                        *(int64_t *)raw_data);
+               ret = 0;
        break;
        default:
                break;
index 3d2e8b4db61ae7408ad0e12b2831bdffe9a2b84e..a4e7c7eff5acf4bc0fe97411b6cf4d6c91e8852d 100644 (file)
@@ -298,8 +298,10 @@ static int berlin2_adc_probe(struct platform_device *pdev)
        int ret;
 
        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
-       if (!indio_dev)
+       if (!indio_dev) {
+               of_node_put(parent_np);
                return -ENOMEM;
+       }
 
        priv = iio_priv(indio_dev);
 
index 36777b827165a0e5be3504d19426eaa4796c87fa..f5a0fc9e64c542acb4742a5abfb4458685657150 100644 (file)
@@ -86,6 +86,8 @@
 
 #define IMX8QXP_ADC_TIMEOUT            msecs_to_jiffies(100)
 
+#define IMX8QXP_ADC_MAX_FIFO_SIZE              16
+
 struct imx8qxp_adc {
        struct device *dev;
        void __iomem *regs;
@@ -95,6 +97,7 @@ struct imx8qxp_adc {
        /* Serialise ADC channel reads */
        struct mutex lock;
        struct completion completion;
+       u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE];
 };
 
 #define IMX8QXP_ADC_CHAN(_idx) {                               \
@@ -238,8 +241,7 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev,
                        return ret;
                }
 
-               *val = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK,
-                                readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO));
+               *val = adc->fifo[0];
 
                mutex_unlock(&adc->lock);
                return IIO_VAL_INT;
@@ -265,10 +267,15 @@ static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id)
 {
        struct imx8qxp_adc *adc = dev_id;
        u32 fifo_count;
+       int i;
 
        fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK,
                               readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL));
 
+       for (i = 0; i < fifo_count; i++)
+               adc->fifo[i] = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK,
+                               readl_relaxed(adc->regs + IMX8QXP_ADR_ADC_RESFIFO));
+
        if (fifo_count)
                complete(&adc->completion);
 
index 6d21ea84fa82dec567ff6fa57312d42916b97b9c..a428bdb567d52acb635256516ee0b729475f26da 100644 (file)
@@ -1520,6 +1520,7 @@ static const struct of_device_id stm32_dfsdm_adc_match[] = {
        },
        {}
 };
+MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match);
 
 static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
 {
index f53e8558b560c7e04e7e41fd22eddfecf0c3c38c..32873fb5f3676df29fec137ca0e77ec1115711dd 100644 (file)
 #define TWL6030_GPADCS                         BIT(1)
 #define TWL6030_GPADCR                         BIT(0)
 
+#define USB_VBUS_CTRL_SET                      0x04
+#define USB_ID_CTRL_SET                                0x06
+
+#define TWL6030_MISC1                          0xE4
+#define VBUS_MEAS                              0x01
+#define ID_MEAS                                        0x01
+
+#define VAC_MEAS                0x04
+#define VBAT_MEAS               0x02
+#define BB_MEAS                 0x01
+
+
 /**
  * struct twl6030_chnl_calib - channel calibration
  * @gain:              slope coefficient for ideal curve
@@ -927,6 +939,26 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       ret = twl_i2c_write_u8(TWL_MODULE_USB, VBUS_MEAS, USB_VBUS_CTRL_SET);
+       if (ret < 0) {
+               dev_err(dev, "failed to wire up inputs\n");
+               return ret;
+       }
+
+       ret = twl_i2c_write_u8(TWL_MODULE_USB, ID_MEAS, USB_ID_CTRL_SET);
+       if (ret < 0) {
+               dev_err(dev, "failed to wire up inputs\n");
+               return ret;
+       }
+
+       ret = twl_i2c_write_u8(TWL6030_MODULE_ID0,
+                               VBAT_MEAS | BB_MEAS | VAC_MEAS,
+                               TWL6030_MISC1);
+       if (ret < 0) {
+               dev_err(dev, "failed to wire up inputs\n");
+               return ret;
+       }
+
        indio_dev->name = DRIVER_NAME;
        indio_dev->info = &twl6030_gpadc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
index 5b4bdf3a26bb8a942151ddbdea53dc3ec6a8f5ad..a507d2e17079286797a726fb52563346525a2393 100644 (file)
@@ -1329,7 +1329,7 @@ static int ams_parse_firmware(struct iio_dev *indio_dev)
 
        dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL);
        if (!dev_channels)
-               ret = -ENOMEM;
+               return -ENOMEM;
 
        indio_dev->channels = dev_channels;
        indio_dev->num_channels = num_channels;
index 8f0ad022c7f1bc40d5d9e0a8a1800b9a2c90e378..698c50da1f10917957d833aa8c520ec709928805 100644 (file)
@@ -231,6 +231,7 @@ static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
                gyro_state->timestamp =
                        hid_sensor_convert_timestamp(&gyro_state->common_attributes,
                                                     *(s64 *)raw_data);
+               ret = 0;
        break;
        default:
                break;
index 423cfe526f2a13aecb32461d6da68c37eb9b8b45..6d189c4b9ff962e0a241680e2d075a002ff69c39 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/regmap.h>
 #include <linux/acpi.h>
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #define FXOS8700_NVM_DATA_BNK0      0xa7
 
 /* Bit definitions for FXOS8700_CTRL_REG1 */
-#define FXOS8700_CTRL_ODR_MSK       0x38
 #define FXOS8700_CTRL_ODR_MAX       0x00
-#define FXOS8700_CTRL_ODR_MIN       GENMASK(4, 3)
+#define FXOS8700_CTRL_ODR_MSK       GENMASK(5, 3)
 
 /* Bit definitions for FXOS8700_M_CTRL_REG1 */
 #define FXOS8700_HMS_MASK           GENMASK(1, 0)
@@ -320,7 +320,7 @@ static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
        switch (iio_type) {
        case IIO_ACCEL:
                return FXOS8700_ACCEL;
-       case IIO_ANGL_VEL:
+       case IIO_MAGN:
                return FXOS8700_MAGN;
        default:
                return -EINVAL;
@@ -345,15 +345,35 @@ static int fxos8700_set_active_mode(struct fxos8700_data *data,
 static int fxos8700_set_scale(struct fxos8700_data *data,
                              enum fxos8700_sensor t, int uscale)
 {
-       int i;
+       int i, ret, val;
+       bool active_mode;
        static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
        struct device *dev = regmap_get_device(data->regmap);
 
        if (t == FXOS8700_MAGN) {
-               dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
+               dev_err(dev, "Magnetometer scale is locked at 0.001Gs\n");
                return -EINVAL;
        }
 
+       /*
+        * When device is in active mode, it failed to set an ACCEL
+        * full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.
+        * This is not align with the datasheet, but it is a fxos8700
+        * chip behavier. Set the device in standby mode before setting
+        * an ACCEL full-scale range.
+        */
+       ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
+       if (ret)
+               return ret;
+
+       active_mode = val & FXOS8700_ACTIVE;
+       if (active_mode) {
+               ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
+                                  val & ~FXOS8700_ACTIVE);
+               if (ret)
+                       return ret;
+       }
+
        for (i = 0; i < scale_num; i++)
                if (fxos8700_accel_scale[i].uscale == uscale)
                        break;
@@ -361,8 +381,12 @@ static int fxos8700_set_scale(struct fxos8700_data *data,
        if (i == scale_num)
                return -EINVAL;
 
-       return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
+       ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
                            fxos8700_accel_scale[i].bits);
+       if (ret)
+               return ret;
+       return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
+                                 active_mode);
 }
 
 static int fxos8700_get_scale(struct fxos8700_data *data,
@@ -372,7 +396,7 @@ static int fxos8700_get_scale(struct fxos8700_data *data,
        static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
 
        if (t == FXOS8700_MAGN) {
-               *uscale = 1200; /* Magnetometer is locked at 1200uT */
+               *uscale = 1000; /* Magnetometer is locked at 0.001Gs */
                return 0;
        }
 
@@ -394,22 +418,61 @@ static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
                             int axis, int *val)
 {
        u8 base, reg;
+       s16 tmp;
        int ret;
-       enum fxos8700_sensor type = fxos8700_to_sensor(chan_type);
 
-       base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB;
+       /*
+        * Different register base addresses varies with channel types.
+        * This bug hasn't been noticed before because using an enum is
+        * really hard to read. Use an a switch statement to take over that.
+        */
+       switch (chan_type) {
+       case IIO_ACCEL:
+               base = FXOS8700_OUT_X_MSB;
+               break;
+       case IIO_MAGN:
+               base = FXOS8700_M_OUT_X_MSB;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        /* Block read 6 bytes of device output registers to avoid data loss */
        ret = regmap_bulk_read(data->regmap, base, data->buf,
-                              FXOS8700_DATA_BUF_SIZE);
+                              sizeof(data->buf));
        if (ret)
                return ret;
 
        /* Convert axis to buffer index */
        reg = axis - IIO_MOD_X;
 
+       /*
+        * Convert to native endianness. The accel data and magn data
+        * are signed, so a forced type conversion is needed.
+        */
+       tmp = be16_to_cpu(data->buf[reg]);
+
+       /*
+        * ACCEL output data registers contain the X-axis, Y-axis, and Z-axis
+        * 14-bit left-justified sample data and MAGN output data registers
+        * contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply
+        * a signed 2 bits right shift to the readback raw data from ACCEL
+        * output data register and keep that from MAGN sensor as the origin.
+        * Value should be extended to 32 bit.
+        */
+       switch (chan_type) {
+       case IIO_ACCEL:
+               tmp = tmp >> 2;
+               break;
+       case IIO_MAGN:
+               /* Nothing to do */
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /* Convert to native endianness */
-       *val = sign_extend32(be16_to_cpu(data->buf[reg]), 15);
+       *val = sign_extend32(tmp, 15);
 
        return 0;
 }
@@ -445,10 +508,9 @@ static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
        if (i >= odr_num)
                return -EINVAL;
 
-       return regmap_update_bits(data->regmap,
-                                 FXOS8700_CTRL_REG1,
-                                 FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE,
-                                 fxos8700_odr[i].bits << 3 | active_mode);
+       val &= ~FXOS8700_CTRL_ODR_MSK;
+       val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE;
+       return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val);
 }
 
 static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
@@ -461,7 +523,7 @@ static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
        if (ret)
                return ret;
 
-       val &= FXOS8700_CTRL_ODR_MSK;
+       val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val);
 
        for (i = 0; i < odr_num; i++)
                if (val == fxos8700_odr[i].bits)
@@ -526,7 +588,7 @@ static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
 static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
                      "1.5625 6.25 12.5 50 100 200 400 800");
 static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
-static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
+static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");
 
 static struct attribute *fxos8700_attrs[] = {
        &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
@@ -592,14 +654,19 @@ static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
        if (ret)
                return ret;
 
-       /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
-       ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
-                          FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
+       /*
+        * Set max full-scale range (+/-8G) for ACCEL sensor in chip
+        * initialization then activate the device.
+        */
+       ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
        if (ret)
                return ret;
 
-       /* Set for max full-scale range (+/-8G) */
-       return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
+       /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
+       return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1,
+                               FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE,
+                               FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) |
+                               FXOS8700_ACTIVE);
 }
 
 static void fxos8700_chip_uninit(void *data)
index f6660847fb58d4c3c886d9911e6925f4193541bf..8c16cdacf2f212bba2a6d0c07a707299779c2c14 100644 (file)
@@ -4,6 +4,7 @@ config IIO_ST_LSM6DSX
        tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors"
        depends on (I2C || SPI || I3C)
        select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        select IIO_KFIFO_BUF
        select IIO_ST_LSM6DSX_I2C if (I2C)
        select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
index 001055d097509e688f7ce330ff2b3e7a24810269..b1674a5bfa368d048b9c3629148e7daec8f0a3f0 100644 (file)
@@ -440,6 +440,8 @@ static int cm32181_probe(struct i2c_client *client)
        if (!indio_dev)
                return -ENOMEM;
 
+       i2c_set_clientdata(client, indio_dev);
+
        /*
         * Some ACPI systems list 2 I2C resources for the CM3218 sensor, the
         * SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address.
@@ -460,8 +462,6 @@ static int cm32181_probe(struct i2c_client *client)
                        return PTR_ERR(client);
        }
 
-       i2c_set_clientdata(client, indio_dev);
-
        cm32181 = iio_priv(indio_dev);
        cm32181->client = client;
        cm32181->dev = dev;
@@ -490,7 +490,8 @@ static int cm32181_probe(struct i2c_client *client)
 
 static int cm32181_suspend(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
+       struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev));
+       struct i2c_client *client = cm32181->client;
 
        return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD,
                                         CM32181_CMD_ALS_DISABLE);
@@ -498,8 +499,8 @@ static int cm32181_suspend(struct device *dev)
 
 static int cm32181_resume(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
        struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev));
+       struct i2c_client *client = cm32181->client;
 
        return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD,
                                         cm32181->conf_regs[CM32181_REG_ADDR_CMD]);
index 26b021f43ba40fbe930c95cdbd3fab30e5765eb8..11b1c1603aeb44e6d0dcbc3904a57a5bf314d03e 100644 (file)
@@ -2957,15 +2957,18 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
 bool __rdma_block_iter_next(struct ib_block_iter *biter)
 {
        unsigned int block_offset;
+       unsigned int sg_delta;
 
        if (!biter->__sg_nents || !biter->__sg)
                return false;
 
        biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
        block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
-       biter->__sg_advance += BIT_ULL(biter->__pg_bit) - block_offset;
+       sg_delta = BIT_ULL(biter->__pg_bit) - block_offset;
 
-       if (biter->__sg_advance >= sg_dma_len(biter->__sg)) {
+       if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) {
+               biter->__sg_advance += sg_delta;
+       } else {
                biter->__sg_advance = 0;
                biter->__sg = sg_next(biter->__sg);
                biter->__sg_nents--;
index 186d3029126069b9f3184dc055831d5937e80429..b02f2f0809c81312a4722ddbe7a8f43722633884 100644 (file)
@@ -23,18 +23,25 @@ static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
 static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
                              const struct mmu_notifier_range *range,
                              unsigned long cur_seq);
+static bool tid_cover_invalidate(struct mmu_interval_notifier *mni,
+                                const struct mmu_notifier_range *range,
+                                unsigned long cur_seq);
 static int program_rcvarray(struct hfi1_filedata *fd, struct tid_user_buf *,
                            struct tid_group *grp,
                            unsigned int start, u16 count,
                            u32 *tidlist, unsigned int *tididx,
                            unsigned int *pmapped);
-static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
-                             struct tid_group **grp);
+static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo);
+static void __clear_tid_node(struct hfi1_filedata *fd,
+                            struct tid_rb_node *node);
 static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node);
 
 static const struct mmu_interval_notifier_ops tid_mn_ops = {
        .invalidate = tid_rb_invalidate,
 };
+static const struct mmu_interval_notifier_ops tid_cover_ops = {
+       .invalidate = tid_cover_invalidate,
+};
 
 /*
  * Initialize context and file private data needed for Expected
@@ -253,53 +260,65 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
                tididx = 0, mapped, mapped_pages = 0;
        u32 *tidlist = NULL;
        struct tid_user_buf *tidbuf;
+       unsigned long mmu_seq = 0;
 
        if (!PAGE_ALIGNED(tinfo->vaddr))
                return -EINVAL;
+       if (tinfo->length == 0)
+               return -EINVAL;
 
        tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL);
        if (!tidbuf)
                return -ENOMEM;
 
+       mutex_init(&tidbuf->cover_mutex);
        tidbuf->vaddr = tinfo->vaddr;
        tidbuf->length = tinfo->length;
        tidbuf->psets = kcalloc(uctxt->expected_count, sizeof(*tidbuf->psets),
                                GFP_KERNEL);
        if (!tidbuf->psets) {
-               kfree(tidbuf);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail_release_mem;
+       }
+
+       if (fd->use_mn) {
+               ret = mmu_interval_notifier_insert(
+                       &tidbuf->notifier, current->mm,
+                       tidbuf->vaddr, tidbuf->npages * PAGE_SIZE,
+                       &tid_cover_ops);
+               if (ret)
+                       goto fail_release_mem;
+               mmu_seq = mmu_interval_read_begin(&tidbuf->notifier);
        }
 
        pinned = pin_rcv_pages(fd, tidbuf);
        if (pinned <= 0) {
-               kfree(tidbuf->psets);
-               kfree(tidbuf);
-               return pinned;
+               ret = (pinned < 0) ? pinned : -ENOSPC;
+               goto fail_unpin;
        }
 
        /* Find sets of physically contiguous pages */
        tidbuf->n_psets = find_phys_blocks(tidbuf, pinned);
 
-       /*
-        * We don't need to access this under a lock since tid_used is per
-        * process and the same process cannot be in hfi1_user_exp_rcv_clear()
-        * and hfi1_user_exp_rcv_setup() at the same time.
-        */
+       /* Reserve the number of expected tids to be used. */
        spin_lock(&fd->tid_lock);
        if (fd->tid_used + tidbuf->n_psets > fd->tid_limit)
                pageset_count = fd->tid_limit - fd->tid_used;
        else
                pageset_count = tidbuf->n_psets;
+       fd->tid_used += pageset_count;
        spin_unlock(&fd->tid_lock);
 
-       if (!pageset_count)
-               goto bail;
+       if (!pageset_count) {
+               ret = -ENOSPC;
+               goto fail_unreserve;
+       }
 
        ngroups = pageset_count / dd->rcv_entries.group_size;
        tidlist = kcalloc(pageset_count, sizeof(*tidlist), GFP_KERNEL);
        if (!tidlist) {
                ret = -ENOMEM;
-               goto nomem;
+               goto fail_unreserve;
        }
 
        tididx = 0;
@@ -395,43 +414,78 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
        }
 unlock:
        mutex_unlock(&uctxt->exp_mutex);
-nomem:
        hfi1_cdbg(TID, "total mapped: tidpairs:%u pages:%u (%d)", tididx,
                  mapped_pages, ret);
-       if (tididx) {
-               spin_lock(&fd->tid_lock);
-               fd->tid_used += tididx;
-               spin_unlock(&fd->tid_lock);
-               tinfo->tidcnt = tididx;
-               tinfo->length = mapped_pages * PAGE_SIZE;
-
-               if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
-                                tidlist, sizeof(tidlist[0]) * tididx)) {
-                       /*
-                        * On failure to copy to the user level, we need to undo
-                        * everything done so far so we don't leak resources.
-                        */
-                       tinfo->tidlist = (unsigned long)&tidlist;
-                       hfi1_user_exp_rcv_clear(fd, tinfo);
-                       tinfo->tidlist = 0;
-                       ret = -EFAULT;
-                       goto bail;
+
+       /* fail if nothing was programmed, set error if none provided */
+       if (tididx == 0) {
+               if (ret >= 0)
+                       ret = -ENOSPC;
+               goto fail_unreserve;
+       }
+
+       /* adjust reserved tid_used to actual count */
+       spin_lock(&fd->tid_lock);
+       fd->tid_used -= pageset_count - tididx;
+       spin_unlock(&fd->tid_lock);
+
+       /* unpin all pages not covered by a TID */
+       unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages, pinned - mapped_pages,
+                       false);
+
+       if (fd->use_mn) {
+               /* check for an invalidate during setup */
+               bool fail = false;
+
+               mutex_lock(&tidbuf->cover_mutex);
+               fail = mmu_interval_read_retry(&tidbuf->notifier, mmu_seq);
+               mutex_unlock(&tidbuf->cover_mutex);
+
+               if (fail) {
+                       ret = -EBUSY;
+                       goto fail_unprogram;
                }
        }
 
-       /*
-        * If not everything was mapped (due to insufficient RcvArray entries,
-        * for example), unpin all unmapped pages so we can pin them nex time.
-        */
-       if (mapped_pages != pinned)
-               unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages,
-                               (pinned - mapped_pages), false);
-bail:
+       tinfo->tidcnt = tididx;
+       tinfo->length = mapped_pages * PAGE_SIZE;
+
+       if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
+                        tidlist, sizeof(tidlist[0]) * tididx)) {
+               ret = -EFAULT;
+               goto fail_unprogram;
+       }
+
+       if (fd->use_mn)
+               mmu_interval_notifier_remove(&tidbuf->notifier);
+       kfree(tidbuf->pages);
        kfree(tidbuf->psets);
+       kfree(tidbuf);
        kfree(tidlist);
+       return 0;
+
+fail_unprogram:
+       /* unprogram, unmap, and unpin all allocated TIDs */
+       tinfo->tidlist = (unsigned long)tidlist;
+       hfi1_user_exp_rcv_clear(fd, tinfo);
+       tinfo->tidlist = 0;
+       pinned = 0;             /* nothing left to unpin */
+       pageset_count = 0;      /* nothing left reserved */
+fail_unreserve:
+       spin_lock(&fd->tid_lock);
+       fd->tid_used -= pageset_count;
+       spin_unlock(&fd->tid_lock);
+fail_unpin:
+       if (fd->use_mn)
+               mmu_interval_notifier_remove(&tidbuf->notifier);
+       if (pinned > 0)
+               unpin_rcv_pages(fd, tidbuf, NULL, 0, pinned, false);
+fail_release_mem:
        kfree(tidbuf->pages);
+       kfree(tidbuf->psets);
        kfree(tidbuf);
-       return ret > 0 ? 0 : ret;
+       kfree(tidlist);
+       return ret;
 }
 
 int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
@@ -452,7 +506,7 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
 
        mutex_lock(&uctxt->exp_mutex);
        for (tididx = 0; tididx < tinfo->tidcnt; tididx++) {
-               ret = unprogram_rcvarray(fd, tidinfo[tididx], NULL);
+               ret = unprogram_rcvarray(fd, tidinfo[tididx]);
                if (ret) {
                        hfi1_cdbg(TID, "Failed to unprogram rcv array %d",
                                  ret);
@@ -706,6 +760,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
        }
 
        node->fdata = fd;
+       mutex_init(&node->invalidate_mutex);
        node->phys = page_to_phys(pages[0]);
        node->npages = npages;
        node->rcventry = rcventry;
@@ -721,11 +776,6 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
                        &tid_mn_ops);
                if (ret)
                        goto out_unmap;
-               /*
-                * FIXME: This is in the wrong order, the notifier should be
-                * established before the pages are pinned by pin_rcv_pages.
-                */
-               mmu_interval_read_begin(&node->notifier);
        }
        fd->entry_to_rb[node->rcventry - uctxt->expected_base] = node;
 
@@ -745,8 +795,7 @@ out_unmap:
        return -EFAULT;
 }
 
-static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
-                             struct tid_group **grp)
+static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo)
 {
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
@@ -769,9 +818,6 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
        if (!node || node->rcventry != (uctxt->expected_base + rcventry))
                return -EBADF;
 
-       if (grp)
-               *grp = node->grp;
-
        if (fd->use_mn)
                mmu_interval_notifier_remove(&node->notifier);
        cacheless_tid_rb_remove(fd, node);
@@ -779,23 +825,34 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
        return 0;
 }
 
-static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
+static void __clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
 {
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
 
+       mutex_lock(&node->invalidate_mutex);
+       if (node->freed)
+               goto done;
+       node->freed = true;
+
        trace_hfi1_exp_tid_unreg(uctxt->ctxt, fd->subctxt, node->rcventry,
                                 node->npages,
                                 node->notifier.interval_tree.start, node->phys,
                                 node->dma_addr);
 
-       /*
-        * Make sure device has seen the write before we unpin the
-        * pages.
-        */
+       /* Make sure device has seen the write before pages are unpinned */
        hfi1_put_tid(dd, node->rcventry, PT_INVALID_FLUSH, 0, 0);
 
        unpin_rcv_pages(fd, NULL, node, 0, node->npages, true);
+done:
+       mutex_unlock(&node->invalidate_mutex);
+}
+
+static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
+{
+       struct hfi1_ctxtdata *uctxt = fd->uctxt;
+
+       __clear_tid_node(fd, node);
 
        node->grp->used--;
        node->grp->map &= ~(1 << (node->rcventry - node->grp->base));
@@ -854,10 +911,16 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
        if (node->freed)
                return true;
 
+       /* take action only if unmapping */
+       if (range->event != MMU_NOTIFY_UNMAP)
+               return true;
+
        trace_hfi1_exp_tid_inval(uctxt->ctxt, fdata->subctxt,
                                 node->notifier.interval_tree.start,
                                 node->rcventry, node->npages, node->dma_addr);
-       node->freed = true;
+
+       /* clear the hardware rcvarray entry */
+       __clear_tid_node(fdata, node);
 
        spin_lock(&fdata->invalid_lock);
        if (fdata->invalid_tid_idx < uctxt->expected_count) {
@@ -887,6 +950,23 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
        return true;
 }
 
+static bool tid_cover_invalidate(struct mmu_interval_notifier *mni,
+                                const struct mmu_notifier_range *range,
+                                unsigned long cur_seq)
+{
+       struct tid_user_buf *tidbuf =
+               container_of(mni, struct tid_user_buf, notifier);
+
+       /* take action only if unmapping */
+       if (range->event == MMU_NOTIFY_UNMAP) {
+               mutex_lock(&tidbuf->cover_mutex);
+               mmu_interval_set_seq(mni, cur_seq);
+               mutex_unlock(&tidbuf->cover_mutex);
+       }
+
+       return true;
+}
+
 static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
                                    struct tid_rb_node *tnode)
 {
index 8c53e416bf843cb662d5abab6e1ea03d11f5fc39..f8ee997d0050ee91bbeaa9384f0a0c6aebd3f9ed 100644 (file)
@@ -16,6 +16,8 @@ struct tid_pageset {
 };
 
 struct tid_user_buf {
+       struct mmu_interval_notifier notifier;
+       struct mutex cover_mutex;
        unsigned long vaddr;
        unsigned long length;
        unsigned int npages;
@@ -27,6 +29,7 @@ struct tid_user_buf {
 struct tid_rb_node {
        struct mmu_interval_notifier notifier;
        struct hfi1_filedata *fdata;
+       struct mutex invalidate_mutex; /* covers hw removal */
        unsigned long phys;
        struct tid_group *grp;
        u32 rcventry;
index a754fc902e3d190c1fbdf7ab3ecdeb59fef266de..7b41d79e72b2dffc7709838046fbc43081d46592 100644 (file)
@@ -98,11 +98,11 @@ enum rxe_device_param {
        RXE_MAX_SRQ                     = DEFAULT_MAX_VALUE - RXE_MIN_SRQ_INDEX,
 
        RXE_MIN_MR_INDEX                = 0x00000001,
-       RXE_MAX_MR_INDEX                = DEFAULT_MAX_VALUE,
-       RXE_MAX_MR                      = DEFAULT_MAX_VALUE - RXE_MIN_MR_INDEX,
-       RXE_MIN_MW_INDEX                = 0x00010001,
-       RXE_MAX_MW_INDEX                = 0x00020000,
-       RXE_MAX_MW                      = 0x00001000,
+       RXE_MAX_MR_INDEX                = DEFAULT_MAX_VALUE >> 1,
+       RXE_MAX_MR                      = RXE_MAX_MR_INDEX - RXE_MIN_MR_INDEX,
+       RXE_MIN_MW_INDEX                = RXE_MAX_MR_INDEX + 1,
+       RXE_MAX_MW_INDEX                = DEFAULT_MAX_VALUE,
+       RXE_MAX_MW                      = RXE_MAX_MW_INDEX - RXE_MIN_MW_INDEX,
 
        RXE_MAX_PKT_PER_ACK             = 64,
 
index f50620f5a0a14103d6ccf67316cd6b89ad03642d..1151c0b5cceaba60311d4ce91da85c69c7701eee 100644 (file)
@@ -23,16 +23,16 @@ static const struct rxe_type_info {
                .size           = sizeof(struct rxe_ucontext),
                .elem_offset    = offsetof(struct rxe_ucontext, elem),
                .min_index      = 1,
-               .max_index      = UINT_MAX,
-               .max_elem       = UINT_MAX,
+               .max_index      = RXE_MAX_UCONTEXT,
+               .max_elem       = RXE_MAX_UCONTEXT,
        },
        [RXE_TYPE_PD] = {
                .name           = "pd",
                .size           = sizeof(struct rxe_pd),
                .elem_offset    = offsetof(struct rxe_pd, elem),
                .min_index      = 1,
-               .max_index      = UINT_MAX,
-               .max_elem       = UINT_MAX,
+               .max_index      = RXE_MAX_PD,
+               .max_elem       = RXE_MAX_PD,
        },
        [RXE_TYPE_AH] = {
                .name           = "ah",
@@ -40,7 +40,7 @@ static const struct rxe_type_info {
                .elem_offset    = offsetof(struct rxe_ah, elem),
                .min_index      = RXE_MIN_AH_INDEX,
                .max_index      = RXE_MAX_AH_INDEX,
-               .max_elem       = RXE_MAX_AH_INDEX - RXE_MIN_AH_INDEX + 1,
+               .max_elem       = RXE_MAX_AH,
        },
        [RXE_TYPE_SRQ] = {
                .name           = "srq",
@@ -49,7 +49,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_srq_cleanup,
                .min_index      = RXE_MIN_SRQ_INDEX,
                .max_index      = RXE_MAX_SRQ_INDEX,
-               .max_elem       = RXE_MAX_SRQ_INDEX - RXE_MIN_SRQ_INDEX + 1,
+               .max_elem       = RXE_MAX_SRQ,
        },
        [RXE_TYPE_QP] = {
                .name           = "qp",
@@ -58,7 +58,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_qp_cleanup,
                .min_index      = RXE_MIN_QP_INDEX,
                .max_index      = RXE_MAX_QP_INDEX,
-               .max_elem       = RXE_MAX_QP_INDEX - RXE_MIN_QP_INDEX + 1,
+               .max_elem       = RXE_MAX_QP,
        },
        [RXE_TYPE_CQ] = {
                .name           = "cq",
@@ -66,8 +66,8 @@ static const struct rxe_type_info {
                .elem_offset    = offsetof(struct rxe_cq, elem),
                .cleanup        = rxe_cq_cleanup,
                .min_index      = 1,
-               .max_index      = UINT_MAX,
-               .max_elem       = UINT_MAX,
+               .max_index      = RXE_MAX_CQ,
+               .max_elem       = RXE_MAX_CQ,
        },
        [RXE_TYPE_MR] = {
                .name           = "mr",
@@ -76,7 +76,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_mr_cleanup,
                .min_index      = RXE_MIN_MR_INDEX,
                .max_index      = RXE_MAX_MR_INDEX,
-               .max_elem       = RXE_MAX_MR_INDEX - RXE_MIN_MR_INDEX + 1,
+               .max_elem       = RXE_MAX_MR,
        },
        [RXE_TYPE_MW] = {
                .name           = "mw",
@@ -85,7 +85,7 @@ static const struct rxe_type_info {
                .cleanup        = rxe_mw_cleanup,
                .min_index      = RXE_MIN_MW_INDEX,
                .max_index      = RXE_MAX_MW_INDEX,
-               .max_elem       = RXE_MAX_MW_INDEX - RXE_MIN_MW_INDEX + 1,
+               .max_elem       = RXE_MAX_MW,
        },
 };
 
index b0f776448a1cdd758ee6286c91e6fe8865ba6310..fa021af8506e4f8c3309026ca474a1c1d20a7824 100644 (file)
@@ -192,7 +192,6 @@ static const char * const smbus_pnp_ids[] = {
        "SYN3221", /* HP 15-ay000 */
        "SYN323d", /* HP Spectre X360 13-w013dx */
        "SYN3257", /* HP Envy 13-ad105ng */
-       "SYN3286", /* HP Laptop 15-da3001TU */
        NULL
 };
 
index 46f8a694291edd13578b850317fdab2872f36cb6..efc61736099b9a606951b8274a6deebbd8488fa0 100644 (file)
@@ -1238,6 +1238,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, "PCX0DX"),
+               },
+               .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+                                       SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "X170SM"),
index ba6781f54ab73a6d37de76272a694161710e1ac2..df3196f7253687248bbd00fe2099e6d531171f38 100644 (file)
@@ -488,7 +488,7 @@ int qnoc_probe(struct platform_device *pdev)
        }
 
 regmap_done:
-       ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
+       ret = devm_clk_bulk_get_optional(dev, qp->num_clks, qp->bus_clks);
        if (ret)
                return ret;
 
index c2903ae3b3bc3708fd325c12a5fd54e158186613..25a1a32bc611facde621e72729c798e4623040b1 100644 (file)
@@ -33,6 +33,13 @@ static const char * const bus_a0noc_clocks[] = {
        "aggre0_noc_mpu_cfg"
 };
 
+static const char * const bus_a2noc_clocks[] = {
+       "bus",
+       "bus_a",
+       "aggre2_ufs_axi",
+       "ufs_axi"
+};
+
 static const u16 mas_a0noc_common_links[] = {
        MSM8996_SLAVE_A0NOC_SNOC
 };
@@ -1806,7 +1813,7 @@ static const struct regmap_config msm8996_a0noc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x9000,
+       .max_register   = 0x6000,
        .fast_io        = true
 };
 
@@ -1830,7 +1837,7 @@ static const struct regmap_config msm8996_a1noc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x7000,
+       .max_register   = 0x5000,
        .fast_io        = true
 };
 
@@ -1851,7 +1858,7 @@ static const struct regmap_config msm8996_a2noc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0xa000,
+       .max_register   = 0x7000,
        .fast_io        = true
 };
 
@@ -1859,6 +1866,8 @@ static const struct qcom_icc_desc msm8996_a2noc = {
        .type = QCOM_ICC_NOC,
        .nodes = a2noc_nodes,
        .num_nodes = ARRAY_SIZE(a2noc_nodes),
+       .clocks = bus_a2noc_clocks,
+       .num_clocks = ARRAY_SIZE(bus_a2noc_clocks),
        .regmap_cfg = &msm8996_a2noc_regmap_config
 };
 
@@ -1877,7 +1886,7 @@ static const struct regmap_config msm8996_bimc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x62000,
+       .max_register   = 0x5a000,
        .fast_io        = true
 };
 
@@ -1988,7 +1997,7 @@ static const struct regmap_config msm8996_mnoc_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0x20000,
+       .max_register   = 0x1c000,
        .fast_io        = true
 };
 
index 97413586195b4c32b0840428640b4f94e2bb067b..f96034e0ba4f20bef11ca28bd06b621d39b2e67a 100644 (file)
@@ -106,7 +106,8 @@ static inline unsigned long bkey_bytes(const struct bkey *k)
        return bkey_u64s(k) * sizeof(__u64);
 }
 
-#define bkey_copy(_dest, _src) memcpy(_dest, _src, bkey_bytes(_src))
+#define bkey_copy(_dest, _src) unsafe_memcpy(_dest, _src, bkey_bytes(_src), \
+                                       /* bkey is always padded */)
 
 static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src)
 {
index e5da469a42357cad3fb8057d318c607737e84bb3..c182c21de2e8199d1d57817e27e149e0d772d2b7 100644 (file)
@@ -149,7 +149,8 @@ add:
                                    bytes, GFP_KERNEL);
                        if (!i)
                                return -ENOMEM;
-                       memcpy(&i->j, j, bytes);
+                       unsafe_memcpy(&i->j, j, bytes,
+                               /* "bytes" was calculated by set_bytes() above */);
                        /* Add to the location after 'where' points to */
                        list_add(&i->list, where);
                        ret = 1;
index 8af639296b3c852b36047dc299a54c71ec99481b..02b0240e7c715a0a4a7dde9af66835fd55df16dc 100644 (file)
@@ -3644,7 +3644,7 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
  */
 static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
-       static struct md_rdev *claim_rdev; /* just for claiming the bdev */
+       static struct md_rdev claim_rdev; /* just for claiming the bdev */
        struct md_rdev *rdev;
        sector_t size;
        int err;
@@ -3662,7 +3662,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
 
        rdev->bdev = blkdev_get_by_dev(newdev,
                        FMODE_READ | FMODE_WRITE | FMODE_EXCL,
-                       super_format == -2 ? claim_rdev : rdev);
+                       super_format == -2 ? &claim_rdev : rdev);
        if (IS_ERR(rdev->bdev)) {
                pr_warn("md: could not open device unknown-block(%u,%u).\n",
                        MAJOR(newdev), MINOR(newdev));
index fc3758a5bc1c2c274efa86f5557d082f946074e5..53e495223ea017135543ddd3b82b46ff6319c1b2 100644 (file)
@@ -2149,8 +2149,6 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
        if (ret)
                return ret;
 
-       q->streaming = 1;
-
        /*
         * Tell driver to start streaming provided sufficient buffers
         * are available.
@@ -2161,12 +2159,13 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
                        goto unprepare;
        }
 
+       q->streaming = 1;
+
        dprintk(q, 3, "successful\n");
        return 0;
 
 unprepare:
        call_void_qop(q, unprepare_streaming, q);
-       q->streaming = 0;
        return ret;
 }
 EXPORT_SYMBOL_GPL(vb2_core_streamon);
index 3d3b6dc24ca6374d64a0e9e39482f10a46ad41f0..002ea6588edf163d116ccfff8be7cf18cfe733da 100644 (file)
@@ -150,8 +150,8 @@ static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
                         * then return an error.
                         */
                        if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last)
-                       ctrl->is_new = 1;
                                return -ERANGE;
+                       ctrl->is_new = 1;
                }
                return ret;
        default:
index 9c49d00c2a966b2859e30d8699f6c1cfcd3f9caa..ea6e9e1eaf04687cd6a9cec822a72467782cbe4e 100644 (file)
@@ -47,19 +47,17 @@ static int atmel_ramc_probe(struct platform_device *pdev)
        caps = of_device_get_match_data(&pdev->dev);
 
        if (caps->has_ddrck) {
-               clk = devm_clk_get(&pdev->dev, "ddrck");
+               clk = devm_clk_get_enabled(&pdev->dev, "ddrck");
                if (IS_ERR(clk))
                        return PTR_ERR(clk);
-               clk_prepare_enable(clk);
        }
 
        if (caps->has_mpddr_clk) {
-               clk = devm_clk_get(&pdev->dev, "mpddr");
+               clk = devm_clk_get_enabled(&pdev->dev, "mpddr");
                if (IS_ERR(clk)) {
                        pr_err("AT91 RAMC: couldn't get mpddr clock\n");
                        return PTR_ERR(clk);
                }
-               clk_prepare_enable(clk);
        }
 
        return 0;
index 8450638e86700763d52bb85ec8131c27019bb33c..efc6c08db2b70a78ae2d6eb902305153fb8cf36e 100644 (file)
@@ -280,10 +280,9 @@ static int mvebu_devbus_probe(struct platform_device *pdev)
        if (IS_ERR(devbus->base))
                return PTR_ERR(devbus->base);
 
-       clk = devm_clk_get(&pdev->dev, NULL);
+       clk = devm_clk_get_enabled(&pdev->dev, NULL);
        if (IS_ERR(clk))
                return PTR_ERR(clk);
-       clk_prepare_enable(clk);
 
        /*
         * Obtain clock period in picoseconds,
index 57d9f91fe89bf9100a40f69f6df88d14e721e625..d78f73db37c88c887fddb062bd14562d9aad660d 100644 (file)
@@ -1918,7 +1918,8 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
                }
        }
 
-       if (p->wait_pin > gpmc_nr_waitpins) {
+       if (p->wait_pin != GPMC_WAITPIN_INVALID &&
+           p->wait_pin > gpmc_nr_waitpins) {
                pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
                return -EINVAL;
        }
index 62477e592bf5f354cd6299f1b3e590a53811cb04..7bb73f06fad3edb3269744d5c3baa7744359233a 100644 (file)
 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
 
-static void tegra186_mc_program_sid(struct tegra_mc *mc)
-{
-       unsigned int i;
-
-       for (i = 0; i < mc->soc->num_clients; i++) {
-               const struct tegra_mc_client *client = &mc->soc->clients[i];
-               u32 override, security;
-
-               override = readl(mc->regs + client->regs.sid.override);
-               security = readl(mc->regs + client->regs.sid.security);
-
-               dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
-                       client->name, override, security);
-
-               dev_dbg(mc->dev, "setting SID %u for %s\n", client->sid,
-                       client->name);
-               writel(client->sid, mc->regs + client->regs.sid.override);
-
-               override = readl(mc->regs + client->regs.sid.override);
-               security = readl(mc->regs + client->regs.sid.security);
-
-               dev_dbg(mc->dev, "client %s: override: %x security: %x\n",
-                       client->name, override, security);
-       }
-}
-
 static int tegra186_mc_probe(struct tegra_mc *mc)
 {
        struct platform_device *pdev = to_platform_device(mc->dev);
@@ -85,8 +59,6 @@ populate:
        if (err < 0)
                return err;
 
-       tegra186_mc_program_sid(mc);
-
        return 0;
 }
 
@@ -95,13 +67,6 @@ static void tegra186_mc_remove(struct tegra_mc *mc)
        of_platform_depopulate(mc->dev);
 }
 
-static int tegra186_mc_resume(struct tegra_mc *mc)
-{
-       tegra186_mc_program_sid(mc);
-
-       return 0;
-}
-
 #if IS_ENABLED(CONFIG_IOMMU_API)
 static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
                                            const struct tegra_mc_client *client,
@@ -173,7 +138,6 @@ static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
 const struct tegra_mc_ops tegra186_mc_ops = {
        .probe = tegra186_mc_probe,
        .remove = tegra186_mc_remove,
-       .resume = tegra186_mc_resume,
        .probe_device = tegra186_mc_probe_device,
        .handle_irq = tegra30_mc_handle_irq,
 };
index c9902a1dcf5d311043182ee87f4dbc5ec6085cae..5310606113fe5c56d5b41ac7b065802bdee07f22 100644 (file)
@@ -321,7 +321,7 @@ static void fastrpc_free_map(struct kref *ref)
                        perm.vmid = QCOM_SCM_VMID_HLOS;
                        perm.perm = QCOM_SCM_PERM_RWX;
                        err = qcom_scm_assign_mem(map->phys, map->size,
-                               &(map->fl->cctx->vmperms[0].vmid), &perm, 1);
+                               &map->fl->cctx->perms, &perm, 1);
                        if (err) {
                                dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                                map->phys, map->size, err);
@@ -334,6 +334,13 @@ static void fastrpc_free_map(struct kref *ref)
                dma_buf_put(map->buf);
        }
 
+       if (map->fl) {
+               spin_lock(&map->fl->lock);
+               list_del(&map->node);
+               spin_unlock(&map->fl->lock);
+               map->fl = NULL;
+       }
+
        kfree(map);
 }
 
@@ -343,38 +350,41 @@ static void fastrpc_map_put(struct fastrpc_map *map)
                kref_put(&map->refcount, fastrpc_free_map);
 }
 
-static void fastrpc_map_get(struct fastrpc_map *map)
+static int fastrpc_map_get(struct fastrpc_map *map)
 {
-       if (map)
-               kref_get(&map->refcount);
+       if (!map)
+               return -ENOENT;
+
+       return kref_get_unless_zero(&map->refcount) ? 0 : -ENOENT;
 }
 
 
 static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
-                           struct fastrpc_map **ppmap)
+                           struct fastrpc_map **ppmap, bool take_ref)
 {
+       struct fastrpc_session_ctx *sess = fl->sctx;
        struct fastrpc_map *map = NULL;
+       int ret = -ENOENT;
 
-       mutex_lock(&fl->mutex);
+       spin_lock(&fl->lock);
        list_for_each_entry(map, &fl->maps, node) {
-               if (map->fd == fd) {
-                       *ppmap = map;
-                       mutex_unlock(&fl->mutex);
-                       return 0;
-               }
-       }
-       mutex_unlock(&fl->mutex);
-
-       return -ENOENT;
-}
+               if (map->fd != fd)
+                       continue;
 
-static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
-                           struct fastrpc_map **ppmap)
-{
-       int ret = fastrpc_map_lookup(fl, fd, ppmap);
+               if (take_ref) {
+                       ret = fastrpc_map_get(map);
+                       if (ret) {
+                               dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n",
+                                       __func__, fd, ret);
+                               break;
+                       }
+               }
 
-       if (!ret)
-               fastrpc_map_get(*ppmap);
+               *ppmap = map;
+               ret = 0;
+               break;
+       }
+       spin_unlock(&fl->lock);
 
        return ret;
 }
@@ -746,7 +756,7 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
        struct fastrpc_map *map = NULL;
        int err = 0;
 
-       if (!fastrpc_map_find(fl, fd, ppmap))
+       if (!fastrpc_map_lookup(fl, fd, ppmap, true))
                return 0;
 
        map = kzalloc(sizeof(*map), GFP_KERNEL);
@@ -788,10 +798,8 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
                 * If subsystem VMIDs are defined in DTSI, then do
                 * hyp_assign from HLOS to those VM(s)
                 */
-               unsigned int perms = BIT(QCOM_SCM_VMID_HLOS);
-
                map->attr = attr;
-               err = qcom_scm_assign_mem(map->phys, (u64)map->size, &perms,
+               err = qcom_scm_assign_mem(map->phys, (u64)map->size, &fl->cctx->perms,
                                fl->cctx->vmperms, fl->cctx->vmcount);
                if (err) {
                        dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
@@ -1070,7 +1078,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
        for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
                if (!fdlist[i])
                        break;
-               if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
+               if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
                        fastrpc_map_put(mmap);
        }
 
@@ -1258,10 +1266,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
 
                /* Map if we have any heap VMIDs associated with this ADSP Static Process. */
                if (fl->cctx->vmcount) {
-                       unsigned int perms = BIT(QCOM_SCM_VMID_HLOS);
-
                        err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
-                                                       (u64)fl->cctx->remote_heap->size, &perms,
+                                                       (u64)fl->cctx->remote_heap->size,
+                                                       &fl->cctx->perms,
                                                        fl->cctx->vmperms, fl->cctx->vmcount);
                        if (err) {
                                dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
@@ -1309,7 +1316,7 @@ err_invoke:
                perm.perm = QCOM_SCM_PERM_RWX;
                err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
                                                (u64)fl->cctx->remote_heap->size,
-                                               &(fl->cctx->vmperms[0].vmid), &perm, 1);
+                                               &fl->cctx->perms, &perm, 1);
                if (err)
                        dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
@@ -1433,12 +1440,7 @@ err_invoke:
        fl->init_mem = NULL;
        fastrpc_buf_free(imem);
 err_alloc:
-       if (map) {
-               spin_lock(&fl->lock);
-               list_del(&map->node);
-               spin_unlock(&fl->lock);
-               fastrpc_map_put(map);
-       }
+       fastrpc_map_put(map);
 err:
        kfree(args);
 
@@ -1514,10 +1516,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
                fastrpc_context_put(ctx);
        }
 
-       list_for_each_entry_safe(map, m, &fl->maps, node) {
-               list_del(&map->node);
+       list_for_each_entry_safe(map, m, &fl->maps, node)
                fastrpc_map_put(map);
-       }
 
        list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
                list_del(&buf->node);
@@ -1894,12 +1894,11 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
        /* Add memory to static PD pool, protection thru hypervisor */
        if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) {
                struct qcom_scm_vmperm perm;
-               int err = 0;
 
                perm.vmid = QCOM_SCM_VMID_HLOS;
                perm.perm = QCOM_SCM_PERM_RWX;
                err = qcom_scm_assign_mem(buf->phys, buf->size,
-                       &(fl->cctx->vmperms[0].vmid), &perm, 1);
+                       &fl->cctx->perms, &perm, 1);
                if (err) {
                        dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
                                        buf->phys, buf->size, err);
index 4a08b624910a0a4114ba43f8b2c0dfdf6c47da1d..a81b890c7ee648255c099264bfccb214b2a56b1e 100644 (file)
@@ -702,13 +702,15 @@ void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t size)
        if (cl->state == MEI_FILE_UNINITIALIZED) {
                ret = mei_cl_link(cl);
                if (ret)
-                       goto out;
+                       goto notlinked;
                /* update pointers */
                cl->cldev = cldev;
        }
 
        ret = mei_cl_dma_alloc_and_map(cl, NULL, buffer_id, size);
-out:
+       if (ret)
+               mei_cl_unlink(cl);
+notlinked:
        mutex_unlock(&bus->device_lock);
        if (ret)
                return ERR_PTR(ret);
@@ -758,7 +760,7 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
        if (cl->state == MEI_FILE_UNINITIALIZED) {
                ret = mei_cl_link(cl);
                if (ret)
-                       goto out;
+                       goto notlinked;
                /* update pointers */
                cl->cldev = cldev;
        }
@@ -785,6 +787,9 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
        }
 
 out:
+       if (ret)
+               mei_cl_unlink(cl);
+notlinked:
        mutex_unlock(&bus->device_lock);
 
        return ret;
@@ -1277,7 +1282,6 @@ static void mei_cl_bus_dev_release(struct device *dev)
        mei_cl_flush_queues(cldev->cl, NULL);
        mei_me_cl_put(cldev->me_cl);
        mei_dev_bus_put(cldev->bus);
-       mei_cl_unlink(cldev->cl);
        kfree(cldev->cl);
        kfree(cldev);
 }
index 99966cd3e7d892ca0f86666614bc7f664e978251..bdc65d50b945fc3c8f65f576880ce006f917559f 100644 (file)
 
 #define MEI_DEV_ID_RPL_S      0x7A68  /* Raptor Lake Point S */
 
+#define MEI_DEV_ID_MTL_M      0x7E70  /* Meteor Lake Point M */
+
 /*
  * MEI HW Section
  */
index 704cd0caa172caec9bbd459dbe15ae7db879364c..5bf0d50d55a00b47391f34ac52dee239fd8145bd 100644 (file)
@@ -118,6 +118,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)},
+
        /* required last entry */
        {0, }
 };
index aa7b05de97dd52d84fa04615912af9df46f7fb5f..4f8d962bb5b2a388c80d03d5edbd280efcc325c6 100644 (file)
@@ -56,8 +56,6 @@ struct vmci_guest_device {
 
        bool exclusive_vectors;
 
-       struct tasklet_struct datagram_tasklet;
-       struct tasklet_struct bm_tasklet;
        struct wait_queue_head inout_wq;
 
        void *data_buffer;
@@ -304,9 +302,8 @@ static int vmci_check_host_caps(struct pci_dev *pdev)
  * This function assumes that it has exclusive access to the data
  * in register(s) for the duration of the call.
  */
-static void vmci_dispatch_dgs(unsigned long data)
+static void vmci_dispatch_dgs(struct vmci_guest_device *vmci_dev)
 {
-       struct vmci_guest_device *vmci_dev = (struct vmci_guest_device *)data;
        u8 *dg_in_buffer = vmci_dev->data_buffer;
        struct vmci_datagram *dg;
        size_t dg_in_buffer_size = VMCI_MAX_DG_SIZE;
@@ -465,10 +462,8 @@ static void vmci_dispatch_dgs(unsigned long data)
  * Scans the notification bitmap for raised flags, clears them
  * and handles the notifications.
  */
-static void vmci_process_bitmap(unsigned long data)
+static void vmci_process_bitmap(struct vmci_guest_device *dev)
 {
-       struct vmci_guest_device *dev = (struct vmci_guest_device *)data;
-
        if (!dev->notification_bitmap) {
                dev_dbg(dev->dev, "No bitmap present in %s\n", __func__);
                return;
@@ -486,13 +481,13 @@ static irqreturn_t vmci_interrupt(int irq, void *_dev)
        struct vmci_guest_device *dev = _dev;
 
        /*
-        * If we are using MSI-X with exclusive vectors then we simply schedule
-        * the datagram tasklet, since we know the interrupt was meant for us.
+        * If we are using MSI-X with exclusive vectors then we simply call
+        * vmci_dispatch_dgs(), since we know the interrupt was meant for us.
         * Otherwise we must read the ICR to determine what to do.
         */
 
        if (dev->exclusive_vectors) {
-               tasklet_schedule(&dev->datagram_tasklet);
+               vmci_dispatch_dgs(dev);
        } else {
                unsigned int icr;
 
@@ -502,12 +497,12 @@ static irqreturn_t vmci_interrupt(int irq, void *_dev)
                        return IRQ_NONE;
 
                if (icr & VMCI_ICR_DATAGRAM) {
-                       tasklet_schedule(&dev->datagram_tasklet);
+                       vmci_dispatch_dgs(dev);
                        icr &= ~VMCI_ICR_DATAGRAM;
                }
 
                if (icr & VMCI_ICR_NOTIFICATION) {
-                       tasklet_schedule(&dev->bm_tasklet);
+                       vmci_process_bitmap(dev);
                        icr &= ~VMCI_ICR_NOTIFICATION;
                }
 
@@ -536,7 +531,7 @@ static irqreturn_t vmci_interrupt_bm(int irq, void *_dev)
        struct vmci_guest_device *dev = _dev;
 
        /* For MSI-X we can just assume it was meant for us. */
-       tasklet_schedule(&dev->bm_tasklet);
+       vmci_process_bitmap(dev);
 
        return IRQ_HANDLED;
 }
@@ -638,10 +633,6 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
        vmci_dev->iobase = iobase;
        vmci_dev->mmio_base = mmio_base;
 
-       tasklet_init(&vmci_dev->datagram_tasklet,
-                    vmci_dispatch_dgs, (unsigned long)vmci_dev);
-       tasklet_init(&vmci_dev->bm_tasklet,
-                    vmci_process_bitmap, (unsigned long)vmci_dev);
        init_waitqueue_head(&vmci_dev->inout_wq);
 
        if (mmio_base != NULL) {
@@ -808,8 +799,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
         * Request IRQ for legacy or MSI interrupts, or for first
         * MSI-X vector.
         */
-       error = request_irq(pci_irq_vector(pdev, 0), vmci_interrupt,
-                           IRQF_SHARED, KBUILD_MODNAME, vmci_dev);
+       error = request_threaded_irq(pci_irq_vector(pdev, 0), NULL,
+                                    vmci_interrupt, IRQF_SHARED,
+                                    KBUILD_MODNAME, vmci_dev);
        if (error) {
                dev_err(&pdev->dev, "Irq %u in use: %d\n",
                        pci_irq_vector(pdev, 0), error);
@@ -823,9 +815,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
         * between the vectors.
         */
        if (vmci_dev->exclusive_vectors) {
-               error = request_irq(pci_irq_vector(pdev, 1),
-                                   vmci_interrupt_bm, 0, KBUILD_MODNAME,
-                                   vmci_dev);
+               error = request_threaded_irq(pci_irq_vector(pdev, 1), NULL,
+                                            vmci_interrupt_bm, 0,
+                                            KBUILD_MODNAME, vmci_dev);
                if (error) {
                        dev_err(&pdev->dev,
                                "Failed to allocate irq %u: %d\n",
@@ -833,9 +825,11 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
                        goto err_free_irq;
                }
                if (caps_in_use & VMCI_CAPS_DMA_DATAGRAM) {
-                       error = request_irq(pci_irq_vector(pdev, 2),
-                                           vmci_interrupt_dma_datagram,
-                                           0, KBUILD_MODNAME, vmci_dev);
+                       error = request_threaded_irq(pci_irq_vector(pdev, 2),
+                                                    NULL,
+                                                   vmci_interrupt_dma_datagram,
+                                                    0, KBUILD_MODNAME,
+                                                    vmci_dev);
                        if (error) {
                                dev_err(&pdev->dev,
                                        "Failed to allocate irq %u: %d\n",
@@ -871,8 +865,6 @@ err_free_bm_irq:
 
 err_free_irq:
        free_irq(pci_irq_vector(pdev, 0), vmci_dev);
-       tasklet_kill(&vmci_dev->datagram_tasklet);
-       tasklet_kill(&vmci_dev->bm_tasklet);
 
 err_disable_msi:
        pci_free_irq_vectors(pdev);
@@ -943,9 +935,6 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)
        free_irq(pci_irq_vector(pdev, 0), vmci_dev);
        pci_free_irq_vectors(pdev);
 
-       tasklet_kill(&vmci_dev->datagram_tasklet);
-       tasklet_kill(&vmci_dev->bm_tasklet);
-
        if (vmci_dev->notification_bitmap) {
                /*
                 * The device reset above cleared the bitmap state of the
index 89ef0c80ac371166cce69067ad71a21960973f1f..9e73c34b64017a51e25d701e52f352cf23186fa6 100644 (file)
 #define ESDHC_TUNING_START_TAP_DEFAULT 0x1
 #define ESDHC_TUNING_START_TAP_MASK    0x7f
 #define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE     (1 << 7)
+#define ESDHC_TUNING_STEP_DEFAULT      0x1
 #define ESDHC_TUNING_STEP_MASK         0x00070000
 #define ESDHC_TUNING_STEP_SHIFT                16
 
@@ -1368,7 +1369,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
        struct cqhci_host *cq_host = host->mmc->cqe_private;
-       int tmp;
+       u32 tmp;
 
        if (esdhc_is_usdhc(imx_data)) {
                /*
@@ -1423,17 +1424,24 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 
                if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
                        tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-                       tmp |= ESDHC_STD_TUNING_EN |
-                               ESDHC_TUNING_START_TAP_DEFAULT;
-                       if (imx_data->boarddata.tuning_start_tap) {
-                               tmp &= ~ESDHC_TUNING_START_TAP_MASK;
+                       tmp |= ESDHC_STD_TUNING_EN;
+
+                       /*
+                        * ROM code or bootloader may config the start tap
+                        * and step, unmask them first.
+                        */
+                       tmp &= ~(ESDHC_TUNING_START_TAP_MASK | ESDHC_TUNING_STEP_MASK);
+                       if (imx_data->boarddata.tuning_start_tap)
                                tmp |= imx_data->boarddata.tuning_start_tap;
-                       }
+                       else
+                               tmp |= ESDHC_TUNING_START_TAP_DEFAULT;
 
                        if (imx_data->boarddata.tuning_step) {
-                               tmp &= ~ESDHC_TUNING_STEP_MASK;
                                tmp |= imx_data->boarddata.tuning_step
                                        << ESDHC_TUNING_STEP_SHIFT;
+                       } else {
+                               tmp |= ESDHC_TUNING_STEP_DEFAULT
+                                       << ESDHC_TUNING_STEP_SHIFT;
                        }
 
                        /* Disable the CMD CRC check for tuning, if not, need to
index b16e12e62e72223ca75a2ac8fa19ce1e0613280d..3db9f32d6a7b9fcd51672ed299e7456c0ac079d7 100644 (file)
@@ -1492,9 +1492,11 @@ static int sunxi_mmc_remove(struct platform_device *pdev)
        struct sunxi_mmc_host *host = mmc_priv(mmc);
 
        mmc_remove_host(mmc);
-       pm_runtime_force_suspend(&pdev->dev);
-       disable_irq(host->irq);
-       sunxi_mmc_disable(host);
+       pm_runtime_disable(&pdev->dev);
+       if (!pm_runtime_status_suspended(&pdev->dev)) {
+               disable_irq(host->irq);
+               sunxi_mmc_disable(host);
+       }
        dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
        mmc_free_host(mmc);
 
index 3585f02575dfbd005d268522dd247f4fbeb180a3..57eeb066a9456b237eab7166b3407b4dd8b12ec5 100644 (file)
@@ -48,6 +48,7 @@ mcp251xfd_ring_set_ringparam(struct net_device *ndev,
        priv->rx_obj_num = layout.cur_rx;
        priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
        priv->tx->obj_num = layout.cur_tx;
+       priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
 
        return 0;
 }
index c26755f662c1ff9bbed72742a2e83eeb747b0821..f6f3b43dfb06ea820f357bde36c7d89bec30f68a 100644 (file)
@@ -35,12 +35,13 @@ config NET_DSA_LANTIQ_GSWIP
          the xrx200 / VR9 SoC.
 
 config NET_DSA_MT7530
-       tristate "MediaTek MT753x and MT7621 Ethernet switch support"
+       tristate "MediaTek MT7530 and MT7531 Ethernet switch support"
        select NET_DSA_TAG_MTK
        select MEDIATEK_GE_PHY
        help
-         This enables support for the MediaTek MT7530, MT7531, and MT7621
-         Ethernet switch chips.
+         This enables support for the MediaTek MT7530 and MT7531 Ethernet
+         switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
+         MT7621ST and MT7623AI SoCs is supported.
 
 config NET_DSA_MV88E6060
        tristate "Marvell 88E6060 ethernet switch chip support"
index 47b54ecf2c6f6b502cd968968d0018c053aec26c..6178a96e389f26fe3199586bd558527ad8678626 100644 (file)
@@ -540,10 +540,10 @@ int ksz9477_fdb_del(struct ksz_device *dev, int port,
                ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]);
 
                /* clear forwarding port */
-               alu_table[2] &= ~BIT(port);
+               alu_table[1] &= ~BIT(port);
 
                /* if there is no port to forward, clear table */
-               if ((alu_table[2] & ALU_V_PORT_MAP) == 0) {
+               if ((alu_table[1] & ALU_V_PORT_MAP) == 0) {
                        alu_table[0] = 0;
                        alu_table[1] = 0;
                        alu_table[2] = 0;
index c1a633ca1e6d8ba709b2b008f5fd20d6f056e7d4..e315f669ec0611c584502d7ecea0981b1c5e5f48 100644 (file)
@@ -104,7 +104,7 @@ static const struct of_device_id ksz9477_dt_ids[] = {
        },
        {
                .compatible = "microchip,ksz8563",
-               .data = &ksz_switch_chips[KSZ9893]
+               .data = &ksz_switch_chips[KSZ8563]
        },
        {
                .compatible = "microchip,ksz9567",
index 0805f249fff29204611f5059873e7e13b52f0084..c26b8597945b5cb5c102eb7531a24c23b82f7b2d 100644 (file)
@@ -356,7 +356,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
 
        if ((port_priv->flags & IFF_ALLMULTI && rxb->pkt_type == PACKET_MULTICAST) ||
            (port_priv->flags & IFF_BROADCAST && rxb->pkt_type == PACKET_BROADCAST))
-               rxb->offload_fwd_mark = 1;
+               rxb->offload_fwd_mark = port_priv->priv->forwarding;
 
        netif_rx(rxb);
 
index 3936543a74d8f70ed5ecefaf6b4e18671cd72805..4030d619e84f56863d0fde61692ef12b386c4c32 100644 (file)
@@ -524,19 +524,28 @@ static void xgbe_disable_vxlan(struct xgbe_prv_data *pdata)
        netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n");
 }
 
+static unsigned int xgbe_get_fc_queue_count(struct xgbe_prv_data *pdata)
+{
+       unsigned int max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
+
+       /* From MAC ver 30H the TFCR is per priority, instead of per queue */
+       if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) >= 0x30)
+               return max_q_count;
+       else
+               return min_t(unsigned int, pdata->tx_q_count, max_q_count);
+}
+
 static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
 {
-       unsigned int max_q_count, q_count;
        unsigned int reg, reg_val;
-       unsigned int i;
+       unsigned int i, q_count;
 
        /* Clear MTL flow control */
        for (i = 0; i < pdata->rx_q_count; i++)
                XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
 
        /* Clear MAC flow control */
-       max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-       q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
+       q_count = xgbe_get_fc_queue_count(pdata);
        reg = MAC_Q0TFCR;
        for (i = 0; i < q_count; i++) {
                reg_val = XGMAC_IOREAD(pdata, reg);
@@ -553,9 +562,8 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
 {
        struct ieee_pfc *pfc = pdata->pfc;
        struct ieee_ets *ets = pdata->ets;
-       unsigned int max_q_count, q_count;
        unsigned int reg, reg_val;
-       unsigned int i;
+       unsigned int i, q_count;
 
        /* Set MTL flow control */
        for (i = 0; i < pdata->rx_q_count; i++) {
@@ -579,8 +587,7 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
        }
 
        /* Set MAC flow control */
-       max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-       q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
+       q_count = xgbe_get_fc_queue_count(pdata);
        reg = MAC_Q0TFCR;
        for (i = 0; i < q_count; i++) {
                reg_val = XGMAC_IOREAD(pdata, reg);
index 0c5c1b1556830b0b62449225a2bd9fa0d2dad45d..43fdd111235a66ab17ce66b47ce694f6f7a49937 100644 (file)
@@ -496,6 +496,7 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
        reg |= XGBE_KR_TRAINING_ENABLE;
        reg |= XGBE_KR_TRAINING_START;
        XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+       pdata->kr_start_time = jiffies;
 
        netif_dbg(pdata, link, pdata->netdev,
                  "KR training initiated\n");
@@ -632,6 +633,8 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
 
        xgbe_switch_mode(pdata);
 
+       pdata->an_result = XGBE_AN_READY;
+
        xgbe_an_restart(pdata);
 
        return XGBE_AN_INCOMPAT_LINK;
@@ -1275,9 +1278,30 @@ static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
 static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
 {
        unsigned long link_timeout;
+       unsigned long kr_time;
+       int wait;
 
        link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
        if (time_after(jiffies, link_timeout)) {
+               if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) &&
+                   pdata->phy.autoneg == AUTONEG_ENABLE) {
+                       /* AN restart should not happen while KR training is in progress.
+                        * The while loop ensures no AN restart during KR training,
+                        * waits up to 500ms and AN restart is triggered only if KR
+                        * training is failed.
+                        */
+                       wait = XGBE_KR_TRAINING_WAIT_ITER;
+                       while (wait--) {
+                               kr_time = pdata->kr_start_time +
+                                         msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
+                               if (time_after(jiffies, kr_time))
+                                       break;
+                               /* AN restart is not required, if AN result is COMPLETE */
+                               if (pdata->an_result == XGBE_AN_COMPLETE)
+                                       return;
+                               usleep_range(10000, 11000);
+                       }
+               }
                netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
                xgbe_phy_config_aneg(pdata);
        }
index 71f24cb479355e8a40d9cdfbeea5f5736ddeb2a3..7a41367c437ddf3cc484d4650b4c0ccdb1496f37 100644 (file)
 /* Auto-negotiation */
 #define XGBE_AN_MS_TIMEOUT             500
 #define XGBE_LINK_TIMEOUT              5
+#define XGBE_KR_TRAINING_WAIT_ITER     50
 
 #define XGBE_SGMII_AN_LINK_STATUS      BIT(1)
 #define XGBE_SGMII_AN_LINK_SPEED       (BIT(2) | BIT(3))
@@ -1280,6 +1281,7 @@ struct xgbe_prv_data {
        unsigned int parallel_detect;
        unsigned int fec_ability;
        unsigned long an_start;
+       unsigned long kr_start_time;
        enum xgbe_an_mode an_mode;
 
        /* I2C support */
index cbf17fcfb7ab431244613871fe8dbf5e7f8818dc..ec573127b70762fd6b26f5108b28a4318f045d92 100644 (file)
@@ -3969,7 +3969,7 @@ void bnxt_ethtool_init(struct bnxt *bp)
                test_info->timeout = HWRM_CMD_TIMEOUT;
        for (i = 0; i < bp->num_tests; i++) {
                char *str = test_info->string[i];
-               char *fw_str = resp->test0_name + i * 32;
+               char *fw_str = resp->test_name[i];
 
                if (i == BNXT_MACLPBK_TEST_IDX) {
                        strcpy(str, "Mac loopback test (offline)");
@@ -3980,14 +3980,9 @@ void bnxt_ethtool_init(struct bnxt *bp)
                } else if (i == BNXT_IRQ_TEST_IDX) {
                        strcpy(str, "Interrupt_test (offline)");
                } else {
-                       strscpy(str, fw_str, ETH_GSTRING_LEN);
-                       strncat(str, " test", ETH_GSTRING_LEN - strlen(str));
-                       if (test_info->offline_mask & (1 << i))
-                               strncat(str, " (offline)",
-                                       ETH_GSTRING_LEN - strlen(str));
-                       else
-                               strncat(str, " (online)",
-                                       ETH_GSTRING_LEN - strlen(str));
+                       snprintf(str, ETH_GSTRING_LEN, "%s test (%s)",
+                                fw_str, test_info->offline_mask & (1 << i) ?
+                                       "offline" : "online");
                }
        }
 
index 2686a714a59f7782ec4bef3112384b31e3fabc5b..a5408879e077e9663ce6deb10dbf4c08d90c961d 100644 (file)
@@ -10249,14 +10249,7 @@ struct hwrm_selftest_qlist_output {
        u8      unused_0;
        __le16  test_timeout;
        u8      unused_1[2];
-       char    test0_name[32];
-       char    test1_name[32];
-       char    test2_name[32];
-       char    test3_name[32];
-       char    test4_name[32];
-       char    test5_name[32];
-       char    test6_name[32];
-       char    test7_name[32];
+       char    test_name[8][32];
        u8      eyescope_target_BER_support;
        #define SELFTEST_QLIST_RESP_EYESCOPE_TARGET_BER_SUPPORT_BER_1E8_SUPPORTED  0x0UL
        #define SELFTEST_QLIST_RESP_EYESCOPE_TARGET_BER_SUPPORT_BER_1E9_SUPPORTED  0x1UL
index 59debdc344a507a97a591c104e73d40737ca4b47..58747292521d8199a85173cad8f2d8afc4473a99 100644 (file)
@@ -11166,7 +11166,7 @@ static void tg3_reset_task(struct work_struct *work)
        rtnl_lock();
        tg3_full_lock(tp, 0);
 
-       if (!netif_running(tp->dev)) {
+       if (tp->pcierr_recovery || !netif_running(tp->dev)) {
                tg3_flag_clear(tp, RESET_TASK_PENDING);
                tg3_full_unlock(tp);
                rtnl_unlock();
@@ -18101,6 +18101,9 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
        netdev_info(netdev, "PCI I/O error detected\n");
 
+       /* Want to make sure that the reset task doesn't run */
+       tg3_reset_task_cancel(tp);
+
        rtnl_lock();
 
        /* Could be second call or maybe we don't have netdev yet */
@@ -18117,9 +18120,6 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
        tg3_timer_stop(tp);
 
-       /* Want to make sure that the reset task doesn't run */
-       tg3_reset_task_cancel(tp);
-
        netif_device_detach(netdev);
 
        /* Clean up software state, even if MMIO is blocked */
index 95667b979fab4254e02636a9b677139cd9042834..72e42820713dffbbca0f6925d32da5c6e53f0e82 100644 (file)
@@ -2187,7 +2187,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
        bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
                      skb_is_nonlinear(*skb);
        int padlen = ETH_ZLEN - (*skb)->len;
-       int headroom = skb_headroom(*skb);
        int tailroom = skb_tailroom(*skb);
        struct sk_buff *nskb;
        u32 fcs;
@@ -2201,9 +2200,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                /* FCS could be appeded to tailroom. */
                if (tailroom >= ETH_FCS_LEN)
                        goto add_fcs;
-               /* FCS could be appeded by moving data to headroom. */
-               else if (!cloned && headroom + tailroom >= ETH_FCS_LEN)
-                       padlen = 0;
                /* No room for FCS, need to reallocate skb. */
                else
                        padlen = ETH_FCS_LEN;
@@ -2212,10 +2208,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                padlen += ETH_FCS_LEN;
        }
 
-       if (!cloned && headroom + tailroom >= padlen) {
-               (*skb)->data = memmove((*skb)->head, (*skb)->data, (*skb)->len);
-               skb_set_tail_pointer(*skb, (*skb)->len);
-       } else {
+       if (cloned || tailroom < padlen) {
                nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC);
                if (!nskb)
                        return -ENOMEM;
index bf0190e1d2ea4c9fdd291eadf5eeeea6b00acbb3..00e2108f2ca4cb9823eae1fba44626e484ebdc81 100644 (file)
@@ -450,7 +450,7 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
                /* ring full, shall not happen because queue is stopped if full
                 * below
                 */
-               netif_stop_queue(tx->adapter->netdev);
+               netif_stop_subqueue(tx->adapter->netdev, tx->queue_index);
 
                spin_unlock_irqrestore(&tx->lock, flags);
 
@@ -493,7 +493,7 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
 
        if (tsnep_tx_desc_available(tx) < (MAX_SKB_FRAGS + 1)) {
                /* ring can get full with next frame */
-               netif_stop_queue(tx->adapter->netdev);
+               netif_stop_subqueue(tx->adapter->netdev, tx->queue_index);
        }
 
        spin_unlock_irqrestore(&tx->lock, flags);
@@ -503,11 +503,14 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
 
 static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
 {
+       struct tsnep_tx_entry *entry;
+       struct netdev_queue *nq;
        unsigned long flags;
        int budget = 128;
-       struct tsnep_tx_entry *entry;
-       int count;
        int length;
+       int count;
+
+       nq = netdev_get_tx_queue(tx->adapter->netdev, tx->queue_index);
 
        spin_lock_irqsave(&tx->lock, flags);
 
@@ -564,8 +567,8 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
        } while (likely(budget));
 
        if ((tsnep_tx_desc_available(tx) >= ((MAX_SKB_FRAGS + 1) * 2)) &&
-           netif_queue_stopped(tx->adapter->netdev)) {
-               netif_wake_queue(tx->adapter->netdev);
+           netif_tx_queue_stopped(nq)) {
+               netif_tx_wake_queue(nq);
        }
 
        spin_unlock_irqrestore(&tx->lock, flags);
index 3f8032947d86ef566db532d0c60651a3e101e4be..027fff9f7db073e9c8d4a6b0de0138df50ed931c 100644 (file)
@@ -2410,6 +2410,9 @@ static int dpaa_eth_poll(struct napi_struct *napi, int budget)
 
        cleaned = qman_p_poll_dqrr(np->p, budget);
 
+       if (np->xdp_act & XDP_REDIRECT)
+               xdp_do_flush();
+
        if (cleaned < budget) {
                napi_complete_done(napi, cleaned);
                qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
@@ -2417,9 +2420,6 @@ static int dpaa_eth_poll(struct napi_struct *napi, int budget)
                qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
        }
 
-       if (np->xdp_act & XDP_REDIRECT)
-               xdp_do_flush();
-
        return cleaned;
 }
 
index 0c35abb7d065e64d6c57a98769e4a0c0c54cfe26..2e79d18fc3c7add1b3a811c008b8bfb4ab548f67 100644 (file)
@@ -1993,10 +1993,15 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
                if (rx_cleaned >= budget ||
                    txconf_cleaned >= DPAA2_ETH_TXCONF_PER_NAPI) {
                        work_done = budget;
+                       if (ch->xdp.res & XDP_REDIRECT)
+                               xdp_do_flush();
                        goto out;
                }
        } while (store_cleaned);
 
+       if (ch->xdp.res & XDP_REDIRECT)
+               xdp_do_flush();
+
        /* Update NET DIM with the values for this CDAN */
        dpaa2_io_update_net_dim(ch->dpio, ch->stats.frames_per_cdan,
                                ch->stats.bytes_per_cdan);
@@ -2032,9 +2037,7 @@ out:
                txc_fq->dq_bytes = 0;
        }
 
-       if (ch->xdp.res & XDP_REDIRECT)
-               xdp_do_flush_map();
-       else if (rx_cleaned && ch->xdp.res & XDP_TX)
+       if (rx_cleaned && ch->xdp.res & XDP_TX)
                dpaa2_eth_xdp_tx_flush(priv, ch, &priv->fq[flowid]);
 
        return work_done;
index 3a79ead5219ae27d1ff0ccf5a6f62f9d8ed39128..e96449eedfb5428a6361a76dc98a8f8df51744c5 100644 (file)
@@ -2290,14 +2290,14 @@ static void enetc_tx_onestep_tstamp(struct work_struct *work)
 
        priv = container_of(work, struct enetc_ndev_priv, tx_onestep_tstamp);
 
-       netif_tx_lock(priv->ndev);
+       netif_tx_lock_bh(priv->ndev);
 
        clear_bit_unlock(ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS, &priv->flags);
        skb = skb_dequeue(&priv->tx_skbs);
        if (skb)
                enetc_start_xmit(skb, priv->ndev);
 
-       netif_tx_unlock(priv->ndev);
+       netif_tx_unlock_bh(priv->ndev);
 }
 
 static void enetc_tx_onestep_tstamp_init(struct enetc_ndev_priv *priv)
index 644f3c96373029af02ea9c8cec801c04e2329228..2341597408d129cda9979f6dddb4db759f3a87fa 100644 (file)
@@ -3191,7 +3191,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
        for (q = 0; q < fep->num_rx_queues; q++) {
                rxq = fep->rx_queue[q];
                for (i = 0; i < rxq->bd.ring_size; i++)
-                       page_pool_release_page(rxq->page_pool, rxq->rx_skb_info[i].page);
+                       page_pool_put_full_page(rxq->page_pool, rxq->rx_skb_info[i].page, false);
 
                for (i = 0; i < XDP_STATS_TOTAL; i++)
                        rxq->stats[i] = 0;
index 9349f841bd0645a068d4538c81ea461df177e531..587ad81a2dc3293b77d6e702b144b6d47ac4aff0 100644 (file)
@@ -1055,6 +1055,9 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
                return ERR_PTR(-EPROBE_DEFER);
 
        pcs = lynx_pcs_create(mdiodev);
+       if (!pcs)
+               mdio_device_free(mdiodev);
+
        return pcs;
 }
 
index 0d1bab4ac1b075858cd5fc3f4a06b966766284a7..2a9f1eeeb7015f3cf4f524d24f2458d261af9367 100644 (file)
@@ -249,6 +249,7 @@ struct iavf_cloud_filter {
 
 /* board specific private data structure */
 struct iavf_adapter {
+       struct workqueue_struct *wq;
        struct work_struct reset_task;
        struct work_struct adminq_task;
        struct delayed_work client_task;
@@ -459,7 +460,6 @@ struct iavf_device {
 
 /* needed by iavf_ethtool.c */
 extern char iavf_driver_name[];
-extern struct workqueue_struct *iavf_wq;
 
 static inline const char *iavf_state_str(enum iavf_state_t state)
 {
index d79ead5e8d0ca684cd8eb2090c6ae8320da5b9a9..6f171d1d85b75f81053de0ae63bb2b9214c21f27 100644 (file)
@@ -532,7 +532,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
        if (changed_flags & IAVF_FLAG_LEGACY_RX) {
                if (netif_running(netdev)) {
                        adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-                       queue_work(iavf_wq, &adapter->reset_task);
+                       queue_work(adapter->wq, &adapter->reset_task);
                }
        }
 
@@ -672,7 +672,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
 
        if (netif_running(netdev)) {
                adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(iavf_wq, &adapter->reset_task);
+               queue_work(adapter->wq, &adapter->reset_task);
        }
 
        return 0;
@@ -1433,7 +1433,7 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
        spin_unlock_bh(&adapter->fdir_fltr_lock);
 
-       mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+       mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 
 ret:
        if (err && fltr)
@@ -1474,7 +1474,7 @@ static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        spin_unlock_bh(&adapter->fdir_fltr_lock);
 
        if (fltr && fltr->state == IAVF_FDIR_FLTR_DEL_REQUEST)
-               mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+               mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 
        return err;
 }
@@ -1658,7 +1658,7 @@ iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,
        spin_unlock_bh(&adapter->adv_rss_lock);
 
        if (!err)
-               mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+               mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 
        mutex_unlock(&adapter->crit_lock);
 
index adc02adef83a2ad180eb9b7fe1390b6ada1c6e07..4b09785d2147a49b0bce91f866e1fa965050276a 100644 (file)
@@ -49,7 +49,6 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Adaptive Virtual Function Network Driver")
 MODULE_LICENSE("GPL v2");
 
 static const struct net_device_ops iavf_netdev_ops;
-struct workqueue_struct *iavf_wq;
 
 int iavf_status_to_errno(enum iavf_status status)
 {
@@ -277,7 +276,7 @@ void iavf_schedule_reset(struct iavf_adapter *adapter)
        if (!(adapter->flags &
              (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
                adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(iavf_wq, &adapter->reset_task);
+               queue_work(adapter->wq, &adapter->reset_task);
        }
 }
 
@@ -291,7 +290,7 @@ void iavf_schedule_reset(struct iavf_adapter *adapter)
 void iavf_schedule_request_stats(struct iavf_adapter *adapter)
 {
        adapter->aq_required |= IAVF_FLAG_AQ_REQUEST_STATS;
-       mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+       mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 }
 
 /**
@@ -411,7 +410,7 @@ static irqreturn_t iavf_msix_aq(int irq, void *data)
 
        if (adapter->state != __IAVF_REMOVE)
                /* schedule work on the private workqueue */
-               queue_work(iavf_wq, &adapter->adminq_task);
+               queue_work(adapter->wq, &adapter->adminq_task);
 
        return IRQ_HANDLED;
 }
@@ -1034,7 +1033,7 @@ int iavf_replace_primary_mac(struct iavf_adapter *adapter,
 
        /* schedule the watchdog task to immediately process the request */
        if (f) {
-               queue_work(iavf_wq, &adapter->watchdog_task.work);
+               mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
                return 0;
        }
        return -ENOMEM;
@@ -1257,7 +1256,7 @@ static void iavf_up_complete(struct iavf_adapter *adapter)
        adapter->aq_required |= IAVF_FLAG_AQ_ENABLE_QUEUES;
        if (CLIENT_ENABLED(adapter))
                adapter->flags |= IAVF_FLAG_CLIENT_NEEDS_OPEN;
-       mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+       mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 }
 
 /**
@@ -1414,7 +1413,7 @@ void iavf_down(struct iavf_adapter *adapter)
                adapter->aq_required |= IAVF_FLAG_AQ_DISABLE_QUEUES;
        }
 
-       mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+       mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 }
 
 /**
@@ -2248,7 +2247,7 @@ iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
 
        if (aq_required) {
                adapter->aq_required |= aq_required;
-               mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0);
+               mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
        }
 }
 
@@ -2693,6 +2692,15 @@ static void iavf_watchdog_task(struct work_struct *work)
                goto restart_watchdog;
        }
 
+       if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
+           adapter->netdev_registered &&
+           !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
+           rtnl_trylock()) {
+               netdev_update_features(adapter->netdev);
+               rtnl_unlock();
+               adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
+       }
+
        if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
                iavf_change_state(adapter, __IAVF_COMM_FAILED);
 
@@ -2700,7 +2708,7 @@ static void iavf_watchdog_task(struct work_struct *work)
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
                mutex_unlock(&adapter->crit_lock);
-               queue_work(iavf_wq, &adapter->reset_task);
+               queue_work(adapter->wq, &adapter->reset_task);
                return;
        }
 
@@ -2708,31 +2716,31 @@ static void iavf_watchdog_task(struct work_struct *work)
        case __IAVF_STARTUP:
                iavf_startup(adapter);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                                   msecs_to_jiffies(30));
                return;
        case __IAVF_INIT_VERSION_CHECK:
                iavf_init_version_check(adapter);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                                   msecs_to_jiffies(30));
                return;
        case __IAVF_INIT_GET_RESOURCES:
                iavf_init_get_resources(adapter);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                                   msecs_to_jiffies(1));
                return;
        case __IAVF_INIT_EXTENDED_CAPS:
                iavf_init_process_extended_caps(adapter);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                                   msecs_to_jiffies(1));
                return;
        case __IAVF_INIT_CONFIG_ADAPTER:
                iavf_init_config_adapter(adapter);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                                   msecs_to_jiffies(1));
                return;
        case __IAVF_INIT_FAILED:
@@ -2751,14 +2759,14 @@ static void iavf_watchdog_task(struct work_struct *work)
                        adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED;
                        iavf_shutdown_adminq(hw);
                        mutex_unlock(&adapter->crit_lock);
-                       queue_delayed_work(iavf_wq,
+                       queue_delayed_work(adapter->wq,
                                           &adapter->watchdog_task, (5 * HZ));
                        return;
                }
                /* Try again from failed step*/
                iavf_change_state(adapter, adapter->last_state);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ);
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task, HZ);
                return;
        case __IAVF_COMM_FAILED:
                if (test_bit(__IAVF_IN_REMOVE_TASK,
@@ -2789,13 +2797,14 @@ static void iavf_watchdog_task(struct work_struct *work)
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq,
+               queue_delayed_work(adapter->wq,
                                   &adapter->watchdog_task,
                                   msecs_to_jiffies(10));
                return;
        case __IAVF_RESETTING:
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2);
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
+                                  HZ * 2);
                return;
        case __IAVF_DOWN:
        case __IAVF_DOWN_PENDING:
@@ -2834,9 +2843,9 @@ static void iavf_watchdog_task(struct work_struct *work)
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
                dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
-               queue_work(iavf_wq, &adapter->reset_task);
+               queue_work(adapter->wq, &adapter->reset_task);
                mutex_unlock(&adapter->crit_lock);
-               queue_delayed_work(iavf_wq,
+               queue_delayed_work(adapter->wq,
                                   &adapter->watchdog_task, HZ * 2);
                return;
        }
@@ -2845,12 +2854,13 @@ static void iavf_watchdog_task(struct work_struct *work)
        mutex_unlock(&adapter->crit_lock);
 restart_watchdog:
        if (adapter->state >= __IAVF_DOWN)
-               queue_work(iavf_wq, &adapter->adminq_task);
+               queue_work(adapter->wq, &adapter->adminq_task);
        if (adapter->aq_required)
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                                   msecs_to_jiffies(20));
        else
-               queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2);
+               queue_delayed_work(adapter->wq, &adapter->watchdog_task,
+                                  HZ * 2);
 }
 
 /**
@@ -2952,7 +2962,7 @@ static void iavf_reset_task(struct work_struct *work)
         */
        if (!mutex_trylock(&adapter->crit_lock)) {
                if (adapter->state != __IAVF_REMOVE)
-                       queue_work(iavf_wq, &adapter->reset_task);
+                       queue_work(adapter->wq, &adapter->reset_task);
 
                goto reset_finish;
        }
@@ -3116,7 +3126,7 @@ continue_reset:
        bitmap_clear(adapter->vsi.active_cvlans, 0, VLAN_N_VID);
        bitmap_clear(adapter->vsi.active_svlans, 0, VLAN_N_VID);
 
-       mod_delayed_work(iavf_wq, &adapter->watchdog_task, 2);
+       mod_delayed_work(adapter->wq, &adapter->watchdog_task, 2);
 
        /* We were running when the reset started, so we need to restore some
         * state here.
@@ -3208,7 +3218,7 @@ static void iavf_adminq_task(struct work_struct *work)
                if (adapter->state == __IAVF_REMOVE)
                        return;
 
-               queue_work(iavf_wq, &adapter->adminq_task);
+               queue_work(adapter->wq, &adapter->adminq_task);
                goto out;
        }
 
@@ -3232,24 +3242,6 @@ static void iavf_adminq_task(struct work_struct *work)
        } while (pending);
        mutex_unlock(&adapter->crit_lock);
 
-       if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES)) {
-               if (adapter->netdev_registered ||
-                   !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
-                       struct net_device *netdev = adapter->netdev;
-
-                       rtnl_lock();
-                       netdev_update_features(netdev);
-                       rtnl_unlock();
-                       /* Request VLAN offload settings */
-                       if (VLAN_V2_ALLOWED(adapter))
-                               iavf_set_vlan_offload_features
-                                       (adapter, 0, netdev->features);
-
-                       iavf_set_queue_vlan_tag_loc(adapter);
-               }
-
-               adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
-       }
        if ((adapter->flags &
             (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
            adapter->state == __IAVF_RESETTING)
@@ -4349,7 +4341,7 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
 
        if (netif_running(netdev)) {
                adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(iavf_wq, &adapter->reset_task);
+               queue_work(adapter->wq, &adapter->reset_task);
        }
 
        return 0;
@@ -4898,6 +4890,13 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw = &adapter->hw;
        hw->back = adapter;
 
+       adapter->wq = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,
+                                             iavf_driver_name);
+       if (!adapter->wq) {
+               err = -ENOMEM;
+               goto err_alloc_wq;
+       }
+
        adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
        iavf_change_state(adapter, __IAVF_STARTUP);
 
@@ -4942,7 +4941,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
        INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
        INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
-       queue_delayed_work(iavf_wq, &adapter->watchdog_task,
+       queue_delayed_work(adapter->wq, &adapter->watchdog_task,
                           msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
 
        /* Setup the wait queue for indicating transition to down status */
@@ -4954,6 +4953,8 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
 err_ioremap:
+       destroy_workqueue(adapter->wq);
+err_alloc_wq:
        free_netdev(netdev);
 err_alloc_etherdev:
        pci_disable_pcie_error_reporting(pdev);
@@ -5023,7 +5024,7 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
                return err;
        }
 
-       queue_work(iavf_wq, &adapter->reset_task);
+       queue_work(adapter->wq, &adapter->reset_task);
 
        netif_device_attach(adapter->netdev);
 
@@ -5170,6 +5171,8 @@ static void iavf_remove(struct pci_dev *pdev)
        }
        spin_unlock_bh(&adapter->adv_rss_lock);
 
+       destroy_workqueue(adapter->wq);
+
        free_netdev(netdev);
 
        pci_disable_pcie_error_reporting(pdev);
@@ -5196,24 +5199,11 @@ static struct pci_driver iavf_driver = {
  **/
 static int __init iavf_init_module(void)
 {
-       int ret;
-
        pr_info("iavf: %s\n", iavf_driver_string);
 
        pr_info("%s\n", iavf_copyright);
 
-       iavf_wq = alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1,
-                                 iavf_driver_name);
-       if (!iavf_wq) {
-               pr_err("%s: Failed to create workqueue\n", iavf_driver_name);
-               return -ENOMEM;
-       }
-
-       ret = pci_register_driver(&iavf_driver);
-       if (ret)
-               destroy_workqueue(iavf_wq);
-
-       return ret;
+       return pci_register_driver(&iavf_driver);
 }
 
 module_init(iavf_init_module);
@@ -5227,7 +5217,6 @@ module_init(iavf_init_module);
 static void __exit iavf_exit_module(void)
 {
        pci_unregister_driver(&iavf_driver);
-       destroy_workqueue(iavf_wq);
 }
 
 module_exit(iavf_exit_module);
index 24a701fd140e9dff7d50c85536cac832b51c36a0..365ca0c710c4a46d50a3c87ed79162ba6e19e080 100644 (file)
@@ -1952,7 +1952,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                        if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
                                adapter->flags |= IAVF_FLAG_RESET_PENDING;
                                dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
-                               queue_work(iavf_wq, &adapter->reset_task);
+                               queue_work(adapter->wq, &adapter->reset_task);
                        }
                        break;
                default:
@@ -2226,6 +2226,14 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
 
                iavf_process_config(adapter);
                adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+
+               /* Request VLAN offload settings */
+               if (VLAN_V2_ALLOWED(adapter))
+                       iavf_set_vlan_offload_features(adapter, 0,
+                                                      netdev->features);
+
+               iavf_set_queue_vlan_tag_loc(adapter);
+
                was_mac_changed = !ether_addr_equal(netdev->dev_addr,
                                                    adapter->hw.mac.addr);
 
index 2f0b604abc5e728da3171105ef340591d060c2a0..713069f809ec43fce6daa9bf360c44ff745f072f 100644 (file)
@@ -880,7 +880,7 @@ void ice_set_ethtool_repr_ops(struct net_device *netdev);
 void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
 u16 ice_get_avail_txq_count(struct ice_pf *pf);
 u16 ice_get_avail_rxq_count(struct ice_pf *pf);
-int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx);
+int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
 void ice_update_vsi_stats(struct ice_vsi *vsi);
 void ice_update_pf_stats(struct ice_pf *pf);
 void
index 4f24d441c35e257ba397d322f6fa8124b8e7eeef..0a55c552189ab198f95087972bd49bd3bbed59b6 100644 (file)
@@ -441,7 +441,7 @@ int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
                goto out;
        }
 
-       ice_pf_dcb_recfg(pf);
+       ice_pf_dcb_recfg(pf, false);
 
 out:
        /* enable previously downed VSIs */
@@ -731,12 +731,13 @@ static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
 /**
  * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
  * @pf: pointer to the PF struct
+ * @locked: is adev device lock held
  *
  * Assumed caller has already disabled all VSIs before
  * calling this function. Reconfiguring DCB based on
  * local_dcbx_cfg.
  */
-void ice_pf_dcb_recfg(struct ice_pf *pf)
+void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked)
 {
        struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
        struct iidc_event *event;
@@ -783,14 +784,16 @@ void ice_pf_dcb_recfg(struct ice_pf *pf)
                if (vsi->type == ICE_VSI_PF)
                        ice_dcbnl_set_all(vsi);
        }
-       /* Notify the AUX drivers that TC change is finished */
-       event = kzalloc(sizeof(*event), GFP_KERNEL);
-       if (!event)
-               return;
+       if (!locked) {
+               /* Notify the AUX drivers that TC change is finished */
+               event = kzalloc(sizeof(*event), GFP_KERNEL);
+               if (!event)
+                       return;
 
-       set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
-       ice_send_event_to_aux(pf, event);
-       kfree(event);
+               set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
+               ice_send_event_to_aux(pf, event);
+               kfree(event);
+       }
 }
 
 /**
@@ -1044,7 +1047,7 @@ ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
        }
 
        /* changes in configuration update VSI */
-       ice_pf_dcb_recfg(pf);
+       ice_pf_dcb_recfg(pf, false);
 
        /* enable previously downed VSIs */
        ice_dcb_ena_dis_vsi(pf, true, true);
index 4c421c842a13fc4fa28b5c168c123786eb2695ca..800879a88c5e7b6f516c9db6c1657e06077064a5 100644 (file)
@@ -23,7 +23,7 @@ u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index);
 int
 ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked);
 int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg);
-void ice_pf_dcb_recfg(struct ice_pf *pf);
+void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked);
 void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
 int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
 void ice_update_dcb_stats(struct ice_pf *pf);
@@ -128,7 +128,7 @@ static inline u8 ice_get_pfc_mode(struct ice_pf *pf)
        return 0;
 }
 
-static inline void ice_pf_dcb_recfg(struct ice_pf *pf) { }
+static inline void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked) { }
 static inline void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) { }
 static inline void ice_update_dcb_stats(struct ice_pf *pf) { }
 static inline void
index 4191994d8f3ae5f442eb77e06d0c740c3d0342c1..a359f1610fc196dde0b16512741d49a8d55e400a 100644 (file)
@@ -3641,7 +3641,9 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
        struct ice_vsi *vsi = np->vsi;
        struct ice_pf *pf = vsi->back;
        int new_rx = 0, new_tx = 0;
+       bool locked = false;
        u32 curr_combined;
+       int ret = 0;
 
        /* do not support changing channels in Safe Mode */
        if (ice_is_safe_mode(pf)) {
@@ -3705,15 +3707,33 @@ static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch)
                return -EINVAL;
        }
 
-       ice_vsi_recfg_qs(vsi, new_rx, new_tx);
+       if (pf->adev) {
+               mutex_lock(&pf->adev_mutex);
+               device_lock(&pf->adev->dev);
+               locked = true;
+               if (pf->adev->dev.driver) {
+                       netdev_err(dev, "Cannot change channels when RDMA is active\n");
+                       ret = -EBUSY;
+                       goto adev_unlock;
+               }
+       }
+
+       ice_vsi_recfg_qs(vsi, new_rx, new_tx, locked);
 
-       if (!netif_is_rxfh_configured(dev))
-               return ice_vsi_set_dflt_rss_lut(vsi, new_rx);
+       if (!netif_is_rxfh_configured(dev)) {
+               ret = ice_vsi_set_dflt_rss_lut(vsi, new_rx);
+               goto adev_unlock;
+       }
 
        /* Update rss_size due to change in Rx queues */
        vsi->rss_size = ice_get_valid_rss_size(&pf->hw, new_rx);
 
-       return 0;
+adev_unlock:
+       if (locked) {
+               device_unlock(&pf->adev->dev);
+               mutex_unlock(&pf->adev_mutex);
+       }
+       return ret;
 }
 
 /**
index 94aa834cd9a6bd3f7baf913e0da8955ba4e77871..a596e07b3ce9db944cd0e9b4bc410d1ea516efd3 100644 (file)
@@ -3235,9 +3235,6 @@ int ice_vsi_release(struct ice_vsi *vsi)
                }
        }
 
-       if (vsi->type == ICE_VSI_PF)
-               ice_devlink_destroy_pf_port(pf);
-
        if (vsi->type == ICE_VSI_VF &&
            vsi->agg_node && vsi->agg_node->valid)
                vsi->agg_node->num_vsis--;
index a9a7f8b52140b4a6e98126a678b07c567ecc5c24..5f86e4111fa9bebb8008e3ffb21f200028f8da13 100644 (file)
@@ -4195,12 +4195,13 @@ bool ice_is_wol_supported(struct ice_hw *hw)
  * @vsi: VSI being changed
  * @new_rx: new number of Rx queues
  * @new_tx: new number of Tx queues
+ * @locked: is adev device_lock held
  *
  * Only change the number of queues if new_tx, or new_rx is non-0.
  *
  * Returns 0 on success.
  */
-int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
+int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked)
 {
        struct ice_pf *pf = vsi->back;
        int err = 0, timeout = 50;
@@ -4229,7 +4230,7 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
 
        ice_vsi_close(vsi);
        ice_vsi_rebuild(vsi, false);
-       ice_pf_dcb_recfg(pf);
+       ice_pf_dcb_recfg(pf, locked);
        ice_vsi_open(vsi);
 done:
        clear_bit(ICE_CFG_BUSY, pf->state);
@@ -4590,7 +4591,7 @@ static void ice_print_wake_reason(struct ice_pf *pf)
 }
 
 /**
- * ice_register_netdev - register netdev and devlink port
+ * ice_register_netdev - register netdev
  * @pf: pointer to the PF struct
  */
 static int ice_register_netdev(struct ice_pf *pf)
@@ -4602,11 +4603,6 @@ static int ice_register_netdev(struct ice_pf *pf)
        if (!vsi || !vsi->netdev)
                return -EIO;
 
-       err = ice_devlink_create_pf_port(pf);
-       if (err)
-               goto err_devlink_create;
-
-       SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port);
        err = register_netdev(vsi->netdev);
        if (err)
                goto err_register_netdev;
@@ -4617,8 +4613,6 @@ static int ice_register_netdev(struct ice_pf *pf)
 
        return 0;
 err_register_netdev:
-       ice_devlink_destroy_pf_port(pf);
-err_devlink_create:
        free_netdev(vsi->netdev);
        vsi->netdev = NULL;
        clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
@@ -4636,6 +4630,7 @@ static int
 ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
 {
        struct device *dev = &pdev->dev;
+       struct ice_vsi *vsi;
        struct ice_pf *pf;
        struct ice_hw *hw;
        int i, err;
@@ -4918,6 +4913,18 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
        pcie_print_link_status(pf->pdev);
 
 probe_done:
+       err = ice_devlink_create_pf_port(pf);
+       if (err)
+               goto err_create_pf_port;
+
+       vsi = ice_get_main_vsi(pf);
+       if (!vsi || !vsi->netdev) {
+               err = -EINVAL;
+               goto err_netdev_reg;
+       }
+
+       SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port);
+
        err = ice_register_netdev(pf);
        if (err)
                goto err_netdev_reg;
@@ -4955,6 +4962,8 @@ err_init_aux_unroll:
 err_devlink_reg_param:
        ice_devlink_unregister_params(pf);
 err_netdev_reg:
+       ice_devlink_destroy_pf_port(pf);
+err_create_pf_port:
 err_send_version_unroll:
        ice_vsi_release_all(pf);
 err_alloc_sw_unroll:
@@ -5083,6 +5092,7 @@ static void ice_remove(struct pci_dev *pdev)
        ice_setup_mc_magic_wake(pf);
        ice_vsi_release_all(pf);
        mutex_destroy(&(&pf->hw)->fdir_fltr_lock);
+       ice_devlink_destroy_pf_port(pf);
        ice_set_wake(pf);
        ice_free_irq_msix_misc(pf);
        ice_for_each_vsi(pf, i) {
index c34734d432e0d726b4e15f7cdd14c80f8eb4630e..4e10ced736dbb5855d0389b8c4636c22c52c06a2 100644 (file)
@@ -417,10 +417,12 @@ static int igc_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
  *
  * We need to convert the system time value stored in the RX/TXSTMP registers
  * into a hwtstamp which can be used by the upper level timestamping functions.
+ *
+ * Returns 0 on success.
  **/
-static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
-                                      struct skb_shared_hwtstamps *hwtstamps,
-                                      u64 systim)
+static int igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
+                                     struct skb_shared_hwtstamps *hwtstamps,
+                                     u64 systim)
 {
        switch (adapter->hw.mac.type) {
        case igc_i225:
@@ -430,8 +432,9 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
                                                systim & 0xFFFFFFFF);
                break;
        default:
-               break;
+               return -EINVAL;
        }
+       return 0;
 }
 
 /**
@@ -652,7 +655,8 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
 
        regval = rd32(IGC_TXSTMPL);
        regval |= (u64)rd32(IGC_TXSTMPH) << 32;
-       igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
+       if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval))
+               return;
 
        switch (adapter->link_speed) {
        case SPEED_10:
index bda1a6fa2ec43cd98cf52ab62600bf968c0252c8..e4407f09c9d34bb27213d22772161769b9745bc1 100644 (file)
@@ -1500,6 +1500,9 @@ static const struct devlink_param rvu_af_dl_params[] = {
                             BIT(DEVLINK_PARAM_CMODE_RUNTIME),
                             rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set,
                             rvu_af_dl_dwrr_mtu_validate),
+};
+
+static const struct devlink_param rvu_af_dl_param_exact_match[] = {
        DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
                             "npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,
                             BIT(DEVLINK_PARAM_CMODE_RUNTIME),
@@ -1556,7 +1559,6 @@ int rvu_register_dl(struct rvu *rvu)
 {
        struct rvu_devlink *rvu_dl;
        struct devlink *dl;
-       size_t size;
        int err;
 
        dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink),
@@ -1578,21 +1580,32 @@ int rvu_register_dl(struct rvu *rvu)
                goto err_dl_health;
        }
 
+       err = devlink_params_register(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
+       if (err) {
+               dev_err(rvu->dev,
+                       "devlink params register failed with error %d", err);
+               goto err_dl_health;
+       }
+
        /* Register exact match devlink only for CN10K-B */
-       size = ARRAY_SIZE(rvu_af_dl_params);
        if (!rvu_npc_exact_has_match_table(rvu))
-               size -= 1;
+               goto done;
 
-       err = devlink_params_register(dl, rvu_af_dl_params, size);
+       err = devlink_params_register(dl, rvu_af_dl_param_exact_match,
+                                     ARRAY_SIZE(rvu_af_dl_param_exact_match));
        if (err) {
                dev_err(rvu->dev,
-                       "devlink params register failed with error %d", err);
-               goto err_dl_health;
+                       "devlink exact match params register failed with error %d", err);
+               goto err_dl_exact_match;
        }
 
+done:
        devlink_register(dl);
        return 0;
 
+err_dl_exact_match:
+       devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
+
 err_dl_health:
        rvu_health_reporters_destroy(rvu);
        devlink_free(dl);
@@ -1605,8 +1618,14 @@ void rvu_unregister_dl(struct rvu *rvu)
        struct devlink *dl = rvu_dl->dl;
 
        devlink_unregister(dl);
-       devlink_params_unregister(dl, rvu_af_dl_params,
-                                 ARRAY_SIZE(rvu_af_dl_params));
+
+       devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
+
+       /* Unregister exact match devlink only for CN10K-B */
+       if (rvu_npc_exact_has_match_table(rvu))
+               devlink_params_unregister(dl, rvu_af_dl_param_exact_match,
+                                         ARRAY_SIZE(rvu_af_dl_param_exact_match));
+
        rvu_health_reporters_destroy(rvu);
        devlink_free(dl);
 }
index 88f8772a61cd527c2ab138fb5a996470a7dfd456..8a41ad8ca04f115de066a1bbc44f80939bdf73f4 100644 (file)
@@ -1012,7 +1012,6 @@ static void otx2_pool_refill_task(struct work_struct *work)
        rbpool = cq->rbpool;
        free_ptrs = cq->pool_ptrs;
 
-       get_cpu();
        while (cq->pool_ptrs) {
                if (otx2_alloc_rbuf(pfvf, rbpool, &bufptr)) {
                        /* Schedule a WQ if we fails to free atleast half of the
@@ -1032,7 +1031,6 @@ static void otx2_pool_refill_task(struct work_struct *work)
                pfvf->hw_ops->aura_freeptr(pfvf, qidx, bufptr + OTX2_HEAD_ROOM);
                cq->pool_ptrs--;
        }
-       put_cpu();
        cq->refill_task_sched = false;
 }
 
@@ -1370,7 +1368,6 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
        if (err)
                goto fail;
 
-       get_cpu();
        /* Allocate pointers and free them to aura/pool */
        for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
                pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
@@ -1394,7 +1391,6 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
        }
 
 err_mem:
-       put_cpu();
        return err ? -ENOMEM : 0;
 
 fail:
@@ -1435,21 +1431,18 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
        if (err)
                goto fail;
 
-       get_cpu();
        /* Allocate pointers and free them to aura/pool */
        for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
                pool = &pfvf->qset.pool[pool_id];
                for (ptr = 0; ptr < num_ptrs; ptr++) {
                        err = otx2_alloc_rbuf(pfvf, pool, &bufptr);
                        if (err)
-                               goto err_mem;
+                               return -ENOMEM;
                        pfvf->hw_ops->aura_freeptr(pfvf, pool_id,
                                                   bufptr + OTX2_HEAD_ROOM);
                }
        }
-err_mem:
-       put_cpu();
-       return err ? -ENOMEM : 0;
+       return 0;
 fail:
        otx2_mbox_reset(&pfvf->mbox.mbox, 0);
        otx2_aura_pool_free(pfvf);
index 5bee3c3a7ce43fef7224fd4265922ff5a8b7a400..3d22cc6a2804a8d43324245a8b65ab554ec6b540 100644 (file)
@@ -736,8 +736,10 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf)
        u64 ptrs[2];
 
        ptrs[1] = buf;
+       get_cpu();
        /* Free only one buffer at time during init and teardown */
        __cn10k_aura_freeptr(pfvf, aura, ptrs, 2);
+       put_cpu();
 }
 
 /* Alloc pointer from pool/aura */
index e3de9a53b2d9aa181092a9d81c06b6b6b237e390..d56eda6397a41ed25f96f4149a393925187f62fd 100644 (file)
@@ -3177,7 +3177,8 @@ static int mtk_open(struct net_device *dev)
        struct mtk_eth *eth = mac->hw;
        int i, err;
 
-       if (mtk_uses_dsa(dev) && !eth->prog) {
+       if ((mtk_uses_dsa(dev) && !eth->prog) &&
+           !(mac->id == 1 && MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_TRGMII))) {
                for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
                        struct metadata_dst *md_dst = eth->dsa_meta[i];
 
@@ -3194,7 +3195,8 @@ static int mtk_open(struct net_device *dev)
                }
        } else {
                /* Hardware special tag parsing needs to be disabled if at least
-                * one MAC does not use DSA.
+                * one MAC does not use DSA, or the second MAC of the MT7621 and
+                * MT7623 SoCs is being used.
                 */
                u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
                val &= ~MTK_CDMP_STAG_EN;
index 18a50529ce7b499dccd853d2a60eb0ee52b31597..2d9186d32bc0932e2d0262fdf0bbadbec9577bee 100644 (file)
 #define SGMII_SPEED_10                 FIELD_PREP(SGMII_SPEED_MASK, 0)
 #define SGMII_SPEED_100                        FIELD_PREP(SGMII_SPEED_MASK, 1)
 #define SGMII_SPEED_1000               FIELD_PREP(SGMII_SPEED_MASK, 2)
-#define SGMII_DUPLEX_FULL              BIT(4)
+#define SGMII_DUPLEX_HALF              BIT(4)
 #define SGMII_IF_MODE_BIT5             BIT(5)
 #define SGMII_REMOTE_FAULT_DIS         BIT(8)
 #define SGMII_CODE_SYNC_SET_VAL                BIT(9)
@@ -1036,11 +1036,13 @@ struct mtk_soc_data {
  * @regmap:            The register map pointing at the range used to setup
  *                     SGMII modes
  * @ana_rgc3:          The offset refers to register ANA_RGC3 related to regmap
+ * @interface:         Currently configured interface mode
  * @pcs:               Phylink PCS structure
  */
 struct mtk_pcs {
        struct regmap   *regmap;
        u32             ana_rgc3;
+       phy_interface_t interface;
        struct phylink_pcs pcs;
 };
 
index 269208a841c763b82a05e930084948f128477326..1ff024f42444b58640a093d64006d632ec13a6ab 100644 (file)
@@ -615,8 +615,7 @@ mtk_foe_entry_commit_subflow(struct mtk_ppe *ppe, struct mtk_flow_entry *entry,
        u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP;
        int type;
 
-       flow_info = kzalloc(offsetof(struct mtk_flow_entry, l2_data.end),
-                           GFP_ATOMIC);
+       flow_info = kzalloc(sizeof(*flow_info), GFP_ATOMIC);
        if (!flow_info)
                return;
 
index ea64fac1d425aaf5012be4ea65fe374a418eacdd..b5e432031340bf9928979e2612f11f22a11ba6c0 100644 (file)
@@ -279,7 +279,6 @@ struct mtk_flow_entry {
                struct {
                        struct mtk_flow_entry *base_flow;
                        struct hlist_node list;
-                       struct {} end;
                } l2_data;
        };
        struct rhash_head node;
index 5c286f2c9418f47ac456848471c8df5cf0679397..bb00de1003ac4355808b6805b3221270a7bfb909 100644 (file)
@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
        int advertise, link_timer;
        bool changed, use_an;
 
-       if (interface == PHY_INTERFACE_MODE_2500BASEX)
-               rgc3 = RG_PHY_SPEED_3_125G;
-       else
-               rgc3 = 0;
-
        advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
                                                             advertising);
        if (advertise < 0)
@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
                bmcr = 0;
        }
 
-       /* Configure the underlying interface speed */
-       regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
-                          RG_PHY_SPEED_3_125G, rgc3);
+       if (mpcs->interface != interface) {
+               /* PHYA power down */
+               regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
+                                  SGMII_PHYA_PWD, SGMII_PHYA_PWD);
+
+               if (interface == PHY_INTERFACE_MODE_2500BASEX)
+                       rgc3 = RG_PHY_SPEED_3_125G;
+               else
+                       rgc3 = 0;
+
+               /* Configure the underlying interface speed */
+               regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
+                                  RG_PHY_SPEED_3_125G, rgc3);
+
+               mpcs->interface = interface;
+       }
 
        /* Update the advertisement, noting whether it has changed */
        regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
        regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
                           SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
 
-       /* Release PHYA power down state */
-       regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
-                          SGMII_PHYA_PWD, 0);
+       /* Release PHYA power down state
+        * Only removing bit SGMII_PHYA_PWD isn't enough.
+        * There are cases when the SGMII_PHYA_PWD register contains 0x9 which
+        * prevents SGMII from working. The SGMII still shows link but no traffic
+        * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
+        * taken from a good working state of the SGMII interface.
+        * Unknown how much the QPHY needs but it is racy without a sleep.
+        * Tested on mt7622 & mt7986.
+        */
+       usleep_range(50, 100);
+       regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
 
        return changed;
 }
@@ -138,11 +154,11 @@ static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
                else
                        sgm_mode = SGMII_SPEED_1000;
 
-               if (duplex == DUPLEX_FULL)
-                       sgm_mode |= SGMII_DUPLEX_FULL;
+               if (duplex != DUPLEX_FULL)
+                       sgm_mode |= SGMII_DUPLEX_HALF;
 
                regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
-                                  SGMII_DUPLEX_FULL | SGMII_SPEED_MASK,
+                                  SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
                                   sgm_mode);
        }
 }
@@ -171,6 +187,8 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
                        return PTR_ERR(ss->pcs[i].regmap);
 
                ss->pcs[i].pcs.ops = &mtk_pcs_ops;
+               ss->pcs[i].pcs.poll = true;
+               ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
        }
 
        return 0;
index 6dac76fa58a3f158fdd5fc08cddeb94685c160c7..09d441ecb9f6d204e236f7e340e174a0842349bb 100644 (file)
@@ -637,7 +637,7 @@ mlx5e_htb_update_children(struct mlx5e_htb *htb, struct mlx5e_qos_node *node,
                if (child->bw_share == old_bw_share)
                        continue;
 
-               err_one = mlx5_qos_update_node(htb->mdev, child->hw_id, child->bw_share,
+               err_one = mlx5_qos_update_node(htb->mdev, child->bw_share,
                                               child->max_average_bw, child->hw_id);
                if (!err && err_one) {
                        err = err_one;
@@ -671,7 +671,7 @@ mlx5e_htb_node_modify(struct mlx5e_htb *htb, u16 classid, u64 rate, u64 ceil,
        mlx5e_htb_convert_rate(htb, rate, node->parent, &bw_share);
        mlx5e_htb_convert_ceil(htb, ceil, &max_average_bw);
 
-       err = mlx5_qos_update_node(htb->mdev, node->parent->hw_id, bw_share,
+       err = mlx5_qos_update_node(htb->mdev, bw_share,
                                   max_average_bw, node->hw_id);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a node.");
index 585bdc8383ee21fb6371757b66a6ee1bf3edd425..4ad19c98129440a00e1aef412c1145f66a5fd487 100644 (file)
@@ -578,7 +578,6 @@ int mlx5e_mpwrq_validate_xsk(struct mlx5_core_dev *mdev, struct mlx5e_params *pa
 {
        enum mlx5e_mpwrq_umr_mode umr_mode = mlx5e_mpwrq_umr_mode(mdev, xsk);
        u8 page_shift = mlx5e_mpwrq_page_shift(mdev, xsk);
-       bool unaligned = xsk ? xsk->unaligned : false;
        u16 max_mtu_pkts;
 
        if (!mlx5e_check_fragmented_striding_rq_cap(mdev, page_shift, umr_mode))
@@ -591,7 +590,7 @@ int mlx5e_mpwrq_validate_xsk(struct mlx5_core_dev *mdev, struct mlx5e_params *pa
         * needed number of WQEs exceeds the maximum.
         */
        max_mtu_pkts = min_t(u8, MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE,
-                            mlx5e_mpwrq_max_log_rq_pkts(mdev, page_shift, unaligned));
+                            mlx5e_mpwrq_max_log_rq_pkts(mdev, page_shift, xsk->unaligned));
        if (params->log_rq_mtu_frames > max_mtu_pkts) {
                mlx5_core_err(mdev, "Current RQ length %d is too big for XSK with given frame size %u\n",
                              1 << params->log_rq_mtu_frames, xsk->chunk_size);
index 1cbd2eb9d04f90ada8e6574ec409bdeaf96f24a4..f2c2c752bd1c345849d68245013feee7c3a4a2f9 100644 (file)
@@ -477,7 +477,6 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample,
        struct mlx5e_sample_flow *sample_flow;
        struct mlx5e_sample_attr *sample_attr;
        struct mlx5_flow_attr *pre_attr;
-       u32 tunnel_id = attr->tunnel_id;
        struct mlx5_eswitch *esw;
        u32 default_tbl_id;
        u32 obj_id;
@@ -522,7 +521,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample,
        restore_obj.sample.group_id = sample_attr->group_num;
        restore_obj.sample.rate = sample_attr->rate;
        restore_obj.sample.trunc_size = sample_attr->trunc_size;
-       restore_obj.sample.tunnel_id = tunnel_id;
+       restore_obj.sample.tunnel_id = attr->tunnel_id;
        err = mapping_add(esw->offloads.reg_c0_obj_pool, &restore_obj, &obj_id);
        if (err)
                goto err_obj_id;
@@ -548,7 +547,7 @@ mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample,
        /* For decap action, do decap in the original flow table instead of the
         * default flow table.
         */
-       if (tunnel_id)
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
                pre_attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
        pre_attr->modify_hdr = sample_flow->restore->modify_hdr;
        pre_attr->flags = MLX5_ATTR_FLAG_SAMPLE;
index a92e19c4c499d405aee95ad39d4853aa374b83bd..8bed9c361075471c5f90b1069d15b9cd3cb6dc53 100644 (file)
@@ -122,11 +122,8 @@ struct mlx5e_ipsec_aso {
        u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)];
        dma_addr_t dma_addr;
        struct mlx5_aso *aso;
-       /* IPsec ASO caches data on every query call,
-        * so in nested calls, we can use this boolean to save
-        * recursive calls to mlx5e_ipsec_aso_query()
-        */
-       u8 use_cache : 1;
+       /* Protect ASO WQ access, as it is global to whole IPsec */
+       spinlock_t lock;
 };
 
 struct mlx5e_ipsec {
index 8e3614218fc4fabc7bac9c60a0874c4234f12581..2461462b7b991c96bebf8b253079246adddfcc0d 100644 (file)
@@ -320,7 +320,6 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
        if (ret)
                goto unlock;
 
-       aso->use_cache = true;
        if (attrs->esn_trigger &&
            !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) {
                u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter);
@@ -333,7 +332,6 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
                    !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm) ||
                    !MLX5_GET(ipsec_aso, aso->ctx, remove_flow_enable))
                        xfrm_state_check_expire(sa_entry->x);
-       aso->use_cache = false;
 
 unlock:
        spin_unlock(&sa_entry->x->lock);
@@ -398,6 +396,7 @@ int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec)
                goto err_aso_create;
        }
 
+       spin_lock_init(&aso->lock);
        ipsec->nb.notifier_call = mlx5e_ipsec_event;
        mlx5_notifier_register(mdev, &ipsec->nb);
 
@@ -456,13 +455,12 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
        struct mlx5e_hw_objs *res;
        struct mlx5_aso_wqe *wqe;
        u8 ds_cnt;
+       int ret;
 
        lockdep_assert_held(&sa_entry->x->lock);
-       if (aso->use_cache)
-               return 0;
-
        res = &mdev->mlx5e_res.hw_objs;
 
+       spin_lock_bh(&aso->lock);
        memset(aso->ctx, 0, sizeof(aso->ctx));
        wqe = mlx5_aso_get_wqe(aso->aso);
        ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS);
@@ -477,7 +475,9 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
        mlx5e_ipsec_aso_copy(ctrl, data);
 
        mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl);
-       return mlx5_aso_poll_cq(aso->aso, false);
+       ret = mlx5_aso_poll_cq(aso->aso, false);
+       spin_unlock_bh(&aso->lock);
+       return ret;
 }
 
 void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
index dbadaf166487962d94fa30f5bb7f7ea0be9397e9..243d5d7750beb54cba6b9f562d58fa8cbdcca6c2 100644 (file)
@@ -166,6 +166,7 @@ struct mlx5_fs_chains *mlx5e_nic_chains(struct mlx5e_tc_table *tc)
  * it's different than the ht->mutex here.
  */
 static struct lock_class_key tc_ht_lock_key;
+static struct lock_class_key tc_ht_wq_key;
 
 static void mlx5e_put_flow_tunnel_id(struct mlx5e_tc_flow *flow);
 static void free_flow_post_acts(struct mlx5e_tc_flow *flow);
@@ -5182,6 +5183,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
                return err;
 
        lockdep_set_class(&tc->ht.mutex, &tc_ht_lock_key);
+       lockdep_init_map(&tc->ht.run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0);
 
        mapping_id = mlx5_query_nic_system_image_guid(dev);
 
@@ -5288,6 +5290,7 @@ int mlx5e_tc_ht_init(struct rhashtable *tc_ht)
                return err;
 
        lockdep_set_class(&tc_ht->mutex, &tc_ht_lock_key);
+       lockdep_init_map(&tc_ht->run_work.lockdep_map, "tc_ht_wq_key", &tc_ht_wq_key, 0);
 
        return 0;
 }
index 4f8a24d84a86a2ba516fc3cc0787b20fe76df2ce..75015d370922e61002798d4d08a37427326690a9 100644 (file)
@@ -22,15 +22,13 @@ struct mlx5_esw_rate_group {
 };
 
 static int esw_qos_tsar_config(struct mlx5_core_dev *dev, u32 *sched_ctx,
-                              u32 parent_ix, u32 tsar_ix,
-                              u32 max_rate, u32 bw_share)
+                              u32 tsar_ix, u32 max_rate, u32 bw_share)
 {
        u32 bitmask = 0;
 
        if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
                return -EOPNOTSUPP;
 
-       MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_ix);
        MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
        MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
        bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
@@ -51,7 +49,7 @@ static int esw_qos_group_config(struct mlx5_eswitch *esw, struct mlx5_esw_rate_g
        int err;
 
        err = esw_qos_tsar_config(dev, sched_ctx,
-                                 esw->qos.root_tsar_ix, group->tsar_ix,
+                                 group->tsar_ix,
                                  max_rate, bw_share);
        if (err)
                NL_SET_ERR_MSG_MOD(extack, "E-Switch modify group TSAR element failed");
@@ -67,23 +65,13 @@ static int esw_qos_vport_config(struct mlx5_eswitch *esw,
                                struct netlink_ext_ack *extack)
 {
        u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
-       struct mlx5_esw_rate_group *group = vport->qos.group;
        struct mlx5_core_dev *dev = esw->dev;
-       u32 parent_tsar_ix;
-       void *vport_elem;
        int err;
 
        if (!vport->qos.enabled)
                return -EIO;
 
-       parent_tsar_ix = group ? group->tsar_ix : esw->qos.root_tsar_ix;
-       MLX5_SET(scheduling_context, sched_ctx, element_type,
-                SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
-       vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
-                                 element_attributes);
-       MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
-
-       err = esw_qos_tsar_config(dev, sched_ctx, parent_tsar_ix, vport->qos.esw_tsar_ix,
+       err = esw_qos_tsar_config(dev, sched_ctx, vport->qos.esw_tsar_ix,
                                  max_rate, bw_share);
        if (err) {
                esw_warn(esw->dev,
index 0dfd5742c6fe9f8688f7bc39bb27c82923a684af..9daf55e90367b17c8d975e862dfc019ad4f0db49 100644 (file)
@@ -1464,6 +1464,7 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
        mlx5_lag_disable_change(esw->dev);
        down_write(&esw->mode_lock);
        mlx5_eswitch_disable_locked(esw);
+       esw->mode = MLX5_ESWITCH_LEGACY;
        up_write(&esw->mode_lock);
        mlx5_lag_enable_change(esw->dev);
 }
index 96417c5feed76b3aa9d4f48fed5cb60f6d18e72e..879555ba847ddcd6174a2e3036d38eb7a5639c88 100644 (file)
@@ -677,6 +677,7 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work)
        mutex_lock(&dev->intf_state_mutex);
        if (test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags)) {
                mlx5_core_err(dev, "health works are not permitted at this stage\n");
+               mutex_unlock(&dev->intf_state_mutex);
                return;
        }
        mutex_unlock(&dev->intf_state_mutex);
index df134f6d32dc583a93f96f24cef5ccfc1a4cfd23..3d5f2a4b1fed4f8d5d6bf235783e4df06c0eb757 100644 (file)
@@ -2098,7 +2098,7 @@ static void mlx5_core_verify_params(void)
        }
 }
 
-static int __init init(void)
+static int __init mlx5_init(void)
 {
        int err;
 
@@ -2133,7 +2133,7 @@ err_debug:
        return err;
 }
 
-static void __exit cleanup(void)
+static void __exit mlx5_cleanup(void)
 {
        mlx5e_cleanup();
        mlx5_sf_driver_unregister();
@@ -2141,5 +2141,5 @@ static void __exit cleanup(void)
        mlx5_unregister_debugfs();
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(mlx5_init);
+module_exit(mlx5_cleanup);
index 0777be24a3074a7a078b091cb30b93d4d33df9e1..8bce730b5c5befdc4e553810eae0ab1400fe836f 100644 (file)
@@ -62,13 +62,12 @@ int mlx5_qos_create_root_node(struct mlx5_core_dev *mdev, u32 *id)
        return mlx5_qos_create_inner_node(mdev, MLX5_QOS_DEFAULT_DWRR_UID, 0, 0, id);
 }
 
-int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 parent_id,
+int mlx5_qos_update_node(struct mlx5_core_dev *mdev,
                         u32 bw_share, u32 max_avg_bw, u32 id)
 {
        u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
        u32 bitmask = 0;
 
-       MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id);
        MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
        MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_avg_bw);
 
index 125e4e47e6f71f2ecf31a960d5eca467ab8a5b92..624ce822b7f596e1c6ca1ce04b0bf0606e894abc 100644 (file)
@@ -23,7 +23,7 @@ int mlx5_qos_create_leaf_node(struct mlx5_core_dev *mdev, u32 parent_id,
 int mlx5_qos_create_inner_node(struct mlx5_core_dev *mdev, u32 parent_id,
                               u32 bw_share, u32 max_avg_bw, u32 *id);
 int mlx5_qos_create_root_node(struct mlx5_core_dev *mdev, u32 *id);
-int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 parent_id, u32 bw_share,
+int mlx5_qos_update_node(struct mlx5_core_dev *mdev, u32 bw_share,
                         u32 max_avg_bw, u32 id);
 int mlx5_qos_destroy_node(struct mlx5_core_dev *mdev, u32 id);
 
index 5314c064ceae736c3f1e18eb336939744dd47a27..55b484b1056275c2b2409c5b14f82853c401eb95 100644 (file)
@@ -608,12 +608,12 @@ allocate_new:
                lan966x_fdma_rx_reload(rx);
        }
 
-       if (counter < weight && napi_complete_done(napi, counter))
-               lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
-
        if (redirect)
                xdp_do_flush();
 
+       if (counter < weight && napi_complete_done(napi, counter))
+               lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
+
        return counter;
 }
 
index cadde20505ba068953112950532b42d3896009e9..580c91d24a5284e72066c9a3e32092454803c56d 100644 (file)
@@ -1043,11 +1043,6 @@ static int lan966x_probe(struct platform_device *pdev)
                lan966x->base_mac[5] &= 0xf0;
        }
 
-       ports = device_get_named_child_node(&pdev->dev, "ethernet-ports");
-       if (!ports)
-               return dev_err_probe(&pdev->dev, -ENODEV,
-                                    "no ethernet-ports child found\n");
-
        err = lan966x_create_targets(pdev, lan966x);
        if (err)
                return dev_err_probe(&pdev->dev, err,
@@ -1125,6 +1120,11 @@ static int lan966x_probe(struct platform_device *pdev)
                }
        }
 
+       ports = device_get_named_child_node(&pdev->dev, "ethernet-ports");
+       if (!ports)
+               return dev_err_probe(&pdev->dev, -ENODEV,
+                                    "no ethernet-ports child found\n");
+
        /* init switch */
        lan966x_init(lan966x);
        lan966x_stats_init(lan966x);
@@ -1162,6 +1162,8 @@ static int lan966x_probe(struct platform_device *pdev)
                        goto cleanup_ports;
        }
 
+       fwnode_handle_put(ports);
+
        lan966x_mdb_init(lan966x);
        err = lan966x_fdb_init(lan966x);
        if (err)
@@ -1191,6 +1193,7 @@ cleanup_fdb:
        lan966x_fdb_deinit(lan966x);
 
 cleanup_ports:
+       fwnode_handle_put(ports);
        fwnode_handle_put(portnp);
 
        lan966x_cleanup_ports(lan966x);
index e708c2d049839f27b578dab501dd47c5b9061bc4..b144f2237748e7d9a2d052010cf57a59676edd2f 100644 (file)
@@ -1259,13 +1259,20 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
                gic->handler = NULL;
                gic->arg = NULL;
 
+               if (!i)
+                       snprintf(gic->name, MANA_IRQ_NAME_SZ, "mana_hwc@pci:%s",
+                                pci_name(pdev));
+               else
+                       snprintf(gic->name, MANA_IRQ_NAME_SZ, "mana_q%d@pci:%s",
+                                i - 1, pci_name(pdev));
+
                irq = pci_irq_vector(pdev, i);
                if (irq < 0) {
                        err = irq;
                        goto free_mask;
                }
 
-               err = request_irq(irq, mana_gd_intr, 0, "mana_intr", gic);
+               err = request_irq(irq, mana_gd_intr, 0, gic->name, gic);
                if (err)
                        goto free_mask;
                irq_set_affinity_and_hint(irq, req_mask);
index a8678d5612eeaf80c2b75290330b11661f1256cd..060a77f2265d9a12e0c675a1a43e9f06ba95a1b2 100644 (file)
@@ -460,6 +460,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
                            sizeof(struct nfp_tun_neigh_v4);
        unsigned long cookie = (unsigned long)neigh;
        struct nfp_flower_priv *priv = app->priv;
+       struct nfp_tun_neigh_lag lag_info;
        struct nfp_neigh_entry *nn_entry;
        u32 port_id;
        u8 mtype;
@@ -468,6 +469,11 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
        if (!port_id)
                return;
 
+       if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT) {
+               memset(&lag_info, 0, sizeof(struct nfp_tun_neigh_lag));
+               nfp_flower_lag_get_info_from_netdev(app, netdev, &lag_info);
+       }
+
        spin_lock_bh(&priv->predt_lock);
        nn_entry = rhashtable_lookup_fast(&priv->neigh_table, &cookie,
                                          neigh_table_params);
@@ -515,7 +521,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
                neigh_ha_snapshot(common->dst_addr, neigh, netdev);
 
                if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT)
-                       nfp_flower_lag_get_info_from_netdev(app, netdev, lag);
+                       memcpy(lag, &lag_info, sizeof(struct nfp_tun_neigh_lag));
                common->port_id = cpu_to_be32(port_id);
 
                if (rhashtable_insert_fast(&priv->neigh_table,
index 7c2af482192d740c420b25799bb48ad467b8e511..cb1746bc0e0c5d65f8fb546cf1236b9b4d16e0e4 100644 (file)
@@ -1438,6 +1438,10 @@ int qede_poll(struct napi_struct *napi, int budget)
        rx_work_done = (likely(fp->type & QEDE_FASTPATH_RX) &&
                        qede_has_rx_work(fp->rxq)) ?
                        qede_rx_int(fp, budget) : 0;
+
+       if (fp->xdp_xmit & QEDE_XDP_REDIRECT)
+               xdp_do_flush();
+
        /* Handle case where we are called by netpoll with a budget of 0 */
        if (rx_work_done < budget || !budget) {
                if (!qede_poll_is_more_work(fp)) {
@@ -1457,9 +1461,6 @@ int qede_poll(struct napi_struct *napi, int budget)
                qede_update_tx_producer(fp->xdp_tx);
        }
 
-       if (fp->xdp_xmit & QEDE_XDP_REDIRECT)
-               xdp_do_flush_map();
-
        return rx_work_done;
 }
 
index b4e0fc7f65bdfed65e376351f0bf7b30cb3734c6..0f54849a38235fe7e564f7fe870d501201f6fbc5 100644 (file)
@@ -1101,14 +1101,14 @@ static void ravb_error_interrupt(struct net_device *ndev)
        ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS);
        if (eis & EIS_QFS) {
                ris2 = ravb_read(ndev, RIS2);
-               ravb_write(ndev, ~(RIS2_QFF0 | RIS2_RFFF | RIS2_RESERVED),
+               ravb_write(ndev, ~(RIS2_QFF0 | RIS2_QFF1 | RIS2_RFFF | RIS2_RESERVED),
                           RIS2);
 
                /* Receive Descriptor Empty int */
                if (ris2 & RIS2_QFF0)
                        priv->stats[RAVB_BE].rx_over_errors++;
 
-                   /* Receive Descriptor Empty int */
+               /* Receive Descriptor Empty int */
                if (ris2 & RIS2_QFF1)
                        priv->stats[RAVB_NC].rx_over_errors++;
 
@@ -2973,6 +2973,9 @@ static int __maybe_unused ravb_suspend(struct device *dev)
        else
                ret = ravb_close(ndev);
 
+       if (priv->info->ccc_gac)
+               ravb_ptp_stop(ndev);
+
        return ret;
 }
 
@@ -3011,6 +3014,9 @@ static int __maybe_unused ravb_resume(struct device *dev)
        /* Restore descriptor base address table */
        ravb_write(ndev, priv->desc_bat_dma, DBAT);
 
+       if (priv->info->ccc_gac)
+               ravb_ptp_init(ndev, priv->pdev);
+
        if (netif_running(ndev)) {
                if (priv->wol_enabled) {
                        ret = ravb_wol_restore(ndev);
index 6441892636dba2fd567c4f58225816f797b93acb..2370c7797a0aad7e4635da178a1253355a447d04 100644 (file)
@@ -1074,8 +1074,11 @@ static struct device_node *rswitch_get_port_node(struct rswitch_device *rdev)
                        port = NULL;
                        goto out;
                }
-               if (index == rdev->etha->index)
+               if (index == rdev->etha->index) {
+                       if (!of_device_is_available(port))
+                               port = NULL;
                        break;
+               }
        }
 
 out:
@@ -1106,7 +1109,7 @@ static int rswitch_etha_get_params(struct rswitch_device *rdev)
 
        port = rswitch_get_port_node(rdev);
        if (!port)
-               return -ENODEV;
+               return 0;       /* ignored */
 
        err = of_get_phy_mode(port, &rdev->etha->phy_interface);
        of_node_put(port);
@@ -1324,13 +1327,13 @@ static int rswitch_ether_port_init_all(struct rswitch_private *priv)
 {
        int i, err;
 
-       for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
+       rswitch_for_each_enabled_port(priv, i) {
                err = rswitch_ether_port_init_one(priv->rdev[i]);
                if (err)
                        goto err_init_one;
        }
 
-       for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
+       rswitch_for_each_enabled_port(priv, i) {
                err = rswitch_serdes_init(priv->rdev[i]);
                if (err)
                        goto err_serdes;
@@ -1339,12 +1342,12 @@ static int rswitch_ether_port_init_all(struct rswitch_private *priv)
        return 0;
 
 err_serdes:
-       for (i--; i >= 0; i--)
+       rswitch_for_each_enabled_port_continue_reverse(priv, i)
                rswitch_serdes_deinit(priv->rdev[i]);
        i = RSWITCH_NUM_PORTS;
 
 err_init_one:
-       for (i--; i >= 0; i--)
+       rswitch_for_each_enabled_port_continue_reverse(priv, i)
                rswitch_ether_port_deinit_one(priv->rdev[i]);
 
        return err;
@@ -1608,6 +1611,7 @@ static int rswitch_device_alloc(struct rswitch_private *priv, int index)
        netif_napi_add(ndev, &rdev->napi, rswitch_poll);
 
        port = rswitch_get_port_node(rdev);
+       rdev->disabled = !port;
        err = of_get_ethdev_address(port, ndev);
        of_node_put(port);
        if (err) {
@@ -1707,16 +1711,16 @@ static int rswitch_init(struct rswitch_private *priv)
        if (err)
                goto err_ether_port_init_all;
 
-       for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
+       rswitch_for_each_enabled_port(priv, i) {
                err = register_netdev(priv->rdev[i]->ndev);
                if (err) {
-                       for (i--; i >= 0; i--)
+                       rswitch_for_each_enabled_port_continue_reverse(priv, i)
                                unregister_netdev(priv->rdev[i]->ndev);
                        goto err_register_netdev;
                }
        }
 
-       for (i = 0; i < RSWITCH_NUM_PORTS; i++)
+       rswitch_for_each_enabled_port(priv, i)
                netdev_info(priv->rdev[i]->ndev, "MAC address %pM\n",
                            priv->rdev[i]->ndev->dev_addr);
 
index edbdd1b98d3d9c5261b8e0e02d7fcab1d7a90ad9..49efb0f31c77ace15d29c0d7c747ceca86424337 100644 (file)
 #define RSWITCH_MAX_NUM_QUEUES 128
 
 #define RSWITCH_NUM_PORTS      3
+#define rswitch_for_each_enabled_port(priv, i)         \
+       for (i = 0; i < RSWITCH_NUM_PORTS; i++)         \
+               if (priv->rdev[i]->disabled)            \
+                       continue;                       \
+               else
+
+#define rswitch_for_each_enabled_port_continue_reverse(priv, i)        \
+       for (i--; i >= 0; i--)                                  \
+               if (priv->rdev[i]->disabled)                    \
+                       continue;                               \
+               else
 
 #define TX_RING_SIZE           1024
 #define RX_RING_SIZE           1024
@@ -938,6 +949,7 @@ struct rswitch_device {
        struct rswitch_gwca_queue *tx_queue;
        struct rswitch_gwca_queue *rx_queue;
        u8 ts_tag;
+       bool disabled;
 
        int port;
        struct rswitch_etha *etha;
index 0556542d7a6b6446e0d38c8fcd09123b1cd9f23e..3a86f1213a05173568265d362506caa6bb1699bb 100644 (file)
@@ -1003,8 +1003,11 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
        /* Determine netdevice features */
        net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
                              NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL);
-       if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
+       if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) {
                net_dev->features |= NETIF_F_TSO6;
+               if (efx_has_cap(efx, TX_TSO_V2_ENCAP))
+                       net_dev->hw_enc_features |= NETIF_F_TSO6;
+       }
        /* Check whether device supports TSO */
        if (!efx->type->tso_versions || !efx->type->tso_versions(efx))
                net_dev->features &= ~NETIF_F_ALL_TSO;
index 835caa15d55fff9d97f6007505c0e5da4109ae9d..732774645c1a680b0365e7df02fbe8bea4a6c695 100644 (file)
@@ -560,6 +560,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
        plat_dat->has_gmac4 = 1;
        plat_dat->pmt = 1;
        plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
+       if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
+               plat_dat->rx_clk_runs_in_lpi = 1;
 
        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
        if (ret)
index 9c2d40f853ed0429d19d2ac0d647640f29dda878..413f660172199c7b893072befd3dce0170a43cc2 100644 (file)
@@ -186,11 +186,25 @@ static void dwmac5_handle_dma_err(struct net_device *ndev,
 int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp,
                              struct stmmac_safety_feature_cfg *safety_feat_cfg)
 {
+       struct stmmac_safety_feature_cfg all_safety_feats = {
+               .tsoee = 1,
+               .mrxpee = 1,
+               .mestee = 1,
+               .mrxee = 1,
+               .mtxee = 1,
+               .epsi = 1,
+               .edpp = 1,
+               .prtyen = 1,
+               .tmouten = 1,
+       };
        u32 value;
 
        if (!asp)
                return -EINVAL;
 
+       if (!safety_feat_cfg)
+               safety_feat_cfg = &all_safety_feats;
+
        /* 1. Enable Safety Features */
        value = readl(ioaddr + MTL_ECC_CONTROL);
        value |= MEEAO; /* MTL ECC Error Addr Status Override */
index f453b0d093663d5db152d217f8376943e3ce5cc1..35c8dd92d3692fb7f19645b2d58b4a4b639cd3e9 100644 (file)
@@ -551,16 +551,16 @@ static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data)
                p = (char *)priv + offsetof(struct stmmac_priv,
                                            xstats.txq_stats[q].tx_pkt_n);
                for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) {
-                       *data++ = (*(u64 *)p);
-                       p += sizeof(u64 *);
+                       *data++ = (*(unsigned long *)p);
+                       p += sizeof(unsigned long);
                }
        }
        for (q = 0; q < rx_cnt; q++) {
                p = (char *)priv + offsetof(struct stmmac_priv,
                                            xstats.rxq_stats[q].rx_pkt_n);
                for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) {
-                       *data++ = (*(u64 *)p);
-                       p += sizeof(u64 *);
+                       *data++ = (*(unsigned long *)p);
+                       p += sizeof(unsigned long);
                }
        }
 }
index c6951c976f5ddb2b67dc760bbb433c871c3efab4..1a5b8dab5e9b65e0ebf634fc6d9691952c148acc 100644 (file)
@@ -1080,7 +1080,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
 
        stmmac_mac_set(priv, priv->ioaddr, true);
        if (phy && priv->dma_cap.eee) {
-               priv->eee_active = phy_init_eee(phy, 1) >= 0;
+               priv->eee_active =
+                       phy_init_eee(phy, !priv->plat->rx_clk_runs_in_lpi) >= 0;
                priv->eee_enabled = stmmac_eee_init(priv);
                priv->tx_lpi_enabled = priv->eee_enabled;
                stmmac_set_eee_pls(priv, priv->hw, true);
@@ -1150,6 +1151,11 @@ static int stmmac_init_phy(struct net_device *dev)
                int addr = priv->plat->phy_addr;
                struct phy_device *phydev;
 
+               if (addr < 0) {
+                       netdev_err(priv->dev, "no phy found\n");
+                       return -ENODEV;
+               }
+
                phydev = mdiobus_get_phy(priv->mii, addr);
                if (!phydev) {
                        netdev_err(priv->dev, "no phy at addr %d\n", addr);
index 9352dad58996d831e596939c94e86daf0524d9a2..e02d1e3ef672a3070349dcd6e6f8938241cf0f61 100644 (file)
@@ -987,9 +987,6 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
 void netvsc_dma_unmap(struct hv_device *hv_dev,
                      struct hv_netvsc_packet *packet)
 {
-       u32 page_count = packet->cp_partial ?
-               packet->page_buf_cnt - packet->rmsg_pgcnt :
-               packet->page_buf_cnt;
        int i;
 
        if (!hv_is_isolation_supported())
@@ -998,7 +995,7 @@ void netvsc_dma_unmap(struct hv_device *hv_dev,
        if (!packet->dma_range)
                return;
 
-       for (i = 0; i < page_count; i++)
+       for (i = 0; i < packet->page_buf_cnt; i++)
                dma_unmap_single(&hv_dev->device, packet->dma_range[i].dma,
                                 packet->dma_range[i].mapping_size,
                                 DMA_TO_DEVICE);
@@ -1028,9 +1025,7 @@ static int netvsc_dma_map(struct hv_device *hv_dev,
                          struct hv_netvsc_packet *packet,
                          struct hv_page_buffer *pb)
 {
-       u32 page_count =  packet->cp_partial ?
-               packet->page_buf_cnt - packet->rmsg_pgcnt :
-               packet->page_buf_cnt;
+       u32 page_count = packet->page_buf_cnt;
        dma_addr_t dma;
        int i;
 
index d458a35839cce9efff1a61ef60ff8f30a451d747..c1b3977e1ae48463a76e6c1e9c694ba24bf49411 100644 (file)
@@ -127,6 +127,16 @@ out_power_put:
        return IRQ_HANDLED;
 }
 
+void ipa_interrupt_irq_disable(struct ipa *ipa)
+{
+       disable_irq(ipa->interrupt->irq);
+}
+
+void ipa_interrupt_irq_enable(struct ipa *ipa)
+{
+       enable_irq(ipa->interrupt->irq);
+}
+
 /* Common function used to enable/disable TX_SUSPEND for an endpoint */
 static void ipa_interrupt_suspend_control(struct ipa_interrupt *interrupt,
                                          u32 endpoint_id, bool enable)
index f31fd9965fdc678a38e5f1223d28233a773007e1..8a1bd5b893932badac38a6669a0fc48fc4da80b2 100644 (file)
@@ -85,6 +85,22 @@ void ipa_interrupt_suspend_clear_all(struct ipa_interrupt *interrupt);
  */
 void ipa_interrupt_simulate_suspend(struct ipa_interrupt *interrupt);
 
+/**
+ * ipa_interrupt_irq_enable() - Enable IPA interrupts
+ * @ipa:       IPA pointer
+ *
+ * This enables the IPA interrupt line
+ */
+void ipa_interrupt_irq_enable(struct ipa *ipa);
+
+/**
+ * ipa_interrupt_irq_disable() - Disable IPA interrupts
+ * @ipa:       IPA pointer
+ *
+ * This disables the IPA interrupt line
+ */
+void ipa_interrupt_irq_disable(struct ipa *ipa);
+
 /**
  * ipa_interrupt_config() - Configure the IPA interrupt framework
  * @ipa:       IPA pointer
index 8420f93128a268cce757f93dcaaf6a7979a3c0cd..8057be8cda8013457a8c4e83ede340eaff07bbf0 100644 (file)
@@ -181,6 +181,17 @@ static int ipa_suspend(struct device *dev)
 
        __set_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags);
 
+       /* Increment the disable depth to ensure that the IRQ won't
+        * be re-enabled until the matching _enable call in
+        * ipa_resume(). We do this to ensure that the interrupt
+        * handler won't run whilst PM runtime is disabled.
+        *
+        * Note that disabling the IRQ is NOT the same as disabling
+        * irq wake. If wakeup is enabled for the IPA then the IRQ
+        * will still cause the system to wake up, see irq_set_irq_wake().
+        */
+       ipa_interrupt_irq_disable(ipa);
+
        return pm_runtime_force_suspend(dev);
 }
 
@@ -193,6 +204,12 @@ static int ipa_resume(struct device *dev)
 
        __clear_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags);
 
+       /* Now that PM runtime is enabled again it's safe
+        * to turn the IRQ back on and process any data
+        * that was received during suspend.
+        */
+       ipa_interrupt_irq_enable(ipa);
+
        return ret;
 }
 
index 4a2e94faf57e2f37980dbedc620743ce1a9fcbbe..c4542ecf5623055025d692915f96c1dcf42c7840 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
@@ -150,6 +151,7 @@ static const struct clk_ops g12a_ephy_pll_ops = {
 
 static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv)
 {
+       u32 value;
        int ret;
 
        /* Enable the phy clock */
@@ -163,18 +165,25 @@ static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv)
 
        /* Initialize ephy control */
        writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0);
-       writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
-              FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
-              FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
-              PHY_CNTL1_CLK_EN |
-              PHY_CNTL1_CLKFREQ |
-              PHY_CNTL1_PHY_ENB,
-              priv->regs + ETH_PHY_CNTL1);
+
+       /* Make sure we get a 0 -> 1 transition on the enable bit */
+       value = FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
+               FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
+               FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
+               PHY_CNTL1_CLK_EN |
+               PHY_CNTL1_CLKFREQ;
+       writel(value, priv->regs + ETH_PHY_CNTL1);
        writel(PHY_CNTL2_USE_INTERNAL |
               PHY_CNTL2_SMI_SRC_MAC |
               PHY_CNTL2_RX_CLK_EPHY,
               priv->regs + ETH_PHY_CNTL2);
 
+       value |= PHY_CNTL1_PHY_ENB;
+       writel(value, priv->regs + ETH_PHY_CNTL1);
+
+       /* The phy needs a bit of time to power up */
+       mdelay(10);
+
        return 0;
 }
 
index a6f05e35d91f2c6e0afefdfcadb70b6bcec02185..b7cb71817780ce8c2c25b05f231f5b24ba1d612c 100644 (file)
@@ -233,7 +233,8 @@ static int dp83822_config_intr(struct phy_device *phydev)
                                DP83822_ENERGY_DET_INT_EN |
                                DP83822_LINK_QUAL_INT_EN);
 
-               if (!dp83822->fx_enabled)
+               /* Private data pointer is NULL on DP83825/26 */
+               if (!dp83822 || !dp83822->fx_enabled)
                        misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
                                       DP83822_DUP_MODE_CHANGE_INT_EN |
                                       DP83822_SPEED_CHANGED_INT_EN;
@@ -253,7 +254,8 @@ static int dp83822_config_intr(struct phy_device *phydev)
                                DP83822_PAGE_RX_INT_EN |
                                DP83822_EEE_ERROR_CHANGE_INT_EN);
 
-               if (!dp83822->fx_enabled)
+               /* Private data pointer is NULL on DP83825/26 */
+               if (!dp83822 || !dp83822->fx_enabled)
                        misr_status |= DP83822_ANEG_ERR_INT_EN |
                                       DP83822_WOL_PKT_INT_EN;
 
index 1cd604cd1fa1b15f2a8be344dcf7ba0443bd78c3..16e021b477f0636d630f8e342234e84bab0440cf 100644 (file)
@@ -108,7 +108,12 @@ EXPORT_SYMBOL(mdiobus_unregister_device);
 
 struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
 {
-       struct mdio_device *mdiodev = bus->mdio_map[addr];
+       struct mdio_device *mdiodev;
+
+       if (addr < 0 || addr >= ARRAY_SIZE(bus->mdio_map))
+               return NULL;
+
+       mdiodev = bus->mdio_map[addr];
 
        if (!mdiodev)
                return NULL;
index c49062ad72c6c6922e18a26c68c2d96627da906e..5e41658b1e2fa18c7362c26ca8df9c849d34eafc 100644 (file)
@@ -271,6 +271,8 @@ static struct phy_driver meson_gxl_phy[] = {
                .handle_interrupt = meson_gxl_handle_interrupt,
                .suspend        = genphy_suspend,
                .resume         = genphy_resume,
+               .read_mmd       = genphy_read_mmd_unsupported,
+               .write_mmd      = genphy_write_mmd_unsupported,
        },
 };
 
index 716870a4499c557eb616389739dc17376f0cefe4..607aa786c8cb4eb4a34fbe6c228cd3b18cb9282c 100644 (file)
@@ -1517,7 +1517,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
         * another mac interface, so we should create a device link between
         * phy dev and mac dev.
         */
-       if (phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
+       if (dev && phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
                phydev->devlink = device_link_add(dev->dev.parent, &phydev->mdio.dev,
                                                  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
 
index fcd43d62d86bcbc2b19567d83541de6248c3c4f8..d10606f257c43345e1d293dd462cdf77fc37497b 100644 (file)
@@ -1044,7 +1044,6 @@ static int team_port_enter(struct team *team, struct team_port *port)
                        goto err_port_enter;
                }
        }
-       port->dev->priv_flags |= IFF_NO_ADDRCONF;
 
        return 0;
 
@@ -1058,7 +1057,6 @@ static void team_port_leave(struct team *team, struct team_port *port)
 {
        if (team->ops.port_leave)
                team->ops.port_leave(team, port);
-       port->dev->priv_flags &= ~IFF_NO_ADDRCONF;
        dev_put(team->dev);
 }
 
index 5a53e63d33a60995ea8023474e664f6fc14017a5..3164451e1010cc80a67e2fddc89a9e59a6721cab 100644 (file)
@@ -413,7 +413,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                /* ignore the CRC length */
                len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 
-               if (len > ETH_FRAME_LEN || len > skb->len)
+               if (len > ETH_FRAME_LEN || len > skb->len || len < 0)
                        return 0;
 
                /* the last packet of current skb */
index 7723b2a49d8ecc84ff10568dd98732657f492882..61e33e4dd0cd66f689863b5d5f33fd980124ae09 100644 (file)
@@ -1677,13 +1677,13 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
 
        received = virtnet_receive(rq, budget, &xdp_xmit);
 
+       if (xdp_xmit & VIRTIO_XDP_REDIR)
+               xdp_do_flush();
+
        /* Out of packets? */
        if (received < budget)
                virtqueue_napi_complete(napi, rq->vq, received);
 
-       if (xdp_xmit & VIRTIO_XDP_REDIR)
-               xdp_do_flush();
-
        if (xdp_xmit & VIRTIO_XDP_TX) {
                sq = virtnet_xdp_get_sq(vi);
                if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) {
@@ -1877,8 +1877,10 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
         */
        if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
                netif_stop_subqueue(dev, qnum);
-               if (!use_napi &&
-                   unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
+               if (use_napi) {
+                       if (unlikely(!virtqueue_enable_cb_delayed(sq->vq)))
+                               virtqueue_napi_schedule(&sq->napi, sq->vq);
+               } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
                        free_old_xmit_skbs(sq, false);
                        if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
@@ -2156,8 +2158,8 @@ static int virtnet_close(struct net_device *dev)
        cancel_delayed_work_sync(&vi->refill);
 
        for (i = 0; i < vi->max_queue_pairs; i++) {
-               xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
                napi_disable(&vi->rq[i].napi);
+               xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
                virtnet_napi_tx_disable(&vi->sq[i].napi);
        }
 
index 22edea6ca4b817b55bfcb7c0a25a8c5d23ceec5c..1c53b5546927052a336bcefabd6876c999f6f1c2 100644 (file)
@@ -1243,9 +1243,11 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
 free_dev:
        free_netdev(dev);
 undo_uhdlc_init:
-       iounmap(utdm->siram);
+       if (utdm)
+               iounmap(utdm->siram);
 unmap_si_regs:
-       iounmap(utdm->si_regs);
+       if (utdm)
+               iounmap(utdm->si_regs);
 free_utdm:
        if (uhdlc_priv->tsa)
                kfree(utdm);
index bff3128c2f261c53a183bec1005d2a7a54b89980..b115902eb475e9ee4cb228f72ed6bdaab3fcfdcc 100644 (file)
@@ -7937,6 +7937,9 @@ cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
 
+       if (chan->flags & IEEE80211_CHAN_DISABLED)
+               return -EINVAL;
+
        /* set_channel */
        chspec = channel_to_chanspec(&cfg->d11inf, chan);
        if (chspec != INVCHANSPEC) {
@@ -7961,7 +7964,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
        struct brcmf_dump_survey survey = {};
        struct ieee80211_supported_band *band;
-       struct ieee80211_channel *chan;
+       enum nl80211_band band_id;
        struct cca_msrmnt_query req;
        u32 noise;
        int err;
@@ -7974,26 +7977,25 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
                return -EBUSY;
        }
 
-       band = wiphy->bands[NL80211_BAND_2GHZ];
-       if (band && idx >= band->n_channels) {
-               idx -= band->n_channels;
-               band = NULL;
-       }
+       for (band_id = 0; band_id < NUM_NL80211_BANDS; band_id++) {
+               band = wiphy->bands[band_id];
+               if (!band)
+                       continue;
+               if (idx >= band->n_channels) {
+                       idx -= band->n_channels;
+                       continue;
+               }
 
-       if (!band || idx >= band->n_channels) {
-               band = wiphy->bands[NL80211_BAND_5GHZ];
-               if (idx >= band->n_channels)
-                       return -ENOENT;
+               info->channel = &band->channels[idx];
+               break;
        }
+       if (band_id == NUM_NL80211_BANDS)
+               return -ENOENT;
 
        /* Setting current channel to the requested channel */
-       chan = &band->channels[idx];
-       err = cfg80211_set_channel(wiphy, ndev, chan, NL80211_CHAN_HT20);
-       if (err) {
-               info->channel = chan;
-               info->filled = 0;
+       info->filled = 0;
+       if (cfg80211_set_channel(wiphy, ndev, info->channel, NL80211_CHAN_HT20))
                return 0;
-       }
 
        /* Disable mpc */
        brcmf_set_mpc(ifp, 0);
@@ -8028,7 +8030,6 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
        if (err)
                goto exit;
 
-       info->channel = chan;
        info->noise = noise;
        info->time = ACS_MSRMNT_DELAY;
        info->time_busy = ACS_MSRMNT_DELAY - survey.idle;
@@ -8040,7 +8041,7 @@ brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
                SURVEY_INFO_TIME_TX;
 
        brcmf_dbg(INFO, "OBSS dump: channel %d: survey duration %d\n",
-                 ieee80211_frequency_to_channel(chan->center_freq),
+                 ieee80211_frequency_to_channel(info->channel->center_freq),
                  ACS_MSRMNT_DELAY);
        brcmf_dbg(INFO, "noise(%d) busy(%llu) rx(%llu) tx(%llu)\n",
                  info->noise, info->time_busy, info->time_rx, info->time_tx);
index ae57a9a3ab055f943f2b3b9b6a7721877796bfee..b67f6d0810b6ccaa12bc6adddc99ebac568f6e0a 100644 (file)
@@ -1228,7 +1228,7 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
                                BRCMF_NROF_H2D_COMMON_MSGRINGS;
                max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
        }
-       if (max_flowrings > 256) {
+       if (max_flowrings > 512) {
                brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings);
                return -EIO;
        }
index f795548562f556d90d834e1b985d568b1aecd481..06161815c180edc6055e08835104aa4d1f259ff7 100644 (file)
@@ -205,6 +205,52 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
        mt76_dma_sync_idx(dev, q);
 }
 
+static int
+mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
+                   struct mt76_queue_buf *buf, void *data)
+{
+       struct mt76_desc *desc = &q->desc[q->head];
+       struct mt76_queue_entry *entry = &q->entry[q->head];
+       struct mt76_txwi_cache *txwi = NULL;
+       u32 buf1 = 0, ctrl;
+       int idx = q->head;
+       int rx_token;
+
+       ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+
+       if ((q->flags & MT_QFLAG_WED) &&
+           FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
+               txwi = mt76_get_rxwi(dev);
+               if (!txwi)
+                       return -ENOMEM;
+
+               rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr);
+               if (rx_token < 0) {
+                       mt76_put_rxwi(dev, txwi);
+                       return -ENOMEM;
+               }
+
+               buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token);
+               ctrl |= MT_DMA_CTL_TO_HOST;
+       }
+
+       WRITE_ONCE(desc->buf0, cpu_to_le32(buf->addr));
+       WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
+       WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
+       WRITE_ONCE(desc->info, 0);
+
+       entry->dma_addr[0] = buf->addr;
+       entry->dma_len[0] = buf->len;
+       entry->txwi = txwi;
+       entry->buf = data;
+       entry->wcid = 0xffff;
+       entry->skip_buf1 = true;
+       q->head = (q->head + 1) % q->ndesc;
+       q->queued++;
+
+       return idx;
+}
+
 static int
 mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
                 struct mt76_queue_buf *buf, int nbufs, u32 info,
@@ -212,65 +258,51 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
 {
        struct mt76_queue_entry *entry;
        struct mt76_desc *desc;
-       u32 ctrl;
        int i, idx = -1;
+       u32 ctrl, next;
+
+       if (txwi) {
+               q->entry[q->head].txwi = DMA_DUMMY_DATA;
+               q->entry[q->head].skip_buf0 = true;
+       }
 
        for (i = 0; i < nbufs; i += 2, buf += 2) {
                u32 buf0 = buf[0].addr, buf1 = 0;
 
                idx = q->head;
-               q->head = (q->head + 1) % q->ndesc;
+               next = (q->head + 1) % q->ndesc;
 
                desc = &q->desc[idx];
                entry = &q->entry[idx];
 
-               if ((q->flags & MT_QFLAG_WED) &&
-                   FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
-                       struct mt76_txwi_cache *t = txwi;
-                       int rx_token;
-
-                       if (!t)
-                               return -ENOMEM;
-
-                       rx_token = mt76_rx_token_consume(dev, (void *)skb, t,
-                                                        buf[0].addr);
-                       buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token);
-                       ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len) |
-                              MT_DMA_CTL_TO_HOST;
-               } else {
-                       if (txwi) {
-                               q->entry[q->head].txwi = DMA_DUMMY_DATA;
-                               q->entry[q->head].skip_buf0 = true;
-                       }
-
-                       if (buf[0].skip_unmap)
-                               entry->skip_buf0 = true;
-                       entry->skip_buf1 = i == nbufs - 1;
-
-                       entry->dma_addr[0] = buf[0].addr;
-                       entry->dma_len[0] = buf[0].len;
-
-                       ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
-                       if (i < nbufs - 1) {
-                               entry->dma_addr[1] = buf[1].addr;
-                               entry->dma_len[1] = buf[1].len;
-                               buf1 = buf[1].addr;
-                               ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
-                               if (buf[1].skip_unmap)
-                                       entry->skip_buf1 = true;
-                       }
-
-                       if (i == nbufs - 1)
-                               ctrl |= MT_DMA_CTL_LAST_SEC0;
-                       else if (i == nbufs - 2)
-                               ctrl |= MT_DMA_CTL_LAST_SEC1;
+               if (buf[0].skip_unmap)
+                       entry->skip_buf0 = true;
+               entry->skip_buf1 = i == nbufs - 1;
+
+               entry->dma_addr[0] = buf[0].addr;
+               entry->dma_len[0] = buf[0].len;
+
+               ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
+               if (i < nbufs - 1) {
+                       entry->dma_addr[1] = buf[1].addr;
+                       entry->dma_len[1] = buf[1].len;
+                       buf1 = buf[1].addr;
+                       ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
+                       if (buf[1].skip_unmap)
+                               entry->skip_buf1 = true;
                }
 
+               if (i == nbufs - 1)
+                       ctrl |= MT_DMA_CTL_LAST_SEC0;
+               else if (i == nbufs - 2)
+                       ctrl |= MT_DMA_CTL_LAST_SEC1;
+
                WRITE_ONCE(desc->buf0, cpu_to_le32(buf0));
                WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
                WRITE_ONCE(desc->info, cpu_to_le32(info));
                WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
 
+               q->head = next;
                q->queued++;
        }
 
@@ -577,17 +609,9 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
        spin_lock_bh(&q->lock);
 
        while (q->queued < q->ndesc - 1) {
-               struct mt76_txwi_cache *t = NULL;
                struct mt76_queue_buf qbuf;
                void *buf = NULL;
 
-               if ((q->flags & MT_QFLAG_WED) &&
-                   FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
-                       t = mt76_get_rxwi(dev);
-                       if (!t)
-                               break;
-               }
-
                buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC);
                if (!buf)
                        break;
@@ -601,7 +625,12 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
                qbuf.addr = addr + offset;
                qbuf.len = len - offset;
                qbuf.skip_unmap = false;
-               mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, t);
+               if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
+                       dma_unmap_single(dev->dma_dev, addr, len,
+                                        DMA_FROM_DEVICE);
+                       skb_free_frag(buf);
+                       break;
+               }
                frames++;
        }
 
index 0a95c3da241b5051ec413f42e8b1562f571b40b2..8388e2a658535fbe5349369e020f68e8a53c8e24 100644 (file)
@@ -653,6 +653,13 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
 
                desc->buf0 = cpu_to_le32(phy_addr);
                token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr);
+               if (token < 0) {
+                       dma_unmap_single(dev->mt76.dma_dev, phy_addr,
+                                        wed->wlan.rx_size, DMA_TO_DEVICE);
+                       skb_free_frag(ptr);
+                       goto unmap;
+               }
+
                desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
                                                      token));
                desc++;
index 24568b98ed9dfb0c9c04fa6492495290d7efb1c9..1f309d05380ad5fb6c266b6cc1e220bc691df986 100644 (file)
@@ -764,11 +764,12 @@ int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
        spin_lock_bh(&dev->rx_token_lock);
        token = idr_alloc(&dev->rx_token, t, 0, dev->rx_token_size,
                          GFP_ATOMIC);
+       if (token >= 0) {
+               t->ptr = ptr;
+               t->dma_addr = phys;
+       }
        spin_unlock_bh(&dev->rx_token_lock);
 
-       t->ptr = ptr;
-       t->dma_addr = phys;
-
        return token;
 }
 EXPORT_SYMBOL_GPL(mt76_rx_token_consume);
index 82a7458e01aec063643ec83da31cb3a50ae96cd4..bf72e5fd39cf40a88c331726f5751eee232192db 100644 (file)
@@ -696,8 +696,8 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
                struct rndis_query      *get;
                struct rndis_query_c    *get_c;
        } u;
-       int ret, buflen;
-       int resplen, respoffs, copylen;
+       int ret;
+       size_t buflen, resplen, respoffs, copylen;
 
        buflen = *len + sizeof(*u.get);
        if (buflen < CONTROL_BUFFER_SIZE)
@@ -732,22 +732,15 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
 
                if (respoffs > buflen) {
                        /* Device returned data offset outside buffer, error. */
-                       netdev_dbg(dev->net, "%s(%s): received invalid "
-                               "data offset: %d > %d\n", __func__,
-                               oid_to_string(oid), respoffs, buflen);
+                       netdev_dbg(dev->net,
+                                  "%s(%s): received invalid data offset: %zu > %zu\n",
+                                  __func__, oid_to_string(oid), respoffs, buflen);
 
                        ret = -EINVAL;
                        goto exit_unlock;
                }
 
-               if ((resplen + respoffs) > buflen) {
-                       /* Device would have returned more data if buffer would
-                        * have been big enough. Copy just the bits that we got.
-                        */
-                       copylen = buflen - respoffs;
-               } else {
-                       copylen = resplen;
-               }
+               copylen = min(resplen, buflen - respoffs);
 
                if (copylen > *len)
                        copylen = *len;
index 7eff3531b9a539802ae4aa931814384f5b3c9ec6..7ff33c1d6ac75ff1b8b12a77b7a7345a2443c4f3 100644 (file)
@@ -152,6 +152,15 @@ static irqreturn_t t7xx_dpmaif_isr_handler(int irq, void *data)
        }
 
        t7xx_pcie_mac_clear_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t t7xx_dpmaif_isr_thread(int irq, void *data)
+{
+       struct dpmaif_isr_para *isr_para = data;
+       struct dpmaif_ctrl *dpmaif_ctrl = isr_para->dpmaif_ctrl;
+
        t7xx_dpmaif_irq_cb(isr_para);
        t7xx_pcie_mac_set_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
        return IRQ_HANDLED;
@@ -188,7 +197,7 @@ static void t7xx_dpmaif_register_pcie_irq(struct dpmaif_ctrl *dpmaif_ctrl)
                t7xx_pcie_mac_clear_int(t7xx_dev, int_type);
 
                t7xx_dev->intr_handler[int_type] = t7xx_dpmaif_isr_handler;
-               t7xx_dev->intr_thread[int_type] = NULL;
+               t7xx_dev->intr_thread[int_type] = t7xx_dpmaif_isr_thread;
                t7xx_dev->callback_param[int_type] = isr_para;
 
                t7xx_pcie_mac_clear_int_status(t7xx_dev, int_type);
index aa2174a1043727ed61597ce3124417bc9b0a8372..f4ff2198b5ef8153d341485f669585fb0fcffbf4 100644 (file)
@@ -840,14 +840,13 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
 
        if (!rxq->que_started) {
                atomic_set(&rxq->rx_processing, 0);
+               pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
                dev_err(rxq->dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
                return work_done;
        }
 
-       if (!rxq->sleep_lock_pending) {
-               pm_runtime_get_noresume(rxq->dpmaif_ctrl->dev);
+       if (!rxq->sleep_lock_pending)
                t7xx_pci_disable_sleep(t7xx_dev);
-       }
 
        ret = try_wait_for_completion(&t7xx_dev->sleep_lock_acquire);
        if (!ret) {
@@ -876,22 +875,22 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
                napi_complete_done(napi, work_done);
                t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
                t7xx_dpmaif_dlq_unmask_rx_done(&rxq->dpmaif_ctrl->hw_info, rxq->index);
+               t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
+               pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
+               pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
+               atomic_set(&rxq->rx_processing, 0);
        } else {
                t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
        }
 
-       t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
-       pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
-       pm_runtime_put_noidle(rxq->dpmaif_ctrl->dev);
-       atomic_set(&rxq->rx_processing, 0);
-
        return work_done;
 }
 
 void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int que_mask)
 {
        struct dpmaif_rx_queue *rxq;
-       int qno;
+       struct dpmaif_ctrl *ctrl;
+       int qno, ret;
 
        qno = ffs(que_mask) - 1;
        if (qno < 0 || qno > DPMAIF_RXQ_NUM - 1) {
@@ -900,6 +899,18 @@ void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int
        }
 
        rxq = &dpmaif_ctrl->rxq[qno];
+       ctrl = rxq->dpmaif_ctrl;
+       /* We need to make sure that the modem has been resumed before
+        * calling napi. This can't be done inside the polling function
+        * as we could be blocked waiting for device to be resumed,
+        * which can't be done from softirq context the poll function
+        * is running in.
+        */
+       ret = pm_runtime_resume_and_get(ctrl->dev);
+       if (ret < 0 && ret != -EACCES) {
+               dev_err(ctrl->dev, "Failed to resume device: %d\n", ret);
+               return;
+       }
        napi_schedule(&rxq->napi);
 }
 
index 494a28e386a3805682a6a51bb7ddfe52f9eae8e8..3ef4a8a4f8fdbced3b31115db04136292e9269c8 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/netdev_features.h>
 #include <linux/netdevice.h>
+#include <linux/pm_runtime.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
 #include <linux/wwan.h>
 
 static void t7xx_ccmni_enable_napi(struct t7xx_ccmni_ctrl *ctlb)
 {
-       int i;
+       struct dpmaif_ctrl *ctrl;
+       int i, ret;
+
+       ctrl =  ctlb->hif_ctrl;
 
        if (ctlb->is_napi_en)
                return;
 
        for (i = 0; i < RXQ_NUM; i++) {
+               /* The usage count has to be bumped every time before calling
+                * napi_schedule. It will be decresed in the poll routine,
+                * right after napi_complete_done is called.
+                */
+               ret = pm_runtime_resume_and_get(ctrl->dev);
+               if (ret < 0) {
+                       dev_err(ctrl->dev, "Failed to resume device: %d\n",
+                               ret);
+                       return;
+               }
                napi_enable(ctlb->napi[i]);
                napi_schedule(ctlb->napi[i]);
        }
index 871f2a27a398a34568980ab0d3b142e2e5cb6876..226fc1703e90f2d56728cfbf73b64c9f5bf49849 100644 (file)
@@ -121,6 +121,8 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev)
        iowrite32(T7XX_L1_BIT(0), IREG_BASE(t7xx_dev) + ENABLE_ASPM_LOWPWR);
        atomic_set(&t7xx_dev->md_pm_state, MTK_PM_RESUMED);
 
+       pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
+       pm_runtime_allow(&t7xx_dev->pdev->dev);
        pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
 }
 
index bf1c60edb7f9ab8a0f40f4bd3cdc0a8b19dcef7a..b317ce6c4ec31803347ff49d1bf9eec569c87150 100644 (file)
@@ -829,7 +829,23 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)
                        apple_nvme_remove_cq(anv);
                }
 
-               nvme_disable_ctrl(&anv->ctrl, shutdown);
+               /*
+                * Always disable the NVMe controller after shutdown.
+                * We need to do this to bring it back up later anyway, and we
+                * can't do it while the firmware is not running (e.g. in the
+                * resume reset path before RTKit is initialized), so for Apple
+                * controllers it makes sense to unconditionally do it here.
+                * Additionally, this sequence of events is reliable, while
+                * others (like disabling after bringing back the firmware on
+                * resume) seem to run into trouble under some circumstances.
+                *
+                * Both U-Boot and m1n1 also use this convention (i.e. an ANS
+                * NVMe controller is handed off with firmware shut down, in an
+                * NVMe disabled state, after a clean shutdown).
+                */
+               if (shutdown)
+                       nvme_disable_ctrl(&anv->ctrl, shutdown);
+               nvme_disable_ctrl(&anv->ctrl, false);
        }
 
        WRITE_ONCE(anv->ioq.enabled, false);
@@ -985,11 +1001,11 @@ static void apple_nvme_reset_work(struct work_struct *work)
                goto out;
        }
 
-       if (anv->ctrl.ctrl_config & NVME_CC_ENABLE)
-               apple_nvme_disable(anv, false);
-
        /* RTKit must be shut down cleanly for the (soft)-reset to work */
        if (apple_rtkit_is_running(anv->rtk)) {
+               /* reset the controller if it is enabled */
+               if (anv->ctrl.ctrl_config & NVME_CC_ENABLE)
+                       apple_nvme_disable(anv, false);
                dev_dbg(anv->dev, "Trying to shut down RTKit before reset.");
                ret = apple_rtkit_shutdown(anv->rtk);
                if (ret)
index 4424f53a8a0a3d1a87b573b43c7d580e42fe1db3..b57630d1d3b8bda0ef8c5f947bbe39b7eeed885f 100644 (file)
@@ -45,6 +45,8 @@ struct nvme_dhchap_queue_context {
        int sess_key_len;
 };
 
+struct workqueue_struct *nvme_auth_wq;
+
 #define nvme_auth_flags_from_qid(qid) \
        (qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED
 #define nvme_auth_queue_from_qid(ctrl, qid) \
@@ -866,7 +868,7 @@ int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid)
 
        chap = &ctrl->dhchap_ctxs[qid];
        cancel_work_sync(&chap->auth_work);
-       queue_work(nvme_wq, &chap->auth_work);
+       queue_work(nvme_auth_wq, &chap->auth_work);
        return 0;
 }
 EXPORT_SYMBOL_GPL(nvme_auth_negotiate);
@@ -1008,10 +1010,15 @@ EXPORT_SYMBOL_GPL(nvme_auth_free);
 
 int __init nvme_init_auth(void)
 {
+       nvme_auth_wq = alloc_workqueue("nvme-auth-wq",
+                              WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+       if (!nvme_auth_wq)
+               return -ENOMEM;
+
        nvme_chap_buf_cache = kmem_cache_create("nvme-chap-buf-cache",
                                CHAP_BUF_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL);
        if (!nvme_chap_buf_cache)
-               return -ENOMEM;
+               goto err_destroy_workqueue;
 
        nvme_chap_buf_pool = mempool_create(16, mempool_alloc_slab,
                        mempool_free_slab, nvme_chap_buf_cache);
@@ -1021,6 +1028,8 @@ int __init nvme_init_auth(void)
        return 0;
 err_destroy_chap_buf_cache:
        kmem_cache_destroy(nvme_chap_buf_cache);
+err_destroy_workqueue:
+       destroy_workqueue(nvme_auth_wq);
        return -ENOMEM;
 }
 
@@ -1028,4 +1037,5 @@ void __exit nvme_exit_auth(void)
 {
        mempool_destroy(nvme_chap_buf_pool);
        kmem_cache_destroy(nvme_chap_buf_cache);
+       destroy_workqueue(nvme_auth_wq);
 }
index 7be562a4e1aa72d6278f657a24730afabb47aee8..8b64211411626b2332888bb263a72464e865a011 100644 (file)
@@ -1093,7 +1093,7 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
        if (ns) {
                if (ns->head->effects)
                        effects = le32_to_cpu(ns->head->effects->iocs[opcode]);
-               if (ns->head->ids.csi == NVME_CAP_CSS_NVM)
+               if (ns->head->ids.csi == NVME_CSI_NVM)
                        effects |= nvme_known_nvm_effects(opcode);
                if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC))
                        dev_warn_once(ctrl->device,
@@ -4921,7 +4921,9 @@ out_cleanup_admin_q:
        blk_mq_destroy_queue(ctrl->admin_q);
        blk_put_queue(ctrl->admin_q);
 out_free_tagset:
-       blk_mq_free_tag_set(ctrl->admin_tagset);
+       blk_mq_free_tag_set(set);
+       ctrl->admin_q = NULL;
+       ctrl->fabrics_q = NULL;
        return ret;
 }
 EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set);
@@ -4983,6 +4985,7 @@ int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
 
 out_free_tag_set:
        blk_mq_free_tag_set(set);
+       ctrl->connect_q = NULL;
        return ret;
 }
 EXPORT_SYMBOL_GPL(nvme_alloc_io_tag_set);
index 4564f16a0b203c1fa0568c3542931f475eb805e4..456ee42a6133431bbe4637f1d4641268fab10580 100644 (file)
@@ -3521,13 +3521,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 
        nvme_fc_init_queue(ctrl, 0);
 
-       ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set,
-                       &nvme_fc_admin_mq_ops,
-                       struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv,
-                                   ctrl->lport->ops->fcprqst_priv_sz));
-       if (ret)
-               goto out_free_queues;
-
        /*
         * Would have been nice to init io queues tag set as well.
         * However, we require interaction from the controller
@@ -3537,10 +3530,17 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 
        ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_fc_ctrl_ops, 0);
        if (ret)
-               goto out_cleanup_tagset;
+               goto out_free_queues;
 
        /* at this point, teardown path changes to ref counting on nvme ctrl */
 
+       ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set,
+                       &nvme_fc_admin_mq_ops,
+                       struct_size((struct nvme_fcp_op_w_sgl *)NULL, priv,
+                                   ctrl->lport->ops->fcprqst_priv_sz));
+       if (ret)
+               goto fail_ctrl;
+
        spin_lock_irqsave(&rport->lock, flags);
        list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list);
        spin_unlock_irqrestore(&rport->lock, flags);
@@ -3592,8 +3592,6 @@ fail_ctrl:
 
        return ERR_PTR(-EIO);
 
-out_cleanup_tagset:
-       nvme_remove_admin_tag_set(&ctrl->ctrl);
 out_free_queues:
        kfree(ctrl->queues);
 out_free_ida:
index a2553b7d9bb8e630199d9a8c0d33bf1e791ad832..c734934c407ccf7457350d017b4facb7e48902bb 100644 (file)
@@ -1362,7 +1362,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
        else
                nvme_poll_irqdisable(nvmeq);
 
-       if (blk_mq_request_completed(req)) {
+       if (blk_mq_rq_state(req) != MQ_RQ_IN_FLIGHT) {
                dev_warn(dev->ctrl.device,
                         "I/O %d QID %d timeout, completion polled\n",
                         req->tag, nvmeq->qid);
@@ -3102,6 +3102,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        nvme_start_ctrl(&dev->ctrl);
        nvme_put_ctrl(&dev->ctrl);
+       flush_work(&dev->ctrl.scan_work);
        return 0;
 
 out_disable:
index ab2627e17bb97f2b85af5e9e2c191f714079d159..1ab6601fdd5cf97cad666437591b166059cebd3e 100644 (file)
@@ -1685,8 +1685,10 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
                else {
                        queue = nvmet_fc_alloc_target_queue(iod->assoc, 0,
                                        be16_to_cpu(rqst->assoc_cmd.sqsize));
-                       if (!queue)
+                       if (!queue) {
                                ret = VERR_QUEUE_ALLOC_FAIL;
+                               nvmet_fc_tgt_a_put(iod->assoc);
+                       }
                }
        }
 
index 34130449f2d28c27dc3b2e23d9f39a43ce62c3bc..39aa27942f28b3d49ed91327e574666023c4fd6f 100644 (file)
@@ -98,6 +98,9 @@ static int brcm_nvram_parse(struct brcm_nvram *priv)
        len = le32_to_cpu(header.len);
 
        data = kzalloc(len, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        memcpy_fromio(data, priv->base, len);
        data[len - 1] = '\0';
 
index 321d7d63e0683c96ae8bd35fbd7c7e989fa7d075..34ee9d36ee7ba2a319d8eb22ce87ac4246dac379 100644 (file)
@@ -770,31 +770,32 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
                return ERR_PTR(rval);
        }
 
-       if (config->wp_gpio)
-               nvmem->wp_gpio = config->wp_gpio;
-       else if (!config->ignore_wp)
+       nvmem->id = rval;
+
+       nvmem->dev.type = &nvmem_provider_type;
+       nvmem->dev.bus = &nvmem_bus_type;
+       nvmem->dev.parent = config->dev;
+
+       device_initialize(&nvmem->dev);
+
+       if (!config->ignore_wp)
                nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
                                                    GPIOD_OUT_HIGH);
        if (IS_ERR(nvmem->wp_gpio)) {
-               ida_free(&nvmem_ida, nvmem->id);
                rval = PTR_ERR(nvmem->wp_gpio);
-               kfree(nvmem);
-               return ERR_PTR(rval);
+               nvmem->wp_gpio = NULL;
+               goto err_put_device;
        }
 
        kref_init(&nvmem->refcnt);
        INIT_LIST_HEAD(&nvmem->cells);
 
-       nvmem->id = rval;
        nvmem->owner = config->owner;
        if (!nvmem->owner && config->dev->driver)
                nvmem->owner = config->dev->driver->owner;
        nvmem->stride = config->stride ?: 1;
        nvmem->word_size = config->word_size ?: 1;
        nvmem->size = config->size;
-       nvmem->dev.type = &nvmem_provider_type;
-       nvmem->dev.bus = &nvmem_bus_type;
-       nvmem->dev.parent = config->dev;
        nvmem->root_only = config->root_only;
        nvmem->priv = config->priv;
        nvmem->type = config->type;
@@ -822,11 +823,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
                break;
        }
 
-       if (rval) {
-               ida_free(&nvmem_ida, nvmem->id);
-               kfree(nvmem);
-               return ERR_PTR(rval);
-       }
+       if (rval)
+               goto err_put_device;
 
        nvmem->read_only = device_property_present(config->dev, "read-only") ||
                           config->read_only || !nvmem->reg_write;
@@ -835,28 +833,22 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
        nvmem->dev.groups = nvmem_dev_groups;
 #endif
 
-       dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
-
-       rval = device_register(&nvmem->dev);
-       if (rval)
-               goto err_put_device;
-
        if (nvmem->nkeepout) {
                rval = nvmem_validate_keepouts(nvmem);
                if (rval)
-                       goto err_device_del;
+                       goto err_put_device;
        }
 
        if (config->compat) {
                rval = nvmem_sysfs_setup_compat(nvmem, config);
                if (rval)
-                       goto err_device_del;
+                       goto err_put_device;
        }
 
        if (config->cells) {
                rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
                if (rval)
-                       goto err_teardown_compat;
+                       goto err_remove_cells;
        }
 
        rval = nvmem_add_cells_from_table(nvmem);
@@ -867,17 +859,20 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
        if (rval)
                goto err_remove_cells;
 
+       dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
+
+       rval = device_add(&nvmem->dev);
+       if (rval)
+               goto err_remove_cells;
+
        blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
 
        return nvmem;
 
 err_remove_cells:
        nvmem_device_remove_all_cells(nvmem);
-err_teardown_compat:
        if (config->compat)
                nvmem_sysfs_remove_compat(nvmem, config);
-err_device_del:
-       device_del(&nvmem->dev);
 err_put_device:
        put_device(&nvmem->dev);
 
@@ -1242,16 +1237,21 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
        if (!cell_np)
                return ERR_PTR(-ENOENT);
 
-       nvmem_np = of_get_next_parent(cell_np);
-       if (!nvmem_np)
+       nvmem_np = of_get_parent(cell_np);
+       if (!nvmem_np) {
+               of_node_put(cell_np);
                return ERR_PTR(-EINVAL);
+       }
 
        nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
        of_node_put(nvmem_np);
-       if (IS_ERR(nvmem))
+       if (IS_ERR(nvmem)) {
+               of_node_put(cell_np);
                return ERR_CAST(nvmem);
+       }
 
        cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np);
+       of_node_put(cell_np);
        if (!cell_entry) {
                __nvmem_device_put(nvmem);
                return ERR_PTR(-ENOENT);
index 4fcb63507ecd151e95cd8089a5000036a1fa2367..8499892044b7b2cc366e1f9426c4e05838535c7d 100644 (file)
@@ -166,6 +166,7 @@ static const struct of_device_id sdam_match_table[] = {
        { .compatible = "qcom,spmi-sdam" },
        {},
 };
+MODULE_DEVICE_TABLE(of, sdam_match_table);
 
 static struct platform_driver sdam_driver = {
        .driver = {
index 5750e1f4bcdbbf682d65164a7164483af96af49a..92dfe4cb10e38617ebfc163f2c33cfd2d58abcfb 100644 (file)
@@ -41,8 +41,21 @@ static int sunxi_sid_read(void *context, unsigned int offset,
                          void *val, size_t bytes)
 {
        struct sunxi_sid *sid = context;
+       u32 word;
+
+       /* .stride = 4 so offset is guaranteed to be aligned */
+       __ioread32_copy(val, sid->base + sid->value_offset + offset, bytes / 4);
 
-       memcpy_fromio(val, sid->base + sid->value_offset + offset, bytes);
+       val += round_down(bytes, 4);
+       offset += round_down(bytes, 4);
+       bytes = bytes % 4;
+
+       if (!bytes)
+               return 0;
+
+       /* Handle any trailing bytes */
+       word = readl_relaxed(sid->base + sid->value_offset + offset);
+       memcpy(val, &word, bytes);
 
        return 0;
 }
index f08b25195ae79d2b51468dd89d6d3e3c20b93f2d..d1a68b6d03b3f1df3789511a432b92ca15911e2a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/serial_core.h>
 #include <linux/sysfs.h>
 #include <linux/random.h>
-#include <linux/kmemleak.h>
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #include <asm/page.h>
@@ -525,12 +524,9 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
                size = dt_mem_next_cell(dt_root_size_cells, &prop);
 
                if (size &&
-                   early_init_dt_reserve_memory(base, size, nomap) == 0) {
+                   early_init_dt_reserve_memory(base, size, nomap) == 0)
                        pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
                                uname, &base, (unsigned long)(size / SZ_1M));
-                       if (!nomap)
-                               kmemleak_alloc_phys(base, size, 0);
-               }
                else
                        pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
                               uname, &base, (unsigned long)(size / SZ_1M));
index d6af5726ddf3548ffb70dec175537a2cfbb9b24e..2a18f7ba2398bcecf723d1a2be304c09c8a7c15d 100644 (file)
@@ -274,8 +274,7 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun
 
        /* We'll use a local copy of buf */
        count = min_t(size_t, count, sizeof(in)-1);
-       strncpy(in, buf, count);
-       in[count] = '\0';
+       strscpy(in, buf, count + 1);
        
        /* Let's clean up the target. 0xff is a blank pattern */
        memset(&hwpath, 0xff, sizeof(hwpath));
@@ -388,8 +387,7 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count
 
        /* We'll use a local copy of buf */
        count = min_t(size_t, count, sizeof(in)-1);
-       strncpy(in, buf, count);
-       in[count] = '\0';
+       strscpy(in, buf, count + 1);
        
        /* Let's clean up the target. 0 is a blank pattern */
        memset(&layers, 0, sizeof(layers));
@@ -756,8 +754,7 @@ static ssize_t pdcs_auto_write(struct kobject *kobj,
 
        /* We'll use a local copy of buf */
        count = min_t(size_t, count, sizeof(in)-1);
-       strncpy(in, buf, count);
-       in[count] = '\0';
+       strscpy(in, buf, count + 1);
 
        /* Current flags are stored in primary boot path entry */
        pathentry = &pdcspath_entry_primary;
index b80a9b74662b1d86fa931d2f5e49dc32da580cc2..1deb61b22bc76767aaac41165a6426cbee8cf2f7 100644 (file)
@@ -1576,7 +1576,6 @@ static int arm_cmn_event_init(struct perf_event *event)
                        hw->dn++;
                        continue;
                }
-               hw->dtcs_used |= arm_cmn_node_to_xp(cmn, dn)->dtc;
                hw->num_dns++;
                if (bynodeid)
                        break;
@@ -1589,6 +1588,12 @@ static int arm_cmn_event_init(struct perf_event *event)
                        nodeid, nid.x, nid.y, nid.port, nid.dev, type);
                return -EINVAL;
        }
+       /*
+        * Keep assuming non-cycles events count in all DTC domains; turns out
+        * it's hard to make a worthwhile optimisation around this, short of
+        * going all-in with domain-local counter allocation as well.
+        */
+       hw->dtcs_used = (1U << cmn->num_dtcs) - 1;
 
        return arm_cmn_validate_group(cmn, event);
 }
index 7585e8080b77d58247aa94f5020f2aa98bcc9c30..afc63552ecaf7994738f9cfad53ef852fde9aa3b 100644 (file)
@@ -255,7 +255,7 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
                imx8_phy->perst =
                        devm_reset_control_get_exclusive(dev, "perst");
                if (IS_ERR(imx8_phy->perst))
-                       dev_err_probe(dev, PTR_ERR(imx8_phy->perst),
+                       return dev_err_probe(dev, PTR_ERR(imx8_phy->perst),
                                      "Failed to get PCIE PHY PERST control\n");
        }
 
index 95c6dbb52da720bffcba85ff9ad037daed688009..ce511ad5d36907631c8c44a730bfe04fd8b66c57 100644 (file)
@@ -99,6 +99,7 @@ static int can_transceiver_phy_probe(struct platform_device *pdev)
        struct gpio_desc *standby_gpio;
        struct gpio_desc *enable_gpio;
        u32 max_bitrate = 0;
+       int err;
 
        can_transceiver_phy = devm_kzalloc(dev, sizeof(struct can_transceiver_phy), GFP_KERNEL);
        if (!can_transceiver_phy)
@@ -124,8 +125,8 @@ static int can_transceiver_phy_probe(struct platform_device *pdev)
                return PTR_ERR(phy);
        }
 
-       device_property_read_u32(dev, "max-bitrate", &max_bitrate);
-       if (!max_bitrate)
+       err = device_property_read_u32(dev, "max-bitrate", &max_bitrate);
+       if ((err != -EINVAL) && !max_bitrate)
                dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n");
        phy->attrs.max_link_rate = max_bitrate;
 
index 8807e59a1162cb05591546e8d4fd06ea3ca6dfff..a52a9bf13b758d99c95786a8e9e8d1cbe2fe15bf 100644 (file)
@@ -401,26 +401,13 @@ static const struct hsphy_init_seq init_seq_femtophy[] = {
        HSPHY_INIT_CFG(0x90, 0x60, 0),
 };
 
-static const struct hsphy_init_seq init_seq_mdm9607[] = {
-       HSPHY_INIT_CFG(0x80, 0x44, 0),
-       HSPHY_INIT_CFG(0x81, 0x38, 0),
-       HSPHY_INIT_CFG(0x82, 0x24, 0),
-       HSPHY_INIT_CFG(0x83, 0x13, 0),
-};
-
 static const struct hsphy_data hsphy_data_femtophy = {
        .init_seq = init_seq_femtophy,
        .init_seq_num = ARRAY_SIZE(init_seq_femtophy),
 };
 
-static const struct hsphy_data hsphy_data_mdm9607 = {
-       .init_seq = init_seq_mdm9607,
-       .init_seq_num = ARRAY_SIZE(init_seq_mdm9607),
-};
-
 static const struct of_device_id qcom_snps_hsphy_match[] = {
        { .compatible = "qcom,usb-hs-28nm-femtophy", .data = &hsphy_data_femtophy, },
-       { .compatible = "qcom,usb-hs-28nm-mdm9607", .data = &hsphy_data_mdm9607, },
        { },
 };
 MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_match);
index ec6594e6dc275bf1c7fac5888736ee5263b0be91..e7588a940d699129e8644b922ab6c1fd688b2427 100644 (file)
@@ -126,7 +126,7 @@ r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel)
                r8a779f0_eth_serdes_write32(channel->addr, 0x0160, 0x180, 0x0007);
                r8a779f0_eth_serdes_write32(channel->addr, 0x01ac, 0x180, 0x0000);
                r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x0310);
-               r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x380, 0x0101);
+               r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0101);
                ret = r8a779f0_eth_serdes_reg_wait(channel, 0x00c8, 0x0180, BIT(0), 0);
                if (ret)
                        return ret;
index e6ededc515239086a7b2e38ffd0a453f6ec88ba6..a0bc10aa79618350caf846a2bbce0cb1ea5d0039 100644 (file)
@@ -485,8 +485,10 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
                return ret;
 
        ret = property_enable(base, &rport->port_cfg->phy_sus, false);
-       if (ret)
+       if (ret) {
+               clk_disable_unprepare(rphy->clk480m);
                return ret;
+       }
 
        /* waiting for the utmi_clk to become stable */
        usleep_range(1500, 2000);
index e827b79f6d493cb9c1571221d7940e16741b0a2a..56de41091d639721fd797491c04684339d4eb64d 100644 (file)
@@ -254,6 +254,9 @@ static int sp_usb_phy_probe(struct platform_device *pdev)
                return PTR_ERR(usbphy->phy_regs);
 
        usbphy->moon4_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "moon4");
+       if (!usbphy->moon4_res_mem)
+               return -EINVAL;
+
        usbphy->moon4_regs = devm_ioremap(&pdev->dev, usbphy->moon4_res_mem->start,
                                          resource_size(usbphy->moon4_res_mem));
        if (!usbphy->moon4_regs)
index 15a3bcf32308603597a9ae5d177c2091e20a6dcd..b905902d57508d0c6f9d05fae9b0d9576d2cf0d9 100644 (file)
@@ -23,7 +23,7 @@ config PHY_DM816X_USB
 
 config PHY_AM654_SERDES
        tristate "TI AM654 SERDES support"
-       depends on OF && ARCH_K3 || COMPILE_TEST
+       depends on OF && (ARCH_K3 || COMPILE_TEST)
        depends on COMMON_CLK
        select GENERIC_PHY
        select MULTIPLEXER
@@ -35,7 +35,7 @@ config PHY_AM654_SERDES
 
 config PHY_J721E_WIZ
        tristate "TI J721E WIZ (SERDES Wrapper) support"
-       depends on OF && ARCH_K3 || COMPILE_TEST
+       depends on OF && (ARCH_K3 || COMPILE_TEST)
        depends on HAS_IOMEM && OF_ADDRESS
        depends on COMMON_CLK
        select GENERIC_PHY
index 3106a21cd277fe11eb32ff8006c8e38d20be3ca5..d7b244df058f28200d21132c889d95abf1150cd1 100644 (file)
@@ -6,9 +6,10 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/gpio/driver.h>
 #include <linux/pinctrl/pinctrl.h>
+
 #include <linux/mfd/abx500/ab8500.h>
+
 #include "pinctrl-abx500.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index b93af1fb37f017f45d200dd1604ae42f2acd7da4..45aa958b573e0af81fc3872f30215a7ecd61f25c 100644 (file)
@@ -6,9 +6,10 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/gpio/driver.h>
 #include <linux/pinctrl/pinctrl.h>
+
 #include <linux/mfd/abx500/ab8500.h>
+
 #include "pinctrl-abx500.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index 7aa534576a459840042dd243a333e84aef1ce4a2..28c3403df1b0387215b3e106e7eca92bd722cd08 100644 (file)
@@ -6,33 +6,37 @@
  *
  * Driver allows to use AxB5xx unused pins to be used as GPIO
  */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/bitops.h>
 #include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
-#include <linux/pinctrl/pinctrl.h>
+
 #include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
 
-#include "pinctrl-abx500.h"
 #include "../core.h"
 #include "../pinconf.h"
 #include "../pinctrl-utils.h"
 
+#include "pinctrl-abx500.h"
+
 /*
  * GPIO registers offset
  * Bank: 0x10
index 90bb12fe8073fd3d1110a8f1f0496deb3031bdb1..d675220846752608e0eab08dbaa406d5fe3b5d2e 100644 (file)
@@ -2,6 +2,10 @@
 #ifndef PINCTRL_PINCTRL_ABx500_H
 #define PINCTRL_PINCTRL_ABx500_H
 
+#include <linux/types.h>
+
+struct pinctrl_pin_desc;
+
 /* Package definitions */
 #define PINCTRL_AB8500 0
 #define PINCTRL_AB8505 1
index 758d21f0a8503a5d4c1548b2d06cae52d34acb06..490e0959e8be6c27e584dd9c81ce839cfba2118d 100644 (file)
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
+#include <linux/types.h>
+
 #include <linux/pinctrl/pinctrl.h>
+
 #include "pinctrl-nomadik.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index c0d7c86d09391035b6d3d9f8cde690af9f2afb4c..1552222ac68e74482dcfb660ac38064e6e12ecc8 100644 (file)
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
+#include <linux/types.h>
+
 #include <linux/pinctrl/pinctrl.h>
+
 #include "pinctrl-nomadik.h"
 
 /* All the pins that can be used for GPIO and some other functions */
index f7d02513d8cc103f98cdc5752dd0abb17df93020..86a638077a697391136bb9057bd306c77c5b63f3 100644 (file)
@@ -7,30 +7,34 @@
  *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
  * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
  */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
+#include <linux/bitops.h>
 #include <linux/clk.h>
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/driver.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/of_address.h>
-#include <linux/bitops.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-/* Since we request GPIOs from ourself */
-#include <linux/pinctrl/consumer.h>
-#include "pinctrl-nomadik.h"
+
 #include "../core.h"
 #include "../pinctrl-utils.h"
 
+#include "pinctrl-nomadik.h"
+
 /*
  * The GPIO module in the Nomadik family of Systems-on-Chip is an
  * AMBA device, managing 32 pins and alternate functions.  The logic block
@@ -907,8 +911,6 @@ static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
        return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
 }
 
-#include <linux/seq_file.h>
-
 static void nmk_gpio_dbg_show_one(struct seq_file *s,
        struct pinctrl_dev *pctldev, struct gpio_chip *chip,
        unsigned offset, unsigned gpio)
index 84e297757335756a8a6e5efc298b397e1ee0a707..1ef2559bc5710bdcb5aeec0c9de81a24d334955d 100644 (file)
@@ -2,6 +2,11 @@
 #ifndef PINCTRL_PINCTRL_NOMADIK_H
 #define PINCTRL_PINCTRL_NOMADIK_H
 
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <linux/pinctrl/pinctrl.h>
+
 /* Package definitions */
 #define PINCTRL_NMK_STN8815    0
 #define PINCTRL_NMK_DB8500     1
index da974ff2d75d0f9898603e7fe7ae3167ef384217..5eeac92f610a058dc8fa60ab59692f72080f26fb 100644 (file)
@@ -926,19 +926,19 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_PMU(0, RK_PB5, 4, 0x0110, WRITE_MASK_VAL(3, 2, 1)), /* PWM1 IO mux M1 */
        RK_MUXROUTE_PMU(0, RK_PC1, 1, 0x0110, WRITE_MASK_VAL(5, 4, 0)), /* PWM2 IO mux M0 */
        RK_MUXROUTE_PMU(0, RK_PB6, 4, 0x0110, WRITE_MASK_VAL(5, 4, 1)), /* PWM2 IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PA1, 4, 0x0300, WRITE_MASK_VAL(0, 0, 1)), /* CAN0 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA1, 3, 0x0300, WRITE_MASK_VAL(2, 2, 0)), /* CAN1 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PC3, 3, 0x0300, WRITE_MASK_VAL(2, 2, 1)), /* CAN1 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PB5, 3, 0x0300, WRITE_MASK_VAL(4, 4, 0)), /* CAN2 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PB2, 4, 0x0300, WRITE_MASK_VAL(4, 4, 1)), /* CAN2 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PC4, 1, 0x0300, WRITE_MASK_VAL(6, 6, 0)), /* HPDIN IO mux M0 */
-       RK_MUXROUTE_PMU(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */
+       RK_MUXROUTE_GRF(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */
        RK_MUXROUTE_GRF(3, RK_PB1, 3, 0x0300, WRITE_MASK_VAL(8, 8, 0)), /* GMAC1 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PA7, 3, 0x0300, WRITE_MASK_VAL(8, 8, 1)), /* GMAC1 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PD1, 1, 0x0300, WRITE_MASK_VAL(10, 10, 0)), /* HDMITX IO mux M0 */
-       RK_MUXROUTE_PMU(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */
+       RK_MUXROUTE_GRF(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PB4, 1, 0x0300, WRITE_MASK_VAL(14, 14, 1)), /* I2C2 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA0, 1, 0x0304, WRITE_MASK_VAL(0, 0, 0)), /* I2C3 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */
@@ -964,7 +964,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_GRF(4, RK_PC3, 1, 0x0308, WRITE_MASK_VAL(12, 12, 1)), /* PWM15 IO mux M1 */
        RK_MUXROUTE_GRF(3, RK_PD2, 3, 0x0308, WRITE_MASK_VAL(14, 14, 0)), /* SDMMC2 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PA5, 5, 0x0308, WRITE_MASK_VAL(14, 14, 1)), /* SDMMC2 IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD3, 3, 0x030c, WRITE_MASK_VAL(0, 0, 1)), /* SPI0 IO mux M1 */
        RK_MUXROUTE_GRF(2, RK_PB5, 3, 0x030c, WRITE_MASK_VAL(2, 2, 0)), /* SPI1 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */
@@ -973,8 +973,8 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_GRF(4, RK_PB3, 4, 0x030c, WRITE_MASK_VAL(6, 6, 0)), /* SPI3 IO mux M0 */
        RK_MUXROUTE_GRF(4, RK_PC2, 2, 0x030c, WRITE_MASK_VAL(6, 6, 1)), /* SPI3 IO mux M1 */
        RK_MUXROUTE_GRF(2, RK_PB4, 2, 0x030c, WRITE_MASK_VAL(8, 8, 0)), /* UART1 IO mux M0 */
-       RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */
-       RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */
+       RK_MUXROUTE_GRF(3, RK_PD6, 4, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */
+       RK_MUXROUTE_GRF(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */
        RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x030c, WRITE_MASK_VAL(10, 10, 1)), /* UART2 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA1, 2, 0x030c, WRITE_MASK_VAL(12, 12, 0)), /* UART3 IO mux M0 */
        RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */
@@ -1004,13 +1004,13 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
        RK_MUXROUTE_GRF(3, RK_PD6, 5, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */
        RK_MUXROUTE_GRF(3, RK_PC4, 5, 0x0314, WRITE_MASK_VAL(1, 0, 2)), /* PDM IO mux M2 */
-       RK_MUXROUTE_PMU(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 1)), /* PCIE20 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PB0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 2)), /* PCIE20 IO mux M2 */
-       RK_MUXROUTE_PMU(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD2, 4, 0x0314, WRITE_MASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux M1 */
        RK_MUXROUTE_GRF(1, RK_PA5, 4, 0x0314, WRITE_MASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux M2 */
-       RK_MUXROUTE_PMU(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */
+       RK_MUXROUTE_GRF(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */
        RK_MUXROUTE_GRF(2, RK_PD4, 4, 0x0314, WRITE_MASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux M1 */
        RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */
 };
@@ -2436,10 +2436,19 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
        case RK3308:
        case RK3368:
        case RK3399:
+       case RK3568:
        case RK3588:
                pull_type = bank->pull_type[pin_num / 8];
                data >>= bit;
                data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
+               /*
+                * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
+                * where that pull up value becomes 3.
+                */
+               if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
+                       if (data == 3)
+                               data = 1;
+               }
 
                return rockchip_pull_list[pull_type][data];
        default:
@@ -2497,7 +2506,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                        }
                }
                /*
-                * In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6,
+                * In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
                 * where that pull up value becomes 3.
                 */
                if (ctrl->type == RK3568 && bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
index 2b3335ab56c66867b21c4c41d385acc4b001fa9d..25101293268f6f579d569bf8ccd312c488620849 100644 (file)
@@ -499,7 +499,6 @@ static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
        return 0;
 }
 
-#ifdef CONFIG_DEBUG_FS
 static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
        const char *label;
@@ -521,7 +520,6 @@ static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                seq_puts(s, "\n");
        }
 }
-#endif
 
 static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pctl)
 {
@@ -550,9 +548,8 @@ static int sppctl_gpio_new(struct platform_device *pdev, struct sppctl_pdata *pc
        gchip->get              = sppctl_gpio_get;
        gchip->set              = sppctl_gpio_set;
        gchip->set_config       = sppctl_gpio_set_config;
-#ifdef CONFIG_DEBUG_FS
-       gchip->dbg_show         = sppctl_gpio_dbg_show;
-#endif
+       gchip->dbg_show         = IS_ENABLED(CONFIG_DEBUG_FS) ?
+                                 sppctl_gpio_dbg_show : NULL;
        gchip->base             = -1;
        gchip->ngpio            = sppctl_gpio_list_sz;
        gchip->names            = sppctl_gpio_list_s;
index a825af8126c83625b44efd76ca478a7a3cade1b7..2ce8cb2170dfc0f9258bd47c4a1d2398f5364c4f 100644 (file)
@@ -8,6 +8,7 @@ source "drivers/platform/x86/amd/pmf/Kconfig"
 config AMD_PMC
        tristate "AMD SoC PMC driver"
        depends on ACPI && PCI && RTC_CLASS
+       select SERIO
        help
          The driver provides support for AMD Power Management Controller
          primarily responsible for S2Idle transactions that are driven from
index 8d924986381bef2974b842d73b0eae25a31f099a..3cbb01ec10e32098f1265b6996b373dca0c4eced 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
+#include <linux/serio.h>
 #include <linux/suspend.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
@@ -160,6 +161,10 @@ static bool enable_stb;
 module_param(enable_stb, bool, 0644);
 MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism");
 
+static bool disable_workarounds;
+module_param(disable_workarounds, bool, 0644);
+MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs");
+
 static struct amd_pmc_dev pmc;
 static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret);
 static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf);
@@ -653,6 +658,33 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
        return -EINVAL;
 }
 
+static int amd_pmc_czn_wa_irq1(struct amd_pmc_dev *pdev)
+{
+       struct device *d;
+       int rc;
+
+       if (!pdev->major) {
+               rc = amd_pmc_get_smu_version(pdev);
+               if (rc)
+                       return rc;
+       }
+
+       if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65))
+               return 0;
+
+       d = bus_find_device_by_name(&serio_bus, NULL, "serio0");
+       if (!d)
+               return 0;
+       if (device_may_wakeup(d)) {
+               dev_info_once(d, "Disabling IRQ1 wakeup source to avoid platform firmware bug\n");
+               disable_irq_wake(1);
+               device_set_wakeup_enable(d, false);
+       }
+       put_device(d);
+
+       return 0;
+}
+
 static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg)
 {
        struct rtc_device *rtc_device;
@@ -715,8 +747,8 @@ static void amd_pmc_s2idle_prepare(void)
        /* Reset and Start SMU logging - to monitor the s0i3 stats */
        amd_pmc_setup_smu_logging(pdev);
 
-       /* Activate CZN specific RTC functionality */
-       if (pdev->cpu_id == AMD_CPU_ID_CZN) {
+       /* Activate CZN specific platform bug workarounds */
+       if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) {
                rc = amd_pmc_verify_czn_rtc(pdev, &arg);
                if (rc) {
                        dev_err(pdev->dev, "failed to set RTC: %d\n", rc);
@@ -782,6 +814,25 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = {
        .check = amd_pmc_s2idle_check,
        .restore = amd_pmc_s2idle_restore,
 };
+
+static int __maybe_unused amd_pmc_suspend_handler(struct device *dev)
+{
+       struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
+
+       if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) {
+               int rc = amd_pmc_czn_wa_irq1(pdev);
+
+               if (rc) {
+                       dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL);
+
 #endif
 
 static const struct pci_device_id pmc_pci_ids[] = {
@@ -980,6 +1031,9 @@ static struct platform_driver amd_pmc_driver = {
                .name = "amd_pmc",
                .acpi_match_table = amd_pmc_acpi_ids,
                .dev_groups = pmc_groups,
+#ifdef CONFIG_SUSPEND
+               .pm = &amd_pmc_pm,
+#endif
        },
        .probe = amd_pmc_probe,
        .remove = amd_pmc_remove,
index 644af42e07cf8168dee748042c5f92698fbc59a2..96a8e1832c05e9cbc9f50bb1305e7bfb92318213 100644 (file)
@@ -275,13 +275,8 @@ int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
         */
 
        if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
-               int mode = amd_pmf_get_pprof_modes(dev);
-
-               if (mode < 0)
-                       return mode;
-
                dev_dbg(dev->dev, "resetting AMT thermals\n");
-               amd_pmf_update_slider(dev, SLIDER_OP_SET, mode, NULL);
+               amd_pmf_set_sps_power_limits(dev);
        }
        return 0;
 }
@@ -299,7 +294,5 @@ void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
 void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)
 {
        amd_pmf_load_defaults_auto_mode(dev);
-       /* update the thermal limits for Automode */
-       amd_pmf_set_automode(dev, config_store.current_mode, NULL);
        amd_pmf_init_metrics_table(dev);
 }
index 3f9731a2ac28d6769a30141ae8be1c07a8172750..4beb22a194667d9f4d0bb67fb20c1de510a63eb9 100644 (file)
@@ -103,7 +103,7 @@ int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_l
 
        src = amd_pmf_cnqf_get_power_source(dev);
 
-       if (dev->current_profile == PLATFORM_PROFILE_BALANCED) {
+       if (is_pprof_balanced(dev)) {
                amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL);
        } else {
                /*
@@ -307,13 +307,9 @@ static ssize_t cnqf_enable_store(struct device *dev,
                                 const char *buf, size_t count)
 {
        struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
-       int mode, result, src;
+       int result, src;
        bool input;
 
-       mode = amd_pmf_get_pprof_modes(pdev);
-       if (mode < 0)
-               return mode;
-
        result = kstrtobool(buf, &input);
        if (result)
                return result;
@@ -321,11 +317,11 @@ static ssize_t cnqf_enable_store(struct device *dev,
        src = amd_pmf_cnqf_get_power_source(pdev);
        pdev->cnqf_enabled = input;
 
-       if (pdev->cnqf_enabled && pdev->current_profile == PLATFORM_PROFILE_BALANCED) {
+       if (pdev->cnqf_enabled && is_pprof_balanced(pdev)) {
                amd_pmf_set_cnqf(pdev, src, config_store.current_mode, NULL);
        } else {
                if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
-                       amd_pmf_update_slider(pdev, SLIDER_OP_SET, mode, NULL);
+                       amd_pmf_set_sps_power_limits(pdev);
        }
 
        dev_dbg(pdev->dev, "Received CnQF %s\n", input ? "on" : "off");
@@ -386,7 +382,7 @@ int amd_pmf_init_cnqf(struct amd_pmf_dev *dev)
        dev->cnqf_enabled = amd_pmf_check_flags(dev);
 
        /* update the thermal for CnQF */
-       if (dev->cnqf_enabled && dev->current_profile == PLATFORM_PROFILE_BALANCED) {
+       if (dev->cnqf_enabled && is_pprof_balanced(dev)) {
                src = amd_pmf_cnqf_get_power_source(dev);
                amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL);
        }
index a5f5a4bcff6d9a50c8a21e30c96e623aa935f718..da23639071d798c4ecfb170bd172771bb32c6375 100644 (file)
@@ -58,6 +58,25 @@ static bool force_load;
 module_param(force_load, bool, 0444);
 MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
 
+static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
+{
+       struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
+
+       if (event != PSY_EVENT_PROP_CHANGED)
+               return NOTIFY_OK;
+
+       if (is_apmf_func_supported(pmf, APMF_FUNC_AUTO_MODE) ||
+           is_apmf_func_supported(pmf, APMF_FUNC_DYN_SLIDER_DC) ||
+           is_apmf_func_supported(pmf, APMF_FUNC_DYN_SLIDER_AC)) {
+               if ((pmf->amt_enabled || pmf->cnqf_enabled) && is_pprof_balanced(pmf))
+                       return NOTIFY_DONE;
+       }
+
+       amd_pmf_set_sps_power_limits(pmf);
+
+       return NOTIFY_OK;
+}
+
 static int current_power_limits_show(struct seq_file *seq, void *unused)
 {
        struct amd_pmf_dev *dev = seq->private;
@@ -366,14 +385,18 @@ static int amd_pmf_probe(struct platform_device *pdev)
        if (!dev->regbase)
                return -ENOMEM;
 
+       mutex_init(&dev->lock);
+       mutex_init(&dev->update_mutex);
+
        apmf_acpi_init(dev);
        platform_set_drvdata(pdev, dev);
        amd_pmf_init_features(dev);
        apmf_install_handler(dev);
        amd_pmf_dbgfs_register(dev);
 
-       mutex_init(&dev->lock);
-       mutex_init(&dev->update_mutex);
+       dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
+       power_supply_reg_notifier(&dev->pwr_src_notifier);
+
        dev_info(dev->dev, "registered PMF device successfully\n");
 
        return 0;
@@ -383,11 +406,12 @@ static int amd_pmf_remove(struct platform_device *pdev)
 {
        struct amd_pmf_dev *dev = platform_get_drvdata(pdev);
 
-       mutex_destroy(&dev->lock);
-       mutex_destroy(&dev->update_mutex);
+       power_supply_unreg_notifier(&dev->pwr_src_notifier);
        amd_pmf_deinit_features(dev);
        apmf_acpi_deinit(dev);
        amd_pmf_dbgfs_unregister(dev);
+       mutex_destroy(&dev->lock);
+       mutex_destroy(&dev->update_mutex);
        kfree(dev->buf);
        return 0;
 }
index 84bbe2c6ea612b88ab9aea13e3d139f46f98e670..06c30cdc05733ac997ebe3227252bbb7d55397bd 100644 (file)
@@ -169,6 +169,7 @@ struct amd_pmf_dev {
        struct mutex update_mutex; /* protects race between ACPI handler and metrics thread */
        bool cnqf_enabled;
        bool cnqf_supported;
+       struct notifier_block pwr_src_notifier;
 };
 
 struct apmf_sps_prop_granular {
@@ -391,9 +392,11 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev);
 void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
 int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
                                    struct apmf_static_slider_granular_output *output);
+bool is_pprof_balanced(struct amd_pmf_dev *pmf);
 
 
 int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
+int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf);
 
 /* Auto Mode Layer */
 int apmf_get_auto_mode_def(struct amd_pmf_dev *pdev, struct apmf_auto_mode *data);
index dba7e36962dc1eadd034dcd8e61d9ebfe51fd93f..bed762d47a14a5edcf39e78387041834d4c2033f 100644 (file)
@@ -70,6 +70,24 @@ void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
        }
 }
 
+int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf)
+{
+       int mode;
+
+       mode = amd_pmf_get_pprof_modes(pmf);
+       if (mode < 0)
+               return mode;
+
+       amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
+
+       return 0;
+}
+
+bool is_pprof_balanced(struct amd_pmf_dev *pmf)
+{
+       return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;
+}
+
 static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
                               enum platform_profile_option *profile)
 {
@@ -105,15 +123,10 @@ static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
                               enum platform_profile_option profile)
 {
        struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
-       int mode;
 
        pmf->current_profile = profile;
-       mode = amd_pmf_get_pprof_modes(pmf);
-       if (mode < 0)
-               return mode;
 
-       amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
-       return 0;
+       return amd_pmf_set_sps_power_limits(pmf);
 }
 
 int amd_pmf_init_sps(struct amd_pmf_dev *dev)
@@ -123,6 +136,9 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
        dev->current_profile = PLATFORM_PROFILE_BALANCED;
        amd_pmf_load_defaults_sps(dev);
 
+       /* update SPS balanced power mode thermals */
+       amd_pmf_set_sps_power_limits(dev);
+
        dev->pprof.profile_get = amd_pmf_profile_get;
        dev->pprof.profile_set = amd_pmf_profile_set;
 
index ca33df7ea550ee1f88aeaa82578863d44b9afe2e..9333f82cfa8a0b00df176e20fc6c57911a653642 100644 (file)
@@ -64,29 +64,6 @@ struct apple_gmux_data {
 
 static struct apple_gmux_data *apple_gmux_data;
 
-/*
- * gmux port offsets. Many of these are not yet used, but may be in the
- * future, and it's useful to have them documented here anyhow.
- */
-#define GMUX_PORT_VERSION_MAJOR                0x04
-#define GMUX_PORT_VERSION_MINOR                0x05
-#define GMUX_PORT_VERSION_RELEASE      0x06
-#define GMUX_PORT_SWITCH_DISPLAY       0x10
-#define GMUX_PORT_SWITCH_GET_DISPLAY   0x11
-#define GMUX_PORT_INTERRUPT_ENABLE     0x14
-#define GMUX_PORT_INTERRUPT_STATUS     0x16
-#define GMUX_PORT_SWITCH_DDC           0x28
-#define GMUX_PORT_SWITCH_EXTERNAL      0x40
-#define GMUX_PORT_SWITCH_GET_EXTERNAL  0x41
-#define GMUX_PORT_DISCRETE_POWER       0x50
-#define GMUX_PORT_MAX_BRIGHTNESS       0x70
-#define GMUX_PORT_BRIGHTNESS           0x74
-#define GMUX_PORT_VALUE                        0xc2
-#define GMUX_PORT_READ                 0xd0
-#define GMUX_PORT_WRITE                        0xd4
-
-#define GMUX_MIN_IO_LEN                        (GMUX_PORT_BRIGHTNESS + 4)
-
 #define GMUX_INTERRUPT_ENABLE          0xff
 #define GMUX_INTERRUPT_DISABLE         0x00
 
@@ -249,23 +226,6 @@ static void gmux_write32(struct apple_gmux_data *gmux_data, int port,
                gmux_pio_write32(gmux_data, port, val);
 }
 
-static bool gmux_is_indexed(struct apple_gmux_data *gmux_data)
-{
-       u16 val;
-
-       outb(0xaa, gmux_data->iostart + 0xcc);
-       outb(0x55, gmux_data->iostart + 0xcd);
-       outb(0x00, gmux_data->iostart + 0xce);
-
-       val = inb(gmux_data->iostart + 0xcc) |
-               (inb(gmux_data->iostart + 0xcd) << 8);
-
-       if (val == 0x55aa)
-               return true;
-
-       return false;
-}
-
 /**
  * DOC: Backlight control
  *
@@ -605,60 +565,43 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
        int ret = -ENXIO;
        acpi_status status;
        unsigned long long gpe;
+       bool indexed = false;
+       u32 version;
 
        if (apple_gmux_data)
                return -EBUSY;
 
+       if (!apple_gmux_detect(pnp, &indexed)) {
+               pr_info("gmux device not present\n");
+               return -ENODEV;
+       }
+
        gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL);
        if (!gmux_data)
                return -ENOMEM;
        pnp_set_drvdata(pnp, gmux_data);
 
        res = pnp_get_resource(pnp, IORESOURCE_IO, 0);
-       if (!res) {
-               pr_err("Failed to find gmux I/O resource\n");
-               goto err_free;
-       }
-
        gmux_data->iostart = res->start;
        gmux_data->iolen = resource_size(res);
 
-       if (gmux_data->iolen < GMUX_MIN_IO_LEN) {
-               pr_err("gmux I/O region too small (%lu < %u)\n",
-                      gmux_data->iolen, GMUX_MIN_IO_LEN);
-               goto err_free;
-       }
-
        if (!request_region(gmux_data->iostart, gmux_data->iolen,
                            "Apple gmux")) {
                pr_err("gmux I/O already in use\n");
                goto err_free;
        }
 
-       /*
-        * Invalid version information may indicate either that the gmux
-        * device isn't present or that it's a new one that uses indexed
-        * io
-        */
-
-       ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
-       ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
-       ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
-       if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
-               if (gmux_is_indexed(gmux_data)) {
-                       u32 version;
-                       mutex_init(&gmux_data->index_lock);
-                       gmux_data->indexed = true;
-                       version = gmux_read32(gmux_data,
-                               GMUX_PORT_VERSION_MAJOR);
-                       ver_major = (version >> 24) & 0xff;
-                       ver_minor = (version >> 16) & 0xff;
-                       ver_release = (version >> 8) & 0xff;
-               } else {
-                       pr_info("gmux device not present\n");
-                       ret = -ENODEV;
-                       goto err_release;
-               }
+       if (indexed) {
+               mutex_init(&gmux_data->index_lock);
+               gmux_data->indexed = true;
+               version = gmux_read32(gmux_data, GMUX_PORT_VERSION_MAJOR);
+               ver_major = (version >> 24) & 0xff;
+               ver_minor = (version >> 16) & 0xff;
+               ver_release = (version >> 8) & 0xff;
+       } else {
+               ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
+               ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
+               ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
        }
        pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
                ver_release, (gmux_data->indexed ? "indexed" : "classic"));
index 104188d70988cbae085b1050fb7d3832e5a5fdb8..1038dfdcdd3250dc24a0e6d95ad9c7e4ae3196d5 100644 (file)
@@ -225,6 +225,7 @@ struct asus_wmi {
 
        int tablet_switch_event_code;
        u32 tablet_switch_dev_id;
+       bool tablet_switch_inverted;
 
        enum fan_type fan_type;
        enum fan_type gpu_fan_type;
@@ -493,6 +494,13 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)
 }
 
 /* Input **********************************************************************/
+static void asus_wmi_tablet_sw_report(struct asus_wmi *asus, bool value)
+{
+       input_report_switch(asus->inputdev, SW_TABLET_MODE,
+                           asus->tablet_switch_inverted ? !value : value);
+       input_sync(asus->inputdev);
+}
+
 static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code)
 {
        struct device *dev = &asus->platform_device->dev;
@@ -501,7 +509,7 @@ static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event
        result = asus_wmi_get_devstate_simple(asus, dev_id);
        if (result >= 0) {
                input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-               input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
+               asus_wmi_tablet_sw_report(asus, result);
                asus->tablet_switch_dev_id = dev_id;
                asus->tablet_switch_event_code = event_code;
        } else if (result == -ENODEV) {
@@ -534,6 +542,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
        case asus_wmi_no_tablet_switch:
                break;
        case asus_wmi_kbd_dock_devid:
+               asus->tablet_switch_inverted = true;
                asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE);
                break;
        case asus_wmi_lid_flip_devid:
@@ -573,10 +582,8 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus)
                return;
 
        result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id);
-       if (result >= 0) {
-               input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
-               input_sync(asus->inputdev);
-       }
+       if (result >= 0)
+               asus_wmi_tablet_sw_report(asus, result);
 }
 
 /* dGPU ********************************************************************/
index 0a259a27459f6de978122967fb550524279f5375..502783a7adb118322d2b8c158b56b3c1ac268776 100644 (file)
@@ -261,6 +261,9 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = {
        { KE_KEY,    0x57, { KEY_BRIGHTNESSDOWN } },
        { KE_KEY,    0x58, { KEY_BRIGHTNESSUP } },
 
+       /*Speaker Mute*/
+       { KE_KEY, 0x109, { KEY_MUTE} },
+
        /* Mic mute */
        { KE_KEY, 0x150, { KEY_MICMUTE } },
 
index 5e7e6659a84971e7cd5227470848659e5ed533d6..322cfaeda17badd650ee3e74cee779e9f7cf6fb7 100644 (file)
@@ -141,6 +141,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev)
 
 static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"),
index 0a99058be81304c8e55e12410524a10a655b6c53..2ef201b625b38cdc35249415004db859215e78a3 100644 (file)
@@ -90,6 +90,7 @@ enum hp_wmi_event_ids {
        HPWMI_PEAKSHIFT_PERIOD          = 0x0F,
        HPWMI_BATTERY_CHARGE_PERIOD     = 0x10,
        HPWMI_SANITIZATION_MODE         = 0x17,
+       HPWMI_OMEN_KEY                  = 0x1D,
        HPWMI_SMART_EXPERIENCE_APP      = 0x21,
 };
 
@@ -216,6 +217,8 @@ static const struct key_entry hp_wmi_keymap[] = {
        { KE_KEY, 0x213b,  { KEY_INFO } },
        { KE_KEY, 0x2169,  { KEY_ROTATE_DISPLAY } },
        { KE_KEY, 0x216a,  { KEY_SETUP } },
+       { KE_KEY, 0x21a5,  { KEY_PROG2 } }, /* HP Omen Key */
+       { KE_KEY, 0x21a7,  { KEY_FN_ESC } },
        { KE_KEY, 0x21a9,  { KEY_TOUCHPAD_OFF } },
        { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } },
        { KE_KEY, 0x231b,  { KEY_HELP } },
@@ -548,7 +551,7 @@ static int __init hp_wmi_enable_hotkeys(void)
 
 static int hp_wmi_set_block(void *data, bool blocked)
 {
-       enum hp_wmi_radio r = (enum hp_wmi_radio) data;
+       enum hp_wmi_radio r = (long)data;
        int query = BIT(r + 8) | ((!blocked) << r);
        int ret;
 
@@ -810,6 +813,7 @@ static void hp_wmi_notify(u32 value, void *context)
        case HPWMI_SMART_ADAPTER:
                break;
        case HPWMI_BEZEL_BUTTON:
+       case HPWMI_OMEN_KEY:
                key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
                if (key_code < 0)
                        break;
index a95946800ae9d3f947acbf752f69afdcd3114210..32c10457399e442ac15ec28ada09d851155f34d8 100644 (file)
@@ -5563,7 +5563,7 @@ static int light_sysfs_set(struct led_classdev *led_cdev,
 
 static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev)
 {
-       return (light_get_status() == 1) ? LED_FULL : LED_OFF;
+       return (light_get_status() == 1) ? LED_ON : LED_OFF;
 }
 
 static struct tpacpi_led_classdev tpacpi_led_thinklight = {
@@ -10496,8 +10496,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
                        if (err)
                                goto unlock;
                }
-       }
-       if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
+       } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
                err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output);
                if (err)
                        goto unlock;
@@ -10525,14 +10524,16 @@ static void dytc_profile_refresh(void)
                        err = dytc_command(DYTC_CMD_MMC_GET, &output);
                else
                        err = dytc_cql_command(DYTC_CMD_GET, &output);
-       } else if (dytc_capabilities & BIT(DYTC_FC_PSC))
+               funcmode = DYTC_FUNCTION_MMC;
+       } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
                err = dytc_command(DYTC_CMD_GET, &output);
-
+               /* Check if we are PSC mode, or have AMT enabled */
+               funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF;
+       }
        mutex_unlock(&dytc_mutex);
        if (err)
                return;
 
-       funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF;
        perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
        convert_dytc_to_profile(funcmode, perfmode, &profile);
        if (profile != dytc_current_profile) {
index f00995390fdfe0ef91b60f5ad5ad7bc2c1d08580..13802a3c3591d8cd71f5c96928a6162875d10cf9 100644 (file)
@@ -1097,6 +1097,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
                },
        },
+       {
+               /* Chuwi Vi8 (CWI501) */
+               .driver_data = (void *)&chuwi_vi8_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.W86JLBNR01"),
+               },
+       },
        {
                /* Chuwi Vi8 (CWI506) */
                .driver_data = (void *)&chuwi_vi8_data,
index de176c2fbad96d3165fba9172ce71a0531ba8d3b..2a52c990d4fecbe7d6044388bfc430e24b66fb3f 100644 (file)
@@ -257,7 +257,7 @@ config RESET_SUNXI
 
 config RESET_TI_SCI
        tristate "TI System Control Interface (TI-SCI) reset driver"
-       depends on TI_SCI_PROTOCOL || COMPILE_TEST
+       depends on TI_SCI_PROTOCOL || (COMPILE_TEST && TI_SCI_PROTOCOL=n)
        help
          This enables the reset driver support over TI System Control Interface
          available on some new TI's SoCs. If you wish to use reset resources
index 146fd5d45e99d3e68695965888f3949ceb7bc0b7..15abac9fc72c074adaeec0a8f98ce73d1355d26a 100644 (file)
@@ -47,7 +47,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct uniphier_glue_reset_priv *priv;
        struct resource *res;
-       resource_size_t size;
        int i, ret;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -60,7 +59,6 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
                return -EINVAL;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       size = resource_size(res);
        priv->rdata.membase = devm_ioremap_resource(dev, res);
        if (IS_ERR(priv->rdata.membase))
                return PTR_ERR(priv->rdata.membase);
@@ -96,7 +94,7 @@ static int uniphier_glue_reset_probe(struct platform_device *pdev)
 
        spin_lock_init(&priv->rdata.lock);
        priv->rdata.rcdev.owner = THIS_MODULE;
-       priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
+       priv->rdata.rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
        priv->rdata.rcdev.ops = &reset_simple_ops;
        priv->rdata.rcdev.of_node = dev->of_node;
        priv->rdata.active_low = true;
index e991cccdb6e9cee46a104b03926d4f2945f34f59..1e8bc6cc1e12d85583e674fe476fb787bab635b0 100644 (file)
@@ -188,9 +188,10 @@ static int efi_set_time(struct device *dev, struct rtc_time *tm)
 
 static int efi_procfs(struct device *dev, struct seq_file *seq)
 {
-       efi_time_t      eft, alm;
-       efi_time_cap_t  cap;
-       efi_bool_t      enabled, pending;
+       efi_time_t        eft, alm;
+       efi_time_cap_t    cap;
+       efi_bool_t        enabled, pending;
+       struct rtc_device *rtc = dev_get_drvdata(dev);
 
        memset(&eft, 0, sizeof(eft));
        memset(&alm, 0, sizeof(alm));
@@ -213,23 +214,25 @@ static int efi_procfs(struct device *dev, struct seq_file *seq)
                /* XXX fixme: convert to string? */
                seq_printf(seq, "Timezone\t: %u\n", eft.timezone);
 
-       seq_printf(seq,
-                  "Alarm Time\t: %u:%u:%u.%09u\n"
-                  "Alarm Date\t: %u-%u-%u\n"
-                  "Alarm Daylight\t: %u\n"
-                  "Enabled\t\t: %s\n"
-                  "Pending\t\t: %s\n",
-                  alm.hour, alm.minute, alm.second, alm.nanosecond,
-                  alm.year, alm.month, alm.day,
-                  alm.daylight,
-                  enabled == 1 ? "yes" : "no",
-                  pending == 1 ? "yes" : "no");
-
-       if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
-               seq_puts(seq, "Timezone\t: unspecified\n");
-       else
-               /* XXX fixme: convert to string? */
-               seq_printf(seq, "Timezone\t: %u\n", alm.timezone);
+       if (test_bit(RTC_FEATURE_ALARM, rtc->features)) {
+               seq_printf(seq,
+                          "Alarm Time\t: %u:%u:%u.%09u\n"
+                          "Alarm Date\t: %u-%u-%u\n"
+                          "Alarm Daylight\t: %u\n"
+                          "Enabled\t\t: %s\n"
+                          "Pending\t\t: %s\n",
+                          alm.hour, alm.minute, alm.second, alm.nanosecond,
+                          alm.year, alm.month, alm.day,
+                          alm.daylight,
+                          enabled == 1 ? "yes" : "no",
+                          pending == 1 ? "yes" : "no");
+
+               if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
+                       seq_puts(seq, "Timezone\t: unspecified\n");
+               else
+                       /* XXX fixme: convert to string? */
+                       seq_printf(seq, "Timezone\t: %u\n", alm.timezone);
+       }
 
        /*
         * now prints the capabilities
@@ -269,7 +272,10 @@ static int __init efi_rtc_probe(struct platform_device *dev)
 
        rtc->ops = &efi_rtc_ops;
        clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
-       set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->features);
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_WAKEUP_SERVICES))
+               set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->features);
+       else
+               clear_bit(RTC_FEATURE_ALARM, rtc->features);
 
        device_init_wakeup(&dev->dev, true);
 
index e8e2ab1103fc049fcfe56aa8e629129847bb6254..4b578e4d44f6aeb48583be4ac5cf7da82b3f96d4 100644 (file)
@@ -240,8 +240,8 @@ static int sp_rtc_probe(struct platform_device *plat_dev)
        if (IS_ERR(sp_rtc->reg_base))
                return dev_err_probe(&plat_dev->dev, PTR_ERR(sp_rtc->reg_base),
                                            "%s devm_ioremap_resource fail\n", RTC_REG_NAME);
-       dev_dbg(&plat_dev->dev, "res = 0x%x, reg_base = 0x%lx\n",
-               sp_rtc->res->start, (unsigned long)sp_rtc->reg_base);
+       dev_dbg(&plat_dev->dev, "res = %pR, reg_base = %p\n",
+               sp_rtc->ressp_rtc->reg_base);
 
        sp_rtc->irq = platform_get_irq(plat_dev, 0);
        if (sp_rtc->irq < 0)
index 49cc18a8747313e5729fccb02f55c292d58c52bc..29a2865b8e2e1453ac8629cb2de307dc3687efbb 100644 (file)
@@ -981,6 +981,9 @@ queue_rtpg:
  *
  * Returns true if and only if alua_rtpg_work() will be called asynchronously.
  * That function is responsible for calling @qdata->fn().
+ *
+ * Context: may be called from atomic context (alua_check()) only if the caller
+ *     holds an sdev reference.
  */
 static bool alua_rtpg_queue(struct alua_port_group *pg,
                            struct scsi_device *sdev,
@@ -989,8 +992,6 @@ static bool alua_rtpg_queue(struct alua_port_group *pg,
        int start_queue = 0;
        unsigned long flags;
 
-       might_sleep();
-
        if (WARN_ON_ONCE(!pg) || scsi_device_get(sdev))
                return false;
 
index 4dbf51e2623ad543bea3f74bf2940d8f9be95509..f6da34850af9dd462fe8bb556fae35f21b1926ae 100644 (file)
@@ -5850,7 +5850,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
 {
        struct Scsi_Host *sh;
 
-       sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
+       sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info));
        if (sh == NULL) {
                dev_err(&h->pdev->dev, "scsi_host_alloc failed\n");
                return -ENOMEM;
index 1d1cf641937c14738596a68d6cb546c576bef741..0454d94e8cf0d44a9e53e6a3f5fced550032be27 100644 (file)
@@ -849,7 +849,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
                                       enum iscsi_host_param param, char *buf)
 {
        struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
-       struct iscsi_session *session = tcp_sw_host->session;
+       struct iscsi_session *session;
        struct iscsi_conn *conn;
        struct iscsi_tcp_conn *tcp_conn;
        struct iscsi_sw_tcp_conn *tcp_sw_conn;
@@ -859,6 +859,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
 
        switch (param) {
        case ISCSI_HOST_PARAM_IPADDRESS:
+               session = tcp_sw_host->session;
                if (!session)
                        return -ENOTCONN;
 
@@ -959,11 +960,13 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
        if (!cls_session)
                goto remove_host;
        session = cls_session->dd_data;
-       tcp_sw_host = iscsi_host_priv(shost);
-       tcp_sw_host->session = session;
 
        if (iscsi_tcp_r2tpool_alloc(session))
                goto remove_session;
+
+       /* We are now fully setup so expose the session to sysfs. */
+       tcp_sw_host = iscsi_host_priv(shost);
+       tcp_sw_host->session = session;
        return cls_session;
 
 remove_session:
@@ -983,10 +986,17 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
        if (WARN_ON_ONCE(session->leadconn))
                return;
 
+       iscsi_session_remove(cls_session);
+       /*
+        * Our get_host_param needs to access the session, so remove the
+        * host from sysfs before freeing the session to make sure userspace
+        * is no longer accessing the callout.
+        */
+       iscsi_host_remove(shost, false);
+
        iscsi_tcp_r2tpool_free(cls_session->dd_data);
-       iscsi_session_teardown(cls_session);
 
-       iscsi_host_remove(shost, false);
+       iscsi_session_free(cls_session);
        iscsi_host_free(shost);
 }
 
index ef2fc860257e6e1b1614a50528bd4b244adb4e2a..127f3d7f19dc69bde17335e10b2a191730a617a2 100644 (file)
@@ -3104,17 +3104,32 @@ dec_session_count:
 }
 EXPORT_SYMBOL_GPL(iscsi_session_setup);
 
-/**
- * iscsi_session_teardown - destroy session, host, and cls_session
- * @cls_session: iscsi session
+/*
+ * issi_session_remove - Remove session from iSCSI class.
  */
-void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+void iscsi_session_remove(struct iscsi_cls_session *cls_session)
 {
        struct iscsi_session *session = cls_session->dd_data;
-       struct module *owner = cls_session->transport->owner;
        struct Scsi_Host *shost = session->host;
 
        iscsi_remove_session(cls_session);
+       /*
+        * host removal only has to wait for its children to be removed from
+        * sysfs, and iscsi_tcp needs to do iscsi_host_remove before freeing
+        * the session, so drop the session count here.
+        */
+       iscsi_host_dec_session_cnt(shost);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_remove);
+
+/**
+ * iscsi_session_free - Free iscsi session and it's resources
+ * @cls_session: iscsi session
+ */
+void iscsi_session_free(struct iscsi_cls_session *cls_session)
+{
+       struct iscsi_session *session = cls_session->dd_data;
+       struct module *owner = cls_session->transport->owner;
 
        iscsi_pool_free(&session->cmdpool);
        kfree(session->password);
@@ -3132,10 +3147,19 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
        kfree(session->discovery_parent_type);
 
        iscsi_free_session(cls_session);
-
-       iscsi_host_dec_session_cnt(shost);
        module_put(owner);
 }
+EXPORT_SYMBOL_GPL(iscsi_session_free);
+
+/**
+ * iscsi_session_teardown - destroy session and cls_session
+ * @cls_session: iscsi session
+ */
+void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+{
+       iscsi_session_remove(cls_session);
+       iscsi_session_free(cls_session);
+}
 EXPORT_SYMBOL_GPL(iscsi_session_teardown);
 
 /**
index 1426b9b03612f9628e6e85af0484675ab8147f3a..9feb0323bc44a536703faa5801ccd587bcc1e5ab 100644 (file)
@@ -588,8 +588,6 @@ void scsi_device_put(struct scsi_device *sdev)
 {
        struct module *mod = sdev->host->hostt->module;
 
-       might_sleep();
-
        put_device(&sdev->sdev_gendev);
        module_put(mod);
 }
index 7a6904a3928e6f8a20115890827e4f29de6f0339..f9b18fdc7b3c8ea3c3b552e49c7ee943ca8f61f0 100644 (file)
@@ -1232,8 +1232,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
         * that no LUN is present, so don't add sdev in these cases.
         * Two specific examples are:
         * 1) NetApp targets: return PQ=1, PDT=0x1f
-        * 2) IBM/2145 targets: return PQ=1, PDT=0
-        * 3) USB UFI: returns PDT=0x1f, with the PQ bits being "reserved"
+        * 2) USB UFI: returns PDT=0x1f, with the PQ bits being "reserved"
         *    in the UFI 1.0 spec (we cannot rely on reserved bits).
         *
         * References:
@@ -1247,8 +1246,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
         * PDT=00h Direct-access device (floppy)
         * PDT=1Fh none (no FDD connected to the requested logical unit)
         */
-       if (((result[0] >> 5) == 1 ||
-           (starget->pdt_1f_for_no_lun && (result[0] & 0x1f) == 0x1f)) &&
+       if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) &&
+           (result[0] & 0x1f) == 0x1f &&
            !scsi_is_wlun(lun)) {
                SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev,
                                        "scsi scan: peripheral device type"
index 981d1bab21207166b97f0003830d069bb01ff615..8ef9a54943403a8c717ed64bbe44181a6bed1ece 100644 (file)
@@ -451,6 +451,8 @@ static void scsi_device_dev_release(struct device *dev)
        struct scsi_vpd *vpd_pgb0 = NULL, *vpd_pgb1 = NULL, *vpd_pgb2 = NULL;
        unsigned long flags;
 
+       might_sleep();
+
        scsi_dh_release_device(sdev);
 
        parent = sdev->sdev_gendev.parent;
index 0e3b6ba22f943e0b3bd2a1c64189e3a1e964d137..0f13853901dfeceb667f20c3513665376393f76e 100644 (file)
@@ -212,7 +212,7 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
                break;
        case IMX8MP_HDMIBLK_PD_LCDIF:
                regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                               BIT(7) | BIT(16) | BIT(17) | BIT(18) |
+                               BIT(16) | BIT(17) | BIT(18) |
                                BIT(19) | BIT(20));
                regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
                regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0,
@@ -241,6 +241,7 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
                regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(1));
                break;
        case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
+               regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
                regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
                regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
                regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
@@ -270,7 +271,7 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
                                  BIT(4) | BIT(5) | BIT(6));
                regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(11));
                regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
-                                 BIT(7) | BIT(16) | BIT(17) | BIT(18) |
+                                 BIT(16) | BIT(17) | BIT(18) |
                                  BIT(19) | BIT(20));
                break;
        case IMX8MP_HDMIBLK_PD_PAI:
@@ -298,6 +299,7 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
        case IMX8MP_HDMIBLK_PD_HDMI_TX_PHY:
                regmap_set_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
                regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
+               regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
                regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
                break;
        case IMX8MP_HDMIBLK_PD_HDCP:
@@ -590,7 +592,6 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
                        ret = PTR_ERR(domain->power_dev);
                        goto cleanup_pds;
                }
-               dev_set_name(domain->power_dev, "%s", data->name);
 
                domain->genpd.name = data->name;
                domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
index 28144c699b0c39c0548a8f50d1b9ef44f34e155d..32ed9dc88e45563e346bbfdfda8b22d34b9c2139 100644 (file)
@@ -66,8 +66,8 @@ static u32 __init imx8mq_soc_revision(void)
        ocotp_base = of_iomap(np, 0);
        WARN_ON(!ocotp_base);
        clk = of_clk_get_by_name(np, NULL);
-       if (!clk) {
-               WARN_ON(!clk);
+       if (IS_ERR(clk)) {
+               WARN_ON(IS_ERR(clk));
                return 0;
        }
 
index cd44f17dad3d04cd3ec1f6b8d8614e3fb9828456..d51abb462ae5d3481d26a0bdc6ababe603d7ca26 100644 (file)
@@ -461,9 +461,10 @@ static int apr_add_device(struct device *dev, struct device_node *np,
                goto out;
        }
 
+       /* Protection domain is optional, it does not exist on older platforms */
        ret = of_property_read_string_index(np, "qcom,protection-domain",
                                            1, &adev->service_path);
-       if (ret < 0) {
+       if (ret < 0 && ret != -EINVAL) {
                dev_err(dev, "Failed to read second value of qcom,protection-domain\n");
                goto out;
        }
index e9b854ed1bdfd645caaa235fc5d18f0fb8362488..144ea68e0920a31da9476293a2075ab30ac75e36 100644 (file)
@@ -1708,12 +1708,16 @@ static int cpr_probe(struct platform_device *pdev)
 
        ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd);
        if (ret)
-               return ret;
+               goto err_remove_genpd;
 
        platform_set_drvdata(pdev, drv);
        cpr_debugfs_init(drv);
 
        return 0;
+
+err_remove_genpd:
+       pm_genpd_remove(&drv->pd);
+       return ret;
 }
 
 static int cpr_remove(struct platform_device *pdev)
index db1441c0cc662092fd238cdf8116b6c6def3b880..690ab7165b2c18cddcfcb194cef1c6b3f3571b69 100644 (file)
@@ -86,7 +86,7 @@ struct vchiq_service_params_kernel {
 
 struct vchiq_instance;
 
-extern enum vchiq_status vchiq_initialise(struct vchiq_instance **pinstance);
+extern int vchiq_initialise(struct vchiq_instance **pinstance);
 extern enum vchiq_status vchiq_shutdown(struct vchiq_instance *instance);
 extern enum vchiq_status vchiq_connect(struct vchiq_instance *instance);
 extern enum vchiq_status vchiq_open_service(struct vchiq_instance *instance,
index 2851ef6b9cd0f628ea17de94861bfebfe1b22c35..cd20eb18f27513cbe19efd025cfed2ae334e3fe7 100644 (file)
@@ -100,10 +100,10 @@ vchiq_dump_platform_use_state(struct vchiq_state *state);
 extern void
 vchiq_dump_service_use_state(struct vchiq_state *state);
 
-extern enum vchiq_status
+extern int
 vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service,
                   enum USE_TYPE_E use_type);
-extern enum vchiq_status
+extern int
 vchiq_release_internal(struct vchiq_state *state,
                       struct vchiq_service *service);
 
index bac111456fa1de9af63e27b6921d8c77c4ec535b..2b95b4550a637bce4545f7112ab54524a82dbc3a 100644 (file)
@@ -73,8 +73,8 @@ static bool __target_check_io_state(struct se_cmd *se_cmd,
 {
        struct se_session *sess = se_cmd->se_sess;
 
-       assert_spin_locked(&sess->sess_cmd_lock);
-       WARN_ON_ONCE(!irqs_disabled());
+       lockdep_assert_held(&sess->sess_cmd_lock);
+
        /*
         * If command already reached CMD_T_COMPLETE state within
         * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown,
index 62c0aa5d0783770baac479928c3a31a922b1c117..0a4eaa307156d6d24936ea85960e632a32f51351 100644 (file)
@@ -44,11 +44,13 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
                                         int trip, int *temp)
 {
        struct int34x_thermal_zone *d = zone->devdata;
-       int i;
+       int i, ret = 0;
 
        if (d->override_ops && d->override_ops->get_trip_temp)
                return d->override_ops->get_trip_temp(zone, trip, temp);
 
+       mutex_lock(&d->trip_mutex);
+
        if (trip < d->aux_trip_nr)
                *temp = d->aux_trips[trip];
        else if (trip == d->crt_trip_id)
@@ -66,10 +68,12 @@ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
                        }
                }
                if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
-                       return -EINVAL;
+                       ret = -EINVAL;
        }
 
-       return 0;
+       mutex_unlock(&d->trip_mutex);
+
+       return ret;
 }
 
 static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
@@ -77,11 +81,13 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
                                         enum thermal_trip_type *type)
 {
        struct int34x_thermal_zone *d = zone->devdata;
-       int i;
+       int i, ret = 0;
 
        if (d->override_ops && d->override_ops->get_trip_type)
                return d->override_ops->get_trip_type(zone, trip, type);
 
+       mutex_lock(&d->trip_mutex);
+
        if (trip < d->aux_trip_nr)
                *type = THERMAL_TRIP_PASSIVE;
        else if (trip == d->crt_trip_id)
@@ -99,10 +105,12 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
                        }
                }
                if (i == INT340X_THERMAL_MAX_ACT_TRIP_COUNT)
-                       return -EINVAL;
+                       ret = -EINVAL;
        }
 
-       return 0;
+       mutex_unlock(&d->trip_mutex);
+
+       return ret;
 }
 
 static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
@@ -180,6 +188,8 @@ int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
        int trip_cnt = int34x_zone->aux_trip_nr;
        int i;
 
+       mutex_lock(&int34x_zone->trip_mutex);
+
        int34x_zone->crt_trip_id = -1;
        if (!int340x_thermal_get_trip_config(int34x_zone->adev->handle, "_CRT",
                                             &int34x_zone->crt_temp))
@@ -207,6 +217,8 @@ int int340x_thermal_read_trips(struct int34x_thermal_zone *int34x_zone)
                int34x_zone->act_trips[i].valid = true;
        }
 
+       mutex_unlock(&int34x_zone->trip_mutex);
+
        return trip_cnt;
 }
 EXPORT_SYMBOL_GPL(int340x_thermal_read_trips);
@@ -230,6 +242,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
        if (!int34x_thermal_zone)
                return ERR_PTR(-ENOMEM);
 
+       mutex_init(&int34x_thermal_zone->trip_mutex);
+
        int34x_thermal_zone->adev = adev;
        int34x_thermal_zone->override_ops = override_ops;
 
@@ -281,6 +295,7 @@ err_thermal_zone:
        acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
        kfree(int34x_thermal_zone->aux_trips);
 err_trip_alloc:
+       mutex_destroy(&int34x_thermal_zone->trip_mutex);
        kfree(int34x_thermal_zone);
        return ERR_PTR(ret);
 }
@@ -292,6 +307,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone
        thermal_zone_device_unregister(int34x_thermal_zone->zone);
        acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
        kfree(int34x_thermal_zone->aux_trips);
+       mutex_destroy(&int34x_thermal_zone->trip_mutex);
        kfree(int34x_thermal_zone);
 }
 EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
index 3b4971df1b33b00534123783f3da2e2670d4abb9..8f9872afd0d3c70a7af2060c09de71474760a6fc 100644 (file)
@@ -32,6 +32,7 @@ struct int34x_thermal_zone {
        struct thermal_zone_device_ops *override_ops;
        void *priv_data;
        struct acpi_lpat_conversion_table *lpat_table;
+       struct mutex trip_mutex;
 };
 
 struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *,
index f17ab2316dbd0f36b79d89d10852d0bf683d0170..77bd47d976a21c237298b24e948b1535db4037b7 100644 (file)
@@ -909,15 +909,20 @@ __thermal_cooling_device_register(struct device_node *np,
        cdev->devdata = devdata;
 
        ret = cdev->ops->get_max_state(cdev, &cdev->max_state);
-       if (ret)
-               goto out_kfree_type;
+       if (ret) {
+               kfree(cdev->type);
+               goto out_ida_remove;
+       }
 
        thermal_cooling_device_setup_sysfs(cdev);
+
        ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
        if (ret) {
+               kfree(cdev->type);
                thermal_cooling_device_destroy_sysfs(cdev);
-               goto out_kfree_type;
+               goto out_ida_remove;
        }
+
        ret = device_register(&cdev->device);
        if (ret)
                goto out_kfree_type;
@@ -943,6 +948,8 @@ out_kfree_type:
        thermal_cooling_device_destroy_sysfs(cdev);
        kfree(cdev->type);
        put_device(&cdev->device);
+
+       /* thermal_release() takes care of the rest */
        cdev = NULL;
 out_ida_remove:
        ida_free(&thermal_cdev_ida, id);
index 81252e31014a18aa907c158572e6b50108a12cc7..56008eb91e2e448b9d584c318d6bc55c9af00a5b 100644 (file)
@@ -427,13 +427,6 @@ int tb_retimer_scan(struct tb_port *port, bool add)
 {
        u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
        int ret, i, last_idx = 0;
-       struct usb4_port *usb4;
-
-       usb4 = port->usb4;
-       if (!usb4)
-               return 0;
-
-       pm_runtime_get_sync(&usb4->dev);
 
        /*
         * Send broadcast RT to make sure retimer indices facing this
@@ -441,7 +434,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
         */
        ret = usb4_port_enumerate_retimers(port);
        if (ret)
-               goto out;
+               return ret;
 
        /*
         * Enable sideband channel for each retimer. We can do this
@@ -471,12 +464,11 @@ int tb_retimer_scan(struct tb_port *port, bool add)
                        break;
        }
 
-       if (!last_idx) {
-               ret = 0;
-               goto out;
-       }
+       if (!last_idx)
+               return 0;
 
        /* Add on-board retimers if they do not exist already */
+       ret = 0;
        for (i = 1; i <= last_idx; i++) {
                struct tb_retimer *rt;
 
@@ -490,10 +482,6 @@ int tb_retimer_scan(struct tb_port *port, bool add)
                }
        }
 
-out:
-       pm_runtime_mark_last_busy(&usb4->dev);
-       pm_runtime_put_autosuspend(&usb4->dev);
-
        return ret;
 }
 
index 4628458044270afca638a14d8d22f3403b1a1137..3f1ab30c4fb1589029d6a98f60f844e97a72a9a8 100644 (file)
@@ -628,11 +628,15 @@ static void tb_scan_port(struct tb_port *port)
                         * Downstream switch is reachable through two ports.
                         * Only scan on the primary port (link_nr == 0).
                         */
+
+       if (port->usb4)
+               pm_runtime_get_sync(&port->usb4->dev);
+
        if (tb_wait_for_port(port, false) <= 0)
-               return;
+               goto out_rpm_put;
        if (port->remote) {
                tb_port_dbg(port, "port already has a remote\n");
-               return;
+               goto out_rpm_put;
        }
 
        tb_retimer_scan(port, true);
@@ -647,12 +651,12 @@ static void tb_scan_port(struct tb_port *port)
                 */
                if (PTR_ERR(sw) == -EIO || PTR_ERR(sw) == -EADDRNOTAVAIL)
                        tb_scan_xdomain(port);
-               return;
+               goto out_rpm_put;
        }
 
        if (tb_switch_configure(sw)) {
                tb_switch_put(sw);
-               return;
+               goto out_rpm_put;
        }
 
        /*
@@ -681,7 +685,7 @@ static void tb_scan_port(struct tb_port *port)
 
        if (tb_switch_add(sw)) {
                tb_switch_put(sw);
-               return;
+               goto out_rpm_put;
        }
 
        /* Link the switches using both links if available */
@@ -733,6 +737,12 @@ static void tb_scan_port(struct tb_port *port)
 
        tb_add_dp_resources(sw);
        tb_scan_switch(sw);
+
+out_rpm_put:
+       if (port->usb4) {
+               pm_runtime_mark_last_busy(&port->usb4->dev);
+               pm_runtime_put_autosuspend(&port->usb4->dev);
+       }
 }
 
 static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel)
index 2c3cf7fc3357150d139002b7c29b55a5c1a23809..1fc3c29b24f8397a540c914fb3533342baf9a630 100644 (file)
@@ -1275,7 +1275,7 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel,
                return;
        } else if (!ret) {
                /* Use maximum link rate if the link valid is not set */
-               ret = usb4_usb3_port_max_link_rate(tunnel->src_port);
+               ret = tb_usb3_max_link_rate(tunnel->dst_port, tunnel->src_port);
                if (ret < 0) {
                        tb_tunnel_warn(tunnel, "failed to read maximum link rate\n");
                        return;
index cfa83486c9dad6892f9b8b0c3ddf14c434ac9ae5..3c51e47dd86b77786ff47a19617b06da13b5e8b4 100644 (file)
@@ -1419,12 +1419,19 @@ static int tb_xdomain_get_properties(struct tb_xdomain *xd)
         * registered, we notify the userspace that it has changed.
         */
        if (!update) {
-               struct tb_port *port;
+               /*
+                * Now disable lane 1 if bonding was not enabled. Do
+                * this only if bonding was possible at the beginning
+                * (that is we are the connection manager and there are
+                * two lanes).
+                */
+               if (xd->bonding_possible) {
+                       struct tb_port *port;
 
-               /* Now disable lane 1 if bonding was not enabled */
-               port = tb_port_at(xd->route, tb_xdomain_parent(xd));
-               if (!port->bonded)
-                       tb_port_disable(port->dual_link_port);
+                       port = tb_port_at(xd->route, tb_xdomain_parent(xd));
+                       if (!port->bonded)
+                               tb_port_disable(port->dual_link_port);
+               }
 
                if (device_add(&xd->dev)) {
                        dev_err(&xd->dev, "failed to add XDomain device\n");
index 37d6af2ec4272e35724f03902d9e32900a6da8bd..7fa66501792dd8043304af153ae9072ff287ce8c 100644 (file)
@@ -43,15 +43,23 @@ static void __dma_rx_complete(struct uart_8250_port *p)
        struct uart_8250_dma    *dma = p->dma;
        struct tty_port         *tty_port = &p->port.state->port;
        struct dma_tx_state     state;
+       enum dma_status         dma_status;
        int                     count;
 
-       dma->rx_running = 0;
-       dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+       /*
+        * New DMA Rx can be started during the completion handler before it
+        * could acquire port's lock and it might still be ongoing. Don't to
+        * anything in such case.
+        */
+       dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+       if (dma_status == DMA_IN_PROGRESS)
+               return;
 
        count = dma->rx_size - state.residue;
 
        tty_insert_flip_string(tty_port, dma->rx_buf, count);
        p->port.icount.rx += count;
+       dma->rx_running = 0;
 
        tty_flip_buffer_push(tty_port);
 }
@@ -62,9 +70,14 @@ static void dma_rx_complete(void *param)
        struct uart_8250_dma *dma = p->dma;
        unsigned long flags;
 
-       __dma_rx_complete(p);
-
        spin_lock_irqsave(&p->port.lock, flags);
+       if (dma->rx_running)
+               __dma_rx_complete(p);
+
+       /*
+        * Cannot be combined with the previous check because __dma_rx_complete()
+        * changes dma->rx_running.
+        */
        if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR))
                p->dma->rx_dma(p);
        spin_unlock_irqrestore(&p->port.lock, flags);
index 314a05e009df97f840928ce1510ebc905d6534b4..64770c62bbec5436d332821ffaf57074276b2422 100644 (file)
 #define PCI_DEVICE_ID_EXAR_XR17V4358           0x4358
 #define PCI_DEVICE_ID_EXAR_XR17V8358           0x8358
 
+#define PCI_DEVICE_ID_SEALEVEL_710xC           0x1001
+#define PCI_DEVICE_ID_SEALEVEL_720xC           0x1002
+#define PCI_DEVICE_ID_SEALEVEL_740xC           0x1004
+#define PCI_DEVICE_ID_SEALEVEL_780xC           0x1008
+#define PCI_DEVICE_ID_SEALEVEL_716xC           0x1010
+
 #define UART_EXAR_INT0         0x80
 #define UART_EXAR_8XMODE       0x88    /* 8X sampling rate select */
 #define UART_EXAR_SLEEP                0x8b    /* Sleep mode */
@@ -638,6 +644,8 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
                nr_ports = BIT(((pcidev->device & 0x38) >> 3) - 1);
        else if (board->num_ports)
                nr_ports = board->num_ports;
+       else if (pcidev->vendor == PCI_VENDOR_ID_SEALEVEL)
+               nr_ports = pcidev->device & 0xff;
        else
                nr_ports = pcidev->device & 0x0f;
 
@@ -864,6 +872,12 @@ static const struct pci_device_id exar_pci_tbl[] = {
        EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
        EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4),
        EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8),
+
+       EXAR_DEVICE(SEALEVEL, 710xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 720xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 740xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 780xC, pbn_exar_XR17V35x),
+       EXAR_DEVICE(SEALEVEL, 716xC, pbn_exar_XR17V35x),
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, exar_pci_tbl);
index d75c39f4622b7b6ae53f1f9bc053dd0c5476083b..d8c2f3455eebad589a712d2e8e6a4be91f3ddcf4 100644 (file)
@@ -1466,6 +1466,10 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
        struct circ_buf *xmit = &uap->port.state->xmit;
        int count = uap->fifosize >> 1;
 
+       if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
+           !uap->rs485_tx_started)
+               pl011_rs485_tx_start(uap);
+
        if (uap->port.x_char) {
                if (!pl011_tx_char(uap, uap->port.x_char, from_irq))
                        return true;
@@ -1477,10 +1481,6 @@ static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
                return false;
        }
 
-       if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
-           !uap->rs485_tx_started)
-               pl011_rs485_tx_start(uap);
-
        /* If we are using DMA mode, try to send some characters. */
        if (pl011_dma_tx_irq(uap))
                return true;
index f1c06e12efa0bb7e720c004fffcc51394e2fd885..9cd7479b03c086e6825218ae905f98a2d4b48f95 100644 (file)
@@ -2657,13 +2657,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
        else if (mr == ATMEL_US_PAR_ODD)
                *parity = 'o';
 
-       /*
-        * The serial core only rounds down when matching this to a
-        * supported baud rate. Make sure we don't end up slightly
-        * lower than one of those, as it would make us fall through
-        * to a much lower baud rate than we really want.
-        */
-       *baud = port->uartclk / (16 * (quot - 1));
+       *baud = port->uartclk / (16 * quot);
 }
 
 static int __init atmel_console_setup(struct console *co, char *options)
index a3ed9b34e2abb557374f91c64e23a1bad4cb16b2..7ce7bb1640054dd309e2feb45eea9083eb89705e 100644 (file)
@@ -171,6 +171,7 @@ static int configure_kgdboc(void)
        int err = -ENODEV;
        char *cptr = config;
        struct console *cons;
+       int cookie;
 
        if (!strlen(config) || isspace(config[0])) {
                err = 0;
@@ -189,20 +190,9 @@ static int configure_kgdboc(void)
        if (kgdboc_register_kbd(&cptr))
                goto do_register;
 
-       /*
-        * tty_find_polling_driver() can call uart_set_options()
-        * (via poll_init) to configure the uart. Take the console_list_lock
-        * in order to synchronize against register_console(), which can also
-        * configure the uart via uart_set_options(). This also allows safe
-        * traversal of the console list.
-        */
-       console_list_lock();
-
        p = tty_find_polling_driver(cptr, &tty_line);
-       if (!p) {
-               console_list_unlock();
+       if (!p)
                goto noconfig;
-       }
 
        /*
         * Take console_lock to serialize device() callback with
@@ -211,7 +201,8 @@ static int configure_kgdboc(void)
         */
        console_lock();
 
-       for_each_console(cons) {
+       cookie = console_srcu_read_lock();
+       for_each_console_srcu(cons) {
                int idx;
                if (cons->device && cons->device(cons, &idx) == p &&
                    idx == tty_line) {
@@ -219,11 +210,10 @@ static int configure_kgdboc(void)
                        break;
                }
        }
+       console_srcu_read_unlock(cookie);
 
        console_unlock();
 
-       console_list_unlock();
-
        kgdb_tty_driver = p;
        kgdb_tty_line = tty_line;
 
index 3d54a43768cd2497180920ce1103f34d1ad3cd14..9576ba8bbc40ec59aca15ddf3c279f784274944c 100644 (file)
@@ -749,7 +749,7 @@ static void pch_dma_tx_complete(void *arg)
                uart_xmit_advance(port, sg_dma_len(sg));
 
        async_tx_ack(priv->desc_tx);
-       dma_unmap_sg(port->dev, sg, priv->orig_nent, DMA_TO_DEVICE);
+       dma_unmap_sg(port->dev, priv->sg_tx_p, priv->orig_nent, DMA_TO_DEVICE);
        priv->tx_dma_use = 0;
        priv->nent = 0;
        priv->orig_nent = 0;
index b487823f0e61724ba8cdb38ff11f8e5c28bfbf6a..57f04f8bf5043206d23a8f93e4285c8dd8347d4e 100644 (file)
@@ -864,9 +864,10 @@ out_unlock:
        return IRQ_HANDLED;
 }
 
-static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
+static int setup_fifos(struct qcom_geni_serial_port *port)
 {
        struct uart_port *uport;
+       u32 old_rx_fifo_depth = port->rx_fifo_depth;
 
        uport = &port->uport;
        port->tx_fifo_depth = geni_se_get_tx_fifo_depth(&port->se);
@@ -874,6 +875,16 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port)
        port->rx_fifo_depth = geni_se_get_rx_fifo_depth(&port->se);
        uport->fifosize =
                (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE;
+
+       if (port->rx_fifo && (old_rx_fifo_depth != port->rx_fifo_depth) && port->rx_fifo_depth) {
+               port->rx_fifo = devm_krealloc(uport->dev, port->rx_fifo,
+                                             port->rx_fifo_depth * sizeof(u32),
+                                             GFP_KERNEL);
+               if (!port->rx_fifo)
+                       return -ENOMEM;
+       }
+
+       return 0;
 }
 
 
@@ -888,6 +899,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
        u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;
        u32 proto;
        u32 pin_swap;
+       int ret;
 
        proto = geni_se_read_proto(&port->se);
        if (proto != GENI_SE_UART) {
@@ -897,7 +909,9 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
 
        qcom_geni_serial_stop_rx(uport);
 
-       get_tx_fifo_size(port);
+       ret = setup_fifos(port);
+       if (ret)
+               return ret;
 
        writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT);
 
@@ -1516,7 +1530,7 @@ static int qcom_geni_serial_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
+static int qcom_geni_serial_sys_suspend(struct device *dev)
 {
        struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
        struct uart_port *uport = &port->uport;
@@ -1533,7 +1547,7 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
        return uart_suspend_port(private_data->drv, uport);
 }
 
-static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
+static int qcom_geni_serial_sys_resume(struct device *dev)
 {
        int ret;
        struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
@@ -1581,10 +1595,12 @@ static int qcom_geni_serial_sys_hib_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops qcom_geni_serial_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_sys_suspend,
-                                       qcom_geni_serial_sys_resume)
-       .restore = qcom_geni_serial_sys_hib_resume,
-       .thaw = qcom_geni_serial_sys_hib_resume,
+       .suspend = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
+       .resume = pm_sleep_ptr(qcom_geni_serial_sys_resume),
+       .freeze = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
+       .poweroff = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
+       .restore = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
+       .thaw = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
 };
 
 static const struct of_device_id qcom_geni_serial_match_table[] = {
index b9fbbee598b815e8cd41527dc0acec65c8958710..ec874f3a567ca79bea6fd1d3503f5b78dfba4f8b 100644 (file)
@@ -2212,6 +2212,9 @@ EXPORT_SYMBOL_GPL(uart_parse_options);
  * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
  * @bits: number of data bits
  * @flow: flow control character - 'r' (rts)
+ *
+ * Locking: Caller must hold console_list_lock in order to serialize
+ * early initialization of the serial-console lock.
  */
 int
 uart_set_options(struct uart_port *port, struct console *co,
@@ -2619,7 +2622,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
 
        if (!ret && options) {
                uart_parse_options(options, &baud, &parity, &bits, &flow);
+               console_list_lock();
                ret = uart_set_options(port, NULL, baud, parity, bits, flow);
+               console_list_unlock();
        }
 out:
        mutex_unlock(&tport->mutex);
index a1490033aa164b77ae884e34749fab32d28fe511..409e91d6829a5d4a6c171f835da8a18139c3e8e1 100644 (file)
@@ -797,25 +797,11 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
                spin_unlock(&port->lock);
        }
 
-       if (stm32_usart_rx_dma_enabled(port))
-               return IRQ_WAKE_THREAD;
-       else
-               return IRQ_HANDLED;
-}
-
-static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
-{
-       struct uart_port *port = ptr;
-       struct tty_port *tport = &port->state->port;
-       struct stm32_port *stm32_port = to_stm32_port(port);
-       unsigned int size;
-       unsigned long flags;
-
        /* Receiver timeout irq for DMA RX */
-       if (!stm32_port->throttled) {
-               spin_lock_irqsave(&port->lock, flags);
+       if (stm32_usart_rx_dma_enabled(port) && !stm32_port->throttled) {
+               spin_lock(&port->lock);
                size = stm32_usart_receive_chars(port, false);
-               uart_unlock_and_check_sysrq_irqrestore(port, flags);
+               uart_unlock_and_check_sysrq(port);
                if (size)
                        tty_flip_buffer_push(tport);
        }
@@ -1015,10 +1001,8 @@ static int stm32_usart_startup(struct uart_port *port)
        u32 val;
        int ret;
 
-       ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
-                                  stm32_usart_threaded_interrupt,
-                                  IRQF_ONESHOT | IRQF_NO_SUSPEND,
-                                  name, port);
+       ret = request_irq(port->irq, stm32_usart_interrupt,
+                         IRQF_NO_SUSPEND, name, port);
        if (ret)
                return ret;
 
@@ -1601,13 +1585,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
        struct dma_slave_config config;
        int ret;
 
-       /*
-        * Using DMA and threaded handler for the console could lead to
-        * deadlocks.
-        */
-       if (uart_console(port))
-               return -ENODEV;
-
        stm32port->rx_buf = dma_alloc_coherent(dev, RX_BUF_L,
                                               &stm32port->rx_dma_buf,
                                               GFP_KERNEL);
index 1850bacdb5b0e19e6e1319bd8daa5c0c80d34961..f566eb1839dc501edb1942f2ea41ab0a9ed75afd 100644 (file)
@@ -386,10 +386,6 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
        uni_mode = use_unicode(inode);
        attr = use_attributes(inode);
-       ret = -ENXIO;
-       vc = vcs_vc(inode, &viewed);
-       if (!vc)
-               goto unlock_out;
 
        ret = -EINVAL;
        if (pos < 0)
@@ -407,6 +403,11 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                unsigned int this_round, skip = 0;
                int size;
 
+               ret = -ENXIO;
+               vc = vcs_vc(inode, &viewed);
+               if (!vc)
+                       goto unlock_out;
+
                /* Check whether we are above size each round,
                 * as copy_to_user at the end of this loop
                 * could sleep.
index bda61be5f0357f016ab82c6def893c4ef3071ada..3a1c4d31e010dadf0644bf27a4d4b2c1de587468 100644 (file)
@@ -1234,12 +1234,14 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
         * clock scaling is in progress
         */
        ufshcd_scsi_block_requests(hba);
+       mutex_lock(&hba->wb_mutex);
        down_write(&hba->clk_scaling_lock);
 
        if (!hba->clk_scaling.is_allowed ||
            ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
                ret = -EBUSY;
                up_write(&hba->clk_scaling_lock);
+               mutex_unlock(&hba->wb_mutex);
                ufshcd_scsi_unblock_requests(hba);
                goto out;
        }
@@ -1251,12 +1253,16 @@ out:
        return ret;
 }
 
-static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock)
+static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool scale_up)
 {
-       if (writelock)
-               up_write(&hba->clk_scaling_lock);
-       else
-               up_read(&hba->clk_scaling_lock);
+       up_write(&hba->clk_scaling_lock);
+
+       /* Enable Write Booster if we have scaled up else disable it */
+       if (ufshcd_enable_wb_if_scaling_up(hba) && !err)
+               ufshcd_wb_toggle(hba, scale_up);
+
+       mutex_unlock(&hba->wb_mutex);
+
        ufshcd_scsi_unblock_requests(hba);
        ufshcd_release(hba);
 }
@@ -1273,7 +1279,6 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock)
 static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
 {
        int ret = 0;
-       bool is_writelock = true;
 
        ret = ufshcd_clock_scaling_prepare(hba);
        if (ret)
@@ -1302,15 +1307,8 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
                }
        }
 
-       /* Enable Write Booster if we have scaled up else disable it */
-       if (ufshcd_enable_wb_if_scaling_up(hba)) {
-               downgrade_write(&hba->clk_scaling_lock);
-               is_writelock = false;
-               ufshcd_wb_toggle(hba, scale_up);
-       }
-
 out_unprepare:
-       ufshcd_clock_scaling_unprepare(hba, is_writelock);
+       ufshcd_clock_scaling_unprepare(hba, ret, scale_up);
        return ret;
 }
 
@@ -6066,9 +6064,11 @@ static void ufshcd_force_error_recovery(struct ufs_hba *hba)
 
 static void ufshcd_clk_scaling_allow(struct ufs_hba *hba, bool allow)
 {
+       mutex_lock(&hba->wb_mutex);
        down_write(&hba->clk_scaling_lock);
        hba->clk_scaling.is_allowed = allow;
        up_write(&hba->clk_scaling_lock);
+       mutex_unlock(&hba->wb_mutex);
 }
 
 static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend)
@@ -9793,6 +9793,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
        /* Initialize mutex for exception event control */
        mutex_init(&hba->ee_ctrl_mutex);
 
+       mutex_init(&hba->wb_mutex);
        init_rwsem(&hba->clk_scaling_lock);
 
        ufshcd_init_clk_gating(hba);
index 5adcb349718c33128b0970b6448080dc458f8b5a..ccfaebca6faa7512ac92ad0beeea239f467bbb52 100644 (file)
@@ -2614,6 +2614,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
        u8 req_on_hw_ring = 0;
        unsigned long flags;
        int ret = 0;
+       int val;
 
        if (!ep || !request || !ep->desc)
                return -EINVAL;
@@ -2649,6 +2650,13 @@ found:
 
        /* Update ring only if removed request is on pending_req_list list */
        if (req_on_hw_ring && link_trb) {
+               /* Stop DMA */
+               writel(EP_CMD_DFLUSH, &priv_dev->regs->ep_cmd);
+
+               /* wait for DFLUSH cleared */
+               readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val,
+                                         !(val & EP_CMD_DFLUSH), 1, 1000);
+
                link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma +
                        ((priv_req->end_trb + 1) * TRB_SIZE)));
                link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control) & TRB_CYCLE) |
@@ -2660,6 +2668,10 @@ found:
 
        cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET);
 
+       req = cdns3_next_request(&priv_ep->pending_req_list);
+       if (req)
+               cdns3_rearm_transfer(priv_ep, 1);
+
 not_found:
        spin_unlock_irqrestore(&priv_dev->lock, flags);
        return ret;
index 484b1cd234317076027c7c9986d8e769e54d552b..27c601296130e23f5b3d740d2b2944ccb2bbe586 100644 (file)
@@ -1294,12 +1294,12 @@ static void ci_extcon_wakeup_int(struct ci_hdrc *ci)
        cable_id = &ci->platdata->id_extcon;
        cable_vbus = &ci->platdata->vbus_extcon;
 
-       if ((!IS_ERR(cable_id->edev) || !IS_ERR(ci->role_switch))
+       if ((!IS_ERR(cable_id->edev) || ci->role_switch)
                && ci->is_otg &&
                (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS))
                ci_irq(ci);
 
-       if ((!IS_ERR(cable_vbus->edev) || !IS_ERR(ci->role_switch))
+       if ((!IS_ERR(cable_vbus->edev) || ci->role_switch)
                && ci->is_otg &&
                (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS))
                ci_irq(ci);
index 77e73fc8d6736b46a4665e63ec593b4fa96663ba..9eca403af2a85bf4541a74e69ebee75ddaa42c61 100644 (file)
@@ -44,6 +44,9 @@
 #define USB_PRODUCT_USB5534B                   0x5534
 #define USB_VENDOR_CYPRESS                     0x04b4
 #define USB_PRODUCT_CY7C65632                  0x6570
+#define USB_VENDOR_TEXAS_INSTRUMENTS           0x0451
+#define USB_PRODUCT_TUSB8041_USB3              0x8140
+#define USB_PRODUCT_TUSB8041_USB2              0x8142
 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND       0x01
 #define HUB_QUIRK_DISABLE_AUTOSUSPEND          0x02
 
@@ -5854,6 +5857,16 @@ static const struct usb_device_id hub_id_table[] = {
       .idVendor = USB_VENDOR_GENESYS_LOGIC,
       .bInterfaceClass = USB_CLASS_HUB,
       .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                       | USB_DEVICE_ID_MATCH_PRODUCT,
+      .idVendor = USB_VENDOR_TEXAS_INSTRUMENTS,
+      .idProduct = USB_PRODUCT_TUSB8041_USB2,
+      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                       | USB_DEVICE_ID_MATCH_PRODUCT,
+      .idVendor = USB_VENDOR_TEXAS_INSTRUMENTS,
+      .idProduct = USB_PRODUCT_TUSB8041_USB3,
+      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
     { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
       .bDeviceClass = USB_CLASS_HUB},
     { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
index 6d93428432f13f1e2cc8461570eebae935c4429c..533baa85083c2e6773f5b5b7483d20b05b782428 100644 (file)
@@ -37,6 +37,71 @@ bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
 }
 EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
 
+#define UUID_USB_CONTROLLER_DSM "ce2ee385-00e6-48cb-9f05-2edb927c4899"
+#define USB_DSM_DISABLE_U1_U2_FOR_PORT 5
+
+/**
+ * usb_acpi_port_lpm_incapable - check if lpm should be disabled for a port.
+ * @hdev: USB device belonging to the usb hub
+ * @index: zero based port index
+ *
+ * Some USB3 ports may not support USB3 link power management U1/U2 states
+ * due to different retimer setup. ACPI provides _DSM method which returns 0x01
+ * if U1 and U2 states should be disabled. Evaluate _DSM with:
+ * Arg0: UUID = ce2ee385-00e6-48cb-9f05-2edb927c4899
+ * Arg1: Revision ID = 0
+ * Arg2: Function Index = 5
+ * Arg3: (empty)
+ *
+ * Return 1 if USB3 port is LPM incapable, negative on error, otherwise 0
+ */
+
+int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
+{
+       union acpi_object *obj;
+       acpi_handle port_handle;
+       int port1 = index + 1;
+       guid_t guid;
+       int ret;
+
+       ret = guid_parse(UUID_USB_CONTROLLER_DSM, &guid);
+       if (ret)
+               return ret;
+
+       port_handle = usb_get_hub_port_acpi_handle(hdev, port1);
+       if (!port_handle) {
+               dev_dbg(&hdev->dev, "port-%d no acpi handle\n", port1);
+               return -ENODEV;
+       }
+
+       if (!acpi_check_dsm(port_handle, &guid, 0,
+                           BIT(USB_DSM_DISABLE_U1_U2_FOR_PORT))) {
+               dev_dbg(&hdev->dev, "port-%d no _DSM function %d\n",
+                       port1, USB_DSM_DISABLE_U1_U2_FOR_PORT);
+               return -ENODEV;
+       }
+
+       obj = acpi_evaluate_dsm(port_handle, &guid, 0,
+                               USB_DSM_DISABLE_U1_U2_FOR_PORT, NULL);
+
+       if (!obj)
+               return -ENODEV;
+
+       if (obj->type != ACPI_TYPE_INTEGER) {
+               dev_dbg(&hdev->dev, "evaluate port-%d _DSM failed\n", port1);
+               ACPI_FREE(obj);
+               return -EINVAL;
+       }
+
+       if (obj->integer.value == 0x01)
+               ret = 1;
+
+       ACPI_FREE(obj);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_acpi_port_lpm_incapable);
+
 /**
  * usb_acpi_set_power_state - control usb port's power via acpi power
  * resource
index b2f72b0e75c6bbfcd763778425ae841576e4373d..be954a9abbe05e8a18bfbbb1bb2b27869b661f41 100644 (file)
@@ -3,6 +3,7 @@
 config USB_DWC3
        tristate "DesignWare USB3 DRD Core Support"
        depends on (USB || USB_GADGET) && HAS_DMA
+       depends on (EXTCON || EXTCON=n)
        select USB_XHCI_PLATFORM if USB_XHCI_HCD
        select USB_ROLE_SWITCH if USB_DWC3_DUAL_ROLE
        help
@@ -44,7 +45,6 @@ config USB_DWC3_GADGET
 config USB_DWC3_DUAL_ROLE
        bool "Dual Role mode"
        depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3))
-       depends on (EXTCON=y || EXTCON=USB_DWC3)
        help
          This is the default mode of working of DWC3 controller where
          both host and gadget features are enabled.
index b0a0351d2d8b5c7bf70320d475f93602e4442f49..959fc925ca7c52316b4df8f23157fd4cedc02257 100644 (file)
@@ -901,7 +901,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
        qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev);
 
        /* enable vbus override for device mode */
-       if (qcom->mode == USB_DR_MODE_PERIPHERAL)
+       if (qcom->mode != USB_DR_MODE_HOST)
                dwc3_qcom_vbus_override_enable(qcom, true);
 
        /* register extcon to override sw_vbus on Vbus change later */
index 87cca81bf4ac970fcdb902e5add8c0a68eacb0e4..eb076746f03206422c17fa0f28d9929537241baa 100644 (file)
@@ -1014,7 +1014,6 @@ static int fotg210_udc_start(struct usb_gadget *g,
        int ret;
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        fotg210->driver = driver;
 
        if (!IS_ERR_OR_NULL(fotg210->phy)) {
index 96121d1c8df4c71e0d4d0077fa0c37121ddd90ba..0853536cbf2e642c880743854ff79ab74714f756 100644 (file)
@@ -393,6 +393,7 @@ static void gadget_info_attr_release(struct config_item *item)
        WARN_ON(!list_empty(&gi->string_list));
        WARN_ON(!list_empty(&gi->available_func));
        kfree(gi->composite.gadget_driver.function);
+       kfree(gi->composite.gadget_driver.driver.name);
        kfree(gi);
 }
 
@@ -1572,7 +1573,6 @@ static const struct usb_gadget_driver configfs_driver_template = {
        .max_speed      = USB_SPEED_SUPER_PLUS,
        .driver = {
                .owner          = THIS_MODULE,
-               .name           = "configfs-gadget",
        },
        .match_existing_only = 1,
 };
@@ -1623,13 +1623,21 @@ static struct config_group *gadgets_make(
 
        gi->composite.gadget_driver = configfs_driver_template;
 
+       gi->composite.gadget_driver.driver.name = kasprintf(GFP_KERNEL,
+                                                           "configfs-gadget.%s", name);
+       if (!gi->composite.gadget_driver.driver.name)
+               goto err;
+
        gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
        gi->composite.name = gi->composite.gadget_driver.function;
 
        if (!gi->composite.gadget_driver.function)
-               goto err;
+               goto out_free_driver_name;
 
        return &gi->group;
+
+out_free_driver_name:
+       kfree(gi->composite.gadget_driver.driver.name);
 err:
        kfree(gi);
        return ERR_PTR(-ENOMEM);
index 73dc10a77cdeadda5a3ef63b5e8d5be32959a3ff..8ad354741380ddbba7764fb0661202f70532931d 100644 (file)
@@ -279,6 +279,11 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
        struct usb_request *req = ffs->ep0req;
        int ret;
 
+       if (!req) {
+               spin_unlock_irq(&ffs->ev.waitq.lock);
+               return -EINVAL;
+       }
+
        req->zero     = len < le16_to_cpu(ffs->ev.setup.wLength);
 
        spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -1892,10 +1897,14 @@ static void functionfs_unbind(struct ffs_data *ffs)
        ENTER();
 
        if (!WARN_ON(!ffs->gadget)) {
+               /* dequeue before freeing ep0req */
+               usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req);
+               mutex_lock(&ffs->mutex);
                usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
                ffs->ep0req = NULL;
                ffs->gadget = NULL;
                clear_bit(FFS_FL_BOUND, &ffs->flags);
+               mutex_unlock(&ffs->mutex);
                ffs_data_put(ffs);
        }
 }
index c36bcfa0e9b46f17e85e7731fe12ca1a28a769a9..424bb3b666dbd7d545a9d9abfb835c1152b51624 100644 (file)
@@ -83,7 +83,9 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f)
 /* peak (theoretical) bulk transfer rate in bits-per-second */
 static inline unsigned ncm_bitrate(struct usb_gadget *g)
 {
-       if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS)
+       if (!g)
+               return 0;
+       else if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS)
                return 4250000000U;
        else if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
                return 3750000000U;
index 08726e4c68a56d4ae865a22096dda7ec44697228..0219cd79493a73714b95f5c1156f5ff9c6216f77 100644 (file)
@@ -1142,6 +1142,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
                }
                std_as_out_if0_desc.bInterfaceNumber = ret;
                std_as_out_if1_desc.bInterfaceNumber = ret;
+               std_as_out_if1_desc.bNumEndpoints = 1;
                uac2->as_out_intf = ret;
                uac2->as_out_alt = 0;
 
index 01c3ead7d1b426a21eb23d1905005c8619682ff4..d605bc2e7e8fd43dd0725e221e22786d96e22bfd 100644 (file)
@@ -229,6 +229,7 @@ static void put_ep (struct ep_data *data)
  */
 
 static const char *CHIP;
+static DEFINE_MUTEX(sb_mutex);         /* Serialize superblock operations */
 
 /*----------------------------------------------------------------------*/
 
@@ -2010,13 +2011,20 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
 {
        struct inode    *inode;
        struct dev_data *dev;
+       int             rc;
 
-       if (the_device)
-               return -ESRCH;
+       mutex_lock(&sb_mutex);
+
+       if (the_device) {
+               rc = -ESRCH;
+               goto Done;
+       }
 
        CHIP = usb_get_gadget_udc_name();
-       if (!CHIP)
-               return -ENODEV;
+       if (!CHIP) {
+               rc = -ENODEV;
+               goto Done;
+       }
 
        /* superblock */
        sb->s_blocksize = PAGE_SIZE;
@@ -2053,13 +2061,17 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc)
         * from binding to a controller.
         */
        the_device = dev;
-       return 0;
+       rc = 0;
+       goto Done;
 
-Enomem:
+ Enomem:
        kfree(CHIP);
        CHIP = NULL;
+       rc = -ENOMEM;
 
-       return -ENOMEM;
+ Done:
+       mutex_unlock(&sb_mutex);
+       return rc;
 }
 
 /* "mount -t gadgetfs path /dev/gadget" ends up here */
@@ -2081,6 +2093,7 @@ static int gadgetfs_init_fs_context(struct fs_context *fc)
 static void
 gadgetfs_kill_sb (struct super_block *sb)
 {
+       mutex_lock(&sb_mutex);
        kill_litter_super (sb);
        if (the_device) {
                put_dev (the_device);
@@ -2088,6 +2101,7 @@ gadgetfs_kill_sb (struct super_block *sb)
        }
        kfree(CHIP);
        CHIP = NULL;
+       mutex_unlock(&sb_mutex);
 }
 
 /*----------------------------------------------------------------------*/
index 53e38f87472b040cc953ba2dfd65dcdfbe53f82f..c06dd1af7a0c506a17210bbc9ea41ac5355985d9 100644 (file)
@@ -293,6 +293,7 @@ static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
        (const struct uvc_descriptor_header *) &uvc_format_yuv,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+       (const struct uvc_descriptor_header *) &uvc_color_matching,
        (const struct uvc_descriptor_header *) &uvc_format_mjpg,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -305,6 +306,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
        (const struct uvc_descriptor_header *) &uvc_format_yuv,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+       (const struct uvc_descriptor_header *) &uvc_color_matching,
        (const struct uvc_descriptor_header *) &uvc_format_mjpg,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -317,6 +319,7 @@ static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
        (const struct uvc_descriptor_header *) &uvc_format_yuv,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+       (const struct uvc_descriptor_header *) &uvc_color_matching,
        (const struct uvc_descriptor_header *) &uvc_format_mjpg,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
        (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
index 2cdb07905bdebee0120c0c8b35992be1c6fea349..d04d72f5816e61edede507aacf8544c4cfe0e6fa 100644 (file)
@@ -1830,7 +1830,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
        bcm63xx_select_phy_mode(udc, true);
 
        udc->driver = driver;
-       driver->driver.bus = NULL;
        udc->gadget.dev.of_node = udc->dev->of_node;
 
        spin_unlock_irqrestore(&udc->lock, flags);
index bf745358e28e6b933edb731fd845b9b99081bf2f..3b1cc8fa30c830c980b9c8c3f021b142ebeb3327 100644 (file)
@@ -2285,7 +2285,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
        /* lock is needed but whether should use this lock or another */
        spin_lock_irqsave(&udc->lock, flags);
 
-       driver->driver.bus = NULL;
        /* hook up the driver */
        udc->driver = driver;
        udc->gadget.speed = driver->max_speed;
index 50435e8041183171c1522eb2552bc100c8de1857..a67873a074b7bc020b30d3c54d39650b9a902c91 100644 (file)
@@ -1943,7 +1943,6 @@ static int fsl_udc_start(struct usb_gadget *g,
        /* lock is needed but whether should use this lock or another */
        spin_lock_irqsave(&udc_controller->lock, flags);
 
-       driver->driver.bus = NULL;
        /* hook up the driver */
        udc_controller->driver = driver;
        spin_unlock_irqrestore(&udc_controller->lock, flags);
index 9af8b415f303bbcd1e4f50a64327fa8bd64b3861..5954800d652ca950d6d76d4738fa273f47c4d757 100644 (file)
@@ -1311,7 +1311,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
        struct fusb300 *fusb300 = to_fusb300(g);
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        fusb300->driver = driver;
 
        return 0;
index bdc56b24b5c900e1b5aab30dea1bc16dffcd0223..5ffb3d5c635becbfa9bfa275f2471df29d002c57 100644 (file)
@@ -1375,7 +1375,6 @@ static int goku_udc_start(struct usb_gadget *g,
        struct goku_udc *dev = to_goku_udc(g);
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        dev->driver = driver;
 
        /*
index 22096f8505de4a64cb2538f0a096561e89b8de85..85cdc0af3bf952621d80bacab7ed219aa64f0602 100644 (file)
@@ -1906,7 +1906,6 @@ static int gr_udc_start(struct usb_gadget *gadget,
        spin_lock(&dev->lock);
 
        /* Hook up the driver */
-       driver->driver.bus = NULL;
        dev->driver = driver;
 
        /* Get ready for host detection */
index c7e421b449f36cade5a1823cdda0c799da2c20ac..06e21cee431be9caec54d43995afd39f976329d8 100644 (file)
@@ -1454,7 +1454,6 @@ static int m66592_udc_start(struct usb_gadget *g,
        struct m66592 *m66592 = to_m66592(g);
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        m66592->driver = driver;
 
        m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
index 3074da00c3df76669919e16b95aa8168c4250b18..ddf0ed3eb4f2616fe6c4a5cbe235a66a50210ea7 100644 (file)
@@ -1108,7 +1108,6 @@ static int max3420_udc_start(struct usb_gadget *gadget,
 
        spin_lock_irqsave(&udc->lock, flags);
        /* hook up the driver */
-       driver->driver.bus = NULL;
        udc->driver = driver;
        udc->gadget.speed = USB_SPEED_FULL;
 
index 598654a3cb4184f4a2e40eb1bec247c71bdacfc7..411b6179782c1d064fff8d9077170c04028a31e6 100644 (file)
@@ -1243,7 +1243,6 @@ static int mv_u3d_start(struct usb_gadget *g,
        }
 
        /* hook up the driver ... */
-       driver->driver.bus = NULL;
        u3d->driver = driver;
 
        u3d->ep0_dir = USB_DIR_OUT;
index fdb17d86cd65603eaeade50a636d0e78a91980dd..b397f3a848cf7ac082dc4296b692bb4df81bd098 100644 (file)
@@ -1359,7 +1359,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
        spin_lock_irqsave(&udc->lock, flags);
 
        /* hook up the driver ... */
-       driver->driver.bus = NULL;
        udc->driver = driver;
 
        udc->usb_state = USB_STATE_ATTACHED;
index 84605a4d0715f53e927a800dbc485b8fd0a7da27..538c1b9a2883546fa15ac03cf0ab241b33c22f74 100644 (file)
@@ -1451,7 +1451,6 @@ static int net2272_start(struct usb_gadget *_gadget,
                dev->ep[i].irqs = 0;
        /* hook up the driver ... */
        dev->softconnect = 1;
-       driver->driver.bus = NULL;
        dev->driver = driver;
 
        /* ... then enable host detection and ep0; and we're ready
index d6a68631354a2805c57448952c08a2395f644516..1b929c519cd7126853b9b8487cf814957225cb0c 100644 (file)
@@ -2423,7 +2423,6 @@ static int net2280_start(struct usb_gadget *_gadget,
                dev->ep[i].irqs = 0;
 
        /* hook up the driver ... */
-       driver->driver.bus = NULL;
        dev->driver = driver;
 
        retval = device_create_file(&dev->pdev->dev, &dev_attr_function);
index bea346e362b2b72df7910c417995d4756aa94927..f660ebfa13799544331fef23be1035ab162aff92 100644 (file)
@@ -2066,7 +2066,6 @@ static int omap_udc_start(struct usb_gadget *g,
        udc->softconnect = 1;
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        udc->driver = driver;
        spin_unlock_irqrestore(&udc->lock, flags);
 
index 9bb7a9d7a2fb245e6039e6254db4077dff4fd998..4f8617210d852643e55a5b8463d0f03b6d9e9c78 100644 (file)
@@ -2908,7 +2908,6 @@ static int pch_udc_start(struct usb_gadget *g,
 {
        struct pch_udc_dev      *dev = to_pch_udc(g);
 
-       driver->driver.bus = NULL;
        dev->driver = driver;
 
        /* get ready for ep0 traffic */
index 52ea4dcf6a9275eb05082a8bb97ac4681b5bd80d..2fc5d4d277bc4a594f3ed883a0b2398712347334 100644 (file)
@@ -1933,7 +1933,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
        struct udc *dev = to_amd5536_udc(g);
        u32 tmp;
 
-       driver->driver.bus = NULL;
        dev->driver = driver;
 
        /* Some gadget drivers use both ep0 directions.
index 9cea785934e596434a0ff380667f29771913168a..38d06e5abfbb35e6ba2c2912f9a613b6c792bf35 100644 (file)
@@ -29,7 +29,7 @@
 #include "ehci-fsl.h"
 
 #define DRIVER_DESC "Freescale EHCI Host controller driver"
-#define DRV_NAME "ehci-fsl"
+#define DRV_NAME "fsl-ehci"
 
 static struct hc_driver __read_mostly fsl_ehci_hc_driver;
 
index 79d679b3e07607b26349e211f1fa37f8248bd0f9..fb988e4ea9244e160e7b2af6aabf01901b9b4d63 100644 (file)
@@ -78,9 +78,12 @@ static const char hcd_name[] = "xhci_hcd";
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
 
 static int xhci_pci_setup(struct usb_hcd *hcd);
+static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+                                     struct usb_tt *tt, gfp_t mem_flags);
 
 static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
        .reset = xhci_pci_setup,
+       .update_hub_device = xhci_pci_update_hub_device,
 };
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -352,8 +355,38 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
                                NULL);
        ACPI_FREE(obj);
 }
+
+static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct xhci_hub *rhub = &xhci->usb3_rhub;
+       int ret;
+       int i;
+
+       /* This is not the usb3 roothub we are looking for */
+       if (hcd != rhub->hcd)
+               return;
+
+       if (hdev->maxchild > rhub->num_ports) {
+               dev_err(&hdev->dev, "USB3 roothub port number mismatch\n");
+               return;
+       }
+
+       for (i = 0; i < hdev->maxchild; i++) {
+               ret = usb_acpi_port_lpm_incapable(hdev, i);
+
+               dev_dbg(&hdev->dev, "port-%d disable U1/U2 _DSM: %d\n", i + 1, ret);
+
+               if (ret >= 0) {
+                       rhub->ports[i]->lpm_incapable = ret;
+                       continue;
+               }
+       }
+}
+
 #else
 static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) { }
 #endif /* CONFIG_ACPI */
 
 /* called during probe() after chip reset completes */
@@ -386,6 +419,16 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        return xhci_pci_reinit(xhci, pdev);
 }
 
+static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+                                     struct usb_tt *tt, gfp_t mem_flags)
+{
+       /* Check if acpi claims some USB3 roothub ports are lpm incapable */
+       if (!hdev->parent)
+               xhci_find_lpm_incapable_ports(hcd, hdev);
+
+       return xhci_update_hub_device(hcd, hdev, tt, mem_flags);
+}
+
 /*
  * We need to register our own PCI probe function (instead of the USB core's
  * function) in order to create a second roothub under xHCI.
@@ -455,6 +498,8 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
                pm_runtime_allow(&dev->dev);
 
+       dma_set_max_seg_size(&dev->dev, UINT_MAX);
+
        return 0;
 
 put_usb3_hcd:
index ddc30037f9cefa6f606f590ea1ed79325b0ba4da..f5b0e1ce22af201582708e6f6c1803935ce4e412 100644 (file)
@@ -1169,7 +1169,10 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
        struct xhci_virt_ep *ep;
        struct xhci_ring *ring;
 
-       ep = &xhci->devs[slot_id]->eps[ep_index];
+       ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+       if (!ep)
+               return;
+
        if ((ep->ep_state & EP_HAS_STREAMS) ||
                        (ep->ep_state & EP_GETTING_NO_STREAMS)) {
                int stream_id;
index 79d7931c048a8cd785101adb064c2f0ea8908f2a..2b280beb001150c59f05d0fc627a6b0cc7d4e879 100644 (file)
@@ -3974,6 +3974,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        struct xhci_virt_device *virt_dev;
        struct xhci_slot_ctx *slot_ctx;
+       unsigned long flags;
        int i, ret;
 
        /*
@@ -4000,7 +4001,11 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
                virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;
        virt_dev->udev = NULL;
        xhci_disable_slot(xhci, udev->slot_id);
+
+       spin_lock_irqsave(&xhci->lock, flags);
        xhci_free_virt_device(xhci, udev->slot_id);
+       spin_unlock_irqrestore(&xhci->lock, flags);
+
 }
 
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
@@ -5044,6 +5049,7 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
                        struct usb_device *udev, enum usb3_link_state state)
 {
        struct xhci_hcd *xhci;
+       struct xhci_port *port;
        u16 hub_encoded_timeout;
        int mel;
        int ret;
@@ -5060,6 +5066,13 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
        if (xhci_check_tier_policy(xhci, udev, state) < 0)
                return USB3_LPM_DISABLED;
 
+       /* If connected to root port then check port can handle lpm */
+       if (udev->parent && !udev->parent->parent) {
+               port = xhci->usb3_rhub.ports[udev->portnum - 1];
+               if (port->lpm_incapable)
+                       return USB3_LPM_DISABLED;
+       }
+
        hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state);
        mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout);
        if (mel < 0) {
@@ -5119,7 +5132,7 @@ static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
 /* Once a hub descriptor is fetched for a device, we need to update the xHC's
  * internal data structures for the device.
  */
-static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
                        struct usb_tt *tt, gfp_t mem_flags)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -5219,6 +5232,7 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
        xhci_free_command(xhci, config_cmd);
        return ret;
 }
+EXPORT_SYMBOL_GPL(xhci_update_hub_device);
 
 static int xhci_get_frame(struct usb_hcd *hcd)
 {
@@ -5502,6 +5516,8 @@ void xhci_init_driver(struct hc_driver *drv,
                        drv->check_bandwidth = over->check_bandwidth;
                if (over->reset_bandwidth)
                        drv->reset_bandwidth = over->reset_bandwidth;
+               if (over->update_hub_device)
+                       drv->update_hub_device = over->update_hub_device;
        }
 }
 EXPORT_SYMBOL_GPL(xhci_init_driver);
index c9f06c5e4e9d2a7795aba70c9099e6bce937134f..dcee7f3207add0bba0ebb9c9d449d0b2608e9ecc 100644 (file)
@@ -1735,6 +1735,7 @@ struct xhci_port {
        int                     hcd_portnum;
        struct xhci_hub         *rhub;
        struct xhci_port_cap    *port_cap;
+       unsigned int            lpm_incapable:1;
 };
 
 struct xhci_hub {
@@ -1943,6 +1944,8 @@ struct xhci_driver_overrides {
                             struct usb_host_endpoint *ep);
        int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
        void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+       int (*update_hub_device)(struct usb_hcd *hcd, struct usb_device *hdev,
+                           struct usb_tt *tt, gfp_t mem_flags);
 };
 
 #define        XHCI_CFC_DELAY          10
@@ -2122,6 +2125,8 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                       struct usb_host_endpoint *ep);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+                          struct usb_tt *tt, gfp_t mem_flags);
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
 int xhci_ext_cap_init(struct xhci_hcd *xhci);
 
index f9427a67789cf7e26a1c95ecb28f17087ad30d42..1e3df27bab58fd1cb2be079dab3bbdca43e6a51a 100644 (file)
@@ -814,7 +814,7 @@ static int iowarrior_probe(struct usb_interface *interface,
                        break;
 
                case USB_DEVICE_ID_CODEMERCS_IOW100:
-                       dev->report_size = 13;
+                       dev->report_size = 12;
                        break;
                }
        }
index 94e7966e199d19a2cf27e7f41de6b179d105d8d2..969c4c4f2ae92dbdb074f356dcbc688e1e1aa0f2 100644 (file)
 
 #include "onboard_usb_hub.h"
 
+static void onboard_hub_attach_usb_driver(struct work_struct *work);
+
 static struct usb_device_driver onboard_hub_usbdev_driver;
+static DECLARE_WORK(attach_usb_driver_work, onboard_hub_attach_usb_driver);
 
 /************************** Platform driver **************************/
 
@@ -45,7 +48,6 @@ struct onboard_hub {
        bool is_powered_on;
        bool going_away;
        struct list_head udev_list;
-       struct work_struct attach_usb_driver_work;
        struct mutex lock;
 };
 
@@ -271,8 +273,7 @@ static int onboard_hub_probe(struct platform_device *pdev)
         * This needs to be done deferred to avoid self-deadlocks on systems
         * with nested onboard hubs.
         */
-       INIT_WORK(&hub->attach_usb_driver_work, onboard_hub_attach_usb_driver);
-       schedule_work(&hub->attach_usb_driver_work);
+       schedule_work(&attach_usb_driver_work);
 
        return 0;
 }
@@ -285,9 +286,6 @@ static int onboard_hub_remove(struct platform_device *pdev)
 
        hub->going_away = true;
 
-       if (&hub->attach_usb_driver_work != current_work())
-               cancel_work_sync(&hub->attach_usb_driver_work);
-
        mutex_lock(&hub->lock);
 
        /* unbind the USB devices to avoid dangling references to this device */
@@ -433,13 +431,13 @@ static int __init onboard_hub_init(void)
 {
        int ret;
 
-       ret = platform_driver_register(&onboard_hub_driver);
+       ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE);
        if (ret)
                return ret;
 
-       ret = usb_register_device_driver(&onboard_hub_usbdev_driver, THIS_MODULE);
+       ret = platform_driver_register(&onboard_hub_driver);
        if (ret)
-               platform_driver_unregister(&onboard_hub_driver);
+               usb_deregister_device_driver(&onboard_hub_usbdev_driver);
 
        return ret;
 }
@@ -449,6 +447,8 @@ static void __exit onboard_hub_exit(void)
 {
        usb_deregister_device_driver(&onboard_hub_usbdev_driver);
        platform_driver_unregister(&onboard_hub_driver);
+
+       cancel_work_sync(&attach_usb_driver_work);
 }
 module_exit(onboard_hub_exit);
 
index 476f55d1fec3084a33ecd586855d626e01ad4caf..44a21ec865fb219ec80eb34e66c46bc1ee7c6265 100644 (file)
@@ -411,8 +411,10 @@ static int omap2430_probe(struct platform_device *pdev)
                memset(musb_res, 0, sizeof(*musb_res) * ARRAY_SIZE(musb_res));
 
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               if (!res)
+               if (!res) {
+                       ret = -EINVAL;
                        goto err2;
+               }
 
                musb_res[i].start = res->start;
                musb_res[i].end = res->end;
index 67372acc23529da1cb5c4e0b2f1e07ca15d7dee6..832ad592b7ef3bed8411922c9fec294591ea0756 100644 (file)
@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
+       { USB_DEVICE(0x0908, 0x0070) }, /* Siemens SCALANCE LPE-9000 USB Serial Console */
        { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */
        { USB_DEVICE(0x0988, 0x0578) }, /* Teraoka AD2000 */
        { USB_DEVICE(0x0B00, 0x3070) }, /* Ingenico 3070 */
index dee79c7d82d5ce475f67477e8ed68709065ff16a..ee5ac4ef7e1620cf0471ccf2f34b4ee6d3768dc9 100644 (file)
@@ -255,10 +255,16 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_EP06                   0x0306
 #define QUECTEL_PRODUCT_EM05G                  0x030a
 #define QUECTEL_PRODUCT_EM060K                 0x030b
+#define QUECTEL_PRODUCT_EM05G_CS               0x030c
+#define QUECTEL_PRODUCT_EM05CN_SG              0x0310
 #define QUECTEL_PRODUCT_EM05G_SG               0x0311
+#define QUECTEL_PRODUCT_EM05CN                 0x0312
+#define QUECTEL_PRODUCT_EM05G_GR               0x0313
+#define QUECTEL_PRODUCT_EM05G_RS               0x0314
 #define QUECTEL_PRODUCT_EM12                   0x0512
 #define QUECTEL_PRODUCT_RM500Q                 0x0800
 #define QUECTEL_PRODUCT_RM520N                 0x0801
+#define QUECTEL_PRODUCT_EC200U                 0x0901
 #define QUECTEL_PRODUCT_EC200S_CN              0x6002
 #define QUECTEL_PRODUCT_EC200T                 0x6026
 #define QUECTEL_PRODUCT_RM500K                 0x7001
@@ -1159,8 +1165,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05CN, 0xff),
+         .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05CN_SG, 0xff),
+         .driver_info = RSVD(6) | ZLP },
        { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
          .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_CS, 0xff),
+         .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_GR, 0xff),
+         .driver_info = RSVD(6) | ZLP },
+       { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_RS, 0xff),
+         .driver_info = RSVD(6) | ZLP },
        { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G_SG, 0xff),
          .driver_info = RSVD(6) | ZLP },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
@@ -1180,6 +1196,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
index 3f720faa6f97c1d313ba45c48822b7c7d6aa7496..d73282c0ec50174e7c37d85a0253fe11abaa55b4 100644 (file)
@@ -116,6 +116,19 @@ static int uas_use_uas_driver(struct usb_interface *intf,
        if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bc2)
                flags |= US_FL_NO_ATA_1X;
 
+       /*
+        * RTL9210-based enclosure from HIKSEMI, MD202 reportedly have issues
+        * with UAS.  This isn't distinguishable with just idVendor and
+        * idProduct, use manufacturer and product too.
+        *
+        * Reported-by: Hongling Zeng <zenghongling@kylinos.cn>
+        */
+       if (le16_to_cpu(udev->descriptor.idVendor) == 0x0bda &&
+                       le16_to_cpu(udev->descriptor.idProduct) == 0x9210 &&
+                       (udev->manufacturer && !strcmp(udev->manufacturer, "HIKSEMI")) &&
+                       (udev->product && !strcmp(udev->product, "MD202")))
+               flags |= US_FL_IGNORE_UAS;
+
        usb_stor_adjust_quirks(udev, &flags);
 
        if (flags & US_FL_IGNORE_UAS) {
index 251778d14e2dd41f848286fa5d2ea50c93c40e61..c7b763d6d102394aba9080cfc104db9cb2b3c9c3 100644 (file)
@@ -83,13 +83,6 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_REPORT_LUNS),
 
-/* Reported-by: Hongling Zeng <zenghongling@kylinos.cn> */
-UNUSUAL_DEV(0x0bda, 0x9210, 0x0000, 0x9999,
-               "Hiksemi",
-               "External HDD",
-               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
-               US_FL_IGNORE_UAS),
-
 /* Reported-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> */
 UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
                "Initio Corporation",
index de66a2949e33b2b2f029056af449228b851904f6..9a6860285fbec44342a45dee74e84af9a4dd2ad3 100644 (file)
@@ -419,6 +419,18 @@ static const char * const pin_assignments[] = {
        [DP_PIN_ASSIGN_F] = "F",
 };
 
+/*
+ * Helper function to extract a peripheral's currently supported
+ * Pin Assignments from its DisplayPort alternate mode state.
+ */
+static u8 get_current_pin_assignments(struct dp_altmode *dp)
+{
+       if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_UFP_U_AS_DFP_D)
+               return DP_CAP_PIN_ASSIGN_DFP_D(dp->alt->vdo);
+       else
+               return DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo);
+}
+
 static ssize_t
 pin_assignment_store(struct device *dev, struct device_attribute *attr,
                     const char *buf, size_t size)
@@ -445,10 +457,7 @@ pin_assignment_store(struct device *dev, struct device_attribute *attr,
                goto out_unlock;
        }
 
-       if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D)
-               assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo);
-       else
-               assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo);
+       assignments = get_current_pin_assignments(dp);
 
        if (!(DP_CONF_GET_PIN_ASSIGN(conf) & assignments)) {
                ret = -EINVAL;
@@ -485,10 +494,7 @@ static ssize_t pin_assignment_show(struct device *dev,
 
        cur = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
 
-       if (DP_CONF_CURRENTLY(dp->data.conf) == DP_CONF_DFP_D)
-               assignments = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo);
-       else
-               assignments = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo);
+       assignments = get_current_pin_assignments(dp);
 
        for (i = 0; assignments; assignments >>= 1, i++) {
                if (assignments & 1) {
index 904c7b4ce2f0c278ed5f36f5d7ccb91ac02ff685..59b366b5c6144728d7637ffca353d93c351b8e2b 100644 (file)
@@ -4594,14 +4594,13 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_state(port, ready_state(port), 0);
                break;
        case DR_SWAP_CHANGE_DR:
-               if (port->data_role == TYPEC_HOST) {
-                       tcpm_unregister_altmodes(port);
+               tcpm_unregister_altmodes(port);
+               if (port->data_role == TYPEC_HOST)
                        tcpm_set_roles(port, true, port->pwr_role,
                                       TYPEC_DEVICE);
-               } else {
+               else
                        tcpm_set_roles(port, true, port->pwr_role,
                                       TYPEC_HOST);
-               }
                tcpm_ams_finish(port);
                tcpm_set_state(port, ready_state(port), 0);
                break;
index eabe519013e7850837c56d60f718d55a27f07fc3..1cf8947c6d6611e9f43d8244941882050621869c 100644 (file)
@@ -187,6 +187,7 @@ EXPORT_SYMBOL_GPL(ucsi_send_command);
 
 struct ucsi_work {
        struct delayed_work work;
+       struct list_head node;
        unsigned long delay;
        unsigned int count;
        struct ucsi_connector *con;
@@ -202,6 +203,7 @@ static void ucsi_poll_worker(struct work_struct *work)
        mutex_lock(&con->lock);
 
        if (!con->partner) {
+               list_del(&uwork->node);
                mutex_unlock(&con->lock);
                kfree(uwork);
                return;
@@ -209,10 +211,12 @@ static void ucsi_poll_worker(struct work_struct *work)
 
        ret = uwork->cb(con);
 
-       if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT))
+       if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT)) {
                queue_delayed_work(con->wq, &uwork->work, uwork->delay);
-       else
+       } else {
+               list_del(&uwork->node);
                kfree(uwork);
+       }
 
        mutex_unlock(&con->lock);
 }
@@ -236,6 +240,7 @@ static int ucsi_partner_task(struct ucsi_connector *con,
        uwork->con = con;
        uwork->cb = cb;
 
+       list_add_tail(&uwork->node, &con->partner_tasks);
        queue_delayed_work(con->wq, &uwork->work, delay);
 
        return 0;
@@ -1056,6 +1061,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
        INIT_WORK(&con->work, ucsi_handle_connector_change);
        init_completion(&con->complete);
        mutex_init(&con->lock);
+       INIT_LIST_HEAD(&con->partner_tasks);
        con->num = index + 1;
        con->ucsi = ucsi;
 
@@ -1263,6 +1269,9 @@ err_unregister:
                con->port = NULL;
        }
 
+       kfree(ucsi->connector);
+       ucsi->connector = NULL;
+
 err_reset:
        memset(&ucsi->cap, 0, sizeof(ucsi->cap));
        ucsi_reset_ppm(ucsi);
@@ -1294,7 +1303,8 @@ static void ucsi_resume_work(struct work_struct *work)
 
 int ucsi_resume(struct ucsi *ucsi)
 {
-       queue_work(system_long_wq, &ucsi->resume_work);
+       if (ucsi->connector)
+               queue_work(system_long_wq, &ucsi->resume_work);
        return 0;
 }
 EXPORT_SYMBOL_GPL(ucsi_resume);
@@ -1414,14 +1424,29 @@ void ucsi_unregister(struct ucsi *ucsi)
        /* Disable notifications */
        ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
 
+       if (!ucsi->connector)
+               return;
+
        for (i = 0; i < ucsi->cap.num_connectors; i++) {
                cancel_work_sync(&ucsi->connector[i].work);
                ucsi_unregister_partner(&ucsi->connector[i]);
                ucsi_unregister_altmodes(&ucsi->connector[i],
                                         UCSI_RECIPIENT_CON);
                ucsi_unregister_port_psy(&ucsi->connector[i]);
-               if (ucsi->connector[i].wq)
+
+               if (ucsi->connector[i].wq) {
+                       struct ucsi_work *uwork;
+
+                       mutex_lock(&ucsi->connector[i].lock);
+                       /*
+                        * queue delayed items immediately so they can execute
+                        * and free themselves before the wq is destroyed
+                        */
+                       list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node)
+                               mod_delayed_work(ucsi->connector[i].wq, &uwork->work, 0);
+                       mutex_unlock(&ucsi->connector[i].lock);
                        destroy_workqueue(ucsi->connector[i].wq);
+               }
                typec_unregister_port(ucsi->connector[i].port);
        }
 
index c968474ee547396fa64d4469b5805e37ed18efb4..60ce9fb6e7450f5c29168393e31ef78fe23c875e 100644 (file)
@@ -322,6 +322,7 @@ struct ucsi_connector {
        struct work_struct work;
        struct completion complete;
        struct workqueue_struct *wq;
+       struct list_head partner_tasks;
 
        struct typec_port *port;
        struct typec_partner *partner;
index f9c0044c6442e4b115224fe2927c02fa2f33aeb0..44b29289aa193883c494863c87159a96e066727d 100644 (file)
@@ -849,7 +849,7 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ret = ifcvf_init_hw(vf, pdev);
        if (ret) {
                IFCVF_ERR(pdev, "Failed to init IFCVF hw\n");
-               return ret;
+               goto err;
        }
 
        for (i = 0; i < vf->nr_vring; i++)
index 23c24fe98c00d4a07ef73826a02d81386cf2118d..2209372f236dbb84d1b77c335c3acbe3d9584e82 100644 (file)
@@ -1856,24 +1856,33 @@ unwind:
  * significantly boosts non-hugetlbfs mappings and doesn't seem to hurt when
  * hugetlbfs is in use.
  */
-static void vfio_test_domain_fgsp(struct vfio_domain *domain)
+static void vfio_test_domain_fgsp(struct vfio_domain *domain, struct list_head *regions)
 {
-       struct page *pages;
        int ret, order = get_order(PAGE_SIZE * 2);
+       struct vfio_iova *region;
+       struct page *pages;
+       dma_addr_t start;
 
        pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
        if (!pages)
                return;
 
-       ret = iommu_map(domain->domain, 0, page_to_phys(pages), PAGE_SIZE * 2,
-                       IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE);
-       if (!ret) {
-               size_t unmapped = iommu_unmap(domain->domain, 0, PAGE_SIZE);
+       list_for_each_entry(region, regions, list) {
+               start = ALIGN(region->start, PAGE_SIZE * 2);
+               if (start >= region->end || (region->end - start < PAGE_SIZE * 2))
+                       continue;
 
-               if (unmapped == PAGE_SIZE)
-                       iommu_unmap(domain->domain, PAGE_SIZE, PAGE_SIZE);
-               else
-                       domain->fgsp = true;
+               ret = iommu_map(domain->domain, start, page_to_phys(pages), PAGE_SIZE * 2,
+                               IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE);
+               if (!ret) {
+                       size_t unmapped = iommu_unmap(domain->domain, start, PAGE_SIZE);
+
+                       if (unmapped == PAGE_SIZE)
+                               iommu_unmap(domain->domain, start + PAGE_SIZE, PAGE_SIZE);
+                       else
+                               domain->fgsp = true;
+               }
+               break;
        }
 
        __free_pages(pages, order);
@@ -2326,7 +2335,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
                }
        }
 
-       vfio_test_domain_fgsp(domain);
+       vfio_test_domain_fgsp(domain, &iova_copy);
 
        /* replay mappings on new domains */
        ret = vfio_iommu_replay(iommu, domain);
index 9af19b0cf3b7e98622cfd0256a3a2f818cf0366b..4c538b30fd76ded5fb19b5a9b98ff9b409557a51 100644 (file)
@@ -1511,6 +1511,9 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        nvq = &n->vqs[index];
        mutex_lock(&vq->mutex);
 
+       if (fd == -1)
+               vhost_clear_msg(&n->dev);
+
        /* Verify that ring has been setup correctly. */
        if (!vhost_vq_access_ok(vq)) {
                r = -EFAULT;
index dca6346d75b306b6638cb9fc67dfe0d7305fb12d..d5ecb8876fc9a18d9a985b546a93249d150ca5e4 100644 (file)
@@ -80,7 +80,7 @@ struct vhost_scsi_cmd {
        struct scatterlist *tvc_prot_sgl;
        struct page **tvc_upages;
        /* Pointer to response header iovec */
-       struct iovec tvc_resp_iov;
+       struct iovec *tvc_resp_iov;
        /* Pointer to vhost_scsi for our device */
        struct vhost_scsi *tvc_vhost;
        /* Pointer to vhost_virtqueue for the cmd */
@@ -563,7 +563,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
                memcpy(v_rsp.sense, cmd->tvc_sense_buf,
                       se_cmd->scsi_sense_length);
 
-               iov_iter_init(&iov_iter, ITER_DEST, &cmd->tvc_resp_iov,
+               iov_iter_init(&iov_iter, ITER_DEST, cmd->tvc_resp_iov,
                              cmd->tvc_in_iovs, sizeof(v_rsp));
                ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter);
                if (likely(ret == sizeof(v_rsp))) {
@@ -594,6 +594,7 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
        struct vhost_scsi_cmd *cmd;
        struct vhost_scsi_nexus *tv_nexus;
        struct scatterlist *sg, *prot_sg;
+       struct iovec *tvc_resp_iov;
        struct page **pages;
        int tag;
 
@@ -613,6 +614,7 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
        sg = cmd->tvc_sgl;
        prot_sg = cmd->tvc_prot_sgl;
        pages = cmd->tvc_upages;
+       tvc_resp_iov = cmd->tvc_resp_iov;
        memset(cmd, 0, sizeof(*cmd));
        cmd->tvc_sgl = sg;
        cmd->tvc_prot_sgl = prot_sg;
@@ -625,6 +627,7 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
        cmd->tvc_data_direction = data_direction;
        cmd->tvc_nexus = tv_nexus;
        cmd->inflight = vhost_scsi_get_inflight(vq);
+       cmd->tvc_resp_iov = tvc_resp_iov;
 
        memcpy(cmd->tvc_cdb, cdb, VHOST_SCSI_MAX_CDB_SIZE);
 
@@ -935,7 +938,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
        struct iov_iter in_iter, prot_iter, data_iter;
        u64 tag;
        u32 exp_data_len, data_direction;
-       int ret, prot_bytes, c = 0;
+       int ret, prot_bytes, i, c = 0;
        u16 lun;
        u8 task_attr;
        bool t10_pi = vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI);
@@ -1092,7 +1095,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                }
                cmd->tvc_vhost = vs;
                cmd->tvc_vq = vq;
-               cmd->tvc_resp_iov = vq->iov[vc.out];
+               for (i = 0; i < vc.in ; i++)
+                       cmd->tvc_resp_iov[i] = vq->iov[vc.out + i];
                cmd->tvc_in_iovs = vc.in;
 
                pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n",
@@ -1461,6 +1465,7 @@ static void vhost_scsi_destroy_vq_cmds(struct vhost_virtqueue *vq)
                kfree(tv_cmd->tvc_sgl);
                kfree(tv_cmd->tvc_prot_sgl);
                kfree(tv_cmd->tvc_upages);
+               kfree(tv_cmd->tvc_resp_iov);
        }
 
        sbitmap_free(&svq->scsi_tags);
@@ -1508,6 +1513,14 @@ static int vhost_scsi_setup_vq_cmds(struct vhost_virtqueue *vq, int max_cmds)
                        goto out;
                }
 
+               tv_cmd->tvc_resp_iov = kcalloc(UIO_MAXIOV,
+                                              sizeof(struct iovec),
+                                              GFP_KERNEL);
+               if (!tv_cmd->tvc_resp_iov) {
+                       pr_err("Unable to allocate tv_cmd->tvc_resp_iov\n");
+                       goto out;
+               }
+
                tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS,
                                               sizeof(struct scatterlist),
                                               GFP_KERNEL);
index cbe72bfd2f1faa11132931511bf8b466b481789f..43c9770b86e5aeb6bcd9ef7788d197c64900271d 100644 (file)
@@ -661,7 +661,7 @@ void vhost_dev_stop(struct vhost_dev *dev)
 }
 EXPORT_SYMBOL_GPL(vhost_dev_stop);
 
-static void vhost_clear_msg(struct vhost_dev *dev)
+void vhost_clear_msg(struct vhost_dev *dev)
 {
        struct vhost_msg_node *node, *n;
 
@@ -679,6 +679,7 @@ static void vhost_clear_msg(struct vhost_dev *dev)
 
        spin_unlock(&dev->iotlb_lock);
 }
+EXPORT_SYMBOL_GPL(vhost_clear_msg);
 
 void vhost_dev_cleanup(struct vhost_dev *dev)
 {
index d9109107af087fc18e031b2f0fc93d6659cfcfee..790b296271f1e465c503cca7779a2d27c51808d9 100644 (file)
@@ -181,6 +181,7 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
 long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
 bool vhost_vq_access_ok(struct vhost_virtqueue *vq);
 bool vhost_log_access_ok(struct vhost_dev *);
+void vhost_clear_msg(struct vhost_dev *dev);
 
 int vhost_get_vq_desc(struct vhost_virtqueue *,
                      struct iovec iov[], unsigned int iov_count,
index 1fc8de4ecbebf9e5e2974c3c97cba94d536d73c4..8187a7c4f9106b05f907da0d75e0394bbd3b54c4 100644 (file)
@@ -49,7 +49,6 @@ struct atmel_lcdfb_info {
        struct clk              *lcdc_clk;
 
        struct backlight_device *backlight;
-       u8                      bl_power;
        u8                      saved_lcdcon;
 
        u32                     pseudo_palette[16];
@@ -109,22 +108,7 @@ static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
 static int atmel_bl_update_status(struct backlight_device *bl)
 {
        struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
-       int                     power = sinfo->bl_power;
-       int                     brightness = bl->props.brightness;
-
-       /* REVISIT there may be a meaningful difference between
-        * fb_blank and power ... there seem to be some cases
-        * this doesn't handle correctly.
-        */
-       if (bl->props.fb_blank != sinfo->bl_power)
-               power = bl->props.fb_blank;
-       else if (bl->props.power != sinfo->bl_power)
-               power = bl->props.power;
-
-       if (brightness < 0 && power == FB_BLANK_UNBLANK)
-               brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
-       else if (power != FB_BLANK_UNBLANK)
-               brightness = 0;
+       int                     brightness = backlight_get_brightness(bl);
 
        lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
        if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
@@ -133,8 +117,6 @@ static int atmel_bl_update_status(struct backlight_device *bl)
        else
                lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
 
-       bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
-
        return 0;
 }
 
@@ -155,8 +137,6 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
        struct backlight_properties props;
        struct backlight_device *bl;
 
-       sinfo->bl_power = FB_BLANK_UNBLANK;
-
        if (sinfo->backlight)
                return;
 
index dd31b9d7d337cc41fb61e9b14a6a65f663be1c4f..36a9ac05a340f93ab6f1259001ad2feee6791e24 100644 (file)
@@ -1766,12 +1766,10 @@ static int aty128_bl_update_status(struct backlight_device *bd)
        unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
        int level;
 
-       if (bd->props.power != FB_BLANK_UNBLANK ||
-           bd->props.fb_blank != FB_BLANK_UNBLANK ||
-           !par->lcd_on)
+       if (!par->lcd_on)
                level = 0;
        else
-               level = bd->props.brightness;
+               level = backlight_get_brightness(bd);
 
        reg |= LVDS_BL_MOD_EN | LVDS_BLON;
        if (level > 0) {
index d59215a4992e0a0d0a3ae7d09517fa0bca28ab95..b02e4e645035c44716740805bc3ffdb666d12c0d 100644 (file)
@@ -2219,13 +2219,7 @@ static int aty_bl_update_status(struct backlight_device *bd)
 {
        struct atyfb_par *par = bl_get_data(bd);
        unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
-       int level;
-
-       if (bd->props.power != FB_BLANK_UNBLANK ||
-           bd->props.fb_blank != FB_BLANK_UNBLANK)
-               level = 0;
-       else
-               level = bd->props.brightness;
+       int level = backlight_get_brightness(bd);
 
        reg |= (BLMOD_EN | BIASMOD_EN);
        if (level > 0) {
index d2c1263ad26005e13795b37bffdf87220c8a042d..427adc838f77e20eb3b37f75c1907a30b9785df2 100644 (file)
@@ -57,11 +57,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
         * backlight. This provides some greater power saving and the display
         * is useless without backlight anyway.
         */
-        if (bd->props.power != FB_BLANK_UNBLANK ||
-           bd->props.fb_blank != FB_BLANK_UNBLANK)
-               level = 0;
-       else
-               level = bd->props.brightness;
+       level = backlight_get_brightness(bd);
 
        del_timer_sync(&rinfo->lvds_timer);
        radeon_engine_idle();
index 14a7d404062c38e006933da5d42a729b8f9fbf07..1b14c21af2b74983f02dd17dbf99bae8a249e25f 100644 (file)
@@ -2495,9 +2495,12 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
            h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres))
                return -EINVAL;
 
+       if (font->width > 32 || font->height > 32)
+               return -EINVAL;
+
        /* Make sure drawing engine can handle the font */
-       if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
-           !(info->pixmap.blit_y & (1 << (font->height - 1))))
+       if (!(info->pixmap.blit_x & BIT(font->width - 1)) ||
+           !(info->pixmap.blit_y & BIT(font->height - 1)))
                return -EINVAL;
 
        /* Make sure driver can handle the font length */
index b0e690f41025a23e2b9798f7675f5991f3797ad1..79e5bfbdd34c26af7345d433e1c551321031aa6e 100644 (file)
@@ -1050,7 +1050,7 @@ static u32 fb_get_vblank(u32 hfreq)
 }
 
 /**
- * fb_get_hblank_by_freq - get horizontal blank time given hfreq
+ * fb_get_hblank_by_hfreq - get horizontal blank time given hfreq
  * @hfreq: horizontal freq
  * @xres: horizontal resolution in pixels
  *
index b945b68984b9732f93679e84651b5a72f4b973f3..76771e126d0af805238ebfc069ea288f5476c3be 100644 (file)
@@ -283,12 +283,7 @@ static int mx3fb_bl_get_brightness(struct backlight_device *bl)
 static int mx3fb_bl_update_status(struct backlight_device *bl)
 {
        struct mx3fb_data *fbd = bl_get_data(bl);
-       int brightness = bl->props.brightness;
-
-       if (bl->props.power != FB_BLANK_UNBLANK)
-               brightness = 0;
-       if (bl->props.fb_blank != FB_BLANK_UNBLANK)
-               brightness = 0;
+       int brightness = backlight_get_brightness(bl);
 
        fbd->backlight_level = (fbd->backlight_level & ~0xFF) | brightness;
 
index 2ce53529f63612507638853cace3ed55aff6ef3e..503a7a683855aaaf8610d6216d5b4dd6d036d305 100644 (file)
@@ -49,17 +49,11 @@ static int nvidia_bl_update_status(struct backlight_device *bd)
 {
        struct nvidia_par *par = bl_get_data(bd);
        u32 tmp_pcrt, tmp_pmc, fpcontrol;
-       int level;
+       int level = backlight_get_brightness(bd);
 
        if (!par->FlatPanel)
                return 0;
 
-       if (bd->props.power != FB_BLANK_UNBLANK ||
-           bd->props.fb_blank != FB_BLANK_UNBLANK)
-               level = 0;
-       else
-               level = bd->props.brightness;
-
        tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
        tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
        fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
index 4fc4b26a8d3043543421b347bd86805ba7c15c73..ba94a0a7bd4fc2100a42e7033cadde19f947ef5c 100644 (file)
@@ -331,13 +331,7 @@ static int dsicm_bl_update_status(struct backlight_device *dev)
        struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
        struct omap_dss_device *in = ddata->in;
        int r;
-       int level;
-
-       if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
-                       dev->props.power == FB_BLANK_UNBLANK)
-               level = dev->props.brightness;
-       else
-               level = 0;
+       int level = backlight_get_brightness(dev);
 
        dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level);
 
index bc5a44c2a144ab03a7a8a0ad3299611e9d7dc8e8..ae937854403b1278107ade98c9d9922cbf83ec22 100644 (file)
@@ -10,6 +10,7 @@
 #define DSS_SUBSYS_NAME "DISPLAY"
 
 #include <linux/kernel.h>
+#include <linux/kstrtox.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/sysfs.h>
@@ -36,7 +37,7 @@ static ssize_t display_enabled_store(struct omap_dss_device *dssdev,
        int r;
        bool enable;
 
-       r = strtobool(buf, &enable);
+       r = kstrtobool(buf, &enable);
        if (r)
                return r;
 
@@ -73,7 +74,7 @@ static ssize_t display_tear_store(struct omap_dss_device *dssdev,
        if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
                return -ENOENT;
 
-       r = strtobool(buf, &te);
+       r = kstrtobool(buf, &te);
        if (r)
                return r;
 
@@ -183,7 +184,7 @@ static ssize_t display_mirror_store(struct omap_dss_device *dssdev,
        if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
                return -ENOENT;
 
-       r = strtobool(buf, &mirror);
+       r = kstrtobool(buf, &mirror);
        if (r)
                return r;
 
index ba21c4a2633dd094c52138b2a5879bfa4e4c825b..1b644be5fe2ed051c1a77e80756b9757dc778d3c 100644 (file)
@@ -10,6 +10,7 @@
 #define DSS_SUBSYS_NAME "MANAGER"
 
 #include <linux/kernel.h>
+#include <linux/kstrtox.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -246,7 +247,7 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
        bool enable;
        int r;
 
-       r = strtobool(buf, &enable);
+       r = kstrtobool(buf, &enable);
        if (r)
                return r;
 
@@ -290,7 +291,7 @@ static ssize_t manager_alpha_blending_enabled_store(
        if(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
                return -ENODEV;
 
-       r = strtobool(buf, &enable);
+       r = kstrtobool(buf, &enable);
        if (r)
                return r;
 
@@ -329,7 +330,7 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
        if (!dss_has_feature(FEAT_CPR))
                return -ENODEV;
 
-       r = strtobool(buf, &enable);
+       r = kstrtobool(buf, &enable);
        if (r)
                return r;
 
index 601c0beb6de969c162f555e29bae0447d14fa5bd..1da4fb1c77b4a681bb913e60b2f74cf6e1c8cf23 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/err.h>
 #include <linux/sysfs.h>
 #include <linux/kobject.h>
+#include <linux/kstrtox.h>
 #include <linux/platform_device.h>
 
 #include <video/omapfb_dss.h>
@@ -210,7 +211,7 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
        int r;
        bool enable;
 
-       r = strtobool(buf, &enable);
+       r = kstrtobool(buf, &enable);
        if (r)
                return r;
 
index 06dc41aa03545ec4efb9b62309b3957626e01b95..831b2c2fbdf9ae709edf7050fc779fdc0e3d94a5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/uaccess.h>
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
+#include <linux/kstrtox.h>
 #include <linux/mm.h>
 #include <linux/omapfb.h>
 
@@ -96,7 +97,7 @@ static ssize_t store_mirror(struct device *dev,
        int r;
        struct fb_var_screeninfo new_var;
 
-       r = strtobool(buf, &mirror);
+       r = kstrtobool(buf, &mirror);
        if (r)
                return r;
 
index 644278146d3b7143add567f37521ea945dd252d6..41edc6e794603145e3d6da922b2285def60f1728 100644 (file)
@@ -293,13 +293,7 @@ static int riva_bl_update_status(struct backlight_device *bd)
 {
        struct riva_par *par = bl_get_data(bd);
        U032 tmp_pcrt, tmp_pmc;
-       int level;
-
-       if (bd->props.power != FB_BLANK_UNBLANK ||
-           bd->props.fb_blank != FB_BLANK_UNBLANK)
-               level = 0;
-       else
-               level = bd->props.brightness;
+       int level = backlight_get_brightness(bd);
 
        tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF;
        tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC;
index f2ae2e563dc54ad51fb9241450c586e13d131d71..4a2ddf730a3acd173caead38a733bda7c4e7f7be 100644 (file)
@@ -1166,6 +1166,8 @@ int w1_process(void *data)
        /* remainder if it woke up early */
        unsigned long jremain = 0;
 
+       atomic_inc(&dev->refcnt);
+
        for (;;) {
 
                if (!jremain && dev->search_count) {
@@ -1193,8 +1195,10 @@ int w1_process(void *data)
                 */
                mutex_unlock(&dev->list_mutex);
 
-               if (kthread_should_stop())
+               if (kthread_should_stop()) {
+                       __set_current_state(TASK_RUNNING);
                        break;
+               }
 
                /* Only sleep when the search is active. */
                if (dev->search_count) {
index b3e1792d9c49fce5da50cdaf67e6278f4a95454e..3a71c5eb2f837fee980adcf2d3fbcfce3346e342 100644 (file)
@@ -51,10 +51,9 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
        dev->search_count       = w1_search_count;
        dev->enable_pullup      = w1_enable_pullup;
 
-       /* 1 for w1_process to decrement
-        * 1 for __w1_remove_master_device to decrement
+       /* For __w1_remove_master_device to decrement
         */
-       atomic_set(&dev->refcnt, 2);
+       atomic_set(&dev->refcnt, 1);
 
        INIT_LIST_HEAD(&dev->slist);
        INIT_LIST_HEAD(&dev->async_list);
index 4cb10877017c7781d021253468589957df49afa8..6ca5d9515d85cae49c89333722658a47765be7b4 100644 (file)
@@ -86,7 +86,7 @@ static int __diag288(unsigned int func, unsigned int timeout,
                "1:\n"
                EX_TABLE(0b, 1b)
                : "+d" (err) : "d"(__func), "d"(__timeout),
-                 "d"(__action), "d"(__len) : "1", "cc");
+                 "d"(__action), "d"(__len) : "1", "cc", "memory");
        return err;
 }
 
@@ -268,12 +268,21 @@ static int __init diag288_init(void)
        char ebc_begin[] = {
                194, 197, 199, 201, 213
        };
+       char *ebc_cmd;
 
        watchdog_set_nowayout(&wdt_dev, nowayout_info);
 
        if (MACHINE_IS_VM) {
-               if (__diag288_vm(WDT_FUNC_INIT, 15,
-                                ebc_begin, sizeof(ebc_begin)) != 0) {
+               ebc_cmd = kmalloc(sizeof(ebc_begin), GFP_KERNEL);
+               if (!ebc_cmd) {
+                       pr_err("The watchdog cannot be initialized\n");
+                       return -ENOMEM;
+               }
+               memcpy(ebc_cmd, ebc_begin, sizeof(ebc_begin));
+               ret = __diag288_vm(WDT_FUNC_INIT, 15,
+                                  ebc_cmd, sizeof(ebc_begin));
+               kfree(ebc_cmd);
+               if (ret != 0) {
                        pr_err("The watchdog cannot be initialized\n");
                        return -EINVAL;
                }
index cefa222f7881c77560d51844ec3a8b7a6231462a..8daeed31e1af949a01beba514664f21725fdebda 100644 (file)
@@ -880,7 +880,7 @@ affs_truncate(struct inode *inode)
        if (inode->i_size > AFFS_I(inode)->mmu_private) {
                struct address_space *mapping = inode->i_mapping;
                struct page *page;
-               void *fsdata;
+               void *fsdata = NULL;
                loff_t isize = inode->i_size;
                int res;
 
index 8aeaada1fcaec2a9de8128cac61d29fafef5210c..3aa04224315eb383f3b61d8a278b02e68e01bb56 100644 (file)
@@ -367,7 +367,14 @@ error:
        btrfs_print_tree(eb, 0);
        btrfs_err(fs_info, "block=%llu write time tree block corruption detected",
                  eb->start);
-       WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
+       /*
+        * Be noisy if this is an extent buffer from a log tree. We don't abort
+        * a transaction in case there's a bad log tree extent buffer, we just
+        * fallback to a transaction commit. Still we want to know when there is
+        * a bad log tree extent buffer, as that may signal a bug somewhere.
+        */
+       WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG) ||
+               btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID);
        return ret;
 }
 
index 834bbcb91102fde71f4e3a7c68135a3cd4277cdd..af046d22300e2ccdcbce0984383a4e5e0a7feef4 100644 (file)
@@ -3541,6 +3541,7 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
                struct extent_buffer *leaf = path->nodes[0];
                struct btrfs_file_extent_item *extent;
                u64 extent_end;
+               u8 type;
 
                if (path->slots[0] >= btrfs_header_nritems(leaf)) {
                        ret = btrfs_next_leaf(root, path);
@@ -3596,10 +3597,16 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
 
                extent = btrfs_item_ptr(leaf, path->slots[0],
                                        struct btrfs_file_extent_item);
+               type = btrfs_file_extent_type(leaf, extent);
 
-               if (btrfs_file_extent_disk_bytenr(leaf, extent) == 0 ||
-                   btrfs_file_extent_type(leaf, extent) ==
-                   BTRFS_FILE_EXTENT_PREALLOC) {
+               /*
+                * Can't access the extent's disk_bytenr field if this is an
+                * inline extent, since at that offset, it's where the extent
+                * data starts.
+                */
+               if (type == BTRFS_FILE_EXTENT_PREALLOC ||
+                   (type == BTRFS_FILE_EXTENT_REG &&
+                    btrfs_file_extent_disk_bytenr(leaf, extent) == 0)) {
                        /*
                         * Explicit hole or prealloc extent, search for delalloc.
                         * A prealloc extent is treated like a hole.
index a749367e5ae2a2b9090a44ec8c0dfc8536f92131..37b86acfcbcf880ded4a2fbed2407a0e6f905982 100644 (file)
@@ -119,6 +119,12 @@ enum {
        /* Indicate that we want to commit the transaction. */
        BTRFS_FS_NEED_TRANS_COMMIT,
 
+       /*
+        * Indicate metadata over-commit is disabled. This is set when active
+        * zone tracking is needed.
+        */
+       BTRFS_FS_NO_OVERCOMMIT,
+
 #if BITS_PER_LONG == 32
        /* Indicate if we have error/warn message printed on 32bit systems */
        BTRFS_FS_32BIT_ERROR,
index d275bf24b250bdfdf78af7d5bdb7f63953660c38..af97413abcf43bd7446d79d1e5a5e2a8e9d57872 100644 (file)
@@ -2765,9 +2765,19 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
 
                        /*
                         * Old roots should be searched when inserting qgroup
-                        * extent record
+                        * extent record.
+                        *
+                        * But for INCONSISTENT (NO_ACCOUNTING) -> rescan case,
+                        * we may have some record inserted during
+                        * NO_ACCOUNTING (thus no old_roots populated), but
+                        * later we start rescan, which clears NO_ACCOUNTING,
+                        * leaving some inserted records without old_roots
+                        * populated.
+                        *
+                        * Those cases are rare and should not cause too much
+                        * time spent during commit_transaction().
                         */
-                       if (WARN_ON(!record->old_roots)) {
+                       if (!record->old_roots) {
                                /* Search commit root to find old_roots */
                                ret = btrfs_find_all_roots(&ctx, false);
                                if (ret < 0)
@@ -3357,6 +3367,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        int err = -ENOMEM;
        int ret = 0;
        bool stopped = false;
+       bool did_leaf_rescans = false;
 
        path = btrfs_alloc_path();
        if (!path)
@@ -3377,6 +3388,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
                }
 
                err = qgroup_rescan_leaf(trans, path);
+               did_leaf_rescans = true;
 
                if (err > 0)
                        btrfs_commit_transaction(trans);
@@ -3397,16 +3409,23 @@ out:
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
        /*
-        * only update status, since the previous part has already updated the
-        * qgroup info.
+        * Only update status, since the previous part has already updated the
+        * qgroup info, and only if we did any actual work. This also prevents
+        * race with a concurrent quota disable, which has already set
+        * fs_info->quota_root to NULL and cleared BTRFS_FS_QUOTA_ENABLED at
+        * btrfs_quota_disable().
         */
-       trans = btrfs_start_transaction(fs_info->quota_root, 1);
-       if (IS_ERR(trans)) {
-               err = PTR_ERR(trans);
+       if (did_leaf_rescans) {
+               trans = btrfs_start_transaction(fs_info->quota_root, 1);
+               if (IS_ERR(trans)) {
+                       err = PTR_ERR(trans);
+                       trans = NULL;
+                       btrfs_err(fs_info,
+                                 "fail to start transaction for status update: %d",
+                                 err);
+               }
+       } else {
                trans = NULL;
-               btrfs_err(fs_info,
-                         "fail to start transaction for status update: %d",
-                         err);
        }
 
        mutex_lock(&fs_info->qgroup_rescan_lock);
index d28ee4e36f3d907e7ce9f8354e56a9f1810be2fc..69c09508afb506ac8121caeae39fb2e7071362c0 100644 (file)
@@ -407,7 +407,8 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
                return 0;
 
        used = btrfs_space_info_used(space_info, true);
-       if (btrfs_is_zoned(fs_info) && (space_info->flags & BTRFS_BLOCK_GROUP_METADATA))
+       if (test_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags) &&
+           (space_info->flags & BTRFS_BLOCK_GROUP_METADATA))
                avail = 0;
        else
                avail = calc_available_free_space(fs_info, space_info, flush);
index fb52aa0600930102e8f519396b2c7298229c5889..d43261545264e3a33a2050669cf7a4a8d90d250a 100644 (file)
@@ -2980,7 +2980,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                ret = 0;
        if (ret) {
                blk_finish_plug(&plug);
-               btrfs_abort_transaction(trans, ret);
                btrfs_set_log_full_commit(trans);
                mutex_unlock(&root->log_mutex);
                goto out;
@@ -3045,15 +3044,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
 
                blk_finish_plug(&plug);
                btrfs_set_log_full_commit(trans);
-
-               if (ret != -ENOSPC) {
-                       btrfs_abort_transaction(trans, ret);
-                       mutex_unlock(&log_root_tree->log_mutex);
-                       goto out;
-               }
+               if (ret != -ENOSPC)
+                       btrfs_err(fs_info,
+                                 "failed to update log for root %llu ret %d",
+                                 root->root_key.objectid, ret);
                btrfs_wait_tree_log_extents(log, mark);
                mutex_unlock(&log_root_tree->log_mutex);
-               ret = BTRFS_LOG_FORCE_COMMIT;
                goto out;
        }
 
@@ -3112,7 +3108,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                goto out_wake_log_root;
        } else if (ret) {
                btrfs_set_log_full_commit(trans);
-               btrfs_abort_transaction(trans, ret);
                mutex_unlock(&log_root_tree->log_mutex);
                goto out_wake_log_root;
        }
@@ -3826,7 +3821,10 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                                              path->slots[0]);
                        if (tmp.type == BTRFS_DIR_INDEX_KEY)
                                last_old_dentry_offset = tmp.offset;
+               } else if (ret < 0) {
+                       err = ret;
                }
+
                goto done;
        }
 
@@ -3846,19 +3844,34 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                 */
                if (tmp.type == BTRFS_DIR_INDEX_KEY)
                        last_old_dentry_offset = tmp.offset;
+       } else if (ret < 0) {
+               err = ret;
+               goto done;
        }
+
        btrfs_release_path(path);
 
        /*
-        * Find the first key from this transaction again.  See the note for
-        * log_new_dir_dentries, if we're logging a directory recursively we
-        * won't be holding its i_mutex, which means we can modify the directory
-        * while we're logging it.  If we remove an entry between our first
-        * search and this search we'll not find the key again and can just
-        * bail.
+        * Find the first key from this transaction again or the one we were at
+        * in the loop below in case we had to reschedule. We may be logging the
+        * directory without holding its VFS lock, which happen when logging new
+        * dentries (through log_new_dir_dentries()) or in some cases when we
+        * need to log the parent directory of an inode. This means a dir index
+        * key might be deleted from the inode's root, and therefore we may not
+        * find it anymore. If we can't find it, just move to the next key. We
+        * can not bail out and ignore, because if we do that we will simply
+        * not log dir index keys that come after the one that was just deleted
+        * and we can end up logging a dir index range that ends at (u64)-1
+        * (@last_offset is initialized to that), resulting in removing dir
+        * entries we should not remove at log replay time.
         */
 search:
        ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0);
+       if (ret > 0)
+               ret = btrfs_next_item(root, path);
+       if (ret < 0)
+               err = ret;
+       /* If ret is 1, there are no more keys in the inode's root. */
        if (ret != 0)
                goto done;
 
@@ -5580,8 +5593,10 @@ static int add_conflicting_inode(struct btrfs_trans_handle *trans,
         * LOG_INODE_EXISTS mode) and slow down other fsyncs or transaction
         * commits.
         */
-       if (ctx->num_conflict_inodes >= MAX_CONFLICT_INODES)
+       if (ctx->num_conflict_inodes >= MAX_CONFLICT_INODES) {
+               btrfs_set_log_full_commit(trans);
                return BTRFS_LOG_FORCE_COMMIT;
+       }
 
        inode = btrfs_iget(root->fs_info->sb, ino, root);
        /*
index aa25fa335d3ed16d9133a4ce4c535830f994248c..bcfef75b97da0de6315e0ab76da7c03e272a5a79 100644 (file)
@@ -768,8 +768,11 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                                        BTRFS_SUPER_FLAG_CHANGING_FSID_V2);
 
        error = lookup_bdev(path, &path_devt);
-       if (error)
+       if (error) {
+               btrfs_err(NULL, "failed to lookup block device for path %s: %d",
+                         path, error);
                return ERR_PTR(error);
+       }
 
        if (fsid_change_in_progress) {
                if (!has_metadata_uuid)
@@ -836,6 +839,9 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                unsigned int nofs_flag;
 
                if (fs_devices->opened) {
+                       btrfs_err(NULL,
+               "device %s belongs to fsid %pU, and the fs is already mounted",
+                                 path, fs_devices->fsid);
                        mutex_unlock(&fs_devices->device_list_mutex);
                        return ERR_PTR(-EBUSY);
                }
@@ -905,6 +911,9 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                         * generation are equal.
                         */
                        mutex_unlock(&fs_devices->device_list_mutex);
+                       btrfs_err(NULL,
+"device %s already registered with a higher generation, found %llu expect %llu",
+                                 path, found_transid, device->generation);
                        return ERR_PTR(-EEXIST);
                }
 
@@ -2005,42 +2014,42 @@ static u64 btrfs_num_devices(struct btrfs_fs_info *fs_info)
        return num_devices;
 }
 
+static void btrfs_scratch_superblock(struct btrfs_fs_info *fs_info,
+                                    struct block_device *bdev, int copy_num)
+{
+       struct btrfs_super_block *disk_super;
+       const size_t len = sizeof(disk_super->magic);
+       const u64 bytenr = btrfs_sb_offset(copy_num);
+       int ret;
+
+       disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr);
+       if (IS_ERR(disk_super))
+               return;
+
+       memset(&disk_super->magic, 0, len);
+       folio_mark_dirty(virt_to_folio(disk_super));
+       btrfs_release_disk_super(disk_super);
+
+       ret = sync_blockdev_range(bdev, bytenr, bytenr + len - 1);
+       if (ret)
+               btrfs_warn(fs_info, "error clearing superblock number %d (%d)",
+                       copy_num, ret);
+}
+
 void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
                               struct block_device *bdev,
                               const char *device_path)
 {
-       struct btrfs_super_block *disk_super;
        int copy_num;
 
        if (!bdev)
                return;
 
        for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX; copy_num++) {
-               struct page *page;
-               int ret;
-
-               disk_super = btrfs_read_dev_one_super(bdev, copy_num, false);
-               if (IS_ERR(disk_super))
-                       continue;
-
-               if (bdev_is_zoned(bdev)) {
+               if (bdev_is_zoned(bdev))
                        btrfs_reset_sb_log_zones(bdev, copy_num);
-                       continue;
-               }
-
-               memset(&disk_super->magic, 0, sizeof(disk_super->magic));
-
-               page = virt_to_page(disk_super);
-               set_page_dirty(page);
-               lock_page(page);
-               /* write_on_page() unlocks the page */
-               ret = write_one_page(page);
-               if (ret)
-                       btrfs_warn(fs_info,
-                               "error clearing superblock number %d (%d)",
-                               copy_num, ret);
-               btrfs_release_disk_super(disk_super);
-
+               else
+                       btrfs_scratch_superblock(fs_info, bdev, copy_num);
        }
 
        /* Notify udev that device has changed */
index a759668477bb2e10eee5f6b60fb03463cd81fcf8..1f503e8e42d483a765b71b9b5910fce0ede0ea6f 100644 (file)
@@ -539,6 +539,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
                }
                atomic_set(&zone_info->active_zones_left,
                           max_active_zones - nactive);
+               /* Overcommit does not work well with active zone tacking. */
+               set_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags);
        }
 
        /* Validate superblock log */
index 8c74871e37c9dc28fb0f14bdd5ce995de27f9458..cac4083e387a50964674282ebbd0664f658c64d4 100644 (file)
@@ -305,7 +305,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
        struct inode *inode = rreq->inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
-       struct ceph_osd_request *req;
+       struct ceph_osd_request *req = NULL;
        struct ceph_vino vino = ceph_vino(inode);
        struct iov_iter iter;
        struct page **pages;
@@ -313,6 +313,11 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
        int err = 0;
        u64 len = subreq->len;
 
+       if (ceph_inode_is_shutdown(inode)) {
+               err = -EIO;
+               goto out;
+       }
+
        if (ceph_has_inline_data(ci) && ceph_netfs_issue_op_inline(subreq))
                return;
 
@@ -563,6 +568,9 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
 
        dout("writepage %p idx %lu\n", page, page->index);
 
+       if (ceph_inode_is_shutdown(inode))
+               return -EIO;
+
        /* verify this is a writeable snap context */
        snapc = page_snap_context(page);
        if (!snapc) {
@@ -1643,7 +1651,7 @@ int ceph_uninline_data(struct file *file)
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_osd_request *req = NULL;
-       struct ceph_cap_flush *prealloc_cf;
+       struct ceph_cap_flush *prealloc_cf = NULL;
        struct folio *folio = NULL;
        u64 inline_version = CEPH_INLINE_NONE;
        struct page *pages[1];
@@ -1657,6 +1665,11 @@ int ceph_uninline_data(struct file *file)
        dout("uninline_data %p %llx.%llx inline_version %llu\n",
             inode, ceph_vinop(inode), inline_version);
 
+       if (ceph_inode_is_shutdown(inode)) {
+               err = -EIO;
+               goto out;
+       }
+
        if (inline_version == CEPH_INLINE_NONE)
                return 0;
 
index f75ad432f375f882abd478bd1fd585568c705721..210e40037881836dda6030d178e4f104109559d3 100644 (file)
@@ -4078,6 +4078,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        void *p, *end;
        struct cap_extra_info extra_info = {};
        bool queue_trunc;
+       bool close_sessions = false;
 
        dout("handle_caps from mds%d\n", session->s_mds);
 
@@ -4215,9 +4216,13 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                realm = NULL;
                if (snaptrace_len) {
                        down_write(&mdsc->snap_rwsem);
-                       ceph_update_snap_trace(mdsc, snaptrace,
-                                              snaptrace + snaptrace_len,
-                                              false, &realm);
+                       if (ceph_update_snap_trace(mdsc, snaptrace,
+                                                  snaptrace + snaptrace_len,
+                                                  false, &realm)) {
+                               up_write(&mdsc->snap_rwsem);
+                               close_sessions = true;
+                               goto done;
+                       }
                        downgrade_write(&mdsc->snap_rwsem);
                } else {
                        down_read(&mdsc->snap_rwsem);
@@ -4277,6 +4282,11 @@ done_unlocked:
        iput(inode);
 out:
        ceph_put_string(extra_info.pool_ns);
+
+       /* Defer closing the sessions after s_mutex lock being released */
+       if (close_sessions)
+               ceph_mdsc_close_sessions(mdsc);
+
        return;
 
 flush_cap_releases:
index 764598e1efd91fd302890220061967135a929801..b5cff85925a109734c12c7eedbf43dffc9480a93 100644 (file)
@@ -2011,6 +2011,9 @@ static int ceph_zero_partial_object(struct inode *inode,
        loff_t zero = 0;
        int op;
 
+       if (ceph_inode_is_shutdown(inode))
+               return -EIO;
+
        if (!length) {
                op = offset ? CEPH_OSD_OP_DELETE : CEPH_OSD_OP_TRUNCATE;
                length = &zero;
index 26a0a8b9975ef3a019b1036f7cb2ff7f47378282..e163f58ff3c5053d01ef696966bc95d7fbd3d53e 100644 (file)
@@ -806,6 +806,9 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
 {
        struct ceph_mds_session *s;
 
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO)
+               return ERR_PTR(-EIO);
+
        if (mds >= mdsc->mdsmap->possible_max_rank)
                return ERR_PTR(-EINVAL);
 
@@ -1478,6 +1481,9 @@ static int __open_session(struct ceph_mds_client *mdsc,
        int mstate;
        int mds = session->s_mds;
 
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO)
+               return -EIO;
+
        /* wait for mds to go active? */
        mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds);
        dout("open_session to mds%d (%s)\n", mds,
@@ -2860,6 +2866,11 @@ static void __do_request(struct ceph_mds_client *mdsc,
                return;
        }
 
+       if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) {
+               dout("do_request metadata corrupted\n");
+               err = -EIO;
+               goto finish;
+       }
        if (req->r_timeout &&
            time_after_eq(jiffies, req->r_started + req->r_timeout)) {
                dout("do_request timed out\n");
@@ -3245,6 +3256,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        u64 tid;
        int err, result;
        int mds = session->s_mds;
+       bool close_sessions = false;
 
        if (msg->front.iov_len < sizeof(*head)) {
                pr_err("mdsc_handle_reply got corrupt (short) reply\n");
@@ -3351,10 +3363,17 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        realm = NULL;
        if (rinfo->snapblob_len) {
                down_write(&mdsc->snap_rwsem);
-               ceph_update_snap_trace(mdsc, rinfo->snapblob,
+               err = ceph_update_snap_trace(mdsc, rinfo->snapblob,
                                rinfo->snapblob + rinfo->snapblob_len,
                                le32_to_cpu(head->op) == CEPH_MDS_OP_RMSNAP,
                                &realm);
+               if (err) {
+                       up_write(&mdsc->snap_rwsem);
+                       close_sessions = true;
+                       if (err == -EIO)
+                               ceph_msg_dump(msg);
+                       goto out_err;
+               }
                downgrade_write(&mdsc->snap_rwsem);
        } else {
                down_read(&mdsc->snap_rwsem);
@@ -3412,6 +3431,10 @@ out_err:
                                     req->r_end_latency, err);
 out:
        ceph_mdsc_put_request(req);
+
+       /* Defer closing the sessions after s_mutex lock being released */
+       if (close_sessions)
+               ceph_mdsc_close_sessions(mdsc);
        return;
 }
 
@@ -5011,7 +5034,7 @@ static bool done_closing_sessions(struct ceph_mds_client *mdsc, int skipped)
 }
 
 /*
- * called after sb is ro.
+ * called after sb is ro or when metadata corrupted.
  */
 void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
 {
@@ -5301,7 +5324,8 @@ static void mds_peer_reset(struct ceph_connection *con)
        struct ceph_mds_client *mdsc = s->s_mdsc;
 
        pr_warn("mds%d closed our session\n", s->s_mds);
-       send_mds_reconnect(mdsc, s);
+       if (READ_ONCE(mdsc->fsc->mount_state) != CEPH_MOUNT_FENCE_IO)
+               send_mds_reconnect(mdsc, s);
 }
 
 static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
index e4151852184e04d092b6ff0b1b4d139d3b2f5dad..87007203f130e14abf51cdf54a5c3d388ba9ab97 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/ceph/ceph_debug.h>
 
+#include <linux/fs.h>
 #include <linux/sort.h>
 #include <linux/slab.h>
 #include <linux/iversion.h>
@@ -766,8 +767,10 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
        struct ceph_snap_realm *realm;
        struct ceph_snap_realm *first_realm = NULL;
        struct ceph_snap_realm *realm_to_rebuild = NULL;
+       struct ceph_client *client = mdsc->fsc->client;
        int rebuild_snapcs;
        int err = -ENOMEM;
+       int ret;
        LIST_HEAD(dirty_realms);
 
        lockdep_assert_held_write(&mdsc->snap_rwsem);
@@ -884,6 +887,27 @@ fail:
        if (first_realm)
                ceph_put_snap_realm(mdsc, first_realm);
        pr_err("%s error %d\n", __func__, err);
+
+       /*
+        * When receiving a corrupted snap trace we don't know what
+        * exactly has happened in MDS side. And we shouldn't continue
+        * writing to OSD, which may corrupt the snapshot contents.
+        *
+        * Just try to blocklist this kclient and then this kclient
+        * must be remounted to continue after the corrupted metadata
+        * fixed in the MDS side.
+        */
+       WRITE_ONCE(mdsc->fsc->mount_state, CEPH_MOUNT_FENCE_IO);
+       ret = ceph_monc_blocklist_add(&client->monc, &client->msgr.inst.addr);
+       if (ret)
+               pr_err("%s failed to blocklist %s: %d\n", __func__,
+                      ceph_pr_addr(&client->msgr.inst.addr), ret);
+
+       WARN(1, "%s: %s%sdo remount to continue%s",
+            __func__, ret ? "" : ceph_pr_addr(&client->msgr.inst.addr),
+            ret ? "" : " was blocklisted, ",
+            err == -EIO ? " after corrupted snaptrace is fixed" : "");
+
        return err;
 }
 
@@ -984,6 +1008,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
        __le64 *split_inos = NULL, *split_realms = NULL;
        int i;
        int locked_rwsem = 0;
+       bool close_sessions = false;
 
        /* decode */
        if (msg->front.iov_len < sizeof(*h))
@@ -1092,8 +1117,12 @@ skip_inode:
         * update using the provided snap trace. if we are deleting a
         * snap, we can avoid queueing cap_snaps.
         */
-       ceph_update_snap_trace(mdsc, p, e,
-                              op == CEPH_SNAP_OP_DESTROY, NULL);
+       if (ceph_update_snap_trace(mdsc, p, e,
+                                  op == CEPH_SNAP_OP_DESTROY,
+                                  NULL)) {
+               close_sessions = true;
+               goto bad;
+       }
 
        if (op == CEPH_SNAP_OP_SPLIT)
                /* we took a reference when we created the realm, above */
@@ -1112,6 +1141,9 @@ bad:
 out:
        if (locked_rwsem)
                up_write(&mdsc->snap_rwsem);
+
+       if (close_sessions)
+               ceph_mdsc_close_sessions(mdsc);
        return;
 }
 
index 0ed3be75bb9ae176ac12555e8f6c86a5690519d4..07c6906cda70d64b336563d413f31bf777c3f537 100644 (file)
@@ -100,6 +100,17 @@ struct ceph_mount_options {
        char *mon_addr;
 };
 
+/* mount state */
+enum {
+       CEPH_MOUNT_MOUNTING,
+       CEPH_MOUNT_MOUNTED,
+       CEPH_MOUNT_UNMOUNTING,
+       CEPH_MOUNT_UNMOUNTED,
+       CEPH_MOUNT_SHUTDOWN,
+       CEPH_MOUNT_RECOVER,
+       CEPH_MOUNT_FENCE_IO,
+};
+
 #define CEPH_ASYNC_CREATE_CONFLICT_BITS 8
 
 struct ceph_fs_client {
index e20f8880363fab1c34a6e69c6a802761c148b89f..ac86bd0ebd637bc2d1440c3f2858489ed27b5364 100644 (file)
@@ -269,7 +269,7 @@ static int dfscache_proc_show(struct seq_file *m, void *v)
                        list_for_each_entry(t, &ce->tlist, list) {
                                seq_printf(m, "  %s%s\n",
                                           t->name,
-                                          ce->tgthint == t ? " (target hint)" : "");
+                                          READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
                        }
                }
        }
@@ -321,7 +321,7 @@ static inline void dump_tgts(const struct cache_entry *ce)
        cifs_dbg(FYI, "target list:\n");
        list_for_each_entry(t, &ce->tlist, list) {
                cifs_dbg(FYI, "  %s%s\n", t->name,
-                        ce->tgthint == t ? " (target hint)" : "");
+                        READ_ONCE(ce->tgthint) == t ? " (target hint)" : "");
        }
 }
 
@@ -427,7 +427,7 @@ static int cache_entry_hash(const void *data, int size, unsigned int *hash)
 /* Return target hint of a DFS cache entry */
 static inline char *get_tgt_name(const struct cache_entry *ce)
 {
-       struct cache_dfs_tgt *t = ce->tgthint;
+       struct cache_dfs_tgt *t = READ_ONCE(ce->tgthint);
 
        return t ? t->name : ERR_PTR(-ENOENT);
 }
@@ -470,6 +470,7 @@ static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
 static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
                         struct cache_entry *ce, const char *tgthint)
 {
+       struct cache_dfs_tgt *target;
        int i;
 
        ce->ttl = max_t(int, refs[0].ttl, CACHE_MIN_TTL);
@@ -496,8 +497,9 @@ static int copy_ref_data(const struct dfs_info3_param *refs, int numrefs,
                ce->numtgts++;
        }
 
-       ce->tgthint = list_first_entry_or_null(&ce->tlist,
-                                              struct cache_dfs_tgt, list);
+       target = list_first_entry_or_null(&ce->tlist, struct cache_dfs_tgt,
+                                         list);
+       WRITE_ONCE(ce->tgthint, target);
 
        return 0;
 }
@@ -558,7 +560,8 @@ static void remove_oldest_entry_locked(void)
 }
 
 /* Add a new DFS cache entry */
-static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
+static struct cache_entry *add_cache_entry_locked(struct dfs_info3_param *refs,
+                                                 int numrefs)
 {
        int rc;
        struct cache_entry *ce;
@@ -573,11 +576,11 @@ static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
 
        rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash);
        if (rc)
-               return rc;
+               return ERR_PTR(rc);
 
        ce = alloc_cache_entry(refs, numrefs);
        if (IS_ERR(ce))
-               return PTR_ERR(ce);
+               return ce;
 
        spin_lock(&cache_ttl_lock);
        if (!cache_ttl) {
@@ -594,7 +597,7 @@ static int add_cache_entry_locked(struct dfs_info3_param *refs, int numrefs)
 
        atomic_inc(&cache_count);
 
-       return 0;
+       return ce;
 }
 
 /* Check if two DFS paths are equal.  @s1 and @s2 are expected to be in @cache_cp's charset */
@@ -641,7 +644,9 @@ static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int h
  *
  * Use whole path components in the match.  Must be called with htable_rw_lock held.
  *
+ * Return cached entry if successful.
  * Return ERR_PTR(-ENOENT) if the entry is not found.
+ * Return error ptr otherwise.
  */
 static struct cache_entry *lookup_cache_entry(const char *path)
 {
@@ -711,14 +716,15 @@ void dfs_cache_destroy(void)
 static int update_cache_entry_locked(struct cache_entry *ce, const struct dfs_info3_param *refs,
                                     int numrefs)
 {
+       struct cache_dfs_tgt *target;
+       char *th = NULL;
        int rc;
-       char *s, *th = NULL;
 
        WARN_ON(!rwsem_is_locked(&htable_rw_lock));
 
-       if (ce->tgthint) {
-               s = ce->tgthint->name;
-               th = kstrdup(s, GFP_ATOMIC);
+       target = READ_ONCE(ce->tgthint);
+       if (target) {
+               th = kstrdup(target->name, GFP_ATOMIC);
                if (!th)
                        return -ENOMEM;
        }
@@ -767,51 +773,75 @@ static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const
  *
  * For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
  * handle them properly.
+ *
+ * On success, return entry with acquired lock for reading, otherwise error ptr.
  */
-static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, const char *path)
+static struct cache_entry *cache_refresh_path(const unsigned int xid,
+                                             struct cifs_ses *ses,
+                                             const char *path,
+                                             bool force_refresh)
 {
-       int rc;
-       struct cache_entry *ce;
        struct dfs_info3_param *refs = NULL;
+       struct cache_entry *ce;
        int numrefs = 0;
-       bool newent = false;
+       int rc;
 
        cifs_dbg(FYI, "%s: search path: %s\n", __func__, path);
 
-       down_write(&htable_rw_lock);
+       down_read(&htable_rw_lock);
 
        ce = lookup_cache_entry(path);
        if (!IS_ERR(ce)) {
-               if (!cache_entry_expired(ce)) {
-                       dump_ce(ce);
-                       up_write(&htable_rw_lock);
-                       return 0;
-               }
-       } else {
-               newent = true;
+               if (!force_refresh && !cache_entry_expired(ce))
+                       return ce;
+       } else if (PTR_ERR(ce) != -ENOENT) {
+               up_read(&htable_rw_lock);
+               return ce;
        }
 
        /*
-        * Either the entry was not found, or it is expired.
+        * Unlock shared access as we don't want to hold any locks while getting
+        * a new referral.  The @ses used for performing the I/O could be
+        * reconnecting and it acquires @htable_rw_lock to look up the dfs cache
+        * in order to failover -- if necessary.
+        */
+       up_read(&htable_rw_lock);
+
+       /*
+        * Either the entry was not found, or it is expired, or it is a forced
+        * refresh.
         * Request a new DFS referral in order to create or update a cache entry.
         */
        rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
-       if (rc)
-               goto out_unlock;
+       if (rc) {
+               ce = ERR_PTR(rc);
+               goto out;
+       }
 
        dump_refs(refs, numrefs);
 
-       if (!newent) {
-               rc = update_cache_entry_locked(ce, refs, numrefs);
-               goto out_unlock;
+       down_write(&htable_rw_lock);
+       /* Re-check as another task might have it added or refreshed already */
+       ce = lookup_cache_entry(path);
+       if (!IS_ERR(ce)) {
+               if (force_refresh || cache_entry_expired(ce)) {
+                       rc = update_cache_entry_locked(ce, refs, numrefs);
+                       if (rc)
+                               ce = ERR_PTR(rc);
+               }
+       } else if (PTR_ERR(ce) == -ENOENT) {
+               ce = add_cache_entry_locked(refs, numrefs);
        }
 
-       rc = add_cache_entry_locked(refs, numrefs);
+       if (IS_ERR(ce)) {
+               up_write(&htable_rw_lock);
+               goto out;
+       }
 
-out_unlock:
-       up_write(&htable_rw_lock);
+       downgrade_write(&htable_rw_lock);
+out:
        free_dfs_info_array(refs, numrefs);
-       return rc;
+       return ce;
 }
 
 /*
@@ -878,7 +908,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
                }
                it->it_path_consumed = t->path_consumed;
 
-               if (ce->tgthint == t)
+               if (READ_ONCE(ce->tgthint) == t)
                        list_add(&it->it_list, head);
                else
                        list_add_tail(&it->it_list, head);
@@ -931,15 +961,8 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl
        if (IS_ERR(npath))
                return PTR_ERR(npath);
 
-       rc = cache_refresh_path(xid, ses, npath);
-       if (rc)
-               goto out_free_path;
-
-       down_read(&htable_rw_lock);
-
-       ce = lookup_cache_entry(npath);
+       ce = cache_refresh_path(xid, ses, npath, false);
        if (IS_ERR(ce)) {
-               up_read(&htable_rw_lock);
                rc = PTR_ERR(ce);
                goto out_free_path;
        }
@@ -1002,72 +1025,6 @@ out_unlock:
        return rc;
 }
 
-/**
- * dfs_cache_update_tgthint - update target hint of a DFS cache entry
- *
- * If it doesn't find the cache entry, then it will get a DFS referral for @path
- * and create a new entry.
- *
- * In case the cache entry exists but expired, it will get a DFS referral
- * for @path and then update the respective cache entry.
- *
- * @xid: syscall id
- * @ses: smb session
- * @cp: codepage
- * @remap: type of character remapping for paths
- * @path: path to lookup in DFS referral cache
- * @it: DFS target iterator
- *
- * Return zero if the target hint was updated successfully, otherwise non-zero.
- */
-int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
-                            const struct nls_table *cp, int remap, const char *path,
-                            const struct dfs_cache_tgt_iterator *it)
-{
-       int rc;
-       const char *npath;
-       struct cache_entry *ce;
-       struct cache_dfs_tgt *t;
-
-       npath = dfs_cache_canonical_path(path, cp, remap);
-       if (IS_ERR(npath))
-               return PTR_ERR(npath);
-
-       cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath);
-
-       rc = cache_refresh_path(xid, ses, npath);
-       if (rc)
-               goto out_free_path;
-
-       down_write(&htable_rw_lock);
-
-       ce = lookup_cache_entry(npath);
-       if (IS_ERR(ce)) {
-               rc = PTR_ERR(ce);
-               goto out_unlock;
-       }
-
-       t = ce->tgthint;
-
-       if (likely(!strcasecmp(it->it_name, t->name)))
-               goto out_unlock;
-
-       list_for_each_entry(t, &ce->tlist, list) {
-               if (!strcasecmp(t->name, it->it_name)) {
-                       ce->tgthint = t;
-                       cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
-                                it->it_name);
-                       break;
-               }
-       }
-
-out_unlock:
-       up_write(&htable_rw_lock);
-out_free_path:
-       kfree(npath);
-       return rc;
-}
-
 /**
  * dfs_cache_noreq_update_tgthint - update target hint of a DFS cache entry
  * without sending any requests to the currently connected server.
@@ -1092,21 +1049,20 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt
 
        cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
 
-       if (!down_write_trylock(&htable_rw_lock))
-               return;
+       down_read(&htable_rw_lock);
 
        ce = lookup_cache_entry(path);
        if (IS_ERR(ce))
                goto out_unlock;
 
-       t = ce->tgthint;
+       t = READ_ONCE(ce->tgthint);
 
        if (unlikely(!strcasecmp(it->it_name, t->name)))
                goto out_unlock;
 
        list_for_each_entry(t, &ce->tlist, list) {
                if (!strcasecmp(t->name, it->it_name)) {
-                       ce->tgthint = t;
+                       WRITE_ONCE(ce->tgthint, t);
                        cifs_dbg(FYI, "%s: new target hint: %s\n", __func__,
                                 it->it_name);
                        break;
@@ -1114,7 +1070,7 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt
        }
 
 out_unlock:
-       up_write(&htable_rw_lock);
+       up_read(&htable_rw_lock);
 }
 
 /**
@@ -1320,35 +1276,37 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, c
  * Mark dfs tcon for reconnecting when the currently connected tcon does not match any of the new
  * target shares in @refs.
  */
-static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cache_tgt_list *tl,
-                                        const struct dfs_info3_param *refs, int numrefs)
+static void mark_for_reconnect_if_needed(struct TCP_Server_Info *server,
+                                        struct dfs_cache_tgt_list *old_tl,
+                                        struct dfs_cache_tgt_list *new_tl)
 {
-       struct dfs_cache_tgt_iterator *it;
-       int i;
-
-       for (it = dfs_cache_get_tgt_iterator(tl); it; it = dfs_cache_get_next_tgt(tl, it)) {
-               for (i = 0; i < numrefs; i++) {
-                       if (target_share_equal(tcon->ses->server, dfs_cache_get_tgt_name(it),
-                                              refs[i].node_name))
+       struct dfs_cache_tgt_iterator *oit, *nit;
+
+       for (oit = dfs_cache_get_tgt_iterator(old_tl); oit;
+            oit = dfs_cache_get_next_tgt(old_tl, oit)) {
+               for (nit = dfs_cache_get_tgt_iterator(new_tl); nit;
+                    nit = dfs_cache_get_next_tgt(new_tl, nit)) {
+                       if (target_share_equal(server,
+                                              dfs_cache_get_tgt_name(oit),
+                                              dfs_cache_get_tgt_name(nit)))
                                return;
                }
        }
 
        cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
-       cifs_signal_cifsd_for_reconnect(tcon->ses->server, true);
+       cifs_signal_cifsd_for_reconnect(server, true);
 }
 
 /* Refresh dfs referral of tcon and mark it for reconnect if needed */
 static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_refresh)
 {
-       struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
+       struct dfs_cache_tgt_list old_tl = DFS_CACHE_TGT_LIST_INIT(old_tl);
+       struct dfs_cache_tgt_list new_tl = DFS_CACHE_TGT_LIST_INIT(new_tl);
        struct cifs_ses *ses = CIFS_DFS_ROOT_SES(tcon->ses);
        struct cifs_tcon *ipc = ses->tcon_ipc;
-       struct dfs_info3_param *refs = NULL;
        bool needs_refresh = false;
        struct cache_entry *ce;
        unsigned int xid;
-       int numrefs = 0;
        int rc = 0;
 
        xid = get_xid();
@@ -1357,9 +1315,8 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
        ce = lookup_cache_entry(path);
        needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce);
        if (!IS_ERR(ce)) {
-               rc = get_targets(ce, &tl);
-               if (rc)
-                       cifs_dbg(FYI, "%s: could not get dfs targets: %d\n", __func__, rc);
+               rc = get_targets(ce, &old_tl);
+               cifs_dbg(FYI, "%s: get_targets: %d\n", __func__, rc);
        }
        up_read(&htable_rw_lock);
 
@@ -1376,26 +1333,18 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
        }
        spin_unlock(&ipc->tc_lock);
 
-       rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
-       if (!rc) {
-               /* Create or update a cache entry with the new referral */
-               dump_refs(refs, numrefs);
-
-               down_write(&htable_rw_lock);
-               ce = lookup_cache_entry(path);
-               if (IS_ERR(ce))
-                       add_cache_entry_locked(refs, numrefs);
-               else if (force_refresh || cache_entry_expired(ce))
-                       update_cache_entry_locked(ce, refs, numrefs);
-               up_write(&htable_rw_lock);
-
-               mark_for_reconnect_if_needed(tcon, &tl, refs, numrefs);
+       ce = cache_refresh_path(xid, ses, path, true);
+       if (!IS_ERR(ce)) {
+               rc = get_targets(ce, &new_tl);
+               up_read(&htable_rw_lock);
+               cifs_dbg(FYI, "%s: get_targets: %d\n", __func__, rc);
+               mark_for_reconnect_if_needed(tcon->ses->server, &old_tl, &new_tl);
        }
 
 out:
        free_xid(xid);
-       dfs_cache_free_tgts(&tl);
-       free_dfs_info_array(refs, numrefs);
+       dfs_cache_free_tgts(&old_tl);
+       dfs_cache_free_tgts(&new_tl);
        return rc;
 }
 
index f7cff0be932747af2d4261272bae880d60ba6f00..be3b5a44cf82711a575e8efe70934f7e07109131 100644 (file)
@@ -35,9 +35,6 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl
                   struct dfs_cache_tgt_list *tgt_list);
 int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
                         struct dfs_cache_tgt_list *tgt_list);
-int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
-                            const struct nls_table *cp, int remap, const char *path,
-                            const struct dfs_cache_tgt_iterator *it);
 void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it);
 int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
                               struct dfs_info3_param *ref);
index 4b71f4a92f76cf42af8de2adb868b8507c576591..2c9ffa921e6f68db581c9ee8d4dc316d5e15ba45 100644 (file)
@@ -4163,12 +4163,15 @@ smb2_readv_callback(struct mid_q_entry *mid)
                                (struct smb2_hdr *)rdata->iov[0].iov_base;
        struct cifs_credits credits = { .value = 0, .instance = 0 };
        struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
-                                .rq_nvec = 1,
-                                .rq_pages = rdata->pages,
-                                .rq_offset = rdata->page_offset,
-                                .rq_npages = rdata->nr_pages,
-                                .rq_pagesz = rdata->pagesz,
-                                .rq_tailsz = rdata->tailsz };
+                                .rq_nvec = 1, };
+
+       if (rdata->got_bytes) {
+               rqst.rq_pages = rdata->pages;
+               rqst.rq_offset = rdata->page_offset;
+               rqst.rq_npages = rdata->nr_pages;
+               rqst.rq_pagesz = rdata->pagesz;
+               rqst.rq_tailsz = rdata->tailsz;
+       }
 
        WARN_ONCE(rdata->server != mid->server,
                  "rdata server %p != mid server %p",
index 90789aaa6567e67c67476a99f6b9c7580be87af1..8c816b25ce7c6a112c6a72832c410b3a7724cf75 100644 (file)
@@ -1405,6 +1405,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
        destroy_workqueue(info->workqueue);
        log_rdma_event(INFO,  "rdma session destroyed\n");
        kfree(info);
+       server->smbd_conn = NULL;
 }
 
 /*
index 481788c24a68ba704bd21804f88333d5c84afe45..626a615dafc2ffa1604f155404165f76288478e1 100644 (file)
@@ -577,26 +577,25 @@ static int erofs_fc_parse_param(struct fs_context *fc,
                }
                ++ctx->devs->extra_devices;
                break;
-       case Opt_fsid:
 #ifdef CONFIG_EROFS_FS_ONDEMAND
+       case Opt_fsid:
                kfree(ctx->fsid);
                ctx->fsid = kstrdup(param->string, GFP_KERNEL);
                if (!ctx->fsid)
                        return -ENOMEM;
-#else
-               errorfc(fc, "fsid option not supported");
-#endif
                break;
        case Opt_domain_id:
-#ifdef CONFIG_EROFS_FS_ONDEMAND
                kfree(ctx->domain_id);
                ctx->domain_id = kstrdup(param->string, GFP_KERNEL);
                if (!ctx->domain_id)
                        return -ENOMEM;
+               break;
 #else
-               errorfc(fc, "domain_id option not supported");
-#endif
+       case Opt_fsid:
+       case Opt_domain_id:
+               errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
                break;
+#endif
        default:
                return -ENOPARAM;
        }
index ccf7c55d477fe5a47c7b3f05475faa490547c28e..5200bb86e2643c3b5432926823f610a46531ef53 100644 (file)
@@ -1032,12 +1032,12 @@ static int z_erofs_decompress_pcluster(struct z_erofs_decompress_backend *be,
 
        if (!be->decompressed_pages)
                be->decompressed_pages =
-                       kvcalloc(be->nr_pages, sizeof(struct page *),
-                                GFP_KERNEL | __GFP_NOFAIL);
+                       kcalloc(be->nr_pages, sizeof(struct page *),
+                               GFP_KERNEL | __GFP_NOFAIL);
        if (!be->compressed_pages)
                be->compressed_pages =
-                       kvcalloc(pclusterpages, sizeof(struct page *),
-                                GFP_KERNEL | __GFP_NOFAIL);
+                       kcalloc(pclusterpages, sizeof(struct page *),
+                               GFP_KERNEL | __GFP_NOFAIL);
 
        z_erofs_parse_out_bvecs(be);
        err2 = z_erofs_parse_in_bvecs(be, &overlapped);
@@ -1085,7 +1085,7 @@ out:
        }
        if (be->compressed_pages < be->onstack_pages ||
            be->compressed_pages >= be->onstack_pages + Z_EROFS_ONSTACK_PAGES)
-               kvfree(be->compressed_pages);
+               kfree(be->compressed_pages);
        z_erofs_fill_other_copies(be, err);
 
        for (i = 0; i < be->nr_pages; ++i) {
@@ -1104,7 +1104,7 @@ out:
        }
 
        if (be->decompressed_pages != be->onstack_pages)
-               kvfree(be->decompressed_pages);
+               kfree(be->decompressed_pages);
 
        pcl->length = 0;
        pcl->partial = true;
index 0150570c33aae1bdb3d3670d592572037bc82218..98fb90b9af715c57112ee21446075218cbe37368 100644 (file)
@@ -793,12 +793,16 @@ static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset,
                iomap->type = IOMAP_HOLE;
                iomap->addr = IOMAP_NULL_ADDR;
                /*
-                * No strict rule how to describe extents for post EOF, yet
-                * we need do like below. Otherwise, iomap itself will get
+                * No strict rule on how to describe extents for post EOF, yet
+                * we need to do like below. Otherwise, iomap itself will get
                 * into an endless loop on post EOF.
+                *
+                * Calculate the effective offset by subtracting extent start
+                * (map.m_la) from the requested offset, and add it to length.
+                * (NB: offset >= map.m_la always)
                 */
                if (iomap->offset >= inode->i_size)
-                       iomap->length = length + map.m_la - offset;
+                       iomap->length = length + offset - map.m_la;
        }
        iomap->flags = 0;
        return 0;
index 7decaaf27e82bd9e090ff1ee99687719105b08a4..a2f04a3808db57677377232224e56fdb10c1dc86 100644 (file)
@@ -81,6 +81,8 @@ ext4_xattr_block_cache_find(struct inode *, struct ext4_xattr_header *,
                            struct mb_cache_entry **);
 static __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
                                    size_t value_count);
+static __le32 ext4_xattr_hash_entry_signed(char *name, size_t name_len, __le32 *value,
+                                   size_t value_count);
 static void ext4_xattr_rehash(struct ext4_xattr_header *);
 
 static const struct xattr_handler * const ext4_xattr_handler_map[] = {
@@ -470,8 +472,22 @@ ext4_xattr_inode_verify_hashes(struct inode *ea_inode,
                tmp_data = cpu_to_le32(hash);
                e_hash = ext4_xattr_hash_entry(entry->e_name, entry->e_name_len,
                                               &tmp_data, 1);
+               /* All good? */
+               if (e_hash == entry->e_hash)
+                       return 0;
+
+               /*
+                * Not good. Maybe the entry hash was calculated
+                * using the buggy signed char version?
+                */
+               e_hash = ext4_xattr_hash_entry_signed(entry->e_name, entry->e_name_len,
+                                                       &tmp_data, 1);
+               /* Still no match - bad */
                if (e_hash != entry->e_hash)
                        return -EFSCORRUPTED;
+
+               /* Let people know about old hash */
+               pr_warn_once("ext4: filesystem with signed xattr name hash");
        }
        return 0;
 }
@@ -3081,7 +3097,29 @@ static __le32 ext4_xattr_hash_entry(char *name, size_t name_len, __le32 *value,
        while (name_len--) {
                hash = (hash << NAME_HASH_SHIFT) ^
                       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-                      *name++;
+                      (unsigned char)*name++;
+       }
+       while (value_count--) {
+               hash = (hash << VALUE_HASH_SHIFT) ^
+                      (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
+                      le32_to_cpu(*value++);
+       }
+       return cpu_to_le32(hash);
+}
+
+/*
+ * ext4_xattr_hash_entry_signed()
+ *
+ * Compute the hash of an extended attribute incorrectly.
+ */
+static __le32 ext4_xattr_hash_entry_signed(char *name, size_t name_len, __le32 *value, size_t value_count)
+{
+       __u32 hash = 0;
+
+       while (name_len--) {
+               hash = (hash << NAME_HASH_SHIFT) ^
+                      (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
+                      (signed char)*name++;
        }
        while (value_count--) {
                hash = (hash << VALUE_HASH_SHIFT) ^
index c05c71d572911ac41a88c397de619c357a641a11..0e2fc08f7de49262fd7833b208105f5896d82ec9 100644 (file)
@@ -8,7 +8,7 @@ config VXFS_FS
          of SCO UnixWare (and possibly others) and optionally available
          for Sunsoft Solaris, HP-UX and many other operating systems. However
          these particular OS implementations of vxfs may differ in on-disk
-         data endianess and/or superblock offset. The vxfs module has been
+         data endianness and/or superblock offset. The vxfs module has been
          tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
          Currently only readonly access is supported and VxFX versions
          2, 3 and 4. Tests were performed with HP-UX VxFS version 3.
index ab8ceddf9efad9d16ed5ecfaa54606fea53412b5..cdf991bdd9def49a9e1217b0c60825def20ed31f 100644 (file)
@@ -141,13 +141,14 @@ static bool fscache_is_acquire_pending(struct fscache_volume *volume)
 static void fscache_wait_on_volume_collision(struct fscache_volume *candidate,
                                             unsigned int collidee_debug_id)
 {
-       wait_var_event_timeout(&candidate->flags,
-                              !fscache_is_acquire_pending(candidate), 20 * HZ);
+       wait_on_bit_timeout(&candidate->flags, FSCACHE_VOLUME_ACQUIRE_PENDING,
+                           TASK_UNINTERRUPTIBLE, 20 * HZ);
        if (fscache_is_acquire_pending(candidate)) {
                pr_notice("Potential volume collision new=%08x old=%08x",
                          candidate->debug_id, collidee_debug_id);
                fscache_stat(&fscache_n_volumes_collision);
-               wait_var_event(&candidate->flags, !fscache_is_acquire_pending(candidate));
+               wait_on_bit(&candidate->flags, FSCACHE_VOLUME_ACQUIRE_PENDING,
+                           TASK_UNINTERRUPTIBLE);
        }
 }
 
@@ -279,8 +280,7 @@ static void fscache_create_volume_work(struct work_struct *work)
        fscache_end_cache_access(volume->cache,
                                 fscache_access_acquire_volume_end);
 
-       clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
-       wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
+       clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
        fscache_put_volume(volume, fscache_volume_put_create_work);
 }
 
@@ -347,8 +347,8 @@ static void fscache_wake_pending_volume(struct fscache_volume *volume,
        hlist_bl_for_each_entry(cursor, p, h, hash_link) {
                if (fscache_volume_same(cursor, volume)) {
                        fscache_see_volume(cursor, fscache_volume_see_hash_wake);
-                       clear_bit(FSCACHE_VOLUME_ACQUIRE_PENDING, &cursor->flags);
-                       wake_up_bit(&cursor->flags, FSCACHE_VOLUME_ACQUIRE_PENDING);
+                       clear_and_wake_up_bit(FSCACHE_VOLUME_ACQUIRE_PENDING,
+                                             &cursor->flags);
                        return;
                }
        }
index a4850aee2639ff819d244f1869d34c22e92f324c..ad670369955f6dc6334adec4c5e4a2990d253ff1 100644 (file)
 #include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
 
-struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
+static struct posix_acl *__fuse_get_acl(struct fuse_conn *fc,
+                                       struct user_namespace *mnt_userns,
+                                       struct inode *inode, int type, bool rcu)
 {
-       struct fuse_conn *fc = get_fuse_conn(inode);
        int size;
        const char *name;
        void *value = NULL;
@@ -25,7 +26,7 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
        if (fuse_is_bad(inode))
                return ERR_PTR(-EIO);
 
-       if (!fc->posix_acl || fc->no_getxattr)
+       if (fc->no_getxattr)
                return NULL;
 
        if (type == ACL_TYPE_ACCESS)
@@ -53,6 +54,46 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
        return acl;
 }
 
+static inline bool fuse_no_acl(const struct fuse_conn *fc,
+                              const struct inode *inode)
+{
+       /*
+        * Refuse interacting with POSIX ACLs for daemons that
+        * don't support FUSE_POSIX_ACL and are not mounted on
+        * the host to retain backwards compatibility.
+        */
+       return !fc->posix_acl && (i_user_ns(inode) != &init_user_ns);
+}
+
+struct posix_acl *fuse_get_acl(struct user_namespace *mnt_userns,
+                              struct dentry *dentry, int type)
+{
+       struct inode *inode = d_inode(dentry);
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       if (fuse_no_acl(fc, inode))
+               return ERR_PTR(-EOPNOTSUPP);
+
+       return __fuse_get_acl(fc, mnt_userns, inode, type, false);
+}
+
+struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       /*
+        * FUSE daemons before FUSE_POSIX_ACL was introduced could get and set
+        * POSIX ACLs without them being used for permission checking by the
+        * vfs. Retain that behavior for backwards compatibility as there are
+        * filesystems that do all permission checking for acls in the daemon
+        * and not in the kernel.
+        */
+       if (!fc->posix_acl)
+               return NULL;
+
+       return __fuse_get_acl(fc, &init_user_ns, inode, type, rcu);
+}
+
 int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
                 struct posix_acl *acl, int type)
 {
@@ -64,7 +105,7 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (fuse_is_bad(inode))
                return -EIO;
 
-       if (!fc->posix_acl || fc->no_setxattr)
+       if (fc->no_setxattr || fuse_no_acl(fc, inode))
                return -EOPNOTSUPP;
 
        if (type == ACL_TYPE_ACCESS)
@@ -99,7 +140,13 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
                        return ret;
                }
 
-               if (!vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) &&
+               /*
+                * Fuse daemons without FUSE_POSIX_ACL never changed the passed
+                * through POSIX ACLs. Such daemons don't expect setgid bits to
+                * be stripped.
+                */
+               if (fc->posix_acl &&
+                   !vfsgid_in_group_p(i_gid_into_vfsgid(&init_user_ns, inode)) &&
                    !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
                        extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID;
 
@@ -108,8 +155,15 @@ int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
        } else {
                ret = fuse_removexattr(inode, name);
        }
-       forget_all_cached_acls(inode);
-       fuse_invalidate_attr(inode);
+
+       if (fc->posix_acl) {
+               /*
+                * Fuse daemons without FUSE_POSIX_ACL never cached POSIX ACLs
+                * and didn't invalidate attributes. Retain that behavior.
+                */
+               forget_all_cached_acls(inode);
+               fuse_invalidate_attr(inode);
+       }
 
        return ret;
 }
index cd1a071b625abcc24930424dfb6b0b6292455263..2725fb54328e58592066af1bea6bf41e0fc8b8c3 100644 (file)
@@ -1942,7 +1942,8 @@ static const struct inode_operations fuse_dir_inode_operations = {
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
        .listxattr      = fuse_listxattr,
-       .get_inode_acl  = fuse_get_acl,
+       .get_inode_acl  = fuse_get_inode_acl,
+       .get_acl        = fuse_get_acl,
        .set_acl        = fuse_set_acl,
        .fileattr_get   = fuse_fileattr_get,
        .fileattr_set   = fuse_fileattr_set,
@@ -1964,7 +1965,8 @@ static const struct inode_operations fuse_common_inode_operations = {
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
        .listxattr      = fuse_listxattr,
-       .get_inode_acl  = fuse_get_acl,
+       .get_inode_acl  = fuse_get_inode_acl,
+       .get_acl        = fuse_get_acl,
        .set_acl        = fuse_set_acl,
        .fileattr_get   = fuse_fileattr_get,
        .fileattr_set   = fuse_fileattr_set,
index c673faefdcb9c253cdbe3851e8de6de2e612787c..46797a171a84f41b4fefbc45ff9ab6e372a634f4 100644 (file)
@@ -1264,11 +1264,11 @@ ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
 ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size);
 int fuse_removexattr(struct inode *inode, const char *name);
 extern const struct xattr_handler *fuse_xattr_handlers[];
-extern const struct xattr_handler *fuse_acl_xattr_handlers[];
-extern const struct xattr_handler *fuse_no_acl_xattr_handlers[];
 
 struct posix_acl;
-struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu);
+struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu);
+struct posix_acl *fuse_get_acl(struct user_namespace *mnt_userns,
+                              struct dentry *dentry, int type);
 int fuse_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
                 struct posix_acl *acl, int type);
 
index 6b3beda16c1ba0a4394d30db7671edd73f2cc034..de9b9ec5ce810a152219e888bd6fbea71443d777 100644 (file)
@@ -311,7 +311,8 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                fuse_dax_dontcache(inode, attr->flags);
 }
 
-static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
+static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr,
+                           struct fuse_conn *fc)
 {
        inode->i_mode = attr->mode & S_IFMT;
        inode->i_size = attr->size;
@@ -333,6 +334,12 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
                                   new_decode_dev(attr->rdev));
        } else
                BUG();
+       /*
+        * Ensure that we don't cache acls for daemons without FUSE_POSIX_ACL
+        * so they see the exact same behavior as before.
+        */
+       if (!fc->posix_acl)
+               inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE;
 }
 
 static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
@@ -372,7 +379,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
                if (!inode)
                        return NULL;
 
-               fuse_init_inode(inode, attr);
+               fuse_init_inode(inode, attr, fc);
                get_fuse_inode(inode)->nodeid = nodeid;
                inode->i_flags |= S_AUTOMOUNT;
                goto done;
@@ -388,7 +395,7 @@ retry:
                if (!fc->writeback_cache || !S_ISREG(attr->mode))
                        inode->i_flags |= S_NOCMTIME;
                inode->i_generation = generation;
-               fuse_init_inode(inode, attr);
+               fuse_init_inode(inode, attr, fc);
                unlock_new_inode(inode);
        } else if (fuse_stale_inode(inode, generation, attr)) {
                /* nodeid was reused, any I/O on the old inode should fail */
@@ -1174,7 +1181,6 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                        if ((flags & FUSE_POSIX_ACL)) {
                                fc->default_permissions = 1;
                                fc->posix_acl = 1;
-                               fm->sb->s_xattr = fuse_acl_xattr_handlers;
                        }
                        if (flags & FUSE_CACHE_SYMLINKS)
                                fc->cache_symlinks = 1;
@@ -1420,13 +1426,6 @@ static void fuse_sb_defaults(struct super_block *sb)
        if (sb->s_user_ns != &init_user_ns)
                sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
        sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
-
-       /*
-        * If we are not in the initial user namespace posix
-        * acls must be translated.
-        */
-       if (sb->s_user_ns != &init_user_ns)
-               sb->s_xattr = fuse_no_acl_xattr_handlers;
 }
 
 static int fuse_fill_super_submount(struct super_block *sb,
index 0d3e7177fce0a70dc99db3e1c02ac8bcf0dfbd8e..9fe571ab569edee49608cd6d099ac3e8161424ab 100644 (file)
@@ -203,27 +203,6 @@ static int fuse_xattr_set(const struct xattr_handler *handler,
        return fuse_setxattr(inode, name, value, size, flags, 0);
 }
 
-static bool no_xattr_list(struct dentry *dentry)
-{
-       return false;
-}
-
-static int no_xattr_get(const struct xattr_handler *handler,
-                       struct dentry *dentry, struct inode *inode,
-                       const char *name, void *value, size_t size)
-{
-       return -EOPNOTSUPP;
-}
-
-static int no_xattr_set(const struct xattr_handler *handler,
-                       struct user_namespace *mnt_userns,
-                       struct dentry *dentry, struct inode *nodee,
-                       const char *name, const void *value,
-                       size_t size, int flags)
-{
-       return -EOPNOTSUPP;
-}
-
 static const struct xattr_handler fuse_xattr_handler = {
        .prefix = "",
        .get    = fuse_xattr_get,
@@ -234,33 +213,3 @@ const struct xattr_handler *fuse_xattr_handlers[] = {
        &fuse_xattr_handler,
        NULL
 };
-
-const struct xattr_handler *fuse_acl_xattr_handlers[] = {
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-       &fuse_xattr_handler,
-       NULL
-};
-
-static const struct xattr_handler fuse_no_acl_access_xattr_handler = {
-       .name  = XATTR_NAME_POSIX_ACL_ACCESS,
-       .flags = ACL_TYPE_ACCESS,
-       .list  = no_xattr_list,
-       .get   = no_xattr_get,
-       .set   = no_xattr_set,
-};
-
-static const struct xattr_handler fuse_no_acl_default_xattr_handler = {
-       .name  = XATTR_NAME_POSIX_ACL_DEFAULT,
-       .flags = ACL_TYPE_ACCESS,
-       .list  = no_xattr_list,
-       .get   = no_xattr_get,
-       .set   = no_xattr_set,
-};
-
-const struct xattr_handler *fuse_no_acl_xattr_handlers[] = {
-       &fuse_no_acl_access_xattr_handler,
-       &fuse_no_acl_default_xattr_handler,
-       &fuse_xattr_handler,
-       NULL
-};
index 723639376ae2a1c125e8c0f8604f8066bf8c4f24..61323deb80bc7b70d91a161898fff3ea6a31e2a1 100644 (file)
@@ -80,6 +80,15 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
        brelse(bd->bd_bh);
 }
 
+static int __gfs2_writepage(struct page *page, struct writeback_control *wbc,
+                      void *data)
+{
+       struct address_space *mapping = data;
+       int ret = mapping->a_ops->writepage(page, wbc);
+       mapping_set_error(mapping, ret);
+       return ret;
+}
+
 /**
  * gfs2_ail1_start_one - Start I/O on a transaction
  * @sdp: The superblock
@@ -131,7 +140,7 @@ __acquires(&sdp->sd_ail_lock)
                if (!mapping)
                        continue;
                spin_unlock(&sdp->sd_ail_lock);
-               ret = filemap_fdatawrite_wbc(mapping, wbc);
+               ret = write_cache_pages(mapping, wbc, __gfs2_writepage, mapping);
                if (need_resched()) {
                        blk_finish_plug(plug);
                        cond_resched();
index fd0a288af299e37d0630f24d4192d530cae3197d..56be077e5d8ac5009f4e80a61a5519d082ed9c8a 100644 (file)
@@ -280,7 +280,7 @@ int ksmbd_conn_handler_loop(void *p)
 {
        struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
        struct ksmbd_transport *t = conn->transport;
-       unsigned int pdu_size;
+       unsigned int pdu_size, max_allowed_pdu_size;
        char hdr_buf[4] = {0,};
        int size;
 
@@ -305,13 +305,26 @@ int ksmbd_conn_handler_loop(void *p)
                pdu_size = get_rfc1002_len(hdr_buf);
                ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
 
+               if (conn->status == KSMBD_SESS_GOOD)
+                       max_allowed_pdu_size =
+                               SMB3_MAX_MSGSIZE + conn->vals->max_write_size;
+               else
+                       max_allowed_pdu_size = SMB3_MAX_MSGSIZE;
+
+               if (pdu_size > max_allowed_pdu_size) {
+                       pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
+                                       pdu_size, max_allowed_pdu_size,
+                                       conn->status);
+                       break;
+               }
+
                /*
                 * Check if pdu size is valid (min : smb header size,
                 * max : 0x00FFFFFF).
                 */
                if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
                    pdu_size > MAX_STREAM_PROT_LEN) {
-                       continue;
+                       break;
                }
 
                /* 4 for rfc1002 length field */
index b6bd8311e6b4d2e84a9ca4d6434353b0343ec3ef..fb8b2d566efb664802f15e399f3c9d10a54c6d2b 100644 (file)
@@ -106,7 +106,8 @@ struct ksmbd_startup_request {
        __u32   sub_auth[3];            /* Subauth value for Security ID */
        __u32   smb2_max_credits;       /* MAX credits */
        __u32   smbd_max_io_size;       /* smbd read write size */
-       __u32   reserved[127];          /* Reserved room */
+       __u32   max_connections;        /* Number of maximum simultaneous connections */
+       __u32   reserved[126];          /* Reserved room */
        __u32   ifc_list_sz;            /* interfaces list size */
        __s8    ____payload[];
 };
index 0ae8d08d85a87da22995083e87ebada3118db7d3..4d9e0b54e3dbfa90a24bed124e2bee638bb572b1 100644 (file)
@@ -242,7 +242,7 @@ int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
                return ret;
 
        if (da->version != 3 && da->version != 4) {
-               pr_err("v%d version is not supported\n", da->version);
+               ksmbd_debug(VFS, "v%d version is not supported\n", da->version);
                return -EINVAL;
        }
 
@@ -251,7 +251,7 @@ int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
                return ret;
 
        if (da->version != version2) {
-               pr_err("ndr version mismatched(version: %d, version2: %d)\n",
+               ksmbd_debug(VFS, "ndr version mismatched(version: %d, version2: %d)\n",
                       da->version, version2);
                return -EINVAL;
        }
@@ -457,7 +457,7 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
        if (ret)
                return ret;
        if (acl->version != 4) {
-               pr_err("v%d version is not supported\n", acl->version);
+               ksmbd_debug(VFS, "v%d version is not supported\n", acl->version);
                return -EINVAL;
        }
 
@@ -465,7 +465,7 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
        if (ret)
                return ret;
        if (acl->version != version2) {
-               pr_err("ndr version mismatched(version: %d, version2: %d)\n",
+               ksmbd_debug(VFS, "ndr version mismatched(version: %d, version2: %d)\n",
                       acl->version, version2);
                return -EINVAL;
        }
index ac9d932f8c8aa170537ebf8147567c16319c6274..db727818176038e23d8e1ed8025606501feabc64 100644 (file)
@@ -41,6 +41,7 @@ struct ksmbd_server_config {
        unsigned int            share_fake_fscaps;
        struct smb_sid          domain_sid;
        unsigned int            auth_mechs;
+       unsigned int            max_connections;
 
        char                    *conf[SERVER_CONF_WORK_GROUP + 1];
 };
index 38fbda52e06fe4128372894e6b1b1e6e34289cad..d681f91947d92746c6a1fba9abec0fb35277421f 100644 (file)
@@ -8663,6 +8663,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
 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);
 
        if (conn->dialect < SMB30_PROT_ID)
@@ -8672,6 +8673,7 @@ bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
                rsp = ksmbd_resp_buf_next(work);
 
        if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE &&
+           sess->user && !user_guest(sess->user) &&
            rsp->Status == STATUS_SUCCESS)
                return true;
        return false;
index aa5dbe54f5a18565971978980a33c4fd0efd1501..0c8a770fe3189b0caeea15c6e04009f5864560c3 100644 (file)
@@ -24,8 +24,9 @@
 
 #define SMB21_DEFAULT_IOSIZE   (1024 * 1024)
 #define SMB3_DEFAULT_TRANS_SIZE        (1024 * 1024)
-#define SMB3_MIN_IOSIZE        (64 * 1024)
-#define SMB3_MAX_IOSIZE        (8 * 1024 * 1024)
+#define SMB3_MIN_IOSIZE                (64 * 1024)
+#define SMB3_MAX_IOSIZE                (8 * 1024 * 1024)
+#define SMB3_MAX_MSGSIZE       (4 * 4096)
 
 /*
  *     Definitions for SMB2 Protocol Data Units (network frames)
index c9aca21637d5b688470338046cebd542ea5c91a2..40c721f9227e4a4e262be0bc3bd073c4505b3fc0 100644 (file)
@@ -308,6 +308,9 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
        if (req->smbd_max_io_size)
                init_smbd_max_io_size(req->smbd_max_io_size);
 
+       if (req->max_connections)
+               server_conf.max_connections = req->max_connections;
+
        ret = ksmbd_set_netbios_name(req->netbios_name);
        ret |= ksmbd_set_server_string(req->server_string);
        ret |= ksmbd_set_work_group(req->work_group);
index 4c6bd0b699791321eda9ab9b82d98be3a5aa7ada..603893fd87f57d632107258052df2b79407db3ae 100644 (file)
@@ -15,6 +15,8 @@
 #define IFACE_STATE_DOWN               BIT(0)
 #define IFACE_STATE_CONFIGURED         BIT(1)
 
+static atomic_t active_num_conn;
+
 struct interface {
        struct task_struct      *ksmbd_kthread;
        struct socket           *ksmbd_socket;
@@ -185,8 +187,10 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
        struct tcp_transport *t;
 
        t = alloc_transport(client_sk);
-       if (!t)
+       if (!t) {
+               sock_release(client_sk);
                return -ENOMEM;
+       }
 
        csin = KSMBD_TCP_PEER_SOCKADDR(KSMBD_TRANS(t)->conn);
        if (kernel_getpeername(client_sk, csin) < 0) {
@@ -239,6 +243,15 @@ static int ksmbd_kthread_fn(void *p)
                        continue;
                }
 
+               if (server_conf.max_connections &&
+                   atomic_inc_return(&active_num_conn) >= server_conf.max_connections) {
+                       pr_info_ratelimited("Limit the maximum number of connections(%u)\n",
+                                           atomic_read(&active_num_conn));
+                       atomic_dec(&active_num_conn);
+                       sock_release(client_sk);
+                       continue;
+               }
+
                ksmbd_debug(CONN, "connect success: accepted new connection\n");
                client_sk->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT;
                client_sk->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT;
@@ -368,6 +381,8 @@ static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
 static void ksmbd_tcp_disconnect(struct ksmbd_transport *t)
 {
        free_transport(TCP_TRANS(t));
+       if (server_conf.max_connections)
+               atomic_dec(&active_num_conn);
 }
 
 static void tcp_destroy_socket(struct socket *ksmbd_socket)
index 0ef0703490144b4017583b26d24547c66f3d9480..c0950edb26b0d31ca9c5b9bcceaf9166b9cb2c2f 100644 (file)
@@ -661,6 +661,39 @@ static struct shrinker     nfsd_file_shrinker = {
        .seeks = 1,
 };
 
+/**
+ * nfsd_file_cond_queue - conditionally unhash and queue a nfsd_file
+ * @nf: nfsd_file to attempt to queue
+ * @dispose: private list to queue successfully-put objects
+ *
+ * Unhash an nfsd_file, try to get a reference to it, and then put that
+ * reference. If it's the last reference, queue it to the dispose list.
+ */
+static void
+nfsd_file_cond_queue(struct nfsd_file *nf, struct list_head *dispose)
+       __must_hold(RCU)
+{
+       int decrement = 1;
+
+       /* If we raced with someone else unhashing, ignore it */
+       if (!nfsd_file_unhash(nf))
+               return;
+
+       /* If we can't get a reference, ignore it */
+       if (!nfsd_file_get(nf))
+               return;
+
+       /* Extra decrement if we remove from the LRU */
+       if (nfsd_file_lru_remove(nf))
+               ++decrement;
+
+       /* If refcount goes to 0, then put on the dispose list */
+       if (refcount_sub_and_test(decrement, &nf->nf_ref)) {
+               list_add(&nf->nf_lru, dispose);
+               trace_nfsd_file_closing(nf);
+       }
+}
+
 /**
  * nfsd_file_queue_for_close: try to close out any open nfsd_files for an inode
  * @inode:   inode on which to close out nfsd_files
@@ -688,30 +721,11 @@ nfsd_file_queue_for_close(struct inode *inode, struct list_head *dispose)
 
        rcu_read_lock();
        do {
-               int decrement = 1;
-
                nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
                                       nfsd_file_rhash_params);
                if (!nf)
                        break;
-
-               /* If we raced with someone else unhashing, ignore it */
-               if (!nfsd_file_unhash(nf))
-                       continue;
-
-               /* If we can't get a reference, ignore it */
-               if (!nfsd_file_get(nf))
-                       continue;
-
-               /* Extra decrement if we remove from the LRU */
-               if (nfsd_file_lru_remove(nf))
-                       ++decrement;
-
-               /* If refcount goes to 0, then put on the dispose list */
-               if (refcount_sub_and_test(decrement, &nf->nf_ref)) {
-                       list_add(&nf->nf_lru, dispose);
-                       trace_nfsd_file_closing(nf);
-               }
+               nfsd_file_cond_queue(nf, dispose);
        } while (1);
        rcu_read_unlock();
 }
@@ -928,11 +942,8 @@ __nfsd_file_cache_purge(struct net *net)
 
                nf = rhashtable_walk_next(&iter);
                while (!IS_ERR_OR_NULL(nf)) {
-                       if (!net || nf->nf_net == net) {
-                               nfsd_file_unhash(nf);
-                               nfsd_file_lru_remove(nf);
-                               list_add(&nf->nf_lru, &dispose);
-                       }
+                       if (!net || nf->nf_net == net)
+                               nfsd_file_cond_queue(nf, &dispose);
                        nf = rhashtable_walk_next(&iter);
                }
 
index 8c854ba3285bbcddfe62010dc6b93018fdc3927c..51a4b7885cae2a2a5f5cab4932ebcd6306d10348 100644 (file)
@@ -195,7 +195,7 @@ struct nfsd_net {
 
        atomic_t                nfsd_courtesy_clients;
        struct shrinker         nfsd_client_shrinker;
-       struct delayed_work     nfsd_shrinker_work;
+       struct work_struct      nfsd_shrinker_work;
 };
 
 /* Simple check to find out if a given net was properly initialized */
index 9b81d012666e2c408495c6505553991a15a4a8e7..f189ba7995f5ae4ec7424e1660822f8e41191dc0 100644 (file)
@@ -1318,6 +1318,7 @@ try_again:
                        /* allow 20secs for mount/unmount for now - revisit */
                        if (signal_pending(current) ||
                                        (schedule_timeout(20*HZ) == 0)) {
+                               finish_wait(&nn->nfsd_ssc_waitq, &wait);
                                kfree(work);
                                return nfserr_eagain;
                        }
index 4809ae0f013850928898ee32a5cac845db8d7156..4ef529379065a10d6957680f1ab50e9392215cc5 100644 (file)
@@ -4411,7 +4411,7 @@ nfsd4_state_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)
        if (!count)
                count = atomic_long_read(&num_delegations);
        if (count)
-               mod_delayed_work(laundry_wq, &nn->nfsd_shrinker_work, 0);
+               queue_work(laundry_wq, &nn->nfsd_shrinker_work);
        return (unsigned long)count;
 }
 
@@ -4421,7 +4421,7 @@ nfsd4_state_shrinker_scan(struct shrinker *shrink, struct shrink_control *sc)
        return SHRINK_STOP;
 }
 
-int
+void
 nfsd4_init_leases_net(struct nfsd_net *nn)
 {
        struct sysinfo si;
@@ -4443,16 +4443,6 @@ nfsd4_init_leases_net(struct nfsd_net *nn)
        nn->nfs4_max_clients = max_t(int, max_clients, NFS4_CLIENTS_PER_GB);
 
        atomic_set(&nn->nfsd_courtesy_clients, 0);
-       nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
-       nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
-       nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
-       return register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client");
-}
-
-void
-nfsd4_leases_net_shutdown(struct nfsd_net *nn)
-{
-       unregister_shrinker(&nn->nfsd_client_shrinker);
 }
 
 static void init_nfs4_replay(struct nfs4_replay *rp)
@@ -6235,8 +6225,7 @@ deleg_reaper(struct nfsd_net *nn)
 static void
 nfsd4_state_shrinker_worker(struct work_struct *work)
 {
-       struct delayed_work *dwork = to_delayed_work(work);
-       struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
+       struct nfsd_net *nn = container_of(work, struct nfsd_net,
                                nfsd_shrinker_work);
 
        courtesy_client_reaper(nn);
@@ -8066,11 +8055,20 @@ static int nfs4_state_create_net(struct net *net)
        INIT_LIST_HEAD(&nn->blocked_locks_lru);
 
        INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
-       INIT_DELAYED_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
+       INIT_WORK(&nn->nfsd_shrinker_work, nfsd4_state_shrinker_worker);
        get_net(net);
 
+       nn->nfsd_client_shrinker.scan_objects = nfsd4_state_shrinker_scan;
+       nn->nfsd_client_shrinker.count_objects = nfsd4_state_shrinker_count;
+       nn->nfsd_client_shrinker.seeks = DEFAULT_SEEKS;
+
+       if (register_shrinker(&nn->nfsd_client_shrinker, "nfsd-client"))
+               goto err_shrinker;
        return 0;
 
+err_shrinker:
+       put_net(net);
+       kfree(nn->sessionid_hashtbl);
 err_sessionid:
        kfree(nn->unconf_id_hashtbl);
 err_unconf_id:
@@ -8163,6 +8161,8 @@ nfs4_state_shutdown_net(struct net *net)
        struct list_head *pos, *next, reaplist;
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
+       unregister_shrinker(&nn->nfsd_client_shrinker);
+       cancel_work(&nn->nfsd_shrinker_work);
        cancel_delayed_work_sync(&nn->laundromat_work);
        locks_end_grace(&nn->nfsd4_manager);
 
index d1e581a60480c04d28d61a6fc5ca60ccfb2d8f70..c2577ee7ffb2208e3f32282de7bd912ac47ca0d7 100644 (file)
@@ -1457,9 +1457,7 @@ static __net_init int nfsd_init_net(struct net *net)
                goto out_idmap_error;
        nn->nfsd_versions = NULL;
        nn->nfsd4_minorversions = NULL;
-       retval = nfsd4_init_leases_net(nn);
-       if (retval)
-               goto out_drc_error;
+       nfsd4_init_leases_net(nn);
        retval = nfsd_reply_cache_init(nn);
        if (retval)
                goto out_cache_error;
@@ -1469,8 +1467,6 @@ static __net_init int nfsd_init_net(struct net *net)
        return 0;
 
 out_cache_error:
-       nfsd4_leases_net_shutdown(nn);
-out_drc_error:
        nfsd_idmap_shutdown(net);
 out_idmap_error:
        nfsd_export_shutdown(net);
@@ -1486,7 +1482,6 @@ static __net_exit void nfsd_exit_net(struct net *net)
        nfsd_idmap_shutdown(net);
        nfsd_export_shutdown(net);
        nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
-       nfsd4_leases_net_shutdown(nn);
 }
 
 static struct pernet_operations nfsd_net_ops = {
index 93b42ef9ed91b63a1636b5d2d953169827bb6746..fa0144a742678fd46119dc6c871dba69cd383257 100644 (file)
@@ -504,8 +504,7 @@ extern void unregister_cld_notifier(void);
 extern void nfsd4_ssc_init_umount_work(struct nfsd_net *nn);
 #endif
 
-extern int nfsd4_init_leases_net(struct nfsd_net *nn);
-extern void nfsd4_leases_net_shutdown(struct nfsd_net *nn);
+extern void nfsd4_init_leases_net(struct nfsd_net *nn);
 
 #else /* CONFIG_NFSD_V4 */
 static inline int nfsd4_is_junction(struct dentry *dentry)
@@ -513,8 +512,7 @@ static inline int nfsd4_is_junction(struct dentry *dentry)
        return 0;
 }
 
-static inline int nfsd4_init_leases_net(struct nfsd_net *nn) { return 0; };
-static inline void nfsd4_leases_net_shutdown(struct nfsd_net *nn) {};
+static inline void nfsd4_init_leases_net(struct nfsd_net *nn) { };
 
 #define register_cld_notifier() 0
 #define unregister_cld_notifier() do { } while(0)
index b9d15c3df3cc193ba10cf88761d45027ee6de346..40ce92a332fe7a6553eeb78acf0414a32defac78 100644 (file)
@@ -480,9 +480,18 @@ static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
        ret = nilfs_btnode_submit_block(btnc, ptr, 0, REQ_OP_READ, &bh,
                                        &submit_ptr);
        if (ret) {
-               if (ret != -EEXIST)
-                       return ret;
-               goto out_check;
+               if (likely(ret == -EEXIST))
+                       goto out_check;
+               if (ret == -ENOENT) {
+                       /*
+                        * Block address translation failed due to invalid
+                        * value of 'ptr'.  In this case, return internal code
+                        * -EINVAL (broken bmap) to notify bmap layer of fatal
+                        * metadata corruption.
+                        */
+                       ret = -EINVAL;
+               }
+               return ret;
        }
 
        if (ra) {
index 6e4e65ee050d6dacdd943780196d4b7f05d5a251..c14e90764e356565cf25561ea92793526e760c47 100644 (file)
@@ -792,7 +792,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
        if (!c->metacopy && c->stat.size) {
                err = ovl_copy_up_file(ofs, c->dentry, tmpfile, c->stat.size);
                if (err)
-                       return err;
+                       goto out_fput;
        }
 
        err = ovl_copy_up_metadata(c, temp);
@@ -1011,6 +1011,10 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
        if (err)
                return err;
 
+       if (!kuid_has_mapping(current_user_ns(), ctx.stat.uid) ||
+           !kgid_has_mapping(current_user_ns(), ctx.stat.gid))
+               return -EOVERFLOW;
+
        ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
 
        if (parent) {
index e35a0398db63f9a805caf89bbe45ecf72ce65919..af1c49ae11b1656168d0c75d696d5d568911a250 100644 (file)
@@ -745,9 +745,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
                        page = pfn_swap_entry_to_page(swpent);
        }
        if (page) {
-               int mapcount = page_mapcount(page);
-
-               if (mapcount >= 2)
+               if (page_mapcount(page) >= 2 || hugetlb_pmd_shared(pte))
                        mss->shared_hugetlb += huge_page_size(hstate_vma(vma));
                else
                        mss->private_hugetlb += huge_page_size(hstate_vma(vma));
index b3fdc8212c5f52d940391ec0345d6f1ab805efcf..95f8e890176899ea5fdde45c3d161007d3acd47f 100644 (file)
@@ -183,7 +183,7 @@ static inline int squashfs_block_size(__le32 raw)
 #define SQUASHFS_ID_BLOCK_BYTES(A)     (SQUASHFS_ID_BLOCKS(A) *\
                                        sizeof(u64))
 /* xattr id lookup table defines */
-#define SQUASHFS_XATTR_BYTES(A)                ((A) * sizeof(struct squashfs_xattr_id))
+#define SQUASHFS_XATTR_BYTES(A)                (((u64) (A)) * sizeof(struct squashfs_xattr_id))
 
 #define SQUASHFS_XATTR_BLOCK(A)                (SQUASHFS_XATTR_BYTES(A) / \
                                        SQUASHFS_METADATA_SIZE)
index 659082e9e51d6f93175800faba8c765d6b1fae9e..72f6f4b378636e8e235c10e3bf2f31a9b5507174 100644 (file)
@@ -63,7 +63,7 @@ struct squashfs_sb_info {
        long long                               bytes_used;
        unsigned int                            inodes;
        unsigned int                            fragments;
-       int                                     xattr_ids;
+       unsigned int                            xattr_ids;
        unsigned int                            ids;
        bool                                    panic_on_errors;
        const struct squashfs_decompressor_thread_ops *thread_ops;
index d8a270d3ac4cb267dbbbc4097c2b1e7034e66072..f1a463d8bfa020d60605d2d4530e746dd15d300d 100644 (file)
 
 #ifdef CONFIG_SQUASHFS_XATTR
 extern __le64 *squashfs_read_xattr_id_table(struct super_block *, u64,
-               u64 *, int *);
+               u64 *, unsigned int *);
 extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *,
                unsigned int *, unsigned long long *);
 #else
 static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb,
-               u64 start, u64 *xattr_table_start, int *xattr_ids)
+               u64 start, u64 *xattr_table_start, unsigned int *xattr_ids)
 {
        struct squashfs_xattr_id_table *id_table;
 
index 087cab8c78f4e86ea7c97e3d3b4266896159f29d..b88d19e9581e932a799a09c2ef7780c265e9892f 100644 (file)
@@ -56,7 +56,7 @@ int squashfs_xattr_lookup(struct super_block *sb, unsigned int index,
  * Read uncompressed xattr id lookup table indexes from disk into memory
  */
 __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start,
-               u64 *xattr_table_start, int *xattr_ids)
+               u64 *xattr_table_start, unsigned int *xattr_ids)
 {
        struct squashfs_sb_info *msblk = sb->s_fs_info;
        unsigned int len, indexes;
@@ -76,7 +76,7 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start,
        /* Sanity check values */
 
        /* there is always at least one xattr id */
-       if (*xattr_ids == 0)
+       if (*xattr_ids <= 0)
                return ERR_PTR(-EINVAL);
 
        len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids);
index 98ac37e34e3d4bd4ac229e01a42b2e2a8a27685d..cc694846617a52bc874b86a85377b7a97811cc49 100644 (file)
@@ -108,6 +108,21 @@ static bool userfaultfd_is_initialized(struct userfaultfd_ctx *ctx)
        return ctx->features & UFFD_FEATURE_INITIALIZED;
 }
 
+static void userfaultfd_set_vm_flags(struct vm_area_struct *vma,
+                                    vm_flags_t flags)
+{
+       const bool uffd_wp_changed = (vma->vm_flags ^ flags) & VM_UFFD_WP;
+
+       vma->vm_flags = flags;
+       /*
+        * For shared mappings, we want to enable writenotify while
+        * userfaultfd-wp is enabled (see vma_wants_writenotify()). We'll simply
+        * recalculate vma->vm_page_prot whenever userfaultfd-wp changes.
+        */
+       if ((vma->vm_flags & VM_SHARED) && uffd_wp_changed)
+               vma_set_page_prot(vma);
+}
+
 static int userfaultfd_wake_function(wait_queue_entry_t *wq, unsigned mode,
                                     int wake_flags, void *key)
 {
@@ -618,7 +633,8 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
                for_each_vma(vmi, vma) {
                        if (vma->vm_userfaultfd_ctx.ctx == release_new_ctx) {
                                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
-                               vma->vm_flags &= ~__VM_UFFD_FLAGS;
+                               userfaultfd_set_vm_flags(vma,
+                                                        vma->vm_flags & ~__VM_UFFD_FLAGS);
                        }
                }
                mmap_write_unlock(mm);
@@ -652,7 +668,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
        octx = vma->vm_userfaultfd_ctx.ctx;
        if (!octx || !(octx->features & UFFD_FEATURE_EVENT_FORK)) {
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
-               vma->vm_flags &= ~__VM_UFFD_FLAGS;
+               userfaultfd_set_vm_flags(vma, vma->vm_flags & ~__VM_UFFD_FLAGS);
                return 0;
        }
 
@@ -733,7 +749,7 @@ void mremap_userfaultfd_prep(struct vm_area_struct *vma,
        } else {
                /* Drop uffd context if remap feature not enabled */
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
-               vma->vm_flags &= ~__VM_UFFD_FLAGS;
+               userfaultfd_set_vm_flags(vma, vma->vm_flags & ~__VM_UFFD_FLAGS);
        }
 }
 
@@ -895,7 +911,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
                        prev = vma;
                }
 
-               vma->vm_flags = new_flags;
+               userfaultfd_set_vm_flags(vma, new_flags);
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
        }
        mmap_write_unlock(mm);
@@ -1463,7 +1479,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                 * the next vma was merged into the current one and
                 * the current one has not been updated yet.
                 */
-               vma->vm_flags = new_flags;
+               userfaultfd_set_vm_flags(vma, new_flags);
                vma->vm_userfaultfd_ctx.ctx = ctx;
 
                if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma))
@@ -1651,7 +1667,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                 * the next vma was merged into the current one and
                 * the current one has not been updated yet.
                 */
-               vma->vm_flags = new_flags;
+               userfaultfd_set_vm_flags(vma, new_flags);
                vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
 
        skip:
index 2c53fbb8d918e5ca63ab3a620455b1f173883251..a9c5c3f720adf86f2afd73a73aec327c2f83399b 100644 (file)
@@ -442,6 +442,10 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
                        data_size = zonefs_check_zone_condition(inode, zone,
                                                                false, false);
                }
+       } else if (sbi->s_mount_opts & ZONEFS_MNTOPT_ERRORS_RO &&
+                  data_size > isize) {
+               /* Do not expose garbage data */
+               data_size = isize;
        }
 
        /*
@@ -805,6 +809,24 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
 
        ret = submit_bio_wait(bio);
 
+       /*
+        * If the file zone was written underneath the file system, the zone
+        * write pointer may not be where we expect it to be, but the zone
+        * append write can still succeed. So check manually that we wrote where
+        * we intended to, that is, at zi->i_wpoffset.
+        */
+       if (!ret) {
+               sector_t wpsector =
+                       zi->i_zsector + (zi->i_wpoffset >> SECTOR_SHIFT);
+
+               if (bio->bi_iter.bi_sector != wpsector) {
+                       zonefs_warn(inode->i_sb,
+                               "Corrupted write pointer %llu for zone at %llu\n",
+                               wpsector, zi->i_zsector);
+                       ret = -EIO;
+               }
+       }
+
        zonefs_file_write_dio_end_io(iocb, size, ret, 0);
        trace_zonefs_file_dio_append(inode, size, ret);
 
index 9778408f8db40584f1bb78b6f912cb600986cd77..8e364cbdd14ab5002974101c3dcb13316256e49d 100644 (file)
@@ -526,7 +526,7 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
                                           struct acpi_buffer *ret_path_ptr))
 ACPI_EXTERNAL_RETURN_STATUS(acpi_status
                             acpi_get_handle(acpi_handle parent,
-                                            acpi_string pathname,
+                                            const char *pathname,
                                             acpi_handle *ret_handle))
 ACPI_EXTERNAL_RETURN_STATUS(acpi_status
                             acpi_attach_data(acpi_handle object,
index 4175dce3967c016783c483be89d3ec92a6711248..cdedccccc4f3194916b64752cb80f15cdb481642 100644 (file)
@@ -50,6 +50,8 @@
 #define ACPI_SIG_S3PT           "S3PT" /* S3 Performance (sub)Table */
 #define ACPI_SIG_PCCS           "PCC"  /* PCC Shared Memory Region */
 
+#define ACPI_SIG_NBFT          "NBFT"  /* NVMe Boot Firmware Table */
+
 /* Reserved table signatures */
 
 #define ACPI_SIG_MATR           "MATR" /* Memory Address Translation Table */
@@ -344,7 +346,7 @@ enum acpi_cdat_type {
 
 /* Subtable 0: Device Scoped Memory Affinity Structure (DSMAS) */
 
-struct acpi_cadt_dsmas {
+struct acpi_cdat_dsmas {
        u8 dsmad_handle;
        u8 flags;
        u16 reserved;
index b111dc7ada78d72dddec80cd7143a0744f277773..095370ef029ded8afb1cea7181a479c6c0e1f0bb 100644 (file)
@@ -208,6 +208,18 @@ struct drm_fb_helper {
         * the smem_start field should always be cleared to zero.
         */
        bool hint_leak_smem_start;
+
+#ifdef CONFIG_FB_DEFERRED_IO
+       /**
+        * @fbdefio:
+        *
+        * Temporary storage for the driver's FB deferred I/O handler. If the
+        * driver uses the DRM fbdev emulation layer, this is set by the core
+        * to a generic deferred I/O handler if a driver is preferring to use
+        * a shadow buffer.
+        */
+       struct fb_deferred_io fbdefio;
+#endif
 };
 
 static inline struct drm_fb_helper *
index 4f8c35206f7cd7802539e1bb6490e5516e6103f4..6c2a2f21dbf00dfe9b2522b7973281ac06df4384 100644 (file)
@@ -74,6 +74,7 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
                           struct drm_vma_offset_node *node);
 
 int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag);
+int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag);
 void drm_vma_node_revoke(struct drm_vma_offset_node *node,
                         struct drm_file *tag);
 bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
index 87ea90576b50749ddac8d7d17e6a2848b6bbad9e..08d3559dd7038c720cdf839936b049922144925a 100644 (file)
@@ -303,7 +303,6 @@ static inline int kunit_run_all_tests(void)
  */
 #define kunit_test_init_section_suites(__suites...)                    \
        __kunit_test_suites(CONCATENATE(__UNIQUE_ID(array), _probe),    \
-                           CONCATENATE(__UNIQUE_ID(suites), _probe),   \
                            ##__suites)
 
 #define kunit_test_init_section_suite(suite)   \
@@ -683,8 +682,9 @@ do {                                                                               \
                .right_text = #right,                                          \
        };                                                                     \
                                                                               \
-       if (likely(memcmp(__left, __right, __size) op 0))                      \
-               break;                                                         \
+       if (likely(__left && __right))                                         \
+               if (likely(memcmp(__left, __right, __size) op 0))              \
+                       break;                                                 \
                                                                               \
        _KUNIT_FAILED(test,                                                    \
                      assert_type,                                             \
index 9270cd87da3fc806319bd1df08246b4879497582..6470f67e63c4850a495b956391c8fe2dcde1f3b6 100644 (file)
@@ -263,7 +263,7 @@ struct vgic_dist {
        struct vgic_io_device   dist_iodev;
 
        bool                    has_its;
-       bool                    save_its_tables_in_progress;
+       bool                    table_write_in_progress;
 
        /*
         * Contains the attributes and gpa of the LPI configuration table.
index ddb10aa67b14360ee0f6f63b5f733b1176557588..1f68b49bcd6880b81b583afb0786e1a72824f1f0 100644 (file)
 #define LINUX_APPLE_GMUX_H
 
 #include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/pnp.h>
 
 #define GMUX_ACPI_HID "APP000B"
 
+/*
+ * gmux port offsets. Many of these are not yet used, but may be in the
+ * future, and it's useful to have them documented here anyhow.
+ */
+#define GMUX_PORT_VERSION_MAJOR                0x04
+#define GMUX_PORT_VERSION_MINOR                0x05
+#define GMUX_PORT_VERSION_RELEASE      0x06
+#define GMUX_PORT_SWITCH_DISPLAY       0x10
+#define GMUX_PORT_SWITCH_GET_DISPLAY   0x11
+#define GMUX_PORT_INTERRUPT_ENABLE     0x14
+#define GMUX_PORT_INTERRUPT_STATUS     0x16
+#define GMUX_PORT_SWITCH_DDC           0x28
+#define GMUX_PORT_SWITCH_EXTERNAL      0x40
+#define GMUX_PORT_SWITCH_GET_EXTERNAL  0x41
+#define GMUX_PORT_DISCRETE_POWER       0x50
+#define GMUX_PORT_MAX_BRIGHTNESS       0x70
+#define GMUX_PORT_BRIGHTNESS           0x74
+#define GMUX_PORT_VALUE                        0xc2
+#define GMUX_PORT_READ                 0xd0
+#define GMUX_PORT_WRITE                        0xd4
+
+#define GMUX_MIN_IO_LEN                        (GMUX_PORT_BRIGHTNESS + 4)
+
 #if IS_ENABLED(CONFIG_APPLE_GMUX)
+static inline bool apple_gmux_is_indexed(unsigned long iostart)
+{
+       u16 val;
+
+       outb(0xaa, iostart + 0xcc);
+       outb(0x55, iostart + 0xcd);
+       outb(0x00, iostart + 0xce);
+
+       val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8);
+       if (val == 0x55aa)
+               return true;
+
+       return false;
+}
 
 /**
- * apple_gmux_present() - detect if gmux is built into the machine
+ * apple_gmux_detect() - detect if gmux is built into the machine
+ *
+ * @pnp_dev:     Device to probe or NULL to use the first matching device
+ * @indexed_ret: Returns (by reference) if the gmux is indexed or not
+ *
+ * Detect if a supported gmux device is present by actually probing it.
+ * This avoids the false positives returned on some models by
+ * apple_gmux_present().
+ *
+ * Return: %true if a supported gmux ACPI device is detected and the kernel
+ * was configured with CONFIG_APPLE_GMUX, %false otherwise.
+ */
+static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
+{
+       u8 ver_major, ver_minor, ver_release;
+       struct device *dev = NULL;
+       struct acpi_device *adev;
+       struct resource *res;
+       bool indexed = false;
+       bool ret = false;
+
+       if (!pnp_dev) {
+               adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
+               if (!adev)
+                       return false;
+
+               dev = get_device(acpi_get_first_physical_node(adev));
+               acpi_dev_put(adev);
+               if (!dev)
+                       return false;
+
+               pnp_dev = to_pnp_dev(dev);
+       }
+
+       res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0);
+       if (!res || resource_size(res) < GMUX_MIN_IO_LEN)
+               goto out;
+
+       /*
+        * Invalid version information may indicate either that the gmux
+        * device isn't present or that it's a new one that uses indexed io.
+        */
+       ver_major = inb(res->start + GMUX_PORT_VERSION_MAJOR);
+       ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR);
+       ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE);
+       if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
+               indexed = apple_gmux_is_indexed(res->start);
+               if (!indexed)
+                       goto out;
+       }
+
+       if (indexed_ret)
+               *indexed_ret = indexed;
+
+       ret = true;
+out:
+       put_device(dev);
+       return ret;
+}
+
+/**
+ * apple_gmux_present() - check if gmux ACPI device is present
  *
  * Drivers may use this to activate quirks specific to dual GPU MacBook Pros
  * and Mac Pros, e.g. for deferred probing, runtime pm and backlight.
  *
- * Return: %true if gmux is present and the kernel was configured
+ * Return: %true if gmux ACPI device is present and the kernel was configured
  * with CONFIG_APPLE_GMUX, %false otherwise.
  */
 static inline bool apple_gmux_present(void)
@@ -34,6 +134,11 @@ static inline bool apple_gmux_present(void)
        return false;
 }
 
+static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
+{
+       return false;
+}
+
 #endif /* !CONFIG_APPLE_GMUX */
 
 #endif /* LINUX_APPLE_GMUX_H */
index 3de24cfb7a3dedfa602e59b84cfb15230ae77ce8..634d37a599fa71984172f22958cdfa37cc2a553b 100644 (file)
@@ -1832,7 +1832,7 @@ void bpf_prog_inc(struct bpf_prog *prog);
 struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog);
 void bpf_prog_put(struct bpf_prog *prog);
 
-void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
+void bpf_prog_free_id(struct bpf_prog *prog);
 void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock);
 
 struct btf_field *btf_record_find(const struct btf_record *rec,
index 00af2c98da75a7f3f36094ceb193b9d11d3171f6..4497d0a6772cdf3d1235db36f015f247b04f2ed3 100644 (file)
@@ -99,16 +99,6 @@ struct ceph_options {
 
 #define CEPH_AUTH_NAME_DEFAULT   "guest"
 
-/* mount state */
-enum {
-       CEPH_MOUNT_MOUNTING,
-       CEPH_MOUNT_MOUNTED,
-       CEPH_MOUNT_UNMOUNTING,
-       CEPH_MOUNT_UNMOUNTED,
-       CEPH_MOUNT_SHUTDOWN,
-       CEPH_MOUNT_RECOVER,
-};
-
 static inline unsigned long ceph_timeout_jiffies(unsigned long timeout)
 {
        return timeout ?: MAX_SCHEDULE_TIMEOUT;
index 4b27519143f56fa93f39d6a50ae9339b713e5088..98598bd1d2fa5208c3289fa0d6c9e59aa992b66d 100644 (file)
@@ -668,7 +668,8 @@ extern struct efi {
 
 #define EFI_RT_SUPPORTED_ALL                                   0x3fff
 
-#define EFI_RT_SUPPORTED_TIME_SERVICES                         0x000f
+#define EFI_RT_SUPPORTED_TIME_SERVICES                         0x0003
+#define EFI_RT_SUPPORTED_WAKEUP_SERVICES                       0x000c
 #define EFI_RT_SUPPORTED_VARIABLE_SERVICES                     0x0070
 
 extern struct mm_struct efi_mm;
index b986e267d149bed6c16fc9b1ceec49b839f8f32c..b09f443d3ab9dfeef354ec3411b70f67606fe3cd 100644 (file)
@@ -545,8 +545,8 @@ int zynqmp_pm_request_wake(const u32 node,
                           const u64 address,
                           const enum zynqmp_pm_request_ack ack);
 int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode);
-int zynqmp_pm_set_rpu_mode(u32 node_id, u32 arg1);
-int zynqmp_pm_set_tcm_config(u32 node_id, u32 arg1);
+int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode);
+int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode);
 int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
                             u32 value);
@@ -845,12 +845,12 @@ static inline int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mo
        return -ENODEV;
 }
 
-static inline int zynqmp_pm_set_rpu_mode(u32 node_id, u32 arg1)
+static inline int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode)
 {
        return -ENODEV;
 }
 
-static inline int zynqmp_pm_set_tcm_config(u32 node_id, u32 arg1)
+static inline int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
 {
        return -ENODEV;
 }
index 034b1106d0228518cecf111c6549f6fa9df9138d..e098f38422af58ba9dcb30caf4f3e182a412072f 100644 (file)
@@ -200,7 +200,7 @@ static inline void *kmap_local_pfn(unsigned long pfn)
 static inline void __kunmap_local(const void *addr)
 {
 #ifdef ARCH_HAS_FLUSH_ON_KUNMAP
-       kunmap_flush_on_unmap(addr);
+       kunmap_flush_on_unmap(PTR_ALIGN_DOWN(addr, PAGE_SIZE));
 #endif
 }
 
@@ -227,7 +227,7 @@ static inline void *kmap_atomic_pfn(unsigned long pfn)
 static inline void __kunmap_atomic(const void *addr)
 {
 #ifdef ARCH_HAS_FLUSH_ON_KUNMAP
-       kunmap_flush_on_unmap(addr);
+       kunmap_flush_on_unmap(PTR_ALIGN_DOWN(addr, PAGE_SIZE));
 #endif
        pagefault_enable();
        if (IS_ENABLED(CONFIG_PREEMPT_RT))
index 551834cd529951e37a73cba4ebbf1840f5579db3..db194e2ba69fd06d599091521ea4e8456ae0d2b8 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/fs.h>
 #include <linux/hugetlb_inline.h>
 #include <linux/cgroup.h>
+#include <linux/page_ref.h>
 #include <linux/list.h>
 #include <linux/kref.h>
 #include <linux/pgtable.h>
@@ -1187,6 +1188,18 @@ static inline __init void hugetlb_cma_reserve(int order)
 }
 #endif
 
+#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+static inline bool hugetlb_pmd_shared(pte_t *pte)
+{
+       return page_count(virt_to_page(pte)) > 1;
+}
+#else
+static inline bool hugetlb_pmd_shared(pte_t *pte)
+{
+       return false;
+}
+#endif
+
 bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr);
 
 #ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
index d3c8203cab6ce7330febe3c0ff58656432ad9b91..85dc9b88ea3799ed5e598548aa99439a1064a8d8 100644 (file)
@@ -1666,10 +1666,13 @@ void mem_cgroup_track_foreign_dirty_slowpath(struct folio *folio,
 static inline void mem_cgroup_track_foreign_dirty(struct folio *folio,
                                                  struct bdi_writeback *wb)
 {
+       struct mem_cgroup *memcg;
+
        if (mem_cgroup_disabled())
                return;
 
-       if (unlikely(&folio_memcg(folio)->css != wb->memcg_css))
+       memcg = folio_memcg(folio);
+       if (unlikely(memcg && &memcg->css != wb->memcg_css))
                mem_cgroup_track_foreign_dirty_slowpath(folio, wb);
 }
 
index f3f196e4d66d6f42c74366731890a5d4102bf75b..8f857163ac89c4ad28e9b5f79899fdc630a2f529 100644 (file)
@@ -1270,10 +1270,10 @@ static inline void folio_put_refs(struct folio *folio, int refs)
                __folio_put(folio);
 }
 
-/**
- * release_pages - release an array of pages or folios
+/*
+ * union release_pages_arg - an array of pages or folios
  *
- * This just releases a simple array of multiple pages, and
+ * release_pages() releases a simple array of multiple pages, and
  * accepts various different forms of said page array: either
  * a regular old boring array of pages, an array of folios, or
  * an array of encoded page pointers.
index e8ed225d8f7cac74c5e44ea5417fb757eedcd920..ff3f3f23f649892ae81683eb69d861a7a8a28df5 100644 (file)
@@ -413,8 +413,7 @@ static inline void free_anon_vma_name(struct vm_area_struct *vma)
         * Not using anon_vma_name because it generates a warning if mmap_lock
         * is not held, which might be the case here.
         */
-       if (!vma->vm_file)
-               anon_vma_name_put(vma->anon_name);
+       anon_vma_name_put(vma->anon_name);
 }
 
 static inline bool anon_vma_name_eq(struct anon_vma_name *anon_name1,
index 3b8475007734dcaf227e35cad41bd77ada806a49..9757067c305374787f9afbba30b77449b52b305e 100644 (file)
@@ -581,7 +581,7 @@ struct vm_area_struct {
        /*
         * For private and shared anonymous mappings, a pointer to a null
         * terminated string containing the name given to the vma, or NULL if
-        * unnamed. Serialized by mmap_sem. Use anon_vma_name to access.
+        * unnamed. Serialized by mmap_lock. Use anon_vma_name to access.
         */
        struct anon_vma_name *anon_name;
 #endif
index 50caa117cb62060cdefe291baa50f5df643e6e7c..bb15c9234e21e8fba644c800d28d8503708842ac 100644 (file)
@@ -70,7 +70,6 @@ struct nvmem_keepout {
  * @word_size: Minimum read/write access granularity.
  * @stride:    Minimum read/write access stride.
  * @priv:      User context passed to read/write callbacks.
- * @wp-gpio:   Write protect pin
  * @ignore_wp:  Write Protect pin is managed by the provider.
  *
  * Note: A default "nvmem<id>" name will be assigned to the device if
@@ -85,7 +84,6 @@ struct nvmem_config {
        const char              *name;
        int                     id;
        struct module           *owner;
-       struct gpio_desc        *wp_gpio;
        const struct nvmem_cell_info    *cells;
        int                     ncells;
        const struct nvmem_keepout *keepout;
index 2e677e6ad09fcf72e05c3f86d5048bf43e2f9258..d7c2d33baa7f8e2f0da7f4ae091dc5e92e1b559c 100644 (file)
@@ -301,7 +301,7 @@ static inline bool folio_ref_try_add_rcu(struct folio *folio, int count)
  *
  * You can also use this function if you're holding a lock that prevents
  * pages being frozen & removed; eg the i_pages lock for the page cache
- * or the mmap_sem or page table lock for page tables.  In this case,
+ * or the mmap_lock or page table lock for page tables.  In this case,
  * it will always succeed, and you could have used a plain folio_get(),
  * but it's sometimes more convenient to have a common function called
  * from both locked and RCU-protected contexts.
index f7f12728d4a637611e43c24df2cbce9867e960e9..9a60f45899d3c4e19a31cbf91272635a21d847ba 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef __ASSEMBLER__
 #include <linux/types.h>
 
-#ifdef CONFIG_ARCH_OMAP1_ANY
+#ifdef CONFIG_ARCH_OMAP1
 /*
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
  */
@@ -15,7 +15,7 @@ extern u32 omap_readl(u32 pa);
 extern void omap_writeb(u8 v, u32 pa);
 extern void omap_writew(u16 v, u32 pa);
 extern void omap_writel(u32 v, u32 pa);
-#else
+#elif defined(CONFIG_COMPILE_TEST)
 static inline u8 omap_readb(u32 pa)  { return 0; }
 static inline u16 omap_readw(u32 pa) { return 0; }
 static inline u32 omap_readl(u32 pa) { return 0; }
index 1341f7d62da44663d48630991e7455e364430b63..be48f1cb1878ba271ef397d36c49feb9ea976a6b 100644 (file)
@@ -476,6 +476,15 @@ extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
 #define atomic_dec_and_lock_irqsave(atomic, lock, flags) \
                __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags)))
 
+extern int _atomic_dec_and_raw_lock(atomic_t *atomic, raw_spinlock_t *lock);
+#define atomic_dec_and_raw_lock(atomic, lock) \
+               __cond_lock(lock, _atomic_dec_and_raw_lock(atomic, lock))
+
+extern int _atomic_dec_and_raw_lock_irqsave(atomic_t *atomic, raw_spinlock_t *lock,
+                                       unsigned long *flags);
+#define atomic_dec_and_raw_lock_irqsave(atomic, lock, flags) \
+               __cond_lock(lock, _atomic_dec_and_raw_lock_irqsave(atomic, lock, &(flags)))
+
 int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,
                             size_t max_size, unsigned int cpu_mult,
                             gfp_t gfp, const char *name,
index 83ca2e8eb6b5745a1bc353d3b3d47055b0de3568..a152678b82b714bd53f59764a8772627c8e25a05 100644 (file)
@@ -252,6 +252,7 @@ struct plat_stmmacenet_data {
        int rss_en;
        int mac_port_sel_speed;
        bool en_tx_lpi_clockgating;
+       bool rx_clk_runs_in_lpi;
        int has_xgmac;
        bool vlan_fail_q_en;
        u8 vlan_fail_q;
index 2787b84eaf12f76b9b16059300d7b84d41ddab00..0ceed49516adcc7797d316f550183c8fd9aa8c25 100644 (file)
@@ -418,8 +418,7 @@ extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                                                  unsigned long nr_pages,
                                                  gfp_t gfp_mask,
-                                                 unsigned int reclaim_options,
-                                                 nodemask_t *nodemask);
+                                                 unsigned int reclaim_options);
 extern unsigned long mem_cgroup_shrink_node(struct mem_cgroup *mem,
                                                gfp_t gfp_mask, bool noswap,
                                                pg_data_t *pgdat,
index 7d5325d47c451dacf0108af5e607e4dac0b78745..86d1c8e79566ee040defebb85df3d85a96b9c3d5 100644 (file)
@@ -267,16 +267,15 @@ static inline void *usb_get_intfdata(struct usb_interface *intf)
 }
 
 /**
- * usb_set_intfdata() - associate driver-specific data with the interface
- * @intf: the usb interface
- * @data: pointer to the device priv structure or %NULL
+ * usb_set_intfdata() - associate driver-specific data with an interface
+ * @intf: USB interface
+ * @data: driver data
  *
- * Drivers should use this function in their probe() to associate their
- * driver-specific data with the usb interface.
+ * Drivers can use this function in their probe() callbacks to associate
+ * driver-specific data with an interface.
  *
- * When disconnecting, the core will take care of setting @intf back to %NULL,
- * so no actions are needed on the driver side. The interface should not be set
- * to %NULL before all actions completed (e.g. no outsanding URB remaining).
+ * Note that there is generally no need to clear the driver-data pointer even
+ * if some drivers do so for historical or implementation-specific reasons.
  */
 static inline void usb_set_intfdata(struct usb_interface *intf, void *data)
 {
@@ -774,11 +773,14 @@ extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
 extern int usb_acpi_set_power_state(struct usb_device *hdev, int index,
        bool enable);
 extern bool usb_acpi_power_manageable(struct usb_device *hdev, int index);
+extern int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index);
 #else
 static inline int usb_acpi_set_power_state(struct usb_device *hdev, int index,
        bool enable) { return 0; }
 static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
        { return true; }
+static inline int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
+       { return 0; }
 #endif
 
 /* USB autosuspend and autoresume */
index 72299f261b253392ead9e08977d033f43bf6b77c..43db6e47503c725b69c2c148fe1f190c0c26aa9d 100644 (file)
  */
 #define find_closest_descending(x, a, as) __find_closest(x, a, as, >=)
 
+/**
+ * is_insidevar - check if the @ptr points inside the @var memory range.
+ * @ptr:       the pointer to a memory address.
+ * @var:       the variable which address and size identify the memory range.
+ *
+ * Evaluates to true if the address in @ptr lies within the memory
+ * range allocated to @var.
+ */
+#define is_insidevar(ptr, var)                                         \
+       ((uintptr_t)(ptr) >= (uintptr_t)(var) &&                        \
+        (uintptr_t)(ptr) <  (uintptr_t)(var) + sizeof(var))
+
 #endif
index 689da327ce2e8113a1478e4668237d5d1b40a9cc..e3235b9c02c21fc3ef5d25df55c07cf3f6d14c49 100644 (file)
@@ -1832,8 +1832,6 @@ struct ieee80211_vif_cfg {
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void \*).
  * @txq: the multicast data TX queue
- * @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
- *     protected by fq->lock.
  * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
  *     &enum ieee80211_offload_flags.
  * @mbssid_tx_vif: Pointer to the transmitting interface if MBSSID is enabled.
@@ -1863,8 +1861,6 @@ struct ieee80211_vif {
        bool probe_req_reg;
        bool rx_mcast_action_reg;
 
-       bool txqs_stopped[IEEE80211_NUM_ACS];
-
        struct ieee80211_vif *mbssid_tx_vif;
 
        /* must be last */
index b3ba04615caa3295fc28a0c6a534221333c70604..56189e4252da3b1abf936930346611c9c70de8fa 100644 (file)
@@ -336,9 +336,12 @@ struct gdma_queue_spec {
        };
 };
 
+#define MANA_IRQ_NAME_SZ 32
+
 struct gdma_irq_context {
        void (*handler)(void *arg);
        void *arg;
+       char name[MANA_IRQ_NAME_SZ];
 };
 
 struct gdma_context {
index d5517719af4ef22282f0a15b132f8e8a07ae4179..af4aa66aaa4eba8f2eacdd00bc8fef31165c6a90 100644 (file)
@@ -1288,4 +1288,11 @@ void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx);
 
 int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb));
 
+/* Make sure qdisc is no longer in SCHED state. */
+static inline void qdisc_synchronize(const struct Qdisc *q)
+{
+       while (test_bit(__QDISC_STATE_SCHED, &q->state))
+               msleep(1);
+}
+
 #endif
index 695eebc6f2c896b71689490d879e9437fb4b74b4..e39fb0736ade5b862c469bac899c7f916718a38c 100644 (file)
@@ -422,6 +422,8 @@ extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,
 extern struct iscsi_cls_session *
 iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
                    uint16_t, int, int, uint32_t, unsigned int);
+void iscsi_session_remove(struct iscsi_cls_session *cls_session);
+void iscsi_session_free(struct iscsi_cls_session *cls_session);
 extern void iscsi_session_teardown(struct iscsi_cls_session *);
 extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
 extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
index ab955591cb72c26598676772e3998f7e1e2b268e..73cac8d0287e89b5d469722c753d137ae549ea52 100644 (file)
@@ -170,7 +170,7 @@ struct rpi_firmware_clk_rate_request {
 
 #define RPI_FIRMWARE_CLK_RATE_REQUEST(_id)     \
        {                                       \
-               .id = _id,                      \
+               .id = cpu_to_le32(_id),         \
        }
 
 #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
index c742469afe21c0110473a012b047673e48e441a5..2d6f80d75ae74c4eaa55809bf96ddcd5edd6c2bf 100644 (file)
@@ -15,8 +15,7 @@ enum sctp_conntrack {
        SCTP_CONNTRACK_SHUTDOWN_RECD,
        SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
        SCTP_CONNTRACK_HEARTBEAT_SENT,
-       SCTP_CONNTRACK_HEARTBEAT_ACKED,
-       SCTP_CONNTRACK_DATA_SENT,
+       SCTP_CONNTRACK_HEARTBEAT_ACKED, /* no longer used */
        SCTP_CONNTRACK_MAX
 };
 
index 94e74034706d98657d8f9e7e9b326ba124fe9b71..aa805e6d4e284d63ae43330e571453cacfc18acd 100644 (file)
@@ -94,8 +94,7 @@ enum ctattr_timeout_sctp {
        CTA_TIMEOUT_SCTP_SHUTDOWN_RECD,
        CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT,
        CTA_TIMEOUT_SCTP_HEARTBEAT_SENT,
-       CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED,
-       CTA_TIMEOUT_SCTP_DATA_SENT,
+       CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED, /* no longer used */
        __CTA_TIMEOUT_SCTP_MAX
 };
 #define CTA_TIMEOUT_SCTP_MAX (__CTA_TIMEOUT_SCTP_MAX - 1)
index 5cf81dff60aa07ce077dabf6d60a27d57d283ea8..727084cd79be42a9a73731864f5b15f54943de1c 100644 (file)
@@ -808,6 +808,7 @@ struct ufs_hba_monitor {
  * @urgent_bkops_lvl: keeps track of urgent bkops level for device
  * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
  *  device is known or not.
+ * @wb_mutex: used to serialize devfreq and sysfs write booster toggling
  * @clk_scaling_lock: used to serialize device commands and clock scaling
  * @desc_size: descriptor sizes reported by device
  * @scsi_block_reqs_cnt: reference counting for scsi block requests
@@ -951,6 +952,7 @@ struct ufs_hba {
        enum bkops_status urgent_bkops_lvl;
        bool is_urgent_bkops_lvl_checked;
 
+       struct mutex wb_mutex;
        struct rw_semaphore clk_scaling_lock;
        unsigned char desc_size[QUERY_DESC_IDN_MAX];
        atomic_t scsi_block_reqs_cnt;
index 0958846b005e1591c5be6d0e4428e7d2ebd9534c..44e90b28a30f12e82e7006d46a4daa588c29f15f 100644 (file)
@@ -204,7 +204,7 @@ config LOCALVERSION_AUTO
          appended after any matching localversion* files, and after the value
          set in CONFIG_LOCALVERSION.
 
-         (The actual string used here is the first eight characters produced
+         (The actual string used here is the first 12 characters produced
          by running the command:
 
            $ git rev-parse --verify HEAD
@@ -776,7 +776,7 @@ config PRINTK_SAFE_LOG_BUF_SHIFT
        depends on PRINTK
        help
          Select the size of an alternate printk per-CPU buffer where messages
-         printed from usafe contexts are temporary stored. One example would
+         printed from unsafe contexts are temporary stored. One example would
          be NMI messages, another one - printk recursion. The messages are
          copied to the main log buffer in a safe context to avoid a deadlock.
          The value defines the size as a power of 2.
index 179e93bae5390e80cd903c691a303872906db4af..043cbf80a766deec23a29e0cac70c22f9a149c6e 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <generated/compile.h>
 #include <generated/utsrelease.h>
-#include <linux/version.h>
 #include <linux/proc_ns.h>
 #include <linux/refcount.h>
 #include <linux/uts.h>
index 2ac1cd8d23ea623cb371f7472a35a45cf9e358b6..db623b3185c823487e264f32a824189ebd49cee2 100644 (file)
@@ -1765,17 +1765,12 @@ queue:
        }
        spin_unlock(&ctx->completion_lock);
 
-       ret = io_req_prep_async(req);
-       if (ret) {
-fail:
-               io_req_defer_failed(req, ret);
-               return;
-       }
        io_prep_async_link(req);
        de = kmalloc(sizeof(*de), GFP_KERNEL);
        if (!de) {
                ret = -ENOMEM;
-               goto fail;
+               io_req_defer_failed(req, ret);
+               return;
        }
 
        spin_lock(&ctx->completion_lock);
@@ -2048,13 +2043,16 @@ static void io_queue_sqe_fallback(struct io_kiocb *req)
                req->flags &= ~REQ_F_HARDLINK;
                req->flags |= REQ_F_LINK;
                io_req_defer_failed(req, req->cqe.res);
-       } else if (unlikely(req->ctx->drain_active)) {
-               io_drain_req(req);
        } else {
                int ret = io_req_prep_async(req);
 
-               if (unlikely(ret))
+               if (unlikely(ret)) {
                        io_req_defer_failed(req, ret);
+                       return;
+               }
+
+               if (unlikely(req->ctx->drain_active))
+                       io_drain_req(req);
                else
                        io_queue_iowq(req, NULL);
        }
@@ -3674,7 +3672,7 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
 
        if (ctx->flags & IORING_SETUP_SINGLE_ISSUER
            && !(ctx->flags & IORING_SETUP_R_DISABLED))
-               ctx->submitter_task = get_task_struct(current);
+               WRITE_ONCE(ctx->submitter_task, get_task_struct(current));
 
        file = io_uring_get_file(ctx);
        if (IS_ERR(file)) {
@@ -3868,7 +3866,7 @@ static int io_register_enable_rings(struct io_ring_ctx *ctx)
                return -EBADFD;
 
        if (ctx->flags & IORING_SETUP_SINGLE_ISSUER && !ctx->submitter_task)
-               ctx->submitter_task = get_task_struct(current);
+               WRITE_ONCE(ctx->submitter_task, get_task_struct(current));
 
        if (ctx->restrictions.registered)
                ctx->restricted = 1;
index 2d3cd945a531b914321a7a667632adcf038563b2..15602a136821b510a8201f90daf541b0c9188e08 100644 (file)
@@ -25,6 +25,28 @@ struct io_msg {
        u32 flags;
 };
 
+static void io_double_unlock_ctx(struct io_ring_ctx *octx)
+{
+       mutex_unlock(&octx->uring_lock);
+}
+
+static int io_double_lock_ctx(struct io_ring_ctx *octx,
+                             unsigned int issue_flags)
+{
+       /*
+        * To ensure proper ordering between the two ctxs, we can only
+        * attempt a trylock on the target. If that fails and we already have
+        * the source ctx lock, punt to io-wq.
+        */
+       if (!(issue_flags & IO_URING_F_UNLOCKED)) {
+               if (!mutex_trylock(&octx->uring_lock))
+                       return -EAGAIN;
+               return 0;
+       }
+       mutex_lock(&octx->uring_lock);
+       return 0;
+}
+
 void io_msg_ring_cleanup(struct io_kiocb *req)
 {
        struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
@@ -36,6 +58,29 @@ void io_msg_ring_cleanup(struct io_kiocb *req)
        msg->src_file = NULL;
 }
 
+static inline bool io_msg_need_remote(struct io_ring_ctx *target_ctx)
+{
+       if (!target_ctx->task_complete)
+               return false;
+       return current != target_ctx->submitter_task;
+}
+
+static int io_msg_exec_remote(struct io_kiocb *req, task_work_func_t func)
+{
+       struct io_ring_ctx *ctx = req->file->private_data;
+       struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
+       struct task_struct *task = READ_ONCE(ctx->submitter_task);
+
+       if (unlikely(!task))
+               return -EOWNERDEAD;
+
+       init_task_work(&msg->tw, func);
+       if (task_work_add(ctx->submitter_task, &msg->tw, TWA_SIGNAL))
+               return -EOWNERDEAD;
+
+       return IOU_ISSUE_SKIP_COMPLETE;
+}
+
 static void io_msg_tw_complete(struct callback_head *head)
 {
        struct io_msg *msg = container_of(head, struct io_msg, tw);
@@ -43,61 +88,54 @@ static void io_msg_tw_complete(struct callback_head *head)
        struct io_ring_ctx *target_ctx = req->file->private_data;
        int ret = 0;
 
-       if (current->flags & PF_EXITING)
+       if (current->flags & PF_EXITING) {
                ret = -EOWNERDEAD;
-       else if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
-               ret = -EOVERFLOW;
+       } else {
+               /*
+                * If the target ring is using IOPOLL mode, then we need to be
+                * holding the uring_lock for posting completions. Other ring
+                * types rely on the regular completion locking, which is
+                * handled while posting.
+                */
+               if (target_ctx->flags & IORING_SETUP_IOPOLL)
+                       mutex_lock(&target_ctx->uring_lock);
+               if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+                       ret = -EOVERFLOW;
+               if (target_ctx->flags & IORING_SETUP_IOPOLL)
+                       mutex_unlock(&target_ctx->uring_lock);
+       }
 
        if (ret < 0)
                req_set_fail(req);
        io_req_queue_tw_complete(req, ret);
 }
 
-static int io_msg_ring_data(struct io_kiocb *req)
+static int io_msg_ring_data(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_ring_ctx *target_ctx = req->file->private_data;
        struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
+       int ret;
 
        if (msg->src_fd || msg->dst_fd || msg->flags)
                return -EINVAL;
+       if (target_ctx->flags & IORING_SETUP_R_DISABLED)
+               return -EBADFD;
 
-       if (target_ctx->task_complete && current != target_ctx->submitter_task) {
-               init_task_work(&msg->tw, io_msg_tw_complete);
-               if (task_work_add(target_ctx->submitter_task, &msg->tw,
-                                 TWA_SIGNAL_NO_IPI))
-                       return -EOWNERDEAD;
-
-               atomic_or(IORING_SQ_TASKRUN, &target_ctx->rings->sq_flags);
-               return IOU_ISSUE_SKIP_COMPLETE;
-       }
-
-       if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
-               return 0;
+       if (io_msg_need_remote(target_ctx))
+               return io_msg_exec_remote(req, io_msg_tw_complete);
 
-       return -EOVERFLOW;
-}
-
-static void io_double_unlock_ctx(struct io_ring_ctx *octx,
-                                unsigned int issue_flags)
-{
-       mutex_unlock(&octx->uring_lock);
-}
-
-static int io_double_lock_ctx(struct io_ring_ctx *octx,
-                             unsigned int issue_flags)
-{
-       /*
-        * To ensure proper ordering between the two ctxs, we can only
-        * attempt a trylock on the target. If that fails and we already have
-        * the source ctx lock, punt to io-wq.
-        */
-       if (!(issue_flags & IO_URING_F_UNLOCKED)) {
-               if (!mutex_trylock(&octx->uring_lock))
+       ret = -EOVERFLOW;
+       if (target_ctx->flags & IORING_SETUP_IOPOLL) {
+               if (unlikely(io_double_lock_ctx(target_ctx, issue_flags)))
                        return -EAGAIN;
-               return 0;
+               if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+                       ret = 0;
+               io_double_unlock_ctx(target_ctx);
+       } else {
+               if (io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+                       ret = 0;
        }
-       mutex_lock(&octx->uring_lock);
-       return 0;
+       return ret;
 }
 
 static struct file *io_msg_grab_file(struct io_kiocb *req, unsigned int issue_flags)
@@ -148,7 +186,7 @@ static int io_msg_install_complete(struct io_kiocb *req, unsigned int issue_flag
        if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
                ret = -EOVERFLOW;
 out_unlock:
-       io_double_unlock_ctx(target_ctx, issue_flags);
+       io_double_unlock_ctx(target_ctx);
        return ret;
 }
 
@@ -174,6 +212,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
 
        if (target_ctx == ctx)
                return -EINVAL;
+       if (target_ctx->flags & IORING_SETUP_R_DISABLED)
+               return -EBADFD;
        if (!src_file) {
                src_file = io_msg_grab_file(req, issue_flags);
                if (!src_file)
@@ -182,14 +222,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
                req->flags |= REQ_F_NEED_CLEANUP;
        }
 
-       if (target_ctx->task_complete && current != target_ctx->submitter_task) {
-               init_task_work(&msg->tw, io_msg_tw_fd_complete);
-               if (task_work_add(target_ctx->submitter_task, &msg->tw,
-                                 TWA_SIGNAL))
-                       return -EOWNERDEAD;
-
-               return IOU_ISSUE_SKIP_COMPLETE;
-       }
+       if (io_msg_need_remote(target_ctx))
+               return io_msg_exec_remote(req, io_msg_tw_fd_complete);
        return io_msg_install_complete(req, issue_flags);
 }
 
@@ -224,7 +258,7 @@ int io_msg_ring(struct io_kiocb *req, unsigned int issue_flags)
 
        switch (msg->cmd) {
        case IORING_MSG_DATA:
-               ret = io_msg_ring_data(req);
+               ret = io_msg_ring_data(req, issue_flags);
                break;
        case IORING_MSG_SEND_FD:
                ret = io_msg_send_fd(req, issue_flags);
index fbc34a7c2743946c7fbabd91513489c8e25a0b25..90326b279965798750006b33d0775b206e94634d 100644 (file)
@@ -62,6 +62,7 @@ struct io_sr_msg {
        u16                             flags;
        /* initialised and used only by !msg send variants */
        u16                             addr_len;
+       u16                             buf_group;
        void __user                     *addr;
        /* used only for send zerocopy */
        struct io_kiocb                 *notif;
@@ -580,6 +581,15 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                if (req->opcode == IORING_OP_RECV && sr->len)
                        return -EINVAL;
                req->flags |= REQ_F_APOLL_MULTISHOT;
+               /*
+                * Store the buffer group for this multishot receive separately,
+                * as if we end up doing an io-wq based issue that selects a
+                * buffer, it has to be committed immediately and that will
+                * clear ->buf_list. This means we lose the link to the buffer
+                * list, and the eventual buffer put on completion then cannot
+                * restore it.
+                */
+               sr->buf_group = req->buf_index;
        }
 
 #ifdef CONFIG_COMPAT
@@ -596,6 +606,7 @@ static inline void io_recv_prep_retry(struct io_kiocb *req)
 
        sr->done_io = 0;
        sr->len = 0; /* get from the provided buffer */
+       req->buf_index = sr->buf_group;
 }
 
 /*
index 32e5fc8365e6a3d1862f24f70788b6e27be5cf7a..2ac1366adbd77e822db141c9aed0b31198a5851d 100644 (file)
@@ -283,8 +283,12 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
                         * to the waitqueue, so if we get nothing back, we
                         * should be safe and attempt a reissue.
                         */
-                       if (unlikely(!req->cqe.res))
+                       if (unlikely(!req->cqe.res)) {
+                               /* Multishot armed need not reissue */
+                               if (!(req->apoll_events & EPOLLONESHOT))
+                                       continue;
                                return IOU_POLL_REISSUE;
+                       }
                }
                if (req->apoll_events & EPOLLONESHOT)
                        return IOU_POLL_DONE;
index a4a41ee3e80b5622d3f5292fb44fdee50d2fedc5..e14c822f8911c9699ff0159fd51ad8bcc6ad31e5 100644 (file)
@@ -51,7 +51,6 @@ BTF_SET_END(bpf_lsm_current_hooks)
  */
 BTF_SET_START(bpf_lsm_locked_sockopt_hooks)
 #ifdef CONFIG_SECURITY_NETWORK
-BTF_ID(func, bpf_lsm_socket_sock_rcv_skb)
 BTF_ID(func, bpf_lsm_sock_graft)
 BTF_ID(func, bpf_lsm_inet_csk_clone)
 BTF_ID(func, bpf_lsm_inet_conn_established)
index f7dd8af064133891e8f3da0253ed2b9d7f855da4..b7017cae6fd1e2b61194693c4c950709e8678b25 100644 (file)
@@ -7782,9 +7782,9 @@ int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_c
 
        sort(tab->dtors, tab->cnt, sizeof(tab->dtors[0]), btf_id_cmp_func, NULL);
 
-       return 0;
 end:
-       btf_free_dtor_kfunc_tab(btf);
+       if (ret)
+               btf_free_dtor_kfunc_tab(btf);
        btf_put(btf);
        return ret;
 }
index 5aa2b5525f7937b06bcd389e3c3c215b4865a455..66bded14437735174de70195ffd2f81481f626d7 100644 (file)
@@ -152,7 +152,7 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab,
 {
        unsigned long flags;
 
-       hash = hash & HASHTAB_MAP_LOCK_MASK;
+       hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
 
        preempt_disable();
        if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) {
@@ -171,7 +171,7 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab,
                                      struct bucket *b, u32 hash,
                                      unsigned long flags)
 {
-       hash = hash & HASHTAB_MAP_LOCK_MASK;
+       hash = hash & min_t(u32, HASHTAB_MAP_LOCK_MASK, htab->n_buckets - 1);
        raw_spin_unlock_irqrestore(&b->raw_lock, flags);
        __this_cpu_dec(*(htab->map_locked[hash]));
        preempt_enable();
index ebcc3dd0fa19cd35b4d17a49477681c2fd074c30..1db156405b68b339ca68a196f714be6d29b556b6 100644 (file)
@@ -71,7 +71,7 @@ static int bpf_mem_cache_idx(size_t size)
        if (size <= 192)
                return size_index[(size - 1) / 8] - 1;
 
-       return fls(size - 1) - 1;
+       return fls(size - 1) - 2;
 }
 
 #define NUM_CACHES 11
index 13e4efc971e6d2d84fe62d9196a1f60b9d4b0f9d..190d9f9dc9870fcf077728be238c95e0c69880ad 100644 (file)
@@ -216,9 +216,6 @@ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
        if (offload->dev_state)
                offload->offdev->ops->destroy(prog);
 
-       /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
-       bpf_prog_free_id(prog, true);
-
        list_del_init(&offload->offloads);
        kfree(offload);
        prog->aux->offload = NULL;
index 64131f88c5537076a25bcfb13a04d81ea9a19ce4..ecca9366c7a6f5385e139c83015bea9f9d11aaed 100644 (file)
@@ -1972,7 +1972,7 @@ static void bpf_audit_prog(const struct bpf_prog *prog, unsigned int op)
                return;
        if (audit_enabled == AUDIT_OFF)
                return;
-       if (op == BPF_AUDIT_LOAD)
+       if (!in_irq() && !irqs_disabled())
                ctx = audit_context();
        ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_BPF);
        if (unlikely(!ab))
@@ -2001,7 +2001,7 @@ static int bpf_prog_alloc_id(struct bpf_prog *prog)
        return id > 0 ? 0 : id;
 }
 
-void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
+void bpf_prog_free_id(struct bpf_prog *prog)
 {
        unsigned long flags;
 
@@ -2013,18 +2013,10 @@ void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
        if (!prog->aux->id)
                return;
 
-       if (do_idr_lock)
-               spin_lock_irqsave(&prog_idr_lock, flags);
-       else
-               __acquire(&prog_idr_lock);
-
+       spin_lock_irqsave(&prog_idr_lock, flags);
        idr_remove(&prog_idr, prog->aux->id);
        prog->aux->id = 0;
-
-       if (do_idr_lock)
-               spin_unlock_irqrestore(&prog_idr_lock, flags);
-       else
-               __release(&prog_idr_lock);
+       spin_unlock_irqrestore(&prog_idr_lock, flags);
 }
 
 static void __bpf_prog_put_rcu(struct rcu_head *rcu)
@@ -2067,17 +2059,15 @@ static void bpf_prog_put_deferred(struct work_struct *work)
        prog = aux->prog;
        perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
        bpf_audit_prog(prog, BPF_AUDIT_UNLOAD);
+       bpf_prog_free_id(prog);
        __bpf_prog_put_noref(prog, true);
 }
 
-static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
+static void __bpf_prog_put(struct bpf_prog *prog)
 {
        struct bpf_prog_aux *aux = prog->aux;
 
        if (atomic64_dec_and_test(&aux->refcnt)) {
-               /* bpf_prog_free_id() must be called first */
-               bpf_prog_free_id(prog, do_idr_lock);
-
                if (in_irq() || irqs_disabled()) {
                        INIT_WORK(&aux->work, bpf_prog_put_deferred);
                        schedule_work(&aux->work);
@@ -2089,7 +2079,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
 
 void bpf_prog_put(struct bpf_prog *prog)
 {
-       __bpf_prog_put(prog, true);
+       __bpf_prog_put(prog);
 }
 EXPORT_SYMBOL_GPL(bpf_prog_put);
 
index 85f96c1e9f62fafd65f1bc5f1eaa711fa159d0c0..7ee2188272597f4196968707d47595cb8ed73f77 100644 (file)
@@ -2748,6 +2748,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx,
                         */
                        if (insn->src_reg == 0 && is_callback_calling_function(insn->imm))
                                return -ENOTSUPP;
+                       /* kfunc with imm==0 is invalid and fixup_kfunc_call will
+                        * catch this error later. Make backtracking conservative
+                        * with ENOTSUPP.
+                        */
+                       if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL && insn->imm == 0)
+                               return -ENOTSUPP;
                        /* regular helper call sets R0 */
                        *reg_mask &= ~1;
                        if (*reg_mask & 0x3f) {
@@ -3237,13 +3243,24 @@ static bool __is_pointer_value(bool allow_ptr_leaks,
        return reg->type != SCALAR_VALUE;
 }
 
+/* Copy src state preserving dst->parent and dst->live fields */
+static void copy_register_state(struct bpf_reg_state *dst, const struct bpf_reg_state *src)
+{
+       struct bpf_reg_state *parent = dst->parent;
+       enum bpf_reg_liveness live = dst->live;
+
+       *dst = *src;
+       dst->parent = parent;
+       dst->live = live;
+}
+
 static void save_register_state(struct bpf_func_state *state,
                                int spi, struct bpf_reg_state *reg,
                                int size)
 {
        int i;
 
-       state->stack[spi].spilled_ptr = *reg;
+       copy_register_state(&state->stack[spi].spilled_ptr, reg);
        if (size == BPF_REG_SIZE)
                state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
 
@@ -3289,7 +3306,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
                bool sanitize = reg && is_spillable_regtype(reg->type);
 
                for (i = 0; i < size; i++) {
-                       if (state->stack[spi].slot_type[i] == STACK_INVALID) {
+                       u8 type = state->stack[spi].slot_type[i];
+
+                       if (type != STACK_MISC && type != STACK_ZERO) {
                                sanitize = true;
                                break;
                        }
@@ -3569,7 +3588,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
                                 */
                                s32 subreg_def = state->regs[dst_regno].subreg_def;
 
-                               state->regs[dst_regno] = *reg;
+                               copy_register_state(&state->regs[dst_regno], reg);
                                state->regs[dst_regno].subreg_def = subreg_def;
                        } else {
                                for (i = 0; i < size; i++) {
@@ -3590,7 +3609,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
 
                if (dst_regno >= 0) {
                        /* restore register state from stack */
-                       state->regs[dst_regno] = *reg;
+                       copy_register_state(&state->regs[dst_regno], reg);
                        /* mark reg as written since spilled pointer state likely
                         * has its liveness marks cleared by is_state_visited()
                         * which resets stack/reg liveness for state transitions
@@ -9584,7 +9603,7 @@ do_sim:
         */
        if (!ptr_is_dst_reg) {
                tmp = *dst_reg;
-               *dst_reg = *ptr_reg;
+               copy_register_state(dst_reg, ptr_reg);
        }
        ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
                                        env->insn_idx);
@@ -10837,7 +10856,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                                         * to propagate min/max range.
                                         */
                                        src_reg->id = ++env->id_gen;
-                               *dst_reg = *src_reg;
+                               copy_register_state(dst_reg, src_reg);
                                dst_reg->live |= REG_LIVE_WRITTEN;
                                dst_reg->subreg_def = DEF_NOT_SUBREG;
                        } else {
@@ -10848,7 +10867,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                                                insn->src_reg);
                                        return -EACCES;
                                } else if (src_reg->type == SCALAR_VALUE) {
-                                       *dst_reg = *src_reg;
+                                       copy_register_state(dst_reg, src_reg);
                                        /* Make sure ID is cleared otherwise
                                         * dst_reg min/max could be incorrectly
                                         * propagated into src_reg by find_equal_scalars()
@@ -11647,7 +11666,7 @@ static void find_equal_scalars(struct bpf_verifier_state *vstate,
 
        bpf_for_each_reg_in_vstate(vstate, state, reg, ({
                if (reg->type == SCALAR_VALUE && reg->id == known_reg->id)
-                       *reg = *known_reg;
+                       copy_register_state(reg, known_reg);
        }));
 }
 
index a29c0b13706bb0b8230596f2ef4bf4fbe4e2666c..205dc9edcaa965bb92891a9c994a60808275730c 100644 (file)
@@ -1346,7 +1346,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
                 * A parent can be left with no CPU as long as there is no
                 * task directly associated with the parent partition.
                 */
-               if (!cpumask_intersects(cs->cpus_allowed, parent->effective_cpus) &&
+               if (cpumask_subset(parent->effective_cpus, cs->cpus_allowed) &&
                    partition_is_populated(parent, cs))
                        return PERR_NOCPUS;
 
@@ -2324,6 +2324,7 @@ out:
                new_prs = -new_prs;
        spin_lock_irq(&callback_lock);
        cs->partition_root_state = new_prs;
+       WRITE_ONCE(cs->prs_err, err);
        spin_unlock_irq(&callback_lock);
        /*
         * Update child cpusets, if present.
index d56328e5080e9814e2d0b3f045a3d8d2a7f51c3f..c4be13e50547bf57d16a7454bb187449dd4ee1b5 100644 (file)
@@ -4813,19 +4813,17 @@ find_get_pmu_context(struct pmu *pmu, struct perf_event_context *ctx,
 
                cpc = per_cpu_ptr(pmu->cpu_pmu_context, event->cpu);
                epc = &cpc->epc;
-
+               raw_spin_lock_irq(&ctx->lock);
                if (!epc->ctx) {
                        atomic_set(&epc->refcount, 1);
                        epc->embedded = 1;
-                       raw_spin_lock_irq(&ctx->lock);
                        list_add(&epc->pmu_ctx_entry, &ctx->pmu_ctx_list);
                        epc->ctx = ctx;
-                       raw_spin_unlock_irq(&ctx->lock);
                } else {
                        WARN_ON_ONCE(epc->ctx != ctx);
                        atomic_inc(&epc->refcount);
                }
-
+               raw_spin_unlock_irq(&ctx->lock);
                return epc;
        }
 
@@ -4896,33 +4894,30 @@ static void free_epc_rcu(struct rcu_head *head)
 
 static void put_pmu_ctx(struct perf_event_pmu_context *epc)
 {
+       struct perf_event_context *ctx = epc->ctx;
        unsigned long flags;
 
-       if (!atomic_dec_and_test(&epc->refcount))
+       /*
+        * XXX
+        *
+        * lockdep_assert_held(&ctx->mutex);
+        *
+        * can't because of the call-site in _free_event()/put_event()
+        * which isn't always called under ctx->mutex.
+        */
+       if (!atomic_dec_and_raw_lock_irqsave(&epc->refcount, &ctx->lock, flags))
                return;
 
-       if (epc->ctx) {
-               struct perf_event_context *ctx = epc->ctx;
+       WARN_ON_ONCE(list_empty(&epc->pmu_ctx_entry));
 
-               /*
-                * XXX
-                *
-                * lockdep_assert_held(&ctx->mutex);
-                *
-                * can't because of the call-site in _free_event()/put_event()
-                * which isn't always called under ctx->mutex.
-                */
-
-               WARN_ON_ONCE(list_empty(&epc->pmu_ctx_entry));
-               raw_spin_lock_irqsave(&ctx->lock, flags);
-               list_del_init(&epc->pmu_ctx_entry);
-               epc->ctx = NULL;
-               raw_spin_unlock_irqrestore(&ctx->lock, flags);
-       }
+       list_del_init(&epc->pmu_ctx_entry);
+       epc->ctx = NULL;
 
        WARN_ON_ONCE(!list_empty(&epc->pinned_active));
        WARN_ON_ONCE(!list_empty(&epc->flexible_active));
 
+       raw_spin_unlock_irqrestore(&ctx->lock, flags);
+
        if (epc->embedded)
                return;
 
index 473036b43c832b2a94c8eef8edb9ef82c11b9a6c..81b97f0f65564e9dafc66c89d8627c8429939306 100755 (executable)
@@ -14,6 +14,8 @@ include/
 arch/$SRCARCH/include/
 "
 
+type cpio > /dev/null
+
 # Support incremental builds by skipping archive generation
 # if timestamps of files being archived are not changed.
 
index 8fe1da9614ee8db33ff75a21010e6da45f9dfbc2..798a9042421fc7d8e993bee632ae787c35b97a86 100644 (file)
@@ -114,7 +114,7 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
 {
        struct irqchip_fwid *fwid;
 
-       if (WARN_ON(!is_fwnode_irqchip(fwnode)))
+       if (!fwnode || WARN_ON(!is_fwnode_irqchip(fwnode)))
                return;
 
        fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
@@ -1915,7 +1915,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d)
 
 static void debugfs_remove_domain_dir(struct irq_domain *d)
 {
-       debugfs_remove(debugfs_lookup(d->name, domain_dir));
+       debugfs_lookup_and_remove(d->name, domain_dir);
 }
 
 void __init irq_domain_debugfs_init(struct dentry *root)
index 955267bbc2be63a225c99fbe0679f5d907d793c1..783a3e6a0b1075a995096e6c68869a978aa3c252 100644 (file)
@@ -1000,7 +1000,7 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
 fail:
        msi_unlock_descs(dev);
 free_fwnode:
-       kfree(fwnode);
+       irq_domain_free_fwnode(fwnode);
 free_bundle:
        kfree(bundle);
        return false;
@@ -1013,6 +1013,7 @@ free_bundle:
  */
 void msi_remove_device_irq_domain(struct device *dev, unsigned int domid)
 {
+       struct fwnode_handle *fwnode = NULL;
        struct msi_domain_info *info;
        struct irq_domain *domain;
 
@@ -1025,7 +1026,10 @@ void msi_remove_device_irq_domain(struct device *dev, unsigned int domid)
 
        dev->msi.data->__domains[domid].domain = NULL;
        info = domain->host_data;
+       if (irq_domain_is_msi_device(domain))
+               fwnode = domain->fwnode;
        irq_domain_remove(domain);
+       irq_domain_free_fwnode(fwnode);
        kfree(container_of(info, struct msi_domain_template, info));
 
 unlock:
index 48568a0f5651ce401643d7a70cdda44017f68ef2..4ac3fe43e6c8ff307aca9099e4917219a04595cf 100644 (file)
@@ -2393,7 +2393,8 @@ static bool finished_loading(const char *name)
        sched_annotate_sleep();
        mutex_lock(&module_mutex);
        mod = find_module_all(name, strlen(name), true);
-       ret = !mod || mod->state == MODULE_STATE_LIVE;
+       ret = !mod || mod->state == MODULE_STATE_LIVE
+               || mod->state == MODULE_STATE_GOING;
        mutex_unlock(&module_mutex);
 
        return ret;
@@ -2569,20 +2570,35 @@ static int add_unformed_module(struct module *mod)
 
        mod->state = MODULE_STATE_UNFORMED;
 
-again:
        mutex_lock(&module_mutex);
        old = find_module_all(mod->name, strlen(mod->name), true);
        if (old != NULL) {
-               if (old->state != MODULE_STATE_LIVE) {
+               if (old->state == MODULE_STATE_COMING
+                   || old->state == MODULE_STATE_UNFORMED) {
                        /* Wait in case it fails to load. */
                        mutex_unlock(&module_mutex);
                        err = wait_event_interruptible(module_wq,
                                               finished_loading(mod->name));
                        if (err)
                                goto out_unlocked;
-                       goto again;
+
+                       /* The module might have gone in the meantime. */
+                       mutex_lock(&module_mutex);
+                       old = find_module_all(mod->name, strlen(mod->name),
+                                             true);
                }
-               err = -EEXIST;
+
+               /*
+                * We are here only when the same module was being loaded. Do
+                * not try to load it again right now. It prevents long delays
+                * caused by serialized module load failures. It might happen
+                * when more devices of the same type trigger load of
+                * a particular module.
+                */
+               if (old && old->state == MODULE_STATE_LIVE)
+                       err = -EEXIST;
+               else
+                       err = -EBUSY;
                goto out;
        }
        mod_update_bounds(mod);
index 7decf1e9c48635c3b151661208108a70c5d63e22..a5ed2e53547c94fdcd016427111f2bc26ee8cc74 100644 (file)
@@ -123,6 +123,7 @@ bool console_srcu_read_lock_is_held(void)
 {
        return srcu_read_lock_held(&console_srcu);
 }
+EXPORT_SYMBOL(console_srcu_read_lock_is_held);
 #endif
 
 enum devkmsg_log_bits {
@@ -1891,6 +1892,7 @@ static void console_lock_spinning_enable(void)
 /**
  * console_lock_spinning_disable_and_check - mark end of code where another
  *     thread was able to busy wait and check if there is a waiter
+ * @cookie: cookie returned from console_srcu_read_lock()
  *
  * This is called at the end of the section where spinning is allowed.
  * It has two functions. First, it is a signal that it is no longer
index bb1ee6d7bddea70b11a7aa136b419a153534a056..e838feb6adc504605c85ff4f252d50a7198826c0 100644 (file)
@@ -8290,12 +8290,18 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
        if (retval)
                goto out_put_task;
 
+       /*
+        * With non-SMP configs, user_cpus_ptr/user_mask isn't used and
+        * alloc_user_cpus_ptr() returns NULL.
+        */
        user_mask = alloc_user_cpus_ptr(NUMA_NO_NODE);
-       if (IS_ENABLED(CONFIG_SMP) && !user_mask) {
+       if (user_mask) {
+               cpumask_copy(user_mask, in_mask);
+       } else if (IS_ENABLED(CONFIG_SMP)) {
                retval = -ENOMEM;
                goto out_put_task;
        }
-       cpumask_copy(user_mask, in_mask);
+
        ac = (struct affinity_context){
                .new_mask  = in_mask,
                .user_mask = user_mask,
index c36aa54ae071a746bc9d585a33228c731e5de025..0f87369914274defe227d59a5e7bfb8c809ffe34 100644 (file)
@@ -7229,10 +7229,10 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
        eenv_task_busy_time(&eenv, p, prev_cpu);
 
        for (; pd; pd = pd->next) {
+               unsigned long util_min = p_util_min, util_max = p_util_max;
                unsigned long cpu_cap, cpu_thermal_cap, util;
                unsigned long cur_delta, max_spare_cap = 0;
                unsigned long rq_util_min, rq_util_max;
-               unsigned long util_min, util_max;
                unsigned long prev_spare_cap = 0;
                int max_spare_cap_cpu = -1;
                unsigned long base_energy;
@@ -7251,6 +7251,8 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
                eenv.pd_cap = 0;
 
                for_each_cpu(cpu, cpus) {
+                       struct rq *rq = cpu_rq(cpu);
+
                        eenv.pd_cap += cpu_thermal_cap;
 
                        if (!cpumask_test_cpu(cpu, sched_domain_span(sd)))
@@ -7269,24 +7271,19 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
                         * much capacity we can get out of the CPU; this is
                         * aligned with sched_cpu_util().
                         */
-                       if (uclamp_is_used()) {
-                               if (uclamp_rq_is_idle(cpu_rq(cpu))) {
-                                       util_min = p_util_min;
-                                       util_max = p_util_max;
-                               } else {
-                                       /*
-                                        * Open code uclamp_rq_util_with() except for
-                                        * the clamp() part. Ie: apply max aggregation
-                                        * only. util_fits_cpu() logic requires to
-                                        * operate on non clamped util but must use the
-                                        * max-aggregated uclamp_{min, max}.
-                                        */
-                                       rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN);
-                                       rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX);
-
-                                       util_min = max(rq_util_min, p_util_min);
-                                       util_max = max(rq_util_max, p_util_max);
-                               }
+                       if (uclamp_is_used() && !uclamp_rq_is_idle(rq)) {
+                               /*
+                                * Open code uclamp_rq_util_with() except for
+                                * the clamp() part. Ie: apply max aggregation
+                                * only. util_fits_cpu() logic requires to
+                                * operate on non clamped util but must use the
+                                * max-aggregated uclamp_{min, max}.
+                                */
+                               rq_util_min = uclamp_rq_get(rq, UCLAMP_MIN);
+                               rq_util_max = uclamp_rq_get(rq, UCLAMP_MAX);
+
+                               util_min = max(rq_util_min, p_util_min);
+                               util_max = max(rq_util_max, p_util_max);
                        }
                        if (!util_fits_cpu(util, util_min, util_max, cpu))
                                continue;
@@ -8871,16 +8868,23 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu)
         *   * Thermal pressure will impact all cpus in this perf domain
         *     equally.
         */
-       if (static_branch_unlikely(&sched_asym_cpucapacity)) {
+       if (sched_energy_enabled()) {
                unsigned long inv_cap = capacity_orig - thermal_load_avg(rq);
-               struct perf_domain *pd = rcu_dereference(rq->rd->pd);
+               struct perf_domain *pd;
 
+               rcu_read_lock();
+
+               pd = rcu_dereference(rq->rd->pd);
                rq->cpu_capacity_inverted = 0;
 
                for (; pd; pd = pd->next) {
                        struct cpumask *pd_span = perf_domain_span(pd);
                        unsigned long pd_cap_orig, pd_cap;
 
+                       /* We can't be inverted against our own pd */
+                       if (cpumask_test_cpu(cpu_of(rq), pd_span))
+                               continue;
+
                        cpu = cpumask_any(pd_span);
                        pd_cap_orig = arch_scale_cpu_capacity(cpu);
 
@@ -8905,6 +8909,8 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu)
                                break;
                        }
                }
+
+               rcu_read_unlock();
        }
 
        trace_sched_cpu_capacity_tp(rq);
index 5fd54bf0e886726dfb9fb955b0099239aedc9464..88b31f096fb2d92f3758e368fd728f04b9a856b5 100644 (file)
@@ -1442,6 +1442,8 @@ static int do_prlimit(struct task_struct *tsk, unsigned int resource,
 
        if (resource >= RLIM_NLIMITS)
                return -EINVAL;
+       resource = array_index_nospec(resource, RLIM_NLIMITS);
+
        if (new_rlim) {
                if (new_rlim->rlim_cur > new_rlim->rlim_max)
                        return -EINVAL;
index 197545241ab835bb625ea37874e8bbd046715a84..d7043043f59c8d2d31ce81794e6279b48ea7aaf6 100644 (file)
@@ -933,8 +933,8 @@ config RING_BUFFER_RECORD_RECURSION
        default y
        help
          The ring buffer has its own internal recursion. Although when
-         recursion happens it wont cause harm because of the protection,
-         but it does cause an unwanted overhead. Enabling this option will
+         recursion happens it won't cause harm because of the protection,
+         but it does cause unwanted overhead. Enabling this option will
          place where recursion was detected into the ftrace "recursed_functions"
          file.
 
@@ -1017,8 +1017,8 @@ config RING_BUFFER_STARTUP_TEST
         The test runs for 10 seconds. This will slow your boot time
         by at least 10 more seconds.
 
-        At the end of the test, statics and more checks are done.
-        It will output the stats of each per cpu buffer. What
+        At the end of the test, statistics and more checks are done.
+        It will output the stats of each per cpu buffer: What
         was written, the sizes, what was read, what was lost, and
         other similar details.
 
index 3bbd3f0c810c895a1c34d1f90af268e3c90b453a..c09792c551bf99fc69bbf9824f0af0fd459cc18f 100644 (file)
@@ -833,6 +833,7 @@ static void do_bpf_send_signal(struct irq_work *entry)
 
        work = container_of(entry, struct send_signal_irq_work, irq_work);
        group_send_sig_info(work->sig, SEND_SIG_PRIV, work->task, work->type);
+       put_task_struct(work->task);
 }
 
 static int bpf_send_signal_common(u32 sig, enum pid_type type)
@@ -848,6 +849,9 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
                return -EPERM;
        if (unlikely(!nmi_uaccess_okay()))
                return -EPERM;
+       /* Task should not be pid=1 to avoid kernel panic. */
+       if (unlikely(is_global_init(current)))
+               return -EPERM;
 
        if (irqs_disabled()) {
                /* Do an early check on signal validity. Otherwise,
@@ -864,7 +868,7 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
                 * to the irq_work. The current task may change when queued
                 * irq works get executed.
                 */
-               work->task = current;
+               work->task = get_task_struct(current);
                work->sig = sig;
                work->type = type;
                irq_work_queue(&work->irq_work);
index 442438b93fe98040349ec5c33161c1d550212e5c..750aa3f08b25ae8b75da06113b8200c4b873ebd4 100644 (file)
@@ -1248,12 +1248,17 @@ static void free_ftrace_hash_rcu(struct ftrace_hash *hash)
        call_rcu(&hash->rcu, __free_ftrace_hash_rcu);
 }
 
+/**
+ * ftrace_free_filter - remove all filters for an ftrace_ops
+ * @ops - the ops to remove the filters from
+ */
 void ftrace_free_filter(struct ftrace_ops *ops)
 {
        ftrace_ops_init(ops);
        free_ftrace_hash(ops->func_hash->filter_hash);
        free_ftrace_hash(ops->func_hash->notrace_hash);
 }
+EXPORT_SYMBOL_GPL(ftrace_free_filter);
 
 static struct ftrace_hash *alloc_ftrace_hash(int size_bits)
 {
@@ -5839,6 +5844,10 @@ EXPORT_SYMBOL_GPL(modify_ftrace_direct_multi);
  *
  * Filters denote which functions should be enabled when tracing is enabled
  * If @ip is NULL, it fails to update filter.
+ *
+ * This can allocate memory which must be freed before @ops can be freed,
+ * either by removing each filtered addr or by using
+ * ftrace_free_filter(@ops).
  */
 int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip,
                         int remove, int reset)
@@ -5858,7 +5867,11 @@ EXPORT_SYMBOL_GPL(ftrace_set_filter_ip);
  *
  * Filters denote which functions should be enabled when tracing is enabled
  * If @ips array or any ip specified within is NULL , it fails to update filter.
- */
+ *
+ * This can allocate memory which must be freed before @ops can be freed,
+ * either by removing each filtered addr or by using
+ * ftrace_free_filter(@ops).
+*/
 int ftrace_set_filter_ips(struct ftrace_ops *ops, unsigned long *ips,
                          unsigned int cnt, int remove, int reset)
 {
@@ -5900,6 +5913,10 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
  *
  * Filters denote which functions should be enabled when tracing is enabled.
  * If @buf is NULL and reset is set, all functions will be enabled for tracing.
+ *
+ * This can allocate memory which must be freed before @ops can be freed,
+ * either by removing each filtered addr or by using
+ * ftrace_free_filter(@ops).
  */
 int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf,
                       int len, int reset)
@@ -5919,6 +5936,10 @@ EXPORT_SYMBOL_GPL(ftrace_set_filter);
  * Notrace Filters denote which functions should not be enabled when tracing
  * is enabled. If @buf is NULL and reset is set, all functions will be enabled
  * for tracing.
+ *
+ * This can allocate memory which must be freed before @ops can be freed,
+ * either by removing each filtered addr or by using
+ * ftrace_free_filter(@ops).
  */
 int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
                        int len, int reset)
index 6c97cc2d754aaefe8d477f572bec03b97633b411..7e9061828c240ad4851ef46a5d9cbd95bd348924 100644 (file)
@@ -516,7 +516,7 @@ static ssize_t enabled_monitors_write(struct file *filp, const char __user *user
        struct rv_monitor_def *mdef;
        int retval = -EINVAL;
        bool enable = true;
-       char *ptr = buff;
+       char *ptr;
        int len;
 
        if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 1)
index a555a861b97811b31f833d483cab0539f379258f..78ed5f1baa8cd0d39b8bd779546a8f71abc1b3fc 100644 (file)
@@ -10295,6 +10295,8 @@ void __init early_trace_init(void)
                        static_key_enable(&tracepoint_printk_key.key);
        }
        tracer_alloc_buffers();
+
+       init_events();
 }
 
 void __init trace_init(void)
index e46a49269be2059812836d7b562cc269af2a00ad..4eb6d6b97a9fd952115cac736bc49cc729a7bfe2 100644 (file)
@@ -1490,6 +1490,7 @@ extern void trace_event_enable_cmd_record(bool enable);
 extern void trace_event_enable_tgid_record(bool enable);
 
 extern int event_trace_init(void);
+extern int init_events(void);
 extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
 extern int event_trace_del_tracer(struct trace_array *tr);
 extern void __trace_early_add_events(struct trace_array *tr);
index 96acc2b71ac747020a44fe22db21d3594e7d4993..e095c3b3a50d3aa219cc557336edbc3f1e608d53 100644 (file)
@@ -128,7 +128,7 @@ static bool is_not(const char *str)
 }
 
 /**
- * prog_entry - a singe entry in the filter program
+ * struct prog_entry - a singe entry in the filter program
  * @target:         Index to jump to on a branch (actually one minus the index)
  * @when_to_branch:  The value of the result of the predicate to do a branch
  * @pred:           The predicate to execute.
@@ -140,16 +140,16 @@ struct prog_entry {
 };
 
 /**
- * update_preds- assign a program entry a label target
+ * update_preds - assign a program entry a label target
  * @prog: The program array
  * @N: The index of the current entry in @prog
- * @when_to_branch: What to assign a program entry for its branch condition
+ * @invert: What to assign a program entry for its branch condition
  *
  * The program entry at @N has a target that points to the index of a program
  * entry that can have its target and when_to_branch fields updated.
  * Update the current program entry denoted by index @N target field to be
  * that of the updated entry. This will denote the entry to update if
- * we are processing an "||" after an "&&"
+ * we are processing an "||" after an "&&".
  */
 static void update_preds(struct prog_entry *prog, int N, int invert)
 {
index fcaf226b77446b4ba32fb51b03dd92b8a5a5ab73..5edbf6b1da3f311805218c252dd4559d249585e0 100644 (file)
@@ -1988,6 +1988,8 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
                hist_field->fn_num = flags & HIST_FIELD_FL_LOG2 ? HIST_FIELD_FN_LOG2 :
                        HIST_FIELD_FN_BUCKET;
                hist_field->operands[0] = create_hist_field(hist_data, field, fl, NULL);
+               if (!hist_field->operands[0])
+                       goto free;
                hist_field->size = hist_field->operands[0]->size;
                hist_field->type = kstrdup_const(hist_field->operands[0]->type, GFP_KERNEL);
                if (!hist_field->type)
index 94c1b5eb1dc0226af9ce3f7641df75a9e622ce8c..210e1f16839295b655de7d02d2620b34694212ec 100644 (file)
@@ -147,9 +147,8 @@ static void osnoise_unregister_instance(struct trace_array *tr)
         * register/unregister serialization is provided by trace's
         * trace_types_lock.
         */
-       lockdep_assert_held(&trace_types_lock);
-
-       list_for_each_entry_rcu(inst, &osnoise_instances, list) {
+       list_for_each_entry_rcu(inst, &osnoise_instances, list,
+                               lockdep_is_held(&trace_types_lock)) {
                if (inst->tr == tr) {
                        list_del_rcu(&inst->list);
                        found = 1;
index 57a13b61f18654b12292cb8b7ef24b5caff0f08d..bd475a00f96d138468b1709b19ebcbbbe9122612 100644 (file)
@@ -1535,7 +1535,7 @@ static struct trace_event *events[] __initdata = {
        NULL
 };
 
-__init static int init_events(void)
+__init int init_events(void)
 {
        struct trace_event *event;
        int i, ret;
@@ -1548,4 +1548,3 @@ __init static int init_events(void)
 
        return 0;
 }
-early_initcall(init_events);
index 881c3f84e88a32da05751dad0b54c0fbca5468e7..02ee440f7be36cab2c0a28b64b3009e1320bdebc 100644 (file)
@@ -754,6 +754,7 @@ config DEBUG_KMEMLEAK
        select KALLSYMS
        select CRC32
        select STACKDEPOT
+       select STACKDEPOT_ALWAYS_INIT if !DEBUG_KMEMLEAK_DEFAULT_OFF
        help
          Say Y here if you want to enable the memory leak
          detector. The memory allocation/freeing is traced in a way
@@ -1207,7 +1208,7 @@ config SCHED_DEBUG
        depends on DEBUG_KERNEL && PROC_FS
        default y
        help
-         If you say Y here, the /proc/sched_debug file will be provided
+         If you say Y here, the /sys/kernel/debug/sched file will be provided
          that can help debug the scheduler. The runtime overhead of this
          option is minimal.
 
@@ -1917,7 +1918,7 @@ config FUNCTION_ERROR_INJECTION
        help
          Add fault injections into various functions that are annotated with
          ALLOW_ERROR_INJECTION() in the kernel. BPF may also modify the return
-         value of theses functions. This is useful to test error paths of code.
+         value of these functions. This is useful to test error paths of code.
 
          If unsure, say N
 
@@ -2566,6 +2567,15 @@ config MEMCPY_KUNIT_TEST
 
          If unsure, say N.
 
+config MEMCPY_SLOW_KUNIT_TEST
+       bool "Include exhaustive memcpy tests"
+       depends on MEMCPY_KUNIT_TEST
+       default y
+       help
+         Some memcpy tests are quite exhaustive in checking for overlaps
+         and bit ranges. These can be very slow, so they are split out
+         as a separate config, in case they need to be disabled.
+
 config IS_SIGNED_TYPE_KUNIT_TEST
        tristate "Test is_signed_type() macro" if !KUNIT_ALL_TESTS
        depends on KUNIT
index 375575a5a0e3cc828a761aa3c6f705a85f3f0c14..4dedd61e5192d2a808169916bda1ae9084a73946 100644 (file)
@@ -194,7 +194,7 @@ config KCSAN_WEAK_MEMORY
          Enable support for modeling a subset of weak memory, which allows
          detecting a subset of data races due to missing memory barriers.
 
-         Depends on KCSAN_STRICT, because the options strenghtening certain
+         Depends on KCSAN_STRICT, because the options strengthening certain
          plain accesses by default (depending on !KCSAN_STRICT) reduce the
          ability to detect any data races invoving reordered accesses, in
          particular reordered writes.
index 9555b68bb774cc3277dca434d19880286d71df0e..1dcca8f2e194204e63fb8bf443c71b052dfab7ee 100644 (file)
@@ -49,3 +49,34 @@ int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
        return 0;
 }
 EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave);
+
+int _atomic_dec_and_raw_lock(atomic_t *atomic, raw_spinlock_t *lock)
+{
+       /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
+       if (atomic_add_unless(atomic, -1, 1))
+               return 0;
+
+       /* Otherwise do it the slow way */
+       raw_spin_lock(lock);
+       if (atomic_dec_and_test(atomic))
+               return 1;
+       raw_spin_unlock(lock);
+       return 0;
+}
+EXPORT_SYMBOL(_atomic_dec_and_raw_lock);
+
+int _atomic_dec_and_raw_lock_irqsave(atomic_t *atomic, raw_spinlock_t *lock,
+                                    unsigned long *flags)
+{
+       /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
+       if (atomic_add_unless(atomic, -1, 1))
+               return 0;
+
+       /* Otherwise do it the slow way */
+       raw_spin_lock_irqsave(lock, *flags);
+       if (atomic_dec_and_test(atomic))
+               return 1;
+       raw_spin_unlock_irqrestore(lock, *flags);
+       return 0;
+}
+EXPORT_SYMBOL(_atomic_dec_and_raw_lock_irqsave);
index f5b50babe38d46586bd9057c4386c8f02ec0bb23..05a09652f5a105f401874366ce74476eebc0e0e0 100644 (file)
@@ -241,24 +241,34 @@ void kunit_mem_assert_format(const struct kunit_assert *assert,
        mem_assert = container_of(assert, struct kunit_mem_assert,
                                  assert);
 
-       string_stream_add(stream,
-                         KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
-                         mem_assert->text->left_text,
-                         mem_assert->text->operation,
-                         mem_assert->text->right_text);
+       if (!mem_assert->left_value) {
+               string_stream_add(stream,
+                                 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
+                                 mem_assert->text->left_text);
+       } else if (!mem_assert->right_value) {
+               string_stream_add(stream,
+                                 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
+                                 mem_assert->text->right_text);
+       } else {
+               string_stream_add(stream,
+                               KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
+                               mem_assert->text->left_text,
+                               mem_assert->text->operation,
+                               mem_assert->text->right_text);
 
-       string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
-                         mem_assert->text->left_text);
-       kunit_assert_hexdump(stream, mem_assert->left_value,
-                            mem_assert->right_value, mem_assert->size);
+               string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
+                               mem_assert->text->left_text);
+               kunit_assert_hexdump(stream, mem_assert->left_value,
+                                       mem_assert->right_value, mem_assert->size);
 
-       string_stream_add(stream, "\n");
+               string_stream_add(stream, "\n");
 
-       string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
-                         mem_assert->text->right_text);
-       kunit_assert_hexdump(stream, mem_assert->right_value,
-                            mem_assert->left_value, mem_assert->size);
+               string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
+                               mem_assert->text->right_text);
+               kunit_assert_hexdump(stream, mem_assert->right_value,
+                                       mem_assert->left_value, mem_assert->size);
 
-       kunit_assert_print_msg(message, stream);
+               kunit_assert_print_msg(message, stream);
+       }
 }
 EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
index c9ebf975e56b65d0fdf3a7c8ed4e75ceafc1619a..890ba5b3a9819ddcf4ac9f4e7c85a95e978e89e9 100644 (file)
@@ -21,6 +21,7 @@
 #include "try-catch-impl.h"
 
 DEFINE_STATIC_KEY_FALSE(kunit_running);
+EXPORT_SYMBOL_GPL(kunit_running);
 
 #if IS_BUILTIN(CONFIG_KUNIT)
 /*
index 26e2045d3cda9eea4592b767b42307d3af0288dc..5a976393c9aeab51472576f9f4640f5b30747010 100644 (file)
@@ -670,12 +670,13 @@ static inline unsigned long mte_pivot(const struct maple_enode *mn,
                                 unsigned char piv)
 {
        struct maple_node *node = mte_to_node(mn);
+       enum maple_type type = mte_node_type(mn);
 
-       if (piv >= mt_pivots[piv]) {
+       if (piv >= mt_pivots[type]) {
                WARN_ON(1);
                return 0;
        }
-       switch (mte_node_type(mn)) {
+       switch (type) {
        case maple_arange_64:
                return node->ma64.pivot[piv];
        case maple_range_64:
@@ -4887,7 +4888,7 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
        unsigned long *pivots, *gaps;
        void __rcu **slots;
        unsigned long gap = 0;
-       unsigned long max, min, index;
+       unsigned long max, min;
        unsigned char offset;
 
        if (unlikely(mas_is_err(mas)))
@@ -4909,8 +4910,7 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
                min = mas_safe_min(mas, pivots, --offset);
 
        max = mas_safe_pivot(mas, pivots, offset, type);
-       index = mas->index;
-       while (index <= max) {
+       while (mas->index <= max) {
                gap = 0;
                if (gaps)
                        gap = gaps[offset];
@@ -4941,10 +4941,8 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
                min = mas_safe_min(mas, pivots, offset);
        }
 
-       if (unlikely(index > max)) {
-               mas_set_err(mas, -EBUSY);
-               return false;
-       }
+       if (unlikely((mas->index > max) || (size - 1 > max - mas->index)))
+               goto no_space;
 
        if (unlikely(ma_is_leaf(type))) {
                mas->offset = offset;
@@ -4961,9 +4959,11 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
        return false;
 
 ascend:
-       if (mte_is_root(mas->node))
-               mas_set_err(mas, -EBUSY);
+       if (!mte_is_root(mas->node))
+               return false;
 
+no_space:
+       mas_set_err(mas, -EBUSY);
        return false;
 }
 
index 89128551448d10a83e7e96a0adad2a613d36a30e..887926f0473124684ea006f6de22cb92250b455f 100644 (file)
@@ -309,6 +309,8 @@ static void set_random_nonzero(struct kunit *test, u8 *byte)
 
 static void init_large(struct kunit *test)
 {
+       if (!IS_ENABLED(CONFIG_MEMCPY_SLOW_KUNIT_TEST))
+               kunit_skip(test, "Slow test skipped. Enable with CONFIG_MEMCPY_SLOW_KUNIT_TEST=y");
 
        /* Get many bit patterns. */
        get_random_bytes(large_src, ARRAY_SIZE(large_src));
index 9055e8b4d144e4c9fc0de6f6d8bbab0d7620932e..489e15bde5c1d248ba4914da2aa4839f1084f5b7 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/jiffies.h>
+#include <linux/nospec.h>
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/types.h>
@@ -381,6 +382,7 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
        if (type <= 0 || type > maxtype)
                return 0;
 
+       type = array_index_nospec(type, maxtype + 1);
        pt = &policy[type];
 
        BUG_ON(pt->type > NLA_TYPE_MAX);
@@ -596,6 +598,7 @@ static int __nla_validate_parse(const struct nlattr *head, int len, int maxtype,
                        }
                        continue;
                }
+               type = array_index_nospec(type, maxtype + 1);
                if (policy) {
                        int err = validate_nla(nla, maxtype, policy,
                                               validate, extack, depth);
index f72aa50c6654b7225624c2d87f25c8c923909e82..8d7519a8f308d94b5d4ac92e4a61fcbc6e6dd670 100644 (file)
@@ -470,22 +470,27 @@ int sg_alloc_append_table_from_pages(struct sg_append_table *sgt_append,
                return -EOPNOTSUPP;
 
        if (sgt_append->prv) {
+               unsigned long next_pfn = (page_to_phys(sg_page(sgt_append->prv)) +
+                       sgt_append->prv->offset + sgt_append->prv->length) / PAGE_SIZE;
+
                if (WARN_ON(offset))
                        return -EINVAL;
 
                /* Merge contiguous pages into the last SG */
                prv_len = sgt_append->prv->length;
-               last_pg = sg_page(sgt_append->prv);
-               while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
-                       if (sgt_append->prv->length + PAGE_SIZE > max_segment)
-                               break;
-                       sgt_append->prv->length += PAGE_SIZE;
-                       last_pg = pages[0];
-                       pages++;
-                       n_pages--;
+               if (page_to_pfn(pages[0]) == next_pfn) {
+                       last_pg = pfn_to_page(next_pfn - 1);
+                       while (n_pages && pages_are_mergeable(pages[0], last_pg)) {
+                               if (sgt_append->prv->length + PAGE_SIZE > max_segment)
+                                       break;
+                               sgt_append->prv->length += PAGE_SIZE;
+                               last_pg = pages[0];
+                               pages++;
+                               n_pages--;
+                       }
+                       if (!n_pages)
+                               goto out;
                }
-               if (!n_pages)
-                       goto out;
        }
 
        /* compute number of contiguous chunks */
index 497fc93ccf9ecf550c0904c03bf20d707022a088..ec847bf4dcb4ddb032bc3c4362fb1cfe0d525526 100644 (file)
@@ -2517,6 +2517,91 @@ static noinline void check_bnode_min_spanning(struct maple_tree *mt)
        mt_set_non_kernel(0);
 }
 
+static noinline void check_empty_area_window(struct maple_tree *mt)
+{
+       unsigned long i, nr_entries = 20;
+       MA_STATE(mas, mt, 0, 0);
+
+       for (i = 1; i <= nr_entries; i++)
+               mtree_store_range(mt, i*10, i*10 + 9,
+                                 xa_mk_value(i), GFP_KERNEL);
+
+       /* Create another hole besides the one at 0 */
+       mtree_store_range(mt, 160, 169, NULL, GFP_KERNEL);
+
+       /* Check lower bounds that don't fit */
+       rcu_read_lock();
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 90, 10) != -EBUSY);
+
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 6, 90, 5) != -EBUSY);
+
+       /* Check lower bound that does fit */
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 90, 5) != 0);
+       MT_BUG_ON(mt, mas.index != 5);
+       MT_BUG_ON(mt, mas.last != 9);
+       rcu_read_unlock();
+
+       /* Check one gap that doesn't fit and one that does */
+       rcu_read_lock();
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 217, 9) != 0);
+       MT_BUG_ON(mt, mas.index != 161);
+       MT_BUG_ON(mt, mas.last != 169);
+
+       /* Check one gap that does fit above the min */
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 218, 3) != 0);
+       MT_BUG_ON(mt, mas.index != 216);
+       MT_BUG_ON(mt, mas.last != 218);
+
+       /* Check size that doesn't fit any gap */
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 218, 16) != -EBUSY);
+
+       /*
+        * Check size that doesn't fit the lower end of the window but
+        * does fit the gap
+        */
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 167, 200, 4) != -EBUSY);
+
+       /*
+        * Check size that doesn't fit the upper end of the window but
+        * does fit the gap
+        */
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 162, 4) != -EBUSY);
+
+       /* Check mas_empty_area forward */
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 9) != 0);
+       MT_BUG_ON(mt, mas.index != 0);
+       MT_BUG_ON(mt, mas.last != 8);
+
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 4) != 0);
+       MT_BUG_ON(mt, mas.index != 0);
+       MT_BUG_ON(mt, mas.last != 3);
+
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 11) != -EBUSY);
+
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area(&mas, 5, 100, 6) != -EBUSY);
+
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area(&mas, 0, 8, 10) != -EBUSY);
+
+       mas_reset(&mas);
+       mas_empty_area(&mas, 100, 165, 3);
+
+       mas_reset(&mas);
+       MT_BUG_ON(mt, mas_empty_area(&mas, 100, 163, 6) != -EBUSY);
+       rcu_read_unlock();
+}
+
 static DEFINE_MTREE(tree);
 static int maple_tree_seed(void)
 {
@@ -2765,6 +2850,10 @@ static int maple_tree_seed(void)
        check_bnode_min_spanning(&tree);
        mtree_destroy(&tree);
 
+       mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
+       check_empty_area_window(&tree);
+       mtree_destroy(&tree);
+
 #if defined(BENCH)
 skip:
 #endif
index 6bdc1cd15f7614e5f4eb2dba7618ba8a16be2249..ec10506834b6291ad189381c7cbf544ebe5fc4ec 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-/**
+/*
  * lib/minmax.c: windowed min/max tracker
  *
  * Kathleen Nichols' algorithm for tracking the minimum (or maximum)
index ca1603524bbe002419a8521a8cdf8572a129b1dd..8238e83385a7916cfa4ff3398daadc641aa691ec 100644 (file)
@@ -1839,6 +1839,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)
                                        pfn = cc->zone->zone_start_pfn;
                                cc->fast_search_fail = 0;
                                found_block = true;
+                               set_pageblock_skip(freepage);
                                break;
                        }
                }
index db895230ee7e4e46304fc005ebf4b78864d6db77..bdbfeb6fb3934dd6f2a41395e3d0361ffa7e5291 100644 (file)
@@ -94,6 +94,8 @@ static int hugetlb_acct_memory(struct hstate *h, long delta);
 static void hugetlb_vma_lock_free(struct vm_area_struct *vma);
 static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma);
 static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma);
+static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end);
 
 static inline bool subpool_is_free(struct hugepage_subpool *spool)
 {
@@ -1181,7 +1183,7 @@ void hugetlb_dup_vma_private(struct vm_area_struct *vma)
 
 /*
  * Reset and decrement one ref on hugepage private reservation.
- * Called with mm->mmap_sem writer semaphore held.
+ * Called with mm->mmap_lock writer semaphore held.
  * This function should be only used by move_vma() and operate on
  * same sized vma. It should never come here with last ref on the
  * reservation.
@@ -4834,6 +4836,25 @@ static int hugetlb_vm_op_split(struct vm_area_struct *vma, unsigned long addr)
 {
        if (addr & ~(huge_page_mask(hstate_vma(vma))))
                return -EINVAL;
+
+       /*
+        * PMD sharing is only possible for PUD_SIZE-aligned address ranges
+        * in HugeTLB VMAs. If we will lose PUD_SIZE alignment due to this
+        * split, unshare PMDs in the PUD_SIZE interval surrounding addr now.
+        */
+       if (addr & ~PUD_MASK) {
+               /*
+                * hugetlb_vm_op_split is called right before we attempt to
+                * split the VMA. We will need to unshare PMDs in the old and
+                * new VMAs, so let's unshare before we split.
+                */
+               unsigned long floor = addr & PUD_MASK;
+               unsigned long ceil = floor + PUD_SIZE;
+
+               if (floor >= vma->vm_start && ceil <= vma->vm_end)
+                       hugetlb_unshare_pmds(vma, floor, ceil);
+       }
+
        return 0;
 }
 
@@ -5030,6 +5051,9 @@ again:
                                entry = huge_pte_clear_uffd_wp(entry);
                        set_huge_pte_at(dst, addr, dst_pte, entry);
                } else if (unlikely(is_pte_marker(entry))) {
+                       /* No swap on hugetlb */
+                       WARN_ON_ONCE(
+                           is_swapin_error_entry(pte_to_swp_entry(entry)));
                        /*
                         * We copy the pte marker only if the dst vma has
                         * uffd-wp enabled.
@@ -5131,7 +5155,7 @@ static void move_huge_pte(struct vm_area_struct *vma, unsigned long old_addr,
 
        /*
         * We don't have to worry about the ordering of src and dst ptlocks
-        * because exclusive mmap_sem (or the i_mmap_lock) prevents deadlock.
+        * because exclusive mmap_lock (or the i_mmap_lock) prevents deadlock.
         */
        if (src_ptl != dst_ptl)
                spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
@@ -6639,8 +6663,17 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                spinlock_t *ptl;
                ptep = huge_pte_offset(mm, address, psize);
                if (!ptep) {
-                       address |= last_addr_mask;
-                       continue;
+                       if (!uffd_wp) {
+                               address |= last_addr_mask;
+                               continue;
+                       }
+                       /*
+                        * Userfaultfd wr-protect requires pgtable
+                        * pre-allocations to install pte markers.
+                        */
+                       ptep = huge_pte_alloc(mm, vma, address, psize);
+                       if (!ptep)
+                               break;
                }
                ptl = huge_pte_lock(h, mm, ptep);
                if (huge_pmd_unshare(mm, vma, address, ptep)) {
@@ -6658,16 +6691,13 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                }
                pte = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
-                       spin_unlock(ptl);
-                       continue;
-               }
-               if (unlikely(is_hugetlb_entry_migration(pte))) {
+                       /* Nothing to do. */
+               } else if (unlikely(is_hugetlb_entry_migration(pte))) {
                        swp_entry_t entry = pte_to_swp_entry(pte);
                        struct page *page = pfn_swap_entry_to_page(entry);
+                       pte_t newpte = pte;
 
-                       if (!is_readable_migration_entry(entry)) {
-                               pte_t newpte;
-
+                       if (is_writable_migration_entry(entry)) {
                                if (PageAnon(page))
                                        entry = make_readable_exclusive_migration_entry(
                                                                swp_offset(entry));
@@ -6675,25 +6705,22 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                                        entry = make_readable_migration_entry(
                                                                swp_offset(entry));
                                newpte = swp_entry_to_pte(entry);
-                               if (uffd_wp)
-                                       newpte = pte_swp_mkuffd_wp(newpte);
-                               else if (uffd_wp_resolve)
-                                       newpte = pte_swp_clear_uffd_wp(newpte);
-                               set_huge_pte_at(mm, address, ptep, newpte);
                                pages++;
                        }
-                       spin_unlock(ptl);
-                       continue;
-               }
-               if (unlikely(pte_marker_uffd_wp(pte))) {
-                       /*
-                        * This is changing a non-present pte into a none pte,
-                        * no need for huge_ptep_modify_prot_start/commit().
-                        */
+
+                       if (uffd_wp)
+                               newpte = pte_swp_mkuffd_wp(newpte);
+                       else if (uffd_wp_resolve)
+                               newpte = pte_swp_clear_uffd_wp(newpte);
+                       if (!pte_same(pte, newpte))
+                               set_huge_pte_at(mm, address, ptep, newpte);
+               } else if (unlikely(is_pte_marker(pte))) {
+                       /* No other markers apply for now. */
+                       WARN_ON_ONCE(!pte_marker_uffd_wp(pte));
                        if (uffd_wp_resolve)
+                               /* Safe to modify directly (non-present->none). */
                                huge_pte_clear(mm, address, ptep, psize);
-               }
-               if (!huge_pte_none(pte)) {
+               } else if (!huge_pte_none(pte)) {
                        pte_t old_pte;
                        unsigned int shift = huge_page_shift(hstate_vma(vma));
 
@@ -7328,26 +7355,21 @@ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int re
        }
 }
 
-/*
- * This function will unconditionally remove all the shared pmd pgtable entries
- * within the specific vma for a hugetlbfs memory range.
- */
-void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
+static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
+                                  unsigned long start,
+                                  unsigned long end)
 {
        struct hstate *h = hstate_vma(vma);
        unsigned long sz = huge_page_size(h);
        struct mm_struct *mm = vma->vm_mm;
        struct mmu_notifier_range range;
-       unsigned long address, start, end;
+       unsigned long address;
        spinlock_t *ptl;
        pte_t *ptep;
 
        if (!(vma->vm_flags & VM_MAYSHARE))
                return;
 
-       start = ALIGN(vma->vm_start, PUD_SIZE);
-       end = ALIGN_DOWN(vma->vm_end, PUD_SIZE);
-
        if (start >= end)
                return;
 
@@ -7379,6 +7401,16 @@ void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
        mmu_notifier_invalidate_range_end(&range);
 }
 
+/*
+ * This function will unconditionally remove all the shared pmd pgtable entries
+ * within the specific vma for a hugetlbfs memory range.
+ */
+void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
+{
+       hugetlb_unshare_pmds(vma, ALIGN(vma->vm_start, PUD_SIZE),
+                       ALIGN_DOWN(vma->vm_end, PUD_SIZE));
+}
+
 #ifdef CONFIG_CMA
 static bool cma_reserve_called __initdata;
 
index 1d02757e90a3266a0d2f66872c68ba117115b33b..22598b20c7b758406f2f8e34d809a7cc621729ab 100644 (file)
@@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(kasan_restore_multi_shot);
  * Whether the KASAN KUnit test suite is currently being executed.
  * Updated in kasan_test.c.
  */
-bool kasan_kunit_executing;
+static bool kasan_kunit_executing;
 
 void kasan_kunit_test_suite_start(void)
 {
index 5cb401aa2b9d8b424462f4bded8511491d1c7045..90acfea40c13c9e13d48b0868bb308251bce4cf4 100644 (file)
@@ -847,6 +847,10 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
        return SCAN_SUCCEED;
 }
 
+/*
+ * See pmd_trans_unstable() for how the result may change out from
+ * underneath us, even if we hold mmap_lock in read.
+ */
 static int find_pmd_or_thp_or_none(struct mm_struct *mm,
                                   unsigned long address,
                                   pmd_t **pmd)
@@ -865,8 +869,12 @@ static int find_pmd_or_thp_or_none(struct mm_struct *mm,
 #endif
        if (pmd_none(pmde))
                return SCAN_PMD_NONE;
+       if (!pmd_present(pmde))
+               return SCAN_PMD_NULL;
        if (pmd_trans_huge(pmde))
                return SCAN_PMD_MAPPED;
+       if (pmd_devmap(pmde))
+               return SCAN_PMD_NULL;
        if (pmd_bad(pmde))
                return SCAN_PMD_NULL;
        return SCAN_SUCCEED;
@@ -1460,14 +1468,6 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
        if (!hugepage_vma_check(vma, vma->vm_flags, false, false, false))
                return SCAN_VMA_CHECK;
 
-       /*
-        * Symmetry with retract_page_tables(): Exclude MAP_PRIVATE mappings
-        * that got written to. Without this, we'd have to also lock the
-        * anon_vma if one exists.
-        */
-       if (vma->anon_vma)
-               return SCAN_VMA_CHECK;
-
        /* Keep pmd pgtable for uffd-wp; see comment in retract_page_tables() */
        if (userfaultfd_wp(vma))
                return SCAN_PTE_UFFD_WP;
@@ -1567,8 +1567,14 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
        }
 
        /* step 4: remove pte entries */
+       /* we make no change to anon, but protect concurrent anon page lookup */
+       if (vma->anon_vma)
+               anon_vma_lock_write(vma->anon_vma);
+
        collapse_and_free_pmd(mm, vma, haddr, pmd);
 
+       if (vma->anon_vma)
+               anon_vma_unlock_write(vma->anon_vma);
        i_mmap_unlock_write(vma->vm_file->f_mapping);
 
 maybe_install_pmd:
@@ -1644,7 +1650,7 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff,
                 * has higher cost too. It would also probably require locking
                 * the anon_vma.
                 */
-               if (vma->anon_vma) {
+               if (READ_ONCE(vma->anon_vma)) {
                        result = SCAN_PAGE_ANON;
                        goto next;
                }
@@ -1672,6 +1678,18 @@ static int retract_page_tables(struct address_space *mapping, pgoff_t pgoff,
                result = SCAN_PTE_MAPPED_HUGEPAGE;
                if ((cc->is_khugepaged || is_target) &&
                    mmap_write_trylock(mm)) {
+                       /*
+                        * Re-check whether we have an ->anon_vma, because
+                        * collapse_and_free_pmd() requires that either no
+                        * ->anon_vma exists or the anon_vma is locked.
+                        * We already checked ->anon_vma above, but that check
+                        * is racy because ->anon_vma can be populated under the
+                        * mmap lock in read mode.
+                        */
+                       if (vma->anon_vma) {
+                               result = SCAN_PAGE_ANON;
+                               goto unlock_next;
+                       }
                        /*
                         * When a vma is registered with uffd-wp, we can't
                         * recycle the pmd pgtable because there can be pte
@@ -2649,7 +2667,7 @@ int madvise_collapse(struct vm_area_struct *vma, struct vm_area_struct **prev,
                                goto out_nolock;
                        }
 
-                       hend = vma->vm_end & HPAGE_PMD_MASK;
+                       hend = min(hend, vma->vm_end & HPAGE_PMD_MASK);
                }
                mmap_assert_locked(mm);
                memset(cc->node_load, 0, sizeof(cc->node_load));
index 92f670edbf518710eed9aef6e115afe6f4b07c1f..55dc8b8b0616237645307e2ccefdd774cc596b09 100644 (file)
@@ -2070,8 +2070,10 @@ static int __init kmemleak_boot_config(char *str)
                return -EINVAL;
        if (strcmp(str, "off") == 0)
                kmemleak_disable();
-       else if (strcmp(str, "on") == 0)
+       else if (strcmp(str, "on") == 0) {
                kmemleak_skip_disable = 1;
+               stack_depot_want_early_init();
+       }
        else
                return -EINVAL;
        return 0;
@@ -2093,7 +2095,6 @@ void __init kmemleak_init(void)
        if (kmemleak_error)
                return;
 
-       stack_depot_init();
        jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE);
        jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000);
 
index a56a6d17e201e3cecc3f2b8d66361db2ee5e91b0..b6ea204d4e23bdf862db9d0eb804c09c6286d45e 100644 (file)
@@ -130,7 +130,7 @@ static int replace_anon_vma_name(struct vm_area_struct *vma,
 #endif /* CONFIG_ANON_VMA_NAME */
 /*
  * Update the vm_flags on region of a vma, splitting it or merging it as
- * necessary.  Must be called with mmap_sem held for writing;
+ * necessary.  Must be called with mmap_lock held for writing;
  * Caller should ensure anon_name stability by raising its refcount even when
  * anon_name belongs to a valid vma because this function might free that vma.
  */
index ab457f0394ab6eeed8bf33c84ee9943586844178..73afff8062f9bf96b17dfae12fbe18091e215cda 100644 (file)
@@ -63,7 +63,6 @@
 #include <linux/resume_user_mode.h>
 #include <linux/psi.h>
 #include <linux/seq_buf.h>
-#include <linux/parser.h>
 #include "internal.h"
 #include <net/sock.h>
 #include <net/ip.h>
@@ -2393,8 +2392,7 @@ static unsigned long reclaim_high(struct mem_cgroup *memcg,
                psi_memstall_enter(&pflags);
                nr_reclaimed += try_to_free_mem_cgroup_pages(memcg, nr_pages,
                                                        gfp_mask,
-                                                       MEMCG_RECLAIM_MAY_SWAP,
-                                                       NULL);
+                                                       MEMCG_RECLAIM_MAY_SWAP);
                psi_memstall_leave(&pflags);
        } while ((memcg = parent_mem_cgroup(memcg)) &&
                 !mem_cgroup_is_root(memcg));
@@ -2685,8 +2683,7 @@ retry:
 
        psi_memstall_enter(&pflags);
        nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages,
-                                                   gfp_mask, reclaim_options,
-                                                   NULL);
+                                                   gfp_mask, reclaim_options);
        psi_memstall_leave(&pflags);
 
        if (mem_cgroup_margin(mem_over_limit) >= nr_pages)
@@ -3506,8 +3503,7 @@ static int mem_cgroup_resize_max(struct mem_cgroup *memcg,
                }
 
                if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL,
-                                       memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP,
-                                       NULL)) {
+                                       memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP)) {
                        ret = -EBUSY;
                        break;
                }
@@ -3618,8 +3614,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
                        return -EINTR;
 
                if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL,
-                                                 MEMCG_RECLAIM_MAY_SWAP,
-                                                 NULL))
+                                                 MEMCG_RECLAIM_MAY_SWAP))
                        nr_retries--;
        }
 
@@ -6429,8 +6424,7 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
                }
 
                reclaimed = try_to_free_mem_cgroup_pages(memcg, nr_pages - high,
-                                       GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP,
-                                       NULL);
+                                       GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP);
 
                if (!reclaimed && !nr_retries--)
                        break;
@@ -6479,8 +6473,7 @@ static ssize_t memory_max_write(struct kernfs_open_file *of,
 
                if (nr_reclaims) {
                        if (!try_to_free_mem_cgroup_pages(memcg, nr_pages - max,
-                                       GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP,
-                                       NULL))
+                                       GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP))
                                nr_reclaims--;
                        continue;
                }
@@ -6603,54 +6596,21 @@ static ssize_t memory_oom_group_write(struct kernfs_open_file *of,
        return nbytes;
 }
 
-enum {
-       MEMORY_RECLAIM_NODES = 0,
-       MEMORY_RECLAIM_NULL,
-};
-
-static const match_table_t if_tokens = {
-       { MEMORY_RECLAIM_NODES, "nodes=%s" },
-       { MEMORY_RECLAIM_NULL, NULL },
-};
-
 static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf,
                              size_t nbytes, loff_t off)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
        unsigned int nr_retries = MAX_RECLAIM_RETRIES;
        unsigned long nr_to_reclaim, nr_reclaimed = 0;
-       unsigned int reclaim_options = MEMCG_RECLAIM_MAY_SWAP |
-                                      MEMCG_RECLAIM_PROACTIVE;
-       char *old_buf, *start;
-       substring_t args[MAX_OPT_ARGS];
-       int token;
-       char value[256];
-       nodemask_t nodemask = NODE_MASK_ALL;
-
-       buf = strstrip(buf);
-
-       old_buf = buf;
-       nr_to_reclaim = memparse(buf, &buf) / PAGE_SIZE;
-       if (buf == old_buf)
-               return -EINVAL;
+       unsigned int reclaim_options;
+       int err;
 
        buf = strstrip(buf);
+       err = page_counter_memparse(buf, "", &nr_to_reclaim);
+       if (err)
+               return err;
 
-       while ((start = strsep(&buf, " ")) != NULL) {
-               if (!strlen(start))
-                       continue;
-               token = match_token(start, if_tokens, args);
-               match_strlcpy(value, args, sizeof(value));
-               switch (token) {
-               case MEMORY_RECLAIM_NODES:
-                       if (nodelist_parse(value, nodemask) < 0)
-                               return -EINVAL;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       }
-
+       reclaim_options = MEMCG_RECLAIM_MAY_SWAP | MEMCG_RECLAIM_PROACTIVE;
        while (nr_reclaimed < nr_to_reclaim) {
                unsigned long reclaimed;
 
@@ -6667,8 +6627,7 @@ static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf,
 
                reclaimed = try_to_free_mem_cgroup_pages(memcg,
                                                nr_to_reclaim - nr_reclaimed,
-                                               GFP_KERNEL, reclaim_options,
-                                               &nodemask);
+                                               GFP_KERNEL, reclaim_options);
 
                if (!reclaimed && !nr_retries--)
                        return -EAGAIN;
index aad226daf41bd5de81b2ea55c39443e8774b4091..3e836fecd0354c8aa433d65ce59b8b5d62ea75a1 100644 (file)
@@ -828,12 +828,8 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                        return -EBUSY;
                return -ENOENT;
        } else if (is_pte_marker_entry(entry)) {
-               /*
-                * We're copying the pgtable should only because dst_vma has
-                * uffd-wp enabled, do sanity check.
-                */
-               WARN_ON_ONCE(!userfaultfd_wp(dst_vma));
-               set_pte_at(dst_mm, addr, dst_pte, pte);
+               if (is_swapin_error_entry(entry) || userfaultfd_wp(dst_vma))
+                       set_pte_at(dst_mm, addr, dst_pte, pte);
                return 0;
        }
        if (!userfaultfd_wp(dst_vma))
@@ -3629,8 +3625,12 @@ static vm_fault_t pte_marker_clear(struct vm_fault *vmf)
        /*
         * Be careful so that we will only recover a special uffd-wp pte into a
         * none pte.  Otherwise it means the pte could have changed, so retry.
+        *
+        * This should also cover the case where e.g. the pte changed
+        * quickly from a PTE_MARKER_UFFD_WP into PTE_MARKER_SWAPIN_ERROR.
+        * So is_pte_marker() check is not enough to safely drop the pte.
         */
-       if (is_pte_marker(*vmf->pte))
+       if (pte_same(vmf->orig_pte, *vmf->pte))
                pte_clear(vmf->vma->vm_mm, vmf->address, vmf->pte);
        pte_unmap_unlock(vmf->pte, vmf->ptl);
        return 0;
index 02c8a712282f1146cd2aa901af7db3e42572cc70..f940395667c82f7beacbb0ac65e08107f3fe5ddb 100644 (file)
@@ -600,7 +600,8 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask,
 
        /* With MPOL_MF_MOVE, we migrate only unshared hugepage. */
        if (flags & (MPOL_MF_MOVE_ALL) ||
-           (flags & MPOL_MF_MOVE && page_mapcount(page) == 1)) {
+           (flags & MPOL_MF_MOVE && page_mapcount(page) == 1 &&
+            !hugetlb_pmd_shared(pte))) {
                if (isolate_hugetlb(page, qp->pagelist) &&
                        (flags & MPOL_MF_STRICT))
                        /*
index 87d929316d57264197b01cc815209ca3a5d039b7..425a9349e610825f69745e5aa446e997e741f1d9 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1524,6 +1524,10 @@ int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
        if (vma_soft_dirty_enabled(vma) && !is_vm_hugetlb_page(vma))
                return 1;
 
+       /* Do we need write faults for uffd-wp tracking? */
+       if (userfaultfd_wp(vma))
+               return 1;
+
        /* Specialty mapping? */
        if (vm_flags & VM_PFNMAP)
                return 0;
@@ -2290,7 +2294,7 @@ static inline int munmap_sidetree(struct vm_area_struct *vma,
  * @start: The aligned start address to munmap.
  * @end: The aligned end address to munmap.
  * @uf: The userfaultfd list_head
- * @downgrade: Set to true to attempt a write downgrade of the mmap_sem
+ * @downgrade: Set to true to attempt a write downgrade of the mmap_lock
  *
  * If @downgrade is true, check return code for potential release of the lock.
  */
@@ -2465,7 +2469,7 @@ map_count_exceeded:
  * @len: The length of the range to munmap
  * @uf: The userfaultfd list_head
  * @downgrade: set to true if the user wants to attempt to write_downgrade the
- * mmap_sem
+ * mmap_lock
  *
  * This function takes a @mas that is either pointing to the previous VMA or set
  * to MA_START and sets it up to remove the mapping(s).  The @len will be
index 908df12caa268582da22ad27821c8c7530308d11..61cf60015a8b8a7e327b0d91e29b3d48a6b2024e 100644 (file)
@@ -245,7 +245,13 @@ static unsigned long change_pte_range(struct mmu_gather *tlb,
                                        newpte = pte_swp_mksoft_dirty(newpte);
                                if (pte_swp_uffd_wp(oldpte))
                                        newpte = pte_swp_mkuffd_wp(newpte);
-                       } else if (pte_marker_entry_uffd_wp(entry)) {
+                       } else if (is_pte_marker_entry(entry)) {
+                               /*
+                                * Ignore swapin errors unconditionally,
+                                * because any access should sigbus anyway.
+                                */
+                               if (is_swapin_error_entry(entry))
+                                       continue;
                                /*
                                 * If this is uffd-wp pte marker and we'd like
                                 * to unprotect it, drop it; the next page
index fe587c5d65913ab19efc27ff0f7261bd58516dd5..930f65c315c02469bd72f1608e69a4f4131256f1 100644 (file)
@@ -1027,16 +1027,29 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
                        }
 
                        /*
-                        * Function vma_merge() is called on the extension we are adding to
-                        * the already existing vma, vma_merge() will merge this extension with
-                        * the already existing vma (expand operation itself) and possibly also
-                        * with the next vma if it becomes adjacent to the expanded vma and
-                        * otherwise compatible.
+                        * Function vma_merge() is called on the extension we
+                        * are adding to the already existing vma, vma_merge()
+                        * will merge this extension with the already existing
+                        * vma (expand operation itself) and possibly also with
+                        * the next vma if it becomes adjacent to the expanded
+                        * vma and  otherwise compatible.
+                        *
+                        * However, vma_merge() can currently fail due to
+                        * is_mergeable_vma() check for vm_ops->close (see the
+                        * comment there). Yet this should not prevent vma
+                        * expanding, so perform a simple expand for such vma.
+                        * Ideally the check for close op should be only done
+                        * when a vma would be actually removed due to a merge.
                         */
-                       vma = vma_merge(mm, vma, extension_start, extension_end,
+                       if (!vma->vm_ops || !vma->vm_ops->close) {
+                               vma = vma_merge(mm, vma, extension_start, extension_end,
                                        vma->vm_flags, vma->anon_vma, vma->vm_file,
                                        extension_pgoff, vma_policy(vma),
                                        vma->vm_userfaultfd_ctx, anon_vma_name(vma));
+                       } else if (vma_adjust(vma, vma->vm_start, addr + new_len,
+                                  vma->vm_pgoff, NULL)) {
+                               vma = NULL;
+                       }
                        if (!vma) {
                                vm_unacct_memory(pages);
                                ret = -ENOMEM;
index 214c70e1d05942e8a0a9a2e4ece7a6f5086f9c62..5b83938ecb67cf4533c4a30e997cea3e3111b285 100644 (file)
@@ -559,7 +559,6 @@ void vma_mas_remove(struct vm_area_struct *vma, struct ma_state *mas)
 
 static void setup_vma_to_mm(struct vm_area_struct *vma, struct mm_struct *mm)
 {
-       mm->map_count++;
        vma->vm_mm = mm;
 
        /* add the VMA to the mapping */
@@ -587,6 +586,7 @@ static void mas_add_vma_to_mm(struct ma_state *mas, struct mm_struct *mm,
        BUG_ON(!vma->vm_region);
 
        setup_vma_to_mm(vma, mm);
+       mm->map_count++;
 
        /* add the VMA to the tree */
        vma_mas_store(vma, mas);
@@ -1240,6 +1240,7 @@ share:
 error_just_free:
        up_write(&nommu_region_sem);
 error:
+       mas_destroy(&mas);
        if (region->vm_file)
                fput(region->vm_file);
        kmem_cache_free(vm_region_jar, region);
@@ -1250,7 +1251,6 @@ error:
 
 sharing_violation:
        up_write(&nommu_region_sem);
-       mas_destroy(&mas);
        pr_warn("Attempt to share mismatched mappings\n");
        ret = -EINVAL;
        goto error;
@@ -1347,6 +1347,7 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
        if (vma->vm_file)
                return -ENOMEM;
 
+       mm = vma->vm_mm;
        if (mm->map_count >= sysctl_max_map_count)
                return -ENOMEM;
 
@@ -1398,6 +1399,7 @@ int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
        mas_set_range(&mas, vma->vm_start, vma->vm_end - 1);
        mas_store(&mas, vma);
        vma_mas_store(new, &mas);
+       mm->map_count++;
        return 0;
 
 err_mas_preallocate:
@@ -1509,7 +1511,8 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len, struct list
 erase_whole_vma:
        if (delete_vma_from_mm(vma))
                ret = -ENOMEM;
-       delete_vma(mm, vma);
+       else
+               delete_vma(mm, vma);
        return ret;
 }
 
index c301487be5fb405d2f2d12a9c497e951dbecdbe3..0005ab2c29af7bc3241bd50514036c2cdbf7a82b 100644 (file)
@@ -478,12 +478,10 @@ bool shmem_is_huge(struct vm_area_struct *vma, struct inode *inode,
        if (vma && ((vma->vm_flags & VM_NOHUGEPAGE) ||
            test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)))
                return false;
-       if (shmem_huge_force)
-               return true;
-       if (shmem_huge == SHMEM_HUGE_FORCE)
-               return true;
        if (shmem_huge == SHMEM_HUGE_DENY)
                return false;
+       if (shmem_huge_force || shmem_huge == SHMEM_HUGE_FORCE)
+               return true;
 
        switch (SHMEM_SB(inode->i_sb)->huge) {
        case SHMEM_HUGE_ALWAYS:
index 7a269db050eed88b5273d2c3820ff8e453de518b..29300fc1289a8375188853a07edb64d69df634e0 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2211,6 +2211,8 @@ static int drain_freelist(struct kmem_cache *cache,
                raw_spin_unlock_irq(&n->list_lock);
                slab_destroy(cache, slab);
                nr_freed++;
+
+               cond_resched();
        }
 out:
        return nr_freed;
index 908a529bca12c9477f460774cae73eba5a31fe02..4fa440e87cd693af2534ad219b86f49e6f802a2e 100644 (file)
@@ -1100,6 +1100,7 @@ start_over:
                        goto check_out;
                pr_debug("scan_swap_map of si %d failed to find offset\n",
                        si->type);
+               cond_resched();
 
                spin_lock(&swap_avail_lock);
 nextsi:
index bd6637fcd8f9b19a69045e79e73d6b0c44d9f15b..bf3eedf0209cec3f831f3a01731b4311af625aa5 100644 (file)
@@ -3323,13 +3323,16 @@ void lru_gen_migrate_mm(struct mm_struct *mm)
        if (mem_cgroup_disabled())
                return;
 
+       /* migration can happen before addition */
+       if (!mm->lru_gen.memcg)
+               return;
+
        rcu_read_lock();
        memcg = mem_cgroup_from_task(task);
        rcu_read_unlock();
        if (memcg == mm->lru_gen.memcg)
                return;
 
-       VM_WARN_ON_ONCE(!mm->lru_gen.memcg);
        VM_WARN_ON_ONCE(list_empty(&mm->lru_gen.list));
 
        lru_gen_del_mm(mm);
@@ -6754,8 +6757,7 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
 unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                                           unsigned long nr_pages,
                                           gfp_t gfp_mask,
-                                          unsigned int reclaim_options,
-                                          nodemask_t *nodemask)
+                                          unsigned int reclaim_options)
 {
        unsigned long nr_reclaimed;
        unsigned int noreclaim_flag;
@@ -6770,7 +6772,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                .may_unmap = 1,
                .may_swap = !!(reclaim_options & MEMCG_RECLAIM_MAY_SWAP),
                .proactive = !!(reclaim_options & MEMCG_RECLAIM_PROACTIVE),
-               .nodemask = nodemask,
        };
        /*
         * Traverse the ZONELIST_FALLBACK zonelist of the current node to put
index 9445bee6b0140b071e9134805e318c145bacea5b..702bc3fd687abeb44a0c193489ada527f1a1c7f0 100644 (file)
  * have room for two bit at least.
  */
 #define OBJ_ALLOCATED_TAG 1
-#define OBJ_TAG_BITS 1
+
+#ifdef CONFIG_ZPOOL
+/*
+ * The second least-significant bit in the object's header identifies if the
+ * value stored at the header is a deferred handle from the last reclaim
+ * attempt.
+ *
+ * As noted above, this is valid because we have room for two bits.
+ */
+#define OBJ_DEFERRED_HANDLE_TAG        2
+#define OBJ_TAG_BITS   2
+#define OBJ_TAG_MASK   (OBJ_ALLOCATED_TAG | OBJ_DEFERRED_HANDLE_TAG)
+#else
+#define OBJ_TAG_BITS   1
+#define OBJ_TAG_MASK   OBJ_ALLOCATED_TAG
+#endif /* CONFIG_ZPOOL */
+
 #define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS - OBJ_TAG_BITS)
 #define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1)
 
@@ -222,6 +238,12 @@ struct link_free {
                 * Handle of allocated object.
                 */
                unsigned long handle;
+#ifdef CONFIG_ZPOOL
+               /*
+                * Deferred handle of a reclaimed object.
+                */
+               unsigned long deferred_handle;
+#endif
        };
 };
 
@@ -272,8 +294,6 @@ struct zspage {
        /* links the zspage to the lru list in the pool */
        struct list_head lru;
        bool under_reclaim;
-       /* list of unfreed handles whose objects have been reclaimed */
-       unsigned long *deferred_handles;
 #endif
 
        struct zs_pool *pool;
@@ -897,7 +917,8 @@ static unsigned long handle_to_obj(unsigned long handle)
        return *(unsigned long *)handle;
 }
 
-static bool obj_allocated(struct page *page, void *obj, unsigned long *phandle)
+static bool obj_tagged(struct page *page, void *obj, unsigned long *phandle,
+               int tag)
 {
        unsigned long handle;
        struct zspage *zspage = get_zspage(page);
@@ -908,13 +929,27 @@ static bool obj_allocated(struct page *page, void *obj, unsigned long *phandle)
        } else
                handle = *(unsigned long *)obj;
 
-       if (!(handle & OBJ_ALLOCATED_TAG))
+       if (!(handle & tag))
                return false;
 
-       *phandle = handle & ~OBJ_ALLOCATED_TAG;
+       /* Clear all tags before returning the handle */
+       *phandle = handle & ~OBJ_TAG_MASK;
        return true;
 }
 
+static inline bool obj_allocated(struct page *page, void *obj, unsigned long *phandle)
+{
+       return obj_tagged(page, obj, phandle, OBJ_ALLOCATED_TAG);
+}
+
+#ifdef CONFIG_ZPOOL
+static bool obj_stores_deferred_handle(struct page *page, void *obj,
+               unsigned long *phandle)
+{
+       return obj_tagged(page, obj, phandle, OBJ_DEFERRED_HANDLE_TAG);
+}
+#endif
+
 static void reset_page(struct page *page)
 {
        __ClearPageMovable(page);
@@ -946,22 +981,36 @@ unlock:
 }
 
 #ifdef CONFIG_ZPOOL
+static unsigned long find_deferred_handle_obj(struct size_class *class,
+               struct page *page, int *obj_idx);
+
 /*
  * Free all the deferred handles whose objects are freed in zs_free.
  */
-static void free_handles(struct zs_pool *pool, struct zspage *zspage)
+static void free_handles(struct zs_pool *pool, struct size_class *class,
+               struct zspage *zspage)
 {
-       unsigned long handle = (unsigned long)zspage->deferred_handles;
+       int obj_idx = 0;
+       struct page *page = get_first_page(zspage);
+       unsigned long handle;
 
-       while (handle) {
-               unsigned long nxt_handle = handle_to_obj(handle);
+       while (1) {
+               handle = find_deferred_handle_obj(class, page, &obj_idx);
+               if (!handle) {
+                       page = get_next_page(page);
+                       if (!page)
+                               break;
+                       obj_idx = 0;
+                       continue;
+               }
 
                cache_free_handle(pool, handle);
-               handle = nxt_handle;
+               obj_idx++;
        }
 }
 #else
-static inline void free_handles(struct zs_pool *pool, struct zspage *zspage) {}
+static inline void free_handles(struct zs_pool *pool, struct size_class *class,
+               struct zspage *zspage) {}
 #endif
 
 static void __free_zspage(struct zs_pool *pool, struct size_class *class,
@@ -979,7 +1028,7 @@ static void __free_zspage(struct zs_pool *pool, struct size_class *class,
        VM_BUG_ON(fg != ZS_EMPTY);
 
        /* Free all deferred handles from zs_free */
-       free_handles(pool, zspage);
+       free_handles(pool, class, zspage);
 
        next = page = get_first_page(zspage);
        do {
@@ -1067,7 +1116,6 @@ static void init_zspage(struct size_class *class, struct zspage *zspage)
 #ifdef CONFIG_ZPOOL
        INIT_LIST_HEAD(&zspage->lru);
        zspage->under_reclaim = false;
-       zspage->deferred_handles = NULL;
 #endif
 
        set_freeobj(zspage, 0);
@@ -1568,7 +1616,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
 }
 EXPORT_SYMBOL_GPL(zs_malloc);
 
-static void obj_free(int class_size, unsigned long obj)
+static void obj_free(int class_size, unsigned long obj, unsigned long *handle)
 {
        struct link_free *link;
        struct zspage *zspage;
@@ -1582,15 +1630,29 @@ static void obj_free(int class_size, unsigned long obj)
        zspage = get_zspage(f_page);
 
        vaddr = kmap_atomic(f_page);
-
-       /* Insert this object in containing zspage's freelist */
        link = (struct link_free *)(vaddr + f_offset);
-       if (likely(!ZsHugePage(zspage)))
-               link->next = get_freeobj(zspage) << OBJ_TAG_BITS;
-       else
-               f_page->index = 0;
+
+       if (handle) {
+#ifdef CONFIG_ZPOOL
+               /* Stores the (deferred) handle in the object's header */
+               *handle |= OBJ_DEFERRED_HANDLE_TAG;
+               *handle &= ~OBJ_ALLOCATED_TAG;
+
+               if (likely(!ZsHugePage(zspage)))
+                       link->deferred_handle = *handle;
+               else
+                       f_page->index = *handle;
+#endif
+       } else {
+               /* Insert this object in containing zspage's freelist */
+               if (likely(!ZsHugePage(zspage)))
+                       link->next = get_freeobj(zspage) << OBJ_TAG_BITS;
+               else
+                       f_page->index = 0;
+               set_freeobj(zspage, f_objidx);
+       }
+
        kunmap_atomic(vaddr);
-       set_freeobj(zspage, f_objidx);
        mod_zspage_inuse(zspage, -1);
 }
 
@@ -1615,7 +1677,6 @@ void zs_free(struct zs_pool *pool, unsigned long handle)
        zspage = get_zspage(f_page);
        class = zspage_class(pool, zspage);
 
-       obj_free(class->size, obj);
        class_stat_dec(class, OBJ_USED, 1);
 
 #ifdef CONFIG_ZPOOL
@@ -1624,15 +1685,15 @@ void zs_free(struct zs_pool *pool, unsigned long handle)
                 * Reclaim needs the handles during writeback. It'll free
                 * them along with the zspage when it's done with them.
                 *
-                * Record current deferred handle at the memory location
-                * whose address is given by handle.
+                * Record current deferred handle in the object's header.
                 */
-               record_obj(handle, (unsigned long)zspage->deferred_handles);
-               zspage->deferred_handles = (unsigned long *)handle;
+               obj_free(class->size, obj, &handle);
                spin_unlock(&pool->lock);
                return;
        }
 #endif
+       obj_free(class->size, obj, NULL);
+
        fullness = fix_fullness_group(class, zspage);
        if (fullness == ZS_EMPTY)
                free_zspage(pool, class, zspage);
@@ -1713,11 +1774,11 @@ static void zs_object_copy(struct size_class *class, unsigned long dst,
 }
 
 /*
- * Find alloced object in zspage from index object and
+ * Find object with a certain tag in zspage from index object and
  * return handle.
  */
-static unsigned long find_alloced_obj(struct size_class *class,
-                                       struct page *page, int *obj_idx)
+static unsigned long find_tagged_obj(struct size_class *class,
+                                       struct page *page, int *obj_idx, int tag)
 {
        unsigned int offset;
        int index = *obj_idx;
@@ -1728,7 +1789,7 @@ static unsigned long find_alloced_obj(struct size_class *class,
        offset += class->size * index;
 
        while (offset < PAGE_SIZE) {
-               if (obj_allocated(page, addr + offset, &handle))
+               if (obj_tagged(page, addr + offset, &handle, tag))
                        break;
 
                offset += class->size;
@@ -1742,6 +1803,28 @@ static unsigned long find_alloced_obj(struct size_class *class,
        return handle;
 }
 
+/*
+ * Find alloced object in zspage from index object and
+ * return handle.
+ */
+static unsigned long find_alloced_obj(struct size_class *class,
+                                       struct page *page, int *obj_idx)
+{
+       return find_tagged_obj(class, page, obj_idx, OBJ_ALLOCATED_TAG);
+}
+
+#ifdef CONFIG_ZPOOL
+/*
+ * Find object storing a deferred handle in header in zspage from index object
+ * and return handle.
+ */
+static unsigned long find_deferred_handle_obj(struct size_class *class,
+               struct page *page, int *obj_idx)
+{
+       return find_tagged_obj(class, page, obj_idx, OBJ_DEFERRED_HANDLE_TAG);
+}
+#endif
+
 struct zs_compact_control {
        /* Source spage for migration which could be a subpage of zspage */
        struct page *s_page;
@@ -1784,7 +1867,7 @@ static int migrate_zspage(struct zs_pool *pool, struct size_class *class,
                zs_object_copy(class, free_obj, used_obj);
                obj_idx++;
                record_obj(handle, free_obj);
-               obj_free(class->size, used_obj);
+               obj_free(class->size, used_obj, NULL);
        }
 
        /* Remember last position in this iteration */
@@ -2478,6 +2561,90 @@ void zs_destroy_pool(struct zs_pool *pool)
 EXPORT_SYMBOL_GPL(zs_destroy_pool);
 
 #ifdef CONFIG_ZPOOL
+static void restore_freelist(struct zs_pool *pool, struct size_class *class,
+               struct zspage *zspage)
+{
+       unsigned int obj_idx = 0;
+       unsigned long handle, off = 0; /* off is within-page offset */
+       struct page *page = get_first_page(zspage);
+       struct link_free *prev_free = NULL;
+       void *prev_page_vaddr = NULL;
+
+       /* in case no free object found */
+       set_freeobj(zspage, (unsigned int)(-1UL));
+
+       while (page) {
+               void *vaddr = kmap_atomic(page);
+               struct page *next_page;
+
+               while (off < PAGE_SIZE) {
+                       void *obj_addr = vaddr + off;
+
+                       /* skip allocated object */
+                       if (obj_allocated(page, obj_addr, &handle)) {
+                               obj_idx++;
+                               off += class->size;
+                               continue;
+                       }
+
+                       /* free deferred handle from reclaim attempt */
+                       if (obj_stores_deferred_handle(page, obj_addr, &handle))
+                               cache_free_handle(pool, handle);
+
+                       if (prev_free)
+                               prev_free->next = obj_idx << OBJ_TAG_BITS;
+                       else /* first free object found */
+                               set_freeobj(zspage, obj_idx);
+
+                       prev_free = (struct link_free *)vaddr + off / sizeof(*prev_free);
+                       /* if last free object in a previous page, need to unmap */
+                       if (prev_page_vaddr) {
+                               kunmap_atomic(prev_page_vaddr);
+                               prev_page_vaddr = NULL;
+                       }
+
+                       obj_idx++;
+                       off += class->size;
+               }
+
+               /*
+                * Handle the last (full or partial) object on this page.
+                */
+               next_page = get_next_page(page);
+               if (next_page) {
+                       if (!prev_free || prev_page_vaddr) {
+                               /*
+                                * There is no free object in this page, so we can safely
+                                * unmap it.
+                                */
+                               kunmap_atomic(vaddr);
+                       } else {
+                               /* update prev_page_vaddr since prev_free is on this page */
+                               prev_page_vaddr = vaddr;
+                       }
+               } else { /* this is the last page */
+                       if (prev_free) {
+                               /*
+                                * Reset OBJ_TAG_BITS bit to last link to tell
+                                * whether it's allocated object or not.
+                                */
+                               prev_free->next = -1UL << OBJ_TAG_BITS;
+                       }
+
+                       /* unmap previous page (if not done yet) */
+                       if (prev_page_vaddr) {
+                               kunmap_atomic(prev_page_vaddr);
+                               prev_page_vaddr = NULL;
+                       }
+
+                       kunmap_atomic(vaddr);
+               }
+
+               page = next_page;
+               off %= PAGE_SIZE;
+       }
+}
+
 static int zs_reclaim_page(struct zs_pool *pool, unsigned int retries)
 {
        int i, obj_idx, ret = 0;
@@ -2561,6 +2728,12 @@ next:
                        return 0;
                }
 
+               /*
+                * Eviction fails on one of the handles, so we need to restore zspage.
+                * We need to rebuild its freelist (and free stored deferred handles),
+                * put it back to the correct size class, and add it to the LRU list.
+                */
+               restore_freelist(pool, class, zspage);
                putback_zspage(class, zspage);
                list_add(&zspage->lru, &pool->lru);
                unlock_zspage(zspage);
index d3e542c2fc3e4939cfa4922b5e1722e11be9e4b0..acf563fbdfd951656216cf3d79dd3cae4e3e42f8 100644 (file)
@@ -821,6 +821,7 @@ static void terminate_big_destroy(struct hci_dev *hdev, void *data, int err)
 static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis)
 {
        struct iso_list_data *d;
+       int ret;
 
        bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", big, bis);
 
@@ -831,8 +832,12 @@ static int hci_le_terminate_big(struct hci_dev *hdev, u8 big, u8 bis)
        d->big = big;
        d->bis = bis;
 
-       return hci_cmd_sync_queue(hdev, terminate_big_sync, d,
-                                 terminate_big_destroy);
+       ret = hci_cmd_sync_queue(hdev, terminate_big_sync, d,
+                                terminate_big_destroy);
+       if (ret)
+               kfree(d);
+
+       return ret;
 }
 
 static int big_terminate_sync(struct hci_dev *hdev, void *data)
@@ -857,6 +862,7 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data)
 static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle)
 {
        struct iso_list_data *d;
+       int ret;
 
        bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, sync_handle);
 
@@ -867,8 +873,12 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, u16 sync_handle)
        d->big = big;
        d->sync_handle = sync_handle;
 
-       return hci_cmd_sync_queue(hdev, big_terminate_sync, d,
-                                 terminate_big_destroy);
+       ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
+                                terminate_big_destroy);
+       if (ret)
+               kfree(d);
+
+       return ret;
 }
 
 /* Cleanup BIS connection
index 0594af4e37cad9733aa52a2035b22d549d408fd3..ad92a4be5851739cba345c629690b9274e154db5 100644 (file)
@@ -3848,8 +3848,11 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data,
                           conn->handle, conn->link);
 
                /* Create CIS if LE is already connected */
-               if (conn->link && conn->link->state == BT_CONNECTED)
+               if (conn->link && conn->link->state == BT_CONNECTED) {
+                       rcu_read_unlock();
                        hci_le_create_cis(conn->link);
+                       rcu_read_lock();
+               }
 
                if (i == rp->num_handles)
                        break;
index 9e2d7e4b850c545cc4d30118247cc47e476ff332..117eedb6f70993a5b58987a7a7bf794aaf8e000e 100644 (file)
@@ -3572,7 +3572,7 @@ static const struct hci_init_stage hci_init2[] = {
 static int hci_le_read_buffer_size_sync(struct hci_dev *hdev)
 {
        /* Use Read LE Buffer Size V2 if supported */
-       if (hdev->commands[41] & 0x20)
+       if (iso_capable(hdev) && hdev->commands[41] & 0x20)
                return __hci_cmd_sync_status(hdev,
                                             HCI_OP_LE_READ_BUFFER_SIZE_V2,
                                             0, NULL, HCI_CMD_TIMEOUT);
@@ -3597,10 +3597,10 @@ static int hci_le_read_supported_states_sync(struct hci_dev *hdev)
 
 /* LE Controller init stage 2 command sequence */
 static const struct hci_init_stage le_init2[] = {
-       /* HCI_OP_LE_READ_BUFFER_SIZE */
-       HCI_INIT(hci_le_read_buffer_size_sync),
        /* HCI_OP_LE_READ_LOCAL_FEATURES */
        HCI_INIT(hci_le_read_local_features_sync),
+       /* HCI_OP_LE_READ_BUFFER_SIZE */
+       HCI_INIT(hci_le_read_buffer_size_sync),
        /* HCI_OP_LE_READ_SUPPORTED_STATES */
        HCI_INIT(hci_le_read_supported_states_sync),
        {}
@@ -6187,20 +6187,13 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
 
 static int _update_adv_data_sync(struct hci_dev *hdev, void *data)
 {
-       u8 instance = *(u8 *)data;
-
-       kfree(data);
+       u8 instance = PTR_ERR(data);
 
        return hci_update_adv_data_sync(hdev, instance);
 }
 
 int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
 {
-       u8 *inst_ptr = kmalloc(1, GFP_KERNEL);
-
-       if (!inst_ptr)
-               return -ENOMEM;
-
-       *inst_ptr = instance;
-       return hci_cmd_sync_queue(hdev, _update_adv_data_sync, inst_ptr, NULL);
+       return hci_cmd_sync_queue(hdev, _update_adv_data_sync,
+                                 ERR_PTR(instance), NULL);
 }
index 035bb5d25f850a7d427f87b2d5bc960526b3fe0f..24444b502e5865400d4eecbdcf68ace4b9e687b6 100644 (file)
@@ -289,15 +289,15 @@ static int iso_connect_bis(struct sock *sk)
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
+       err = iso_chan_add(conn, sk, NULL);
+       if (err)
+               return err;
+
        lock_sock(sk);
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
 
-       err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               goto release;
-
        if (hcon->state == BT_CONNECTED) {
                iso_sock_clear_timer(sk);
                sk->sk_state = BT_CONNECTED;
@@ -306,7 +306,6 @@ static int iso_connect_bis(struct sock *sk)
                iso_sock_set_timer(sk, sk->sk_sndtimeo);
        }
 
-release:
        release_sock(sk);
        return err;
 
@@ -372,15 +371,15 @@ static int iso_connect_cis(struct sock *sk)
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
+       err = iso_chan_add(conn, sk, NULL);
+       if (err)
+               return err;
+
        lock_sock(sk);
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
 
-       err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               goto release;
-
        if (hcon->state == BT_CONNECTED) {
                iso_sock_clear_timer(sk);
                sk->sk_state = BT_CONNECTED;
@@ -392,7 +391,6 @@ static int iso_connect_cis(struct sock *sk)
                iso_sock_set_timer(sk, sk->sk_sndtimeo);
        }
 
-release:
        release_sock(sk);
        return err;
 
@@ -895,13 +893,10 @@ static int iso_listen_bis(struct sock *sk)
        if (!hdev)
                return -EHOSTUNREACH;
 
-       hci_dev_lock(hdev);
-
        err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
                                 le_addr_type(iso_pi(sk)->dst_type),
                                 iso_pi(sk)->bc_sid);
 
-       hci_dev_unlock(hdev);
        hci_dev_put(hdev);
 
        return err;
@@ -1432,33 +1427,29 @@ static void iso_conn_ready(struct iso_conn *conn)
        struct sock *parent;
        struct sock *sk = conn->sk;
        struct hci_ev_le_big_sync_estabilished *ev;
+       struct hci_conn *hcon;
 
        BT_DBG("conn %p", conn);
 
        if (sk) {
                iso_sock_ready(conn->sk);
        } else {
-               iso_conn_lock(conn);
-
-               if (!conn->hcon) {
-                       iso_conn_unlock(conn);
+               hcon = conn->hcon;
+               if (!hcon)
                        return;
-               }
 
-               ev = hci_recv_event_data(conn->hcon->hdev,
+               ev = hci_recv_event_data(hcon->hdev,
                                         HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
                if (ev)
-                       parent = iso_get_sock_listen(&conn->hcon->src,
-                                                    &conn->hcon->dst,
+                       parent = iso_get_sock_listen(&hcon->src,
+                                                    &hcon->dst,
                                                     iso_match_big, ev);
                else
-                       parent = iso_get_sock_listen(&conn->hcon->src,
+                       parent = iso_get_sock_listen(&hcon->src,
                                                     BDADDR_ANY, NULL, NULL);
 
-               if (!parent) {
-                       iso_conn_unlock(conn);
+               if (!parent)
                        return;
-               }
 
                lock_sock(parent);
 
@@ -1466,30 +1457,29 @@ static void iso_conn_ready(struct iso_conn *conn)
                                    BTPROTO_ISO, GFP_ATOMIC, 0);
                if (!sk) {
                        release_sock(parent);
-                       iso_conn_unlock(conn);
                        return;
                }
 
                iso_sock_init(sk, parent);
 
-               bacpy(&iso_pi(sk)->src, &conn->hcon->src);
-               iso_pi(sk)->src_type = conn->hcon->src_type;
+               bacpy(&iso_pi(sk)->src, &hcon->src);
+               iso_pi(sk)->src_type = hcon->src_type;
 
                /* If hcon has no destination address (BDADDR_ANY) it means it
                 * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we need to
                 * initialize using the parent socket destination address.
                 */
-               if (!bacmp(&conn->hcon->dst, BDADDR_ANY)) {
-                       bacpy(&conn->hcon->dst, &iso_pi(parent)->dst);
-                       conn->hcon->dst_type = iso_pi(parent)->dst_type;
-                       conn->hcon->sync_handle = iso_pi(parent)->sync_handle;
+               if (!bacmp(&hcon->dst, BDADDR_ANY)) {
+                       bacpy(&hcon->dst, &iso_pi(parent)->dst);
+                       hcon->dst_type = iso_pi(parent)->dst_type;
+                       hcon->sync_handle = iso_pi(parent)->sync_handle;
                }
 
-               bacpy(&iso_pi(sk)->dst, &conn->hcon->dst);
-               iso_pi(sk)->dst_type = conn->hcon->dst_type;
+               bacpy(&iso_pi(sk)->dst, &hcon->dst);
+               iso_pi(sk)->dst_type = hcon->dst_type;
 
-               hci_conn_hold(conn->hcon);
-               __iso_chan_add(conn, sk, parent);
+               hci_conn_hold(hcon);
+               iso_chan_add(conn, sk, parent);
 
                if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
                        sk->sk_state = BT_CONNECT2;
@@ -1500,8 +1490,6 @@ static void iso_conn_ready(struct iso_conn *conn)
                parent->sk_data_ready(parent);
 
                release_sock(parent);
-
-               iso_conn_unlock(conn);
        }
 }
 
index 6a8b7e84293dfd436af59a433f4d82e92497867e..bdf978605d5a85bcbee1c0db1a76065e31a6096e 100644 (file)
@@ -27,7 +27,7 @@ struct mgmt_mesh_tx {
        struct sock *sk;
        u8 handle;
        u8 instance;
-       u8 param[sizeof(struct mgmt_cp_mesh_send) + 29];
+       u8 param[sizeof(struct mgmt_cp_mesh_send) + 31];
 };
 
 struct mgmt_pending_cmd {
index 21e24da4847f05a96145815e76e19c3e543a46f0..4397e14ff560fd1ca954bc2fdc08639f6988019c 100644 (file)
@@ -391,6 +391,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
            addr->sa_family != AF_BLUETOOTH)
                return -EINVAL;
 
+       sock_hold(sk);
        lock_sock(sk);
 
        if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
@@ -410,14 +411,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
        d->sec_level = rfcomm_pi(sk)->sec_level;
        d->role_switch = rfcomm_pi(sk)->role_switch;
 
+       /* Drop sock lock to avoid potential deadlock with the RFCOMM lock */
+       release_sock(sk);
        err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr,
                              sa->rc_channel);
-       if (!err)
+       lock_sock(sk);
+       if (!err && !sock_flag(sk, SOCK_ZAPPED))
                err = bt_sock_wait_state(sk, BT_CONNECTED,
                                sock_sndtimeo(sk, flags & O_NONBLOCK));
 
 done:
        release_sock(sk);
+       sock_put(sk);
        return err;
 }
 
index f20f4373ff408ffaca8e9337d4bab3a31711b5f0..9554abcfd5b4ed8a370360ec9b37f0219092c0e9 100644 (file)
@@ -871,6 +871,7 @@ static unsigned int ip_sabotage_in(void *priv,
        if (nf_bridge && !nf_bridge->in_prerouting &&
            !netif_is_l3_master(skb->dev) &&
            !netif_is_l3_slave(skb->dev)) {
+               nf_bridge_info_free(skb);
                state->okfn(state->net, state->sk, skb);
                return NF_STOLEN;
        }
index 608f8c24ae46b60722904eae1dd0dff23b91c571..fc81d77724a1310e9caebfbfb125f1f61de00e13 100644 (file)
@@ -140,7 +140,7 @@ struct isotp_sock {
        canid_t rxid;
        ktime_t tx_gap;
        ktime_t lastrxcf_tstamp;
-       struct hrtimer rxtimer, txtimer;
+       struct hrtimer rxtimer, txtimer, txfrtimer;
        struct can_isotp_options opt;
        struct can_isotp_fc_options rxfc, txfc;
        struct can_isotp_ll_options ll;
@@ -871,7 +871,7 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
        }
 
        /* start timer to send next consecutive frame with correct delay */
-       hrtimer_start(&so->txtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
+       hrtimer_start(&so->txfrtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
 }
 
 static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
@@ -879,49 +879,39 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
        struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
                                             txtimer);
        struct sock *sk = &so->sk;
-       enum hrtimer_restart restart = HRTIMER_NORESTART;
 
-       switch (so->tx.state) {
-       case ISOTP_SENDING:
-
-               /* cfecho should be consumed by isotp_rcv_echo() here */
-               if (!so->cfecho) {
-                       /* start timeout for unlikely lost echo skb */
-                       hrtimer_set_expires(&so->txtimer,
-                                           ktime_add(ktime_get(),
-                                                     ktime_set(ISOTP_ECHO_TIMEOUT, 0)));
-                       restart = HRTIMER_RESTART;
+       /* don't handle timeouts in IDLE state */
+       if (so->tx.state == ISOTP_IDLE)
+               return HRTIMER_NORESTART;
 
-                       /* push out the next consecutive frame */
-                       isotp_send_cframe(so);
-                       break;
-               }
+       /* we did not get any flow control or echo frame in time */
 
-               /* cfecho has not been cleared in isotp_rcv_echo() */
-               pr_notice_once("can-isotp: cfecho %08X timeout\n", so->cfecho);
-               fallthrough;
+       /* report 'communication error on send' */
+       sk->sk_err = ECOMM;
+       if (!sock_flag(sk, SOCK_DEAD))
+               sk_error_report(sk);
 
-       case ISOTP_WAIT_FC:
-       case ISOTP_WAIT_FIRST_FC:
+       /* reset tx state */
+       so->tx.state = ISOTP_IDLE;
+       wake_up_interruptible(&so->wait);
 
-               /* we did not get any flow control frame in time */
+       return HRTIMER_NORESTART;
+}
 
-               /* report 'communication error on send' */
-               sk->sk_err = ECOMM;
-               if (!sock_flag(sk, SOCK_DEAD))
-                       sk_error_report(sk);
+static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer)
+{
+       struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
+                                            txfrtimer);
 
-               /* reset tx state */
-               so->tx.state = ISOTP_IDLE;
-               wake_up_interruptible(&so->wait);
-               break;
+       /* start echo timeout handling and cover below protocol error */
+       hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
+                     HRTIMER_MODE_REL_SOFT);
 
-       default:
-               WARN_ONCE(1, "can-isotp: tx timer state %08X cfecho %08X\n",
-                         so->tx.state, so->cfecho);
-       }
+       /* cfecho should be consumed by isotp_rcv_echo() here */
+       if (so->tx.state == ISOTP_SENDING && !so->cfecho)
+               isotp_send_cframe(so);
 
-       return restart;
+       return HRTIMER_NORESTART;
 }
 
 static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
@@ -1162,6 +1152,10 @@ static int isotp_release(struct socket *sock)
        /* wait for complete transmission of current pdu */
        wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
 
+       /* force state machines to be idle also when a signal occurred */
+       so->tx.state = ISOTP_IDLE;
+       so->rx.state = ISOTP_IDLE;
+
        spin_lock(&isotp_notifier_lock);
        while (isotp_busy_notifier == so) {
                spin_unlock(&isotp_notifier_lock);
@@ -1194,6 +1188,7 @@ static int isotp_release(struct socket *sock)
                }
        }
 
+       hrtimer_cancel(&so->txfrtimer);
        hrtimer_cancel(&so->txtimer);
        hrtimer_cancel(&so->rxtimer);
 
@@ -1597,6 +1592,8 @@ static int isotp_init(struct sock *sk)
        so->rxtimer.function = isotp_rx_timer_handler;
        hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
        so->txtimer.function = isotp_tx_timer_handler;
+       hrtimer_init(&so->txfrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
+       so->txfrtimer.function = isotp_txfr_timer_handler;
 
        init_waitqueue_head(&so->wait);
        spin_lock_init(&so->rx_lock);
index 5c722b55fe237f0ee09f2958633fce060ed4a3ca..fce9b9ebf13f668584c26bda3be121bf227baa12 100644 (file)
@@ -1092,10 +1092,6 @@ static bool j1939_session_deactivate(struct j1939_session *session)
        bool active;
 
        j1939_session_list_lock(priv);
-       /* This function should be called with a session ref-count of at
-        * least 2.
-        */
-       WARN_ON_ONCE(kref_read(&session->kref) < 2);
        active = j1939_session_deactivate_locked(session);
        j1939_session_list_unlock(priv);
 
index 81071cdb03010193bb0e90086659fab6d9aea5bb..ba86782ba8bb3cb9c1d4234016ec6c030449eb6c 100644 (file)
@@ -132,8 +132,8 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
                return;
 
        /* make sure to not pass oversized frames to the socket */
-       if ((can_is_canfd_skb(oskb) && !ro->fd_frames && !ro->xl_frames) ||
-           (can_is_canxl_skb(oskb) && !ro->xl_frames))
+       if ((!ro->fd_frames && can_is_canfd_skb(oskb)) ||
+           (!ro->xl_frames && can_is_canxl_skb(oskb)))
                return;
 
        /* eliminate multiple filter matches for the same skb */
@@ -670,6 +670,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                if (copy_from_sockptr(&ro->fd_frames, optval, optlen))
                        return -EFAULT;
 
+               /* Enabling CAN XL includes CAN FD */
+               if (ro->xl_frames && !ro->fd_frames) {
+                       ro->fd_frames = ro->xl_frames;
+                       return -EINVAL;
+               }
                break;
 
        case CAN_RAW_XL_FRAMES:
@@ -679,6 +684,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                if (copy_from_sockptr(&ro->xl_frames, optval, optlen))
                        return -EFAULT;
 
+               /* Enabling CAN XL includes CAN FD */
+               if (ro->xl_frames)
+                       ro->fd_frames = ro->xl_frames;
                break;
 
        case CAN_RAW_JOIN_FILTERS:
@@ -786,6 +794,25 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
        return 0;
 }
 
+static bool raw_bad_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu)
+{
+       /* Classical CAN -> no checks for flags and device capabilities */
+       if (can_is_can_skb(skb))
+               return false;
+
+       /* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */
+       if (ro->fd_frames && can_is_canfd_skb(skb) &&
+           (mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu)))
+               return false;
+
+       /* CAN XL -> needs to be enabled and a CAN XL device */
+       if (ro->xl_frames && can_is_canxl_skb(skb) &&
+           can_is_canxl_dev_mtu(mtu))
+               return false;
+
+       return true;
+}
+
 static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 {
        struct sock *sk = sock->sk;
@@ -833,20 +860,8 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
                goto free_skb;
 
        err = -EINVAL;
-       if (ro->xl_frames && can_is_canxl_dev_mtu(dev->mtu)) {
-               /* CAN XL, CAN FD and Classical CAN */
-               if (!can_is_canxl_skb(skb) && !can_is_canfd_skb(skb) &&
-                   !can_is_can_skb(skb))
-                       goto free_skb;
-       } else if (ro->fd_frames && dev->mtu == CANFD_MTU) {
-               /* CAN FD and Classical CAN */
-               if (!can_is_canfd_skb(skb) && !can_is_can_skb(skb))
-                       goto free_skb;
-       } else {
-               /* Classical CAN */
-               if (!can_is_can_skb(skb))
-                       goto free_skb;
-       }
+       if (raw_bad_txframe(ro, skb, dev->mtu))
+               goto free_skb;
 
        sockcm_init(&sockc, sk);
        if (msg->msg_controllen) {
index 506f83d715f873c9bc3727e28ace71e00fa79d2f..4bac7ea6e0256542429b630b3cb50a1b4cf4ae06 100644 (file)
@@ -162,6 +162,15 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
        struct sk_buff *lp;
        int segs;
 
+       /* Do not splice page pool based packets w/ non-page pool
+        * packets. This can result in reference count issues as page
+        * pool pages will not decrement the reference count and will
+        * instead be immediately returned to the pool or have frag
+        * count decremented.
+        */
+       if (p->pp_recycle != skb->pp_recycle)
+               return -ETOOMANYREFS;
+
        /* pairs with WRITE_ONCE() in netif_set_gro_max_size() */
        gro_max_size = READ_ONCE(p->dev->gro_max_size);
 
index 5581d22cc19127af07b57efb518e9e412ada6f43..078a0a420c8a7a7c3b5c4f3c2e752c5db1519540 100644 (file)
@@ -137,12 +137,12 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
                return 0;
 
        if (ops->id && ops->size) {
-cleanup:
                ng = rcu_dereference_protected(net->gen,
                                               lockdep_is_held(&pernet_ops_rwsem));
                ng->ptr[*ops->id] = NULL;
        }
 
+cleanup:
        kfree(data);
 
 out:
index 4a0eb5593275c868eaf4886ac7d05a5d19a7cd59..a31ff4d83ecc49e0c600df9c28007990f96735e4 100644 (file)
@@ -4100,7 +4100,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
 
        skb_shinfo(skb)->frag_list = NULL;
 
-       do {
+       while (list_skb) {
                nskb = list_skb;
                list_skb = list_skb->next;
 
@@ -4146,8 +4146,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
                if (skb_needs_linearize(nskb, features) &&
                    __skb_linearize(nskb))
                        goto err_linearize;
-
-       } while (list_skb);
+       }
 
        skb->truesize = skb->truesize - delta_truesize;
        skb->data_len = skb->data_len - delta_len;
index 22fa2c5bc6ec9652c4e4a904990a5b7635c20cb6..a68a7290a3b2b1f618960a0ac91961418ee13449 100644 (file)
@@ -1569,15 +1569,16 @@ void sock_map_unhash(struct sock *sk)
        psock = sk_psock(sk);
        if (unlikely(!psock)) {
                rcu_read_unlock();
-               if (sk->sk_prot->unhash)
-                       sk->sk_prot->unhash(sk);
-               return;
+               saved_unhash = READ_ONCE(sk->sk_prot)->unhash;
+       } else {
+               saved_unhash = psock->saved_unhash;
+               sock_map_remove_links(sk, psock);
+               rcu_read_unlock();
        }
-
-       saved_unhash = psock->saved_unhash;
-       sock_map_remove_links(sk, psock);
-       rcu_read_unlock();
-       saved_unhash(sk);
+       if (WARN_ON_ONCE(saved_unhash == sock_map_unhash))
+               return;
+       if (saved_unhash)
+               saved_unhash(sk);
 }
 EXPORT_SYMBOL_GPL(sock_map_unhash);
 
@@ -1590,17 +1591,18 @@ void sock_map_destroy(struct sock *sk)
        psock = sk_psock_get(sk);
        if (unlikely(!psock)) {
                rcu_read_unlock();
-               if (sk->sk_prot->destroy)
-                       sk->sk_prot->destroy(sk);
-               return;
+               saved_destroy = READ_ONCE(sk->sk_prot)->destroy;
+       } else {
+               saved_destroy = psock->saved_destroy;
+               sock_map_remove_links(sk, psock);
+               rcu_read_unlock();
+               sk_psock_stop(psock);
+               sk_psock_put(sk, psock);
        }
-
-       saved_destroy = psock->saved_destroy;
-       sock_map_remove_links(sk, psock);
-       rcu_read_unlock();
-       sk_psock_stop(psock);
-       sk_psock_put(sk, psock);
-       saved_destroy(sk);
+       if (WARN_ON_ONCE(saved_destroy == sock_map_destroy))
+               return;
+       if (saved_destroy)
+               saved_destroy(sk);
 }
 EXPORT_SYMBOL_GPL(sock_map_destroy);
 
@@ -1615,16 +1617,21 @@ void sock_map_close(struct sock *sk, long timeout)
        if (unlikely(!psock)) {
                rcu_read_unlock();
                release_sock(sk);
-               return sk->sk_prot->close(sk, timeout);
+               saved_close = READ_ONCE(sk->sk_prot)->close;
+       } else {
+               saved_close = psock->saved_close;
+               sock_map_remove_links(sk, psock);
+               rcu_read_unlock();
+               sk_psock_stop(psock);
+               release_sock(sk);
+               cancel_work_sync(&psock->work);
+               sk_psock_put(sk, psock);
        }
-
-       saved_close = psock->saved_close;
-       sock_map_remove_links(sk, psock);
-       rcu_read_unlock();
-       sk_psock_stop(psock);
-       release_sock(sk);
-       cancel_work_sync(&psock->work);
-       sk_psock_put(sk, psock);
+       /* Make sure we do not recurse. This is a bug.
+        * Leak the socket instead of crashing on a stack overflow.
+        */
+       if (WARN_ON_ONCE(saved_close == sock_map_close))
+               return;
        saved_close(sk, timeout);
 }
 EXPORT_SYMBOL_GPL(sock_map_close);
index ebe6145aed3f1a79d30d17cb221c55cdcee9134a..be260ab34e5801ab03ad7ad6306f6037ee5c5101 100644 (file)
@@ -122,10 +122,13 @@ rss_fill_reply(struct sk_buff *skb, const struct ethnl_req_info *req_base,
 {
        const struct rss_reply_data *data = RSS_REPDATA(reply_base);
 
-       if (nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc) ||
-           nla_put(skb, ETHTOOL_A_RSS_INDIR,
-                   sizeof(u32) * data->indir_size, data->indir_table) ||
-           nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey))
+       if ((data->hfunc &&
+            nla_put_u32(skb, ETHTOOL_A_RSS_HFUNC, data->hfunc)) ||
+           (data->indir_size &&
+            nla_put(skb, ETHTOOL_A_RSS_INDIR,
+                    sizeof(u32) * data->indir_size, data->indir_table)) ||
+           (data->hkey_size &&
+            nla_put(skb, ETHTOOL_A_RSS_HKEY, data->hkey_size, data->hkey)))
                return -EMSGSIZE;
 
        return 0;
index ce9ff3c62e84055393ca1ff98f1d2ae391978638..3bb890a40ed73626acba8c22044d1c5f99c872e8 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/netlink.h>
 #include <linux/hash.h>
+#include <linux/nospec.h>
 
 #include <net/arp.h>
 #include <net/inet_dscp.h>
@@ -1022,6 +1023,7 @@ bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi)
                if (type > RTAX_MAX)
                        return false;
 
+               type = array_index_nospec(type, RTAX_MAX + 1);
                if (type == RTAX_CC_ALGO) {
                        char tmp[TCP_CA_NAME_MAX];
                        bool ecn_ca = false;
index 24a38b56fab9e9d7d893e23b30d26e275359ec70..f58d73888638b916904083af542a1e921fc0467a 100644 (file)
@@ -650,8 +650,20 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        spin_lock(lock);
        if (osk) {
                WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
-               ret = sk_nulls_del_node_init_rcu(osk);
-       } else if (found_dup_sk) {
+               ret = sk_hashed(osk);
+               if (ret) {
+                       /* Before deleting the node, we insert a new one to make
+                        * sure that the look-up-sk process would not miss either
+                        * of them and that at least one node would exist in ehash
+                        * table all the time. Otherwise there's a tiny chance
+                        * that lookup process could find nothing in ehash table.
+                        */
+                       __sk_nulls_add_node_tail_rcu(sk, list);
+                       sk_nulls_del_node_init_rcu(osk);
+               }
+               goto unlock;
+       }
+       if (found_dup_sk) {
                *found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
                if (*found_dup_sk)
                        ret = false;
@@ -660,6 +672,7 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        if (ret)
                __sk_nulls_add_node_rcu(sk, list);
 
+unlock:
        spin_unlock(lock);
 
        return ret;
index 1d77d992e6e77f7d96bd061be6dbb802c2566b3f..beed32fff484183f21e9d20834d67474e4565076 100644 (file)
@@ -91,10 +91,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
 }
 EXPORT_SYMBOL_GPL(inet_twsk_put);
 
-static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
-                                  struct hlist_nulls_head *list)
+static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw,
+                                       struct hlist_nulls_head *list)
 {
-       hlist_nulls_add_head_rcu(&tw->tw_node, list);
+       hlist_nulls_add_tail_rcu(&tw->tw_node, list);
 }
 
 static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
@@ -147,7 +147,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 
        spin_lock(lock);
 
-       inet_twsk_add_node_rcu(tw, &ehead->chain);
+       inet_twsk_add_node_tail_rcu(tw, &ehead->chain);
 
        /* Step 3: Remove SK from hash chain */
        if (__sk_nulls_del_node_init_rcu(sk))
index 7fcfdfd8f9def057cbe163b8b395cd2379d98152..0e3ee1532848c8f49e0a342b7c8ecc1c27684e67 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <linux/netlink.h>
+#include <linux/nospec.h>
 #include <linux/rtnetlink.h>
 #include <linux/types.h>
 #include <net/ip.h>
@@ -25,6 +26,7 @@ static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
                        return -EINVAL;
                }
 
+               type = array_index_nospec(type, RTAX_MAX + 1);
                if (type == RTAX_CC_ALGO) {
                        char tmp[TCP_CA_NAME_MAX];
 
index c567d5e8053e0c2668196d8a0c9afc6494d8f972..33f559f491c8cfd1a66a6f58c7b4a8a19ffa6b4f 100644 (file)
@@ -435,6 +435,7 @@ void tcp_init_sock(struct sock *sk)
 
        /* There's a bubble in the pipe until at least the first ACK. */
        tp->app_limited = ~0U;
+       tp->rate_app_limited = 1;
 
        /* See draft-stevens-tcpca-spec-01 for discussion of the
         * initialization of these values.
@@ -3178,6 +3179,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->plb_rehash = 0;
        /* There's a bubble in the pipe until at least the first ACK. */
        tp->app_limited = ~0U;
+       tp->rate_app_limited = 1;
        tp->rack.mstamp = 0;
        tp->rack.advanced = 0;
        tp->rack.reo_wnd_steps = 1;
index 94aad3870c5fcce9e0140a4547631c50ec49e219..cf26d65ca3893d5fc1b9c4fdc7d4e85316c1fc76 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/bpf.h>
 #include <linux/init.h>
 #include <linux/wait.h>
+#include <linux/util_macros.h>
 
 #include <net/inet_common.h>
 #include <net/tls.h>
@@ -639,10 +640,9 @@ EXPORT_SYMBOL_GPL(tcp_bpf_update_proto);
  */
 void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)
 {
-       int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
        struct proto *prot = newsk->sk_prot;
 
-       if (prot == &tcp_bpf_prots[family][TCP_BPF_BASE])
+       if (is_insidevar(prot, tcp_bpf_prots))
                newsk->sk_prot = sk->sk_prot_creator;
 }
 #endif /* CONFIG_BPF_SYSCALL */
index 05b6077b9f2c3543a5aaeed72d6a5e7b99edd1ec..2aa442128630e5fbc48d72c2f09f7eba475cc62c 100644 (file)
@@ -139,7 +139,7 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
        if (sk->sk_socket)
                clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
 
-       err = -EINVAL;
+       err = -ENOTCONN;
        if (!ulp_ops->clone && sk->sk_state == TCP_LISTEN)
                goto out_err;
 
index f7a84a4acffcb593d6a284d1bba0bcfb34c1bf1a..faa47f9ea73a68cc6fd0b38bd6f78510f0558101 100644 (file)
@@ -3127,17 +3127,17 @@ static void add_v4_addrs(struct inet6_dev *idev)
                offset = sizeof(struct in6_addr) - 4;
        memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
 
-       if (idev->dev->flags&IFF_POINTOPOINT) {
+       if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
+               scope = IPV6_ADDR_COMPATv4;
+               plen = 96;
+               pflags |= RTF_NONEXTHOP;
+       } else {
                if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE)
                        return;
 
                addr.s6_addr32[0] = htonl(0xfe800000);
                scope = IFA_LINK;
                plen = 64;
-       } else {
-               scope = IPV6_ADDR_COMPATv4;
-               plen = 96;
-               pflags |= RTF_NONEXTHOP;
        }
 
        if (addr.s6_addr32[3]) {
@@ -3447,6 +3447,30 @@ static void addrconf_gre_config(struct net_device *dev)
 }
 #endif
 
+static void addrconf_init_auto_addrs(struct net_device *dev)
+{
+       switch (dev->type) {
+#if IS_ENABLED(CONFIG_IPV6_SIT)
+       case ARPHRD_SIT:
+               addrconf_sit_config(dev);
+               break;
+#endif
+#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
+       case ARPHRD_IP6GRE:
+       case ARPHRD_IPGRE:
+               addrconf_gre_config(dev);
+               break;
+#endif
+       case ARPHRD_LOOPBACK:
+               init_loopback(dev);
+               break;
+
+       default:
+               addrconf_dev_config(dev);
+               break;
+       }
+}
+
 static int fixup_permanent_addr(struct net *net,
                                struct inet6_dev *idev,
                                struct inet6_ifaddr *ifp)
@@ -3615,26 +3639,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                        run_pending = 1;
                }
 
-               switch (dev->type) {
-#if IS_ENABLED(CONFIG_IPV6_SIT)
-               case ARPHRD_SIT:
-                       addrconf_sit_config(dev);
-                       break;
-#endif
-#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE)
-               case ARPHRD_IP6GRE:
-               case ARPHRD_IPGRE:
-                       addrconf_gre_config(dev);
-                       break;
-#endif
-               case ARPHRD_LOOPBACK:
-                       init_loopback(dev);
-                       break;
-
-               default:
-                       addrconf_dev_config(dev);
-                       break;
-               }
+               addrconf_init_auto_addrs(dev);
 
                if (!IS_ERR_OR_NULL(idev)) {
                        if (run_pending)
@@ -6397,7 +6402,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
 
                        if (idev->cnf.addr_gen_mode != new_val) {
                                idev->cnf.addr_gen_mode = new_val;
-                               addrconf_dev_config(idev->dev);
+                               addrconf_init_auto_addrs(idev->dev);
                        }
                } else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
                        struct net_device *dev;
@@ -6408,7 +6413,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
                                if (idev &&
                                    idev->cnf.addr_gen_mode != new_val) {
                                        idev->cnf.addr_gen_mode = new_val;
-                                       addrconf_dev_config(idev->dev);
+                                       addrconf_init_auto_addrs(idev->dev);
                                }
                        }
                }
index 60fd91bb5171c70f437b73aa81ccc6ce9e5e2d98..c314fdde0097c8c8dc30ab1dc43cbc2905c0f5d1 100644 (file)
@@ -547,7 +547,20 @@ int ip6_forward(struct sk_buff *skb)
            pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
                int proxied = ip6_forward_proxy_check(skb);
                if (proxied > 0) {
-                       hdr->hop_limit--;
+                       /* It's tempting to decrease the hop limit
+                        * here by 1, as we do at the end of the
+                        * function too.
+                        *
+                        * But that would be incorrect, as proxying is
+                        * not forwarding.  The ip6_input function
+                        * will handle this packet locally, and it
+                        * depends on the hop limit being unchanged.
+                        *
+                        * One example is the NDP hop limit, that
+                        * always has to stay 255, but other would be
+                        * similar checks around RA packets, where the
+                        * user can even change the desired limit.
+                        */
                        return ip6_input(skb);
                } else if (proxied < 0) {
                        __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
index 9a1415fe3fa78bf419efc86c4a6ccfc7e0f0c78b..03608d3ded4b83d1e59e064e482f54cffcdf5240 100644 (file)
@@ -104,9 +104,9 @@ static struct workqueue_struct *l2tp_wq;
 /* per-net private data for this module */
 static unsigned int l2tp_net_id;
 struct l2tp_net {
-       struct list_head l2tp_tunnel_list;
-       /* Lock for write access to l2tp_tunnel_list */
-       spinlock_t l2tp_tunnel_list_lock;
+       /* Lock for write access to l2tp_tunnel_idr */
+       spinlock_t l2tp_tunnel_idr_lock;
+       struct idr l2tp_tunnel_idr;
        struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2];
        /* Lock for write access to l2tp_session_hlist */
        spinlock_t l2tp_session_hlist_lock;
@@ -208,13 +208,10 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
        struct l2tp_tunnel *tunnel;
 
        rcu_read_lock_bh();
-       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-               if (tunnel->tunnel_id == tunnel_id &&
-                   refcount_inc_not_zero(&tunnel->ref_count)) {
-                       rcu_read_unlock_bh();
-
-                       return tunnel;
-               }
+       tunnel = idr_find(&pn->l2tp_tunnel_idr, tunnel_id);
+       if (tunnel && refcount_inc_not_zero(&tunnel->ref_count)) {
+               rcu_read_unlock_bh();
+               return tunnel;
        }
        rcu_read_unlock_bh();
 
@@ -224,13 +221,14 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_get);
 
 struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth)
 {
-       const struct l2tp_net *pn = l2tp_pernet(net);
+       struct l2tp_net *pn = l2tp_pernet(net);
+       unsigned long tunnel_id, tmp;
        struct l2tp_tunnel *tunnel;
        int count = 0;
 
        rcu_read_lock_bh();
-       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-               if (++count > nth &&
+       idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
+               if (tunnel && ++count > nth &&
                    refcount_inc_not_zero(&tunnel->ref_count)) {
                        rcu_read_unlock_bh();
                        return tunnel;
@@ -1043,7 +1041,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
        IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
        nf_reset_ct(skb);
 
-       bh_lock_sock(sk);
+       bh_lock_sock_nested(sk);
        if (sock_owned_by_user(sk)) {
                kfree_skb(skb);
                ret = NET_XMIT_DROP;
@@ -1227,6 +1225,15 @@ static void l2tp_udp_encap_destroy(struct sock *sk)
                l2tp_tunnel_delete(tunnel);
 }
 
+static void l2tp_tunnel_remove(struct net *net, struct l2tp_tunnel *tunnel)
+{
+       struct l2tp_net *pn = l2tp_pernet(net);
+
+       spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
+       idr_remove(&pn->l2tp_tunnel_idr, tunnel->tunnel_id);
+       spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
+}
+
 /* Workqueue tunnel deletion function */
 static void l2tp_tunnel_del_work(struct work_struct *work)
 {
@@ -1234,7 +1241,6 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
                                                  del_work);
        struct sock *sk = tunnel->sock;
        struct socket *sock = sk->sk_socket;
-       struct l2tp_net *pn;
 
        l2tp_tunnel_closeall(tunnel);
 
@@ -1248,12 +1254,7 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
                }
        }
 
-       /* Remove the tunnel struct from the tunnel list */
-       pn = l2tp_pernet(tunnel->l2tp_net);
-       spin_lock_bh(&pn->l2tp_tunnel_list_lock);
-       list_del_rcu(&tunnel->list);
-       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-
+       l2tp_tunnel_remove(tunnel->l2tp_net, tunnel);
        /* drop initial ref */
        l2tp_tunnel_dec_refcount(tunnel);
 
@@ -1384,8 +1385,6 @@ out:
        return err;
 }
 
-static struct lock_class_key l2tp_socket_class;
-
 int l2tp_tunnel_create(int fd, int version, u32 tunnel_id, u32 peer_tunnel_id,
                       struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
 {
@@ -1455,12 +1454,19 @@ static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
 int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
                         struct l2tp_tunnel_cfg *cfg)
 {
-       struct l2tp_tunnel *tunnel_walk;
-       struct l2tp_net *pn;
+       struct l2tp_net *pn = l2tp_pernet(net);
+       u32 tunnel_id = tunnel->tunnel_id;
        struct socket *sock;
        struct sock *sk;
        int ret;
 
+       spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
+       ret = idr_alloc_u32(&pn->l2tp_tunnel_idr, NULL, &tunnel_id, tunnel_id,
+                           GFP_ATOMIC);
+       spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
+       if (ret)
+               return ret == -ENOSPC ? -EEXIST : ret;
+
        if (tunnel->fd < 0) {
                ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
                                              tunnel->peer_tunnel_id, cfg,
@@ -1474,6 +1480,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
        }
 
        sk = sock->sk;
+       lock_sock(sk);
        write_lock_bh(&sk->sk_callback_lock);
        ret = l2tp_validate_socket(sk, net, tunnel->encap);
        if (ret < 0)
@@ -1481,24 +1488,6 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
        rcu_assign_sk_user_data(sk, tunnel);
        write_unlock_bh(&sk->sk_callback_lock);
 
-       tunnel->l2tp_net = net;
-       pn = l2tp_pernet(net);
-
-       sock_hold(sk);
-       tunnel->sock = sk;
-
-       spin_lock_bh(&pn->l2tp_tunnel_list_lock);
-       list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) {
-               if (tunnel_walk->tunnel_id == tunnel->tunnel_id) {
-                       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-                       sock_put(sk);
-                       ret = -EEXIST;
-                       goto err_sock;
-               }
-       }
-       list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
-       spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-
        if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
                struct udp_tunnel_sock_cfg udp_cfg = {
                        .sk_user_data = tunnel,
@@ -1512,9 +1501,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 
        tunnel->old_sk_destruct = sk->sk_destruct;
        sk->sk_destruct = &l2tp_tunnel_destruct;
-       lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class,
-                                  "l2tp_sock");
        sk->sk_allocation = GFP_ATOMIC;
+       release_sock(sk);
+
+       sock_hold(sk);
+       tunnel->sock = sk;
+       tunnel->l2tp_net = net;
+
+       spin_lock_bh(&pn->l2tp_tunnel_idr_lock);
+       idr_replace(&pn->l2tp_tunnel_idr, tunnel, tunnel->tunnel_id);
+       spin_unlock_bh(&pn->l2tp_tunnel_idr_lock);
 
        trace_register_tunnel(tunnel);
 
@@ -1523,17 +1519,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 
        return 0;
 
-err_sock:
-       write_lock_bh(&sk->sk_callback_lock);
-       rcu_assign_sk_user_data(sk, NULL);
 err_inval_sock:
        write_unlock_bh(&sk->sk_callback_lock);
+       release_sock(sk);
 
        if (tunnel->fd < 0)
                sock_release(sock);
        else
                sockfd_put(sock);
 err:
+       l2tp_tunnel_remove(net, tunnel);
        return ret;
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
@@ -1647,8 +1642,8 @@ static __net_init int l2tp_init_net(struct net *net)
        struct l2tp_net *pn = net_generic(net, l2tp_net_id);
        int hash;
 
-       INIT_LIST_HEAD(&pn->l2tp_tunnel_list);
-       spin_lock_init(&pn->l2tp_tunnel_list_lock);
+       idr_init(&pn->l2tp_tunnel_idr);
+       spin_lock_init(&pn->l2tp_tunnel_idr_lock);
 
        for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
                INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]);
@@ -1662,11 +1657,13 @@ static __net_exit void l2tp_exit_net(struct net *net)
 {
        struct l2tp_net *pn = l2tp_pernet(net);
        struct l2tp_tunnel *tunnel = NULL;
+       unsigned long tunnel_id, tmp;
        int hash;
 
        rcu_read_lock_bh();
-       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-               l2tp_tunnel_delete(tunnel);
+       idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
+               if (tunnel)
+                       l2tp_tunnel_delete(tunnel);
        }
        rcu_read_unlock_bh();
 
@@ -1676,6 +1673,7 @@ static __net_exit void l2tp_exit_net(struct net *net)
 
        for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++)
                WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash]));
+       idr_destroy(&pn->l2tp_tunnel_idr);
 }
 
 static struct pernet_operations l2tp_net_ops = {
index 9c40f8d3bce8cbb3bad8710b8f889a4ed02b3a21..f9514bacbd4a184d677226ce65fd7a0635fcb5d1 100644 (file)
@@ -491,7 +491,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
 {
        struct tid_ampdu_tx *tid_tx;
        struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ieee80211_sub_if_data *sdata;
        struct ieee80211_ampdu_params params = {
                .sta = &sta->sta,
                .action = IEEE80211_AMPDU_TX_START,
@@ -511,8 +511,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
         */
        clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
 
-       ieee80211_agg_stop_txq(sta, tid);
-
        /*
         * Make sure no packets are being processed. This ensures that
         * we have a valid starting sequence number and that in-flight
@@ -521,6 +519,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
         */
        synchronize_net();
 
+       sdata = sta->sdata;
        params.ssn = sta->tid_seq[tid] >> 4;
        ret = drv_ampdu_action(local, sdata, &params);
        tid_tx->ssn = params.ssn;
@@ -534,6 +533,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
                 */
                set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state);
        } else if (ret) {
+               if (!sdata)
+                       return;
+
                ht_dbg(sdata,
                       "BA request denied - HW unavailable for %pM tid %d\n",
                       sta->sta.addr, tid);
index 8f9a2ab502b38e9f95ae954b3d087acd7e9a1456..672eff6f5d328de2d6e09cf9909f5e1923dbc8a2 100644 (file)
@@ -147,6 +147,7 @@ static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata,
        link_conf->bssid_index = 0;
        link_conf->nontransmitted = false;
        link_conf->ema_ap = false;
+       link_conf->bssid_indicator = 0;
 
        if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev)
                return -EINVAL;
@@ -1511,6 +1512,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
        kfree(link_conf->ftmr_params);
        link_conf->ftmr_params = NULL;
 
+       sdata->vif.mbssid_tx_vif = NULL;
+       link_conf->bssid_index = 0;
+       link_conf->nontransmitted = false;
+       link_conf->ema_ap = false;
+       link_conf->bssid_indicator = 0;
+
        __sta_info_flush(sdata, true);
        ieee80211_free_keys(sdata, true);
 
index 7a3d7893e19d6a607c0c1a20ecec6683c6d51b38..f1914bf39f0e61f37c623eccaf9e62d3ab39b528 100644 (file)
@@ -167,7 +167,7 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
                        continue;
                txqi = to_txq_info(sta->sta.txq[i]);
                p += scnprintf(p, bufsz + buf - p,
-                              "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s)\n",
+                              "%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s%s)\n",
                               txqi->txq.tid,
                               txqi->txq.ac,
                               txqi->tin.backlog_bytes,
@@ -182,7 +182,8 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
                               txqi->flags,
                               test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ? "STOP" : "RUN",
                               test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags) ? " AMPDU" : "",
-                              test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags) ? " NO-AMSDU" : "");
+                              test_bit(IEEE80211_TXQ_NO_AMSDU, &txqi->flags) ? " NO-AMSDU" : "",
+                              test_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) ? " DIRTY" : "");
        }
 
        rcu_read_unlock();
index d737db4e07e2436de3b47ccb98be943ad7afc1c5..cfb09e4aed4d3e8abd47bb78e05fbbedf4f42df2 100644 (file)
@@ -392,6 +392,9 @@ int drv_ampdu_action(struct ieee80211_local *local,
 
        might_sleep();
 
+       if (!sdata)
+               return -EIO;
+
        sdata = get_bss_sdata(sdata);
        if (!check_sdata_in_driver(sdata))
                return -EIO;
index 809bad53e15b67d63c9d953aacc60e16f2fa57d6..5d13a3dfd3664bb3820b4a9baa42b23f087d95de 100644 (file)
@@ -1199,7 +1199,7 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
 
        /* In reconfig don't transmit now, but mark for waking later */
        if (local->in_reconfig) {
-               set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txq->flags);
+               set_bit(IEEE80211_TXQ_DIRTY, &txq->flags);
                return;
        }
 
index 83bc41346ae7fe110d5cfa164cf8f4276579fe26..5315ab750280278787e462f8a5861013d2c42f4d 100644 (file)
@@ -391,6 +391,37 @@ void ieee80211_ba_session_work(struct work_struct *work)
 
                tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
                if (!blocked && tid_tx) {
+                       struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
+                       struct ieee80211_sub_if_data *sdata =
+                               vif_to_sdata(txqi->txq.vif);
+                       struct fq *fq = &sdata->local->fq;
+
+                       spin_lock_bh(&fq->lock);
+
+                       /* Allow only frags to be dequeued */
+                       set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
+
+                       if (!skb_queue_empty(&txqi->frags)) {
+                               /* Fragmented Tx is ongoing, wait for it to
+                                * finish. Reschedule worker to retry later.
+                                */
+
+                               spin_unlock_bh(&fq->lock);
+                               spin_unlock_bh(&sta->lock);
+
+                               /* Give the task working on the txq a chance
+                                * to send out the queued frags
+                                */
+                               synchronize_net();
+
+                               mutex_unlock(&sta->ampdu_mlme.mtx);
+
+                               ieee80211_queue_work(&sdata->local->hw, work);
+                               return;
+                       }
+
+                       spin_unlock_bh(&fq->lock);
+
                        /*
                         * Assign it over to the normal tid_tx array
                         * where it "goes live".
index 63ff0d2524b6530bcd0b27649ecf4492d70ea10f..d16606e84e22de34e47945cd5f1376b2639c4b70 100644 (file)
@@ -838,7 +838,7 @@ enum txq_info_flags {
        IEEE80211_TXQ_STOP,
        IEEE80211_TXQ_AMPDU,
        IEEE80211_TXQ_NO_AMSDU,
-       IEEE80211_TXQ_STOP_NETIF_TX,
+       IEEE80211_TXQ_DIRTY,
 };
 
 /**
index d49a5906a94351f37644a3ccca4eba90379ee591..23ed13f150675d1ffa869796c857f5905fb8dae8 100644 (file)
@@ -364,7 +364,9 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
 
                        /* No support for VLAN with MLO yet */
                        if (iftype == NL80211_IFTYPE_AP_VLAN &&
-                           nsdata->wdev.use_4addr)
+                           sdata->wdev.use_4addr &&
+                           nsdata->vif.type == NL80211_IFTYPE_AP &&
+                           nsdata->vif.valid_links)
                                return -EOPNOTSUPP;
 
                        /*
@@ -2195,7 +2197,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
                ret = cfg80211_register_netdevice(ndev);
                if (ret) {
-                       ieee80211_if_free(ndev);
                        free_netdev(ndev);
                        return ret;
                }
index 7e3ab6e1b28f3d5c4547e97fbbabc42a2e83adbc..c6562a6d25035765a4c0d7cb353da894afbbbaed 100644 (file)
@@ -4049,6 +4049,58 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
 #undef CALL_RXH
 }
 
+static bool
+ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
+{
+       if (!sta->mlo)
+               return false;
+
+       return !!(sta->valid_links & BIT(link_id));
+}
+
+static bool ieee80211_rx_data_set_link(struct ieee80211_rx_data *rx,
+                                      u8 link_id)
+{
+       rx->link_id = link_id;
+       rx->link = rcu_dereference(rx->sdata->link[link_id]);
+
+       if (!rx->sta)
+               return rx->link;
+
+       if (!ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta, link_id))
+               return false;
+
+       rx->link_sta = rcu_dereference(rx->sta->link[link_id]);
+
+       return rx->link && rx->link_sta;
+}
+
+static bool ieee80211_rx_data_set_sta(struct ieee80211_rx_data *rx,
+                                     struct ieee80211_sta *pubsta,
+                                     int link_id)
+{
+       struct sta_info *sta;
+
+       sta = container_of(pubsta, struct sta_info, sta);
+
+       rx->link_id = link_id;
+       rx->sta = sta;
+
+       if (sta) {
+               rx->local = sta->sdata->local;
+               if (!rx->sdata)
+                       rx->sdata = sta->sdata;
+               rx->link_sta = &sta->deflink;
+       }
+
+       if (link_id < 0)
+               rx->link = &rx->sdata->deflink;
+       else if (!ieee80211_rx_data_set_link(rx, link_id))
+               return false;
+
+       return true;
+}
+
 /*
  * This function makes calls into the RX path, therefore
  * it has to be invoked under RCU read lock.
@@ -4057,16 +4109,19 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
 {
        struct sk_buff_head frames;
        struct ieee80211_rx_data rx = {
-               .sta = sta,
-               .sdata = sta->sdata,
-               .local = sta->local,
                /* This is OK -- must be QoS data frame */
                .security_idx = tid,
                .seqno_idx = tid,
-               .link_id = -1,
        };
        struct tid_ampdu_rx *tid_agg_rx;
-       u8 link_id;
+       int link_id = -1;
+
+       /* FIXME: statistics won't be right with this */
+       if (sta->sta.valid_links)
+               link_id = ffs(sta->sta.valid_links) - 1;
+
+       if (!ieee80211_rx_data_set_sta(&rx, &sta->sta, link_id))
+               return;
 
        tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
        if (!tid_agg_rx)
@@ -4086,10 +4141,6 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                };
                drv_event_callback(rx.local, rx.sdata, &event);
        }
-       /* FIXME: statistics won't be right with this */
-       link_id = sta->sta.valid_links ? ffs(sta->sta.valid_links) - 1 : 0;
-       rx.link = rcu_dereference(sta->sdata->link[link_id]);
-       rx.link_sta = rcu_dereference(sta->link[link_id]);
 
        ieee80211_rx_handlers(&rx, &frames);
 }
@@ -4105,7 +4156,6 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
                /* This is OK -- must be QoS data frame */
                .security_idx = tid,
                .seqno_idx = tid,
-               .link_id = -1,
        };
        int i, diff;
 
@@ -4116,10 +4166,8 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
 
        sta = container_of(pubsta, struct sta_info, sta);
 
-       rx.sta = sta;
-       rx.sdata = sta->sdata;
-       rx.link = &rx.sdata->deflink;
-       rx.local = sta->local;
+       if (!ieee80211_rx_data_set_sta(&rx, pubsta, -1))
+               return;
 
        rcu_read_lock();
        tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
@@ -4506,15 +4554,6 @@ void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata)
        mutex_unlock(&local->sta_mtx);
 }
 
-static bool
-ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
-{
-       if (!sta->mlo)
-               return false;
-
-       return !!(sta->valid_links & BIT(link_id));
-}
-
 static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
                              struct ieee80211_fast_rx *fast_rx,
                              int orig_len)
@@ -4625,7 +4664,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
        struct sk_buff *skb = rx->skb;
        struct ieee80211_hdr *hdr = (void *)skb->data;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-       struct sta_info *sta = rx->sta;
        int orig_len = skb->len;
        int hdrlen = ieee80211_hdrlen(hdr->frame_control);
        int snap_offs = hdrlen;
@@ -4637,7 +4675,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
                u8 da[ETH_ALEN];
                u8 sa[ETH_ALEN];
        } addrs __aligned(2);
-       struct link_sta_info *link_sta;
        struct ieee80211_sta_rx_stats *stats;
 
        /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
@@ -4740,18 +4777,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
  drop:
        dev_kfree_skb(skb);
 
-       if (rx->link_id >= 0) {
-               link_sta = rcu_dereference(sta->link[rx->link_id]);
-               if (!link_sta)
-                       return true;
-       } else {
-               link_sta = &sta->deflink;
-       }
-
        if (fast_rx->uses_rss)
-               stats = this_cpu_ptr(link_sta->pcpu_rx_stats);
+               stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats);
        else
-               stats = &link_sta->rx_stats;
+               stats = &rx->link_sta->rx_stats;
 
        stats->dropped++;
        return true;
@@ -4769,8 +4798,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
        struct ieee80211_local *local = rx->local;
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_hdr *hdr = (void *)skb->data;
-       struct link_sta_info *link_sta = NULL;
-       struct ieee80211_link_data *link;
+       struct link_sta_info *link_sta = rx->link_sta;
+       struct ieee80211_link_data *link = rx->link;
 
        rx->skb = skb;
 
@@ -4792,35 +4821,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
        if (!ieee80211_accept_frame(rx))
                return false;
 
-       if (rx->link_id >= 0) {
-               link = rcu_dereference(rx->sdata->link[rx->link_id]);
-
-               /* we might race link removal */
-               if (!link)
-                       return true;
-               rx->link = link;
-
-               if (rx->sta) {
-                       rx->link_sta =
-                               rcu_dereference(rx->sta->link[rx->link_id]);
-                       if (!rx->link_sta)
-                               return true;
-               }
-       } else {
-               if (rx->sta)
-                       rx->link_sta = &rx->sta->deflink;
-
-               rx->link = &sdata->deflink;
-       }
-
-       if (unlikely(!is_multicast_ether_addr(hdr->addr1) &&
-                    rx->link_id >= 0 && rx->sta && rx->sta->sta.mlo)) {
-               link_sta = rcu_dereference(rx->sta->link[rx->link_id]);
-
-               if (WARN_ON_ONCE(!link_sta))
-                       return true;
-       }
-
        if (!consume) {
                struct skb_shared_hwtstamps *shwt;
 
@@ -4838,9 +4838,12 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
                 */
                shwt = skb_hwtstamps(rx->skb);
                shwt->hwtstamp = skb_hwtstamps(skb)->hwtstamp;
+
+               /* Update the hdr pointer to the new skb for translation below */
+               hdr = (struct ieee80211_hdr *)rx->skb->data;
        }
 
-       if (unlikely(link_sta)) {
+       if (unlikely(rx->sta && rx->sta->sta.mlo)) {
                /* translate to MLD addresses */
                if (ether_addr_equal(link->conf->addr, hdr->addr1))
                        ether_addr_copy(hdr->addr1, rx->sdata->vif.addr);
@@ -4870,6 +4873,7 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_fast_rx *fast_rx;
        struct ieee80211_rx_data rx;
+       int link_id = -1;
 
        memset(&rx, 0, sizeof(rx));
        rx.skb = skb;
@@ -4886,12 +4890,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
        if (!pubsta)
                goto drop;
 
-       rx.sta = container_of(pubsta, struct sta_info, sta);
-       rx.sdata = rx.sta->sdata;
-
-       if (status->link_valid &&
-           !ieee80211_rx_is_valid_sta_link_id(pubsta, status->link_id))
-               goto drop;
+       if (status->link_valid)
+               link_id = status->link_id;
 
        /*
         * TODO: Should the frame be dropped if the right link_id is not
@@ -4900,19 +4900,8 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
         * link_id is used only for stats purpose and updating the stats on
         * the deflink is fine?
         */
-       if (status->link_valid)
-               rx.link_id = status->link_id;
-
-       if (rx.link_id >= 0) {
-               struct ieee80211_link_data *link;
-
-               link =  rcu_dereference(rx.sdata->link[rx.link_id]);
-               if (!link)
-                       goto drop;
-               rx.link = link;
-       } else {
-               rx.link = &rx.sdata->deflink;
-       }
+       if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
+               goto drop;
 
        fast_rx = rcu_dereference(rx.sta->fast_rx);
        if (!fast_rx)
@@ -4930,6 +4919,8 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
 {
        struct link_sta_info *link_sta;
        struct ieee80211_hdr *hdr = (void *)skb->data;
+       struct sta_info *sta;
+       int link_id = -1;
 
        /*
         * Look up link station first, in case there's a
@@ -4939,24 +4930,19 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
         */
        link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
        if (link_sta) {
-               rx->sta = link_sta->sta;
-               rx->link_id = link_sta->link_id;
+               sta = link_sta->sta;
+               link_id = link_sta->link_id;
        } else {
                struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-               rx->sta = sta_info_get_bss(rx->sdata, hdr->addr2);
-               if (rx->sta) {
-                       if (status->link_valid &&
-                           !ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta,
-                                                              status->link_id))
-                               return false;
-
-                       rx->link_id = status->link_valid ? status->link_id : -1;
-               } else {
-                       rx->link_id = -1;
-               }
+               sta = sta_info_get_bss(rx->sdata, hdr->addr2);
+               if (status->link_valid)
+                       link_id = status->link_id;
        }
 
+       if (!ieee80211_rx_data_set_sta(rx, &sta->sta, link_id))
+               return false;
+
        return ieee80211_prepare_and_rx_handle(rx, skb, consume);
 }
 
@@ -5015,19 +5001,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
        if (ieee80211_is_data(fc)) {
                struct sta_info *sta, *prev_sta;
-               u8 link_id = status->link_id;
+               int link_id = -1;
 
-               if (pubsta) {
-                       rx.sta = container_of(pubsta, struct sta_info, sta);
-                       rx.sdata = rx.sta->sdata;
+               if (status->link_valid)
+                       link_id = status->link_id;
 
-                       if (status->link_valid &&
-                           !ieee80211_rx_is_valid_sta_link_id(pubsta, link_id))
+               if (pubsta) {
+                       if (!ieee80211_rx_data_set_sta(&rx, pubsta, link_id))
                                goto out;
 
-                       if (status->link_valid)
-                               rx.link_id = status->link_id;
-
                        /*
                         * In MLO connection, fetch the link_id using addr2
                         * when the driver does not pass link_id in status.
@@ -5045,7 +5027,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                if (!link_sta)
                                        goto out;
 
-                               rx.link_id = link_sta->link_id;
+                               ieee80211_rx_data_set_link(&rx, link_sta->link_id);
                        }
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
@@ -5061,30 +5043,27 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                continue;
                        }
 
-                       if ((status->link_valid &&
-                            !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
-                                                               link_id)) ||
-                           (!status->link_valid && prev_sta->sta.mlo))
+                       rx.sdata = prev_sta->sdata;
+                       if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
+                                                      link_id))
+                               goto out;
+
+                       if (!status->link_valid && prev_sta->sta.mlo)
                                continue;
 
-                       rx.link_id = status->link_valid ? link_id : -1;
-                       rx.sta = prev_sta;
-                       rx.sdata = prev_sta->sdata;
                        ieee80211_prepare_and_rx_handle(&rx, skb, false);
 
                        prev_sta = sta;
                }
 
                if (prev_sta) {
-                       if ((status->link_valid &&
-                            !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
-                                                               link_id)) ||
-                           (!status->link_valid && prev_sta->sta.mlo))
+                       rx.sdata = prev_sta->sdata;
+                       if (!ieee80211_rx_data_set_sta(&rx, &prev_sta->sta,
+                                                      link_id))
                                goto out;
 
-                       rx.link_id = status->link_valid ? link_id : -1;
-                       rx.sta = prev_sta;
-                       rx.sdata = prev_sta->sdata;
+                       if (!status->link_valid && prev_sta->sta.mlo)
+                               goto out;
 
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
                                return;
index 2171cd1ca807e8608f1f00a417f8705391e3d634..defe97a31724d81399d844e2fd337444e445351b 100644 (file)
@@ -1129,7 +1129,6 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
        struct sk_buff *purge_skb = NULL;
 
        if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
-               info->flags |= IEEE80211_TX_CTL_AMPDU;
                reset_agg_timer = true;
        } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
                /*
@@ -1161,7 +1160,6 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
                if (!tid_tx) {
                        /* do nothing, let packet pass through */
                } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) {
-                       info->flags |= IEEE80211_TX_CTL_AMPDU;
                        reset_agg_timer = true;
                } else {
                        queued = true;
@@ -3677,8 +3675,7 @@ static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
        info->band = fast_tx->band;
        info->control.vif = &sdata->vif;
        info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
-                     IEEE80211_TX_CTL_DONTFRAG |
-                     (ampdu ? IEEE80211_TX_CTL_AMPDU : 0);
+                     IEEE80211_TX_CTL_DONTFRAG;
        info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
                              u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
                                              IEEE80211_TX_CTRL_MLO_LINK);
@@ -3783,6 +3780,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
        struct ieee80211_tx_data tx;
        ieee80211_tx_result r;
        struct ieee80211_vif *vif = txq->vif;
+       int q = vif->hw_queue[txq->ac];
+       bool q_stopped;
 
        WARN_ON_ONCE(softirq_count() == 0);
 
@@ -3790,17 +3789,18 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
                return NULL;
 
 begin:
-       spin_lock_bh(&fq->lock);
-
-       if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) ||
-           test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags))
-               goto out;
+       spin_lock(&local->queue_stop_reason_lock);
+       q_stopped = local->queue_stop_reasons[q];
+       spin_unlock(&local->queue_stop_reason_lock);
 
-       if (vif->txqs_stopped[txq->ac]) {
-               set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags);
-               goto out;
+       if (unlikely(q_stopped)) {
+               /* mark for waking later */
+               set_bit(IEEE80211_TXQ_DIRTY, &txqi->flags);
+               return NULL;
        }
 
+       spin_lock_bh(&fq->lock);
+
        /* Make sure fragments stay together. */
        skb = __skb_dequeue(&txqi->frags);
        if (unlikely(skb)) {
@@ -3810,6 +3810,9 @@ begin:
                IEEE80211_SKB_CB(skb)->control.flags &=
                        ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
        } else {
+               if (unlikely(test_bit(IEEE80211_TXQ_STOP, &txqi->flags)))
+                       goto out;
+
                skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
        }
 
@@ -3860,9 +3863,8 @@ begin:
        }
 
        if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
-               info->flags |= IEEE80211_TX_CTL_AMPDU;
-       else
-               info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+               info->flags |= (IEEE80211_TX_CTL_AMPDU |
+                               IEEE80211_TX_CTL_DONTFRAG);
 
        if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
                if (!ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
@@ -4596,8 +4598,6 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 
        info = IEEE80211_SKB_CB(skb);
        memset(info, 0, sizeof(*info));
-       if (tid_tx)
-               info->flags |= IEEE80211_TX_CTL_AMPDU;
 
        info->hw_queue = sdata->vif.hw_queue[queue];
 
index 6f5407038459d03cc3ceaa4ac29a66c3da570a57..261ac667887f88c375038ada1c777ef8b3b26ae3 100644 (file)
@@ -292,22 +292,12 @@ static void wake_tx_push_queue(struct ieee80211_local *local,
                               struct ieee80211_sub_if_data *sdata,
                               struct ieee80211_txq *queue)
 {
-       int q = sdata->vif.hw_queue[queue->ac];
        struct ieee80211_tx_control control = {
                .sta = queue->sta,
        };
        struct sk_buff *skb;
-       unsigned long flags;
-       bool q_stopped;
 
        while (1) {
-               spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-               q_stopped = local->queue_stop_reasons[q];
-               spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-
-               if (q_stopped)
-                       break;
-
                skb = ieee80211_tx_dequeue(&local->hw, queue);
                if (!skb)
                        break;
@@ -347,8 +337,6 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
        local_bh_disable();
        spin_lock(&fq->lock);
 
-       sdata->vif.txqs_stopped[ac] = false;
-
        if (!test_bit(SDATA_STATE_RUNNING, &sdata->state))
                goto out;
 
@@ -370,7 +358,7 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
                        if (ac != txq->ac)
                                continue;
 
-                       if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX,
+                       if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY,
                                                &txqi->flags))
                                continue;
 
@@ -385,7 +373,7 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
 
        txqi = to_txq_info(vif->txq);
 
-       if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags) ||
+       if (!test_and_clear_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) ||
            (ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac)
                goto out;
 
@@ -517,8 +505,6 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
                                   bool refcounted)
 {
        struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_sub_if_data *sdata;
-       int n_acs = IEEE80211_NUM_ACS;
 
        trace_stop_queue(local, queue, reason);
 
@@ -530,29 +516,7 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
        else
                local->q_stop_reasons[queue][reason]++;
 
-       if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
-               return;
-
-       if (local->hw.queues < IEEE80211_NUM_ACS)
-               n_acs = 1;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               int ac;
-
-               if (!sdata->dev)
-                       continue;
-
-               for (ac = 0; ac < n_acs; ac++) {
-                       if (sdata->vif.hw_queue[ac] == queue ||
-                           sdata->vif.cab_queue == queue) {
-                               spin_lock(&local->fq.lock);
-                               sdata->vif.txqs_stopped[ac] = true;
-                               spin_unlock(&local->fq.lock);
-                       }
-               }
-       }
-       rcu_read_unlock();
+       set_bit(reason, &local->queue_stop_reasons[queue]);
 }
 
 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
index c2aae2a6d6a6ba98b5513980f8ee97946cde0810..97bb4401dd3ee2bc3e3171aafb0d0844ffb81c06 100644 (file)
@@ -213,7 +213,6 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local,
        ret = ieee802154_parse_frame_start(skb, &hdr);
        if (ret) {
                pr_debug("got invalid frame\n");
-               kfree_skb(skb);
                return;
        }
 
index fc9e728b6333a1f126d8ac615e28fb66028217bc..3150f3f0c87258d3306e7d564435bca35418e566 100644 (file)
@@ -544,9 +544,6 @@ static int mctp_sk_init(struct sock *sk)
 
 static void mctp_sk_close(struct sock *sk, long timeout)
 {
-       struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
-
-       del_timer_sync(&msk->key_expiry);
        sk_common_release(sk);
 }
 
@@ -580,7 +577,19 @@ static void mctp_sk_unhash(struct sock *sk)
                spin_lock_irqsave(&key->lock, fl2);
                __mctp_key_remove(key, net, fl2, MCTP_TRACE_KEY_CLOSED);
        }
+       sock_set_flag(sk, SOCK_DEAD);
        spin_unlock_irqrestore(&net->mctp.keys_lock, flags);
+
+       /* Since there are no more tag allocations (we have removed all of the
+        * keys), stop any pending expiry events. the timer cannot be re-queued
+        * as the sk is no longer observable
+        */
+       del_timer_sync(&msk->key_expiry);
+}
+
+static void mctp_sk_destruct(struct sock *sk)
+{
+       skb_queue_purge(&sk->sk_receive_queue);
 }
 
 static struct proto mctp_proto = {
@@ -619,6 +628,7 @@ static int mctp_pf_create(struct net *net, struct socket *sock,
                return -ENOMEM;
 
        sock_init_data(sock, sk);
+       sk->sk_destruct = mctp_sk_destruct;
 
        rc = 0;
        if (sk->sk_prot->init)
index f9a80b82dc511dbcde9e116838702259c7765759..f51a05ec7162493afbee18f14459c2c27cc88290 100644 (file)
@@ -147,6 +147,7 @@ static struct mctp_sk_key *mctp_key_alloc(struct mctp_sock *msk,
        key->valid = true;
        spin_lock_init(&key->lock);
        refcount_set(&key->refs, 1);
+       sock_hold(key->sk);
 
        return key;
 }
@@ -165,6 +166,7 @@ void mctp_key_unref(struct mctp_sk_key *key)
        mctp_dev_release_key(key->dev, key);
        spin_unlock_irqrestore(&key->lock, flags);
 
+       sock_put(key->sk);
        kfree(key);
 }
 
@@ -177,6 +179,11 @@ static int mctp_key_add(struct mctp_sk_key *key, struct mctp_sock *msk)
 
        spin_lock_irqsave(&net->mctp.keys_lock, flags);
 
+       if (sock_flag(&msk->sk, SOCK_DEAD)) {
+               rc = -EINVAL;
+               goto out_unlock;
+       }
+
        hlist_for_each_entry(tmp, &net->mctp.keys, hlist) {
                if (mctp_key_match(tmp, key->local_addr, key->peer_addr,
                                   key->tag)) {
@@ -198,6 +205,7 @@ static int mctp_key_add(struct mctp_sk_key *key, struct mctp_sock *msk)
                hlist_add_head(&key->sklist, &msk->keys);
        }
 
+out_unlock:
        spin_unlock_irqrestore(&net->mctp.keys_lock, flags);
 
        return rc;
@@ -315,8 +323,8 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
 
 static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
 {
+       struct mctp_sk_key *key, *any_key = NULL;
        struct net *net = dev_net(skb->dev);
-       struct mctp_sk_key *key;
        struct mctp_sock *msk;
        struct mctp_hdr *mh;
        unsigned long f;
@@ -361,13 +369,11 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
                         * key for reassembly - we'll create a more specific
                         * one for future packets if required (ie, !EOM).
                         */
-                       key = mctp_lookup_key(net, skb, MCTP_ADDR_ANY, &f);
-                       if (key) {
-                               msk = container_of(key->sk,
+                       any_key = mctp_lookup_key(net, skb, MCTP_ADDR_ANY, &f);
+                       if (any_key) {
+                               msk = container_of(any_key->sk,
                                                   struct mctp_sock, sk);
-                               spin_unlock_irqrestore(&key->lock, f);
-                               mctp_key_unref(key);
-                               key = NULL;
+                               spin_unlock_irqrestore(&any_key->lock, f);
                        }
                }
 
@@ -419,14 +425,14 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
                         * this function.
                         */
                        rc = mctp_key_add(key, msk);
-                       if (rc) {
-                               kfree(key);
-                       } else {
+                       if (!rc)
                                trace_mctp_key_acquire(key);
 
-                               /* we don't need to release key->lock on exit */
-                               mctp_key_unref(key);
-                       }
+                       /* we don't need to release key->lock on exit, so
+                        * clean up here and suppress the unlock via
+                        * setting to NULL
+                        */
+                       mctp_key_unref(key);
                        key = NULL;
 
                } else {
@@ -473,6 +479,8 @@ out_unlock:
                spin_unlock_irqrestore(&key->lock, f);
                mctp_key_unref(key);
        }
+       if (any_key)
+               mctp_key_unref(any_key);
 out:
        if (rc)
                kfree_skb(skb);
index 45e2a48397b959e0a6bb7205c18373bb61334598..70f0ced3ca86e18dd0a63d56bfc2c0ded3b31a33 100644 (file)
@@ -420,6 +420,31 @@ void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
        }
 }
 
+/* if sk is ipv4 or ipv6_only allows only same-family local and remote addresses,
+ * otherwise allow any matching local/remote pair
+ */
+bool mptcp_pm_addr_families_match(const struct sock *sk,
+                                 const struct mptcp_addr_info *loc,
+                                 const struct mptcp_addr_info *rem)
+{
+       bool mptcp_is_v4 = sk->sk_family == AF_INET;
+
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+       bool loc_is_v4 = loc->family == AF_INET || ipv6_addr_v4mapped(&loc->addr6);
+       bool rem_is_v4 = rem->family == AF_INET || ipv6_addr_v4mapped(&rem->addr6);
+
+       if (mptcp_is_v4)
+               return loc_is_v4 && rem_is_v4;
+
+       if (ipv6_only_sock(sk))
+               return !loc_is_v4 && !rem_is_v4;
+
+       return loc_is_v4 == rem_is_v4;
+#else
+       return mptcp_is_v4 && loc->family == AF_INET && rem->family == AF_INET;
+#endif
+}
+
 void mptcp_pm_data_reset(struct mptcp_sock *msk)
 {
        u8 pm_type = mptcp_get_pm_type(sock_net((struct sock *)msk));
index 65dcc55a8ad89f141765f6a4829f3d47bedb2b47..ea6ad9da749303a239f51702905bd11d34d5efed 100644 (file)
@@ -294,6 +294,13 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
        }
 
        sk = (struct sock *)msk;
+
+       if (!mptcp_pm_addr_families_match(sk, &addr_l, &addr_r)) {
+               GENL_SET_ERR_MSG(info, "families mismatch");
+               err = -EINVAL;
+               goto create_err;
+       }
+
        lock_sock(sk);
 
        err = __mptcp_subflow_connect(sk, &addr_l, &addr_r);
index b7ad030dfe891c81a1f4ee0f3db18bf9058789ec..8cd6cc67c2c5cf9c94d9bb041b83058351c30cae 100644 (file)
@@ -98,7 +98,7 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
        struct socket *ssock;
        int err;
 
-       err = mptcp_subflow_create_socket(sk, &ssock);
+       err = mptcp_subflow_create_socket(sk, sk->sk_family, &ssock);
        if (err)
                return err;
 
index a0d1658ce59eea250b03948665f52e86876c2490..601469249da803d1ec622e4ebc6b219dd31a7d06 100644 (file)
@@ -641,7 +641,8 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
 /* called with sk socket lock held */
 int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
                            const struct mptcp_addr_info *remote);
-int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock);
+int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
+                               struct socket **new_sock);
 void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
                         struct sockaddr_storage *addr,
                         unsigned short family);
@@ -776,6 +777,9 @@ int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
 int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
                         bool require_family,
                         struct mptcp_pm_addr_entry *entry);
+bool mptcp_pm_addr_families_match(const struct sock *sk,
+                                 const struct mptcp_addr_info *loc,
+                                 const struct mptcp_addr_info *rem);
 void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk);
 void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk);
 void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side);
index bd387d4b5a38f4a20745c879fe83846a3396e6e6..ec54413fb31f7862ccf1602395235a7888e44dd4 100644 (file)
@@ -1547,7 +1547,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
        if (!mptcp_is_fully_established(sk))
                goto err_out;
 
-       err = mptcp_subflow_create_socket(sk, &sf);
+       err = mptcp_subflow_create_socket(sk, loc->family, &sf);
        if (err)
                goto err_out;
 
@@ -1660,7 +1660,9 @@ static void mptcp_subflow_ops_undo_override(struct sock *ssk)
 #endif
                ssk->sk_prot = &tcp_prot;
 }
-int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
+
+int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
+                               struct socket **new_sock)
 {
        struct mptcp_subflow_context *subflow;
        struct net *net = sock_net(sk);
@@ -1673,8 +1675,7 @@ int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock)
        if (unlikely(!sk->sk_socket))
                return -EINVAL;
 
-       err = sock_create_kern(net, sk->sk_family, SOCK_STREAM, IPPROTO_TCP,
-                              &sf);
+       err = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &sf);
        if (err)
                return err;
 
index a8ce04a4bb72abef52524edad94dc7d69d39458a..e4fa00abde6a2ab9941c8cd7d0b8a12f537503e0 100644 (file)
@@ -308,8 +308,8 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
                        return -IPSET_ERR_BITMAP_RANGE;
 
                pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
-               hosts = 2 << (32 - netmask - 1);
-               elements = 2 << (netmask - mask_bits - 1);
+               hosts = 2U << (32 - netmask - 1);
+               elements = 2UL << (netmask - mask_bits - 1);
        }
        if (elements > IPSET_BITMAP_MAX_RANGE + 1)
                return -IPSET_ERR_BITMAP_RANGE_SIZE;
index d88b92a8ffca889841b34f8213431e08da678d40..011d414038ea086b1df4f74829f461e5d3e065d0 100644 (file)
 #include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_conntrack_timeout.h>
 
-/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
-   closely.  They're more complex. --RR
-
-   And so for me for SCTP :D -Kiran */
-
 static const char *const sctp_conntrack_names[] = {
-       "NONE",
-       "CLOSED",
-       "COOKIE_WAIT",
-       "COOKIE_ECHOED",
-       "ESTABLISHED",
-       "SHUTDOWN_SENT",
-       "SHUTDOWN_RECD",
-       "SHUTDOWN_ACK_SENT",
-       "HEARTBEAT_SENT",
-       "HEARTBEAT_ACKED",
+       [SCTP_CONNTRACK_NONE]                   = "NONE",
+       [SCTP_CONNTRACK_CLOSED]                 = "CLOSED",
+       [SCTP_CONNTRACK_COOKIE_WAIT]            = "COOKIE_WAIT",
+       [SCTP_CONNTRACK_COOKIE_ECHOED]          = "COOKIE_ECHOED",
+       [SCTP_CONNTRACK_ESTABLISHED]            = "ESTABLISHED",
+       [SCTP_CONNTRACK_SHUTDOWN_SENT]          = "SHUTDOWN_SENT",
+       [SCTP_CONNTRACK_SHUTDOWN_RECD]          = "SHUTDOWN_RECD",
+       [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT]      = "SHUTDOWN_ACK_SENT",
+       [SCTP_CONNTRACK_HEARTBEAT_SENT]         = "HEARTBEAT_SENT",
 };
 
 #define SECS  * HZ
@@ -54,13 +48,11 @@ static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = {
        [SCTP_CONNTRACK_CLOSED]                 = 10 SECS,
        [SCTP_CONNTRACK_COOKIE_WAIT]            = 3 SECS,
        [SCTP_CONNTRACK_COOKIE_ECHOED]          = 3 SECS,
-       [SCTP_CONNTRACK_ESTABLISHED]            = 5 DAYS,
+       [SCTP_CONNTRACK_ESTABLISHED]            = 210 SECS,
        [SCTP_CONNTRACK_SHUTDOWN_SENT]          = 300 SECS / 1000,
        [SCTP_CONNTRACK_SHUTDOWN_RECD]          = 300 SECS / 1000,
        [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT]      = 3 SECS,
        [SCTP_CONNTRACK_HEARTBEAT_SENT]         = 30 SECS,
-       [SCTP_CONNTRACK_HEARTBEAT_ACKED]        = 210 SECS,
-       [SCTP_CONNTRACK_DATA_SENT]              = 30 SECS,
 };
 
 #define        SCTP_FLAG_HEARTBEAT_VTAG_FAILED 1
@@ -74,8 +66,6 @@ static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = {
 #define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
 #define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
 #define        sHS SCTP_CONNTRACK_HEARTBEAT_SENT
-#define        sHA SCTP_CONNTRACK_HEARTBEAT_ACKED
-#define        sDS SCTP_CONNTRACK_DATA_SENT
 #define        sIV SCTP_CONNTRACK_MAX
 
 /*
@@ -98,10 +88,6 @@ SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
 CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
                    the SHUTDOWN chunk. Connection is closed.
 HEARTBEAT_SENT    - We have seen a HEARTBEAT in a new flow.
-HEARTBEAT_ACKED   - We have seen a HEARTBEAT-ACK/DATA/SACK in the direction
-                   opposite to that of the HEARTBEAT/DATA chunk. Secondary connection
-                   is established.
-DATA_SENT         - We have seen a DATA/SACK in a new flow.
 */
 
 /* TODO
@@ -115,38 +101,36 @@ cookie echoed to closed.
 */
 
 /* SCTP conntrack state transitions */
-static const u8 sctp_conntracks[2][12][SCTP_CONNTRACK_MAX] = {
+static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
        {
 /*     ORIGINAL        */
-/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA, sDS */
-/* init         */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW, sHA, sCW},
-/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA, sCL},
-/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
-/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL, sSS, sCL},
-/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA, sHA, sSA},
-/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA, sCL},/* Can't have Stale cookie*/
-/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL, sHA, sCL},/* 5.2.4 - Big TODO */
-/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA, sCL},/* Can't come in orig dir */
-/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL, sHA, sCL},
-/* heartbeat    */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA, sDS},
-/* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA, sDS},
-/* data/sack    */ {sDS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA, sDS}
+/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */
+/* init         */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW},
+/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},
+/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL},
+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA},
+/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/
+/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */
+/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */
+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL},
+/* heartbeat    */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS},
+/* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS},
        },
        {
 /*     REPLY   */
-/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA, sDS */
-/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA, sIV},/* INIT in sCL Big TODO */
-/* init_ack     */ {sIV, sCW, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA, sIV},
-/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV, sCL, sIV},
-/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV, sSR, sIV},
-/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV, sHA, sIV},
-/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV, sHA, sIV},
-/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA, sIV},/* Can't come in reply dir */
-/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV, sHA, sIV},
-/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV, sHA, sIV},
-/* heartbeat    */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA, sHA},
-/* heartbeat_ack*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHA, sHA, sHA},
-/* data/sack    */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHA, sHA, sHA},
+/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */
+/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* INIT in sCL Big TODO */
+/* init_ack     */ {sIV, sCW, sCW, sCE, sES, sSS, sSR, sSA, sIV},
+/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV},
+/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV},
+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV},
+/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV},
+/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */
+/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV},
+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV},
+/* heartbeat    */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS},
+/* heartbeat_ack*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sES},
        }
 };
 
@@ -158,6 +142,7 @@ static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
 }
 #endif
 
+/* do_basic_checks ensures sch->length > 0, do not use before */
 #define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count)    \
 for ((offset) = (dataoff) + sizeof(struct sctphdr), (count) = 0;       \
        (offset) < (skb)->len &&                                        \
@@ -258,11 +243,6 @@ static int sctp_new_state(enum ip_conntrack_dir dir,
                pr_debug("SCTP_CID_HEARTBEAT_ACK");
                i = 10;
                break;
-       case SCTP_CID_DATA:
-       case SCTP_CID_SACK:
-               pr_debug("SCTP_CID_DATA/SACK");
-               i = 11;
-               break;
        default:
                /* Other chunks like DATA or SACK do not change the state */
                pr_debug("Unknown chunk type, Will stay in %s\n",
@@ -316,9 +296,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
                                 ih->init_tag);
 
                        ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = ih->init_tag;
-               } else if (sch->type == SCTP_CID_HEARTBEAT ||
-                          sch->type == SCTP_CID_DATA ||
-                          sch->type == SCTP_CID_SACK) {
+               } else if (sch->type == SCTP_CID_HEARTBEAT) {
                        pr_debug("Setting vtag %x for secondary conntrack\n",
                                 sh->vtag);
                        ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag;
@@ -404,19 +382,19 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
 
                if (!sctp_new(ct, skb, sh, dataoff))
                        return -NF_ACCEPT;
-       } else {
-               /* Check the verification tag (Sec 8.5) */
-               if (!test_bit(SCTP_CID_INIT, map) &&
-                   !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) &&
-                   !test_bit(SCTP_CID_COOKIE_ECHO, map) &&
-                   !test_bit(SCTP_CID_ABORT, map) &&
-                   !test_bit(SCTP_CID_SHUTDOWN_ACK, map) &&
-                   !test_bit(SCTP_CID_HEARTBEAT, map) &&
-                   !test_bit(SCTP_CID_HEARTBEAT_ACK, map) &&
-                   sh->vtag != ct->proto.sctp.vtag[dir]) {
-                       pr_debug("Verification tag check failed\n");
-                       goto out;
-               }
+       }
+
+       /* Check the verification tag (Sec 8.5) */
+       if (!test_bit(SCTP_CID_INIT, map) &&
+           !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) &&
+           !test_bit(SCTP_CID_COOKIE_ECHO, map) &&
+           !test_bit(SCTP_CID_ABORT, map) &&
+           !test_bit(SCTP_CID_SHUTDOWN_ACK, map) &&
+           !test_bit(SCTP_CID_HEARTBEAT, map) &&
+           !test_bit(SCTP_CID_HEARTBEAT_ACK, map) &&
+           sh->vtag != ct->proto.sctp.vtag[dir]) {
+               pr_debug("Verification tag check failed\n");
+               goto out;
        }
 
        old_state = new_state = SCTP_CONNTRACK_NONE;
@@ -424,22 +402,29 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
        for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
                /* Special cases of Verification tag check (Sec 8.5.1) */
                if (sch->type == SCTP_CID_INIT) {
-                       /* Sec 8.5.1 (A) */
+                       /* (A) vtag MUST be zero */
                        if (sh->vtag != 0)
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_ABORT) {
-                       /* Sec 8.5.1 (B) */
-                       if (sh->vtag != ct->proto.sctp.vtag[dir] &&
-                           sh->vtag != ct->proto.sctp.vtag[!dir])
+                       /* (B) vtag MUST match own vtag if T flag is unset OR
+                        * MUST match peer's vtag if T flag is set
+                        */
+                       if ((!(sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[dir]) ||
+                           ((sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[!dir]))
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
-                       /* Sec 8.5.1 (C) */
-                       if (sh->vtag != ct->proto.sctp.vtag[dir] &&
-                           sh->vtag != ct->proto.sctp.vtag[!dir] &&
-                           sch->flags & SCTP_CHUNK_FLAG_T)
+                       /* (C) vtag MUST match own vtag if T flag is unset OR
+                        * MUST match peer's vtag if T flag is set
+                        */
+                       if ((!(sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[dir]) ||
+                           ((sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[!dir]))
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
-                       /* Sec 8.5.1 (D) */
+                       /* (D) vtag must be same as init_vtag as found in INIT_ACK */
                        if (sh->vtag != ct->proto.sctp.vtag[dir])
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_HEARTBEAT) {
@@ -476,11 +461,6 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
                        } else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) {
                                ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
                        }
-               } else if (sch->type == SCTP_CID_DATA || sch->type == SCTP_CID_SACK) {
-                       if (ct->proto.sctp.vtag[dir] == 0) {
-                               pr_debug("Setting vtag %x for dir %d\n", sh->vtag, dir);
-                               ct->proto.sctp.vtag[dir] = sh->vtag;
-                       }
                }
 
                old_state = ct->proto.sctp.state;
@@ -518,8 +498,12 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
                }
 
                ct->proto.sctp.state = new_state;
-               if (old_state != new_state)
+               if (old_state != new_state) {
                        nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
+                       if (new_state == SCTP_CONNTRACK_ESTABLISHED &&
+                           !test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
+                               nf_conntrack_event_cache(IPCT_ASSURED, ct);
+               }
        }
        spin_unlock_bh(&ct->lock);
 
@@ -533,14 +517,6 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
 
        nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
 
-       if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
-           dir == IP_CT_DIR_REPLY &&
-           new_state == SCTP_CONNTRACK_ESTABLISHED) {
-               pr_debug("Setting assured bit\n");
-               set_bit(IPS_ASSURED_BIT, &ct->status);
-               nf_conntrack_event_cache(IPCT_ASSURED, ct);
-       }
-
        return NF_ACCEPT;
 
 out_unlock:
@@ -701,7 +677,6 @@ sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = {
        [CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT]    = { .type = NLA_U32 },
        [CTA_TIMEOUT_SCTP_HEARTBEAT_SENT]       = { .type = NLA_U32 },
        [CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED]      = { .type = NLA_U32 },
-       [CTA_TIMEOUT_SCTP_DATA_SENT]            = { .type = NLA_U32 },
 };
 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 
index 6566310831779bbac55317361adfaf2f88b143d0..3ac1af6f59fccaad5f1cd0053f038e7ed6acadc4 100644 (file)
@@ -1068,6 +1068,13 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
                                ct->proto.tcp.last_flags |=
                                        IP_CT_EXP_CHALLENGE_ACK;
                }
+
+               /* possible challenge ack reply to syn */
+               if (old_state == TCP_CONNTRACK_SYN_SENT &&
+                   index == TCP_ACK_SET &&
+                   dir == IP_CT_DIR_REPLY)
+                       ct->proto.tcp.last_ack = ntohl(th->ack_seq);
+
                spin_unlock_bh(&ct->lock);
                nf_ct_l4proto_log_invalid(skb, ct, state,
                                          "packet (index %d) in dir %d ignored, state %s",
@@ -1193,6 +1200,14 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
                         * segments we ignored. */
                        goto in_window;
                }
+
+               /* Reset in response to a challenge-ack we let through earlier */
+               if (old_state == TCP_CONNTRACK_SYN_SENT &&
+                   ct->proto.tcp.last_index == TCP_ACK_SET &&
+                   ct->proto.tcp.last_dir == IP_CT_DIR_REPLY &&
+                   ntohl(th->seq) == ct->proto.tcp.last_ack)
+                       goto in_window;
+
                break;
        default:
                /* Keep compilers happy. */
index 0250725e38a44d0e1db870b537e10f7eb02511f8..460294bd4b6061250955c74f04cacd32e64ed080 100644 (file)
@@ -601,8 +601,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_RECD,
        NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT,
        NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_SENT,
-       NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED,
-       NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_DATA_SENT,
 #endif
 #ifdef CONFIG_NF_CT_PROTO_DCCP
        NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST,
@@ -887,18 +885,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED] = {
-               .procname       = "nf_conntrack_sctp_timeout_heartbeat_acked",
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
-       [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_DATA_SENT] = {
-               .procname       = "nf_conntrack_sctp_timeout_data_sent",
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
 #endif
 #ifdef CONFIG_NF_CT_PROTO_DCCP
        [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST] = {
@@ -1042,8 +1028,6 @@ static void nf_conntrack_standalone_init_sctp_sysctl(struct net *net,
        XASSIGN(SHUTDOWN_RECD, sn);
        XASSIGN(SHUTDOWN_ACK_SENT, sn);
        XASSIGN(HEARTBEAT_SENT, sn);
-       XASSIGN(HEARTBEAT_ACKED, sn);
-       XASSIGN(DATA_SENT, sn);
 #undef XASSIGN
 #endif
 }
index 17b418a5a593af2aa20f89e2a6ddc076488124c7..3a3c7746e88fe6ef0bc443454788bc5650f3b6d9 100644 (file)
@@ -63,7 +63,7 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
                        return false;
 
                if (offset + len > VLAN_ETH_HLEN + vlan_hlen)
-                       ethlen -= offset + len - VLAN_ETH_HLEN + vlan_hlen;
+                       ethlen -= offset + len - VLAN_ETH_HLEN - vlan_hlen;
 
                memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen);
 
index 7325bee7d14425232f953e630b7453cd490b5ce9..19ea4d3c35535552a3acf1ac18f33b91645f944a 100644 (file)
@@ -38,10 +38,12 @@ static bool nft_rbtree_interval_start(const struct nft_rbtree_elem *rbe)
        return !nft_rbtree_interval_end(rbe);
 }
 
-static bool nft_rbtree_equal(const struct nft_set *set, const void *this,
-                            const struct nft_rbtree_elem *interval)
+static int nft_rbtree_cmp(const struct nft_set *set,
+                         const struct nft_rbtree_elem *e1,
+                         const struct nft_rbtree_elem *e2)
 {
-       return memcmp(this, nft_set_ext_key(&interval->ext), set->klen) == 0;
+       return memcmp(nft_set_ext_key(&e1->ext), nft_set_ext_key(&e2->ext),
+                     set->klen);
 }
 
 static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
@@ -52,7 +54,6 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
        const struct nft_rbtree_elem *rbe, *interval = NULL;
        u8 genmask = nft_genmask_cur(net);
        const struct rb_node *parent;
-       const void *this;
        int d;
 
        parent = rcu_dereference_raw(priv->root.rb_node);
@@ -62,12 +63,11 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
 
                rbe = rb_entry(parent, struct nft_rbtree_elem, node);
 
-               this = nft_set_ext_key(&rbe->ext);
-               d = memcmp(this, key, set->klen);
+               d = memcmp(nft_set_ext_key(&rbe->ext), key, set->klen);
                if (d < 0) {
                        parent = rcu_dereference_raw(parent->rb_left);
                        if (interval &&
-                           nft_rbtree_equal(set, this, interval) &&
+                           !nft_rbtree_cmp(set, rbe, interval) &&
                            nft_rbtree_interval_end(rbe) &&
                            nft_rbtree_interval_start(interval))
                                continue;
@@ -215,154 +215,216 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set,
        return rbe;
 }
 
+static int nft_rbtree_gc_elem(const struct nft_set *__set,
+                             struct nft_rbtree *priv,
+                             struct nft_rbtree_elem *rbe)
+{
+       struct nft_set *set = (struct nft_set *)__set;
+       struct rb_node *prev = rb_prev(&rbe->node);
+       struct nft_rbtree_elem *rbe_prev;
+       struct nft_set_gc_batch *gcb;
+
+       gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
+       if (!gcb)
+               return -ENOMEM;
+
+       /* search for expired end interval coming before this element. */
+       do {
+               rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
+               if (nft_rbtree_interval_end(rbe_prev))
+                       break;
+
+               prev = rb_prev(prev);
+       } while (prev != NULL);
+
+       rb_erase(&rbe_prev->node, &priv->root);
+       rb_erase(&rbe->node, &priv->root);
+       atomic_sub(2, &set->nelems);
+
+       nft_set_gc_batch_add(gcb, rbe);
+       nft_set_gc_batch_complete(gcb);
+
+       return 0;
+}
+
+static bool nft_rbtree_update_first(const struct nft_set *set,
+                                   struct nft_rbtree_elem *rbe,
+                                   struct rb_node *first)
+{
+       struct nft_rbtree_elem *first_elem;
+
+       first_elem = rb_entry(first, struct nft_rbtree_elem, node);
+       /* this element is closest to where the new element is to be inserted:
+        * update the first element for the node list path.
+        */
+       if (nft_rbtree_cmp(set, rbe, first_elem) < 0)
+               return true;
+
+       return false;
+}
+
 static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                               struct nft_rbtree_elem *new,
                               struct nft_set_ext **ext)
 {
-       bool overlap = false, dup_end_left = false, dup_end_right = false;
+       struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
+       struct rb_node *node, *parent, **p, *first = NULL;
        struct nft_rbtree *priv = nft_set_priv(set);
        u8 genmask = nft_genmask_next(net);
-       struct nft_rbtree_elem *rbe;
-       struct rb_node *parent, **p;
-       int d;
+       int d, err;
 
-       /* Detect overlaps as we descend the tree. Set the flag in these cases:
-        *
-        * a1. _ _ __>|  ?_ _ __|  (insert end before existing end)
-        * a2. _ _ ___|  ?_ _ _>|  (insert end after existing end)
-        * a3. _ _ ___? >|_ _ __|  (insert start before existing end)
-        *
-        * and clear it later on, as we eventually reach the points indicated by
-        * '?' above, in the cases described below. We'll always meet these
-        * later, locally, due to tree ordering, and overlaps for the intervals
-        * that are the closest together are always evaluated last.
-        *
-        * b1. _ _ __>|  !_ _ __|  (insert end before existing start)
-        * b2. _ _ ___|  !_ _ _>|  (insert end after existing start)
-        * b3. _ _ ___! >|_ _ __|  (insert start after existing end, as a leaf)
-        *            '--' no nodes falling in this range
-        * b4.          >|_ _   !  (insert start before existing start)
-        *
-        * Case a3. resolves to b3.:
-        * - if the inserted start element is the leftmost, because the '0'
-        *   element in the tree serves as end element
-        * - otherwise, if an existing end is found immediately to the left. If
-        *   there are existing nodes in between, we need to further descend the
-        *   tree before we can conclude the new start isn't causing an overlap
-        *
-        * or to b4., which, preceded by a3., means we already traversed one or
-        * more existing intervals entirely, from the right.
-        *
-        * For a new, rightmost pair of elements, we'll hit cases b3. and b2.,
-        * in that order.
-        *
-        * The flag is also cleared in two special cases:
-        *
-        * b5. |__ _ _!|<_ _ _   (insert start right before existing end)
-        * b6. |__ _ >|!__ _ _   (insert end right after existing start)
-        *
-        * which always happen as last step and imply that no further
-        * overlapping is possible.
-        *
-        * Another special case comes from the fact that start elements matching
-        * an already existing start element are allowed: insertion is not
-        * performed but we return -EEXIST in that case, and the error will be
-        * cleared by the caller if NLM_F_EXCL is not present in the request.
-        * This way, request for insertion of an exact overlap isn't reported as
-        * error to userspace if not desired.
-        *
-        * However, if the existing start matches a pre-existing start, but the
-        * end element doesn't match the corresponding pre-existing end element,
-        * we need to report a partial overlap. This is a local condition that
-        * can be noticed without need for a tracking flag, by checking for a
-        * local duplicated end for a corresponding start, from left and right,
-        * separately.
+       /* Descend the tree to search for an existing element greater than the
+        * key value to insert that is greater than the new element. This is the
+        * first element to walk the ordered elements to find possible overlap.
         */
-
        parent = NULL;
        p = &priv->root.rb_node;
        while (*p != NULL) {
                parent = *p;
                rbe = rb_entry(parent, struct nft_rbtree_elem, node);
-               d = memcmp(nft_set_ext_key(&rbe->ext),
-                          nft_set_ext_key(&new->ext),
-                          set->klen);
+               d = nft_rbtree_cmp(set, rbe, new);
+
                if (d < 0) {
                        p = &parent->rb_left;
-
-                       if (nft_rbtree_interval_start(new)) {
-                               if (nft_rbtree_interval_end(rbe) &&
-                                   nft_set_elem_active(&rbe->ext, genmask) &&
-                                   !nft_set_elem_expired(&rbe->ext) && !*p)
-                                       overlap = false;
-                       } else {
-                               if (dup_end_left && !*p)
-                                       return -ENOTEMPTY;
-
-                               overlap = nft_rbtree_interval_end(rbe) &&
-                                         nft_set_elem_active(&rbe->ext,
-                                                             genmask) &&
-                                         !nft_set_elem_expired(&rbe->ext);
-
-                               if (overlap) {
-                                       dup_end_right = true;
-                                       continue;
-                               }
-                       }
                } else if (d > 0) {
-                       p = &parent->rb_right;
+                       if (!first ||
+                           nft_rbtree_update_first(set, rbe, first))
+                               first = &rbe->node;
 
-                       if (nft_rbtree_interval_end(new)) {
-                               if (dup_end_right && !*p)
-                                       return -ENOTEMPTY;
-
-                               overlap = nft_rbtree_interval_end(rbe) &&
-                                         nft_set_elem_active(&rbe->ext,
-                                                             genmask) &&
-                                         !nft_set_elem_expired(&rbe->ext);
-
-                               if (overlap) {
-                                       dup_end_left = true;
-                                       continue;
-                               }
-                       } else if (nft_set_elem_active(&rbe->ext, genmask) &&
-                                  !nft_set_elem_expired(&rbe->ext)) {
-                               overlap = nft_rbtree_interval_end(rbe);
-                       }
+                       p = &parent->rb_right;
                } else {
-                       if (nft_rbtree_interval_end(rbe) &&
-                           nft_rbtree_interval_start(new)) {
+                       if (nft_rbtree_interval_end(rbe))
                                p = &parent->rb_left;
-
-                               if (nft_set_elem_active(&rbe->ext, genmask) &&
-                                   !nft_set_elem_expired(&rbe->ext))
-                                       overlap = false;
-                       } else if (nft_rbtree_interval_start(rbe) &&
-                                  nft_rbtree_interval_end(new)) {
+                       else
                                p = &parent->rb_right;
+               }
+       }
+
+       if (!first)
+               first = rb_first(&priv->root);
+
+       /* Detect overlap by going through the list of valid tree nodes.
+        * Values stored in the tree are in reversed order, starting from
+        * highest to lowest value.
+        */
+       for (node = first; node != NULL; node = rb_next(node)) {
+               rbe = rb_entry(node, struct nft_rbtree_elem, node);
 
-                               if (nft_set_elem_active(&rbe->ext, genmask) &&
-                                   !nft_set_elem_expired(&rbe->ext))
-                                       overlap = false;
-                       } else if (nft_set_elem_active(&rbe->ext, genmask) &&
-                                  !nft_set_elem_expired(&rbe->ext)) {
-                               *ext = &rbe->ext;
-                               return -EEXIST;
-                       } else {
-                               overlap = false;
-                               if (nft_rbtree_interval_end(rbe))
-                                       p = &parent->rb_left;
-                               else
-                                       p = &parent->rb_right;
+               if (!nft_set_elem_active(&rbe->ext, genmask))
+                       continue;
+
+               /* perform garbage collection to avoid bogus overlap reports. */
+               if (nft_set_elem_expired(&rbe->ext)) {
+                       err = nft_rbtree_gc_elem(set, priv, rbe);
+                       if (err < 0)
+                               return err;
+
+                       continue;
+               }
+
+               d = nft_rbtree_cmp(set, rbe, new);
+               if (d == 0) {
+                       /* Matching end element: no need to look for an
+                        * overlapping greater or equal element.
+                        */
+                       if (nft_rbtree_interval_end(rbe)) {
+                               rbe_le = rbe;
+                               break;
+                       }
+
+                       /* first element that is greater or equal to key value. */
+                       if (!rbe_ge) {
+                               rbe_ge = rbe;
+                               continue;
+                       }
+
+                       /* this is a closer more or equal element, update it. */
+                       if (nft_rbtree_cmp(set, rbe_ge, new) != 0) {
+                               rbe_ge = rbe;
+                               continue;
+                       }
+
+                       /* element is equal to key value, make sure flags are
+                        * the same, an existing more or equal start element
+                        * must not be replaced by more or equal end element.
+                        */
+                       if ((nft_rbtree_interval_start(new) &&
+                            nft_rbtree_interval_start(rbe_ge)) ||
+                           (nft_rbtree_interval_end(new) &&
+                            nft_rbtree_interval_end(rbe_ge))) {
+                               rbe_ge = rbe;
+                               continue;
                        }
+               } else if (d > 0) {
+                       /* annotate element greater than the new element. */
+                       rbe_ge = rbe;
+                       continue;
+               } else if (d < 0) {
+                       /* annotate element less than the new element. */
+                       rbe_le = rbe;
+                       break;
                }
+       }
 
-               dup_end_left = dup_end_right = false;
+       /* - new start element matching existing start element: full overlap
+        *   reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given.
+        */
+       if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) &&
+           nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) {
+               *ext = &rbe_ge->ext;
+               return -EEXIST;
        }
 
-       if (overlap)
+       /* - new end element matching existing end element: full overlap
+        *   reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given.
+        */
+       if (rbe_le && !nft_rbtree_cmp(set, new, rbe_le) &&
+           nft_rbtree_interval_end(rbe_le) == nft_rbtree_interval_end(new)) {
+               *ext = &rbe_le->ext;
+               return -EEXIST;
+       }
+
+       /* - new start element with existing closest, less or equal key value
+        *   being a start element: partial overlap, reported as -ENOTEMPTY.
+        *   Anonymous sets allow for two consecutive start element since they
+        *   are constant, skip them to avoid bogus overlap reports.
+        */
+       if (!nft_set_is_anonymous(set) && rbe_le &&
+           nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
+               return -ENOTEMPTY;
+
+       /* - new end element with existing closest, less or equal key value
+        *   being a end element: partial overlap, reported as -ENOTEMPTY.
+        */
+       if (rbe_le &&
+           nft_rbtree_interval_end(rbe_le) && nft_rbtree_interval_end(new))
                return -ENOTEMPTY;
 
+       /* - new end element with existing closest, greater or equal key value
+        *   being an end element: partial overlap, reported as -ENOTEMPTY
+        */
+       if (rbe_ge &&
+           nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new))
+               return -ENOTEMPTY;
+
+       /* Accepted element: pick insertion point depending on key value */
+       parent = NULL;
+       p = &priv->root.rb_node;
+       while (*p != NULL) {
+               parent = *p;
+               rbe = rb_entry(parent, struct nft_rbtree_elem, node);
+               d = nft_rbtree_cmp(set, rbe, new);
+
+               if (d < 0)
+                       p = &parent->rb_left;
+               else if (d > 0)
+                       p = &parent->rb_right;
+               else if (nft_rbtree_interval_end(rbe))
+                       p = &parent->rb_left;
+               else
+                       p = &parent->rb_right;
+       }
+
        rb_link_node_rcu(&new->node, parent, p);
        rb_insert_color(&new->node, &priv->root);
        return 0;
@@ -501,23 +563,37 @@ static void nft_rbtree_gc(struct work_struct *work)
        struct nft_rbtree *priv;
        struct rb_node *node;
        struct nft_set *set;
+       struct net *net;
+       u8 genmask;
 
        priv = container_of(work, struct nft_rbtree, gc_work.work);
        set  = nft_set_container_of(priv);
+       net  = read_pnet(&set->net);
+       genmask = nft_genmask_cur(net);
 
        write_lock_bh(&priv->lock);
        write_seqcount_begin(&priv->count);
        for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
                rbe = rb_entry(node, struct nft_rbtree_elem, node);
 
+               if (!nft_set_elem_active(&rbe->ext, genmask))
+                       continue;
+
+               /* elements are reversed in the rbtree for historical reasons,
+                * from highest to lowest value, that is why end element is
+                * always visited before the start element.
+                */
                if (nft_rbtree_interval_end(rbe)) {
                        rbe_end = rbe;
                        continue;
                }
                if (!nft_set_elem_expired(&rbe->ext))
                        continue;
-               if (nft_set_elem_mark_busy(&rbe->ext))
+
+               if (nft_set_elem_mark_busy(&rbe->ext)) {
+                       rbe_end = NULL;
                        continue;
+               }
 
                if (rbe_prev) {
                        rb_erase(&rbe_prev->node, &priv->root);
index bca2a470ccad5fac1caa1eb810d16e95103c93dc..c6427765975318b4c7fe3d5291dc4d69988f5249 100644 (file)
@@ -580,7 +580,9 @@ static int netlink_insert(struct sock *sk, u32 portid)
        if (nlk_sk(sk)->bound)
                goto err;
 
-       nlk_sk(sk)->portid = portid;
+       /* portid can be read locklessly from netlink_getname(). */
+       WRITE_ONCE(nlk_sk(sk)->portid, portid);
+
        sock_hold(sk);
 
        err = __netlink_insert(table, sk);
@@ -1096,9 +1098,11 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
                return -EINVAL;
 
        if (addr->sa_family == AF_UNSPEC) {
-               sk->sk_state    = NETLINK_UNCONNECTED;
-               nlk->dst_portid = 0;
-               nlk->dst_group  = 0;
+               /* paired with READ_ONCE() in netlink_getsockbyportid() */
+               WRITE_ONCE(sk->sk_state, NETLINK_UNCONNECTED);
+               /* dst_portid and dst_group can be read locklessly */
+               WRITE_ONCE(nlk->dst_portid, 0);
+               WRITE_ONCE(nlk->dst_group, 0);
                return 0;
        }
        if (addr->sa_family != AF_NETLINK)
@@ -1119,9 +1123,11 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
                err = netlink_autobind(sock);
 
        if (err == 0) {
-               sk->sk_state    = NETLINK_CONNECTED;
-               nlk->dst_portid = nladdr->nl_pid;
-               nlk->dst_group  = ffs(nladdr->nl_groups);
+               /* paired with READ_ONCE() in netlink_getsockbyportid() */
+               WRITE_ONCE(sk->sk_state, NETLINK_CONNECTED);
+               /* dst_portid and dst_group can be read locklessly */
+               WRITE_ONCE(nlk->dst_portid, nladdr->nl_pid);
+               WRITE_ONCE(nlk->dst_group, ffs(nladdr->nl_groups));
        }
 
        return err;
@@ -1138,10 +1144,12 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr,
        nladdr->nl_pad = 0;
 
        if (peer) {
-               nladdr->nl_pid = nlk->dst_portid;
-               nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
+               /* Paired with WRITE_ONCE() in netlink_connect() */
+               nladdr->nl_pid = READ_ONCE(nlk->dst_portid);
+               nladdr->nl_groups = netlink_group_mask(READ_ONCE(nlk->dst_group));
        } else {
-               nladdr->nl_pid = nlk->portid;
+               /* Paired with WRITE_ONCE() in netlink_insert() */
+               nladdr->nl_pid = READ_ONCE(nlk->portid);
                netlink_lock_table();
                nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
                netlink_unlock_table();
@@ -1168,8 +1176,9 @@ static struct sock *netlink_getsockbyportid(struct sock *ssk, u32 portid)
 
        /* Don't bother queuing skb if kernel socket has no input function */
        nlk = nlk_sk(sock);
-       if (sock->sk_state == NETLINK_CONNECTED &&
-           nlk->dst_portid != nlk_sk(ssk)->portid) {
+       /* dst_portid and sk_state can be changed in netlink_connect() */
+       if (READ_ONCE(sock->sk_state) == NETLINK_CONNECTED &&
+           READ_ONCE(nlk->dst_portid) != nlk_sk(ssk)->portid) {
                sock_put(sock);
                return ERR_PTR(-ECONNREFUSED);
        }
@@ -1886,8 +1895,9 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                        goto out;
                netlink_skb_flags |= NETLINK_SKB_DST;
        } else {
-               dst_portid = nlk->dst_portid;
-               dst_group = nlk->dst_group;
+               /* Paired with WRITE_ONCE() in netlink_connect() */
+               dst_portid = READ_ONCE(nlk->dst_portid);
+               dst_group = READ_ONCE(nlk->dst_group);
        }
 
        /* Paired with WRITE_ONCE() in netlink_insert() */
index 6f7f4392cffb1bd382a89ebe925a7cad2d730b44..5a4cb796150f5abfcfd2f500e954d3e197149d6b 100644 (file)
@@ -400,6 +400,11 @@ static int nr_listen(struct socket *sock, int backlog)
        struct sock *sk = sock->sk;
 
        lock_sock(sk);
+       if (sock->state != SS_UNCONNECTED) {
+               release_sock(sk);
+               return -EINVAL;
+       }
+
        if (sk->sk_state != TCP_LISTEN) {
                memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
                sk->sk_max_ack_backlog = backlog;
index a8da88db7893fcdc445ed74fd9c25c24ef24d47f..4e7c968cde2dcf58e00d3bb080942034147613ec 100644 (file)
@@ -121,6 +121,7 @@ static void nr_heartbeat_expiry(struct timer_list *t)
                   is accepted() it isn't 'dead' so doesn't get removed. */
                if (sock_flag(sk, SOCK_DESTROY) ||
                    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
+                       sock_hold(sk);
                        bh_unlock_sock(sk);
                        nr_destroy_socket(sk);
                        goto out;
index 3364caabef8b1908e264f8462553eef93c825d64..a27e1842b2a09648475759008f46ce085ce78f48 100644 (file)
@@ -157,6 +157,7 @@ static void local_cleanup(struct nfc_llcp_local *local)
        cancel_work_sync(&local->rx_work);
        cancel_work_sync(&local->timeout_work);
        kfree_skb(local->rx_pending);
+       local->rx_pending = NULL;
        del_timer_sync(&local->sdreq_timer);
        cancel_work_sync(&local->sdreq_timeout_work);
        nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
index a71795355aecf5a4f3560f85eb02cb1953c5060f..fcee6012293b1755d4ea675bba7cb331c23a65c6 100644 (file)
@@ -1004,14 +1004,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
        key = kzalloc(sizeof(*key), GFP_KERNEL);
        if (!key) {
                error = -ENOMEM;
-               goto err_kfree_key;
+               goto err_kfree_flow;
        }
 
        ovs_match_init(&match, key, false, &mask);
        error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
                                  a[OVS_FLOW_ATTR_MASK], log);
        if (error)
-               goto err_kfree_flow;
+               goto err_kfree_key;
 
        ovs_flow_mask_key(&new_flow->key, key, true, &mask);
 
@@ -1019,14 +1019,14 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
        error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
                                       key, log);
        if (error)
-               goto err_kfree_flow;
+               goto err_kfree_key;
 
        /* Validate actions. */
        error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
                                     &new_flow->key, &acts, log);
        if (error) {
                OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
-               goto err_kfree_flow;
+               goto err_kfree_key;
        }
 
        reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
@@ -1126,10 +1126,10 @@ err_unlock_ovs:
        kfree_skb(reply);
 err_kfree_acts:
        ovs_nla_free_flow_actions(acts);
-err_kfree_flow:
-       ovs_flow_free(new_flow, false);
 err_kfree_key:
        kfree(key);
+err_kfree_flow:
+       ovs_flow_free(new_flow, false);
 error:
        return error;
 }
index 1990d496fcfc0003ecc93b67f7a7a740c36cc39b..e595079c2cafe8bea4078223170b79b4e003ce3f 100644 (file)
@@ -83,7 +83,10 @@ static struct qrtr_node *node_get(unsigned int node_id)
 
        node->id = node_id;
 
-       radix_tree_insert(&nodes, node_id, node);
+       if (radix_tree_insert(&nodes, node_id, node)) {
+               kfree(node);
+               return NULL;
+       }
 
        return node;
 }
index 36fefc3957d772257755f9e5b90e71e423370ca5..ca2b17f32670dc232ebaeced139782d0ccb4e899 100644 (file)
@@ -488,6 +488,12 @@ static int rose_listen(struct socket *sock, int backlog)
 {
        struct sock *sk = sock->sk;
 
+       lock_sock(sk);
+       if (sock->state != SS_UNCONNECTED) {
+               release_sock(sk);
+               return -EINVAL;
+       }
+
        if (sk->sk_state != TCP_LISTEN) {
                struct rose_sock *rose = rose_sk(sk);
 
@@ -497,8 +503,10 @@ static int rose_listen(struct socket *sock, int backlog)
                memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS);
                sk->sk_max_ack_backlog = backlog;
                sk->sk_state           = TCP_LISTEN;
+               release_sock(sk);
                return 0;
        }
+       release_sock(sk);
 
        return -EOPNOTSUPP;
 }
index 3ded5a24627c55f6850392192b7e9e414c14547c..f3c9f0201c15617071db548179754354eed60335 100644 (file)
@@ -294,7 +294,7 @@ static void rxrpc_put_call_slot(struct rxrpc_call *call)
 static int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
 {
        struct rxrpc_local *local = call->local;
-       int ret = 0;
+       int ret = -ENOMEM;
 
        _enter("{%d,%lx},", call->debug_id, call->user_call_ID);
 
index a661b062cca85431845ef3abf84205035d3029ae..872d127c9db42a6eb4d67879f25c665ae6e7f0f1 100644 (file)
@@ -377,6 +377,7 @@ static int gred_offload_dump_stats(struct Qdisc *sch)
        /* Even if driver returns failure adjust the stats - in case offload
         * ended but driver still wants to adjust the values.
         */
+       sch_tree_lock(sch);
        for (i = 0; i < MAX_DPs; i++) {
                if (!table->tab[i])
                        continue;
@@ -393,6 +394,7 @@ static int gred_offload_dump_stats(struct Qdisc *sch)
                sch->qstats.overlimits += hw_stats->stats.qstats[i].overlimits;
        }
        _bstats_update(&sch->bstats, bytes, packets);
+       sch_tree_unlock(sch);
 
        kfree(hw_stats);
        return ret;
index 2238edece1a462991ff048331e7978b37cd1b170..cc28e41fb745c0fb23289de413264211912968c7 100644 (file)
@@ -431,7 +431,10 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
        while (cl->cmode == HTB_MAY_BORROW && p && mask) {
                m = mask;
                while (m) {
-                       int prio = ffz(~m);
+                       unsigned int prio = ffz(~m);
+
+                       if (WARN_ON_ONCE(prio > ARRAY_SIZE(p->inner.clprio)))
+                               break;
                        m &= ~(1 << prio);
 
                        if (p->inner.clprio[prio].feed.rb_node)
@@ -1549,7 +1552,7 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
        struct tc_htb_qopt_offload offload_opt;
        struct netdev_queue *dev_queue;
        struct Qdisc *q = cl->leaf.q;
-       struct Qdisc *old = NULL;
+       struct Qdisc *old;
        int err;
 
        if (cl->level)
@@ -1557,14 +1560,17 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
 
        WARN_ON(!q);
        dev_queue = htb_offload_get_queue(cl);
-       old = htb_graft_helper(dev_queue, NULL);
-       if (destroying)
-               /* Before HTB is destroyed, the kernel grafts noop_qdisc to
-                * all queues.
+       /* When destroying, caller qdisc_graft grafts the new qdisc and invokes
+        * qdisc_put for the qdisc being destroyed. htb_destroy_class_offload
+        * does not need to graft or qdisc_put the qdisc being destroyed.
+        */
+       if (!destroying) {
+               old = htb_graft_helper(dev_queue, NULL);
+               /* Last qdisc grafted should be the same as cl->leaf.q when
+                * calling htb_delete.
                 */
-               WARN_ON(!(old->flags & TCQ_F_BUILTIN));
-       else
                WARN_ON(old != q);
+       }
 
        if (cl->parent) {
                _bstats_update(&cl->parent->bstats_bias,
@@ -1581,10 +1587,12 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
        };
        err = htb_offload(qdisc_dev(sch), &offload_opt);
 
-       if (!err || destroying)
-               qdisc_put(old);
-       else
-               htb_graft_helper(dev_queue, old);
+       if (!destroying) {
+               if (!err)
+                       qdisc_put(old);
+               else
+                       htb_graft_helper(dev_queue, old);
+       }
 
        if (last_child)
                return err;
index 570389f6cdd7dbab5749dc06d886555305cbf623..c322a61eaeeac4b3744ec7b347d1256a19dfb244 100644 (file)
@@ -1700,6 +1700,7 @@ static void taprio_reset(struct Qdisc *sch)
        int i;
 
        hrtimer_cancel(&q->advance_timer);
+
        if (q->qdiscs) {
                for (i = 0; i < dev->num_tx_queues; i++)
                        if (q->qdiscs[i])
@@ -1720,6 +1721,7 @@ static void taprio_destroy(struct Qdisc *sch)
         * happens in qdisc_create(), after taprio_init() has been called.
         */
        hrtimer_cancel(&q->advance_timer);
+       qdisc_synchronize(sch);
 
        taprio_disable_offload(dev, q, NULL);
 
index 59e653b528b1faec6c6fcf73f0dd42633880e08d..6b95d3ba8fe1cecf4d75956bf87546b1f1a81c4f 100644 (file)
@@ -73,6 +73,12 @@ int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
                }
        }
 
+       /* If somehow no addresses were found that can be used with this
+        * scope, it's an error.
+        */
+       if (list_empty(&dest->address_list))
+               error = -ENETUNREACH;
+
 out:
        if (error)
                sctp_bind_addr_clean(dest);
index ca1eba95c293483b95b361658bdba69318a050a9..2f66a200651742d318d90778a9452fe9ad656a2c 100644 (file)
@@ -196,9 +196,7 @@ void sctp_transport_reset_hb_timer(struct sctp_transport *transport)
 
        /* When a data chunk is sent, reset the heartbeat interval.  */
        expires = jiffies + sctp_transport_timeout(transport);
-       if ((time_before(transport->hb_timer.expires, expires) ||
-            !timer_pending(&transport->hb_timer)) &&
-           !mod_timer(&transport->hb_timer,
+       if (!mod_timer(&transport->hb_timer,
                       expires + get_random_u32_below(transport->rto)))
                sctp_transport_hold(transport);
 }
index 9ed9786341259ea6dc4ed1a255f35534f9f902bf..a83d2b4275fa69a15931d193183f7ba7ed0fc935 100644 (file)
@@ -2427,7 +2427,7 @@ static bool tls_is_tx_ready(struct tls_sw_context_tx *ctx)
 {
        struct tls_rec *rec;
 
-       rec = list_first_entry(&ctx->tx_list, struct tls_rec, list);
+       rec = list_first_entry_or_null(&ctx->tx_list, struct tls_rec, list);
        if (!rec)
                return false;
 
index 3b55502b296570ed0305b9d679cdf3e10b2f13f3..5c7ad301d742e8776320c51d13c7d9eff0793992 100644 (file)
@@ -482,6 +482,12 @@ static int x25_listen(struct socket *sock, int backlog)
        int rc = -EOPNOTSUPP;
 
        lock_sock(sk);
+       if (sock->state != SS_UNCONNECTED) {
+               rc = -EINVAL;
+               release_sock(sk);
+               return rc;
+       }
+
        if (sk->sk_state != TCP_LISTEN) {
                memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
                sk->sk_max_ack_backlog = backlog;
index 29bf9c2e8aee6139881305fd47353d6f51e46d91..30103325696d801df5458f7f398a997835fbe8fe 100644 (file)
@@ -142,17 +142,24 @@ pub fn call_printk_cont(args: fmt::Arguments<'_>) {
 macro_rules! print_macro (
     // The non-continuation cases (most of them, e.g. `INFO`).
     ($format_string:path, false, $($arg:tt)+) => (
-        // SAFETY: This hidden macro should only be called by the documented
-        // printing macros which ensure the format string is one of the fixed
-        // ones. All `__LOG_PREFIX`s are null-terminated as they are generated
-        // by the `module!` proc macro or fixed values defined in a kernel
-        // crate.
-        unsafe {
-            $crate::print::call_printk(
-                &$format_string,
-                crate::__LOG_PREFIX,
-                format_args!($($arg)+),
-            );
+        // To remain sound, `arg`s must be expanded outside the `unsafe` block.
+        // Typically one would use a `let` binding for that; however, `format_args!`
+        // takes borrows on the arguments, but does not extend the scope of temporaries.
+        // Therefore, a `match` expression is used to keep them around, since
+        // the scrutinee is kept until the end of the `match`.
+        match format_args!($($arg)+) {
+            // SAFETY: This hidden macro should only be called by the documented
+            // printing macros which ensure the format string is one of the fixed
+            // ones. All `__LOG_PREFIX`s are null-terminated as they are generated
+            // by the `module!` proc macro or fixed values defined in a kernel
+            // crate.
+            args => unsafe {
+                $crate::print::call_printk(
+                    &$format_string,
+                    crate::__LOG_PREFIX,
+                    args,
+                );
+            }
         }
     );
 
index d52370cad0b6e5ea5d2a44342bcf0044f53a1d5d..a825dbd2c9cfd21e3a0dbd902ac981d45e6549ca 100644 (file)
@@ -152,6 +152,7 @@ static void __exit ftrace_direct_multi_exit(void)
 {
        kthread_stop(simple_tsk);
        unregister_ftrace_direct_multi(&direct, my_tramp);
+       ftrace_free_filter(&direct);
 }
 
 module_init(ftrace_direct_multi_init);
index ec1088922517dfbdab42d2efb9a628b7094a15fb..d955a26506053fa9912db48a477a78757b2c8b1d 100644 (file)
@@ -79,6 +79,7 @@ static int __init ftrace_direct_multi_init(void)
 static void __exit ftrace_direct_multi_exit(void)
 {
        unregister_ftrace_direct_multi(&direct, (unsigned long) my_tramp);
+       ftrace_free_filter(&direct);
 }
 
 module_init(ftrace_direct_multi_init);
index 836391e5d2097785b0a845ed0190d2ea3b31b65e..4815a8e32227d308cbb230e3313f795bcf61d665 100644 (file)
@@ -66,9 +66,13 @@ endif
 # Don't stop modules_install even if we can't sign external modules.
 #
 ifeq ($(CONFIG_MODULE_SIG_ALL),y)
+ifeq ($(filter pkcs11:%, $(CONFIG_MODULE_SIG_KEY)),)
 sig-key := $(if $(wildcard $(CONFIG_MODULE_SIG_KEY)),,$(srctree)/)$(CONFIG_MODULE_SIG_KEY)
+else
+sig-key := $(CONFIG_MODULE_SIG_KEY)
+endif
 quiet_cmd_sign = SIGN    $@
-      cmd_sign = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) $(sig-key) certs/signing_key.x509 $@ \
+      cmd_sign = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) "$(sig-key)" certs/signing_key.x509 $@ \
                  $(if $(KBUILD_EXTMOD),|| true)
 else
 quiet_cmd_sign :=
old mode 100755 (executable)
new mode 100644 (file)
index 9a1895747b153671c3a400e48bb5af5e987920e9..84c730da36dd3ff54027f6b449f82843b59c1dbb 100644 (file)
@@ -71,7 +71,9 @@
 #include "varasm.h"
 #include "stor-layout.h"
 #include "internal-fn.h"
+#include "gimple.h"
 #include "gimple-expr.h"
+#include "gimple-iterator.h"
 #include "gimple-fold.h"
 #include "context.h"
 #include "tree-ssa-alias.h"
 #include "tree-eh.h"
 #include "stmt.h"
 #include "gimplify.h"
-#include "gimple.h"
 #include "tree-phinodes.h"
 #include "tree-cfg.h"
-#include "gimple-iterator.h"
 #include "gimple-ssa.h"
 #include "ssa-iterators.h"
 
index 4192855f5b8b5c1e3b64480c11c8b1e001a89dcd..7eca035472d3030822f46c58cd8989b59601306b 100755 (executable)
@@ -26,11 +26,20 @@ try:
        # If the MAKEFLAGS variable contains multiple instances of the
        # --jobserver-auth= option, the last one is relevant.
        fds = opts[-1].split("=", 1)[1]
-       reader, writer = [int(x) for x in fds.split(",", 1)]
-       # Open a private copy of reader to avoid setting nonblocking
-       # on an unexpecting process with the same reader fd.
-       reader = os.open("/proc/self/fd/%d" % (reader),
-                        os.O_RDONLY | os.O_NONBLOCK)
+
+       # Starting with GNU Make 4.4, named pipes are used for reader and writer.
+       # Example argument: --jobserver-auth=fifo:/tmp/GMfifo8134
+       _, _, path = fds.partition('fifo:')
+
+       if path:
+               reader = os.open(path, os.O_RDONLY | os.O_NONBLOCK)
+               writer = os.open(path, os.O_WRONLY)
+       else:
+               reader, writer = [int(x) for x in fds.split(",", 1)]
+               # Open a private copy of reader to avoid setting nonblocking
+               # on an unexpecting process with the same reader fd.
+               reader = os.open("/proc/self/fd/%d" % (reader),
+                                os.O_RDONLY | os.O_NONBLOCK)
 
        # Read out as many jobserver slots as possible.
        while True:
index c8a3f9cd52f0281c3b070463596b8960f4d22412..0b2ff775b2e33a82749d6efa4820825e3118ba22 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 /conf
 /[gmnq]conf
+/[gmnq]conf-bin
 /[gmnq]conf-cflags
 /[gmnq]conf-libs
-/qconf-bin
 /qconf-moc.cc
index 0b1d15efaeb0c2c71fbe3d31d06c1bba73240005..af1c96198f4919c1af966e5fc06dcddb7c405fef 100644 (file)
@@ -209,7 +209,7 @@ $(obj)/gconf: | $(obj)/gconf-libs
 $(obj)/gconf.o: | $(obj)/gconf-cflags
 
 # check if necessary packages are available, and configure build flags
-cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin)
+cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin); touch $(obj)/$*conf-bin
 
 $(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh
        $(call cmd,conf_cfg)
index adab28fa7f892f1704e498530f01ae3a69d5a05a..094e52c979a8cdbea1af95da6fcba93104e82ff4 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 #      Output a simple RPM spec file.
-#      This version assumes a minimum of RPM 4.0.3.
+#      This version assumes a minimum of RPM 4.13
 #
 #      The only gothic bit here is redefining install_post to avoid
 #      stripping the symbols from files in the kernel which we want
index 926701162bc8322149c33d6451c41e53660fd36a..bb4f59262bbe9e1f9f425699499abfc4226b309e 100755 (executable)
@@ -12,7 +12,7 @@
 #   (note, if this is a problem with function_graph tracing, then simply
 #    replace "function" with "function_graph" in the following steps).
 #
-#  # cd /sys/kernel/debug/tracing
+#  # cd /sys/kernel/tracing
 #  # echo schedule > set_ftrace_filter
 #  # echo function > current_tracer
 #
 #
 #  # echo nop > current_tracer
 #
-#  # cat available_filter_functions > ~/full-file
+# Starting with v5.1 this can be done with numbers, making it much faster:
+#
+# The old (slow) way, for kernels before v5.1.
+#
+# [old-way] # cat available_filter_functions > ~/full-file
+#
+# [old-way] *** Note ***  this process will take several minutes to update the
+# [old-way] filters. Setting multiple functions is an O(n^2) operation, and we
+# [old-way] are dealing with thousands of functions. So go have coffee, talk
+# [old-way] with your coworkers, read facebook. And eventually, this operation
+# [old-way] will end.
+#
+# The new way (using numbers) is an O(n) operation, and usually takes less than a second.
+#
+# seq `wc -l available_filter_functions | cut -d' ' -f1` > ~/full-file
+#
+# This will create a sequence of numbers that match the functions in
+# available_filter_functions, and when echoing in a number into the
+# set_ftrace_filter file, it will enable the corresponding function in
+# O(1) time. Making enabling all functions O(n) where n is the number of
+# functions to enable.
+#
+# For either the new or old way, the rest of the operations remain the same.
+#
 #  # ftrace-bisect ~/full-file ~/test-file ~/non-test-file
 #  # cat ~/test-file > set_ftrace_filter
 #
-# *** Note *** this will take several minutes. Setting multiple functions is
-# an O(n^2) operation, and we are dealing with thousands of functions. So go
-# have  coffee, talk with your coworkers, read facebook. And eventually, this
-# operation will end.
-#
 #  # echo function > current_tracer
 #
 # If it crashes, we know that ~/test-file has a bad function.
 #
 #   Reboot back to test kernel.
 #
-#     # cd /sys/kernel/debug/tracing
+#     # cd /sys/kernel/tracing
 #     # mv ~/test-file ~/full-file
 #
 # If it didn't crash.
index b9f867100a9ff54f6c31a7c6e8a37d0a72457cab..fad75be5f381d6e0d16466fa8b0b47fcfd092a23 100644 (file)
@@ -6,13 +6,11 @@ config SECURITY_TOMOYO
        select SECURITYFS
        select SECURITY_PATH
        select SECURITY_NETWORK
-       select SRCU
-       select BUILD_BIN2C
        default n
        help
          This selects TOMOYO Linux, pathname-based access control.
          Required userspace tools and further information may be
-         found at <http://tomoyo.sourceforge.jp/>.
+         found at <https://tomoyo.osdn.jp/>.
          If you are unsure how to answer this question, answer N.
 
 config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY
index cca5a3012fee2e564ffa0ae293d1e8e223d80689..884ff155edc3929eff38bd084ba8893af86b6b17 100644 (file)
@@ -2,15 +2,18 @@
 obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
 
 targets += builtin-policy.h
-define do_policy
-echo "static char tomoyo_builtin_$(1)[] __initdata ="; \
-$(objtree)/scripts/bin2c <$(firstword $(wildcard $(obj)/policy/$(1).conf $(srctree)/$(src)/policy/$(1).conf.default) /dev/null); \
-echo ";"
-endef
-quiet_cmd_policy  = POLICY  $@
-      cmd_policy  = ($(call do_policy,profile); $(call do_policy,exception_policy); $(call do_policy,domain_policy); $(call do_policy,manager); $(call do_policy,stat)) >$@
 
-$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(src)/policy/*.conf.default) FORCE
+quiet_cmd_policy = POLICY  $@
+      cmd_policy = { \
+       $(foreach x, profile exception_policy domain_policy manager stat, \
+       printf 'static char tomoyo_builtin_$x[] __initdata =\n'; \
+       sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/\t"\1\\n"/' -- $(firstword $(filter %/$x.conf %/$x.conf.default, $^) /dev/null);  \
+       printf '\t"";\n';) \
+       } > $@
+
+$(obj)/builtin-policy.h: $(wildcard $(obj)/policy/*.conf $(srctree)/$(src)/policy/*.conf.default) FORCE
        $(call if_changed,policy)
 
+ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
 $(obj)/common.o: $(obj)/builtin-policy.h
+endif
index 81025f50a54229b080b9069b8003a891bb5e16a7..f901504b5afc17aef00a1bf1dafb277098624e1a 100644 (file)
@@ -541,16 +541,15 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
        struct sg_table *sgt;
        void *p;
 
+#ifdef CONFIG_SND_DMA_SGBUF
+       if (cpu_feature_enabled(X86_FEATURE_XENPV))
+               return snd_dma_sg_fallback_alloc(dmab, size);
+#endif
        sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
                                      DEFAULT_GFP, 0);
 #ifdef CONFIG_SND_DMA_SGBUF
-       if (!sgt && !get_dma_ops(dmab->dev.dev)) {
-               if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
-                       dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
-               else
-                       dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
+       if (!sgt && !get_dma_ops(dmab->dev.dev))
                return snd_dma_sg_fallback_alloc(dmab, size);
-       }
 #endif
        if (!sgt)
                return NULL;
@@ -717,19 +716,38 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
 
 /* Fallback SG-buffer allocations for x86 */
 struct snd_dma_sg_fallback {
+       bool use_dma_alloc_coherent;
        size_t count;
        struct page **pages;
+       /* DMA address array; the first page contains #pages in ~PAGE_MASK */
+       dma_addr_t *addrs;
 };
 
 static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
                                       struct snd_dma_sg_fallback *sgbuf)
 {
-       bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
-       size_t i;
-
-       for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
-               do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
+       size_t i, size;
+
+       if (sgbuf->pages && sgbuf->addrs) {
+               i = 0;
+               while (i < sgbuf->count) {
+                       if (!sgbuf->pages[i] || !sgbuf->addrs[i])
+                               break;
+                       size = sgbuf->addrs[i] & ~PAGE_MASK;
+                       if (WARN_ON(!size))
+                               break;
+                       if (sgbuf->use_dma_alloc_coherent)
+                               dma_free_coherent(dmab->dev.dev, size << PAGE_SHIFT,
+                                                 page_address(sgbuf->pages[i]),
+                                                 sgbuf->addrs[i] & PAGE_MASK);
+                       else
+                               do_free_pages(page_address(sgbuf->pages[i]),
+                                             size << PAGE_SHIFT, false);
+                       i += size;
+               }
+       }
        kvfree(sgbuf->pages);
+       kvfree(sgbuf->addrs);
        kfree(sgbuf);
 }
 
@@ -738,24 +756,36 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
        struct snd_dma_sg_fallback *sgbuf;
        struct page **pagep, *curp;
        size_t chunk, npages;
+       dma_addr_t *addrp;
        dma_addr_t addr;
        void *p;
-       bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
+
+       /* correct the type */
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG)
+               dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
+       else if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
+               dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
 
        sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
        if (!sgbuf)
                return NULL;
+       sgbuf->use_dma_alloc_coherent = cpu_feature_enabled(X86_FEATURE_XENPV);
        size = PAGE_ALIGN(size);
        sgbuf->count = size >> PAGE_SHIFT;
        sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
-       if (!sgbuf->pages)
+       sgbuf->addrs = kvcalloc(sgbuf->count, sizeof(*sgbuf->addrs), GFP_KERNEL);
+       if (!sgbuf->pages || !sgbuf->addrs)
                goto error;
 
        pagep = sgbuf->pages;
-       chunk = size;
+       addrp = sgbuf->addrs;
+       chunk = (PAGE_SIZE - 1) << PAGE_SHIFT; /* to fit in low bits in addrs */
        while (size > 0) {
                chunk = min(size, chunk);
-               p = do_alloc_pages(dmab->dev.dev, chunk, &addr, wc);
+               if (sgbuf->use_dma_alloc_coherent)
+                       p = dma_alloc_coherent(dmab->dev.dev, chunk, &addr, DEFAULT_GFP);
+               else
+                       p = do_alloc_pages(dmab->dev.dev, chunk, &addr, false);
                if (!p) {
                        if (chunk <= PAGE_SIZE)
                                goto error;
@@ -767,17 +797,25 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
                size -= chunk;
                /* fill pages */
                npages = chunk >> PAGE_SHIFT;
+               *addrp = npages; /* store in lower bits */
                curp = virt_to_page(p);
-               while (npages--)
+               while (npages--) {
                        *pagep++ = curp++;
+                       *addrp++ |= addr;
+                       addr += PAGE_SIZE;
+               }
        }
 
        p = vmap(sgbuf->pages, sgbuf->count, VM_MAP, PAGE_KERNEL);
        if (!p)
                goto error;
+
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
+               set_pages_array_wc(sgbuf->pages, sgbuf->count);
+
        dmab->private_data = sgbuf;
        /* store the first page address for convenience */
-       dmab->addr = snd_sgbuf_get_addr(dmab, 0);
+       dmab->addr = sgbuf->addrs[0] & PAGE_MASK;
        return p;
 
  error:
@@ -787,10 +825,23 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
 
 static void snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab)
 {
+       struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
+
+       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
+               set_pages_array_wb(sgbuf->pages, sgbuf->count);
        vunmap(dmab->area);
        __snd_dma_sg_fallback_free(dmab, dmab->private_data);
 }
 
+static dma_addr_t snd_dma_sg_fallback_get_addr(struct snd_dma_buffer *dmab,
+                                              size_t offset)
+{
+       struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
+       size_t index = offset >> PAGE_SHIFT;
+
+       return (sgbuf->addrs[index] & PAGE_MASK) | (offset & ~PAGE_MASK);
+}
+
 static int snd_dma_sg_fallback_mmap(struct snd_dma_buffer *dmab,
                                    struct vm_area_struct *area)
 {
@@ -805,8 +856,8 @@ static const struct snd_malloc_ops snd_dma_sg_fallback_ops = {
        .alloc = snd_dma_sg_fallback_alloc,
        .free = snd_dma_sg_fallback_free,
        .mmap = snd_dma_sg_fallback_mmap,
+       .get_addr = snd_dma_sg_fallback_get_addr,
        /* reuse vmalloc helpers */
-       .get_addr = snd_dma_vmalloc_get_addr,
        .get_page = snd_dma_vmalloc_get_page,
        .get_chunk_size = snd_dma_vmalloc_get_chunk_size,
 };
index a900fc0e76440cb73a7eeff3dd747ee7a85e0427..88d1f4b56e4be401d1cb45db2eba4875a1d4b712 100644 (file)
@@ -87,6 +87,10 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
                        return -EFAULT;
 
                count = consumed;
+       } else {
+               spin_unlock_irq(&motu->lock);
+
+               count = 0;
        }
 
        return count;
index 1a868dd9dc4b6886a8dda83514052910e52014cc..890c2f7c33fc21f1d82d1e17abdc0e928046c80d 100644 (file)
@@ -144,6 +144,7 @@ static int hda_codec_driver_probe(struct device *dev)
 
  error:
        snd_hda_codec_cleanup_for_unbind(codec);
+       codec->preset = NULL;
        return err;
 }
 
@@ -166,6 +167,7 @@ static int hda_codec_driver_remove(struct device *dev)
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
        snd_hda_codec_cleanup_for_unbind(codec);
+       codec->preset = NULL;
        module_put(dev->driver->owner);
        return 0;
 }
index edd653ece70d7387db8f53faeee5e0ba98c800fd..ac1cc7c5290e3d7a974b8618cd9772ee04d40b8f 100644 (file)
@@ -795,7 +795,6 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
        snd_array_free(&codec->cvt_setups);
        snd_array_free(&codec->spdif_out);
        snd_array_free(&codec->verbs);
-       codec->preset = NULL;
        codec->follower_dig_outs = NULL;
        codec->spdif_status_reset = 0;
        snd_array_free(&codec->mixers);
index 6fab7c8fc19ae19727d9b3b905579c3a5e3cfee1..db9518de9343c38d528e671f08bec56c94bb62b6 100644 (file)
@@ -9202,6 +9202,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
+       SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
        SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
@@ -9432,6 +9433,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
index aea7fae2ca4b2b9dd594a24eca935bda569fd0f9..2994f85bc1b9a1fafded6b68e2af598b3d297721 100644 (file)
@@ -819,6 +819,9 @@ static int add_secret_dac_path(struct hda_codec *codec)
                return 0;
        nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
                                       ARRAY_SIZE(conn) - 1);
+       if (nums < 0)
+               return nums;
+
        for (i = 0; i < nums; i++) {
                if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
                        return 0;
index 2fe8df86053ae8035ed52a30070662ff3b939c6a..89499542c803fedf33beb06495e8a4403e415b67 100644 (file)
@@ -198,9 +198,11 @@ static int st_es8336_late_probe(struct snd_soc_card *card)
        int ret;
 
        adev = acpi_dev_get_first_match_dev("ESSX8336", NULL, -1);
-       if (adev)
-               put_device(&adev->dev);
+       if (!adev)
+               return -ENODEV;
+
        codec_dev = acpi_get_first_physical_node(adev);
+       acpi_dev_put(adev);
        if (!codec_dev)
                dev_err(card->dev, "can not find codec dev\n");
 
index 0d283e41f66dc0d8249e84f9e1f85a6b8ea12095..36314753923b8c6adf458d5d7af6ca15681ac800 100644 (file)
@@ -227,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 14 2022"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 15 2022"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
@@ -234,6 +241,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "RB"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Swift SFA16-41"),
+               }
+       },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "IRBIS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"),
+               }
+       },
        {}
 };
 
index 26066682c983e6d34d65c70ef1af5df3e98633d2..3b0e715549c9c10ed871821e44a50c4e49160e73 100644 (file)
@@ -1191,18 +1191,12 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client)
        if (pdata) {
                cs42l56->pdata = *pdata;
        } else {
-               pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
-                                    GFP_KERNEL);
-               if (!pdata)
-                       return -ENOMEM;
-
                if (i2c_client->dev.of_node) {
                        ret = cs42l56_handle_of_data(i2c_client,
                                                     &cs42l56->pdata);
                        if (ret != 0)
                                return ret;
                }
-               cs42l56->pdata = *pdata;
        }
 
        if (cs42l56->pdata.gpio_nreset) {
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 966ba4909204a6411d3d052e334462ae0f9a16dc..58fdb4e9fd978b1c7446140e6f5ad7befa42adba 100644 (file)
@@ -1359,8 +1359,8 @@ static struct snd_soc_dai_driver wsa883x_dais[] = {
                        .stream_name = "SPKR Playback",
                        .rates = WSA883X_RATES | WSA883X_FRAC_RATES,
                        .formats = WSA883X_FORMATS,
-                       .rate_max = 8000,
-                       .rate_min = 352800,
+                       .rate_min = 8000,
+                       .rate_max = 352800,
                        .channels_min = 1,
                        .channels_max = 1,
                },
index 2ca24273c4910ae840e40292258ab571f0b5099b..6375018507288cbc0ca2176700d958afc4d6ab29 100644 (file)
@@ -481,6 +481,29 @@ err_remap_bar0:
        return ret;
 }
 
+static void avs_pci_shutdown(struct pci_dev *pci)
+{
+       struct hdac_bus *bus = pci_get_drvdata(pci);
+       struct avs_dev *adev = hdac_to_avs(bus);
+
+       cancel_work_sync(&adev->probe_work);
+       avs_ipc_block(adev->ipc);
+
+       snd_hdac_stop_streams(bus);
+       avs_dsp_op(adev, int_control, false);
+       snd_hdac_ext_bus_ppcap_int_enable(bus, false);
+       snd_hdac_ext_bus_link_power_down_all(bus);
+
+       snd_hdac_bus_stop_chip(bus);
+       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
+
+       if (avs_platattr_test(adev, CLDMA))
+               pci_free_irq(pci, 0, &code_loader);
+       pci_free_irq(pci, 0, adev);
+       pci_free_irq(pci, 0, bus);
+       pci_free_irq_vectors(pci);
+}
+
 static void avs_pci_remove(struct pci_dev *pci)
 {
        struct hdac_device *hdev, *save;
@@ -739,6 +762,7 @@ static struct pci_driver avs_pci_driver = {
        .id_table = avs_ids,
        .probe = avs_pci_probe,
        .remove = avs_pci_remove,
+       .shutdown = avs_pci_shutdown,
        .driver = {
                .pm = &avs_dev_pm,
        },
index 09d1f0f6d68658b77581458466d94c85f0993510..df157b01df8bba58d6cd7e9c9c0c69ad6c5e7b24 100644 (file)
@@ -497,21 +497,28 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
        if (adev) {
                snprintf(codec_name, sizeof(codec_name),
                         "i2c-%s", acpi_dev_name(adev));
-               put_device(&adev->dev);
                byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
        } else {
                dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
                return -ENXIO;
        }
 
+       codec_dev = acpi_get_first_physical_node(adev);
+       acpi_dev_put(adev);
+       if (!codec_dev)
+               return -EPROBE_DEFER;
+       priv->codec_dev = get_device(codec_dev);
+
        /* override platform name, if required */
        byt_cht_es8316_card.dev = dev;
        platform_name = mach->mach_params.platform;
 
        ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
                                                    platform_name);
-       if (ret)
+       if (ret) {
+               put_device(codec_dev);
                return ret;
+       }
 
        /* Check for BYTCR or other platform and setup quirks */
        dmi_id = dmi_first_match(byt_cht_es8316_quirk_table);
@@ -539,13 +546,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
 
        /* get the clock */
        priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
-       if (IS_ERR(priv->mclk))
+       if (IS_ERR(priv->mclk)) {
+               put_device(codec_dev);
                return dev_err_probe(dev, PTR_ERR(priv->mclk), "clk_get pmc_plt_clk_3 failed\n");
-
-       codec_dev = acpi_get_first_physical_node(adev);
-       if (!codec_dev)
-               return -EPROBE_DEFER;
-       priv->codec_dev = get_device(codec_dev);
+       }
 
        if (quirk & BYT_CHT_ES8316_JD_INVERTED)
                props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
index 4699ca79f3ea679b40059f59ce43f325d063bc78..79e0039c79a388f911d90f71f5025aa8a6bf452b 100644 (file)
@@ -1636,13 +1636,18 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
        if (adev) {
                snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
                         "i2c-%s", acpi_dev_name(adev));
-               put_device(&adev->dev);
                byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
        } else {
                dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
                return -ENXIO;
        }
 
+       codec_dev = acpi_get_first_physical_node(adev);
+       acpi_dev_put(adev);
+       if (!codec_dev)
+               return -EPROBE_DEFER;
+       priv->codec_dev = get_device(codec_dev);
+
        /*
         * swap SSP0 if bytcr is detected
         * (will be overridden if DMI quirk is detected)
@@ -1717,11 +1722,6 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
                byt_rt5640_quirk = quirk_override;
        }
 
-       codec_dev = acpi_get_first_physical_node(adev);
-       if (!codec_dev)
-               return -EPROBE_DEFER;
-       priv->codec_dev = get_device(codec_dev);
-
        if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {
                acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),
                                          byt_rt5640_hp_elitepad_1000g2_gpios);
index 81ac6eeda2e6eaf6d8629e172187e51c963a8b9e..8fca9b82d4d04ae189c136436747230485b3644e 100644 (file)
@@ -922,7 +922,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
        if (adev) {
                snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
                         "i2c-%s", acpi_dev_name(adev));
-               put_device(&adev->dev);
                byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name;
        } else {
                dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
@@ -930,6 +929,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
        }
 
        codec_dev = acpi_get_first_physical_node(adev);
+       acpi_dev_put(adev);
        if (!codec_dev)
                return -EPROBE_DEFER;
        priv->codec_dev = get_device(codec_dev);
index 1669eb3bd80f3ccac067eb3ea6332352e0019e23..c0706537f6736a4112642a121d53c961da875a5f 100644 (file)
@@ -411,9 +411,9 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
                return -ENOENT;
        }
        snprintf(codec_name, sizeof(codec_name), "spi-%s", acpi_dev_name(adev));
-       put_device(&adev->dev);
 
        codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, codec_name);
+       acpi_dev_put(adev);
        if (!codec_dev)
                return -EPROBE_DEFER;
 
index e38bd2831e6ac77a6e7486ea47889113e0246223..e9d190cb13b0ad5a912d3691c71490a319b02d32 100644 (file)
@@ -336,6 +336,9 @@ static int create_spk_amp_dai_links(struct device *dev,
        links[*id].platforms = platform_component;
        links[*id].num_platforms = ARRAY_SIZE(platform_component);
        links[*id].dpcm_playback = 1;
+       /* firmware-generated echo reference */
+       links[*id].dpcm_capture = 1;
+
        links[*id].no_pcm = 1;
        links[*id].cpus = &cpus[*id];
        links[*id].num_cpus = 1;
index 773e5d1d87d460362bb7d440544fe764cac2ad08..894b6610b9e27d7da84bcf28efc94da0bf2f2c07 100644 (file)
@@ -681,7 +681,6 @@ static int sof_es8336_probe(struct platform_device *pdev)
        if (adev) {
                snprintf(codec_name, sizeof(codec_name),
                         "i2c-%s", acpi_dev_name(adev));
-               put_device(&adev->dev);
                dai_links[0].codecs->name = codec_name;
 
                /* also fixup codec dai name if relevant */
@@ -692,16 +691,19 @@ static int sof_es8336_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
-                                                   mach->mach_params.platform);
-       if (ret)
-               return ret;
-
        codec_dev = acpi_get_first_physical_node(adev);
+       acpi_dev_put(adev);
        if (!codec_dev)
                return -EPROBE_DEFER;
        priv->codec_dev = get_device(codec_dev);
 
+       ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card,
+                                                   mach->mach_params.platform);
+       if (ret) {
+               put_device(codec_dev);
+               return ret;
+       }
+
        if (quirk & SOF_ES8336_JD_INVERTED)
                props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
 
index a800854c2831a130d1d549be3d7fe0e521f99202..6794a0249a9ad1ceaf21656cecebfc21335b16be 100644 (file)
@@ -487,8 +487,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                        links[id].num_codecs = ARRAY_SIZE(max_98373_components);
                        links[id].init = max_98373_spk_codec_init;
                        links[id].ops = &max_98373_ops;
-                       /* feedback stream */
-                       links[id].dpcm_capture = 1;
                } else if (sof_nau8825_quirk &
                                SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
                        max_98360a_dai_link(&links[id]);
@@ -506,6 +504,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                links[id].platforms = platform_component;
                links[id].num_platforms = ARRAY_SIZE(platform_component);
                links[id].dpcm_playback = 1;
+               /* feedback stream or firmware-generated echo reference */
+               links[id].dpcm_capture = 1;
+
                links[id].no_pcm = 1;
                links[id].cpus = &cpus[id];
                links[id].num_cpus = 1;
index 2eabc4b0fafa499a6dd5e867380812dc63acd004..71a11d747622a61659cecb62f90cb298ffe6f63a 100644 (file)
@@ -761,8 +761,6 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                        links[id].num_codecs = ARRAY_SIZE(max_98373_components);
                        links[id].init = max_98373_spk_codec_init;
                        links[id].ops = &max_98373_ops;
-                       /* feedback stream */
-                       links[id].dpcm_capture = 1;
                } else if (sof_rt5682_quirk &
                                SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
                        max_98360a_dai_link(&links[id]);
@@ -789,6 +787,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                links[id].platforms = platform_component;
                links[id].num_platforms = ARRAY_SIZE(platform_component);
                links[id].dpcm_playback = 1;
+               /* feedback stream or firmware-generated echo reference */
+               links[id].dpcm_capture = 1;
+
                links[id].no_pcm = 1;
                links[id].cpus = &cpus[id];
                links[id].num_cpus = 1;
index 94d25aeb6e7cea1603ec55be7be24903b81e5d8d..7b74f122e34004efa183ba5b6bce3ad9a2b202be 100644 (file)
@@ -258,13 +258,12 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                sof_rt1308_dai_link(&links[id]);
        } else if (sof_ssp_amp_quirk & SOF_CS35L41_SPEAKER_AMP_PRESENT) {
                cs35l41_set_dai_link(&links[id]);
-
-               /* feedback from amplifier */
-               links[id].dpcm_capture = 1;
        }
        links[id].platforms = platform_component;
        links[id].num_platforms = ARRAY_SIZE(platform_component);
        links[id].dpcm_playback = 1;
+       /* feedback from amplifier or firmware-generated echo reference */
+       links[id].dpcm_capture = 1;
        links[id].no_pcm = 1;
        links[id].cpus = &cpus[id];
        links[id].num_cpus = 1;
index 70dea8ae706e97b3cdae3cdf879765e21234a2ff..0ec6ef681012d6ecd654d7cda8a4afa4ca80efc3 100644 (file)
@@ -344,9 +344,10 @@ static ssize_t sof_ipc4_priority_mask_dfs_write(struct file *file,
                                                size_t count, loff_t *ppos)
 {
        struct sof_mtrace_priv *priv = file->private_data;
-       int id, ret;
+       unsigned int id;
        char *buf;
        u32 mask;
+       int ret;
 
        /*
         * To update Nth mask entry, write:
@@ -357,9 +358,9 @@ static ssize_t sof_ipc4_priority_mask_dfs_write(struct file *file,
        if (IS_ERR(buf))
                return PTR_ERR(buf);
 
-       ret = sscanf(buf, "%d,0x%x", &id, &mask);
+       ret = sscanf(buf, "%u,0x%x", &id, &mask);
        if (ret != 2) {
-               ret = sscanf(buf, "%d,%x", &id, &mask);
+               ret = sscanf(buf, "%u,%x", &id, &mask);
                if (ret != 2) {
                        ret = -EINVAL;
                        goto out;
index 7306a2649857a7da34a32072a087b27c66111637..865c367eb2f2bfa3067444d570cff0d9cc989865 100644 (file)
@@ -271,9 +271,9 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg
        struct snd_sof_widget *swidget = widget->dobj.private;
        struct snd_soc_dapm_path *p;
 
-       /* return if the widget is in use or if it is already unprepared */
-       if (!swidget->prepared || swidget->use_count > 1)
-               return;
+       /* skip if the widget is in use or if it is already unprepared */
+       if (!swidget || !swidget->prepared || swidget->use_count > 0)
+               goto sink_unprepare;
 
        if (widget_ops[widget->id].ipc_unprepare)
                /* unprepare the source widget */
@@ -281,6 +281,7 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg
 
        swidget->prepared = false;
 
+sink_unprepare:
        /* unprepare all widgets in the sink paths */
        snd_soc_dapm_widget_for_each_sink_path(widget, p) {
                if (!p->walking && p->sink->dobj.private) {
@@ -303,7 +304,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
        struct snd_soc_dapm_path *p;
        int ret;
 
-       if (!widget_ops[widget->id].ipc_prepare || swidget->prepared)
+       if (!swidget || !widget_ops[widget->id].ipc_prepare || swidget->prepared)
                goto sink_prepare;
 
        /* prepare the source widget */
@@ -326,7 +327,8 @@ sink_prepare:
                        p->walking = false;
                        if (ret < 0) {
                                /* unprepare the source widget */
-                               if (widget_ops[widget->id].ipc_unprepare && swidget->prepared) {
+                               if (widget_ops[widget->id].ipc_unprepare &&
+                                   swidget && swidget->prepared) {
                                        widget_ops[widget->id].ipc_unprepare(swidget);
                                        swidget->prepared = false;
                                }
@@ -429,11 +431,11 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l
 
        for_each_dapm_widgets(list, i, widget) {
                /* starting widget for playback is AIF type */
-               if (dir == SNDRV_PCM_STREAM_PLAYBACK && !WIDGET_IS_AIF(widget->id))
+               if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in)
                        continue;
 
                /* starting widget for capture is DAI type */
-               if (dir == SNDRV_PCM_STREAM_CAPTURE && !WIDGET_IS_DAI(widget->id))
+               if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_dai_out)
                        continue;
 
                switch (op) {
index 3d13fdf7590cd12fd8ffc355f23ee256711712e4..3ecd1ba7fd4b125ccc519d1a2bde1e0c6599d9bd 100644 (file)
@@ -2152,6 +2152,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_GENERIC_IMPLICIT_FB),
        DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
                   QUIRK_FLAG_IFACE_SKIP_CLOSE),
+       DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
+                  QUIRK_FLAG_FIXED_RATE),
        DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
                   QUIRK_FLAG_FIXED_RATE),
 
index abc418650fec04fda7f79c2c46f3ec255124781d..683ca3af408485aa6cdf4aa44b5988d91cd6a0f3 100644 (file)
@@ -41,7 +41,7 @@
        (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
 
 #define MIDR_CPU_MODEL(imp, partnum) \
-       (((imp)                 << MIDR_IMPLEMENTOR_SHIFT) | \
+       ((_AT(u32, imp)         << MIDR_IMPLEMENTOR_SHIFT) | \
        (0xf                    << MIDR_ARCHITECTURE_SHIFT) | \
        ((partnum)              << MIDR_PARTNUM_SHIFT))
 
@@ -80,6 +80,7 @@
 #define ARM_CPU_PART_CORTEX_X1         0xD44
 #define ARM_CPU_PART_CORTEX_A510       0xD46
 #define ARM_CPU_PART_CORTEX_A710       0xD47
+#define ARM_CPU_PART_CORTEX_A715       0xD4D
 #define ARM_CPU_PART_CORTEX_X2         0xD48
 #define ARM_CPU_PART_NEOVERSE_N2       0xD49
 #define ARM_CPU_PART_CORTEX_A78C       0xD4B
 #define APPLE_CPU_PART_M1_FIRESTORM_PRO        0x025
 #define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028
 #define APPLE_CPU_PART_M1_FIRESTORM_MAX        0x029
+#define APPLE_CPU_PART_M2_BLIZZARD     0x032
+#define APPLE_CPU_PART_M2_AVALANCHE    0x033
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
 #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_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)
 #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
 #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
 #define MIDR_CORTEX_A78C       MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
 #define MIDR_APPLE_M1_FIRESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO)
 #define MIDR_APPLE_M1_ICESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX)
 #define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
+#define MIDR_APPLE_M2_BLIZZARD MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD)
+#define MIDR_APPLE_M2_AVALANCHE MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE)
 #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
index 316917b9870704de245f002cb4261c46f8a2fea4..a7a857f1784d80d6264eeebecbeb371c7d13ba5b 100644 (file)
@@ -43,6 +43,7 @@
 #define __KVM_HAVE_VCPU_EVENTS
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_DIRTY_LOG_PAGE_OFFSET 64
 
 #define KVM_REG_SIZE(id)                                               \
        (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
index 649e50a8f9ddff8780e71fb7d3862b094872a322..e48deab8901d4ecb9fddaaf334247e27fb6c1762 100644 (file)
@@ -206,6 +206,8 @@ struct kvm_msr_list {
 struct kvm_msr_filter_range {
 #define KVM_MSR_FILTER_READ  (1 << 0)
 #define KVM_MSR_FILTER_WRITE (1 << 1)
+#define KVM_MSR_FILTER_RANGE_VALID_MASK (KVM_MSR_FILTER_READ | \
+                                        KVM_MSR_FILTER_WRITE)
        __u32 flags;
        __u32 nmsrs; /* number of msrs in bitmap */
        __u32 base;  /* MSR index the bitmap starts at */
@@ -214,8 +216,11 @@ struct kvm_msr_filter_range {
 
 #define KVM_MSR_FILTER_MAX_RANGES 16
 struct kvm_msr_filter {
+#ifndef __KERNEL__
 #define KVM_MSR_FILTER_DEFAULT_ALLOW (0 << 0)
+#endif
 #define KVM_MSR_FILTER_DEFAULT_DENY  (1 << 0)
+#define KVM_MSR_FILTER_VALID_MASK (KVM_MSR_FILTER_DEFAULT_DENY)
        __u32 flags;
        struct kvm_msr_filter_range ranges[KVM_MSR_FILTER_MAX_RANGES];
 };
index 6c122952c5892fa070c1c2e5d3232cf43c30d210..5dee2b98ab60439fed115d0aae0e558935adc571 100644 (file)
@@ -86,6 +86,7 @@ int monitor_device(const char *device_name,
                        gpiotools_test_bit(values.bits, i));
        }
 
+       i = 0;
        while (1) {
                struct gpio_v2_line_event event;
 
index cc7070c7439ba6a5327d992a6cebf4fdc591f7ab..b4898ff085ded5a9a8720cf6b2e9e400835a93c4 100644 (file)
 #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 #endif // static_assert
 
+
+/*
+ * Compile time check that field has an expected offset
+ */
+#define ASSERT_STRUCT_OFFSET(type, field, expected_offset)     \
+       BUILD_BUG_ON_MSG(offsetof(type, field) != (expected_offset),    \
+               "Offset of " #field " in " #type " has changed.")
+
+
 #endif /* _LINUX_BUILD_BUG_H */
index 20522d4ba1e0d8b058876d93fd9dd554910f6263..55155e262646e5fc48b6317054b07b1c15aad02a 100644 (file)
@@ -1767,6 +1767,7 @@ struct kvm_xen_hvm_attr {
                __u8 runstate_update_flag;
                struct {
                        __u64 gfn;
+#define KVM_XEN_INVALID_GFN ((__u64)-1)
                } shared_info;
                struct {
                        __u32 send_port;
@@ -1798,6 +1799,7 @@ struct kvm_xen_hvm_attr {
        } u;
 };
 
+
 /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
 #define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
 #define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
@@ -1823,6 +1825,7 @@ struct kvm_xen_vcpu_attr {
        __u16 pad[3];
        union {
                __u64 gpa;
+#define KVM_XEN_INVALID_GPA ((__u64)-1)
                __u64 pad[8];
                struct {
                        __u64 state;
index f05670d1e39eb93be6e8120f2f2ad3df8504a143..aaf851108ca35ef08682438643f241b16f1ee418 100755 (executable)
@@ -77,7 +77,20 @@ check()
        file=${build_id_dir}/.build-id/${id:0:2}/`readlink ${link}`/elf
        echo "file: ${file}"
 
-       if [ ! -x $file ]; then
+       # Check for file permission of original file
+       # in case of pe-file.exe file
+       echo $1 | grep ".exe"
+       if [ $? -eq 0 ]; then
+               if [ -x $1  -a ! -x $file ]; then
+                       echo "failed: file ${file} executable does not exist"
+                       exit 1
+               fi
+
+               if [ ! -x $file -a ! -e $file ]; then
+                       echo "failed: file ${file} does not exist"
+                       exit 1
+               fi
+       elif [ ! -x $file ]; then
                echo "failed: file ${file} does not exist"
                exit 1
        fi
index de3701a2a2129dd6357f1910ec4878cb1005eaf9..13c3a237b9c934a534aa4a8513fea5e34864528d 100644 (file)
@@ -33,7 +33,10 @@ typedef __kernel_sa_family_t sa_family_t;
 
 struct sockaddr {
        sa_family_t     sa_family;      /* address family, AF_xxx       */
-       char            sa_data[14];    /* 14 bytes of protocol address */
+       union {
+               char sa_data_min[14];           /* Minimum 14 bytes of protocol address */
+               DECLARE_FLEX_ARRAY(char, sa_data);
+       };
 };
 
 struct linger {
index a839b30c981b7b07bcbd2993970bea98131938b8..ea9c083ab1e3fa65f84702b69f77d56213191cd7 100644 (file)
@@ -715,9 +715,13 @@ build_id_cache__add(const char *sbuild_id, const char *name, const char *realnam
                } else if (nsi && nsinfo__need_setns(nsi)) {
                        if (copyfile_ns(name, filename, nsi))
                                goto out_free;
-               } else if (link(realname, filename) && errno != EEXIST &&
-                               copyfile(name, filename))
-                       goto out_free;
+               } else if (link(realname, filename) && errno != EEXIST) {
+                       struct stat f_stat;
+
+                       if (!(stat(name, &f_stat) < 0) &&
+                                       copyfile_mode(name, filename, f_stat.st_mode))
+                               goto out_free;
+               }
        }
 
        /* Some binaries are stripped, but have .debug files with their symbol
index 0168a96373309b712002fa91e40d6efe061813c0..d47de5f270a8e94e0f977a9d2fbe43713b4e5b21 100644 (file)
@@ -42,8 +42,11 @@ static char *normalize(char *str, int runtime)
        char *dst = str;
 
        while (*str) {
-               if (*str == '\\')
+               if (*str == '\\') {
                        *dst++ = *++str;
+                       if (!*str)
+                               break;
+               }
                else if (*str == '?') {
                        char *paramval;
                        int i = 0;
index 5f195ee756d672040a0e3dab629a25dea6e9b80b..5fd1424db37d82c399b4bfda72652e54c38dfe4c 100644 (file)
@@ -7,11 +7,6 @@ all:
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
 
-ifeq (x86,$(ARCH))
-TEST_GEN_FILES += ../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py
-TEST_GEN_FILES += ../../../power/x86/intel_pstate_tracer/intel_pstate_tracer.py
-endif
-
 TEST_PROGS := run.sh
 TEST_FILES := basic.sh tbench.sh gitsource.sh
 
index 2cf0c7a3fe2326c03076281030751a36f6940901..567e07c19ecc96895b890300e6a2161b5f1a440a 100644 (file)
@@ -30,6 +30,8 @@
 #define MAX_STRERR_LEN 256
 #define MAX_TEST_NAME 80
 
+#define __always_unused        __attribute__((__unused__))
+
 #define _FAIL(errnum, fmt...)                                                  \
        ({                                                                     \
                error_at_line(0, (errnum), __func__, __LINE__, fmt);           \
@@ -321,7 +323,8 @@ static int socket_loopback(int family, int sotype)
        return socket_loopback_reuseport(family, sotype, -1);
 }
 
-static void test_insert_invalid(int family, int sotype, int mapfd)
+static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused,
+                               int family, int sotype, int mapfd)
 {
        u32 key = 0;
        u64 value;
@@ -338,7 +341,8 @@ static void test_insert_invalid(int family, int sotype, int mapfd)
                FAIL_ERRNO("map_update: expected EBADF");
 }
 
-static void test_insert_opened(int family, int sotype, int mapfd)
+static void test_insert_opened(struct test_sockmap_listen *skel __always_unused,
+                              int family, int sotype, int mapfd)
 {
        u32 key = 0;
        u64 value;
@@ -359,7 +363,8 @@ static void test_insert_opened(int family, int sotype, int mapfd)
        xclose(s);
 }
 
-static void test_insert_bound(int family, int sotype, int mapfd)
+static void test_insert_bound(struct test_sockmap_listen *skel __always_unused,
+                             int family, int sotype, int mapfd)
 {
        struct sockaddr_storage addr;
        socklen_t len;
@@ -386,7 +391,8 @@ close:
        xclose(s);
 }
 
-static void test_insert(int family, int sotype, int mapfd)
+static void test_insert(struct test_sockmap_listen *skel __always_unused,
+                       int family, int sotype, int mapfd)
 {
        u64 value;
        u32 key;
@@ -402,7 +408,8 @@ static void test_insert(int family, int sotype, int mapfd)
        xclose(s);
 }
 
-static void test_delete_after_insert(int family, int sotype, int mapfd)
+static void test_delete_after_insert(struct test_sockmap_listen *skel __always_unused,
+                                    int family, int sotype, int mapfd)
 {
        u64 value;
        u32 key;
@@ -419,7 +426,8 @@ static void test_delete_after_insert(int family, int sotype, int mapfd)
        xclose(s);
 }
 
-static void test_delete_after_close(int family, int sotype, int mapfd)
+static void test_delete_after_close(struct test_sockmap_listen *skel __always_unused,
+                                   int family, int sotype, int mapfd)
 {
        int err, s;
        u64 value;
@@ -442,7 +450,8 @@ static void test_delete_after_close(int family, int sotype, int mapfd)
                FAIL_ERRNO("map_delete: expected EINVAL/EINVAL");
 }
 
-static void test_lookup_after_insert(int family, int sotype, int mapfd)
+static void test_lookup_after_insert(struct test_sockmap_listen *skel __always_unused,
+                                    int family, int sotype, int mapfd)
 {
        u64 cookie, value;
        socklen_t len;
@@ -470,7 +479,8 @@ static void test_lookup_after_insert(int family, int sotype, int mapfd)
        xclose(s);
 }
 
-static void test_lookup_after_delete(int family, int sotype, int mapfd)
+static void test_lookup_after_delete(struct test_sockmap_listen *skel __always_unused,
+                                    int family, int sotype, int mapfd)
 {
        int err, s;
        u64 value;
@@ -493,7 +503,8 @@ static void test_lookup_after_delete(int family, int sotype, int mapfd)
        xclose(s);
 }
 
-static void test_lookup_32_bit_value(int family, int sotype, int mapfd)
+static void test_lookup_32_bit_value(struct test_sockmap_listen *skel __always_unused,
+                                    int family, int sotype, int mapfd)
 {
        u32 key, value32;
        int err, s;
@@ -523,7 +534,8 @@ close:
        xclose(s);
 }
 
-static void test_update_existing(int family, int sotype, int mapfd)
+static void test_update_existing(struct test_sockmap_listen *skel __always_unused,
+                                int family, int sotype, int mapfd)
 {
        int s1, s2;
        u64 value;
@@ -551,7 +563,7 @@ close_s1:
 /* Exercise the code path where we destroy child sockets that never
  * got accept()'ed, aka orphans, when parent socket gets closed.
  */
-static void test_destroy_orphan_child(int family, int sotype, int mapfd)
+static void do_destroy_orphan_child(int family, int sotype, int mapfd)
 {
        struct sockaddr_storage addr;
        socklen_t len;
@@ -582,10 +594,38 @@ close_srv:
        xclose(s);
 }
 
+static void test_destroy_orphan_child(struct test_sockmap_listen *skel,
+                                     int family, int sotype, int mapfd)
+{
+       int msg_verdict = bpf_program__fd(skel->progs.prog_msg_verdict);
+       int skb_verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
+       const struct test {
+               int progfd;
+               enum bpf_attach_type atype;
+       } tests[] = {
+               { -1, -1 },
+               { msg_verdict, BPF_SK_MSG_VERDICT },
+               { skb_verdict, BPF_SK_SKB_VERDICT },
+       };
+       const struct test *t;
+
+       for (t = tests; t < tests + ARRAY_SIZE(tests); t++) {
+               if (t->progfd != -1 &&
+                   xbpf_prog_attach(t->progfd, mapfd, t->atype, 0) != 0)
+                       return;
+
+               do_destroy_orphan_child(family, sotype, mapfd);
+
+               if (t->progfd != -1)
+                       xbpf_prog_detach2(t->progfd, mapfd, t->atype);
+       }
+}
+
 /* Perform a passive open after removing listening socket from SOCKMAP
  * to ensure that callbacks get restored properly.
  */
-static void test_clone_after_delete(int family, int sotype, int mapfd)
+static void test_clone_after_delete(struct test_sockmap_listen *skel __always_unused,
+                                   int family, int sotype, int mapfd)
 {
        struct sockaddr_storage addr;
        socklen_t len;
@@ -621,7 +661,8 @@ close_srv:
  * SOCKMAP, but got accept()'ed only after the parent has been removed
  * from SOCKMAP, gets cloned without parent psock state or callbacks.
  */
-static void test_accept_after_delete(int family, int sotype, int mapfd)
+static void test_accept_after_delete(struct test_sockmap_listen *skel __always_unused,
+                                    int family, int sotype, int mapfd)
 {
        struct sockaddr_storage addr;
        const u32 zero = 0;
@@ -675,7 +716,8 @@ close_srv:
 /* Check that child socket that got created and accepted while parent
  * was in a SOCKMAP is cloned without parent psock state or callbacks.
  */
-static void test_accept_before_delete(int family, int sotype, int mapfd)
+static void test_accept_before_delete(struct test_sockmap_listen *skel __always_unused,
+                                     int family, int sotype, int mapfd)
 {
        struct sockaddr_storage addr;
        const u32 zero = 0, one = 1;
@@ -784,7 +826,8 @@ done:
        return NULL;
 }
 
-static void test_syn_recv_insert_delete(int family, int sotype, int mapfd)
+static void test_syn_recv_insert_delete(struct test_sockmap_listen *skel __always_unused,
+                                       int family, int sotype, int mapfd)
 {
        struct connect_accept_ctx ctx = { 0 };
        struct sockaddr_storage addr;
@@ -847,7 +890,8 @@ static void *listen_thread(void *arg)
        return NULL;
 }
 
-static void test_race_insert_listen(int family, int socktype, int mapfd)
+static void test_race_insert_listen(struct test_sockmap_listen *skel __always_unused,
+                                   int family, int socktype, int mapfd)
 {
        struct connect_accept_ctx ctx = { 0 };
        const u32 zero = 0;
@@ -1473,7 +1517,8 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
                     int family, int sotype)
 {
        const struct op_test {
-               void (*fn)(int family, int sotype, int mapfd);
+               void (*fn)(struct test_sockmap_listen *skel,
+                          int family, int sotype, int mapfd);
                const char *name;
                int sotype;
        } tests[] = {
@@ -1520,7 +1565,7 @@ static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map,
                if (!test__start_subtest(s))
                        continue;
 
-               t->fn(family, sotype, map_fd);
+               t->fn(skel, family, sotype, map_fd);
                test_ops_cleanup(map);
        }
 }
index 68b14fdfebdb1f3d2d08afd3ac655e67a712d32a..d63fd8991b03aa9e9f3f2ec1b3f03419f8a1686c 100644 (file)
        .result_unpriv = ACCEPT,
        .insn_processed = 15,
 },
+/* The test performs a conditional 64-bit write to a stack location
+ * fp[-8], this is followed by an unconditional 8-bit write to fp[-8],
+ * then data is read from fp[-8]. This sequence is unsafe.
+ *
+ * The test would be mistakenly marked as safe w/o dst register parent
+ * preservation in verifier.c:copy_register_state() function.
+ *
+ * Note the usage of BPF_F_TEST_STATE_FREQ to force creation of the
+ * checkpoint state after conditional 64-bit assignment.
+ */
+{
+       "write tracking and register parent chain bug",
+       .insns = {
+       /* r6 = ktime_get_ns() */
+       BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
+       /* r0 = ktime_get_ns() */
+       BPF_EMIT_CALL(BPF_FUNC_ktime_get_ns),
+       /* if r0 > r6 goto +1 */
+       BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_6, 1),
+       /* *(u64 *)(r10 - 8) = 0xdeadbeef */
+       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -8, 0xdeadbeef),
+       /* r1 = 42 */
+       BPF_MOV64_IMM(BPF_REG_1, 42),
+       /* *(u8 *)(r10 - 8) = r1 */
+       BPF_STX_MEM(BPF_B, BPF_REG_FP, BPF_REG_1, -8),
+       /* r2 = *(u64 *)(r10 - 8) */
+       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_FP, -8),
+       /* exit(0) */
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .flags = BPF_F_TEST_STATE_FREQ,
+       .errstr = "invalid read from stack off -8+1 size 8",
+       .result = REJECT,
+},
index 186e1c26867ef5cacb95e1ea8fae6405018b5ed2..75c100de90ffe28e012dacde41ab71fc573da812 100755 (executable)
@@ -268,6 +268,7 @@ TEST_MATRIX=(
        # Taking away all CPUs from parent or itself if there are tasks
        # will make the partition invalid.
        "  S+ C2-3:P1:S+  C3:P1  .      .      T     C2-3    .      .     0 A1:2-3,A2:2-3 A1:P1,A2:P-1"
+       "  S+  C3:P1:S+    C3    .      .      T      P1     .      .     0 A1:3,A2:3 A1:P1,A2:P-1"
        "  S+ $SETUP_A123_PARTITIONS    .    T:C2-3   .      .      .     0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
        "  S+ $SETUP_A123_PARTITIONS    . T:C2-3:C1-3 .      .      .     0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
 
index beb944fa6fd4692fddad8875ef16fb2469c8ab74..54680dc5887fae044306040c127e5c9ff099ea7b 100644 (file)
@@ -237,6 +237,11 @@ static void guest_check_s1ptw_wr_in_dirty_log(void)
        GUEST_SYNC(CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG);
 }
 
+static void guest_check_no_s1ptw_wr_in_dirty_log(void)
+{
+       GUEST_SYNC(CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG);
+}
+
 static void guest_exec(void)
 {
        int (*code)(void) = (int (*)(void))TEST_EXEC_GVA;
@@ -304,7 +309,7 @@ static struct uffd_args {
 
 /* Returns true to continue the test, and false if it should be skipped. */
 static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg,
-                               struct uffd_args *args, bool expect_write)
+                               struct uffd_args *args)
 {
        uint64_t addr = msg->arg.pagefault.address;
        uint64_t flags = msg->arg.pagefault.flags;
@@ -313,7 +318,6 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg,
 
        TEST_ASSERT(uffd_mode == UFFDIO_REGISTER_MODE_MISSING,
                    "The only expected UFFD mode is MISSING");
-       ASSERT_EQ(!!(flags & UFFD_PAGEFAULT_FLAG_WRITE), expect_write);
        ASSERT_EQ(addr, (uint64_t)args->hva);
 
        pr_debug("uffd fault: addr=%p write=%d\n",
@@ -337,19 +341,14 @@ static int uffd_generic_handler(int uffd_mode, int uffd, struct uffd_msg *msg,
        return 0;
 }
 
-static int uffd_pt_write_handler(int mode, int uffd, struct uffd_msg *msg)
-{
-       return uffd_generic_handler(mode, uffd, msg, &pt_args, true);
-}
-
-static int uffd_data_write_handler(int mode, int uffd, struct uffd_msg *msg)
+static int uffd_pt_handler(int mode, int uffd, struct uffd_msg *msg)
 {
-       return uffd_generic_handler(mode, uffd, msg, &data_args, true);
+       return uffd_generic_handler(mode, uffd, msg, &pt_args);
 }
 
-static int uffd_data_read_handler(int mode, int uffd, struct uffd_msg *msg)
+static int uffd_data_handler(int mode, int uffd, struct uffd_msg *msg)
 {
-       return uffd_generic_handler(mode, uffd, msg, &data_args, false);
+       return uffd_generic_handler(mode, uffd, msg, &data_args);
 }
 
 static void setup_uffd_args(struct userspace_mem_region *region,
@@ -471,9 +470,12 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd)
 {
        struct userspace_mem_region *data_region, *pt_region;
        bool continue_test = true;
+       uint64_t pte_gpa, pte_pg;
 
        data_region = vm_get_mem_region(vm, MEM_REGION_TEST_DATA);
        pt_region = vm_get_mem_region(vm, MEM_REGION_PT);
+       pte_gpa = addr_hva2gpa(vm, virt_get_pte_hva(vm, TEST_GVA));
+       pte_pg = (pte_gpa - pt_region->region.guest_phys_addr) / getpagesize();
 
        if (cmd == CMD_SKIP_TEST)
                continue_test = false;
@@ -486,13 +488,13 @@ static bool handle_cmd(struct kvm_vm *vm, int cmd)
                TEST_ASSERT(check_write_in_dirty_log(vm, data_region, 0),
                            "Missing write in dirty log");
        if (cmd & CMD_CHECK_S1PTW_WR_IN_DIRTY_LOG)
-               TEST_ASSERT(check_write_in_dirty_log(vm, pt_region, 0),
+               TEST_ASSERT(check_write_in_dirty_log(vm, pt_region, pte_pg),
                            "Missing s1ptw write in dirty log");
        if (cmd & CMD_CHECK_NO_WRITE_IN_DIRTY_LOG)
                TEST_ASSERT(!check_write_in_dirty_log(vm, data_region, 0),
                            "Unexpected write in dirty log");
        if (cmd & CMD_CHECK_NO_S1PTW_WR_IN_DIRTY_LOG)
-               TEST_ASSERT(!check_write_in_dirty_log(vm, pt_region, 0),
+               TEST_ASSERT(!check_write_in_dirty_log(vm, pt_region, pte_pg),
                            "Unexpected s1ptw write in dirty log");
 
        return continue_test;
@@ -797,7 +799,7 @@ static void help(char *name)
        .expected_events        = { .uffd_faults = _uffd_faults, },             \
 }
 
-#define TEST_DIRTY_LOG(_access, _with_af, _test_check)                         \
+#define TEST_DIRTY_LOG(_access, _with_af, _test_check, _pt_check)              \
 {                                                                              \
        .name                   = SCAT3(dirty_log, _access, _with_af),          \
        .data_memslot_flags     = KVM_MEM_LOG_DIRTY_PAGES,                      \
@@ -805,13 +807,12 @@ static void help(char *name)
        .guest_prepare          = { _PREPARE(_with_af),                         \
                                    _PREPARE(_access) },                        \
        .guest_test             = _access,                                      \
-       .guest_test_check       = { _CHECK(_with_af), _test_check,              \
-                                   guest_check_s1ptw_wr_in_dirty_log},         \
+       .guest_test_check       = { _CHECK(_with_af), _test_check, _pt_check }, \
        .expected_events        = { 0 },                                        \
 }
 
 #define TEST_UFFD_AND_DIRTY_LOG(_access, _with_af, _uffd_data_handler,         \
-                               _uffd_faults, _test_check)                      \
+                               _uffd_faults, _test_check, _pt_check)           \
 {                                                                              \
        .name                   = SCAT3(uffd_and_dirty_log, _access, _with_af), \
        .data_memslot_flags     = KVM_MEM_LOG_DIRTY_PAGES,                      \
@@ -820,16 +821,17 @@ static void help(char *name)
                                    _PREPARE(_access) },                        \
        .guest_test             = _access,                                      \
        .mem_mark_cmd           = CMD_HOLE_DATA | CMD_HOLE_PT,                  \
-       .guest_test_check       = { _CHECK(_with_af), _test_check },            \
+       .guest_test_check       = { _CHECK(_with_af), _test_check, _pt_check }, \
        .uffd_data_handler      = _uffd_data_handler,                           \
-       .uffd_pt_handler        = uffd_pt_write_handler,                        \
+       .uffd_pt_handler        = uffd_pt_handler,                              \
        .expected_events        = { .uffd_faults = _uffd_faults, },             \
 }
 
 #define TEST_RO_MEMSLOT(_access, _mmio_handler, _mmio_exits)                   \
 {                                                                              \
-       .name                   = SCAT3(ro_memslot, _access, _with_af),         \
+       .name                   = SCAT2(ro_memslot, _access),                   \
        .data_memslot_flags     = KVM_MEM_READONLY,                             \
+       .pt_memslot_flags       = KVM_MEM_READONLY,                             \
        .guest_prepare          = { _PREPARE(_access) },                        \
        .guest_test             = _access,                                      \
        .mmio_handler           = _mmio_handler,                                \
@@ -840,6 +842,7 @@ static void help(char *name)
 {                                                                              \
        .name                   = SCAT2(ro_memslot_no_syndrome, _access),       \
        .data_memslot_flags     = KVM_MEM_READONLY,                             \
+       .pt_memslot_flags       = KVM_MEM_READONLY,                             \
        .guest_test             = _access,                                      \
        .fail_vcpu_run_handler  = fail_vcpu_run_mmio_no_syndrome_handler,       \
        .expected_events        = { .fail_vcpu_runs = 1 },                      \
@@ -848,9 +851,9 @@ static void help(char *name)
 #define TEST_RO_MEMSLOT_AND_DIRTY_LOG(_access, _mmio_handler, _mmio_exits,     \
                                      _test_check)                              \
 {                                                                              \
-       .name                   = SCAT3(ro_memslot, _access, _with_af),         \
+       .name                   = SCAT2(ro_memslot, _access),                   \
        .data_memslot_flags     = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES,   \
-       .pt_memslot_flags       = KVM_MEM_LOG_DIRTY_PAGES,                      \
+       .pt_memslot_flags       = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES,   \
        .guest_prepare          = { _PREPARE(_access) },                        \
        .guest_test             = _access,                                      \
        .guest_test_check       = { _test_check },                              \
@@ -862,7 +865,7 @@ static void help(char *name)
 {                                                                              \
        .name                   = SCAT2(ro_memslot_no_syn_and_dlog, _access),   \
        .data_memslot_flags     = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES,   \
-       .pt_memslot_flags       = KVM_MEM_LOG_DIRTY_PAGES,                      \
+       .pt_memslot_flags       = KVM_MEM_READONLY | KVM_MEM_LOG_DIRTY_PAGES,   \
        .guest_test             = _access,                                      \
        .guest_test_check       = { _test_check },                              \
        .fail_vcpu_run_handler  = fail_vcpu_run_mmio_no_syndrome_handler,       \
@@ -874,11 +877,12 @@ static void help(char *name)
 {                                                                              \
        .name                   = SCAT2(ro_memslot_uffd, _access),              \
        .data_memslot_flags     = KVM_MEM_READONLY,                             \
+       .pt_memslot_flags       = KVM_MEM_READONLY,                             \
        .mem_mark_cmd           = CMD_HOLE_DATA | CMD_HOLE_PT,                  \
        .guest_prepare          = { _PREPARE(_access) },                        \
        .guest_test             = _access,                                      \
        .uffd_data_handler      = _uffd_data_handler,                           \
-       .uffd_pt_handler        = uffd_pt_write_handler,                        \
+       .uffd_pt_handler        = uffd_pt_handler,                              \
        .mmio_handler           = _mmio_handler,                                \
        .expected_events        = { .mmio_exits = _mmio_exits,                  \
                                    .uffd_faults = _uffd_faults },              \
@@ -889,10 +893,11 @@ static void help(char *name)
 {                                                                              \
        .name                   = SCAT2(ro_memslot_no_syndrome, _access),       \
        .data_memslot_flags     = KVM_MEM_READONLY,                             \
+       .pt_memslot_flags       = KVM_MEM_READONLY,                             \
        .mem_mark_cmd           = CMD_HOLE_DATA | CMD_HOLE_PT,                  \
        .guest_test             = _access,                                      \
        .uffd_data_handler      = _uffd_data_handler,                           \
-       .uffd_pt_handler        = uffd_pt_write_handler,                        \
+       .uffd_pt_handler        = uffd_pt_handler,                      \
        .fail_vcpu_run_handler  = fail_vcpu_run_mmio_no_syndrome_handler,       \
        .expected_events        = { .fail_vcpu_runs = 1,                        \
                                    .uffd_faults = _uffd_faults },              \
@@ -933,44 +938,51 @@ static struct test_desc tests[] = {
         * (S1PTW).
         */
        TEST_UFFD(guest_read64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_read_handler, uffd_pt_write_handler, 2),
-       /* no_af should also lead to a PT write. */
+                 uffd_data_handler, uffd_pt_handler, 2),
        TEST_UFFD(guest_read64, no_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_read_handler, uffd_pt_write_handler, 2),
-       /* Note how that cas invokes the read handler. */
+                 uffd_data_handler, uffd_pt_handler, 2),
        TEST_UFFD(guest_cas, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_read_handler, uffd_pt_write_handler, 2),
+                 uffd_data_handler, uffd_pt_handler, 2),
        /*
         * Can't test guest_at with_af as it's IMPDEF whether the AF is set.
         * The S1PTW fault should still be marked as a write.
         */
        TEST_UFFD(guest_at, no_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_read_handler, uffd_pt_write_handler, 1),
+                 uffd_no_handler, uffd_pt_handler, 1),
        TEST_UFFD(guest_ld_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_read_handler, uffd_pt_write_handler, 2),
+                 uffd_data_handler, uffd_pt_handler, 2),
        TEST_UFFD(guest_write64, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_write_handler, uffd_pt_write_handler, 2),
+                 uffd_data_handler, uffd_pt_handler, 2),
        TEST_UFFD(guest_dc_zva, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_write_handler, uffd_pt_write_handler, 2),
+                 uffd_data_handler, uffd_pt_handler, 2),
        TEST_UFFD(guest_st_preidx, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_write_handler, uffd_pt_write_handler, 2),
+                 uffd_data_handler, uffd_pt_handler, 2),
        TEST_UFFD(guest_exec, with_af, CMD_HOLE_DATA | CMD_HOLE_PT,
-                 uffd_data_read_handler, uffd_pt_write_handler, 2),
+                 uffd_data_handler, uffd_pt_handler, 2),
 
        /*
         * Try accesses when the data and PT memory regions are both
         * tracked for dirty logging.
         */
-       TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log),
-       /* no_af should also lead to a PT write. */
-       TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_ld_preidx, with_af, guest_check_no_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log),
-       TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log),
+       TEST_DIRTY_LOG(guest_read64, with_af, guest_check_no_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_read64, no_af, guest_check_no_write_in_dirty_log,
+                      guest_check_no_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_ld_preidx, with_af,
+                      guest_check_no_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_at, no_af, guest_check_no_write_in_dirty_log,
+                      guest_check_no_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_exec, with_af, guest_check_no_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_write64, with_af, guest_check_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_cas, with_af, guest_check_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_dc_zva, with_af, guest_check_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
+       TEST_DIRTY_LOG(guest_st_preidx, with_af, guest_check_write_in_dirty_log,
+                      guest_check_s1ptw_wr_in_dirty_log),
 
        /*
         * Access when the data and PT memory regions are both marked for
@@ -980,29 +992,43 @@ static struct test_desc tests[] = {
         * fault, and nothing in the dirty log.  Any S1PTW should result in
         * a write in the dirty log and a userfaultfd write.
         */
-       TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af, uffd_data_read_handler, 2,
-                               guest_check_no_write_in_dirty_log),
-       /* no_af should also lead to a PT write. */
-       TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af, uffd_data_read_handler, 2,
-                               guest_check_no_write_in_dirty_log),
-       TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af, uffd_data_read_handler,
-                               2, guest_check_no_write_in_dirty_log),
-       TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, 0, 1,
-                               guest_check_no_write_in_dirty_log),
-       TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af, uffd_data_read_handler, 2,
-                               guest_check_no_write_in_dirty_log),
-       TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af, uffd_data_write_handler,
-                               2, guest_check_write_in_dirty_log),
-       TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af, uffd_data_read_handler, 2,
-                               guest_check_write_in_dirty_log),
-       TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af, uffd_data_write_handler,
-                               2, guest_check_write_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_read64, with_af,
+                               uffd_data_handler, 2,
+                               guest_check_no_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_read64, no_af,
+                               uffd_data_handler, 2,
+                               guest_check_no_write_in_dirty_log,
+                               guest_check_no_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_ld_preidx, with_af,
+                               uffd_data_handler,
+                               2, guest_check_no_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_at, with_af, uffd_no_handler, 1,
+                               guest_check_no_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_exec, with_af,
+                               uffd_data_handler, 2,
+                               guest_check_no_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_write64, with_af,
+                               uffd_data_handler,
+                               2, guest_check_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_cas, with_af,
+                               uffd_data_handler, 2,
+                               guest_check_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
+       TEST_UFFD_AND_DIRTY_LOG(guest_dc_zva, with_af,
+                               uffd_data_handler,
+                               2, guest_check_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
        TEST_UFFD_AND_DIRTY_LOG(guest_st_preidx, with_af,
-                               uffd_data_write_handler, 2,
-                               guest_check_write_in_dirty_log),
-
+                               uffd_data_handler, 2,
+                               guest_check_write_in_dirty_log,
+                               guest_check_s1ptw_wr_in_dirty_log),
        /*
-        * Try accesses when the data memory region is marked read-only
+        * Access when both the PT and data regions are marked read-only
         * (with KVM_MEM_READONLY). Writes with a syndrome result in an
         * MMIO exit, writes with no syndrome (e.g., CAS) result in a
         * failed vcpu run, and reads/execs with and without syndroms do
@@ -1018,7 +1044,7 @@ static struct test_desc tests[] = {
        TEST_RO_MEMSLOT_NO_SYNDROME(guest_st_preidx),
 
        /*
-        * Access when both the data region is both read-only and marked
+        * The PT and data regions are both read-only and marked
         * for dirty logging at the same time. The expected result is that
         * for writes there should be no write in the dirty log. The
         * readonly handling is the same as if the memslot was not marked
@@ -1043,7 +1069,7 @@ static struct test_desc tests[] = {
                                                  guest_check_no_write_in_dirty_log),
 
        /*
-        * Access when the data region is both read-only and punched with
+        * The PT and data regions are both read-only and punched with
         * holes tracked with userfaultfd.  The expected result is the
         * union of both userfaultfd and read-only behaviors. For example,
         * write accesses result in a userfaultfd write fault and an MMIO
@@ -1051,22 +1077,15 @@ static struct test_desc tests[] = {
         * no userfaultfd write fault. Reads result in userfaultfd getting
         * triggered.
         */
-       TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0,
-                                uffd_data_read_handler, 2),
-       TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0,
-                                uffd_data_read_handler, 2),
-       TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0,
-                                uffd_no_handler, 1),
-       TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0,
-                                uffd_data_read_handler, 2),
+       TEST_RO_MEMSLOT_AND_UFFD(guest_read64, 0, 0, uffd_data_handler, 2),
+       TEST_RO_MEMSLOT_AND_UFFD(guest_ld_preidx, 0, 0, uffd_data_handler, 2),
+       TEST_RO_MEMSLOT_AND_UFFD(guest_at, 0, 0, uffd_no_handler, 1),
+       TEST_RO_MEMSLOT_AND_UFFD(guest_exec, 0, 0, uffd_data_handler, 2),
        TEST_RO_MEMSLOT_AND_UFFD(guest_write64, mmio_on_test_gpa_handler, 1,
-                                uffd_data_write_handler, 2),
-       TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas,
-                                            uffd_data_read_handler, 2),
-       TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva,
-                                            uffd_no_handler, 1),
-       TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx,
-                                            uffd_no_handler, 1),
+                                uffd_data_handler, 2),
+       TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_cas, uffd_data_handler, 2),
+       TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_dc_zva, uffd_no_handler, 1),
+       TEST_RO_MEMSLOT_NO_SYNDROME_AND_UFFD(guest_st_preidx, uffd_no_handler, 1),
 
        { 0 }
 };
index ea0978f22db860b0dcfd92a6dee48fb6d6579485..251794f8371939e7b33f15fda448b7b341fd2ab0 100644 (file)
@@ -241,7 +241,7 @@ int main(int argc, char **argv)
        while ((opt = getopt(argc, argv, "hp:t:r")) != -1) {
                switch (opt) {
                case 'p':
-                       reclaim_period_ms = atoi_non_negative("Reclaim period", optarg);
+                       reclaim_period_ms = atoi_positive("Reclaim period", optarg);
                        break;
                case 't':
                        token = atoi_paranoid(optarg);
index dae510c263b45b6e14d81524cf42893edea2c49c..13c75dc18c10b53abc98459657570ea6c4ce1ee5 100644 (file)
@@ -434,6 +434,7 @@ static void *juggle_shinfo_state(void *arg)
 int main(int argc, char *argv[])
 {
        struct timespec min_ts, max_ts, vm_ts;
+       struct kvm_xen_hvm_attr evt_reset;
        struct kvm_vm *vm;
        pthread_t thread;
        bool verbose;
@@ -962,10 +963,8 @@ int main(int argc, char *argv[])
        }
 
  done:
-       struct kvm_xen_hvm_attr evt_reset = {
-               .type = KVM_XEN_ATTR_TYPE_EVTCHN,
-               .u.evtchn.flags = KVM_XEN_EVTCHN_RESET,
-       };
+       evt_reset.type = KVM_XEN_ATTR_TYPE_EVTCHN;
+       evt_reset.u.evtchn.flags = KVM_XEN_EVTCHN_RESET;
        vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &evt_reset);
 
        alarm(0);
index 291144c284fbcb4139549ea470402d84a206af23..f7900e75d2306d2ff79d930e78a1c9110c69b48b 100644 (file)
@@ -20,7 +20,7 @@ CLANG_TARGET_FLAGS              := $(CLANG_TARGET_FLAGS_$(ARCH))
 
 ifeq ($(CROSS_COMPILE),)
 ifeq ($(CLANG_TARGET_FLAGS),)
-$(error Specify CROSS_COMPILE or add '--target=' option to lib.mk
+$(error Specify CROSS_COMPILE or add '--target=' option to lib.mk)
 else
 CLANG_FLAGS     += --target=$(CLANG_TARGET_FLAGS)
 endif # CLANG_TARGET_FLAGS
index 2d89cb0ad2889af1b1ef845c20ab388fadeb9170..330d0b1ceced3de3bf34c45821cc8a310d06f0bf 100755 (executable)
@@ -6,7 +6,7 @@ ksft_skip=4
 NS=ns
 IP6=2001:db8:1::1/64
 TGT6=2001:db8:1::2
-TMPF=`mktemp`
+TMPF=$(mktemp --suffix ".pcap")
 
 cleanup()
 {
index a29deb9fa024cd5804e5be81f6b1cfcaa821c00d..ab2d581f28a1d1663c59ab19822d8c86650b027d 100755 (executable)
@@ -752,6 +752,52 @@ test_subflows()
           "$server4_token" > /dev/null 2>&1
 }
 
+test_subflows_v4_v6_mix()
+{
+       # Attempt to add a listener at 10.0.2.1:<subflow-port>
+       ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
+          $app6_port > /dev/null 2>&1 &
+       local listener_pid=$!
+
+       # ADD_ADDR4 from server to client machine reusing the subflow port on
+       # the established v6 connection
+       :>"$client_evts"
+       ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server6_token" id\
+          $server_addr_id dev ns1eth2 > /dev/null 2>&1
+       stdbuf -o0 -e0 printf "ADD_ADDR4 id:%d 10.0.2.1 (ns1) => ns2, reuse port\t\t" $server_addr_id
+       sleep 0.5
+       verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "10.0.2.1"\
+                             "$server_addr_id" "$app6_port"
+
+       # CREATE_SUBFLOW from client to server machine
+       :>"$client_evts"
+       ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
+          $app6_port token "$client6_token" > /dev/null 2>&1
+       sleep 0.5
+       verify_subflow_events "$client_evts" "$SUB_ESTABLISHED" "$client6_token"\
+                             "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
+                             "$server_addr_id" "ns2" "ns1"
+
+       # Delete the listener from the server ns, if one was created
+       kill_wait $listener_pid
+
+       sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
+
+       # DESTROY_SUBFLOW from client to server machine
+       :>"$client_evts"
+       ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
+          $app6_port token "$client6_token" > /dev/null 2>&1
+       sleep 0.5
+       verify_subflow_events "$client_evts" "$SUB_CLOSED" "$client6_token" \
+                             "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
+                             "$server_addr_id" "ns2" "ns1"
+
+       # RM_ADDR from server to client machine
+       ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
+          "$server6_token" > /dev/null 2>&1
+       sleep 0.5
+}
+
 test_prio()
 {
        local count
@@ -861,6 +907,7 @@ make_connection "v6"
 test_announce
 test_remove
 test_subflows
+test_subflows_v4_v6_mix
 test_prio
 test_listener
 
index 90026a27eac0cb678bcb3ed15e6855e2cb0aa885..9ba03164d73a692f6ea39c560d43e678659ce21f 100644 (file)
@@ -215,7 +215,7 @@ static char *recv_frame(const struct ring_state *ring, char *frame)
 }
 
 /* A single TPACKET_V3 block can hold multiple frames */
-static void recv_block(struct ring_state *ring)
+static bool recv_block(struct ring_state *ring)
 {
        struct tpacket_block_desc *block;
        char *frame;
@@ -223,7 +223,7 @@ static void recv_block(struct ring_state *ring)
 
        block = (void *)(ring->mmap + ring->idx * ring_block_sz);
        if (!(block->hdr.bh1.block_status & TP_STATUS_USER))
-               return;
+               return false;
 
        frame = (char *)block;
        frame += block->hdr.bh1.offset_to_first_pkt;
@@ -235,6 +235,8 @@ static void recv_block(struct ring_state *ring)
 
        block->hdr.bh1.block_status = TP_STATUS_KERNEL;
        ring->idx = (ring->idx + 1) % ring_block_nr;
+
+       return true;
 }
 
 /* simple test: sleep once unconditionally and then process all rings */
@@ -245,7 +247,7 @@ static void process_rings(void)
        usleep(1000 * cfg_timeout_msec);
 
        for (i = 0; i < num_cpus; i++)
-               recv_block(&rings[i]);
+               do {} while (recv_block(&rings[i]));
 
        fprintf(stderr, "count: pass=%u nohash=%u fail=%u\n",
                frames_received - frames_nohash - frames_error,
@@ -257,12 +259,12 @@ static char *setup_ring(int fd)
        struct tpacket_req3 req3 = {0};
        void *ring;
 
-       req3.tp_retire_blk_tov = cfg_timeout_msec;
+       req3.tp_retire_blk_tov = cfg_timeout_msec / 8;
        req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
 
        req3.tp_frame_size = 2048;
        req3.tp_frame_nr = 1 << 10;
-       req3.tp_block_nr = 2;
+       req3.tp_block_nr = 16;
 
        req3.tp_block_size = req3.tp_frame_size * req3.tp_frame_nr;
        req3.tp_block_size /= req3.tp_block_nr;
index dc932fd65363450c093e491d690da5366ad84f7d..640bc43452faa9cd6ac2d18b16817ac67bd353a9 100755 (executable)
@@ -7,6 +7,7 @@ readonly GREEN='\033[0;92m'
 readonly YELLOW='\033[0;33m'
 readonly RED='\033[0;31m'
 readonly NC='\033[0m' # No Color
+readonly TESTPORT=8000
 
 readonly KSFT_PASS=0
 readonly KSFT_FAIL=1
@@ -56,11 +57,26 @@ trap wake_children EXIT
 
 run_one() {
        local -r args=$@
+       local nr_socks=0
+       local i=0
+       local -r timeout=10
+
+       ./udpgso_bench_rx -p "$TESTPORT" &
+       ./udpgso_bench_rx -p "$TESTPORT" -t &
+
+       # Wait for the above test program to get ready to receive connections.
+       while [ "$i" -lt "$timeout" ]; do
+               nr_socks="$(ss -lnHi | grep -c "\*:${TESTPORT}")"
+               [ "$nr_socks" -eq 2 ] && break
+               i=$((i + 1))
+               sleep 1
+       done
+       if [ "$nr_socks" -ne 2 ]; then
+               echo "timed out while waiting for udpgso_bench_rx"
+               exit 1
+       fi
 
-       ./udpgso_bench_rx &
-       ./udpgso_bench_rx -t &
-
-       ./udpgso_bench_tx ${args}
+       ./udpgso_bench_tx -p "$TESTPORT" ${args}
 }
 
 run_in_netns() {
index 6a193425c367fccdbb18bcc1269f8f4b240acdce..4058c7451e70da721c50c0f214054abe4a94d782 100644 (file)
@@ -250,7 +250,7 @@ static int recv_msg(int fd, char *buf, int len, int *gso_size)
 static void do_flush_udp(int fd)
 {
        static char rbuf[ETH_MAX_MTU];
-       int ret, len, gso_size, budget = 256;
+       int ret, len, gso_size = 0, budget = 256;
 
        len = cfg_read_all ? sizeof(rbuf) : 0;
        while (budget--) {
@@ -336,6 +336,8 @@ static void parse_opts(int argc, char **argv)
                        cfg_verify = true;
                        cfg_read_all = true;
                        break;
+               default:
+                       exit(1);
                }
        }
 
index f1fdaa270291331e70fb2456003bdd44056b93d5..477392715a9ad52a2edb76d95e4b332ba953f06c 100644 (file)
@@ -62,6 +62,7 @@ static int    cfg_payload_len = (1472 * 42);
 static int     cfg_port        = 8000;
 static int     cfg_runtime_ms  = -1;
 static bool    cfg_poll;
+static int     cfg_poll_loop_timeout_ms = 2000;
 static bool    cfg_segment;
 static bool    cfg_sendmmsg;
 static bool    cfg_tcp;
@@ -235,16 +236,17 @@ static void flush_errqueue_recv(int fd)
        }
 }
 
-static void flush_errqueue(int fd, const bool do_poll)
+static void flush_errqueue(int fd, const bool do_poll,
+                          unsigned long poll_timeout, const bool poll_err)
 {
        if (do_poll) {
                struct pollfd fds = {0};
                int ret;
 
                fds.fd = fd;
-               ret = poll(&fds, 1, 500);
+               ret = poll(&fds, 1, poll_timeout);
                if (ret == 0) {
-                       if (cfg_verbose)
+                       if ((cfg_verbose) && (poll_err))
                                fprintf(stderr, "poll timeout\n");
                } else if (ret < 0) {
                        error(1, errno, "poll");
@@ -254,6 +256,20 @@ static void flush_errqueue(int fd, const bool do_poll)
        flush_errqueue_recv(fd);
 }
 
+static void flush_errqueue_retry(int fd, unsigned long num_sends)
+{
+       unsigned long tnow, tstop;
+       bool first_try = true;
+
+       tnow = gettimeofday_ms();
+       tstop = tnow + cfg_poll_loop_timeout_ms;
+       do {
+               flush_errqueue(fd, true, tstop - tnow, first_try);
+               first_try = false;
+               tnow = gettimeofday_ms();
+       } while ((stat_zcopies != num_sends) && (tnow < tstop));
+}
+
 static int send_tcp(int fd, char *data)
 {
        int ret, done = 0, count = 0;
@@ -413,7 +429,8 @@ static int send_udp_segment(int fd, char *data)
 
 static void usage(const char *filepath)
 {
-       error(1, 0, "Usage: %s [-46acmHPtTuvz] [-C cpu] [-D dst ip] [-l secs] [-M messagenr] [-p port] [-s sendsize] [-S gsosize]",
+       error(1, 0, "Usage: %s [-46acmHPtTuvz] [-C cpu] [-D dst ip] [-l secs] "
+                   "[-L secs] [-M messagenr] [-p port] [-s sendsize] [-S gsosize]",
                    filepath);
 }
 
@@ -423,7 +440,7 @@ static void parse_opts(int argc, char **argv)
        int max_len, hdrlen;
        int c;
 
-       while ((c = getopt(argc, argv, "46acC:D:Hl:mM:p:s:PS:tTuvz")) != -1) {
+       while ((c = getopt(argc, argv, "46acC:D:Hl:L:mM:p:s:PS:tTuvz")) != -1) {
                switch (c) {
                case '4':
                        if (cfg_family != PF_UNSPEC)
@@ -452,6 +469,9 @@ static void parse_opts(int argc, char **argv)
                case 'l':
                        cfg_runtime_ms = strtoul(optarg, NULL, 10) * 1000;
                        break;
+               case 'L':
+                       cfg_poll_loop_timeout_ms = strtoul(optarg, NULL, 10) * 1000;
+                       break;
                case 'm':
                        cfg_sendmmsg = true;
                        break;
@@ -490,6 +510,8 @@ static void parse_opts(int argc, char **argv)
                case 'z':
                        cfg_zerocopy = true;
                        break;
+               default:
+                       exit(1);
                }
        }
 
@@ -677,7 +699,7 @@ int main(int argc, char **argv)
                        num_sends += send_udp(fd, buf[i]);
                num_msgs++;
                if ((cfg_zerocopy && ((num_msgs & 0xF) == 0)) || cfg_tx_tstamp)
-                       flush_errqueue(fd, cfg_poll);
+                       flush_errqueue(fd, cfg_poll, 500, true);
 
                if (cfg_msg_nr && num_msgs >= cfg_msg_nr)
                        break;
@@ -696,7 +718,7 @@ int main(int argc, char **argv)
        } while (!interrupted && (cfg_runtime_ms == -1 || tnow < tstop));
 
        if (cfg_zerocopy || cfg_tx_tstamp)
-               flush_errqueue(fd, true);
+               flush_errqueue_retry(fd, num_sends);
 
        if (close(fd))
                error(1, errno, "close");
index a7f62ad4f6611d1cd987b84369c1da3f213d338a..2ffba45a78bf450bd3f969476607d2866a2dcb85 100755 (executable)
 ksft_skip=4
 
 testns=testns-$(mktemp -u "XXXXXXXX")
+tmp=""
 
 tables="foo bar baz quux"
 global_ret=0
 eret=0
 lret=0
 
+cleanup() {
+       ip netns pids "$testns" | xargs kill 2>/dev/null
+       ip netns del "$testns"
+
+       rm -f "$tmp"
+}
+
 check_result()
 {
        local r=$1
@@ -43,6 +51,7 @@ if [ $? -ne 0 ];then
        exit $ksft_skip
 fi
 
+trap cleanup EXIT
 tmp=$(mktemp)
 
 for table in $tables; do
@@ -139,11 +148,4 @@ done
 
 check_result $lret "add/delete with nftrace enabled"
 
-pkill -9 ping
-
-wait
-
-rm -f "$tmp"
-ip netns del "$testns"
-
 exit $global_ret
diff --git a/tools/testing/selftests/netfilter/settings b/tools/testing/selftests/netfilter/settings
new file mode 100644 (file)
index 0000000..6091b45
--- /dev/null
@@ -0,0 +1 @@
+timeout=120
index d95b1cb43d9d08cb6c41eaef267b992082705910..7588428b8fcd7de0791a3fc66e45503a2bc95247 100644 (file)
@@ -25,6 +25,7 @@
 #undef NDEBUG
 #include <assert.h>
 #include <errno.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -41,7 +42,7 @@
  * 1: vsyscall VMA is --xp             vsyscall=xonly
  * 2: vsyscall VMA is r-xp             vsyscall=emulate
  */
-static int g_vsyscall;
+static volatile int g_vsyscall;
 static const char *g_proc_pid_maps_vsyscall;
 static const char *g_proc_pid_smaps_vsyscall;
 
@@ -147,11 +148,12 @@ static void vsyscall(void)
 
                g_vsyscall = 0;
                /* gettimeofday(NULL, NULL); */
+               uint64_t rax = 0xffffffffff600000;
                asm volatile (
-                       "call %P0"
-                       :
-                       : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
-                       : "rax", "rcx", "r11"
+                       "call *%[rax]"
+                       : [rax] "+a" (rax)
+                       : "D" (NULL), "S" (NULL)
+                       : "rcx", "r11"
                );
 
                g_vsyscall = 1;
index 69551bfa215c4e8321a1971f405e602a67940148..cacbd2a4aec9120b06285a47688cf4b4decc6a2d 100644 (file)
@@ -257,11 +257,12 @@ static void vsyscall(void)
 
                g_vsyscall = 0;
                /* gettimeofday(NULL, NULL); */
+               uint64_t rax = 0xffffffffff600000;
                asm volatile (
-                       "call %P0"
-                       :
-                       : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
-                       : "rax", "rcx", "r11"
+                       "call *%[rax]"
+                       : [rax] "+a" (rax)
+                       : "D" (NULL), "S" (NULL)
+                       : "rcx", "r11"
                );
 
                g_vsyscall = 1;
index a634f47d1e56314c681ea69e3940f52951becdd9..9a127a8fe1761246f088be6ddff8b94895816f3c 100644 (file)
@@ -17,7 +17,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/mman.h>
-#define __USE_GNU
 #include <fcntl.h>
 
 #define MIN_FREE_PAGES 20
index 813baf13f62a2836fa68beda1db6dd7269172bb9..51a919083d9b85823fe9e8ac42c910c0460c7c43 100644 (file)
@@ -1,13 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef BUG_H
-#define BUG_H
+#ifndef _LINUX_BUG_H
+#define _LINUX_BUG_H
 
 #include <asm/bug.h>
 
 #define BUG_ON(__BUG_ON_cond) assert(!(__BUG_ON_cond))
 
-#define BUILD_BUG_ON(x)
-
 #define BUG() abort()
 
-#endif /* BUG_H */
+#endif /* _LINUX_BUG_H */
diff --git a/tools/virtio/linux/build_bug.h b/tools/virtio/linux/build_bug.h
new file mode 100644 (file)
index 0000000..cdbb75e
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BUILD_BUG_H
+#define _LINUX_BUILD_BUG_H
+
+#define BUILD_BUG_ON(x)
+
+#endif /* _LINUX_BUILD_BUG_H */
diff --git a/tools/virtio/linux/cpumask.h b/tools/virtio/linux/cpumask.h
new file mode 100644 (file)
index 0000000..307da69
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_CPUMASK_H
+#define _LINUX_CPUMASK_H
+
+#include <linux/kernel.h>
+
+#endif /* _LINUX_CPUMASK_H */
diff --git a/tools/virtio/linux/gfp.h b/tools/virtio/linux/gfp.h
new file mode 100644 (file)
index 0000000..43d146f
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_GFP_H
+#define __LINUX_GFP_H
+
+#include <linux/topology.h>
+
+#endif
index 21593bf9775526692c297a3ed28a0f8ea0d14cca..8b877167933d13df8dca2519c429cba395843cd6 100644 (file)
@@ -10,6 +10,7 @@
 #include <stdarg.h>
 
 #include <linux/compiler.h>
+#include <linux/log2.h>
 #include <linux/types.h>
 #include <linux/overflow.h>
 #include <linux/list.h>
diff --git a/tools/virtio/linux/kmsan.h b/tools/virtio/linux/kmsan.h
new file mode 100644 (file)
index 0000000..272b5aa
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KMSAN_H
+#define _LINUX_KMSAN_H
+
+#include <linux/gfp.h>
+
+inline void kmsan_handle_dma(struct page *page, size_t offset, size_t size,
+                            enum dma_data_direction dir)
+{
+}
+
+#endif /* _LINUX_KMSAN_H */
index 369ee308b6686ca4a106581b91f8d382e45c79e8..74d9e1825748e971568f1b6abafd211b03eefc02 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef SCATTERLIST_H
 #define SCATTERLIST_H
 #include <linux/kernel.h>
+#include <linux/bug.h>
 
 struct scatterlist {
        unsigned long   page_link;
diff --git a/tools/virtio/linux/topology.h b/tools/virtio/linux/topology.h
new file mode 100644 (file)
index 0000000..910794a
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_TOPOLOGY_H
+#define _LINUX_TOPOLOGY_H
+
+#include <linux/cpumask.h>
+
+#endif /* _LINUX_TOPOLOGY_H */
index 495ceabffe88bb7270083e404d6576c7258634a0..9584eb57e0edadf20f57260fd9591ca3d2899ee7 100644 (file)
@@ -336,7 +336,7 @@ static int kvm_vfio_has_attr(struct kvm_device *dev,
        return -ENXIO;
 }
 
-static void kvm_vfio_destroy(struct kvm_device *dev)
+static void kvm_vfio_release(struct kvm_device *dev)
 {
        struct kvm_vfio *kv = dev->private;
        struct kvm_vfio_group *kvg, *tmp;
@@ -355,7 +355,7 @@ static void kvm_vfio_destroy(struct kvm_device *dev)
        kvm_vfio_update_coherency(dev);
 
        kfree(kv);
-       kfree(dev); /* alloc by kvm_ioctl_create_device, free by .destroy */
+       kfree(dev); /* alloc by kvm_ioctl_create_device, free by .release */
 }
 
 static int kvm_vfio_create(struct kvm_device *dev, u32 type);
@@ -363,7 +363,7 @@ static int kvm_vfio_create(struct kvm_device *dev, u32 type);
 static struct kvm_device_ops kvm_vfio_ops = {
        .name = "kvm-vfio",
        .create = kvm_vfio_create,
-       .destroy = kvm_vfio_destroy,
+       .release = kvm_vfio_release,
        .set_attr = kvm_vfio_set_attr,
        .has_attr = kvm_vfio_has_attr,
 };