Merge tag 'edac_urgent_for_v6.9_rc7' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 5 May 2024 17:51:29 +0000 (10:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 5 May 2024 17:51:29 +0000 (10:51 -0700)
Pull EDAC fixes from Borislav Petkov:

 - Fix error logging and check user-supplied data when injecting an
   error in the versal EDAC driver

* tag 'edac_urgent_for_v6.9_rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras:
  EDAC/versal: Do not log total error counts
  EDAC/versal: Check user-supplied data before injecting an error
  EDAC/versal: Do not register for NOC errors

603 files changed:
.mailmap
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst
Documentation/core-api/workqueue.rst
Documentation/devicetree/bindings/eeprom/at24.yaml
Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml
Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
Documentation/devicetree/bindings/soc/rockchip/grf.yaml
Documentation/devicetree/bindings/sound/rt5645.txt
Documentation/rust/arch-support.rst
Documentation/timers/no_hz.rst
Documentation/translations/zh_CN/core-api/workqueue.rst
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/Kconfig
arch/arc/boot/Makefile
arch/arc/boot/dts/axc003.dtsi
arch/arc/boot/dts/hsdk.dts
arch/arc/boot/dts/vdk_axs10x_mb.dtsi
arch/arc/include/asm/cachetype.h [deleted file]
arch/arc/include/asm/dsp.h
arch/arc/include/asm/entry-compact.h
arch/arc/include/asm/entry.h
arch/arc/include/asm/irq.h
arch/arc/include/asm/irqflags-compact.h
arch/arc/include/asm/mmu_context.h
arch/arc/include/asm/pgtable-bits-arcv2.h
arch/arc/include/asm/ptrace.h
arch/arc/include/asm/shmparam.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/thread_info.h
arch/arc/include/uapi/asm/swab.h
arch/arc/kernel/entry-arcv2.S
arch/arc/kernel/entry.S
arch/arc/kernel/head.S
arch/arc/kernel/intc-arcv2.c
arch/arc/kernel/kprobes.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/signal.c
arch/arc/kernel/traps.c
arch/arc/kernel/vmlinux.lds.S
arch/arc/mm/tlb.c
arch/arc/mm/tlbex.S
arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts
arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi
arch/arm/net/bpf_jit_32.c
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/mediatek/mt2712-evb.dts
arch/arm64/boot/dts/mediatek/mt2712e.dtsi
arch/arm64/boot/dts/mediatek/mt7622.dtsi
arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
arch/arm64/boot/dts/mediatek/mt7986a.dtsi
arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
arch/arm64/boot/dts/mediatek/mt8183.dtsi
arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi
arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
arch/arm64/boot/dts/mediatek/mt8192.dtsi
arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
arch/arm64/boot/dts/mediatek/mt8195.dtsi
arch/arm64/boot/dts/qcom/sc7280.dtsi
arch/arm64/boot/dts/qcom/sc8180x.dtsi
arch/arm64/boot/dts/qcom/sc8280xp.dtsi
arch/arm64/boot/dts/qcom/sm6350.dtsi
arch/arm64/boot/dts/qcom/sm6375.dtsi
arch/arm64/boot/dts/qcom/sm8250.dtsi
arch/arm64/boot/dts/qcom/sm8450.dtsi
arch/arm64/boot/dts/qcom/sm8550.dtsi
arch/arm64/boot/dts/qcom/sm8650.dtsi
arch/arm64/boot/dts/qcom/x1e80100.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts
arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts
arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
arch/arm64/kvm/vgic/vgic-kvm-device.c
arch/arm64/net/bpf_jit_comp.c
arch/loongarch/Kconfig
arch/loongarch/include/asm/crash_core.h [deleted file]
arch/loongarch/include/asm/crash_reserve.h [new file with mode: 0644]
arch/loongarch/include/asm/perf_event.h
arch/loongarch/include/asm/tlb.h
arch/loongarch/kernel/perf_event.c
arch/loongarch/mm/fault.c
arch/powerpc/include/asm/plpks.h
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/plpks.c
arch/riscv/Kconfig.errata
arch/riscv/errata/thead/errata.c
arch/riscv/include/asm/errata_list.h
arch/riscv/include/asm/page.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/uapi/asm/hwprobe.h
arch/riscv/mm/init.c
arch/riscv/net/bpf_jit_comp64.c
arch/s390/crypto/paes_s390.c
arch/s390/include/asm/dwarf.h
arch/s390/kernel/vdso64/vdso_user_wrapper.S
arch/s390/mm/gmap.c
arch/s390/mm/hugetlbpage.c
arch/x86/Kconfig
arch/x86/entry/vsyscall/vsyscall_64.c
arch/x86/include/asm/coco.h
arch/x86/include/asm/e820/api.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/sev.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/e820.c
arch/x86/kernel/process_64.c
arch/x86/kernel/sev-shared.c
arch/x86/mm/fault.c
arch/x86/mm/mem_encrypt.c
arch/x86/net/bpf_jit_comp.c
arch/x86/virt/svm/sev.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/smp_pv.c
arch/xtensa/include/asm/cacheflush.h
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/stacktrace.c
arch/xtensa/platforms/iss/console.c
block/bdev.c
drivers/acpi/cppc_acpi.c
drivers/acpi/x86/s2idle.c
drivers/base/regmap/regmap.c
drivers/block/ublk_drv.c
drivers/bluetooth/btmtk.c
drivers/bluetooth/btqca.c
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_qca.c
drivers/clk/qcom/clk-smd-rpm.c
drivers/clk/qcom/gdsc.c
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun50i-h6.c
drivers/clk/sunxi-ng/ccu_common.c
drivers/clk/sunxi-ng/ccu_common.h
drivers/cxl/core/mbox.c
drivers/cxl/core/port.c
drivers/dma/idma64.c
drivers/dma/idxd/cdev.c
drivers/dma/idxd/debugfs.c
drivers/dma/idxd/device.c
drivers/dma/idxd/idxd.h
drivers/dma/idxd/init.c
drivers/dma/idxd/irq.c
drivers/dma/idxd/perfmon.c
drivers/dma/owl-dma.c
drivers/dma/pl330.c
drivers/dma/tegra186-gpc-dma.c
drivers/dma/xilinx/xdma-regs.h
drivers/dma/xilinx/xdma.c
drivers/dma/xilinx/xilinx_dpdma.c
drivers/dpll/dpll_core.c
drivers/firewire/nosy.c
drivers/firewire/ohci.c
drivers/firmware/efi/unaccepted_memory.c
drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
drivers/firmware/qcom/qcom_scm.c
drivers/fpga/dfl-pci.c
drivers/gpio/gpio-tangier.c
drivers/gpio/gpio-tegra186.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c
drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
drivers/gpu/drm/drm_gem_atomic_helper.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
drivers/gpu/drm/gma500/Makefile
drivers/gpu/drm/gma500/psb_device.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_lid.c [deleted file]
drivers/gpu/drm/imagination/pvr_fw_mips.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
drivers/gpu/drm/nouveau/nvkm/core/firmware.c
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/panel-ilitek-ili9341.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
drivers/gpu/drm/xe/xe_gt.c
drivers/gpu/drm/xe/xe_gt_ccs_mode.c
drivers/gpu/drm/xe/xe_gt_ccs_mode.h
drivers/gpu/drm/xe/xe_guc_ct.c
drivers/gpu/drm/xe/xe_huc.c
drivers/gpu/drm/xe/xe_vm.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-mcp2221.c
drivers/hid/hid-nintendo.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/intel-ish-hid/ipc/ipc.c
drivers/i2c/i2c-core-base.c
drivers/iio/accel/mxc4005.c
drivers/iio/imu/adis16475.c
drivers/iio/pressure/bmp280-core.c
drivers/iio/pressure/bmp280-spi.c
drivers/iio/pressure/bmp280.h
drivers/input/joystick/xpad.c
drivers/input/mouse/amimouse.c
drivers/irqchip/irq-gic-v3-its.c
drivers/md/dm-vdo/murmurhash3.c
drivers/md/dm.c
drivers/misc/eeprom/at24.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mei/pxp/mei_pxp.c
drivers/misc/pvpanic/pvpanic-pci.c
drivers/mmc/host/moxart-mmc.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-dwcmshc.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/raw/brcmnand/brcmnand.c
drivers/mtd/nand/raw/diskonchip.c
drivers/mtd/nand/raw/qcom_nandc.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h
drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/brocade/bna/bnad_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_debugfs.c
drivers/net/ethernet/intel/ice/ice_vf_lib.c
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_leds.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core_env.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
drivers/net/ethernet/qlogic/qede/qede_filter.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/ti/am65-cpts.c
drivers/net/ethernet/ti/icssg/icssg_prueth.c
drivers/net/ethernet/wangxun/libwx/wx_lib.c
drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
drivers/net/gtp.c
drivers/net/macsec.c
drivers/net/phy/dp83869.c
drivers/net/phy/mediatek-ge-soc.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/qmi_wwan.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/intel/iwlwifi/cfg/bz.c
drivers/net/wireless/intel/iwlwifi/cfg/sc.c
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/virtual/mac80211_hwsim.c
drivers/nfc/trf7970a.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/tcp.c
drivers/nvme/target/auth.c
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/tcp.c
drivers/phy/freescale/phy-fsl-imx8m-pcie.c
drivers/phy/marvell/phy-mvebu-a3700-comphy.c
drivers/phy/qualcomm/phy-qcom-m31.c
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v5.h
drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v6.h
drivers/phy/rockchip/Kconfig
drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
drivers/phy/ti/phy-tusb1210.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
drivers/pinctrl/core.c
drivers/pinctrl/devicetree.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-intel.h
drivers/pinctrl/mediatek/pinctrl-paris.c
drivers/pinctrl/meson/pinctrl-meson-a1.c
drivers/pinctrl/renesas/pinctrl-rzg2l.c
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
drivers/power/supply/mt6360_charger.c
drivers/power/supply/rt9455_charger.c
drivers/regulator/irq_helpers.c
drivers/regulator/mt6360-regulator.c
drivers/regulator/qcom-refgen-regulator.c
drivers/regulator/vqmmc-ipq4019-regulator.c
drivers/s390/char/raw3270.c
drivers/s390/cio/cio_inject.c
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/net/qeth_core_main.c
drivers/scsi/sd.c
drivers/slimbus/qcom-ngd-ctrl.c
drivers/soc/mediatek/Kconfig
drivers/soc/mediatek/mtk-svs.c
drivers/soundwire/amd_manager.c
drivers/soundwire/amd_manager.h
drivers/spi/spi-axi-spi-engine.c
drivers/spi/spi-hisi-kunpeng.c
drivers/spi/spi.c
drivers/thermal/thermal_debugfs.c
drivers/usb/core/hub.c
drivers/usb/core/port.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/host.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/uvc_configfs.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/xhci-plat.h
drivers/usb/host/xhci-rzv2m.c
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
drivers/usb/typec/tcpm/tcpm.c
drivers/vdpa/vdpa.c
drivers/video/fbdev/core/fb_defio.c
fs/9p/v9fs.h
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/bcachefs/backpointers.c
fs/bcachefs/bcachefs_format.h
fs/bcachefs/btree_gc.c
fs/bcachefs/btree_io.c
fs/bcachefs/btree_key_cache.c
fs/bcachefs/btree_node_scan.c
fs/bcachefs/btree_node_scan_types.h
fs/bcachefs/btree_types.h
fs/bcachefs/btree_update_interior.c
fs/bcachefs/buckets.c
fs/bcachefs/chardev.c
fs/bcachefs/fs.c
fs/bcachefs/inode.c
fs/bcachefs/journal_io.c
fs/bcachefs/recovery.c
fs/bcachefs/sb-clean.c
fs/bcachefs/sb-errors_types.h
fs/bcachefs/sb-members.c
fs/bcachefs/sb-members.h
fs/bcachefs/super.c
fs/bcachefs/thread_with_file.c
fs/bcachefs/thread_with_file.h
fs/btrfs/backref.c
fs/btrfs/extent_map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/messages.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/scrub.c
fs/btrfs/tests/extent-map-tests.c
fs/btrfs/volumes.c
fs/erofs/fscache.c
fs/erofs/internal.h
fs/erofs/super.c
fs/ioctl.c
fs/netfs/buffered_write.c
fs/nfs/inode.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4xdr.c
fs/nfsd/state.h
fs/ntfs3/Kconfig
fs/ntfs3/dir.c
fs/ntfs3/file.c
fs/ntfs3/inode.c
fs/ntfs3/ntfs_fs.h
fs/ntfs3/super.c
fs/proc/page.c
fs/smb/client/cifsfs.c
fs/smb/client/cifsglob.h
fs/smb/client/cifspdu.h
fs/smb/client/cifsproto.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h
fs/smb/client/fscache.c
fs/smb/client/misc.c
fs/smb/client/smb2misc.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2pdu.c
fs/smb/client/smb2pdu.h
fs/smb/client/smb2transport.c
fs/smb/client/trace.h
fs/smb/client/transport.c
fs/smb/common/smb2pdu.h
fs/smb/server/ksmbd_netlink.h
fs/smb/server/server.c
fs/smb/server/smb2pdu.c
fs/smb/server/vfs.c
fs/tracefs/event_inode.c
fs/tracefs/inode.c
fs/tracefs/internal.h
include/linux/cpu.h
include/linux/etherdevice.h
include/linux/filter.h
include/linux/firmware/qcom/qcom_qseecom.h
include/linux/firmware/qcom/qcom_scm.h
include/linux/mm.h
include/linux/page-flags.h
include/linux/profile.h
include/linux/regmap.h
include/linux/regulator/consumer.h
include/linux/skmsg.h
include/linux/sunrpc/svc_rdma.h
include/linux/tracefs.h
include/net/af_unix.h
include/net/bluetooth/hci_core.h
include/net/gro.h
include/net/mac80211.h
include/net/macsec.h
include/net/sock.h
include/net/tls.h
include/sound/cs35l56.h
include/sound/emu10k1.h
include/trace/events/mmflags.h
include/uapi/drm/etnaviv_drm.h
include/uapi/linux/vdpa.h
init/Kconfig
kernel/bounds.c
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/cpu.c
kernel/dma/swiotlb.c
kernel/profile.c
kernel/sched/fair.c
kernel/sched/isolation.c
kernel/softirq.c
kernel/trace/trace_events.c
kernel/trace/trace_probe.c
kernel/vmcore_info.c
kernel/workqueue.c
lib/Kconfig.debug
lib/dynamic_debug.c
lib/scatterlist.c
lib/stackdepot.c
mm/hugetlb.c
mm/zswap.c
net/8021q/vlan_core.c
net/ax25/af_ax25.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/sco.c
net/bridge/br_forward.c
net/bridge/br_netlink.c
net/core/filter.c
net/core/gro.c
net/core/skbuff.c
net/core/skmsg.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/icmp.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp_ao.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/ip6_offload.c
net/ipv6/udp.c
net/ipv6/udp_offload.c
net/l2tp/l2tp_eth.c
net/mac80211/chan.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_pathtbl.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/tx.c
net/mptcp/protocol.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/nft_chain_filter.c
net/nsh/nsh.c
net/openvswitch/conntrack.c
net/rxrpc/conn_object.c
net/rxrpc/insecure.c
net/rxrpc/rxkad.c
net/rxrpc/txbuf.c
net/sunrpc/xprtrdma/svc_rdma_rw.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtsock.c
net/tipc/msg.c
net/tls/tls.h
net/tls/tls_strp.c
net/unix/garbage.c
net/wireless/nl80211.c
net/wireless/trace.h
rust/Makefile
rust/kernel/init.rs
rust/kernel/lib.rs
rust/kernel/net/phy.rs
rust/macros/lib.rs
rust/macros/module.rs
scripts/Makefile.build
sound/hda/intel-dsp-config.c
sound/hda/intel-sdw-acpi.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/io.c
sound/pci/hda/cs35l56_hda.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/cs35l41.c
sound/soc/codecs/cs35l56-sdw.c
sound/soc/codecs/cs35l56-shared.c
sound/soc/codecs/cs35l56.c
sound/soc/codecs/da7219-aad.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt715-sdca.c
sound/soc/codecs/rt715-sdw.c
sound/soc/codecs/rt722-sdca.c
sound/soc/codecs/rt722-sdca.h
sound/soc/codecs/wsa881x.c
sound/soc/intel/avs/icl.c
sound/soc/intel/avs/topology.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/meson/Kconfig
sound/soc/meson/axg-card.c
sound/soc/meson/axg-fifo.c
sound/soc/meson/axg-tdm-formatter.c
sound/soc/meson/axg-tdm-interface.c
sound/soc/meson/axg-tdm.h
sound/soc/sof/core.c
sound/soc/sof/debug.c
sound/soc/sof/intel/pci-lnl.c
sound/soc/sof/ipc3-pcm.c
sound/soc/sof/ipc4-pcm.c
sound/soc/sof/pcm.c
sound/soc/sof/sof-audio.h
sound/soc/tegra/tegra186_dspk.c
sound/soc/ti/davinci-mcasp.c
tools/net/ynl/lib/ynl.py
tools/perf/arch/riscv/util/header.c
tools/testing/cxl/test/cxl.c
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
tools/testing/selftests/kselftest_harness.h
tools/testing/selftests/kvm/aarch64/vgic_init.c
tools/testing/selftests/mm/mdwe_test.c
tools/testing/selftests/mm/protection_keys.c
tools/testing/selftests/mm/run_vmtests.sh
tools/testing/selftests/mm/split_huge_page_test.c
tools/testing/selftests/riscv/hwprobe/cbo.c
tools/testing/selftests/riscv/hwprobe/hwprobe.h
tools/testing/selftests/syscall_user_dispatch/sud_test.c

index f877262b0be99a588a14c1ed744ef9a79ee5c515..9f41b3906b663794ca27b77730d12cba68f05c35 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -38,6 +38,16 @@ Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
 Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
 Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
 Alexey Makhalov <alexey.amakhalov@broadcom.com> <amakhalov@vmware.com>
+Alex Elder <elder@kernel.org>
+Alex Elder <elder@kernel.org> <aelder@sgi.com>
+Alex Elder <elder@kernel.org> <alex.elder@linaro.org>
+Alex Elder <elder@kernel.org> <alex.elder@linary.org>
+Alex Elder <elder@kernel.org> <elder@dreamhost.com>
+Alex Elder <elder@kernel.org> <elder@dreawmhost.com>
+Alex Elder <elder@kernel.org> <elder@ieee.org>
+Alex Elder <elder@kernel.org> <elder@inktank.com>
+Alex Elder <elder@kernel.org> <elder@linaro.org>
+Alex Elder <elder@kernel.org> <elder@newdream.net>
 Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
 Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
 Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
@@ -98,6 +108,8 @@ Ben Widawsky <bwidawsk@kernel.org> <ben@bwidawsk.net>
 Ben Widawsky <bwidawsk@kernel.org> <ben.widawsky@intel.com>
 Ben Widawsky <bwidawsk@kernel.org> <benjamin.widawsky@intel.com>
 Benjamin Poirier <benjamin.poirier@gmail.com> <bpoirier@suse.de>
+Benjamin Tissoires <bentiss@kernel.org> <benjamin.tissoires@gmail.com>
+Benjamin Tissoires <bentiss@kernel.org> <benjamin.tissoires@redhat.com>
 Bjorn Andersson <andersson@kernel.org> <bjorn@kryo.se>
 Bjorn Andersson <andersson@kernel.org> <bjorn.andersson@linaro.org>
 Bjorn Andersson <andersson@kernel.org> <bjorn.andersson@sonymobile.com>
@@ -500,6 +512,7 @@ Praveen BP <praveenbp@ti.com>
 Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> <pradeepc@codeaurora.org>
 Prasad Sodagudi <quic_psodagud@quicinc.com> <psodagud@codeaurora.org>
 Punit Agrawal <punitagrawal@gmail.com> <punit.agrawal@arm.com>
+Puranjay Mohan <puranjay@kernel.org> <puranjay12@gmail.com>
 Qais Yousef <qyousef@layalina.io> <qais.yousef@imgtec.com>
 Qais Yousef <qyousef@layalina.io> <qais.yousef@arm.com>
 Quentin Monnet <qmo@kernel.org> <quentin.monnet@netronome.com>
index 902ecd92a29fbe83df18d32d1a8fe652c8277132..213d0719e2b7a68e4daa12482a4c60361e19e3c4 100644 (file)
                        arch-independent options, each of which is an
                        aggregation of existing arch-specific options.
 
+                       Note, "mitigations" is supported if and only if the
+                       kernel was built with CPU_MITIGATIONS=y.
+
                        off
                                Disable all optional CPU mitigations.  This
                                improves system performance, but it may also
index d3504826f401541e1dd4946c3f6d9f55989bee46..c389d4fd7599df2a8003365ee7df3d12793fae16 100644 (file)
@@ -29,7 +29,7 @@ The essence of the process (aka 'TL;DR')
 ========================================
 
 *[If you are new to building or bisecting Linux, ignore this section and head
-over to the* ":ref:`step-by-step guide<introguide_bissbs>`" *below. It utilizes
+over to the* ':ref:`step-by-step guide <introguide_bissbs>`' *below. It utilizes
 the same commands as this section while describing them in brief fashion. The
 steps are nevertheless easy to follow and together with accompanying entries
 in a reference section mention many alternatives, pitfalls, and additional
@@ -38,8 +38,8 @@ aspects, all of which might be essential in your present case.]*
 **In case you want to check if a bug is present in code currently supported by
 developers**, execute just the *preparations* and *segment 1*; while doing so,
 consider the newest Linux kernel you regularly use to be the 'working' kernel.
-In the following example that's assumed to be 6.0.13, which is why the sources
-of 6.0 will be used to prepare the .config file.
+In the following example that's assumed to be 6.0, which is why its sources
+will be used to prepare the .config file.
 
 **In case you face a regression**, follow the steps at least till the end of
 *segment 2*. Then you can submit a preliminary report -- or continue with
@@ -61,7 +61,7 @@ will be considered the 'good' release and used to prepare the .config file.
     cd ~/linux/
     git remote add -t master stable \
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
-    git checkout --detach v6.0
+    git switch --detach v6.0
     # * Hint: if you used an existing clone, ensure no stale .config is around.
     make olddefconfig
     # * Ensure the former command picked the .config of the 'working' kernel.
@@ -87,7 +87,7 @@ will be considered the 'good' release and used to prepare the .config file.
   a) Checking out latest mainline code::
 
        cd ~/linux/
-       git checkout --force --detach mainline/master
+       git switch --discard-changes --detach mainline/master
 
   b) Build, install, and boot a kernel::
 
@@ -125,7 +125,7 @@ will be considered the 'good' release and used to prepare the .config file.
   a) Start by checking out the sources of the 'good' version::
 
        cd ~/linux/
-       git checkout --force --detach v6.0
+       git switch --discard-changes --detach v6.0
 
   b) Build, install, and boot a kernel as described earlier in *segment 1,
      section b* -- just feel free to skip the 'du' commands, as you have a rough
@@ -136,8 +136,7 @@ will be considered the 'good' release and used to prepare the .config file.
 
 * **Segment 3**: perform and validate the bisection.
 
-  a) In case your 'broken' version is a stable/longterm release, add the Git
-     branch holding it::
+  a) Retrieve the sources for your 'bad' version::
 
        git remote set-branches --add stable linux-6.1.y
        git fetch stable
@@ -157,11 +156,12 @@ will be considered the 'good' release and used to prepare the .config file.
      works with the newly built kernel. If it does, tell Git by executing
      ``git bisect good``; if it does not, run ``git bisect bad`` instead.
 
-     All three commands will make Git checkout another commit; then re-execute
+     All three commands will make Git check out another commit; then re-execute
      this step (e.g. build, install, boot, and test a kernel to then tell Git
      the outcome). Do so again and again until Git shows which commit broke
      things. If you run short of disk space during this process, check the
-     "Supplementary tasks" section below.
+     section 'Complementary tasks: cleanup during and after the process'
+     below.
 
   d) Once your finished the bisection, put a few things away::
 
@@ -172,14 +172,17 @@ will be considered the 'good' release and used to prepare the .config file.
 
   e) Try to verify the bisection result::
 
-       git checkout --force --detach mainline/master
+       git switch --discard-changes --detach mainline/master
        git revert --no-edit cafec0cacaca0
+       cp ~/kernel-config-working .config
+       ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted'
 
     This is optional, as some commits are impossible to revert. But if the
     second command worked flawlessly, build, install, and boot one more kernel
-    kernel, which should not show the regression.
+    kernel; just this time skip the first command copying the base .config file
+    over, as that already has been taken care off.
 
-* **Supplementary tasks**: cleanup during and after the process.
+* **Complementary tasks**: cleanup during and after the process.
 
   a) To avoid running out of disk space during a bisection, you might need to
      remove some kernels you built earlier. You most likely want to keep those
@@ -202,13 +205,25 @@ will be considered the 'good' release and used to prepare the .config file.
      the kernels you built earlier and later you might want to keep around for
      a week or two.
 
+* **Optional task**: test a debug patch or a proposed fix later::
+
+    git fetch mainline
+    git switch --discard-changes --detach mainline/master
+    git apply /tmp/foobars-proposed-fix-v1.patch
+    cp ~/kernel-config-working .config
+    ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1'
+
+  Build, install, and boot a kernel as described in *segment 1, section b* --
+  but this time omit the first command copying the build configuration over,
+  as that has been taken care of already.
+
 .. _introguide_bissbs:
 
 Step-by-step guide on how to verify bugs and bisect regressions
 ===============================================================
 
 This guide describes how to set up your own Linux kernels for investigating bugs
-or regressions you intent to report. How far you want to follow the instructions
+or regressions you intend to report. How far you want to follow the instructions
 depends on your issue:
 
 Execute all steps till the end of *segment 1* to **verify if your kernel problem
@@ -221,15 +236,17 @@ report; instead of the latter your could also head straight on and follow
 *segment 3* to **perform a bisection** for a full-fledged regression report
 developers are obliged to act upon.
 
- :ref:`Preparations: set up everything to build your own kernels.<introprep_bissbs>`
+ :ref:`Preparations: set up everything to build your own kernels <introprep_bissbs>`.
 
- :ref:`Segment 1: try to reproduce the problem with the latest codebase.<introlatestcheck_bissbs>`
+ :ref:`Segment 1: try to reproduce the problem with the latest codebase <introlatestcheck_bissbs>`.
 
- :ref:`Segment 2: check if the kernels you build work fine.<introworkingcheck_bissbs>`
+ :ref:`Segment 2: check if the kernels you build work fine <introworkingcheck_bissbs>`.
 
- :ref:`Segment 3: perform a bisection and validate the result.<introbisect_bissbs>`
+ :ref:`Segment 3: perform a bisection and validate the result <introbisect_bissbs>`.
 
- :ref:`Supplementary tasks: cleanup during and after following this guide.<introclosure_bissbs>`
+ :ref:`Complementary tasks: cleanup during and after following this guide <introclosure_bissbs>`.
+
+ :ref:`Optional tasks: test reverts, patches, or later versions <introoptional_bissbs>`.
 
 The steps in each segment illustrate the important aspects of the process, while
 a comprehensive reference section holds additional details for almost all of the
@@ -240,24 +257,35 @@ to get things rolling again.
 For further details on how to report Linux kernel issues or regressions check
 out Documentation/admin-guide/reporting-issues.rst, which works in conjunction
 with this document. It among others explains why you need to verify bugs with
-the latest 'mainline' kernel, even if you face a problem with a kernel from a
-'stable/longterm' series; for users facing a regression it also explains that
-sending a preliminary report after finishing segment 2 might be wise, as the
-regression and its culprit might be known already. For further details on
-what actually qualifies as a regression check out
-Documentation/admin-guide/reporting-regressions.rst.
+the latest 'mainline' kernel (e.g. versions like 6.0, 6.1-rc1, or 6.1-rc6),
+even if you face a problem with a kernel from a 'stable/longterm' series
+(say 6.0.13).
+
+For users facing a regression that document also explains why sending a
+preliminary report after segment 2 might be wise, as the regression and its
+culprit might be known already. For further details on what actually qualifies
+as a regression check out Documentation/admin-guide/reporting-regressions.rst.
+
+If you run into any problems while following this guide or have ideas how to
+improve it, :ref:`please let the kernel developers know <submit_improvements>`.
 
 .. _introprep_bissbs:
 
 Preparations: set up everything to build your own kernels
 ---------------------------------------------------------
 
+The following steps lay the groundwork for all further tasks.
+
+Note: the instructions assume you are building and testing on the same
+machine; if you want to compile the kernel on another system, check
+:ref:`Build kernels on a different machine <buildhost_bis>` below.
+
 .. _backup_bissbs:
 
 * Create a fresh backup and put system repair and restore tools at hand, just
   to be prepared for the unlikely case of something going sideways.
 
-  [:ref:`details<backup_bisref>`]
+  [:ref:`details <backup_bisref>`]
 
 .. _vanilla_bissbs:
 
@@ -265,7 +293,7 @@ Preparations: set up everything to build your own kernels
   builds them automatically. That includes but is not limited to DKMS, openZFS,
   VirtualBox, and Nvidia's graphics drivers (including the GPLed kernel module).
 
-  [:ref:`details<vanilla_bisref>`]
+  [:ref:`details <vanilla_bisref>`]
 
 .. _secureboot_bissbs:
 
@@ -276,48 +304,49 @@ Preparations: set up everything to build your own kernels
   their restrictions through a process initiated by
   ``mokutil --disable-validation``.
 
-  [:ref:`details<secureboot_bisref>`]
+  [:ref:`details <secureboot_bisref>`]
 
 .. _rangecheck_bissbs:
 
 * Determine the kernel versions considered 'good' and 'bad' throughout this
-  guide.
+  guide:
 
-  Do you follow this guide to verify if a bug is present in the code developers
-  care for? Then consider the mainline release your 'working' kernel (the newest
-  one you regularly use) is based on to be the 'good' version; if your 'working'
-  kernel for example is 6.0.11, then your 'good' kernel is 6.0.
+  * Do you follow this guide to verify if a bug is present in the code the
+    primary developers care for? Then consider the version of the newest kernel
+    you regularly use currently as 'good' (e.g. 6.0, 6.0.13, or 6.1-rc2).
 
-  In case you face a regression, it depends on the version range where the
-  regression was introduced:
+  * Do you face a regression, e.g. something broke or works worse after
+    switching to a newer kernel version? In that case it depends on the version
+    range during which the problem appeared:
 
-  * Something which used to work in Linux 6.0 broke when switching to Linux
-    6.1-rc1? Then henceforth regard 6.0 as the last known 'good' version
-    and 6.1-rc1 as the first 'bad' one.
+    * Something regressed when updating from a stable/longterm release
+      (say 6.0.13) to a newer mainline series (like 6.1-rc7 or 6.1) or a
+      stable/longterm version based on one (say 6.1.5)? Then consider the
+      mainline release your working kernel is based on to be the 'good'
+      version (e.g. 6.0) and the first version to be broken as the 'bad' one
+      (e.g. 6.1-rc7, 6.1, or 6.1.5). Note, at this point it is merely assumed
+      that 6.0 is fine; this hypothesis will be checked in segment 2.
 
-  * Some function stopped working when updating from 6.0.11 to 6.1.4? Then for
-    the time being consider 6.0 as the last 'good' version and 6.1.4 as
-    the 'bad' one. Note, at this point it is merely assumed that 6.0 is fine;
-    this assumption will be checked in segment 2.
+    * Something regressed when switching from one mainline version (say 6.0) to
+      a later one (like 6.1-rc1) or a stable/longterm release based on it
+      (say 6.1.5)? Then regard the last working version (e.g. 6.0) as 'good' and
+      the first broken (e.g. 6.1-rc1 or 6.1.5) as 'bad'.
 
-  * A feature you used in 6.0.11 does not work at all or worse in 6.1.13? In
-    that case you want to bisect within a stable/longterm series: consider
-    6.0.11 as the last known 'good' version and 6.0.13 as the first 'bad'
-    one. Note, in this case you still want to compile and test a mainline kernel
-    as explained in segment 1: the outcome will determine if you need to report
-    your issue to the regular developers or the stable team.
+    * Something regressed when updating within a stable/longterm series (say
+      from 6.0.13 to 6.0.15)? Then consider those versions as 'good' and 'bad'
+      (e.g. 6.0.13 and 6.0.15), as you need to bisect within that series.
 
   *Note, do not confuse 'good' version with 'working' kernel; the latter term
   throughout this guide will refer to the last kernel that has been working
   fine.*
 
-  [:ref:`details<rangecheck_bisref>`]
+  [:ref:`details <rangecheck_bisref>`]
 
 .. _bootworking_bissbs:
 
 * Boot into the 'working' kernel and briefly use the apparently broken feature.
 
-  [:ref:`details<bootworking_bisref>`]
+  [:ref:`details <bootworking_bisref>`]
 
 .. _diskspace_bissbs:
 
@@ -327,7 +356,7 @@ Preparations: set up everything to build your own kernels
   debug symbols: both explain approaches reducing the amount of space, which
   should allow you to master these tasks with about 4 Gigabytes free space.
 
-  [:ref:`details<diskspace_bisref>`]
+  [:ref:`details <diskspace_bisref>`]
 
 .. _buildrequires_bissbs:
 
@@ -337,7 +366,7 @@ Preparations: set up everything to build your own kernels
   reference section shows how to quickly install those on various popular Linux
   distributions.
 
-  [:ref:`details<buildrequires_bisref>`]
+  [:ref:`details <buildrequires_bisref>`]
 
 .. _sources_bissbs:
 
@@ -360,14 +389,23 @@ Preparations: set up everything to build your own kernels
     git remote add -t master stable \
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
 
-  [:ref:`details<sources_bisref>`]
+  [:ref:`details <sources_bisref>`]
+
+.. _stablesources_bissbs:
+
+* Is one of the versions you earlier established as 'good' or 'bad' a stable or
+  longterm release (say 6.1.5)? Then download the code for the series it belongs
+  to ('linux-6.1.y' in this example)::
+
+    git remote set-branches --add stable linux-6.1.y
+    git fetch stable
 
 .. _oldconfig_bissbs:
 
 * Start preparing a kernel build configuration (the '.config' file).
 
   Before doing so, ensure you are still running the 'working' kernel an earlier
-  step told you to boot; if you are unsure, check the current kernel release
+  step told you to boot; if you are unsure, check the current kernelrelease
   identifier using ``uname -r``.
 
   Afterwards check out the source code for the version earlier established as
@@ -375,7 +413,7 @@ Preparations: set up everything to build your own kernels
   the version number in this and all later Git commands needs to be prefixed
   with a 'v'::
 
-    git checkout --detach v6.0
+    git switch --discard-changes --detach v6.0
 
   Now create a build configuration file::
 
@@ -398,7 +436,7 @@ Preparations: set up everything to build your own kernels
   'make olddefconfig' again and check if it now picked up the right config file
   as base.
 
-  [:ref:`details<oldconfig_bisref>`]
+  [:ref:`details <oldconfig_bisref>`]
 
 .. _localmodconfig_bissbs:
 
@@ -432,7 +470,7 @@ Preparations: set up everything to build your own kernels
   spending much effort on, as long as it boots and allows to properly test the
   feature that causes trouble.
 
-  [:ref:`details<localmodconfig_bisref>`]
+  [:ref:`details <localmodconfig_bisref>`]
 
 .. _tagging_bissbs:
 
@@ -442,7 +480,7 @@ Preparations: set up everything to build your own kernels
     ./scripts/config --set-str CONFIG_LOCALVERSION '-local'
     ./scripts/config -e CONFIG_LOCALVERSION_AUTO
 
-  [:ref:`details<tagging_bisref>`]
+  [:ref:`details <tagging_bisref>`]
 
 .. _debugsymbols_bissbs:
 
@@ -461,7 +499,7 @@ Preparations: set up everything to build your own kernels
     ./scripts/config -d DEBUG_INFO -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT \
       -d DEBUG_INFO_DWARF4 -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE
 
-  [:ref:`details<debugsymbols_bisref>`]
+  [:ref:`details <debugsymbols_bisref>`]
 
 .. _configmods_bissbs:
 
@@ -471,14 +509,14 @@ Preparations: set up everything to build your own kernels
   * Are you running Debian? Then you want to avoid known problems by performing
     additional adjustments explained in the reference section.
 
-    [:ref:`details<configmods_distros_bisref>`].
+    [:ref:`details <configmods_distros_bisref>`].
 
   * If you want to influence other aspects of the configuration, do so now using
     your preferred tool. Note, to use make targets like 'menuconfig' or
     'nconfig', you will need to install the development files of ncurses; for
     'xconfig' you likewise need the Qt5 or Qt6 headers.
 
-    [:ref:`details<configmods_individual_bisref>`].
+    [:ref:`details <configmods_individual_bisref>`].
 
 .. _saveconfig_bissbs:
 
@@ -488,7 +526,7 @@ Preparations: set up everything to build your own kernels
      make olddefconfig
      cp .config ~/kernel-config-working
 
-  [:ref:`details<saveconfig_bisref>`]
+  [:ref:`details <saveconfig_bisref>`]
 
 .. _introlatestcheck_bissbs:
 
@@ -498,16 +536,30 @@ Segment 1: try to reproduce the problem with the latest codebase
 The following steps verify if the problem occurs with the code currently
 supported by developers. In case you face a regression, it also checks that the
 problem is not caused by some .config change, as reporting the issue then would
-be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
+be a waste of time. [:ref:`details <introlatestcheck_bisref>`]
 
 .. _checkoutmaster_bissbs:
 
-* Check out the latest Linux codebase::
+* Check out the latest Linux codebase.
 
-    cd ~/linux/
-    git checkout --force --detach mainline/master
+  * Are your 'good' and 'bad' versions from the same stable or longterm series?
+    Then check the `front page of kernel.org <https://kernel.org/>`_: if it
+    lists a release from that series without an '[EOL]' tag, checkout the series
+    latest version ('linux-6.1.y' in the following example)::
+
+      cd ~/linux/
+      git switch --discard-changes --detach stable/linux-6.1.y
+
+    Your series is unsupported, if is not listed or carrying a 'end of life'
+    tag. In that case you might want to check if a successor series (say
+    linux-6.2.y) or mainline (see next point) fix the bug.
 
-  [:ref:`details<checkoutmaster_bisref>`]
+  * In all other cases, run::
+
+      cd ~/linux/
+      git switch --discard-changes --detach mainline/master
+
+  [:ref:`details <checkoutmaster_bisref>`]
 
 .. _build_bissbs:
 
@@ -522,7 +574,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   reference section for alternatives, which obviously will require other
   steps to install as well.
 
-  [:ref:`details<build_bisref>`]
+  [:ref:`details <build_bisref>`]
 
 .. _install_bissbs:
 
@@ -555,7 +607,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   down: if you will build more kernels as described in segment 2 and 3, you will
   have to perform those again after executing ``command -v installkernel [...]``.
 
-  [:ref:`details<install_bisref>`]
+  [:ref:`details <install_bisref>`]
 
 .. _storagespace_bissbs:
 
@@ -568,7 +620,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   Write down or remember those two values for later: they enable you to prevent
   running out of disk space accidentally during a bisection.
 
-  [:ref:`details<storagespace_bisref>`]
+  [:ref:`details <storagespace_bisref>`]
 
 .. _kernelrelease_bissbs:
 
@@ -595,7 +647,7 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   If that command does not return '0', check the reference section, as the cause
   for this might interfere with your testing.
 
-  [:ref:`details<tainted_bisref>`]
+  [:ref:`details <tainted_bisref>`]
 
 .. _recheckbroken_bissbs:
 
@@ -603,21 +655,19 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
   out the instructions in the reference section to ensure nothing went sideways
   during your tests.
 
-  [:ref:`details<recheckbroken_bisref>`]
+  [:ref:`details <recheckbroken_bisref>`]
 
 .. _recheckstablebroken_bissbs:
 
-* Are you facing a problem within a stable/longterm series, but failed to
-  reproduce it with the mainline kernel you just built? One that according to
-  the `front page of kernel.org <https://kernel.org/>`_ is still supported? Then
-  check if the latest codebase for the particular series might already fix the
-  problem. To do so, add the stable series Git branch for your 'good' kernel
-  (again, this here is assumed to be 6.0) and check out the latest version::
+* Did you just built a stable or longterm kernel? And were you able to reproduce
+  the regression with it? Then you should test the latest mainline codebase as
+  well, because the result determines which developers the bug must be submitted
+  to.
+
+  To prepare that test, check out current mainline::
 
     cd ~/linux/
-    git remote set-branches --add stable linux-6.0.y
-    git fetch stable
-    git checkout --force --detach linux-6.0.y
+    git switch --discard-changes --detach mainline/master
 
   Now use the checked out code to build and install another kernel using the
   commands the earlier steps already described in more detail::
@@ -639,14 +689,16 @@ be a waste of time. [:ref:`details<introlatestcheck_bisref>`]
     uname -r
     cat /proc/sys/kernel/tainted
 
-  Now verify if this kernel is showing the problem.
+  Now verify if this kernel is showing the problem. If it does, then you need
+  to report the bug to the primary developers; if it does not, report it to the
+  stable team. See Documentation/admin-guide/reporting-issues.rst for details.
 
-  [:ref:`details<recheckstablebroken_bisref>`]
+  [:ref:`details <recheckstablebroken_bisref>`]
 
 Do you follow this guide to verify if a problem is present in the code
 currently supported by Linux kernel developers? Then you are done at this
 point. If you later want to remove the kernel you just built, check out
-:ref:`Supplementary tasks: cleanup during and after following this guide<introclosure_bissbs>`.
+:ref:`Complementary tasks: cleanup during and after following this guide <introclosure_bissbs>`.
 
 In case you face a regression, move on and execute at least the next segment
 as well.
@@ -658,7 +710,7 @@ Segment 2: check if the kernels you build work fine
 
 In case of a regression, you now want to ensure the trimmed configuration file
 you created earlier works as expected; a bisection with the .config file
-otherwise would be a waste of time. [:ref:`details<introworkingcheck_bisref>`]
+otherwise would be a waste of time. [:ref:`details <introworkingcheck_bisref>`]
 
 .. _recheckworking_bissbs:
 
@@ -669,7 +721,7 @@ otherwise would be a waste of time. [:ref:`details<introworkingcheck_bisref>`]
   'good' (once again assumed to be 6.0 here)::
 
     cd ~/linux/
-    git checkout --detach v6.0
+    git switch --discard-changes --detach v6.0
 
   Now use the checked out code to configure, build, and install another kernel
   using the commands the previous subsection explained in more detail::
@@ -693,7 +745,7 @@ otherwise would be a waste of time. [:ref:`details<introworkingcheck_bisref>`]
   Now check if this kernel works as expected; if not, consult the reference
   section for further instructions.
 
-  [:ref:`details<recheckworking_bisref>`]
+  [:ref:`details <recheckworking_bisref>`]
 
 .. _introbisect_bissbs:
 
@@ -703,18 +755,11 @@ Segment 3: perform the bisection and validate the result
 With all the preparations and precaution builds taken care of, you are now ready
 to begin the bisection. This will make you build quite a few kernels -- usually
 about 15 in case you encountered a regression when updating to a newer series
-(say from 6.0.11 to 6.1.3). But do not worry, due to the trimmed build
+(say from 6.0.13 to 6.1.5). But do not worry, due to the trimmed build
 configuration created earlier this works a lot faster than many people assume:
 overall on average it will often just take about 10 to 15 minutes to compile
 each kernel on commodity x86 machines.
 
-* In case your 'bad' version is a stable/longterm release (say 6.1.5), add its
-  stable branch, unless you already did so earlier::
-
-    cd ~/linux/
-    git remote set-branches --add stable linux-6.1.y
-    git fetch stable
-
 .. _bisectstart_bissbs:
 
 * Start the bisection and tell Git about the versions earlier established as
@@ -725,7 +770,7 @@ each kernel on commodity x86 machines.
     git bisect good v6.0
     git bisect bad v6.1.5
 
-  [:ref:`details<bisectstart_bisref>`]
+  [:ref:`details <bisectstart_bisref>`]
 
 .. _bisectbuild_bissbs:
 
@@ -745,7 +790,7 @@ each kernel on commodity x86 machines.
   If compilation fails for some reason, run ``git bisect skip`` and restart
   executing the stack of commands from the beginning.
 
-  In case you skipped the "test latest codebase" step in the guide, check its
+  In case you skipped the 'test latest codebase' step in the guide, check its
   description as for why the 'df [...]' and 'make -s kernelrelease [...]'
   commands are here.
 
@@ -754,7 +799,7 @@ each kernel on commodity x86 machines.
   totally normal to see release identifiers like '6.0-rc1-local-gcafec0cacaca0'
   if you bisect between versions 6.1 and 6.2 for example.
 
-  [:ref:`details<bisectbuild_bisref>`]
+  [:ref:`details <bisectbuild_bisref>`]
 
 .. _bisecttest_bissbs:
 
@@ -794,7 +839,7 @@ each kernel on commodity x86 machines.
   might need to scroll up to see the message mentioning the culprit;
   alternatively, run ``git bisect log > ~/bisection-log``.
 
-  [:ref:`details<bisecttest_bisref>`]
+  [:ref:`details <bisecttest_bisref>`]
 
 .. _bisectlog_bissbs:
 
@@ -806,7 +851,7 @@ each kernel on commodity x86 machines.
     cp .config ~/bisection-config-culprit
     git bisect reset
 
-  [:ref:`details<bisectlog_bisref>`]
+  [:ref:`details <bisectlog_bisref>`]
 
 .. _revert_bissbs:
 
@@ -823,16 +868,16 @@ each kernel on commodity x86 machines.
   Begin by checking out the latest codebase depending on the range you bisected:
 
   * Did you face a regression within a stable/longterm series (say between
-    6.0.11 and 6.0.13) that does not happen in mainline? Then check out the
+    6.0.13 and 6.0.15) that does not happen in mainline? Then check out the
     latest codebase for the affected series like this::
 
       git fetch stable
-      git checkout --force --detach linux-6.0.y
+      git switch --discard-changes --detach linux-6.0.y
 
   * In all other cases check out latest mainline::
 
       git fetch mainline
-      git checkout --force --detach mainline/master
+      git switch --discard-changes --detach mainline/master
 
     If you bisected a regression within a stable/longterm series that also
     happens in mainline, there is one more thing to do: look up the mainline
@@ -846,27 +891,33 @@ each kernel on commodity x86 machines.
 
     git revert --no-edit cafec0cacaca0
 
-  If that fails, give up trying and move on to the next step. But if it works,
-  build a kernel again using the familiar command sequence::
+  If that fails, give up trying and move on to the next step; if it works,
+  adjust the tag to facilitate the identification and prevent accidentally
+  overwriting another kernel::
 
     cp ~/kernel-config-working .config
+    ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted'
+
+  Build a kernel using the familiar command sequence, just without copying the
+  the base .config over::
+
     make olddefconfig &&
-    make -j $(nproc --all) &&
+    make -j $(nproc --all)
     # * Check if the free space suffices holding another kernel:
     df -h /boot/ /lib/modules/
     sudo make modules_install
     command -v installkernel && sudo make install
-    Make -s kernelrelease | tee -a ~/kernels-built
+    make -s kernelrelease | tee -a ~/kernels-built
     reboot
 
-  Now check one last time if the feature that made you perform a bisection work
-  with that kernel.
+  Now check one last time if the feature that made you perform a bisection works
+  with that kernel: if everything went well, it should not show the regression.
 
-  [:ref:`details<revert_bisref>`]
+  [:ref:`details <revert_bisref>`]
 
 .. _introclosure_bissbs:
 
-Supplementary tasks: cleanup during and after the bisection
+Complementary tasks: cleanup during and after the bisection
 -----------------------------------------------------------
 
 During and after following this guide you might want or need to remove some of
@@ -903,7 +954,7 @@ space might run out.
   kernel image and related files behind; in that case remove them as described
   in the reference section.
 
-  [:ref:`details<makeroom_bisref>`]
+  [:ref:`details <makeroom_bisref>`]
 
 .. _finishingtouch_bissbs:
 
@@ -926,18 +977,99 @@ space might run out.
     the version considered 'good', and the last three or four you compiled
     during the actual bisection process.
 
-  [:ref:`details<finishingtouch_bisref>`]
+  [:ref:`details <finishingtouch_bisref>`]
+
+.. _introoptional_bissbs:
+
+Optional: test reverts, patches, or later versions
+--------------------------------------------------
+
+While or after reporting a bug, you might want or potentially will be asked to
+test reverts, debug patches, proposed fixes, or other versions. In that case
+follow these instructions.
+
+* Update your Git clone and check out the latest code.
+
+  * In case you want to test mainline, fetch its latest changes before checking
+    its code out::
+
+      git fetch mainline
+      git switch --discard-changes --detach mainline/master
+
+  * In case you want to test a stable or longterm kernel, first add the branch
+    holding the series you are interested in (6.2 in the example), unless you
+    already did so earlier::
+
+      git remote set-branches --add stable linux-6.2.y
+
+    Then fetch the latest changes and check out the latest version from the
+    series::
+
+      git fetch stable
+      git switch --discard-changes --detach stable/linux-6.2.y
+
+* Copy your kernel build configuration over::
+
+    cp ~/kernel-config-working .config
+
+* Your next step depends on what you want to do:
+
+  * In case you just want to test the latest codebase, head to the next step,
+    you are already all set.
+
+  * In case you want to test if a revert fixes an issue, revert one or multiple
+    changes by specifying their commit ids::
+
+      git revert --no-edit cafec0cacaca0
+
+    Now give that kernel a special tag to facilitates its identification and
+    prevent accidentally overwriting another kernel::
+
+      ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted'
+
+  * In case you want to test a patch, store the patch in a file like
+    '/tmp/foobars-proposed-fix-v1.patch' and apply it like this::
+
+      git apply /tmp/foobars-proposed-fix-v1.patch
+
+    In case of multiple patches, repeat this step with the others.
+
+    Now give that kernel a special tag to facilitates its identification and
+    prevent accidentally overwriting another kernel::
+
+    ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1'
+
+* Build a kernel using the familiar commands, just without copying the kernel
+  build configuration over, as that has been taken care of already::
+
+    make olddefconfig &&
+    make -j $(nproc --all)
+    # * Check if the free space suffices holding another kernel:
+    df -h /boot/ /lib/modules/
+    sudo make modules_install
+    command -v installkernel && sudo make install
+    make -s kernelrelease | tee -a ~/kernels-built
+    reboot
+
+* Now verify you booted the newly built kernel and check it.
+
+[:ref:`details <introoptional_bisref>`]
 
 .. _submit_improvements:
 
-This concludes the step-by-step guide.
+Conclusion
+----------
+
+You have reached the end of the step-by-step guide.
 
 Did you run into trouble following any of the above steps not cleared up by the
 reference section below? Did you spot errors? Or do you have ideas how to
-improve the guide? Then please take a moment and let the maintainer of this
+improve the guide?
+
+If any of that applies, please take a moment and let the maintainer of this
 document know by email (Thorsten Leemhuis <linux@leemhuis.info>), ideally while
 CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is
-vital to improve this document further, which is in everybody's interest, as it
+vital to improve this text further, which is in everybody's interest, as it
 will enable more people to master the task described here -- and hopefully also
 improve similar guides inspired by this one.
 
@@ -948,10 +1080,20 @@ Reference section for the step-by-step guide
 This section holds additional information for almost all the items in the above
 step-by-step guide.
 
+Preparations for building your own kernels
+------------------------------------------
+
+  *The steps in this section lay the groundwork for all further tests.*
+  [:ref:`... <introprep_bissbs>`]
+
+The steps in all later sections of this guide depend on those described here.
+
+[:ref:`back to step-by-step guide <introprep_bissbs>`].
+
 .. _backup_bisref:
 
 Prepare for emergencies
------------------------
+~~~~~~~~~~~~~~~~~~~~~~~
 
   *Create a fresh backup and put system repair and restore tools at hand.*
   [:ref:`... <backup_bissbs>`]
@@ -966,7 +1108,7 @@ for something going sideways, even if that should not happen.
 .. _vanilla_bisref:
 
 Remove anything related to externally maintained kernel modules
----------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Remove all software that depends on externally developed kernel drivers or
   builds them automatically.* [:ref:`...<vanilla_bissbs>`]
@@ -984,7 +1126,7 @@ explains in more detail.
 .. _secureboot_bisref:
 
 Deal with techniques like Secure Boot
--------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *On platforms with 'Secure Boot' or similar techniques, prepare everything to
   ensure the system will permit your self-compiled kernel to boot later.*
@@ -1021,7 +1163,7 @@ Afterwards, permit MokManager to reboot the machine.
 .. _bootworking_bisref:
 
 Boot the last kernel that was working
--------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Boot into the last working kernel and briefly recheck if the feature that
   regressed really works.* [:ref:`...<bootworking_bissbs>`]
@@ -1034,7 +1176,7 @@ the right thing.
 .. _diskspace_bisref:
 
 Space requirements
-------------------
+~~~~~~~~~~~~~~~~~~
 
   *Ensure to have enough free space for building Linux.*
   [:ref:`... <diskspace_bissbs>`]
@@ -1052,32 +1194,32 @@ space by quite a few gigabytes.
 .. _rangecheck_bisref:
 
 Bisection range
----------------
+~~~~~~~~~~~~~~~
 
   *Determine the kernel versions considered 'good' and 'bad' throughout this
   guide.* [:ref:`...<rangecheck_bissbs>`]
 
 Establishing the range of commits to be checked is mostly straightforward,
 except when a regression occurred when switching from a release of one stable
-series to a release of a later series (e.g. from 6.0.11 to 6.1.4). In that case
+series to a release of a later series (e.g. from 6.0.13 to 6.1.5). In that case
 Git will need some hand holding, as there is no straight line of descent.
 
 That's because with the release of 6.0 mainline carried on to 6.1 while the
 stable series 6.0.y branched to the side. It's therefore theoretically possible
-that the issue you face with 6.1.4 only worked in 6.0.11, as it was fixed by a
+that the issue you face with 6.1.5 only worked in 6.0.13, as it was fixed by a
 commit that went into one of the 6.0.y releases, but never hit mainline or the
 6.1.y series. Thankfully that normally should not happen due to the way the
 stable/longterm maintainers maintain the code. It's thus pretty safe to assume
 6.0 as a 'good' kernel. That assumption will be tested anyway, as that kernel
 will be built and tested in the segment '2' of this guide; Git would force you
-to do this as well, if you tried bisecting between 6.0.11 and 6.1.13.
+to do this as well, if you tried bisecting between 6.0.13 and 6.1.15.
 
 [:ref:`back to step-by-step guide <rangecheck_bissbs>`]
 
 .. _buildrequires_bisref:
 
 Install build requirements
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Install all software required to build a Linux kernel.*
   [:ref:`...<buildrequires_bissbs>`]
@@ -1117,7 +1259,7 @@ These commands install a few packages that are often, but not always needed. You
 for example might want to skip installing the development headers for ncurses,
 which you will only need in case you later might want to adjust the kernel build
 configuration using make the targets 'menuconfig' or 'nconfig'; likewise omit
-the headers of Qt6 is you do not plan to adjust the .config using 'xconfig'.
+the headers of Qt6 if you do not plan to adjust the .config using 'xconfig'.
 
 You furthermore might need additional libraries and their development headers
 for tasks not covered in this guide -- for example when building utilities from
@@ -1128,7 +1270,7 @@ the kernel's tools/ directory.
 .. _sources_bisref:
 
 Download the sources using Git
-------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Retrieve the Linux mainline sources.*
   [:ref:`...<sources_bissbs>`]
@@ -1148,7 +1290,7 @@ work better for you:
 .. _sources_bundle_bisref:
 
 Downloading Linux mainline sources using a bundle
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"""""""""""""""""""""""""""""""""""""""""""""""""
 
 Use the following commands to retrieve the Linux mainline sources using a
 bundle::
@@ -1184,7 +1326,7 @@ First, execute the following command to retrieve the latest mainline codebase::
       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
 
 Now deepen your clone's history to the second predecessor of the mainline
-release of your 'good' version. In case the latter are 6.0 or 6.0.11, 5.19 would
+release of your 'good' version. In case the latter are 6.0 or 6.0.13, 5.19 would
 be the first predecessor and 5.18 the second -- hence deepen the history up to
 that version::
 
@@ -1219,7 +1361,7 @@ Note, shallow clones have a few peculiar characteristics:
 .. _oldconfig_bisref:
 
 Start defining the build configuration for your kernel
-------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Start preparing a kernel build configuration (the '.config' file).*
   [:ref:`... <oldconfig_bissbs>`]
@@ -1279,7 +1421,7 @@ that file to the build machine and store it as ~/linux/.config; afterwards run
 .. _localmodconfig_bisref:
 
 Trim the build configuration for your kernel
---------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Disable any kernel modules apparently superfluous for your setup.*
   [:ref:`... <localmodconfig_bissbs>`]
@@ -1328,7 +1470,7 @@ step-by-step guide mentions::
 .. _tagging_bisref:
 
 Tag the kernels about to be build
----------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Ensure all the kernels you will build are clearly identifiable using a
   special tag and a unique version identifier.* [:ref:`... <tagging_bissbs>`]
@@ -1344,7 +1486,7 @@ confusing during the bisection.
 .. _debugsymbols_bisref:
 
 Decide to enable or disable debug symbols
------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Decide how to handle debug symbols.* [:ref:`... <debugsymbols_bissbs>`]
 
@@ -1373,7 +1515,7 @@ explains this process in more detail.
 .. _configmods_bisref:
 
 Adjust build configuration
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check if you may want or need to adjust some other kernel configuration
   options:*
@@ -1384,7 +1526,7 @@ kernel configuration options.
 .. _configmods_distros_bisref:
 
 Distro specific adjustments
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"""""""""""""""""""""""""""
 
   *Are you running* [:ref:`... <configmods_bissbs>`]
 
@@ -1409,7 +1551,7 @@ when following this guide on a few commodity distributions.
 .. _configmods_individual_bisref:
 
 Individual adjustments
-~~~~~~~~~~~~~~~~~~~~~~
+""""""""""""""""""""""
 
   *If you want to influence the other aspects of the configuration, do so
   now.* [:ref:`... <configmods_bissbs>`]
@@ -1426,13 +1568,13 @@ is missing.
 .. _saveconfig_bisref:
 
 Put the .config file aside
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Reprocess the .config after the latest changes and store it in a safe place.*
   [:ref:`... <saveconfig_bissbs>`]
 
 Put the .config you prepared aside, as you want to copy it back to the build
-directory every time  during this guide before you start building another
+directory every time during this guide before you start building another
 kernel. That's because going back and forth between different versions can alter
 .config files in odd ways; those occasionally cause side effects that could
 confuse testing or in some cases render the result of your bisection
@@ -1442,8 +1584,8 @@ meaningless.
 
 .. _introlatestcheck_bisref:
 
-Try to reproduce the regression
------------------------------------------
+Try to reproduce the problem with the latest codebase
+-----------------------------------------------------
 
   *Verify the regression is not caused by some .config change and check if it
   still occurs with the latest codebase.* [:ref:`... <introlatestcheck_bissbs>`]
@@ -1490,28 +1632,28 @@ highly recommended for these reasons:
 
   Your report might be ignored if you send it to the wrong party -- and even
   when you get a reply there is a decent chance that developers tell you to
-  evaluate   which of the two cases it is before they take a closer look.
+  evaluate which of the two cases it is before they take a closer look.
 
 [:ref:`back to step-by-step guide <introlatestcheck_bissbs>`]
 
 .. _checkoutmaster_bisref:
 
 Check out the latest Linux codebase
------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check out the latest Linux codebase.*
-  [:ref:`... <introlatestcheck_bissbs>`]
+  [:ref:`... <checkoutmaster_bissbs>`]
 
 In case you later want to recheck if an ever newer codebase might fix the
 problem, remember to run that ``git fetch --shallow-exclude [...]`` command
 again mentioned earlier to update your local Git repository.
 
-[:ref:`back to step-by-step guide <introlatestcheck_bissbs>`]
+[:ref:`back to step-by-step guide <checkoutmaster_bissbs>`]
 
 .. _build_bisref:
 
 Build your kernel
------------------
+~~~~~~~~~~~~~~~~~
 
   *Build the image and the modules of your first kernel using the config file
   you prepared.* [:ref:`... <build_bissbs>`]
@@ -1521,7 +1663,7 @@ yourself. Another subsection explains how to directly package your kernel up as
 deb, rpm or tar file.
 
 Dealing with build errors
-~~~~~~~~~~~~~~~~~~~~~~~~~
+"""""""""""""""""""""""""
 
 When a build error occurs, it might be caused by some aspect of your machine's
 setup that often can be fixed quickly; other times though the problem lies in
@@ -1552,11 +1694,11 @@ by modifying your search terms or using another line from the error messages.
 
 In the end, most issues you run into have likely been encountered and
 reported by others already. That includes issues where the cause is not your
-system, but lies in the code. If you run into one of those, you might thus find a
-solution (e.g. a patch) or workaround for your issue, too.
+system, but lies in the code. If you run into one of those, you might thus find
+solution (e.g. a patch) or workaround for your issue, too.
 
 Package your kernel up
-~~~~~~~~~~~~~~~~~~~~~~
+""""""""""""""""""""""
 
 The step-by-step guide uses the default make targets (e.g. 'bzImage' and
 'modules' on x86) to build the image and the modules of your kernel, which later
@@ -1587,7 +1729,7 @@ distribution's kernel packages.
 .. _install_bisref:
 
 Put the kernel in place
------------------------
+~~~~~~~~~~~~~~~~~~~~~~~
 
   *Install the kernel you just built.* [:ref:`... <install_bissbs>`]
 
@@ -1630,7 +1772,7 @@ process. Afterwards add your kernel to your bootloader configuration and reboot.
 .. _storagespace_bisref:
 
 Storage requirements per kernel
--------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check how much storage space the kernel, its modules, and other related files
   like the initramfs consume.* [:ref:`... <storagespace_bissbs>`]
@@ -1651,7 +1793,7 @@ need to look in different places.
 .. _tainted_bisref:
 
 Check if your newly built kernel considers itself 'tainted'
------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Check if the kernel marked itself as 'tainted'.*
   [:ref:`... <tainted_bissbs>`]
@@ -1670,7 +1812,7 @@ interest, as your testing might be flawed otherwise.
 .. _recheckbroken_bisref:
 
 Check the kernel built from a recent mainline codebase
-------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Verify if your bug occurs with the newly built kernel.*
   [:ref:`... <recheckbroken_bissbs>`]
@@ -1696,7 +1838,7 @@ the kernel you built from the latest codebase. These are the most frequent:
 .. _recheckstablebroken_bisref:
 
 Check the kernel built from the latest stable/longterm codebase
----------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Are you facing a regression within a stable/longterm release, but failed to
   reproduce it with the kernel you just built using the latest mainline sources?
@@ -1741,7 +1883,7 @@ ensure the kernel version you assumed to be 'good' earlier in the process (e.g.
 .. _recheckworking_bisref:
 
 Build your own version of the 'good' kernel
--------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Build your own variant of the working kernel and check if the feature that
   regressed works as expected with it.* [:ref:`... <recheckworking_bissbs>`]
@@ -1767,15 +1909,25 @@ multitude of reasons why this might happen. Some ideas where to look:
 
 Note, if you found and fixed problems with the .config file, you want to use it
 to build another kernel from the latest codebase, as your earlier tests with
-mainline and the latest version from an affected stable/longterm series were most
-likely flawed.
+mainline and the latest version from an affected stable/longterm series were
+most likely flawed.
 
 [:ref:`back to step-by-step guide <recheckworking_bissbs>`]
 
+Perform a bisection and validate the result
+-------------------------------------------
+
+  *With all the preparations and precaution builds taken care of, you are now
+  ready to begin the bisection.* [:ref:`... <introbisect_bissbs>`]
+
+The steps in this segment perform and validate the bisection.
+
+[:ref:`back to step-by-step guide <introbisect_bissbs>`].
+
 .. _bisectstart_bisref:
 
 Start the bisection
--------------------
+~~~~~~~~~~~~~~~~~~~
 
   *Start the bisection and tell Git about the versions earlier established as
   'good' and 'bad'.* [:ref:`... <bisectstart_bissbs>`]
@@ -1789,7 +1941,7 @@ for you to test.
 .. _bisectbuild_bisref:
 
 Build a kernel from the bisection point
----------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Build, install, and boot a kernel from the code Git checked out using the
   same commands you used earlier.* [:ref:`... <bisectbuild_bissbs>`]
@@ -1817,7 +1969,7 @@ There are two things worth of note here:
 .. _bisecttest_bisref:
 
 Bisection checkpoint
---------------------
+~~~~~~~~~~~~~~~~~~~~
 
   *Check if the feature that regressed works in the kernel you just built.*
   [:ref:`... <bisecttest_bissbs>`]
@@ -1831,7 +1983,7 @@ will be for nothing.
 .. _bisectlog_bisref:
 
 Put the bisection log away
---------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Store Git's bisection log and the current .config file in a safe place.*
   [:ref:`... <bisectlog_bissbs>`]
@@ -1851,7 +2003,7 @@ ask for it after you report the regression.
 .. _revert_bisref:
 
 Try reverting the culprit
--------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *Try reverting the culprit on top of the latest codebase to see if this fixes
   your regression.* [:ref:`... <revert_bissbs>`]
@@ -1869,14 +2021,20 @@ succeeds, test that kernel version instead.
 
 [:ref:`back to step-by-step guide <revert_bissbs>`]
 
+Cleanup steps during and after following this guide
+---------------------------------------------------
 
-Supplementary tasks: cleanup during and after the bisection
------------------------------------------------------------
+  *During and after following this guide you might want or need to remove some
+  of the kernels you installed.* [:ref:`... <introclosure_bissbs>`]
+
+The steps in this section describe clean-up procedures.
+
+[:ref:`back to step-by-step guide <introclosure_bissbs>`].
 
 .. _makeroom_bisref:
 
 Cleaning up during the bisection
---------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
   *To remove one of the kernels you installed, look up its 'kernelrelease'
   identifier.* [:ref:`... <makeroom_bissbs>`]
@@ -1911,13 +2069,13 @@ Now remove the boot entry for the kernel from your bootloader's configuration;
 the steps to do that vary quite a bit between Linux distributions.
 
 Note, be careful with wildcards like '*' when deleting files or directories
-for kernels manually: you might accidentally remove files of a 6.0.11 kernel
+for kernels manually: you might accidentally remove files of a 6.0.13 kernel
 when all you want is to remove 6.0 or 6.0.1.
 
 [:ref:`back to step-by-step guide <makeroom_bissbs>`]
 
 Cleaning up after the bisection
--------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. _finishingtouch_bisref:
 
@@ -1932,26 +2090,105 @@ build artifacts and the Linux sources, but will leave the Git repository
 (~/linux/.git/) behind -- a simple ``git reset --hard`` thus will bring the
 sources back.
 
-Removing the repository as well would likely be unwise at this point: there is a
-decent chance developers will ask you to build another kernel to perform
-additional tests. This is often required to debug an issue or check proposed
-fixes. Before doing so you want to run the ``git fetch mainline`` command again
-followed by ``git checkout mainline/master`` to bring your clone up to date and
-checkout the latest codebase. Then apply the patch using ``git apply
-<filename>`` or ``git am <filename>`` and build yet another kernel using the
-familiar commands.
+Removing the repository as well would likely be unwise at this point: there
+is a decent chance developers will ask you to build another kernel to
+perform additional tests -- like testing a debug patch or a proposed fix.
+Details on how to perform those can be found in the section :ref:`Optional
+tasks: test reverts, patches, or later versions <introoptional_bissbs>`.
 
 Additional tests are also the reason why you want to keep the
 ~/kernel-config-working file around for a few weeks.
 
 [:ref:`back to step-by-step guide <finishingtouch_bissbs>`]
 
+.. _introoptional_bisref:
 
-Additional reading material
-===========================
+Test reverts, patches, or later versions
+----------------------------------------
+
+  *While or after reporting a bug, you might want or potentially will be asked
+  to test reverts, patches, proposed fixes, or other versions.*
+  [:ref:`... <introoptional_bissbs>`]
+
+All the commands used in this section should be pretty straight forward, so
+there is not much to add except one thing: when setting a kernel tag as
+instructed, ensure it is not much longer than the one used in the example, as
+problems will arise if the kernelrelease identifier exceeds 63 characters.
+
+[:ref:`back to step-by-step guide <introoptional_bissbs>`].
+
+
+Additional information
+======================
+
+.. _buildhost_bis:
+
+Build kernels on a different machine
+------------------------------------
+
+To compile kernels on another system, slightly alter the step-by-step guide's
+instructions:
+
+* Start following the guide on the machine where you want to install and test
+  the kernels later.
+
+* After executing ':ref:`Boot into the working kernel and briefly use the
+  apparently broken feature <bootworking_bissbs>`', save the list of loaded
+  modules to a file using ``lsmod > ~/test-machine-lsmod``. Then locate the
+  build configuration for the running kernel (see ':ref:`Start defining the
+  build configuration for your kernel <oldconfig_bisref>`' for hints on where
+  to find it) and store it as '~/test-machine-config-working'. Transfer both
+  files to the home directory of your build host.
+
+* Continue the guide on the build host (e.g. with ':ref:`Ensure to have enough
+  free space for building [...] <diskspace_bissbs>`').
+
+* When you reach ':ref:`Start preparing a kernel build configuration[...]
+  <oldconfig_bissbs>`': before running ``make olddefconfig`` for the first time,
+  execute the following command to base your configuration on the one from the
+  test machine's 'working' kernel::
+
+    cp ~/test-machine-config-working ~/linux/.config
+
+* During the next step to ':ref:`disable any apparently superfluous kernel
+  modules <localmodconfig_bissbs>`' use the following command instead::
 
-Further sources
----------------
+    yes '' | make localmodconfig LSMOD=~/lsmod_foo-machine localmodconfig
+
+* Continue the guide, but ignore the instructions outlining how to compile,
+  install, and reboot into a kernel every time they come up. Instead build
+  like this::
+
+    cp ~/kernel-config-working .config
+    make olddefconfig &&
+    make -j $(nproc --all) targz-pkg
+
+  This will generate a gzipped tar file whose name is printed in the last
+  line shown; for example, a kernel with the kernelrelease identifier
+  '6.0.0-rc1-local-g928a87efa423' built for x86 machines usually will
+  be stored as '~/linux/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz'.
+
+  Copy that file to your test machine's home directory.
+
+* Switch to the test machine to check if you have enough space to hold another
+  kernel. Then extract the file you transferred::
+
+    sudo tar -xvzf ~/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz -C /
+
+  Afterwards :ref:`generate the initramfs and add the kernel to your boot
+  loader's configuration <install_bisref>`; on some distributions the following
+  command will take care of both these tasks::
+
+    sudo /sbin/installkernel 6.0.0-rc1-local-g928a87efa423 /boot/vmlinuz-6.0.0-rc1-local-g928a87efa423
+
+  Now reboot and ensure you started the intended kernel.
+
+This approach even works when building for another architecture: just install
+cross-compilers and add the appropriate parameters to every invocation of make
+(e.g. ``make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- [...]``).
+
+Additional reading material
+---------------------------
 
 * The `man page for 'git bisect' <https://git-scm.com/docs/git-bisect>`_ and
   `fighting regressions with 'git bisect' <https://git-scm.com/docs/git-bisect-lk2009.html>`_
index ed73c612174d4c99d3329cc1443b553537e049db..bcc370c876be9538c5020c6a14e8584d9090ebdf 100644 (file)
@@ -671,7 +671,7 @@ configuration, worker pools and how workqueues map to the pools: ::
   events_unbound           unbound  9  9 10 10  8
   events_freezable         percpu   0  2  4  6
   events_power_efficient   percpu   0  2  4  6
-  events_freezable_power_  percpu   0  2  4  6
+  events_freezable_pwr_ef  percpu   0  2  4  6
   rcu_gp                   percpu   0  2  4  6
   rcu_par_gp               percpu   0  2  4  6
   slub_flushwq             percpu   0  2  4  6
@@ -694,7 +694,7 @@ Use tools/workqueue/wq_monitor.py to monitor workqueue operations: ::
   events_unbound              38306     0      0.1       -       7       -       -
   events_freezable                0     0      0.0       0       0       -       -
   events_power_efficient      29598     0      0.2       0       0       -       -
-  events_freezable_power_        10     0      0.0       0       0       -       -
+  events_freezable_pwr_ef        10     0      0.0       0       0       -       -
   sock_diag_events                0     0      0.0       0       0       -       -
 
                               total  infl  CPUtime  CPUhog CMW/RPR  mayday rescued
@@ -704,7 +704,7 @@ Use tools/workqueue/wq_monitor.py to monitor workqueue operations: ::
   events_unbound              38322     0      0.1       -       7       -       -
   events_freezable                0     0      0.0       0       0       -       -
   events_power_efficient      29603     0      0.2       0       0       -       -
-  events_freezable_power_        10     0      0.0       0       0       -       -
+  events_freezable_pwr_ef        10     0      0.0       0       0       -       -
   sock_diag_events                0     0      0.0       0       0       -       -
 
   ...
index 1812ef31d5f1e941d4ae0e5a53e06f278cd55aca..3c36cd0510de8364fd3bb034fd2e9c8e32ed5b85 100644 (file)
@@ -68,14 +68,10 @@ properties:
                   pattern: cs16$
               - items:
                   pattern: c32$
-              - items:
-                  pattern: c32d-wl$
               - items:
                   pattern: cs32$
               - items:
                   pattern: c64$
-              - items:
-                  pattern: c64d-wl$
               - items:
                   pattern: cs64$
               - items:
@@ -136,6 +132,7 @@ properties:
               - renesas,r1ex24128
               - samsung,s524ad0xd1
           - const: atmel,24c128
+      - pattern: '^atmel,24c(32|64)d-wl$' # Actual vendor is st
 
   label:
     description: Descriptive name of the EEPROM.
index c13c10c8d65da26cfc7faa0517f28332a2c9d8ae..eed0df9d3a2322d9818709588ca4c335f5f689d5 100644 (file)
@@ -42,7 +42,7 @@ allOf:
       properties:
         compatible:
           contains:
-            const: maxim,max30100
+            const: maxim,max30102
     then:
       properties:
         maxim,green-led-current-microamp: false
index d476de82e5c3f487b0275d1f2d8d8b5a79a6a116..4d5a957fa232eb55d0bd71ea887eefec35b60063 100644 (file)
@@ -120,7 +120,9 @@ additionalProperties:
         slew-rate: true
         gpio-hog: true
         gpios: true
+        input: true
         input-enable: true
+        output-enable: true
         output-high: true
         output-low: true
         line-name: true
index 0b87c266760c6ed4326bc3ee458c77987745bae1..79798c7474768a0d167f6fef8f59ba144bba01a2 100644 (file)
@@ -171,6 +171,7 @@ allOf:
           unevaluatedProperties: false
 
         pcie-phy:
+          type: object
           description:
             Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt
 
index 41a62fd2ae1ffb4f2afaa58d204797a2b15e91ec..c1fa379f5f3ea1388ed9e54ea8fef66d4645d673 100644 (file)
@@ -20,6 +20,11 @@ Optional properties:
   a GPIO spec for the external headphone detect pin. If jd-mode = 0,
   we will get the JD status by getting the value of hp-detect-gpios.
 
+- cbj-sleeve-gpios:
+  a GPIO spec to control the external combo jack circuit to tie the sleeve/ring2
+  contacts to the ground or floating. It could avoid some electric noise from the
+  active speaker jacks.
+
 - realtek,in2-differential
   Boolean. Indicate MIC2 input are differential, rather than single-ended.
 
@@ -68,6 +73,7 @@ codec: rt5650@1a {
        compatible = "realtek,rt5650";
        reg = <0x1a>;
        hp-detect-gpios = <&gpio 19 0>;
+       cbj-sleeve-gpios = <&gpio 20 0>;
        interrupt-parent = <&gpio>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
        realtek,dmic-en = "true";
index 5c4fa9f5d1cdb7a1691c95d09180be804b2f9e55..c9137710633a37d6c88c46191dbfc7e4fc4d32c6 100644 (file)
@@ -16,7 +16,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
 Architecture   Level of support  Constraints
 =============  ================  ==============================================
 ``arm64``      Maintained        Little Endian only.
-``loongarch``  Maintained        -
+``loongarch``  Maintained        \-
 ``um``         Maintained        ``x86_64`` only.
 ``x86``        Maintained        ``x86_64`` only.
 =============  ================  ==============================================
index f8786be15183c15879a188f61fa36bceda99c6e9..7fe8ef9718d8e357567671295a3cc4dc1c97751a 100644 (file)
@@ -129,11 +129,8 @@ adaptive-tick CPUs:  At least one non-adaptive-tick CPU must remain
 online to handle timekeeping tasks in order to ensure that system
 calls like gettimeofday() returns accurate values on adaptive-tick CPUs.
 (This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running
-user processes to observe slight drifts in clock rate.)  Therefore, the
-boot CPU is prohibited from entering adaptive-ticks mode.  Specifying a
-"nohz_full=" mask that includes the boot CPU will result in a boot-time
-error message, and the boot CPU will be removed from the mask.  Note that
-this means that your system must have at least two CPUs in order for
+user processes to observe slight drifts in clock rate.) Note that this
+means that your system must have at least two CPUs in order for
 CONFIG_NO_HZ_FULL=y to do anything for you.
 
 Finally, adaptive-ticks CPUs must have their RCU callbacks offloaded.
index 7fac6f75d0782062f3f11c342068e9f13e90f2ad..fe0ff5a127f3f9255fe2606c15beb9380522cc4c 100644 (file)
@@ -7,12 +7,13 @@
 
  司延腾 Yanteng Si <siyanteng@loongson.cn>
  周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+ 陈兴友 Xingyou Chen <rockrush@rockwork.org>
 
 .. _cn_workqueue.rst:
 
-=========================
¹¶å\8f\91管ç\90\86ç\9a\84å·¥ä½\9cé\98\9få\88\97 (cmwq)
-=========================
+========
·¥ä½\9cé\98\9få\88\97
+========
 
 :日期: September, 2010
 :作者: Tejun Heo <tj@kernel.org>
@@ -22,7 +23,7 @@
 简介
 ====
 
-在很多情况下,需要一个异步进程的执行环境,工作队列(wq)API是这种情况下
+在很多情况下,需要一个异步的程序执行环境,工作队列(wq)API是这种情况下
 最常用的机制。
 
 当需要这样一个异步执行上下文时,一个描述将要执行的函数的工作项(work,
@@ -34,8 +35,8 @@
 队列时,工作者又开始执行。
 
 
-为什么要cmwq?
-=============
+为什么要有并发管理工作队列?
+===========================
 
 在最初的wq实现中,多线程(MT)wq在每个CPU上有一个工作者线程,而单线程
 (ST)wq在全系统有一个工作者线程。一个MT wq需要保持与CPU数量相同的工
 向该函数的工作项,并在工作队列中排队等待该工作项。(就是挂到workqueue
 队列里面去)
 
-特定目的线程,称为工作线程(工作者),一个接一个地执行队列中的功能。
-如果没有工作项排队,工作者线程就会闲置。这些工作者线程被管理在所谓
-的工作者池中。
+工作项可以在线程或BH(软中断)上下文中执行。
+
+对于由线程执行的工作队列,被称为(内核)工作者([k]worker)的特殊
+线程会依次执行其中的函数。如果没有工作项排队,工作者线程就会闲置。
+这些工作者线程被管理在所谓的工作者池中。
 
 cmwq设计区分了面向用户的工作队列,子系统和驱动程序在上面排队工作,
 以及管理工作者池和处理排队工作项的后端机制。
@@ -84,6 +87,10 @@ cmwq设计区分了面向用户的工作队列,子系统和驱动程序在上
 优先级的工作项,还有一些额外的工作者池,用于服务未绑定工作队列的工
 作项目——这些后备池的数量是动态的。
 
+BH工作队列使用相同的结构。然而,由于同一时间只可能有一个执行上下文,
+不需要担心并发问题。每个CPU上的BH工作者池只包含一个用于表示BH执行
+上下文的虚拟工作者。BH工作队列可以被看作软中断的便捷接口。
+
 当他们认为合适的时候,子系统和驱动程序可以通过特殊的
 ``workqueue API`` 函数创建和排队工作项。他们可以通过在工作队列上
 设置标志来影响工作项执行方式的某些方面,他们把工作项放在那里。这些
@@ -95,9 +102,9 @@ cmwq设计区分了面向用户的工作队列,子系统和驱动程序在上
 否则一个绑定的工作队列的工作项将被排在与发起线程运行的CPU相关的普
 通或高级工作工作者池的工作项列表中。
 
-对于任何工作者池的实施,管理并发水平(有多少执行上下文处于活动状
-态)是一个重要问题。最低水平是为了节省资源,而饱和水平是指系统被
-充分使用。
+对于任何线程池的实施,管理并发水平(有多少执行上下文处于活动状
+态)是一个重要问题。cmwq试图将并发保持在一个尽可能低且充足的
+水平。最低水平是为了节省资源,而充足是为了使系统能被充分使用。
 
 每个与实际CPU绑定的worker-pool通过钩住调度器来实现并发管理。每当
 一个活动的工作者被唤醒或睡眠时,工作者池就会得到通知,并跟踪当前可
@@ -140,6 +147,17 @@ workqueue将自动创建与属性相匹配的后备工作者池。调节并发
 ``flags``
 ---------
 
+``WQ_BH``
+  BH工作队列可以被看作软中断的便捷接口。它总是每个CPU一份,
+  其中的各个工作项也会按在队列中的顺序,被所属CPU在软中断
+  上下文中执行。
+
+  BH工作队列的 ``max_active`` 值必须为0,且只能单独或和
+  ``WQ_HIGHPRI`` 标志组合使用。
+
+  BH工作项不可以睡眠。像延迟排队、冲洗、取消等所有其他特性
+  都是支持的。
+
 ``WQ_UNBOUND``
   排队到非绑定wq的工作项由特殊的工作者池提供服务,这些工作者不
   绑定在任何特定的CPU上。这使得wq表现得像一个简单的执行环境提
@@ -184,25 +202,21 @@ workqueue将自动创建与属性相匹配的后备工作者池。调节并发
 --------------
 
 ``@max_active`` 决定了每个CPU可以分配给wq的工作项的最大执行上
-下文数量。例如,如果 ``@max_active为16`` ,每个CPU最多可以同
-时执行16个wq的工作项。
+下文数量。例如,如果 ``@max_active`` 为16 ,每个CPU最多可以同
+时执行16个wq的工作项。它总是每CPU属性,即便对于未绑定 wq。
 
-目前,对于一个绑定的wq, ``@max_active`` 的最大限制是512,当指
-定为0时使用的默认值是256。对于非绑定的wq,其限制是512和
-4 * ``num_possible_cpus()`` 中的较高值。这些值被选得足够高,所
-以它们不是限制性因素,同时会在失控情况下提供保护。
+``@max_active`` 的最大限制是512,当指定为0时使用的默认值是256。
+这些值被选得足够高,所以它们不是限制性因素,同时会在失控情况下提供
+保护。
 
 一个wq的活动工作项的数量通常由wq的用户来调节,更具体地说,是由用
 户在同一时间可以排列多少个工作项来调节。除非有特定的需求来控制活动
 工作项的数量,否则建议指定 为"0"。
 
-一些用户依赖于ST wq的严格执行顺序。 ``@max_active`` 为1和 ``WQ_UNBOUND``
-的组合用来实现这种行为。这种wq上的工作项目总是被排到未绑定的工作池
-中,并且在任何时候都只有一个工作项目处于活动状态,从而实现与ST wq相
-同的排序属性。
-
-在目前的实现中,上述配置只保证了特定NUMA节点内的ST行为。相反,
-``alloc_ordered_workqueue()`` 应该被用来实现全系统的ST行为。
+一些用户依赖于任意时刻最多只有一个工作项被执行,且各工作项被按队列中
+顺序处理带来的严格执行顺序。``@max_active`` 为1和 ``WQ_UNBOUND``
+的组合曾被用来实现这种行为,现在不用了。请使用
+``alloc_ordered_workqueue()`` 。
 
 
 执行场景示例
@@ -285,7 +299,7 @@ And with cmwq with ``@max_active`` >= 3, ::
 * 除非有特殊需要,建议使用0作为@max_active。在大多数使用情
   况下,并发水平通常保持在默认限制之下。
 
-* ä¸\80个wqä½\9c为å\89\8dè¿\9bè¿\9b度ä¿\9dè¯\81ï¼\88WQ_MEM_RECLAIM,冲洗(flush)和工
+* ä¸\80个wqä½\9c为å\89\8dè¿\9bè¿\9b度ä¿\9dè¯\81ï¼\8c``WQ_MEM_RECLAIM`` ,冲洗(flush)和工
   作项属性的域。不涉及内存回收的工作项,不需要作为工作项组的一
   部分被刷新,也不需要任何特殊属性,可以使用系统中的一个wq。使
   用专用wq和系统wq在执行特性上没有区别。
@@ -294,6 +308,337 @@ And with cmwq with ``@max_active`` >= 3, ::
   益的,因为wq操作和工作项执行中的定位水平提高了。
 
 
+亲和性作用域
+============
+
+一个非绑定工作队列根据其亲和性作用域来对CPU进行分组以提高缓存
+局部性。比如如果一个工作队列使用默认的“cache”亲和性作用域,
+它将根据最后一级缓存的边界来分组处理器。这个工作队列上的工作项
+将被分配给一个与发起CPU共用最后级缓存的处理器上的工作者。根据
+``affinity_strict`` 的设置,工作者在启动后可能被允许移出
+所在作用域,也可能不被允许。
+
+工作队列目前支持以下亲和性作用域。
+
+``default``
+  使用模块参数 ``workqueue.default_affinity_scope`` 指定
+  的作用域,该参数总是会被设为以下作用域中的一个。
+
+``cpu``
+  CPU不被分组。一个CPU上发起的工作项会被同一CPU上的工作者执行。
+  这使非绑定工作队列表现得像是不含并发管理的每CPU工作队列。
+
+``smt``
+  CPU被按SMT边界分组。这通常意味着每个物理CPU核上的各逻辑CPU会
+  被分进同一组。
+
+``cache``
+  CPU被按缓存边界分组。采用哪个缓存边界由架构代码决定。很多情况
+  下会使用L3。这是默认的亲和性作用域。
+
+``numa``
+  CPU被按NUMA边界分组。
+
+``system``
+  所有CPU被放在同一组。工作队列不尝试在临近发起CPU的CPU上运行
+  工作项。
+
+默认的亲和性作用域可以被模块参数 ``workqueue.default_affinity_scope``
+修改,特定工作队列的亲和性作用域可以通过 ``apply_workqueue_attrs()``
+被更改。
+
+如果设置了 ``WQ_SYSFS`` ,工作队列会在它的 ``/sys/devices/virtual/workqueue/WQ_NAME/``
+目录中有以下亲和性作用域相关的接口文件。
+
+``affinity_scope``
+  读操作以查看当前的亲和性作用域。写操作用于更改设置。
+
+  当前作用域是默认值时,当前生效的作用域也可以被从这个文件中
+  读到(小括号内),例如 ``default (cache)`` 。
+
+``affinity_strict``
+  默认值0表明亲和性作用域不是严格的。当一个工作项开始执行时,
+  工作队列尽量尝试使工作者处于亲和性作用域内,称为遣返。启动后,
+  调度器可以自由地将工作者调度到系统中任意它认为合适的地方去。
+  这使得在保留使用其他CPU(如果必需且有可用)能力的同时,
+  还能从作用域局部性上获益。
+
+  如果设置为1,作用域内的所有工作者将被保证总是处于作用域内。
+  这在跨亲和性作用域会导致如功耗、负载隔离等方面的潜在影响时
+  会有用。严格的NUMA作用域也可用于和旧版内核中工作队列的行为
+  保持一致。
+
+
+亲和性作用域与性能
+==================
+
+如果非绑定工作队列的行为对绝大多数使用场景来说都是最优的,
+不需要更多调节,就完美了。很不幸,在当前内核中,重度使用
+工作队列时,需要在局部性和利用率间显式地作一个明显的权衡。
+
+更高的局部性带来更高效率,也就是相同数量的CPU周期内可以做
+更多工作。然而,如果发起者没能将工作项充分地分散在亲和性
+作用域间,更高的局部性也可能带来更低的整体系统利用率。以下
+dm-crypt 的性能测试清楚地阐明了这一取舍。
+
+测试运行在一个12核24线程、4个L3缓存的处理器(AMD Ryzen
+9 3900x)上。为保持一致性,关闭CPU超频。 ``/dev/dm-0``
+是NVME SSD(三星 990 PRO)上创建,用 ``cryptsetup``
+以默认配置打开的一个 dm-crypt 设备。
+
+
+场景 1: 机器上遍布着有充足的发起者和工作量
+------------------------------------------
+
+使用命令:::
+
+  $ fio --filename=/dev/dm-0 --direct=1 --rw=randrw --bs=32k --ioengine=libaio \
+    --iodepth=64 --runtime=60 --numjobs=24 --time_based --group_reporting \
+    --name=iops-test-job --verify=sha512
+
+这里有24个发起者,每个同时发起64个IO。 ``--verify=sha512``
+使得 ``fio`` 每次生成和读回内容受发起者和 ``kcryptd``
+间的执行局部性影响。下面是基于不同 ``kcryptd`` 的亲和性
+作用域设置,各经过五次测试得到的读取带宽和CPU利用率数据。
+
+.. list-table::
+   :widths: 16 20 20
+   :header-rows: 1
+
+   * - 亲和性
+     - 带宽 (MiBps)
+     - CPU利用率(%)
+
+   * - system
+     - 1159.40 ±1.34
+     - 99.31 ±0.02
+
+   * - cache
+     - 1166.40 ±0.89
+     - 99.34 ±0.01
+
+   * - cache (strict)
+     - 1166.00 ±0.71
+     - 99.35 ±0.01
+
+在系统中分布着足够多发起者的情况下,不论严格与否,“cache”
+没有表现得更差。三种配置均使整个机器达到饱和,但由于提高了
+局部性,缓存相关的两种有0.6%的(带宽)提升。
+
+
+场景 2: 更少发起者,足以达到饱和的工作量
+----------------------------------------
+
+使用命令:::
+
+  $ fio --filename=/dev/dm-0 --direct=1 --rw=randrw --bs=32k \
+    --ioengine=libaio --iodepth=64 --runtime=60 --numjobs=8 \
+    --time_based --group_reporting --name=iops-test-job --verify=sha512
+
+与上一个场景唯一的区别是 ``--numjobs=8``。 发起者数量
+减少为三分之一,但仍然有足以使系统达到饱和的工作总量。
+
+.. list-table::
+   :widths: 16 20 20
+   :header-rows: 1
+
+   * - 亲和性
+     - 带宽 (MiBps)
+     - CPU利用率(%)
+
+   * - system
+     - 1155.40 ±0.89
+     - 97.41 ±0.05
+
+   * - cache
+     - 1154.40 ±1.14
+     - 96.15 ±0.09
+
+   * - cache (strict)
+     - 1112.00 ±4.64
+     - 93.26 ±0.35
+
+这里有超过使系统达到饱和所需的工作量。“system”和“cache”
+都接近但并未使机器完全饱和。“cache”消耗更少的CPU但更高的
+效率使其得到和“system”相同的带宽。
+
+八个发起者盘桓在四个L3缓存作用域间仍然允许“cache (strict)”
+几乎使机器饱和,但缺少对工作的保持(不移到空闲处理器上)
+开始带来3.7%的带宽损失。
+
+
+场景 3: 更少发起者,不充足的工作量
+----------------------------------
+
+使用命令:::
+
+  $ fio --filename=/dev/dm-0 --direct=1 --rw=randrw --bs=32k \
+    --ioengine=libaio --iodepth=64 --runtime=60 --numjobs=4 \
+    --time_based --group_reporting --name=iops-test-job --verify=sha512
+
+再次,唯一的区别是 ``--numjobs=4``。由于发起者减少到四个,
+现在没有足以使系统饱和的工作量,带宽变得依赖于完成时延。
+
+.. list-table::
+   :widths: 16 20 20
+   :header-rows: 1
+
+   * - 亲和性
+     - 带宽 (MiBps)
+     - CPU利用率(%)
+
+   * - system
+     - 993.60 ±1.82
+     - 75.49 ±0.06
+
+   * - cache
+     - 973.40 ±1.52
+     - 74.90 ±0.07
+
+   * - cache (strict)
+     - 828.20 ±4.49
+     - 66.84 ±0.29
+
+现在,局部性和利用率间的权衡更清晰了。“cache”展示出相比
+“system”2%的带宽损失,而“cache (strict)”跌到20%。
+
+
+结论和建议
+----------
+
+在以上试验中,虽然一致并且也明显,但“cache”亲和性作用域
+相比“system”的性能优势并不大。然而,这影响是依赖于作用域
+间距离的,在更复杂的处理器拓扑下可能有更明显的影响。
+
+虽然这些情形下缺少工作保持是有坏处的,但比“cache (strict)”
+好多了,而且最大化工作队列利用率的需求也并不常见。因此,
+“cache”是非绑定池的默认亲和性作用域。
+
+* 由于不存在一个适用于大多数场景的选择,对于可能需要消耗
+  大量CPU的工作队列,建议通过 ``apply_workqueue_attrs()``
+  进行(专门)配置,并考虑是否启用 ``WQ_SYSFS``。
+
+* 设置了严格“cpu”亲和性作用域的非绑定工作队列,它的行为与
+  ``WQ_CPU_INTENSIVE`` 每CPU工作队列一样。后者没有真正
+  优势,而前者提供了大幅度的灵活性。
+
+* 亲和性作用域是从Linux v6.5起引入的。为了模拟旧版行为,
+  可以使用严格的“numa”亲和性作用域。
+
+* 不严格的亲和性作用域中,缺少工作保持大概缘于调度器。内核
+  为什么没能维护好大多数场景下的工作保持,把事情作对,还没有
+  理论上的解释。因此,未来调度器的改进可能会使我们不再需要
+  这些调节项。
+
+
+检查配置
+========
+
+使用 tools/workqueue/wq_dump.py(drgn脚本) 来检查未
+绑定CPU的亲和性配置,工作者池,以及工作队列如何映射到池上: ::
+
+  $ tools/workqueue/wq_dump.py
+  Affinity Scopes
+  ===============
+  wq_unbound_cpumask=0000000f
+
+  CPU
+    nr_pods  4
+    pod_cpus [0]=00000001 [1]=00000002 [2]=00000004 [3]=00000008
+    pod_node [0]=0 [1]=0 [2]=1 [3]=1
+    cpu_pod  [0]=0 [1]=1 [2]=2 [3]=3
+
+  SMT
+    nr_pods  4
+    pod_cpus [0]=00000001 [1]=00000002 [2]=00000004 [3]=00000008
+    pod_node [0]=0 [1]=0 [2]=1 [3]=1
+    cpu_pod  [0]=0 [1]=1 [2]=2 [3]=3
+
+  CACHE (default)
+    nr_pods  2
+    pod_cpus [0]=00000003 [1]=0000000c
+    pod_node [0]=0 [1]=1
+    cpu_pod  [0]=0 [1]=0 [2]=1 [3]=1
+
+  NUMA
+    nr_pods  2
+    pod_cpus [0]=00000003 [1]=0000000c
+    pod_node [0]=0 [1]=1
+    cpu_pod  [0]=0 [1]=0 [2]=1 [3]=1
+
+  SYSTEM
+    nr_pods  1
+    pod_cpus [0]=0000000f
+    pod_node [0]=-1
+    cpu_pod  [0]=0 [1]=0 [2]=0 [3]=0
+
+  Worker Pools
+  ============
+  pool[00] ref= 1 nice=  0 idle/workers=  4/  4 cpu=  0
+  pool[01] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  0
+  pool[02] ref= 1 nice=  0 idle/workers=  4/  4 cpu=  1
+  pool[03] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  1
+  pool[04] ref= 1 nice=  0 idle/workers=  4/  4 cpu=  2
+  pool[05] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  2
+  pool[06] ref= 1 nice=  0 idle/workers=  3/  3 cpu=  3
+  pool[07] ref= 1 nice=-20 idle/workers=  2/  2 cpu=  3
+  pool[08] ref=42 nice=  0 idle/workers=  6/  6 cpus=0000000f
+  pool[09] ref=28 nice=  0 idle/workers=  3/  3 cpus=00000003
+  pool[10] ref=28 nice=  0 idle/workers= 17/ 17 cpus=0000000c
+  pool[11] ref= 1 nice=-20 idle/workers=  1/  1 cpus=0000000f
+  pool[12] ref= 2 nice=-20 idle/workers=  1/  1 cpus=00000003
+  pool[13] ref= 2 nice=-20 idle/workers=  1/  1 cpus=0000000c
+
+  Workqueue CPU -> pool
+  =====================
+  [    workqueue \ CPU              0  1  2  3 dfl]
+  events                   percpu   0  2  4  6
+  events_highpri           percpu   1  3  5  7
+  events_long              percpu   0  2  4  6
+  events_unbound           unbound  9  9 10 10  8
+  events_freezable         percpu   0  2  4  6
+  events_power_efficient   percpu   0  2  4  6
+  events_freezable_power_  percpu   0  2  4  6
+  rcu_gp                   percpu   0  2  4  6
+  rcu_par_gp               percpu   0  2  4  6
+  slub_flushwq             percpu   0  2  4  6
+  netns                    ordered  8  8  8  8  8
+  ...
+
+参见命令的帮助消息以获取更多信息。
+
+
+监视
+====
+
+使用 tools/workqueue/wq_monitor.py 来监视工作队列的运行: ::
+
+  $ tools/workqueue/wq_monitor.py events
+                              total  infl  CPUtime  CPUhog CMW/RPR  mayday rescued
+  events                      18545     0      6.1       0       5       -       -
+  events_highpri                  8     0      0.0       0       0       -       -
+  events_long                     3     0      0.0       0       0       -       -
+  events_unbound              38306     0      0.1       -       7       -       -
+  events_freezable                0     0      0.0       0       0       -       -
+  events_power_efficient      29598     0      0.2       0       0       -       -
+  events_freezable_power_        10     0      0.0       0       0       -       -
+  sock_diag_events                0     0      0.0       0       0       -       -
+
+                              total  infl  CPUtime  CPUhog CMW/RPR  mayday rescued
+  events                      18548     0      6.1       0       5       -       -
+  events_highpri                  8     0      0.0       0       0       -       -
+  events_long                     3     0      0.0       0       0       -       -
+  events_unbound              38322     0      0.1       -       7       -       -
+  events_freezable                0     0      0.0       0       0       -       -
+  events_power_efficient      29603     0      0.2       0       0       -       -
+  events_freezable_power_        10     0      0.0       0       0       -       -
+  sock_diag_events                0     0      0.0       0       0       -       -
+
+  ...
+
+参见命令的帮助消息以获取更多信息。
+
+
 调试
 ====
 
@@ -330,7 +675,6 @@ And with cmwq with ``@max_active`` >= 3, ::
 
 工作队列保证,如果在工作项排队后满足以下条件,则工作项不能重入:
 
-
         1. 工作函数没有被改变。
         2. 没有人将该工作项排到另一个工作队列中。
         3. 该工作项尚未被重新启动。
index ebf03f5f0619a662bfca89f6457ae98375fb660d..ec0284125e8f706cf4a6f6da241493ce8150e5fe 100644 (file)
@@ -553,7 +553,7 @@ F:  Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
 F:     drivers/input/misc/adxl34x.c
 
 ADXL355 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
-M:     Puranjay Mohan <puranjay12@gmail.com>
+M:     Puranjay Mohan <puranjay@kernel.org>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml
@@ -3714,7 +3714,7 @@ F:        drivers/iio/imu/bmi323/
 
 BPF JIT for ARM
 M:     Russell King <linux@armlinux.org.uk>
-M:     Puranjay Mohan <puranjay12@gmail.com>
+M:     Puranjay Mohan <puranjay@kernel.org>
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/arm/net/
@@ -3764,6 +3764,8 @@ X:        arch/riscv/net/bpf_jit_comp64.c
 
 BPF JIT for RISC-V (64-bit)
 M:     Björn Töpel <bjorn@kernel.org>
+R:     Pu Lehui <pulehui@huawei.com>
+R:     Puranjay Mohan <puranjay@kernel.org>
 L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/riscv/net/
@@ -4191,7 +4193,6 @@ S:        Supported
 F:     drivers/scsi/bnx2i/
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Ariel Elior <aelior@marvell.com>
 M:     Sudarsana Kalluru <skalluru@marvell.com>
 M:     Manish Chopra <manishc@marvell.com>
 L:     netdev@vger.kernel.org
@@ -7829,9 +7830,8 @@ W:        http://aeschi.ch.eu.org/efs/
 F:     fs/efs/
 
 EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
-M:     Douglas Miller <dougmill@linux.ibm.com>
 L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/ethernet/ibm/ehea/
 
 ELM327 CAN NETWORK DRIVER
@@ -9576,7 +9576,7 @@ F:        kernel/power/
 
 HID CORE LAYER
 M:     Jiri Kosina <jikos@kernel.org>
-M:     Benjamin Tissoires <benjamin.tissoires@redhat.com>
+M:     Benjamin Tissoires <bentiss@kernel.org>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
@@ -15161,9 +15161,8 @@ F:      drivers/scsi/myrb.*
 F:     drivers/scsi/myrs.*
 
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
-M:     Chris Lee <christopher.lee@cspi.com>
 L:     netdev@vger.kernel.org
-S:     Supported
+S:     Orphan
 W:     https://www.cspi.com/ethernet-products/support/downloads/
 F:     drivers/net/ethernet/myricom/myri10ge/
 
@@ -16799,12 +16798,6 @@ S:     Maintained
 F:     drivers/leds/leds-pca9532.c
 F:     include/linux/leds-pca9532.h
 
-PCA9541 I2C BUS MASTER SELECTOR DRIVER
-M:     Guenter Roeck <linux@roeck-us.net>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     drivers/i2c/muxes/i2c-mux-pca9541.c
-
 PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
 M:     Thomas Petazzoni <thomas.petazzoni@bootlin.com>
 M:     Pali Rohár <pali@kernel.org>
@@ -17873,7 +17866,7 @@ F:      Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
 F:     drivers/media/rc/pwm-ir-tx.c
 
 PWM SUBSYSTEM
-M:     Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+M:     Uwe Kleine-König <ukleinek@kernel.org>
 L:     linux-pwm@vger.kernel.org
 S:     Maintained
 Q:     https://patchwork.ozlabs.org/project/linux-pwm/list/
@@ -17997,7 +17990,6 @@ S:      Supported
 F:     drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Ariel Elior <aelior@marvell.com>
 M:     Manish Chopra <manishc@marvell.com>
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -18007,7 +17999,6 @@ F:      include/linux/qed/
 
 QLOGIC QL4xxx RDMA DRIVER
 M:     Michal Kalderon <mkalderon@marvell.com>
-M:     Ariel Elior <aelior@marvell.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 F:     drivers/infiniband/hw/qedr/
@@ -20177,7 +20168,6 @@ F:      include/linux/platform_data/simplefb.h
 
 SIOX
 M:     Thorsten Scherer <t.scherer@eckelmann.de>
-M:     Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 R:     Pengutronix Kernel Team <kernel@pengutronix.de>
 S:     Supported
 F:     drivers/gpio/gpio-siox.c
@@ -21926,7 +21916,7 @@ F:      include/linux/soc/ti/ti_sci_inta_msi.h
 F:     include/linux/soc/ti/ti_sci_protocol.h
 
 TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER
-M:     Puranjay Mohan <puranjay12@gmail.com>
+M:     Puranjay Mohan <puranjay@kernel.org>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml
@@ -22839,7 +22829,7 @@ F:      drivers/usb/host/ehci*
 
 USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
 M:     Jiri Kosina <jikos@kernel.org>
-M:     Benjamin Tissoires <benjamin.tissoires@redhat.com>
+M:     Benjamin Tissoires <bentiss@kernel.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
@@ -24467,6 +24457,14 @@ T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/har
 F:     Documentation/admin-guide/LSM/Yama.rst
 F:     security/yama/
 
+YAML NETLINK (YNL)
+M:     Donald Hunter <donald.hunter@gmail.com>
+M:     Jakub Kicinski <kuba@kernel.org>
+F:     Documentation/netlink/
+F:     Documentation/userspace-api/netlink/intro-specs.rst
+F:     Documentation/userspace-api/netlink/specs.rst
+F:     tools/net/ynl/
+
 YEALINK PHONE DRIVER
 M:     Henk Vergonet <Henk.Vergonet@gmail.com>
 L:     usbb2k-api-dev@nongnu.org
index 43b10f3d438cf4f3b8b099340f7cc2c1396ee178..40fb2ca6fe4c049115b83851350b4af6904eec42 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 65afb1de48b36e843bd665a91df6b33badfd23d1..30f7930275d8388d6fca8ddcd97fbd56ec007873 100644 (file)
@@ -9,6 +9,14 @@
 #
 source "arch/$(SRCARCH)/Kconfig"
 
+config ARCH_CONFIGURES_CPU_MITIGATIONS
+       bool
+
+if !ARCH_CONFIGURES_CPU_MITIGATIONS
+config CPU_MITIGATIONS
+       def_bool y
+endif
+
 menu "General architecture-dependent options"
 
 config ARCH_HAS_SUBPAGE_FAULTS
index 99d2845f3feb954d495253e938fb4dec73be1720..4092bec198beca44d6c019643db6829293f7320d 100644 (file)
@@ -6,7 +6,6 @@
 config ARC
        def_bool y
        select ARC_TIMERS
-       select ARCH_HAS_CPU_CACHE_ALIASING
        select ARCH_HAS_CACHE_LINE_SIZE
        select ARCH_HAS_DEBUG_VM_PGTABLE
        select ARCH_HAS_DMA_PREP_COHERENT
index 5648748c285f52c46a5fbe8df1d5c8e683cafc88..5a8550124b73ec0ae01461af4623009110b3007e 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# uImage build relies on mkimage being availble on your host for ARC target
+# uImage build relies on mkimage being available on your host for ARC target
 # You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
-# and make sure it's reacable from your PATH
+# and make sure it's reachable from your PATH
 
 OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S
 
index 3434c8131ecd546911bdbfb03d280d9b158e5a86..c0a812674ce9edac177c5ae98889766b5e052ad6 100644 (file)
        /*
         * The DW APB ICTL intc on MB is connected to CPU intc via a
         * DT "invisible" DW APB GPIO block, configured to simply pass thru
-        * interrupts - setup accordinly in platform init (plat-axs10x/ax10x.c)
+        * interrupts - setup accordingly in platform init (plat-axs10x/ax10x.c)
         *
-        * So here we mimic a direct connection betwen them, ignoring the
+        * So here we mimic a direct connection between them, ignoring the
         * ABPG GPIO. Thus set "interrupts = <24>" (DW APB GPIO to core)
         * instead of "interrupts = <12>" (DW APB ICTL to DW APB GPIO)
         *
index 6691f42550778853f2917a2d18347fd4c05f0488..41b980df862b14aa2a97867d05051f0f29434b65 100644 (file)
                };
 
                gmac: ethernet@8000 {
-                       #interrupt-cells = <1>;
                        compatible = "snps,dwmac";
                        reg = <0x8000 0x2000>;
                        interrupts = <10>;
index 90a412026e6433cb3e07d97c64e4aec879ef2c20..0e0e2d337bf8711d63f182b7f5a4a60341822d1b 100644 (file)
        /*
         * Embedded Vision subsystem UIO mappings; only relevant for EV VDK
         *
-        * This node is intentionally put outside of MB above becase
+        * This node is intentionally put outside of MB above because
         * it maps areas outside of MB's 0xez-0xfz.
         */
        uio_ev: uio@d0000000 {
diff --git a/arch/arc/include/asm/cachetype.h b/arch/arc/include/asm/cachetype.h
deleted file mode 100644 (file)
index 05fc7ed..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_ARC_CACHETYPE_H
-#define __ASM_ARC_CACHETYPE_H
-
-#include <linux/types.h>
-
-#define cpu_dcache_is_aliasing()       true
-
-#endif
index 202c78e567045bdc442c62f4a23c5b382a6d5b80..f496dbc4640b2461a7ca7696c21a19dcb6d2d6be 100644 (file)
@@ -12,7 +12,7 @@
 /*
  * DSP-related saved registers - need to be saved only when you are
  * scheduled out.
- * structure fields name must correspond to aux register defenitions for
+ * structure fields name must correspond to aux register definitions for
  * automatic offset calculation in DSP_AUX_SAVE_RESTORE macros
  */
 struct dsp_callee_regs {
index 92c3e9f13252193a1f0d241c272ee1acb6af41b6..00946fe04c9b26802aed8e214337e582476b9f5b 100644 (file)
@@ -7,7 +7,7 @@
  *  Stack switching code can no longer reliably rely on the fact that
  *  if we are NOT in user mode, stack is switched to kernel mode.
  *  e.g. L2 IRQ interrupted a L1 ISR which had not yet completed
- *  it's prologue including stack switching from user mode
+ *  its prologue including stack switching from user mode
  *
  * Vineetg: Aug 28th 2008: Bug #94984
  *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
         * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode)
         * 3. But before it could switch SP from USER to KERNEL stack
         *      a L2 IRQ "Interrupts" L1
-        * Thay way although L2 IRQ happened in Kernel mode, stack is still
+        * That way although L2 IRQ happened in Kernel mode, stack is still
         * not switched.
         * To handle this, we may need to switch stack even if in kernel mode
         * provided SP has values in range of USER mode stack ( < 0x7000_0000 )
 
        GET_CURR_TASK_ON_CPU   r9
 
-       /* With current tsk in r9, get it's kernel mode stack base */
+       /* With current tsk in r9, get its kernel mode stack base */
        GET_TSK_STACK_BASE  r9, r9
 
        /* save U mode SP @ pt_regs->sp */
  * NOTE:
  *
  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
- * for memory load operations. If used in that way interrupts are deffered
+ * for memory load operations. If used in that way interrupts are deferred
  * by hardware and that is not good.
  *-------------------------------------------------------------*/
 .macro EXCEPTION_EPILOGUE
  * NOTE:
  *
  * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg
- * for memory load operations. If used in that way interrupts are deffered
+ * for memory load operations. If used in that way interrupts are deferred
  * by hardware and that is not good.
  *-------------------------------------------------------------*/
 .macro INTERRUPT_EPILOGUE  LVL
index cf1ba376e992c600b0e270056eabf9179cbd96b7..38c35722cebf0312899bf8ac63562550a779dd4e 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef __ASM_ARC_ENTRY_H
 #define __ASM_ARC_ENTRY_H
 
-#include <asm/unistd.h>                /* For NR_syscalls defination */
+#include <asm/unistd.h>                /* For NR_syscalls definition */
 #include <asm/arcregs.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>     /* For VMALLOC_START */
@@ -56,7 +56,7 @@
 .endm
 
 /*-------------------------------------------------------------
- * given a tsk struct, get to the base of it's kernel mode stack
+ * given a tsk struct, get to the base of its kernel mode stack
  * tsk->thread_info is really a PAGE, whose bottom hoists stack
  * which grows upwards towards thread_info
  *------------------------------------------------------------*/
index c574712ad86589eb858c4d6b0c4c3721af3e904d..9cd79263acba824ff4e50ba5d71144bea4307b2f 100644 (file)
@@ -10,7 +10,7 @@
  * ARCv2 can support 240 interrupts in the core interrupts controllers and
  * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
  * configurations of boards.
- * This doesnt affect ARCompact, but we change it to same value
+ * This doesn't affect ARCompact, but we change it to same value
  */
 #define NR_IRQS                512
 
index 0d63e568d64cb524b907d80023d56c43e2bcc499..936a2f21f315ed881ff9a972ac8e68d6d93170e2 100644 (file)
@@ -46,7 +46,7 @@
  * IRQ Control Macros
  *
  * All of them have "memory" clobber (compiler barrier) which is needed to
- * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available)
+ * ensure that LD/ST requiring irq safety (R-M-W when LLSC is not available)
  * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register)
  *
  * Noted at the time of Abilis Timer List corruption
index dda471f5f05bbf06c2949daa503c272206ad0c4b..9963bb1a5733fb690476841f770318c0356056a8 100644 (file)
@@ -165,7 +165,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
  * for retiring-mm. However destroy_context( ) still needs to do that because
  * between mm_release( ) = >deactive_mm( ) and
  * mmput => .. => __mmdrop( ) => destroy_context( )
- * there is a good chance that task gets sched-out/in, making it's ASID valid
+ * there is a good chance that task gets sched-out/in, making its ASID valid
  * again (this teased me for a whole day).
  */
 
index f3eea3f30b2e2998ca9b90ae5232c47bc0837182..8ebec1b21d246e61aa688c152dba9b5e2e564104 100644 (file)
@@ -66,7 +66,7 @@
  * Other rules which cause the divergence from 1:1 mapping
  *
  *  1. Although ARC700 can do exclusive execute/write protection (meaning R
- *     can be tracked independet of X/W unlike some other CPUs), still to
+ *     can be tracked independently of X/W unlike some other CPUs), still to
  *     keep things consistent with other archs:
  *      -Write implies Read:   W => R
  *      -Execute implies Read: X => R
index 00b9318e551e7e31fc2eeff345d6d722f4e3efb6..cf79df0b257053494fcc20ba48c6105828bd4318 100644 (file)
@@ -169,7 +169,7 @@ static inline unsigned long regs_get_register(struct pt_regs *regs,
        return *(unsigned long *)((unsigned long)regs + offset);
 }
 
-extern int syscall_trace_entry(struct pt_regs *);
+extern int syscall_trace_enter(struct pt_regs *);
 extern void syscall_trace_exit(struct pt_regs *);
 
 #endif /* !__ASSEMBLY__ */
index 8b0251464ffd42b848ad61fe0e5a14b493c9389b..719112af0f41ae45ce4687d4af06bd7f0955812f 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __ARC_ASM_SHMPARAM_H
 #define __ARC_ASM_SHMPARAM_H
 
-/* Handle upto 2 cache bins */
+/* Handle up to 2 cache bins */
 #define        SHMLBA  (2 * PAGE_SIZE)
 
 /* Enforce SHMLBA in shmat */
index e0913f52c2cddadf7840282bf43fb430dba7a235..990f834909f088d8c5e57366a5c4d3ad56d800f7 100644 (file)
@@ -77,7 +77,7 @@ static inline const char *arc_platform_smp_cpuinfo(void)
 
 /*
  * ARC700 doesn't support atomic Read-Modify-Write ops.
- * Originally Interrupts had to be disabled around code to gaurantee atomicity.
+ * Originally Interrupts had to be disabled around code to guarantee atomicity.
  * The LLOCK/SCOND insns allow writing interrupt-hassle-free based atomic ops
  * based on retry-if-irq-in-atomic (with hardware assist).
  * However despite these, we provide the IRQ disabling variant
@@ -86,7 +86,7 @@ static inline const char *arc_platform_smp_cpuinfo(void)
  *     support needed.
  *
  * (2) In a SMP setup, the LLOCK/SCOND atomicity across CPUs needs to be
- *     gaurantted by the platform (not something which core handles).
+ *     guaranteed by the platform (not something which core handles).
  *     Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ
  *     disabling for atomicity.
  *
index 4c530cf131f339c5dbe92ecfce6a4f0f57a17903..12daaf3a61eaf613dcbb259643107558092db1c2 100644 (file)
@@ -38,7 +38,7 @@
 struct thread_info {
        unsigned long flags;            /* low level flags */
        unsigned long ksp;              /* kernel mode stack top in __switch_to */
-       int preempt_count;              /* 0 => preemptable, <0 => BUG */
+       int preempt_count;              /* 0 => preemptible, <0 => BUG */
        int cpu;                        /* current CPU */
        unsigned long thr_ptr;          /* TLS ptr */
        struct task_struct *task;       /* main task structure */
index 02109cd48ee1298b8a2d6da2eda5611b0d7d9643..8d1f1ef44ba75078cdd5339dd6dff7cb2825e3c6 100644 (file)
@@ -62,7 +62,7 @@
  * 8051fdc4:   st     r2,[r1,20]       ; Mem op : save result back to mem
  *
  * Joern suggested a better "C" algorithm which is great since
- * (1) It is portable to any architecure
+ * (1) It is portable to any architecture
  * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
  */
 
index 2e49c81c8086b11de360c0e37421b2f9091a9c85..e238b5fd3c8cffe8da4b6e42255663b5e0aeb52a 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
  */
 
-#include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */
+#include <linux/linkage.h>   /* ARC_{ENTRY,EXIT} */
 #include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,TRAP...} */
 #include <asm/errno.h>
 #include <asm/arcregs.h>
@@ -31,7 +31,7 @@ VECTOR        res_service             ; Reset Vector
 VECTOR mem_service             ; Mem exception
 VECTOR instr_service           ; Instrn Error
 VECTOR EV_MachineCheck         ; Fatal Machine check
-VECTOR EV_TLBMissI             ; Intruction TLB miss
+VECTOR EV_TLBMissI             ; Instruction TLB miss
 VECTOR EV_TLBMissD             ; Data TLB miss
 VECTOR EV_TLBProtV             ; Protection Violation
 VECTOR EV_PrivilegeV           ; Privilege Violation
@@ -76,11 +76,11 @@ ENTRY(handle_interrupt)
        # query in hard ISR path would return false (since .IE is set) which would
        # trips genirq interrupt handling asserts.
        #
-       # So do a "soft" disable of interrutps here.
+       # So do a "soft" disable of interrupts here.
        #
        # Note this disable is only for consistent book-keeping as further interrupts
        # will be disabled anyways even w/o this. Hardware tracks active interrupts
-       # seperately in AUX_IRQ_ACT.active and will not take new interrupts
+       # separately in AUX_IRQ_ACT.active and will not take new interrupts
        # unless this one returns (or higher prio becomes pending in 2-prio scheme)
 
        IRQ_DISABLE
index 089f6680518f82908664a6f2883ab6d3e1b2c5ca..3c7e74aba6794e8c1be2c99a7aa3dbe0393e1a1a 100644 (file)
@@ -95,7 +95,7 @@ ENTRY(EV_MachineCheck)
        lr  r0, [efa]
        mov r1, sp
 
-       ; MC excpetions disable MMU
+       ; MC exceptions disable MMU
        ARC_MMU_REENABLE r3
 
        lsr     r3, r10, 8
@@ -209,7 +209,7 @@ trap_with_param:
 
 ; ---------------------------------------------
 ; syscall TRAP
-; ABI: (r0-r7) upto 8 args, (r8) syscall number
+; ABI: (r0-r7) up to 8 args, (r8) syscall number
 ; ---------------------------------------------
 
 ENTRY(EV_Trap)
index 9152782444b55737ad04a227598fc4a17f69d7a8..8d541f53fae3ecee633ce19b7f99a818d1609bd0 100644 (file)
@@ -165,7 +165,7 @@ ENTRY(first_lines_of_secondary)
        ; setup stack (fp, sp)
        mov     fp, 0
 
-       ; set it's stack base to tsk->thread_info bottom
+       ; set its stack base to tsk->thread_info bottom
        GET_TSK_STACK_BASE r0, sp
 
        j       start_kernel_secondary
index 678898757e4739da5fcffb1df8ae289a783957c2..f324f0e3341a3939ad52f44d454eebc4288500fc 100644 (file)
@@ -56,7 +56,7 @@ void arc_init_IRQ(void)
        WRITE_AUX(AUX_IRQ_CTRL, ictrl);
 
        /*
-        * ARCv2 core intc provides multiple interrupt priorities (upto 16).
+        * ARCv2 core intc provides multiple interrupt priorities (up to 16).
         * Typical builds though have only two levels (0-high, 1-low)
         * Linux by default uses lower prio 1 for most irqs, reserving 0 for
         * NMI style interrupts in future (say perf)
index e71d64119d71acc999869c56b6459d381629aadc..f8e2960832d943282a7bc698e1e229ed7a92b074 100644 (file)
@@ -190,7 +190,8 @@ static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs)
        }
 }
 
-int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
+static int
+__kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
 {
        struct kprobe *p;
        struct kprobe_ctlblk *kcb;
@@ -241,8 +242,8 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
        return 0;
 }
 
-static int __kprobes arc_post_kprobe_handler(unsigned long addr,
-                                        struct pt_regs *regs)
+static int
+__kprobes arc_post_kprobe_handler(unsigned long addr, struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
index adff957962da88382f9e55e72d39eca5c5ed9dcf..6e5a651cd75cf5403001dc73c13717d0b53ffe13 100644 (file)
@@ -38,7 +38,7 @@
  * (based on a specific RTL build)
  * Below is the static map between perf generic/arc specific event_id and
  * h/w condition names.
- * At the time of probe, we loop thru each index and find it's name to
+ * At the time of probe, we loop thru each index and find its name to
  * complete the mapping of perf event_id to h/w index as latter is needed
  * to program the counter really
  */
index d08a5092c2b4d451e50b1b26e47926d04f01d2c2..7b6a9beba9db6d1dc55bae6e71c7e7c99508145d 100644 (file)
@@ -390,7 +390,7 @@ static void arc_chk_core_config(struct cpuinfo_arc *info)
 #ifdef CONFIG_ARC_HAS_DCCM
        /*
         * DCCM can be arbit placed in hardware.
-        * Make sure it's placement/sz matches what Linux is built with
+        * Make sure its placement/sz matches what Linux is built with
         */
        if ((unsigned int)__arc_dccm_base != info->dccm.base)
                panic("Linux built with incorrect DCCM Base address\n");
index 8f6f4a5429646fc431f94f5ea600caa4fa8d8d43..fefa705a8638503c596543af3cbb6ce2436586b1 100644 (file)
@@ -8,15 +8,16 @@
  *
  * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
  *  -do_signal() supports TIF_RESTORE_SIGMASK
- *  -do_signal() no loner needs oldset, required by OLD sys_sigsuspend
- *  -sys_rt_sigsuspend() now comes from generic code, so discard arch implemen
+ *  -do_signal() no longer needs oldset, required by OLD sys_sigsuspend
+ *  -sys_rt_sigsuspend() now comes from generic code, so discard arch
+ *   implementation
  *  -sys_sigsuspend() no longer needs to fudge ptregs, hence that arg removed
  *  -sys_sigsuspend() no longer loops for do_signal(), sets TIF_xxx and leaves
  *   the job to do_signal()
  *
  * vineetg: July 2009
  *  -Modified Code to support the uClibc provided userland sigreturn stub
- *   to avoid kernel synthesing it on user stack at runtime, costing TLB
+ *   to avoid kernel synthesizing it on user stack at runtime, costing TLB
  *   probes and Cache line flushes.
  *
  * vineetg: July 2009
index 9b9570b79362ee08931044931bccbd965526c786..a19751e824fb4c272e5cfa21ab3349210d30bfa7 100644 (file)
@@ -89,7 +89,7 @@ int do_misaligned_access(unsigned long address, struct pt_regs *regs,
 
 /*
  * Entry point for miscll errors such as Nested Exceptions
- *  -Duplicate TLB entry is handled seperately though
+ *  -Duplicate TLB entry is handled separately though
  */
 void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
 {
index 549c3f407918693f4407e4b0854cdd63d2017952..61a1b2b96e1d81396d6b7f7ab505756d0d8bb86e 100644 (file)
@@ -41,8 +41,8 @@ SECTIONS
 #endif
 
        /*
-        * The reason for having a seperate subsection .init.ramfs is to
-        * prevent objump from including it in kernel dumps
+        * The reason for having a separate subsection .init.ramfs is to
+        * prevent objdump from including it in kernel dumps
         *
         * Reason for having .init.ramfs above .init is to make sure that the
         * binary blob is tucked away to one side, reducing the displacement
index ad702b49aeb3b8d2a0306f209bf140acb5fd2beb..cae4a7aae0ed4e186addda91d54b02153ca7181c 100644 (file)
@@ -212,7 +212,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
        unsigned long flags;
 
        /* If range @start to @end is more than 32 TLB entries deep,
-        * its better to move to a new ASID rather than searching for
+        * it's better to move to a new ASID rather than searching for
         * individual entries and then shooting them down
         *
         * The calc above is rough, doesn't account for unaligned parts,
@@ -408,7 +408,7 @@ static void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *p
         * -More importantly it makes this handler inconsistent with fast-path
         *  TLB Refill handler which always deals with "current"
         *
-        * Lets see the use cases when current->mm != vma->mm and we land here
+        * Let's see the use cases when current->mm != vma->mm and we land here
         *  1. execve->copy_strings()->__get_user_pages->handle_mm_fault
         *     Here VM wants to pre-install a TLB entry for user stack while
         *     current->mm still points to pre-execve mm (hence the condition).
index e054780a8fe0c99b8a0103a3f0786d8dca3294fe..dc65e87a531fdb054466f8682af3649acb4d6fa3 100644 (file)
@@ -5,19 +5,19 @@
  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  *
  * Vineetg: April 2011 :
- *  -MMU v1: moved out legacy code into a seperate file
+ *  -MMU v1: moved out legacy code into a separate file
  *  -MMU v3: PD{0,1} bits layout changed: They don't overlap anymore,
  *      helps avoid a shift when preparing PD0 from PTE
  *
  * Vineetg: July 2009
- *  -For MMU V2, we need not do heuristics at the time of commiting a D-TLB
- *   entry, so that it doesn't knock out it's I-TLB entry
+ *  -For MMU V2, we need not do heuristics at the time of committing a D-TLB
+ *   entry, so that it doesn't knock out its I-TLB entry
  *  -Some more fine tuning:
  *   bmsk instead of add, asl.cc instead of branch, delay slot utilise etc
  *
  * Vineetg: July 2009
  *  -Practically rewrote the I/D TLB Miss handlers
- *   Now 40 and 135 instructions a peice as compared to 131 and 449 resp.
+ *   Now 40 and 135 instructions apiece as compared to 131 and 449 resp.
  *   Hence Leaner by 1.5 K
  *   Used Conditional arithmetic to replace excessive branching
  *   Also used short instructions wherever possible
index 4f609e9e510ef6e6821ef8f4d9cf0090a48c78f1..009d2c83242102c8e46a6f2019026b5d60a583ac 100644 (file)
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1150000>;
+                                               regulator-suspend-microvolt = <1150000>;
                                                regulator-mode = <4>;
                                        };
 
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1050000>;
+                                               regulator-suspend-microvolt = <1050000>;
                                                regulator-mode = <4>;
                                        };
 
                                        regulator-always-on;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <1800000>;
+                                               regulator-suspend-microvolt = <1800000>;
                                                regulator-on-in-suspend;
                                        };
 
                                        regulator-always-on;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <3300000>;
+                                               regulator-suspend-microvolt = <3300000>;
                                                regulator-on-in-suspend;
                                        };
 
index 217e9b96c61e5dea644c6b2f46d5807f58312b38..20b2497657ae48e691f06424ff688e27073bb63f 100644 (file)
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1150000>;
+                                               regulator-suspend-microvolt = <1150000>;
                                                regulator-mode = <4>;
                                        };
 
 
                                        regulator-state-standby {
                                                regulator-on-in-suspend;
-                                               regulator-suspend-voltage = <1050000>;
+                                               regulator-suspend-microvolt = <1050000>;
                                                regulator-mode = <4>;
                                        };
 
                                        regulator-always-on;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <1800000>;
+                                               regulator-suspend-microvolt = <1800000>;
                                                regulator-on-in-suspend;
                                        };
 
                                        regulator-max-microvolt = <3700000>;
 
                                        regulator-state-standby {
-                                               regulator-suspend-voltage = <1800000>;
+                                               regulator-suspend-microvolt = <1800000>;
                                                regulator-on-in-suspend;
                                        };
 
index 3fdece5bd31f9d00de384b911ca554b93bbc33b0..5248a058230c86910ef587ffa4e044e8645e6b6c 100644 (file)
                     &pinctrl_usb_pwr>;
        dr_mode = "host";
        power-active-high;
+       over-current-active-low;
        disable-over-current;
        status = "okay";
 };
index 1d672457d02ff3fcdd849c57c9108f94a8563886..72b5cd697f5d94b742fb59b98913c975838de871 100644 (file)
@@ -871,16 +871,11 @@ static inline void emit_a32_alu_r64(const bool is64, const s8 dst[],
 }
 
 /* dst = src (4 bytes)*/
-static inline void emit_a32_mov_r(const s8 dst, const s8 src, const u8 off,
-                                 struct jit_ctx *ctx) {
+static inline void emit_a32_mov_r(const s8 dst, const s8 src, struct jit_ctx *ctx) {
        const s8 *tmp = bpf2a32[TMP_REG_1];
        s8 rt;
 
        rt = arm_bpf_get_reg32(src, tmp[0], ctx);
-       if (off && off != 32) {
-               emit(ARM_LSL_I(rt, rt, 32 - off), ctx);
-               emit(ARM_ASR_I(rt, rt, 32 - off), ctx);
-       }
        arm_bpf_put_reg32(dst, rt, ctx);
 }
 
@@ -889,15 +884,15 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
                                  const s8 src[],
                                  struct jit_ctx *ctx) {
        if (!is64) {
-               emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
+               emit_a32_mov_r(dst_lo, src_lo, ctx);
                if (!ctx->prog->aux->verifier_zext)
                        /* Zero out high 4 bytes */
                        emit_a32_mov_i(dst_hi, 0, ctx);
        } else if (__LINUX_ARM_ARCH__ < 6 &&
                   ctx->cpu_architecture < CPU_ARCH_ARMv5TE) {
                /* complete 8 byte move */
-               emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
-               emit_a32_mov_r(dst_hi, src_hi, 0, ctx);
+               emit_a32_mov_r(dst_lo, src_lo, ctx);
+               emit_a32_mov_r(dst_hi, src_hi, ctx);
        } else if (is_stacked(src_lo) && is_stacked(dst_lo)) {
                const u8 *tmp = bpf2a32[TMP_REG_1];
 
@@ -917,17 +912,52 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
 static inline void emit_a32_movsx_r64(const bool is64, const u8 off, const s8 dst[], const s8 src[],
                                      struct jit_ctx *ctx) {
        const s8 *tmp = bpf2a32[TMP_REG_1];
-       const s8 *rt;
+       s8 rs;
+       s8 rd;
 
-       rt = arm_bpf_get_reg64(dst, tmp, ctx);
+       if (is_stacked(dst_lo))
+               rd = tmp[1];
+       else
+               rd = dst_lo;
+       rs = arm_bpf_get_reg32(src_lo, rd, ctx);
+       /* rs may be one of src[1], dst[1], or tmp[1] */
+
+       /* Sign extend rs if needed. If off == 32, lower 32-bits of src are moved to dst and sign
+        * extension only happens in the upper 64 bits.
+        */
+       if (off != 32) {
+               /* Sign extend rs into rd */
+               emit(ARM_LSL_I(rd, rs, 32 - off), ctx);
+               emit(ARM_ASR_I(rd, rd, 32 - off), ctx);
+       } else {
+               rd = rs;
+       }
+
+       /* Write rd to dst_lo
+        *
+        * Optimization:
+        * Assume:
+        * 1. dst == src and stacked.
+        * 2. off == 32
+        *
+        * In this case src_lo was loaded into rd(tmp[1]) but rd was not sign extended as off==32.
+        * So, we don't need to write rd back to dst_lo as they have the same value.
+        * This saves us one str instruction.
+        */
+       if (dst_lo != src_lo || off != 32)
+               arm_bpf_put_reg32(dst_lo, rd, ctx);
 
-       emit_a32_mov_r(dst_lo, src_lo, off, ctx);
        if (!is64) {
                if (!ctx->prog->aux->verifier_zext)
                        /* Zero out high 4 bytes */
                        emit_a32_mov_i(dst_hi, 0, ctx);
        } else {
-               emit(ARM_ASR_I(rt[0], rt[1], 31), ctx);
+               if (is_stacked(dst_hi)) {
+                       emit(ARM_ASR_I(tmp[0], rd, 31), ctx);
+                       arm_bpf_put_reg32(dst_hi, tmp[0], ctx);
+               } else {
+                       emit(ARM_ASR_I(dst_hi, rd, 31), ctx);
+               }
        }
 }
 
index bfc5c81a5bd4eb44b2fb4cdf57ded83ccf8cb6e8..8141926e4ef1424639a3196337c7e006f5f6995e 100644 (file)
                                         <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>,
                                         <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pclk", "wrap", "phy", "axi";
-                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>,
+                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>,
                                                  <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>;
                                assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
                                                         <&clk IMX8MP_CLK_24M>;
index 0c38f7b51763776cda640ab73f8513f4cce9f1e5..234e3b23d7a8d3206c1f5e74f875a4501eea3942 100644 (file)
 };
 
 &pio {
-       eth_default: eth_default {
+       eth_default: eth-default-pins {
                tx_pins {
                        pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GBE_TXD3>,
                                 <MT2712_PIN_72_GBE_TXD2__FUNC_GBE_TXD2>,
                };
        };
 
-       eth_sleep: eth_sleep {
+       eth_sleep: eth-sleep-pins {
                tx_pins {
                        pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GPIO71>,
                                 <MT2712_PIN_72_GBE_TXD2__FUNC_GPIO72>,
                };
        };
 
-       usb0_id_pins_float: usb0_iddig {
+       usb0_id_pins_float: usb0-iddig-pins {
                pins_iddig {
                        pinmux = <MT2712_PIN_12_IDDIG_P0__FUNC_IDDIG_A>;
                        bias-pull-up;
                };
        };
 
-       usb1_id_pins_float: usb1_iddig {
+       usb1_id_pins_float: usb1-iddig-pins {
                pins_iddig {
                        pinmux = <MT2712_PIN_14_IDDIG_P1__FUNC_IDDIG_B>;
                        bias-pull-up;
index 6d218caa198cfd304eb546988737b1dc261c34ed..082672efba0a3408e9a9bb47ffad26046f97c3a2 100644 (file)
                #clock-cells = <1>;
        };
 
-       infracfg: syscon@10001000 {
+       infracfg: clock-controller@10001000 {
                compatible = "mediatek,mt2712-infracfg", "syscon";
                reg = <0 0x10001000 0 0x1000>;
                #clock-cells = <1>;
+               #reset-cells = <1>;
        };
 
        pericfg: syscon@10003000 {
index 3ee9266fa8e985cedcd4177f04dfdff8a4b689f4..917fa39a74f8d7f3d07cb71b7f0533c0777b5583 100644 (file)
                clock-names = "hif_sel";
        };
 
-       cir: cir@10009000 {
+       cir: ir-receiver@10009000 {
                compatible = "mediatek,mt7622-cir";
                reg = <0 0x10009000 0 0x1000>;
                interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
                };
        };
 
-       apmixedsys: apmixedsys@10209000 {
-               compatible = "mediatek,mt7622-apmixedsys",
-                            "syscon";
+       apmixedsys: clock-controller@10209000 {
+               compatible = "mediatek,mt7622-apmixedsys";
                reg = <0 0x10209000 0 0x1000>;
                #clock-cells = <1>;
        };
 
-       topckgen: topckgen@10210000 {
-               compatible = "mediatek,mt7622-topckgen",
-                            "syscon";
+       topckgen: clock-controller@10210000 {
+               compatible = "mediatek,mt7622-topckgen";
                reg = <0 0x10210000 0 0x1000>;
                #clock-cells = <1>;
        };
                         <&pericfg CLK_PERI_AUXADC_PD>;
                clock-names = "therm", "auxadc";
                resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
-               reset-names = "therm";
                mediatek,auxadc = <&auxadc>;
                mediatek,apmixedsys = <&apmixedsys>;
                nvmem-cells = <&thermal_calibration>;
                power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>;
        };
 
-       ssusbsys: ssusbsys@1a000000 {
-               compatible = "mediatek,mt7622-ssusbsys",
-                            "syscon";
+       ssusbsys: clock-controller@1a000000 {
+               compatible = "mediatek,mt7622-ssusbsys";
                reg = <0 0x1a000000 0 0x1000>;
                #clock-cells = <1>;
                #reset-cells = <1>;
                };
        };
 
-       pciesys: pciesys@1a100800 {
-               compatible = "mediatek,mt7622-pciesys",
-                            "syscon";
+       pciesys: clock-controller@1a100800 {
+               compatible = "mediatek,mt7622-pciesys";
                reg = <0 0x1a100800 0 0x1000>;
                #clock-cells = <1>;
                #reset-cells = <1>;
                };
        };
 
-       hifsys: syscon@1af00000 {
-               compatible = "mediatek,mt7622-hifsys", "syscon";
+       hifsys: clock-controller@1af00000 {
+               compatible = "mediatek,mt7622-hifsys";
                reg = <0 0x1af00000 0 0x70>;
+               #clock-cells = <1>;
        };
 
-       ethsys: syscon@1b000000 {
+       ethsys: clock-controller@1b000000 {
                compatible = "mediatek,mt7622-ethsys",
                             "syscon";
                reg = <0 0x1b000000 0 0x1000>;
        };
 
        eth: ethernet@1b100000 {
-               compatible = "mediatek,mt7622-eth",
-                            "mediatek,mt2701-eth",
-                            "syscon";
+               compatible = "mediatek,mt7622-eth";
                reg = <0 0x1b100000 0 0x20000>;
                interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
                             <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
index e04b1c0c0ebbfb59e6e75318ebfaef1dfbe02997..ed79ad1ae8716e0f750e8b747eea930f496541cb 100644 (file)
 
 &cpu_thermal {
        cooling-maps {
-               cpu-active-high {
+               map-cpu-active-high {
                        /* active: set fan to cooling level 2 */
                        cooling-device = <&fan 2 2>;
                        trip = <&cpu_trip_active_high>;
                };
 
-               cpu-active-med {
+               map-cpu-active-med {
                        /* active: set fan to cooling level 1 */
                        cooling-device = <&fan 1 1>;
                        trip = <&cpu_trip_active_med>;
                };
 
-               cpu-active-low {
+               map-cpu-active-low {
                        /* active: set fan to cooling level 0 */
                        cooling-device = <&fan 0 0>;
                        trip = <&cpu_trip_active_low>;
index b3f416b9a7a4da6c15c040c160ee6d6203979aeb..559990dcd1d1790b2f985dda29e6bd2ebdfd08c0 100644 (file)
                        reg = <0 0x1100c800 0 0x800>;
                        interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&infracfg CLK_INFRA_THERM_CK>,
-                                <&infracfg CLK_INFRA_ADC_26M_CK>,
-                                <&infracfg CLK_INFRA_ADC_FRC_CK>;
-                       clock-names = "therm", "auxadc", "adc_32k";
+                                <&infracfg CLK_INFRA_ADC_26M_CK>;
+                       clock-names = "therm", "auxadc";
                        nvmem-cells = <&thermal_calibration>;
                        nvmem-cell-names = "calibration-data";
                        #thermal-sensor-cells = <1>;
                         compatible = "mediatek,mt7986-ethsys",
                                      "syscon";
                         reg = <0 0x15000000 0 0x1000>;
-                        #address-cells = <1>;
-                        #size-cells = <1>;
                         #clock-cells = <1>;
                         #reset-cells = <1>;
                };
                                          <&topckgen CLK_TOP_SGM_325M_SEL>;
                        assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>,
                                                 <&apmixedsys CLK_APMIXED_SGMPLL>;
-                       #reset-cells = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        mediatek,ethsys = <&ethsys>;
index 6bd7424ef66c53b48d89d07ca14d25e913fd1c98..100191c6453ba3b6f69762654e7ef421bf87cd30 100644 (file)
 };
 
 &mt6358_vgpu_reg {
-       regulator-min-microvolt = <625000>;
        regulator-max-microvolt = <900000>;
 
        regulator-coupled-with = <&mt6358_vsram_gpu_reg>;
index 93dfbf1302315d83c2a4c556694c4193ed56e8a3..774ae5d9143f1ea95cc15a7148b5ec54c7d8552a 100644 (file)
                        compatible = "mediatek,mt8183-mfgcfg", "syscon";
                        reg = <0 0x13000000 0 0x1000>;
                        #clock-cells = <1>;
+                       power-domains = <&spm MT8183_POWER_DOMAIN_MFG_ASYNC>;
                };
 
                gpu: gpu@13040000 {
index 3dea28f1d80612737c1309199d334734411aee07..1807e9d6cb0e4123329c5b369fc83a61f7677721 100644 (file)
                                 * regulator coupling requirements.
                                 */
                                regulator-name = "ppvar_dvdd_vgpu";
-                               regulator-min-microvolt = <600000>;
+                               regulator-min-microvolt = <500000>;
                                regulator-max-microvolt = <950000>;
                                regulator-ramp-delay = <6250>;
                                regulator-enable-ramp-delay = <200>;
index 9b738f6a5d213ada21fb98eef5ff223caa4dfdc7..7a704246678f03000c6640f5e3efc8d9fcb49884 100644 (file)
                        mt6315_6_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vbcpu";
-                               regulator-min-microvolt = <300000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-allowed-modes = <0 1 2>;
                        mt6315_6_vbuck3: vbuck3 {
                                regulator-compatible = "vbuck3";
                                regulator-name = "Vlcpu";
-                               regulator-min-microvolt = <300000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-allowed-modes = <0 1 2>;
                        mt6315_7_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vgpu";
-                               regulator-min-microvolt = <606250>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <800000>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-allowed-modes = <0 1 2>;
index 05e401670bced3abf9eed4117739f2e4f24e99ee..84cbdf6e9eb0ca06b0187d14ab0c251ca1a9ef05 100644 (file)
                        reg = <0 0x14001000 0 0x1000>;
                        interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>;
                        clocks = <&mmsys CLK_MM_DISP_MUTEX0>;
+                       mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x1000 0x1000>;
                        mediatek,gce-events = <CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_0>,
                                              <CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_1>;
                        power-domains = <&spm MT8192_POWER_DOMAIN_DISP>;
index f94c07f8b9334e817041a21e83515cb3dc274c40..4a11918da370483c287d5e03193e02656b617af1 100644 (file)
        status = "okay";
 };
 
+&cpu0 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu1 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu2 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu3 {
+       cpu-supply = <&mt6359_vcore_buck_reg>;
+};
+
+&cpu4 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu5 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu6 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
+&cpu7 {
+       cpu-supply = <&mt6315_6_vbuck1>;
+};
+
 &dp_intf0 {
        status = "okay";
 
                        mt6315_6_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vbcpu";
-                               regulator-min-microvolt = <300000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-ramp-delay = <6250>;
                        mt6315_7_vbuck1: vbuck1 {
                                regulator-compatible = "vbuck1";
                                regulator-name = "Vgpu";
-                               regulator-min-microvolt = <625000>;
+                               regulator-min-microvolt = <400000>;
                                regulator-max-microvolt = <1193750>;
                                regulator-enable-ramp-delay = <256>;
                                regulator-ramp-delay = <6250>;
index ea6dc220e1cce2181422fd33b9081ad1082e64b6..5d8b68f86ce44655664c07276e8ae813307cb248 100644 (file)
                        compatible = "mediatek,mt8195-vppsys0", "syscon";
                        reg = <0 0x14000000 0 0x1000>;
                        #clock-cells = <1>;
+                       mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0 0x1000>;
                };
 
                dma-controller@14001000 {
                        compatible = "mediatek,mt8195-vppsys1", "syscon";
                        reg = <0 0x14f00000 0 0x1000>;
                        #clock-cells = <1>;
+                       mediatek,gce-client-reg = <&gce1 SUBSYS_14f0XXXX 0 0x1000>;
                };
 
                mutex@14f01000 {
                        reg = <0 0x1c01a000 0 0x1000>;
                        mboxes = <&gce0 0 CMDQ_THR_PRIO_4>;
                        #clock-cells = <1>;
+                       mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xa000 0x1000>;
                };
 
 
                        interrupts = <GIC_SPI 658 IRQ_TYPE_LEVEL_HIGH 0>;
                        power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS0>;
                        clocks = <&vdosys0 CLK_VDO0_DISP_MUTEX0>;
+                       mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0x6000 0x1000>;
                        mediatek,gce-events = <CMDQ_EVENT_VDO0_DISP_STREAM_DONE_0>;
                };
 
                        power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
                        clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>;
                        clock-names = "vdo1_mutex";
+                       mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>;
                        mediatek,gce-events = <CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0>;
                };
 
index 7e7f0f0fb41ba03fe39095c7d1b5e2e24ac3136d..41f51d32611107ef84d30034d703c89b32f7dec2 100644 (file)
                        compatible = "qcom,sc7280-adsp-pas";
                        reg = <0 0x03700000 0 0x100>;
 
-                       interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                                              <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sc7280-cdsp-pas";
                        reg = <0 0x0a300000 0 0x10000>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
index 32afc78d5b769d56d6f316b2bbd34343a2497b56..053f7861c3ceced82c3dfb0cf539f94c9c2f64a5 100644 (file)
                        resets = <&gcc GCC_USB30_SEC_BCR>;
                        power-domains = <&gcc USB30_SEC_GDSC>;
                        interrupts-extended = <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
-                                             <&pdc 7 IRQ_TYPE_LEVEL_HIGH>,
+                                             <&pdc 40 IRQ_TYPE_LEVEL_HIGH>,
                                              <&pdc 10 IRQ_TYPE_EDGE_BOTH>,
                                              <&pdc 11 IRQ_TYPE_EDGE_BOTH>;
                        interrupt-names = "hs_phy_irq", "ss_phy_irq",
index a5b194813079e9779e7913a4054a413af3a14750..d0f82e12289e1b53f1d01592a2131932a48866c5 100644 (file)
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_4_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie4_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_3B_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie3b_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_3A_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie3a_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_2B_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie2b_phy>;
                        phy-names = "pciephy";
                        reset-names = "pci";
 
                        power-domains = <&gcc PCIE_2A_GDSC>;
+                       required-opps = <&rpmhpd_opp_nom>;
 
                        phys = <&pcie2a_phy>;
                        phy-names = "pciephy";
                        compatible = "qcom,sc8280xp-adsp-pas";
                        reg = <0 0x03000000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sc8280xp-nsp0-pas";
                        reg = <0 0x1b300000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp0_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp0_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp0_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sc8280xp-nsp1-pas";
                        reg = <0 0x21300000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp1_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp1_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_nsp1_in 2 IRQ_TYPE_EDGE_RISING>,
index 24bcec3366efd58671cbcd6fa27cd0d807ab2d4f..0be053555602c0d3e1bd52888c05e841bb4de9ae 100644 (file)
                        compatible = "qcom,sm6350-adsp-pas";
                        reg = <0 0x03000000 0 0x100>;
 
-                       interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sm6350-cdsp-pas";
                        reg = <0 0x08300000 0 0x10000>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
index 4386f8a9c636c1dd58a21ed8002d385c3d716c5c..f40509d91bbda8a73d9624ca78fcb3b03e2bf60c 100644 (file)
                        compatible = "qcom,sm6375-adsp-pas";
                        reg = <0 0x0a400000 0 0x100>;
 
-                       interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
index 39bd8f0eba1e653a7fe1b452cb7615317f3f6b68..7f2333c9d17d6d74ee3fe33a017e2fa03bcb3683 100644 (file)
                        compatible = "qcom,sm8250-slpi-pas";
                        reg = <0 0x05c00000 0 0x4000>;
 
-                       interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 9 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sm8250-cdsp-pas";
                        reg = <0 0x08300000 0 0x10000>;
 
-                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
                        compatible = "qcom,sm8250-adsp-pas";
                        reg = <0 0x17300000 0 0x100>;
 
-                       interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+                       interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
                                              <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
index b86be34a912b943e7649eecbd71fae2b78411e5f..024d2653cc3075126a59da6f099c5a14b18bc8d6 100644 (file)
                        ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
                                 <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
 
-                       /*
-                        * MSIs for BDF (1:0.0) only works with Device ID 0x5980.
-                        * Hence, the IDs are swapped.
-                        */
-                       msi-map = <0x0 &gic_its 0x5981 0x1>,
-                                 <0x100 &gic_its 0x5980 0x1>;
+                       msi-map = <0x0 &gic_its 0x5980 0x1>,
+                                 <0x100 &gic_its 0x5981 0x1>;
                        msi-map-mask = <0xff00>;
                        interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
                        ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
                                 <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
 
-                       /*
-                        * MSIs for BDF (1:0.0) only works with Device ID 0x5a00.
-                        * Hence, the IDs are swapped.
-                        */
-                       msi-map = <0x0 &gic_its 0x5a01 0x1>,
-                                 <0x100 &gic_its 0x5a00 0x1>;
+                       msi-map = <0x0 &gic_its 0x5a00 0x1>,
+                                 <0x100 &gic_its 0x5a01 0x1>;
                        msi-map-mask = <0xff00>;
                        interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
index 3904348075f67945a9e54117a518631541806ad9..3348bc06db488a77e4dd17dff687ffbcfa1cfced 100644 (file)
                                        <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_0 0>;
                        interconnect-names = "pcie-mem", "cpu-pcie";
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1401 0x1>,
-                                 <0x100 &gic_its 0x1400 0x1>;
+                       msi-map = <0x0 &gic_its 0x1400 0x1>,
+                                 <0x100 &gic_its 0x1401 0x1>;
                        iommu-map = <0x0   &apps_smmu 0x1400 0x1>,
                                    <0x100 &apps_smmu 0x1401 0x1>;
 
                                        <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_1 0>;
                        interconnect-names = "pcie-mem", "cpu-pcie";
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1481 0x1>,
-                                 <0x100 &gic_its 0x1480 0x1>;
+                       msi-map = <0x0 &gic_its 0x1480 0x1>,
+                                 <0x100 &gic_its 0x1481 0x1>;
                        iommu-map = <0x0   &apps_smmu 0x1480 0x1>,
                                    <0x100 &apps_smmu 0x1481 0x1>;
 
index ba72d8f3842073fd481926009ce37075894dc8c8..eb117866e59ff861bf8a41827a44429e172d6010 100644 (file)
                        interrupt-map-mask = <0 0 0 0x7>;
                        #interrupt-cells = <1>;
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1401 0x1>,
-                                 <0x100 &gic_its 0x1400 0x1>;
+                       msi-map = <0x0 &gic_its 0x1400 0x1>,
+                                 <0x100 &gic_its 0x1401 0x1>;
                        msi-map-mask = <0xff00>;
 
                        linux,pci-domain = <0>;
                        interrupt-map-mask = <0 0 0 0x7>;
                        #interrupt-cells = <1>;
 
-                       /* Entries are reversed due to the unusual ITS DeviceID encoding */
-                       msi-map = <0x0 &gic_its 0x1481 0x1>,
-                                 <0x100 &gic_its 0x1480 0x1>;
+                       msi-map = <0x0 &gic_its 0x1480 0x1>,
+                                 <0x100 &gic_its 0x1481 0x1>;
                        msi-map-mask = <0xff00>;
 
                        linux,pci-domain = <1>;
index 8e517f76189e19cb038dfa0d3557ef729c630b46..6b40082bac68ce92d87076f6ba7e0fd980dfb23c 100644 (file)
 
                domain-idle-states {
                        CLUSTER_CL4: cluster-sleep-0 {
-                               compatible = "arm,idle-state";
+                               compatible = "domain-idle-state";
                                idle-state-name = "l2-ret";
                                arm,psci-suspend-param = <0x01000044>;
                                entry-latency-us = <350>;
                        };
 
                        CLUSTER_CL5: cluster-sleep-1 {
-                               compatible = "arm,idle-state";
+                               compatible = "domain-idle-state";
                                idle-state-name = "ret-pll-off";
                                arm,psci-suspend-param = <0x01000054>;
                                entry-latency-us = <2200>;
index 5846a11f0e848fc059446a47b57ff732b45e9f4c..d5e035823eb5e430c896c3a20a4347ccd919cc50 100644 (file)
@@ -663,7 +663,7 @@ camera: &i2c7 {
                        port@1 {
                                reg = <1>;
 
-                               mipi1_in_panel: endpoint@1 {
+                               mipi1_in_panel: endpoint {
                                        remote-endpoint = <&mipi1_out_panel>;
                                };
                        };
@@ -689,7 +689,6 @@ camera: &i2c7 {
        ep-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
 
        /* PERST# asserted in S3 */
-       pcie-reset-suspend = <1>;
 
        vpcie3v3-supply = <&wlan_3v3>;
        vpcie1v8-supply = <&pp1800_pcie>;
index dfb2a0bdea5b736d7ce6554e22a60c01d0b31297..9586bb12a5d8f51dbf81e8c9c200d6bafa0ae3e2 100644 (file)
                                #size-cells = <0>;
 
                                interface@0 {   /* interface 0 of configuration 1 */
-                                       compatible = "usbbda,8156.config1.0";
+                                       compatible = "usbifbda,8156.config1.0";
                                        reg = <0 1>;
                                };
                        };
index 054c6a4d1a45f71c7951752cbe8e86bd4e24d6ab..294eb2de263debd89e7bbc1a41495fb5fdf782a3 100644 (file)
 };
 
 &pcie0 {
-       bus-scan-delay-ms = <1000>;
        ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;
        num-lanes = <4>;
        pinctrl-names = "default";
index 2c3984a880af64ceaf3f7ec1a09ceee02f0dffeb..f6f15946579ebfc32925256e2569535be5a48f89 100644 (file)
        num-lanes = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&pcie_clkreqn_cpm>;
+       vpcie3v3-supply = <&vcc3v3_baseboard>;
+       vpcie12v-supply = <&dc_12v>;
        status = "okay";
 };
 
index c08e69391c015405a5ea7de34e211ee12ee6c58a..ccbe3a7a1d2c2fd9c195a027976d2c076d4f7381 100644 (file)
                regulator-max-microvolt = <5000000>;
        };
 
+       vcca_0v9: vcca-0v9-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcca_0v9";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <900000>;
+               vin-supply = <&vcc_1v8>;
+       };
+
+       vcca_1v8: vcca-1v8-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcca_1v8";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc3v3_sys>;
+       };
+
        vdd_log: vdd-log {
                compatible = "pwm-regulator";
                pwms = <&pwm2 0 25000 1>;
        gpio1830-supply = <&vcc_1v8>;
 };
 
-&pmu_io_domains {
-       status = "okay";
-       pmu1830-supply = <&vcc_1v8>;
+&pcie0 {
+       /* PCIe PHY supplies */
+       vpcie0v9-supply = <&vcca_0v9>;
+       vpcie1v8-supply = <&vcca_1v8>;
 };
 
-&pwm2 {
-       status = "okay";
+&pcie_clkreqn_cpm {
+       rockchip,pins =
+               <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &pinctrl {
+       pinctrl-names = "default";
+       pinctrl-0 = <&q7_thermal_pin>;
+
+       gpios {
+               q7_thermal_pin: q7-thermal-pin {
+                       rockchip,pins =
+                               <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
        i2c8 {
                i2c8_xfer_a: i2c8-xfer {
                        rockchip,pins =
        usb3 {
                usb3_id: usb3-id {
                        rockchip,pins =
-                         <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+                         <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
 };
 
+&pmu_io_domains {
+       status = "okay";
+       pmu1830-supply = <&vcc_1v8>;
+};
+
+&pwm2 {
+       status = "okay";
+};
+
 &sdhci {
        /*
         * Signal integrity isn't great at 200MHz but 100MHz has proven stable
index 6ecdf5d283390ae354063bc936468a17ddc0050b..c1194d1e438d0d0667ee3d7e0aa143856c87d319 100644 (file)
 
 &pcie2x1 {
        reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
-       disable-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
        vpcie3v3-supply = <&vcc3v3_pcie>;
        status = "okay";
 };
index 7b5f3904ef6104754d8d2bc6c96ab668e5b3b230..c87fad2c34cba3bb58c4ab3ee61998128c1a566b 100644 (file)
 
                        vccio_sd: LDO_REG5 {
                                regulator-name = "vccio_sd";
+                               regulator-always-on;
+                               regulator-boot-on;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
 
        #address-cells = <1>;
        #size-cells = <0>;
 
-       switch@0 {
+       switch@1f {
                compatible = "mediatek,mt7531";
-               reg = <0>;
+               reg = <0x1f>;
 
                ports {
                        #address-cells = <1>;
index a8a4cc190eb32e2cf18d9ab7f8549a96c12a6465..a3112d5df2008d99a236febbcadb883e036cb4e0 100644 (file)
 
 &pcie2x1 {
        reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
-       disable-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
        vpcie3v3-supply = <&vcc3v3_mini_pcie>;
        status = "okay";
 };
index cce1c8e835877c4341d90f2fe80da7c57dde8d0c..94ecb9b4f98f88c6ec0f93ff839f6a594eb75c19 100644 (file)
        pinctrl-0 = <&i2c7m0_xfer>;
        status = "okay";
 
-       es8316: audio-codec@11 {
+       es8316: audio-codec@10 {
                compatible = "everest,es8316";
-               reg = <0x11>;
+               reg = <0x10>;
                assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
                assigned-clock-rates = <12288000>;
                clocks = <&cru I2S0_8CH_MCLKOUT>;
index 1b606ea5b6cf2b32c72eab2bdac812b4a94d310c..1a604429fb266e687ab9fb20e7f157c78ac461c9 100644 (file)
                pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
                            <&rk806_dvs2_null>, <&rk806_dvs3_null>;
                spi-max-frequency = <1000000>;
+               system-power-controller;
 
                vcc1-supply = <&vcc5v0_sys>;
                vcc2-supply = <&vcc5v0_sys>;
                #gpio-cells = <2>;
 
                rk806_dvs1_null: dvs1-null-pins {
-                       pins = "gpio_pwrctrl2";
+                       pins = "gpio_pwrctrl1";
                        function = "pin_fun0";
                };
 
index 67414d72e2b6ef9308aa357c606f64d652c54075..22bbfbe729c11b6e0d30cd88a5fa144ba52a22e6 100644 (file)
                            <&rk806_dvs2_null>, <&rk806_dvs3_null>;
                pinctrl-names = "default";
                spi-max-frequency = <1000000>;
+               system-power-controller;
 
                vcc1-supply = <&vcc4v0_sys>;
                vcc2-supply = <&vcc4v0_sys>;
index f48b8dab8b3d2fe175a02ddf3c81aa39dea5f16c..1d26bb5b02f4b592775dee6f964938f8ce4c866c 100644 (file)
@@ -338,12 +338,12 @@ int kvm_register_vgic_device(unsigned long type)
 int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
                       struct vgic_reg_attr *reg_attr)
 {
-       int cpuid;
+       int cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
 
-       cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
-
-       reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
        reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+       reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
+       if (!reg_attr->vcpu)
+               return -EINVAL;
 
        return 0;
 }
index 122021f9bdfc87c3c9634d6801edad7845b9f96e..13eac43c632dfe793912ba310f7449d59e3bd9ed 100644 (file)
@@ -1844,15 +1844,15 @@ static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
 
        emit_call(enter_prog, ctx);
 
+       /* save return value to callee saved register x20 */
+       emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
+
        /* if (__bpf_prog_enter(prog) == 0)
         *         goto skip_exec_of_prog;
         */
        branch = ctx->image + ctx->idx;
        emit(A64_NOP, ctx);
 
-       /* save return value to callee saved register x20 */
-       emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
-
        emit(A64_ADD_I(1, A64_R(0), A64_SP, args_off), ctx);
        if (!p->jited)
                emit_addr_mov_i64(A64_R(1), (const u64)p->insnsi, ctx);
index a5f300ec6f2808b8890ebc27d0de8a918eaa8636..54ad04dacdee94d869b2bd7d0ab92a92e60fe642 100644 (file)
@@ -595,7 +595,7 @@ config ARCH_SELECTS_CRASH_DUMP
        select RELOCATABLE
 
 config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION
-       def_bool CRASH_CORE
+       def_bool CRASH_RESERVE
 
 config RELOCATABLE
        bool "Relocatable kernel"
diff --git a/arch/loongarch/include/asm/crash_core.h b/arch/loongarch/include/asm/crash_core.h
deleted file mode 100644 (file)
index 218bdbf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef _LOONGARCH_CRASH_CORE_H
-#define _LOONGARCH_CRASH_CORE_H
-
-#define CRASH_ALIGN                    SZ_2M
-
-#define CRASH_ADDR_LOW_MAX             SZ_4G
-#define CRASH_ADDR_HIGH_MAX            memblock_end_of_DRAM()
-
-extern phys_addr_t memblock_end_of_DRAM(void);
-
-#endif
diff --git a/arch/loongarch/include/asm/crash_reserve.h b/arch/loongarch/include/asm/crash_reserve.h
new file mode 100644 (file)
index 0000000..a1d9b84
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _LOONGARCH_CRASH_RESERVE_H
+#define _LOONGARCH_CRASH_RESERVE_H
+
+#define CRASH_ALIGN                    SZ_2M
+
+#define CRASH_ADDR_LOW_MAX             SZ_4G
+#define CRASH_ADDR_HIGH_MAX            memblock_end_of_DRAM()
+
+extern phys_addr_t memblock_end_of_DRAM(void);
+
+#endif
index 2a35a0bc2aaabf128cb5336d25dcbec1738d646b..52b638059e40b31645a62243e467c09e7d7ce0cf 100644 (file)
@@ -7,6 +7,14 @@
 #ifndef __LOONGARCH_PERF_EVENT_H__
 #define __LOONGARCH_PERF_EVENT_H__
 
+#include <asm/ptrace.h>
+
 #define perf_arch_bpf_user_pt_regs(regs) (struct user_pt_regs *)regs
 
+#define perf_arch_fetch_caller_regs(regs, __ip) { \
+       (regs)->csr_era = (__ip); \
+       (regs)->regs[3] = current_stack_pointer; \
+       (regs)->regs[22] = (unsigned long) __builtin_frame_address(0); \
+}
+
 #endif /* __LOONGARCH_PERF_EVENT_H__ */
index da7a3b5b9374aeaf8bc1009d49d3ee0265938e9e..e071f5e9e85802b2117ba89ce86e4ca3219864d2 100644 (file)
@@ -132,8 +132,6 @@ static __always_inline void invtlb_all(u32 op, u32 info, u64 addr)
                );
 }
 
-#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
-
 static void tlb_flush(struct mmu_gather *tlb);
 
 #define tlb_flush tlb_flush
index 0491bf453cd49601c4f8b7b35565ea4a2b83c689..cac7cba81b65f791cf5d3379dfda2daca01814ec 100644 (file)
@@ -884,4 +884,4 @@ static int __init init_hw_perf_events(void)
 
        return 0;
 }
-early_initcall(init_hw_perf_events);
+pure_initcall(init_hw_perf_events);
index 1fc2f6813ea027d43ccf24af8aade31f1093df62..97b40defde060846d95c9bc02c70b13ec53372a7 100644 (file)
@@ -202,10 +202,10 @@ good_area:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        } else {
-               if (!(vma->vm_flags & VM_READ) && address != exception_era(regs))
-                       goto bad_area;
                if (!(vma->vm_flags & VM_EXEC) && address == exception_era(regs))
                        goto bad_area;
+               if (!(vma->vm_flags & (VM_READ | VM_WRITE)) && address != exception_era(regs))
+                       goto bad_area;
        }
 
        /*
index 23b77027c91637d0ef05e9952ebc1e72f7c24aa3..7a84069759b032dc61c2545773550417bf177d64 100644 (file)
@@ -44,9 +44,8 @@
 #define PLPKS_MAX_DATA_SIZE            4000
 
 // Timeouts for PLPKS operations
-#define PLPKS_MAX_TIMEOUT              5000 // msec
-#define PLPKS_FLUSH_SLEEP              10 // msec
-#define PLPKS_FLUSH_SLEEP_RANGE                400
+#define PLPKS_MAX_TIMEOUT              (5 * USEC_PER_SEC)
+#define PLPKS_FLUSH_SLEEP              10000 // usec
 
 struct plpks_var {
        char *component;
index e8c4129697b142ba48490481ee38793086e8425a..b1e6d275cda9ebaa7fa4659905691348d17faa75 100644 (file)
@@ -786,8 +786,16 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
         * parent bus. During reboot, there will be ibm,dma-window property to
         * define DMA window. For kdump, there will at least be default window or DDW
         * or both.
+        * There is an exception to the above. In case the PE goes into frozen
+        * state, firmware may not provide ibm,dma-window property at the time
+        * of LPAR boot up.
         */
 
+       if (!pdn) {
+               pr_debug("  no ibm,dma-window property !\n");
+               return;
+       }
+
        ppci = PCI_DN(pdn);
 
        pr_debug("  parent is %pOF, iommu_table: 0x%p\n",
index febe18f251d0cfb360a6330e4d0932e6941ae75e..4a595493d28ae3b808db8394e02c2b85b600b417 100644 (file)
@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label,
                        break;
                }
 
-               usleep_range(PLPKS_FLUSH_SLEEP,
-                            PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
+               fsleep(PLPKS_FLUSH_SLEEP);
                timeout = timeout + PLPKS_FLUSH_SLEEP;
        } while (timeout < PLPKS_MAX_TIMEOUT);
 
@@ -464,9 +463,10 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags)
 
                continuetoken = retbuf[0];
                if (pseries_status_to_err(rc) == -EBUSY) {
-                       int delay_ms = get_longbusy_msecs(rc);
-                       mdelay(delay_ms);
-                       timeout += delay_ms;
+                       int delay_us = get_longbusy_msecs(rc) * 1000;
+
+                       fsleep(delay_us);
+                       timeout += delay_us;
                }
                rc = pseries_status_to_err(rc);
        } while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT);
index 910ba8837add866f622fba84f7c0c3535ee175e6..2acc7d876e1fb6aa5dc14ad3c3150f587ba1edea 100644 (file)
@@ -82,14 +82,14 @@ config ERRATA_THEAD
 
          Otherwise, please say "N" here to avoid unnecessary overhead.
 
-config ERRATA_THEAD_PBMT
-       bool "Apply T-Head memory type errata"
+config ERRATA_THEAD_MAE
+       bool "Apply T-Head's memory attribute extension (XTheadMae) errata"
        depends on ERRATA_THEAD && 64BIT && MMU
        select RISCV_ALTERNATIVE_EARLY
        default y
        help
-         This will apply the memory type errata to handle the non-standard
-         memory type bits in page-table-entries on T-Head SoCs.
+         This will apply the memory attribute extension errata to handle the
+         non-standard PTE utilization on T-Head SoCs (XTheadMae).
 
          If you don't know what to do here, say "Y".
 
index b1c410bbc1aece3c1fe0bea8cbd68271c8c0e29a..bf6a0a6318ee307085c3cc04c4056a0b63a000e9 100644 (file)
 #include <asm/patch.h>
 #include <asm/vendorid_list.h>
 
-static bool errata_probe_pbmt(unsigned int stage,
-                             unsigned long arch_id, unsigned long impid)
+#define CSR_TH_SXSTATUS                0x5c0
+#define SXSTATUS_MAEE          _AC(0x200000, UL)
+
+static bool errata_probe_mae(unsigned int stage,
+                            unsigned long arch_id, unsigned long impid)
 {
-       if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PBMT))
+       if (!IS_ENABLED(CONFIG_ERRATA_THEAD_MAE))
                return false;
 
        if (arch_id != 0 || impid != 0)
                return false;
 
-       if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
-           stage == RISCV_ALTERNATIVES_MODULE)
-               return true;
+       if (stage != RISCV_ALTERNATIVES_EARLY_BOOT &&
+           stage != RISCV_ALTERNATIVES_MODULE)
+               return false;
+
+       if (!(csr_read(CSR_TH_SXSTATUS) & SXSTATUS_MAEE))
+               return false;
 
-       return false;
+       return true;
 }
 
 /*
@@ -140,8 +146,8 @@ static u32 thead_errata_probe(unsigned int stage,
 {
        u32 cpu_req_errata = 0;
 
-       if (errata_probe_pbmt(stage, archid, impid))
-               cpu_req_errata |= BIT(ERRATA_THEAD_PBMT);
+       if (errata_probe_mae(stage, archid, impid))
+               cpu_req_errata |= BIT(ERRATA_THEAD_MAE);
 
        errata_probe_cmo(stage, archid, impid);
 
index 1f2dbfb8a8bfc8c9f5d46b9129c26756941c4918..efd851e1b48321e1f098008ce8fe7755ab49339d 100644 (file)
@@ -23,7 +23,7 @@
 #endif
 
 #ifdef CONFIG_ERRATA_THEAD
-#define        ERRATA_THEAD_PBMT 0
+#define        ERRATA_THEAD_MAE 0
 #define        ERRATA_THEAD_PMU 1
 #define        ERRATA_THEAD_NUMBER 2
 #endif
@@ -53,20 +53,20 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID,    \
  * in the default case.
  */
 #define ALT_SVPBMT_SHIFT 61
-#define ALT_THEAD_PBMT_SHIFT 59
+#define ALT_THEAD_MAE_SHIFT 59
 #define ALT_SVPBMT(_val, prot)                                         \
 asm(ALTERNATIVE_2("li %0, 0\t\nnop",                                   \
                  "li %0, %1\t\nslli %0,%0,%3", 0,                      \
                        RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,  \
                  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,        \
-                       ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)    \
+                       ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE)      \
                : "=r"(_val)                                            \
                : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),               \
-                 "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),            \
+                 "I"(prot##_THEAD >> ALT_THEAD_MAE_SHIFT),             \
                  "I"(ALT_SVPBMT_SHIFT),                                \
-                 "I"(ALT_THEAD_PBMT_SHIFT))
+                 "I"(ALT_THEAD_MAE_SHIFT))
 
-#ifdef CONFIG_ERRATA_THEAD_PBMT
+#ifdef CONFIG_ERRATA_THEAD_MAE
 /*
  * IO/NOCACHE memory types are handled together with svpbmt,
  * so on T-Head chips, check if no other memory type is set,
@@ -83,11 +83,11 @@ asm volatile(ALTERNATIVE(                                           \
        "slli    t3, t3, %3\n\t"                                        \
        "or      %0, %0, t3\n\t"                                        \
        "2:",  THEAD_VENDOR_ID,                                         \
-               ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)            \
+               ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE)              \
        : "+r"(_val)                                                    \
-       : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT),              \
-         "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT),                 \
-         "I"(ALT_THEAD_PBMT_SHIFT)                                     \
+       : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_MAE_SHIFT),               \
+         "I"(_PAGE_PMA_THEAD >> ALT_THEAD_MAE_SHIFT),                  \
+         "I"(ALT_THEAD_MAE_SHIFT)                                      \
        : "t3")
 #else
 #define ALT_THEAD_PMA(_val)
index 2947423b5082e9b7f69b25a347685af499258161..115ac98b8d729da4e8f07f0f8f44e27438be107f 100644 (file)
@@ -89,7 +89,7 @@ typedef struct page *pgtable_t;
 #define PTE_FMT "%08lx"
 #endif
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
 /*
  * We override this value as its generic definition uses __pa too early in
  * the boot process (before kernel_map.va_pa_offset is set).
index 9f8ea0e33eb10424c5a05eb55849eacce627c3c3..6afd6bb4882eb28d1f1e96e451c7c92c20a6d2cc 100644 (file)
@@ -896,7 +896,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
 #define PAGE_SHARED            __pgprot(0)
 #define PAGE_KERNEL            __pgprot(0)
 #define swapper_pg_dir         NULL
-#define TASK_SIZE              0xffffffffUL
+#define TASK_SIZE              _AC(-1, UL)
 #define VMALLOC_START          _AC(0, UL)
 #define VMALLOC_END            TASK_SIZE
 
index 9f2a8e3ff2048e78201e188a5fc832a67429a06c..2902f68dc913aa620996da70d9b9bad39a133c2c 100644 (file)
@@ -54,7 +54,7 @@ struct riscv_hwprobe {
 #define                RISCV_HWPROBE_EXT_ZFHMIN        (1 << 28)
 #define                RISCV_HWPROBE_EXT_ZIHINTNTL     (1 << 29)
 #define                RISCV_HWPROBE_EXT_ZVFH          (1 << 30)
-#define                RISCV_HWPROBE_EXT_ZVFHMIN       (1 << 31)
+#define                RISCV_HWPROBE_EXT_ZVFHMIN       (1ULL << 31)
 #define                RISCV_HWPROBE_EXT_ZFA           (1ULL << 32)
 #define                RISCV_HWPROBE_EXT_ZTSO          (1ULL << 33)
 #define                RISCV_HWPROBE_EXT_ZACAS         (1ULL << 34)
index fe8e159394d8eeeeab34f83ae97ffadbec979b77..9687618432031fec77907d1c15fad0b9a3cc4c0a 100644 (file)
@@ -231,7 +231,7 @@ static void __init setup_bootmem(void)
         * In 64-bit, any use of __va/__pa before this point is wrong as we
         * did not know the start of DRAM before.
         */
-       if (IS_ENABLED(CONFIG_64BIT))
+       if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU))
                kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base;
 
        /*
index 1adf2f39ce59cbb691b7f89ae9fc7a5127642ca4..ec9d692838fca54ee445d10ab3d862130338cd3b 100644 (file)
@@ -722,6 +722,9 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
        if (ret)
                return ret;
 
+       /* store prog start time */
+       emit_mv(RV_REG_S1, RV_REG_A0, ctx);
+
        /* if (__bpf_prog_enter(prog) == 0)
         *      goto skip_exec_of_prog;
         */
@@ -729,9 +732,6 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
        /* nop reserved for conditional jump */
        emit(rv_nop(), ctx);
 
-       /* store prog start time */
-       emit_mv(RV_REG_S1, RV_REG_A0, ctx);
-
        /* arg1: &args_off */
        emit_addi(RV_REG_A0, RV_REG_FP, -args_off, ctx);
        if (!p->jited)
index 99f7e1f2b70aff61da33cc06bc0e7455394150a8..99ea3f12c5d2ab2990c06b73602a3c513f361f7f 100644 (file)
@@ -125,8 +125,19 @@ struct s390_pxts_ctx {
 static inline int __paes_keyblob2pkey(struct key_blob *kb,
                                     struct pkey_protkey *pk)
 {
-       return pkey_keyblob2pkey(kb->key, kb->keylen,
-                                pk->protkey, &pk->len, &pk->type);
+       int i, ret = -EIO;
+
+       /* try three times in case of busy card */
+       for (i = 0; ret && i < 3; i++) {
+               if (ret == -EBUSY && in_task()) {
+                       if (msleep_interruptible(1000))
+                               return -EINTR;
+               }
+               ret = pkey_keyblob2pkey(kb->key, kb->keylen,
+                                       pk->protkey, &pk->len, &pk->type);
+       }
+
+       return ret;
 }
 
 static inline int __paes_convert_key(struct s390_paes_ctx *ctx)
index 4f21ae561e4ddc7af7bc7a21f848f0fe4315ab59..390906b8e386e609f760d891484133b1c0fbea79 100644 (file)
@@ -9,6 +9,7 @@
 #define CFI_DEF_CFA_OFFSET     .cfi_def_cfa_offset
 #define CFI_ADJUST_CFA_OFFSET  .cfi_adjust_cfa_offset
 #define CFI_RESTORE            .cfi_restore
+#define CFI_REL_OFFSET         .cfi_rel_offset
 
 #ifdef CONFIG_AS_CFI_VAL_OFFSET
 #define CFI_VAL_OFFSET         .cfi_val_offset
index 57f62596e53b958a2737f23f1985e5154179fd9e..85247ef5a41b89a390d3290cefb785c6c5a81ad6 100644 (file)
@@ -24,8 +24,10 @@ __kernel_\func:
        CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE)
        CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
        stg     %r14,STACK_FRAME_OVERHEAD(%r15)
+       CFI_REL_OFFSET 14, STACK_FRAME_OVERHEAD
        brasl   %r14,__s390_vdso_\func
        lg      %r14,STACK_FRAME_OVERHEAD(%r15)
+       CFI_RESTORE 14
        aghi    %r15,WRAPPER_FRAME_SIZE
        CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
        CFI_RESTORE 15
index 094b43b121cd5d8d8895af0f1c830ab5cfb1d355..12d22a7fa32fd27a97d111f7d36971ecc7461bf5 100644 (file)
@@ -2661,7 +2661,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr,
                return 0;
 
        start = pmd_val(*pmd) & HPAGE_MASK;
-       end = start + HPAGE_SIZE - 1;
+       end = start + HPAGE_SIZE;
        __storage_key_init_range(start, end);
        set_bit(PG_arch_1, &page->flags);
        cond_resched();
index c2e8242bd15dd0afb6454e9e71e9ca5ef969ba13..dc3db86e13ffb8c14ca607c6df86ede9d3cf6262 100644 (file)
@@ -139,7 +139,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
        }
 
        if (!test_and_set_bit(PG_arch_1, &page->flags))
-               __storage_key_init_range(paddr, paddr + size - 1);
+               __storage_key_init_range(paddr, paddr + size);
 }
 
 void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
index 4474bf32d0a4970daec7fad3f12f8aa4a9e43871..928820e61cb5020a1eeb3bcc99b0a72227ae6c82 100644 (file)
@@ -62,6 +62,7 @@ config X86
        select ACPI_HOTPLUG_CPU                 if ACPI_PROCESSOR && HOTPLUG_CPU
        select ARCH_32BIT_OFF_T                 if X86_32
        select ARCH_CLOCKSOURCE_INIT
+       select ARCH_CONFIGURES_CPU_MITIGATIONS
        select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
        select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
        select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
@@ -2488,17 +2489,21 @@ config PREFIX_SYMBOLS
        def_bool y
        depends on CALL_PADDING && !CFI_CLANG
 
-menuconfig SPECULATION_MITIGATIONS
-       bool "Mitigations for speculative execution vulnerabilities"
+menuconfig CPU_MITIGATIONS
+       bool "Mitigations for CPU vulnerabilities"
        default y
        help
-         Say Y here to enable options which enable mitigations for
-         speculative execution hardware vulnerabilities.
+         Say Y here to enable options which enable mitigations for hardware
+         vulnerabilities (usually related to speculative execution).
+         Mitigations can be disabled or restricted to SMT systems at runtime
+         via the "mitigations" kernel parameter.
 
-         If you say N, all mitigations will be disabled. You really
-         should know what you are doing to say so.
+         If you say N, all mitigations will be disabled.  This CANNOT be
+         overridden at runtime.
 
-if SPECULATION_MITIGATIONS
+         Say 'Y', unless you really know what you are doing.
+
+if CPU_MITIGATIONS
 
 config MITIGATION_PAGE_TABLE_ISOLATION
        bool "Remove the kernel mapping in user mode"
index a3c0df11d0e6d8c36db77b59077fef711724b2db..2fb7d53cf3338d3c390fa1fe2f000cc622b3af03 100644 (file)
@@ -98,11 +98,6 @@ static int addr_to_vsyscall_nr(unsigned long addr)
 
 static bool write_ok_or_segv(unsigned long ptr, size_t size)
 {
-       /*
-        * XXX: if access_ok, get_user, and put_user handled
-        * sig_on_uaccess_err, this could go away.
-        */
-
        if (!access_ok((void __user *)ptr, size)) {
                struct thread_struct *thread = &current->thread;
 
@@ -120,10 +115,8 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
 bool emulate_vsyscall(unsigned long error_code,
                      struct pt_regs *regs, unsigned long address)
 {
-       struct task_struct *tsk;
        unsigned long caller;
        int vsyscall_nr, syscall_nr, tmp;
-       int prev_sig_on_uaccess_err;
        long ret;
        unsigned long orig_dx;
 
@@ -172,8 +165,6 @@ bool emulate_vsyscall(unsigned long error_code,
                goto sigsegv;
        }
 
-       tsk = current;
-
        /*
         * Check for access_ok violations and find the syscall nr.
         *
@@ -234,12 +225,8 @@ bool emulate_vsyscall(unsigned long error_code,
                goto do_ret;  /* skip requested */
 
        /*
-        * With a real vsyscall, page faults cause SIGSEGV.  We want to
-        * preserve that behavior to make writing exploits harder.
+        * With a real vsyscall, page faults cause SIGSEGV.
         */
-       prev_sig_on_uaccess_err = current->thread.sig_on_uaccess_err;
-       current->thread.sig_on_uaccess_err = 1;
-
        ret = -EFAULT;
        switch (vsyscall_nr) {
        case 0:
@@ -262,23 +249,12 @@ bool emulate_vsyscall(unsigned long error_code,
                break;
        }
 
-       current->thread.sig_on_uaccess_err = prev_sig_on_uaccess_err;
-
 check_fault:
        if (ret == -EFAULT) {
                /* Bad news -- userspace fed a bad pointer to a vsyscall. */
                warn_bad_vsyscall(KERN_INFO, regs,
                                  "vsyscall fault (exploit attempt?)");
-
-               /*
-                * If we failed to generate a signal for any reason,
-                * generate one here.  (This should be impossible.)
-                */
-               if (WARN_ON_ONCE(!sigismember(&tsk->pending.signal, SIGBUS) &&
-                                !sigismember(&tsk->pending.signal, SIGSEGV)))
-                       goto sigsegv;
-
-               return true;  /* Don't emulate the ret. */
+               goto sigsegv;
        }
 
        regs->ax = ret;
index c086699b0d0c59fc62834bb457963f1b81b541d3..aa6c8f8ca9588e90894750ce4f93226c05af9c23 100644 (file)
@@ -25,6 +25,7 @@ u64 cc_mkdec(u64 val);
 void cc_random_init(void);
 #else
 #define cc_vendor (CC_VENDOR_NONE)
+static const u64 cc_mask = 0;
 
 static inline u64 cc_mkenc(u64 val)
 {
index e8f58ddd06d97fbce6ef1f701f9f91766ef2847d..2e74a7f0e93575c3aa4180dc9ad4a9728f07700d 100644 (file)
@@ -17,6 +17,7 @@ extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
 extern void e820__range_add   (u64 start, u64 size, enum e820_type type);
 extern u64  e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
 extern u64  e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type);
+extern u64  e820__range_update_table(struct e820_table *t, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
 
 extern void e820__print_table(char *who);
 extern int  e820__update_table(struct e820_table *table);
index 0b748ee16b3d94ea09516ee14e187dbebae0bf4a..9abb8cc4cd4747f4982655d425df997852b1553b 100644 (file)
 #define _COMMON_PAGE_CHG_MASK  (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \
                                 _PAGE_SPECIAL | _PAGE_ACCESSED |       \
                                 _PAGE_DIRTY_BITS | _PAGE_SOFT_DIRTY |  \
-                                _PAGE_DEVMAP | _PAGE_ENC | _PAGE_UFFD_WP)
+                                _PAGE_DEVMAP | _PAGE_CC | _PAGE_UFFD_WP)
 #define _PAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PAT)
 #define _HPAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PSE | _PAGE_PAT_LARGE)
 
@@ -173,6 +173,7 @@ enum page_cache_mode {
 };
 #endif
 
+#define _PAGE_CC               (_AT(pteval_t, cc_mask))
 #define _PAGE_ENC              (_AT(pteval_t, sme_me_mask))
 
 #define _PAGE_CACHE_MASK       (_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)
index 811548f131f4e30418bedfdf98f1f302fc06723d..78e51b0d6433d6685c725b558bdd578c8ca4d6e8 100644 (file)
@@ -472,7 +472,6 @@ struct thread_struct {
        unsigned long           iopl_emul;
 
        unsigned int            iopl_warn:1;
-       unsigned int            sig_on_uaccess_err:1;
 
        /*
         * Protection Keys Register for Userspace.  Loaded immediately on
index 7f57382afee41754beb8164244f199e4ac30a148..93ed60080cfe7b58dc0349ab34fdb7e5704abd81 100644 (file)
@@ -269,6 +269,7 @@ int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immut
 int rmp_make_shared(u64 pfn, enum pg_level level);
 void snp_leak_pages(u64 pfn, unsigned int npages);
 void kdump_sev_callback(void);
+void snp_fixup_e820_tables(void);
 #else
 static inline bool snp_probe_rmptable_info(void) { return false; }
 static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
@@ -282,6 +283,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
 static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
 static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
 static inline void kdump_sev_callback(void) { }
+static inline void snp_fixup_e820_tables(void) {}
 #endif
 
 #endif
index c342c4aa9c6848c607238dad1ff07105737d5873..803dcfb0e3469c6393a81e0ada1675ea56451eb7 100644 (file)
@@ -1771,7 +1771,7 @@ void x2apic_setup(void)
        __x2apic_enable();
 }
 
-static __init void apic_set_fixmap(void);
+static __init void apic_set_fixmap(bool read_apic);
 
 static __init void x2apic_disable(void)
 {
@@ -1793,7 +1793,12 @@ static __init void x2apic_disable(void)
        }
 
        __x2apic_disable();
-       apic_set_fixmap();
+       /*
+        * Don't reread the APIC ID as it was already done from
+        * check_x2apic() and the APIC driver still is a x2APIC variant,
+        * which fails to do the read after x2APIC was disabled.
+        */
+       apic_set_fixmap(false);
 }
 
 static __init void x2apic_enable(void)
@@ -2057,13 +2062,14 @@ void __init init_apic_mappings(void)
        }
 }
 
-static __init void apic_set_fixmap(void)
+static __init void apic_set_fixmap(bool read_apic)
 {
        set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
        apic_mmio_base = APIC_BASE;
        apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
                    apic_mmio_base, mp_lapic_addr);
-       apic_read_boot_cpu_id(false);
+       if (read_apic)
+               apic_read_boot_cpu_id(false);
 }
 
 void __init register_lapic_address(unsigned long address)
@@ -2073,7 +2079,7 @@ void __init register_lapic_address(unsigned long address)
        mp_lapic_addr = address;
 
        if (!x2apic_mode)
-               apic_set_fixmap();
+               apic_set_fixmap(true);
 }
 
 /*
index cb9eece55904d049edc600960bdaa0db58765459..307302af0aeee22d0f3871d06ee117bd6c82818d 100644 (file)
@@ -459,8 +459,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
 
        case 0x1a:
                switch (c->x86_model) {
-               case 0x00 ... 0x0f:
-               case 0x20 ... 0x2f:
+               case 0x00 ... 0x2f:
                case 0x40 ... 0x4f:
                case 0x70 ... 0x7f:
                        setup_force_cpu_cap(X86_FEATURE_ZEN5);
index 6f1b379e3b3851bbef0b66945563076b8cde40c0..68b09f718f10e47b9efa59e017d7c1558be7f273 100644 (file)
@@ -532,9 +532,10 @@ u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum
        return __e820__range_update(e820_table, start, size, old_type, new_type);
 }
 
-static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type  new_type)
+u64 __init e820__range_update_table(struct e820_table *t, u64 start, u64 size,
+                                   enum e820_type old_type, enum e820_type new_type)
 {
-       return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
+       return __e820__range_update(t, start, size, old_type, new_type);
 }
 
 /* Remove a range of memory from the E820 table: */
@@ -806,7 +807,7 @@ u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
 
        addr = memblock_phys_alloc(size, align);
        if (addr) {
-               e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
+               e820__range_update_table(e820_table_kexec, addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
                pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n");
                e820__update_table_kexec();
        }
index 7062b84dd467d62ac1aed8c4fe4bdb86d5a7ac61..6d3d20e3e43a9b005f725d1e89dcc8fd81560dcd 100644 (file)
@@ -139,7 +139,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
                       log_lvl, d3, d6, d7);
        }
 
-       if (cpu_feature_enabled(X86_FEATURE_OSPKE))
+       if (cr4 & X86_CR4_PKE)
                printk("%sPKRU: %08x\n", log_lvl, read_pkru());
 }
 
index 8b04958da5e7d6c4bd096cffdaa4874e73433846..b4f8fa0f722cd6749079ba81d69458200c5051bb 100644 (file)
@@ -1203,12 +1203,14 @@ static enum es_result vc_check_opcode_bytes(struct es_em_ctxt *ctxt,
                break;
 
        case SVM_EXIT_MONITOR:
-               if (opcode == 0x010f && modrm == 0xc8)
+               /* MONITOR and MONITORX instructions generate the same error code */
+               if (opcode == 0x010f && (modrm == 0xc8 || modrm == 0xfa))
                        return ES_OK;
                break;
 
        case SVM_EXIT_MWAIT:
-               if (opcode == 0x010f && modrm == 0xc9)
+               /* MWAIT and MWAITX instructions generate the same error code */
+               if (opcode == 0x010f && (modrm == 0xc9 || modrm == 0xfb))
                        return ES_OK;
                break;
 
index 622d12ec7f08518ba6701c33efd74d5f77545806..bba4e020dd646cc257056fa05ece3ccdc24ae560 100644 (file)
@@ -723,39 +723,8 @@ kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code,
        WARN_ON_ONCE(user_mode(regs));
 
        /* Are we prepared to handle this kernel fault? */
-       if (fixup_exception(regs, X86_TRAP_PF, error_code, address)) {
-               /*
-                * Any interrupt that takes a fault gets the fixup. This makes
-                * the below recursive fault logic only apply to a faults from
-                * task context.
-                */
-               if (in_interrupt())
-                       return;
-
-               /*
-                * Per the above we're !in_interrupt(), aka. task context.
-                *
-                * In this case we need to make sure we're not recursively
-                * faulting through the emulate_vsyscall() logic.
-                */
-               if (current->thread.sig_on_uaccess_err && signal) {
-                       sanitize_error_code(address, &error_code);
-
-                       set_signal_archinfo(address, error_code);
-
-                       if (si_code == SEGV_PKUERR) {
-                               force_sig_pkuerr((void __user *)address, pkey);
-                       } else {
-                               /* XXX: hwpoison faults will set the wrong code. */
-                               force_sig_fault(signal, si_code, (void __user *)address);
-                       }
-               }
-
-               /*
-                * Barring that, we can do the fixup and be happy.
-                */
+       if (fixup_exception(regs, X86_TRAP_PF, error_code, address))
                return;
-       }
 
        /*
         * AMD erratum #91 manifests as a spurious page fault on a PREFETCH
index 6f3b3e028718556667c1d86e8f56442eafc78dcc..0a120d85d7bba88b33c59b97f9109a6acde727cd 100644 (file)
@@ -102,6 +102,13 @@ void __init mem_encrypt_setup_arch(void)
        phys_addr_t total_mem = memblock_phys_mem_size();
        unsigned long size;
 
+       /*
+        * Do RMP table fixups after the e820 tables have been setup by
+        * e820__memory_setup().
+        */
+       if (cc_platform_has(CC_ATTR_HOST_SEV_SNP))
+               snp_fixup_e820_tables();
+
        if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
                return;
 
index df5fac428408fe65ecc03766def03e0959bc539a..59cbc94b6e6903d915d9b16b04e82f269c88754b 100644 (file)
@@ -1807,36 +1807,41 @@ populate_extable:
                        if (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
                            BPF_MODE(insn->code) == BPF_PROBE_MEMSX) {
                                /* Conservatively check that src_reg + insn->off is a kernel address:
-                                *   src_reg + insn->off >= TASK_SIZE_MAX + PAGE_SIZE
-                                * src_reg is used as scratch for src_reg += insn->off and restored
-                                * after emit_ldx if necessary
+                                *   src_reg + insn->off > TASK_SIZE_MAX + PAGE_SIZE
+                                *   and
+                                *   src_reg + insn->off < VSYSCALL_ADDR
                                 */
 
-                               u64 limit = TASK_SIZE_MAX + PAGE_SIZE;
+                               u64 limit = TASK_SIZE_MAX + PAGE_SIZE - VSYSCALL_ADDR;
                                u8 *end_of_jmp;
 
-                               /* At end of these emitted checks, insn->off will have been added
-                                * to src_reg, so no need to do relative load with insn->off offset
-                                */
-                               insn_off = 0;
+                               /* movabsq r10, VSYSCALL_ADDR */
+                               emit_mov_imm64(&prog, BPF_REG_AX, (long)VSYSCALL_ADDR >> 32,
+                                              (u32)(long)VSYSCALL_ADDR);
 
-                               /* movabsq r11, limit */
-                               EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG));
-                               EMIT((u32)limit, 4);
-                               EMIT(limit >> 32, 4);
+                               /* mov src_reg, r11 */
+                               EMIT_mov(AUX_REG, src_reg);
 
                                if (insn->off) {
-                                       /* add src_reg, insn->off */
-                                       maybe_emit_1mod(&prog, src_reg, true);
-                                       EMIT2_off32(0x81, add_1reg(0xC0, src_reg), insn->off);
+                                       /* add r11, insn->off */
+                                       maybe_emit_1mod(&prog, AUX_REG, true);
+                                       EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off);
                                }
 
-                               /* cmp src_reg, r11 */
-                               maybe_emit_mod(&prog, src_reg, AUX_REG, true);
-                               EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG));
+                               /* sub r11, r10 */
+                               maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true);
+                               EMIT2(0x29, add_2reg(0xC0, AUX_REG, BPF_REG_AX));
+
+                               /* movabsq r10, limit */
+                               emit_mov_imm64(&prog, BPF_REG_AX, (long)limit >> 32,
+                                              (u32)(long)limit);
+
+                               /* cmp r10, r11 */
+                               maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true);
+                               EMIT2(0x39, add_2reg(0xC0, AUX_REG, BPF_REG_AX));
 
-                               /* if unsigned '>=', goto load */
-                               EMIT2(X86_JAE, 0);
+                               /* if unsigned '>', goto load */
+                               EMIT2(X86_JA, 0);
                                end_of_jmp = prog;
 
                                /* xor dst_reg, dst_reg */
@@ -1862,18 +1867,6 @@ populate_extable:
                                /* populate jmp_offset for JMP above */
                                start_of_ldx[-1] = prog - start_of_ldx;
 
-                               if (insn->off && src_reg != dst_reg) {
-                                       /* sub src_reg, insn->off
-                                        * Restore src_reg after "add src_reg, insn->off" in prev
-                                        * if statement. But if src_reg == dst_reg, emit_ldx
-                                        * above already clobbered src_reg, so no need to restore.
-                                        * If add src_reg, insn->off was unnecessary, no need to
-                                        * restore either.
-                                        */
-                                       maybe_emit_1mod(&prog, src_reg, true);
-                                       EMIT2_off32(0x81, add_1reg(0xE8, src_reg), insn->off);
-                               }
-
                                if (!bpf_prog->aux->extable)
                                        break;
 
@@ -3473,3 +3466,9 @@ bool bpf_jit_supports_ptr_xchg(void)
 {
        return true;
 }
+
+/* x86-64 JIT emits its own code to filter user addresses so return 0 here */
+u64 bpf_arch_uaddress_limit(void)
+{
+       return 0;
+}
index ab0e8448bb6eb2bfbc4fab29321cd0ddbe876f7e..0ae10535c699982e15f20026a3e8012e52c41f32 100644 (file)
@@ -163,6 +163,42 @@ bool snp_probe_rmptable_info(void)
        return true;
 }
 
+static void __init __snp_fixup_e820_tables(u64 pa)
+{
+       if (IS_ALIGNED(pa, PMD_SIZE))
+               return;
+
+       /*
+        * Handle cases where the RMP table placement by the BIOS is not
+        * 2M aligned and the kexec kernel could try to allocate
+        * from within that chunk which then causes a fatal RMP fault.
+        *
+        * The e820_table needs to be updated as it is converted to
+        * kernel memory resources and used by KEXEC_FILE_LOAD syscall
+        * to load kexec segments.
+        *
+        * The e820_table_firmware needs to be updated as it is exposed
+        * to sysfs and used by the KEXEC_LOAD syscall to load kexec
+        * segments.
+        *
+        * The e820_table_kexec needs to be updated as it passed to
+        * the kexec-ed kernel.
+        */
+       pa = ALIGN_DOWN(pa, PMD_SIZE);
+       if (e820__mapped_any(pa, pa + PMD_SIZE, E820_TYPE_RAM)) {
+               pr_info("Reserving start/end of RMP table on a 2MB boundary [0x%016llx]\n", pa);
+               e820__range_update(pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+               e820__range_update_table(e820_table_kexec, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+               e820__range_update_table(e820_table_firmware, pa, PMD_SIZE, E820_TYPE_RAM, E820_TYPE_RESERVED);
+       }
+}
+
+void __init snp_fixup_e820_tables(void)
+{
+       __snp_fixup_e820_tables(probed_rmp_base);
+       __snp_fixup_e820_tables(probed_rmp_base + probed_rmp_size);
+}
+
 /*
  * Do the necessary preparations which are verified by the firmware as
  * described in the SNP_INIT_EX firmware command description in the SNP
index ace2eb054053f95e53ac43992d9b778335e68748..9ba53814ed6a9e392b60c53477246977d649f20e 100644 (file)
@@ -219,13 +219,21 @@ static __read_mostly unsigned int cpuid_leaf5_edx_val;
 static void xen_cpuid(unsigned int *ax, unsigned int *bx,
                      unsigned int *cx, unsigned int *dx)
 {
-       unsigned maskebx = ~0;
+       unsigned int maskebx = ~0;
+       unsigned int or_ebx = 0;
 
        /*
         * Mask out inconvenient features, to try and disable as many
         * unsupported kernel subsystems as possible.
         */
        switch (*ax) {
+       case 0x1:
+               /* Replace initial APIC ID in bits 24-31 of EBX. */
+               /* See xen_pv_smp_config() for related topology preparations. */
+               maskebx = 0x00ffffff;
+               or_ebx = smp_processor_id() << 24;
+               break;
+
        case CPUID_MWAIT_LEAF:
                /* Synthesize the values.. */
                *ax = 0;
@@ -248,6 +256,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
                : "0" (*ax), "2" (*cx));
 
        *bx &= maskebx;
+       *bx |= or_ebx;
 }
 
 static bool __init xen_check_mwait(void)
index 27d1a5b7f571a3487cfa68a037e51516a6b9b287..ac41d83b38d3c49d3116dff58d5998a5fe9efb62 100644 (file)
@@ -154,9 +154,9 @@ static void __init xen_pv_smp_config(void)
        u32 apicid = 0;
        int i;
 
-       topology_register_boot_apic(apicid++);
+       topology_register_boot_apic(apicid);
 
-       for (i = 1; i < nr_cpu_ids; i++)
+       for (i = 0; i < nr_cpu_ids; i++)
                topology_register_apic(apicid++, CPU_ACPIID_INVALID, true);
 
        /* Pretend to be a proper enumerated system */
index 38bcecb0e457d9741c142cada4d38ec65ff0f88b..a2b6bb5429f5cb4c3c9694c9db6dbb8f6992d9fa 100644 (file)
@@ -100,6 +100,10 @@ void flush_cache_range(struct vm_area_struct*, ulong, ulong);
 void flush_icache_range(unsigned long start, unsigned long end);
 void flush_cache_page(struct vm_area_struct*,
                             unsigned long, unsigned long);
+#define flush_cache_all flush_cache_all
+#define flush_cache_range flush_cache_range
+#define flush_icache_range flush_icache_range
+#define flush_cache_page flush_cache_page
 #else
 #define flush_cache_all local_flush_cache_all
 #define flush_cache_range local_flush_cache_range
@@ -136,20 +140,7 @@ void local_flush_cache_page(struct vm_area_struct *vma,
 
 #else
 
-#define flush_cache_all()                              do { } while (0)
-#define flush_cache_mm(mm)                             do { } while (0)
-#define flush_cache_dup_mm(mm)                         do { } while (0)
-
-#define flush_cache_vmap(start,end)                    do { } while (0)
-#define flush_cache_vmap_early(start,end)              do { } while (0)
-#define flush_cache_vunmap(start,end)                  do { } while (0)
-
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)                                do { } while (0)
-
 #define flush_icache_range local_flush_icache_range
-#define flush_cache_page(vma, addr, pfn)               do { } while (0)
-#define flush_cache_range(vma, start, end)             do { } while (0)
 
 #endif
 
@@ -162,15 +153,14 @@ void local_flush_cache_page(struct vm_area_struct *vma,
                __invalidate_icache_range(start,(end) - (start));       \
        } while (0)
 
-#define flush_dcache_mmap_lock(mapping)                        do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)              do { } while (0)
-
 #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE)
 
 extern void copy_to_user_page(struct vm_area_struct*, struct page*,
                unsigned long, void*, const void*, unsigned long);
 extern void copy_from_user_page(struct vm_area_struct*, struct page*,
                unsigned long, void*, const void*, unsigned long);
+#define copy_to_user_page copy_to_user_page
+#define copy_from_user_page copy_from_user_page
 
 #else
 
@@ -186,4 +176,6 @@ extern void copy_from_user_page(struct vm_area_struct*, struct page*,
 
 #endif
 
+#include <asm-generic/cacheflush.h>
+
 #endif /* _XTENSA_CACHEFLUSH_H */
index d008a153a2b9f7a9782b5874643f2d5a3741e995..7ed1a2085bd72883025c7de7d0d028ab077cc56c 100644 (file)
 #define MAKE_RA_FOR_CALL(ra,ws)   (((ra) & 0x3fffffff) | (ws) << 30)
 
 /* Convert return address to a valid pc
- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ * Note: 'text' is the address within the same 1GB range as the ra
  */
-#define MAKE_PC_FROM_RA(ra,sp)    (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
+#define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000))
 
 #elif defined(__XTENSA_CALL0_ABI__)
 
 #define MAKE_RA_FOR_CALL(ra, ws)   (ra)
 
 /* Convert return address to a valid pc
- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ * Note: 'text' is not used as 'ra' is always the full address
  */
-#define MAKE_PC_FROM_RA(ra, sp)    (ra)
+#define MAKE_PC_FROM_RA(ra, text)  (ra)
 
 #else
 #error Unsupported Xtensa ABI
index a270467556dc84df2c6ceb0786acee3669a059f8..86c70117371bb7cc022b0793f0a4eb8ef834bc63 100644 (file)
@@ -87,7 +87,7 @@ struct pt_regs {
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
 # define instruction_pointer(regs) ((regs)->pc)
 # define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
-                                              (regs)->areg[1]))
+                                              (regs)->pc))
 
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
index a815577d25fd02f3b267359d923cb83aae512c3d..7bd66677f7b6de58d0a1bda1b414ebc622dce962 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/regs.h>
 #include <asm/hw_breakpoint.h>
+#include <asm/sections.h>
 #include <asm/traps.h>
 
 extern void ret_from_fork(void);
@@ -380,7 +381,7 @@ unsigned long __get_wchan(struct task_struct *p)
        int count = 0;
 
        sp = p->thread.sp;
-       pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
+       pc = MAKE_PC_FROM_RA(p->thread.ra, _text);
 
        do {
                if (sp < stack_page + sizeof(struct task_struct) ||
@@ -392,7 +393,7 @@ unsigned long __get_wchan(struct task_struct *p)
 
                /* Stack layout: sp-4: ra, sp-3: sp' */
 
-               pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp);
+               pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), _text);
                sp = SPILL_SLOT(sp, 1);
        } while (count++ < 16);
        return 0;
index 831ffb648bda7e160408fd97530eddee760c27fc..ed324fdf2a2f9124527a5514ce14ac731996a2ad 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/stacktrace.h>
 
 #include <asm/ftrace.h>
+#include <asm/sections.h>
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
 #include <linux/uaccess.h>
@@ -189,7 +190,7 @@ void walk_stackframe(unsigned long *sp,
                if (a1 <= (unsigned long)sp)
                        break;
 
-               frame.pc = MAKE_PC_FROM_RA(a0, a1);
+               frame.pc = MAKE_PC_FROM_RA(a0, _text);
                frame.sp = a1;
 
                if (fn(&frame, data))
index 8896e691c051eab87ba88ffcbac01bd4860df0de..abec44b687dff0d4da3a77307603a0866a35ce88 100644 (file)
@@ -166,10 +166,8 @@ late_initcall(rs_init);
 
 static void iss_console_write(struct console *co, const char *s, unsigned count)
 {
-       if (s && *s != 0) {
-               int len = strlen(s);
-               simc_write(1, s, count < len ? count : len);
-       }
+       if (s && *s != 0)
+               simc_write(1, s, min(count, strlen(s)));
 }
 
 static struct tty_driver* iss_console_device(struct console *c, int *index)
index 4dc94145eb533065f2ad4547c0b11e010dfe126a..da2a167a4d08b66fe26c99826a9e84277f76f0e3 100644 (file)
@@ -882,7 +882,7 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
                goto abort_claiming;
        ret = -EBUSY;
        if (!bdev_may_open(bdev, mode))
-               goto abort_claiming;
+               goto put_module;
        if (bdev_is_partition(bdev))
                ret = blkdev_get_part(bdev, mode);
        else
index 4bfbe55553f410119378fc3bbf8c73b9d6717a05..a40b6f3946efeb6b46fccd445053a5c48e069254 100644 (file)
@@ -170,8 +170,8 @@ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
 #define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width)
 
 /* Shift and apply the mask for CPC reads/writes */
-#define MASK_VAL(reg, val) ((val) >> ((reg)->bit_offset &                      \
-                                       GENMASK(((reg)->bit_width), 0)))
+#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) &                     \
+                                       GENMASK(((reg)->bit_width) - 1, 0))
 
 static ssize_t show_feedback_ctrs(struct kobject *kobj,
                struct kobj_attribute *attr, char *buf)
@@ -1002,14 +1002,14 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
        }
 
        *val = 0;
+       size = GET_BIT_WIDTH(reg);
 
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
-               u32 width = GET_BIT_WIDTH(reg);
                u32 val_u32;
                acpi_status status;
 
                status = acpi_os_read_port((acpi_io_address)reg->address,
-                                          &val_u32, width);
+                                          &val_u32, size);
                if (ACPI_FAILURE(status)) {
                        pr_debug("Error: Failed to read SystemIO port %llx\n",
                                 reg->address);
@@ -1018,17 +1018,22 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
 
                *val = val_u32;
                return 0;
-       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
+       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
+               /*
+                * For registers in PCC space, the register size is determined
+                * by the bit width field; the access size is used to indicate
+                * the PCC subspace id.
+                */
+               size = reg->bit_width;
                vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
+       }
        else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
                vaddr = reg_res->sys_mem_vaddr;
        else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
                return cpc_read_ffh(cpu, reg, val);
        else
                return acpi_os_read_memory((acpi_physical_address)reg->address,
-                               val, reg->bit_width);
-
-       size = GET_BIT_WIDTH(reg);
+                               val, size);
 
        switch (size) {
        case 8:
@@ -1044,8 +1049,13 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
                *val = readq_relaxed(vaddr);
                break;
        default:
-               pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
-                        reg->bit_width, pcc_ss_id);
+               if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+                       pr_debug("Error: Cannot read %u bit width from system memory: 0x%llx\n",
+                               size, reg->address);
+               } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+                       pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
+                               size, pcc_ss_id);
+               }
                return -EFAULT;
        }
 
@@ -1063,12 +1073,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
        int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
        struct cpc_reg *reg = &reg_res->cpc_entry.reg;
 
+       size = GET_BIT_WIDTH(reg);
+
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
-               u32 width = GET_BIT_WIDTH(reg);
                acpi_status status;
 
                status = acpi_os_write_port((acpi_io_address)reg->address,
-                                           (u32)val, width);
+                                           (u32)val, size);
                if (ACPI_FAILURE(status)) {
                        pr_debug("Error: Failed to write SystemIO port %llx\n",
                                 reg->address);
@@ -1076,17 +1087,22 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
                }
 
                return 0;
-       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
+       } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
+               /*
+                * For registers in PCC space, the register size is determined
+                * by the bit width field; the access size is used to indicate
+                * the PCC subspace id.
+                */
+               size = reg->bit_width;
                vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
+       }
        else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
                vaddr = reg_res->sys_mem_vaddr;
        else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
                return cpc_write_ffh(cpu, reg, val);
        else
                return acpi_os_write_memory((acpi_physical_address)reg->address,
-                               val, reg->bit_width);
-
-       size = GET_BIT_WIDTH(reg);
+                               val, size);
 
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
                val = MASK_VAL(reg, val);
@@ -1105,8 +1121,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
                writeq_relaxed(val, vaddr);
                break;
        default:
-               pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
-                        reg->bit_width, pcc_ss_id);
+               if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+                       pr_debug("Error: Cannot write %u bit width to system memory: 0x%llx\n",
+                               size, reg->address);
+               } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+                       pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
+                               size, pcc_ss_id);
+               }
                ret_val = -EFAULT;
                break;
        }
index cd84af23f7eac8fad793c6393bcd8130596077ce..dd0b40b9bbe8bef5f8c30a082eebbc25dcdfeafd 100644 (file)
@@ -492,16 +492,14 @@ static int lps0_device_attach(struct acpi_device *adev,
                        unsigned int func_mask;
 
                        /*
-                        * Avoid evaluating the same _DSM function for two
-                        * different UUIDs and prioritize the MSFT one.
+                        * Log a message if the _DSM function sets for two
+                        * different UUIDs overlap.
                         */
                        func_mask = lps0_dsm_func_mask & lps0_dsm_func_mask_microsoft;
-                       if (func_mask) {
+                       if (func_mask)
                                acpi_handle_info(adev->handle,
                                                 "Duplicate LPS0 _DSM functions (mask: 0x%x)\n",
                                                 func_mask);
-                               lps0_dsm_func_mask &= ~func_mask;
-                       }
                }
        }
 
index 5cb425f6f02d4bd1e4aa4f0e58d846a52896fdca..0a34dd3c4f38d298b8766065026cc465801f7aa7 100644 (file)
@@ -2838,6 +2838,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
 }
 EXPORT_SYMBOL_GPL(regmap_read);
 
+/**
+ * regmap_read_bypassed() - Read a value from a single register direct
+ *                         from the device, bypassing the cache
+ *
+ * @map: Register map to read from
+ * @reg: Register to be read from
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
+{
+       int ret;
+       bool bypass, cache_only;
+
+       if (!IS_ALIGNED(reg, map->reg_stride))
+               return -EINVAL;
+
+       map->lock(map->lock_arg);
+
+       bypass = map->cache_bypass;
+       cache_only = map->cache_only;
+       map->cache_bypass = true;
+       map->cache_only = false;
+
+       ret = _regmap_read(map, reg, val);
+
+       map->cache_bypass = bypass;
+       map->cache_only = cache_only;
+
+       map->unlock(map->lock_arg);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_read_bypassed);
+
 /**
  * regmap_raw_read() - Read raw data from the device
  *
index bea3d5cf8a83487909270d5f2398267250507a31..374e4efa8759fba62df2cdbbc49c9428ddb5ea5b 100644 (file)
@@ -2177,7 +2177,8 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
                .max_hw_sectors         = p->max_sectors,
                .chunk_sectors          = p->chunk_sectors,
                .virt_boundary_mask     = p->virt_boundary_mask,
-
+               .max_segments           = USHRT_MAX,
+               .max_segment_size       = UINT_MAX,
        };
        struct gendisk *disk;
        int ret = -EINVAL;
index ac8ebccd350756747eee3400596e04fcbac3cabd..812fd2a8f853e1dc305fa6aab04db8098ea28872 100644 (file)
@@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
        switch (data->cd_info.state) {
        case HCI_DEVCOREDUMP_IDLE:
                err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
-               if (err < 0)
+               if (err < 0) {
+                       kfree_skb(skb);
                        break;
+               }
                data->cd_info.cnt = 0;
 
                /* It is supposed coredump can be done within 5 seconds */
@@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
                break;
        }
 
-       if (err < 0)
-               kfree_skb(skb);
-
        return err;
 }
 EXPORT_SYMBOL_GPL(btmtk_process_coredump);
index 19cfc342fc7bbb67af65cb4de10e074622a991a4..216826c31ee34f0e65ef74edcab98c7cd9eff7e5 100644 (file)
@@ -15,6 +15,8 @@
 
 #define VERSION "0.1"
 
+#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
+
 int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
                         enum qca_btsoc_type soc_type)
 {
@@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
 }
 EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
 
+static int qca_check_bdaddr(struct hci_dev *hdev)
+{
+       struct hci_rp_read_bd_addr *bda;
+       struct sk_buff *skb;
+       int err;
+
+       if (bacmp(&hdev->public_addr, BDADDR_ANY))
+               return 0;
+
+       skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+                            HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               err = PTR_ERR(skb);
+               bt_dev_err(hdev, "Failed to read device address (%d)", err);
+               return err;
+       }
+
+       if (skb->len != sizeof(*bda)) {
+               bt_dev_err(hdev, "Device address length mismatch");
+               kfree_skb(skb);
+               return -EIO;
+       }
+
+       bda = (struct hci_rp_read_bd_addr *)skb->data;
+       if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT))
+               set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+
+       kfree_skb(skb);
+
+       return 0;
+}
+
 static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
                struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
 {
@@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                break;
        }
 
+       err = qca_check_bdaddr(hdev);
+       if (err)
+               return err;
+
        bt_dev_info(hdev, "QCA setup on UART is completed");
 
        return 0;
index 06e915b57283f8ca3d3ab19b64e1e248e6ecb2bc..e3946f7b736e3cccfe727575096ff073fd86cf1d 100644 (file)
@@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = {
        /* Realtek 8852BE Bluetooth devices */
        { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
+       { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
+                                                    BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
                                                     BTUSB_WIDEBAND_SPEECH },
        { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
@@ -3480,13 +3482,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)
 
 static void btusb_coredump_qca(struct hci_dev *hdev)
 {
+       int err;
        static const u8 param[] = { 0x26 };
-       struct sk_buff *skb;
 
-       skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT);
-       if (IS_ERR(skb))
-               bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb));
-       kfree_skb(skb);
+       err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
+       if (err < 0)
+               bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
 }
 
 /*
index ecbc52eaf1010912b9024ddbc3c87aac4254e1e3..0c9c9ee56592dc851ab12f98be5a6be2465b812e 100644 (file)
@@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev)
        struct hci_uart *hu = hci_get_drvdata(hdev);
        bool wakeup;
 
+       if (!hu->serdev)
+               return true;
+
        /* BT SoC attached through the serial bus is handled by the serdev driver.
         * So we need to use the device handle of the serdev driver to get the
         * status of device may wakeup.
@@ -1905,8 +1908,6 @@ retry:
        case QCA_WCN6750:
        case QCA_WCN6855:
        case QCA_WCN7850:
-               set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
-
                qcadev = serdev_device_get_drvdata(hu->serdev);
                if (qcadev->bdaddr_property_broken)
                        set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
@@ -1957,8 +1958,10 @@ retry:
                qca_debugfs_init(hdev);
                hu->hdev->hw_error = qca_hw_error;
                hu->hdev->cmd_timeout = qca_cmd_timeout;
-               if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
-                       hu->hdev->wakeup = qca_wakeup;
+               if (hu->serdev) {
+                       if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
+                               hu->hdev->wakeup = qca_wakeup;
+               }
        } else if (ret == -ENOENT) {
                /* No patch/nvm-config found, run with original fw/config */
                set_bit(QCA_ROM_FW, &qca->flags);
@@ -2329,16 +2332,21 @@ static int qca_serdev_probe(struct serdev_device *serdev)
                    (data->soc_type == QCA_WCN6750 ||
                     data->soc_type == QCA_WCN6855)) {
                        dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
-                       power_ctrl_enabled = false;
+                       return PTR_ERR(qcadev->bt_en);
                }
 
+               if (!qcadev->bt_en)
+                       power_ctrl_enabled = false;
+
                qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
                                               GPIOD_IN);
                if (IS_ERR(qcadev->sw_ctrl) &&
                    (data->soc_type == QCA_WCN6750 ||
                     data->soc_type == QCA_WCN6855 ||
-                    data->soc_type == QCA_WCN7850))
-                       dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
+                    data->soc_type == QCA_WCN7850)) {
+                       dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
+                       return PTR_ERR(qcadev->sw_ctrl);
+               }
 
                qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
                if (IS_ERR(qcadev->susclk)) {
@@ -2357,10 +2365,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
                qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
                                               GPIOD_OUT_LOW);
                if (IS_ERR(qcadev->bt_en)) {
-                       dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
-                       power_ctrl_enabled = false;
+                       dev_err(&serdev->dev, "failed to acquire enable gpio\n");
+                       return PTR_ERR(qcadev->bt_en);
                }
 
+               if (!qcadev->bt_en)
+                       power_ctrl_enabled = false;
+
                qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
                if (IS_ERR(qcadev->susclk)) {
                        dev_warn(&serdev->dev, "failed to acquire clk\n");
index 8602c02047d0481b28e7c7da75ddb1564aa3da14..45c5255bcd11bae69b83138ba1d5e52a8a3f3be8 100644 (file)
@@ -768,6 +768,7 @@ static struct clk_smd_rpm *msm8976_clks[] = {
 
 static const struct rpm_smd_clk_desc rpm_clk_msm8976 = {
        .clks = msm8976_clks,
+       .num_clks = ARRAY_SIZE(msm8976_clks),
        .icc_clks = bimc_pcnoc_snoc_smmnoc_icc_clks,
        .num_icc_clks = ARRAY_SIZE(bimc_pcnoc_snoc_smmnoc_icc_clks),
 };
index e7a4068b9f3906f99d9d5ca444fe903b237811b6..df9618ab7eea1fb0422ee73fd21938e6fc77e257 100644 (file)
@@ -487,9 +487,14 @@ int gdsc_register(struct gdsc_desc *desc,
                if (!scs[i] || !scs[i]->supply)
                        continue;
 
-               scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
-               if (IS_ERR(scs[i]->rsupply))
-                       return PTR_ERR(scs[i]->rsupply);
+               scs[i]->rsupply = devm_regulator_get_optional(dev, scs[i]->supply);
+               if (IS_ERR(scs[i]->rsupply)) {
+                       ret = PTR_ERR(scs[i]->rsupply);
+                       if (ret != -ENODEV)
+                               return ret;
+
+                       scs[i]->rsupply = NULL;
+               }
        }
 
        data->num_domains = num;
index 3484e6cc80ad10d1eceaba017de2a9bfc7602880..503c6f5b20d5c5538dc2bfc44afbc594df0878d6 100644 (file)
@@ -13,9 +13,9 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
-#include <linux/property.h>
 
 #define EXYNOS_CLKOUT_NR_CLKS          1
 #define EXYNOS_CLKOUT_PARENTS          32
@@ -84,17 +84,24 @@ MODULE_DEVICE_TABLE(of, exynos_clkout_ids);
 static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask)
 {
        const struct exynos_clkout_variant *variant;
+       const struct of_device_id *match;
 
        if (!dev->parent) {
                dev_err(dev, "not instantiated from MFD\n");
                return -EINVAL;
        }
 
-       variant = device_get_match_data(dev->parent);
-       if (!variant) {
+       /*
+        * 'exynos_clkout_ids' arrays is not the ids array matched by
+        * the dev->parent driver, so of_device_get_match_data() or
+        * device_get_match_data() cannot be used here.
+        */
+       match = of_match_device(exynos_clkout_ids, dev->parent);
+       if (!match) {
                dev_err(dev, "cannot match parent device\n");
                return -EINVAL;
        }
+       variant = match->data;
 
        *mux_mask = variant->mux_mask;
 
index 8951ffc14ff52c5a2bd7d6be60f47539cad36fb1..6a4b2b9ef30a82e1721e21695f299351a378f8fb 100644 (file)
@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
                                              &ccu_nkm_ops,
                                              CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
                .features       = CCU_FEATURE_CLOSEST_RATE,
+               .min_rate       = 500000000,
+               .max_rate       = 1400000000,
        },
 };
 
index 42568c6161814dc797079d1ee224bc7a2e6847a8..892df807275c8e57b1b53112faece02a47f22f6e 100644 (file)
@@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = {
        SUN50I_H6_USB3_CLK_REG,
 };
 
+static struct ccu_mux_nb sun50i_h6_cpu_nb = {
+       .common         = &cpux_clk.common,
+       .cm             = &cpux_clk.mux,
+       .delay_us       = 1,
+       .bypass_index   = 0, /* index of 24 MHz oscillator */
+};
+
 static int sun50i_h6_ccu_probe(struct platform_device *pdev)
 {
        void __iomem *reg;
+       int i, ret;
        u32 val;
-       int i;
 
        reg = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(reg))
@@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
        val |= BIT(24);
        writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
 
-       return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
+       ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
+       if (ret)
+               return ret;
+
+       /* Reparent CPU during PLL CPUX rate changes */
+       ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
+                                 &sun50i_h6_cpu_nb);
+
+       return 0;
 }
 
 static const struct of_device_id sun50i_h6_ccu_ids[] = {
index 8babce55302f5f9dd9ddd59ef0113e3af5171d37..ac0091b4ce2425b77750619383531191c228e7ed 100644 (file)
@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
                        unsigned long current_rate,
                        unsigned long best_rate)
 {
+       unsigned long min_rate, max_rate;
+
+       clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate);
+
+       if (current_rate > max_rate)
+               return false;
+
+       if (current_rate < min_rate)
+               return false;
+
        if (common->features & CCU_FEATURE_CLOSEST_RATE)
                return abs(current_rate - target_rate) < abs(best_rate - target_rate);
 
@@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
 
        for (i = 0; i < desc->hw_clks->num ; i++) {
                struct clk_hw *hw = desc->hw_clks->hws[i];
+               struct ccu_common *common = hw_to_ccu_common(hw);
                const char *name;
 
                if (!hw)
@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
                        pr_err("Couldn't register clock %d - %s\n", i, name);
                        goto err_clk_unreg;
                }
+
+               if (common->max_rate)
+                       clk_hw_set_rate_range(hw, common->min_rate,
+                                             common->max_rate);
+               else
+                       WARN(common->min_rate,
+                            "No max_rate, ignoring min_rate of clock %d - %s\n",
+                            i, name);
        }
 
        ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
index 942a72c094374435d73e9f27ddfd04af4f241fd4..329734f8cf42b41263fbc4eb2de9bb1315e498e1 100644 (file)
@@ -31,6 +31,9 @@ struct ccu_common {
        u16             lock_reg;
        u32             prediv;
 
+       unsigned long   min_rate;
+       unsigned long   max_rate;
+
        unsigned long   features;
        spinlock_t      *lock;
        struct clk_hw   hw;
index f0f54aeccc872b50311a14958ddf874860af7982..65185c9fa00134e4ed9f5449628ae04f053ba927 100644 (file)
@@ -946,25 +946,22 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
        struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
        struct device *dev = mds->cxlds.dev;
        struct cxl_get_event_payload *payload;
-       struct cxl_mbox_cmd mbox_cmd;
        u8 log_type = type;
        u16 nr_rec;
 
        mutex_lock(&mds->event.log_lock);
        payload = mds->event.buf;
 
-       mbox_cmd = (struct cxl_mbox_cmd) {
-               .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
-               .payload_in = &log_type,
-               .size_in = sizeof(log_type),
-               .payload_out = payload,
-               .min_out = struct_size(payload, records, 0),
-       };
-
        do {
                int rc, i;
-
-               mbox_cmd.size_out = mds->payload_size;
+               struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd) {
+                       .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
+                       .payload_in = &log_type,
+                       .size_in = sizeof(log_type),
+                       .payload_out = payload,
+                       .size_out = mds->payload_size,
+                       .min_out = struct_size(payload, records, 0),
+               };
 
                rc = cxl_internal_send_cmd(mds, &mbox_cmd);
                if (rc) {
@@ -1297,7 +1294,6 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
        struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
        struct cxl_mbox_poison_out *po;
        struct cxl_mbox_poison_in pi;
-       struct cxl_mbox_cmd mbox_cmd;
        int nr_records = 0;
        int rc;
 
@@ -1309,16 +1305,16 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
        pi.offset = cpu_to_le64(offset);
        pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT);
 
-       mbox_cmd = (struct cxl_mbox_cmd) {
-               .opcode = CXL_MBOX_OP_GET_POISON,
-               .size_in = sizeof(pi),
-               .payload_in = &pi,
-               .size_out = mds->payload_size,
-               .payload_out = po,
-               .min_out = struct_size(po, record, 0),
-       };
-
        do {
+               struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd){
+                       .opcode = CXL_MBOX_OP_GET_POISON,
+                       .size_in = sizeof(pi),
+                       .payload_in = &pi,
+                       .size_out = mds->payload_size,
+                       .payload_out = po,
+                       .min_out = struct_size(po, record, 0),
+               };
+
                rc = cxl_internal_send_cmd(mds, &mbox_cmd);
                if (rc)
                        break;
index 762783bb091afc8a40883c9ab2ee9c0f39e37219..887ed6e358fb9f6c77fcb9ba9424342df4e03579 100644 (file)
@@ -2184,6 +2184,7 @@ static bool parent_port_is_cxl_root(struct cxl_port *port)
 int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
                                      struct access_coordinate *coord)
 {
+       struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
        struct access_coordinate c[] = {
                {
                        .read_bandwidth = UINT_MAX,
@@ -2197,12 +2198,20 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
        struct cxl_port *iter = port;
        struct cxl_dport *dport;
        struct pci_dev *pdev;
+       struct device *dev;
        unsigned int bw;
        bool is_cxl_root;
 
        if (!is_cxl_endpoint(port))
                return -EINVAL;
 
+       /*
+        * Skip calculation for RCD. Expectation is HMAT already covers RCD case
+        * since RCH does not support hotplug.
+        */
+       if (cxlmd->cxlds->rcd)
+               return 0;
+
        /*
         * Exit the loop when the parent port of the current iter port is cxl
         * root. The iterative loop starts at the endpoint and gathers the
@@ -2232,8 +2241,12 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
                return -EINVAL;
        cxl_coordinates_combine(c, c, dport->coord);
 
+       dev = port->uport_dev->parent;
+       if (!dev_is_pci(dev))
+               return -ENODEV;
+
        /* Get the calculated PCI paths bandwidth */
-       pdev = to_pci_dev(port->uport_dev->parent);
+       pdev = to_pci_dev(dev);
        bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL);
        if (bw == 0)
                return -ENXIO;
index 78a938969d7d76f513885d3c749392399f367256..1398814d8fbb63c3dd750a603deca0a050e488a1 100644 (file)
@@ -171,6 +171,10 @@ static irqreturn_t idma64_irq(int irq, void *dev)
        u32 status_err;
        unsigned short i;
 
+       /* Since IRQ may be shared, check if DMA controller is powered on */
+       if (status == GENMASK(31, 0))
+               return IRQ_NONE;
+
        dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status);
 
        /* Check if we have any interrupt from the DMA controller */
index 8078ab9acfbc37da0c5f633b0af9bb8529a559fe..c095a2c8f65956c696eab833f32308124dee2fd9 100644 (file)
@@ -342,7 +342,7 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
        if (!evl)
                return;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = status.tail;
        h = status.head;
@@ -354,9 +354,8 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
                        set_bit(h, evl->bmap);
                h = (h + 1) % size;
        }
-       spin_unlock(&evl->lock);
-
        drain_workqueue(wq->wq);
+       mutex_unlock(&evl->lock);
 }
 
 static int idxd_cdev_release(struct inode *node, struct file *filep)
index f3f25ee676f30eb283989586d458a5c8b8c01f9f..ad4245cb301d506d7952f0a47baea171234db903 100644 (file)
@@ -66,7 +66,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
        if (!evl || !evl->log)
                return 0;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
 
        evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = evl_status.tail;
@@ -87,7 +87,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
                dump_event_entry(idxd, s, i, &count, processed);
        }
 
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
        return 0;
 }
 
index ecfdf4a8f1f838ea49f1dbe3f60b15574aa8be11..c41ef195eeb9f218935520301f3582b9b6787c7d 100644 (file)
@@ -775,7 +775,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
                goto err_alloc;
        }
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        evl->log = addr;
        evl->dma = dma_addr;
        evl->log_size = size;
@@ -796,7 +796,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
        gencfg.evl_en = 1;
        iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
 
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
        return 0;
 
 err_alloc:
@@ -819,7 +819,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
        if (!gencfg.evl_en)
                return;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        gencfg.evl_en = 0;
        iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
 
@@ -836,7 +836,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
        evl_dma = evl->dma;
        evl->log = NULL;
        evl->size = IDXD_EVL_SIZE_MIN;
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
 
        dma_free_coherent(dev, evl_log_size, evl_log, evl_dma);
 }
index a4099a1e2340fde5271e1dc29e9a5b5c224b8641..7b98944135eb440c2c5659b8e4a637085698f93c 100644 (file)
@@ -293,7 +293,7 @@ struct idxd_driver_data {
 
 struct idxd_evl {
        /* Lock to protect event log access. */
-       spinlock_t lock;
+       struct mutex lock;
        void *log;
        dma_addr_t dma;
        /* Total size of event log = number of entries * entry size. */
index 4954adc6bb609e508c510daf630f1077191fd2c7..264c4e47d7cca5651c02595652419970504e554a 100644 (file)
@@ -354,7 +354,7 @@ static int idxd_init_evl(struct idxd_device *idxd)
        if (!evl)
                return -ENOMEM;
 
-       spin_lock_init(&evl->lock);
+       mutex_init(&evl->lock);
        evl->size = IDXD_EVL_SIZE_MIN;
 
        idxd_name = dev_name(idxd_confdev(idxd));
index 348aa21389a9fceb4cd522579c8f8a9963e72ef3..8dc029c8655151a1a47d7849e6fae313c4130add 100644 (file)
@@ -363,7 +363,7 @@ static void process_evl_entries(struct idxd_device *idxd)
        evl_status.bits = 0;
        evl_status.int_pending = 1;
 
-       spin_lock(&evl->lock);
+       mutex_lock(&evl->lock);
        /* Clear interrupt pending bit */
        iowrite32(evl_status.bits_upper32,
                  idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32));
@@ -380,7 +380,7 @@ static void process_evl_entries(struct idxd_device *idxd)
 
        evl_status.head = h;
        iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
-       spin_unlock(&evl->lock);
+       mutex_unlock(&evl->lock);
 }
 
 irqreturn_t idxd_misc_thread(int vec, void *data)
index fdda6d60426295baf11b191186b1d3956c1d94ae..5e94247e1ea703086365a01d1d124e5ef2acb5de 100644 (file)
@@ -528,14 +528,11 @@ static int perf_event_cpu_offline(unsigned int cpu, struct hlist_node *node)
                return 0;
 
        target = cpumask_any_but(cpu_online_mask, cpu);
-
        /* migrate events if there is a valid target */
-       if (target < nr_cpu_ids)
+       if (target < nr_cpu_ids) {
                cpumask_set_cpu(target, &perfmon_dsa_cpu_mask);
-       else
-               target = -1;
-
-       perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target);
+               perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target);
+       }
 
        return 0;
 }
index 4e76c4ec2d39660bf91d0350f0b8334e943feb3f..e001f4f7aa640fd05f76e3423ddb183f4883de4b 100644 (file)
@@ -250,7 +250,7 @@ static void pchan_update(struct owl_dma_pchan *pchan, u32 reg,
        else
                regval &= ~val;
 
-       writel(val, pchan->base + reg);
+       writel(regval, pchan->base + reg);
 }
 
 static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data)
@@ -274,7 +274,7 @@ static void dma_update(struct owl_dma *od, u32 reg, u32 val, bool state)
        else
                regval &= ~val;
 
-       writel(val, od->base + reg);
+       writel(regval, od->base + reg);
 }
 
 static void dma_writel(struct owl_dma *od, u32 reg, u32 data)
index 5f6d7f1e095f906ec22b4a4b6f67cc7309242994..ad8e3da1b2cd229ff9bdf222439c1db6d1e229ad 100644 (file)
@@ -1053,9 +1053,6 @@ static bool _trigger(struct pl330_thread *thrd)
 
        thrd->req_running = idx;
 
-       if (desc->rqtype == DMA_MEM_TO_DEV || desc->rqtype == DMA_DEV_TO_MEM)
-               UNTIL(thrd, PL330_STATE_WFP);
-
        return true;
 }
 
index 88547a23825b18aece9f4eb00221549e02eaadd1..3642508e88bb2211c13ad705bce34975945821e9 100644 (file)
@@ -746,6 +746,9 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
        bytes_xfer = dma_desc->bytes_xfer +
                     sg_req[dma_desc->sg_idx].len - (wcount * 4);
 
+       if (dma_desc->bytes_req == bytes_xfer)
+               return 0;
+
        residual = dma_desc->bytes_req - (bytes_xfer % dma_desc->bytes_req);
 
        return residual;
index 98f5f6fb9ff9c771270c64c364265f72fd7b216d..6ad08878e93862b770febb71b8bc85e66813428e 100644 (file)
@@ -117,6 +117,9 @@ struct xdma_hw_desc {
                         CHAN_CTRL_IE_WRITE_ERROR |                     \
                         CHAN_CTRL_IE_DESC_ERROR)
 
+/* bits of the channel status register */
+#define XDMA_CHAN_STATUS_BUSY                  BIT(0)
+
 #define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START
 
 #define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH |       \
index 170017ff2aad6e58c8d0ee4ea6e7d42c15c8202c..313b217388fe95e2fd539d53c5542ce858cc25a6 100644 (file)
@@ -71,6 +71,8 @@ struct xdma_chan {
        enum dma_transfer_direction     dir;
        struct dma_slave_config         cfg;
        u32                             irq;
+       struct completion               last_interrupt;
+       bool                            stop_requested;
 };
 
 /**
@@ -376,6 +378,8 @@ static int xdma_xfer_start(struct xdma_chan *xchan)
                return ret;
 
        xchan->busy = true;
+       xchan->stop_requested = false;
+       reinit_completion(&xchan->last_interrupt);
 
        return 0;
 }
@@ -387,7 +391,6 @@ static int xdma_xfer_start(struct xdma_chan *xchan)
 static int xdma_xfer_stop(struct xdma_chan *xchan)
 {
        int ret;
-       u32 val;
        struct xdma_device *xdev = xchan->xdev_hdl;
 
        /* clear run stop bit to prevent any further auto-triggering */
@@ -395,13 +398,7 @@ static int xdma_xfer_stop(struct xdma_chan *xchan)
                           CHAN_CTRL_RUN_STOP);
        if (ret)
                return ret;
-
-       /* Clear the channel status register */
-       ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &val);
-       if (ret)
-               return ret;
-
-       return 0;
+       return ret;
 }
 
 /**
@@ -474,6 +471,8 @@ static int xdma_alloc_channels(struct xdma_device *xdev,
                xchan->xdev_hdl = xdev;
                xchan->base = base + i * XDMA_CHAN_STRIDE;
                xchan->dir = dir;
+               xchan->stop_requested = false;
+               init_completion(&xchan->last_interrupt);
 
                ret = xdma_channel_init(xchan);
                if (ret)
@@ -521,6 +520,7 @@ static int xdma_terminate_all(struct dma_chan *chan)
        spin_lock_irqsave(&xdma_chan->vchan.lock, flags);
 
        xdma_chan->busy = false;
+       xdma_chan->stop_requested = true;
        vd = vchan_next_desc(&xdma_chan->vchan);
        if (vd) {
                list_del(&vd->node);
@@ -542,17 +542,26 @@ static int xdma_terminate_all(struct dma_chan *chan)
 static void xdma_synchronize(struct dma_chan *chan)
 {
        struct xdma_chan *xdma_chan = to_xdma_chan(chan);
+       struct xdma_device *xdev = xdma_chan->xdev_hdl;
+       int st = 0;
+
+       /* If the engine continues running, wait for the last interrupt */
+       regmap_read(xdev->rmap, xdma_chan->base + XDMA_CHAN_STATUS, &st);
+       if (st & XDMA_CHAN_STATUS_BUSY)
+               wait_for_completion_timeout(&xdma_chan->last_interrupt, msecs_to_jiffies(1000));
 
        vchan_synchronize(&xdma_chan->vchan);
 }
 
 /**
- * xdma_fill_descs - Fill hardware descriptors with contiguous memory block addresses
- * @sw_desc: tx descriptor state container
- * @src_addr: Value for a ->src_addr field of a first descriptor
- * @dst_addr: Value for a ->dst_addr field of a first descriptor
- * @size: Total size of a contiguous memory block
- * @filled_descs_num: Number of filled hardware descriptors for corresponding sw_desc
+ * xdma_fill_descs() - Fill hardware descriptors for one contiguous memory chunk.
+ *                    More than one descriptor will be used if the size is bigger
+ *                    than XDMA_DESC_BLEN_MAX.
+ * @sw_desc: Descriptor container
+ * @src_addr: First value for the ->src_addr field
+ * @dst_addr: First value for the ->dst_addr field
+ * @size: Size of the contiguous memory block
+ * @filled_descs_num: Index of the first descriptor to take care of in @sw_desc
  */
 static inline u32 xdma_fill_descs(struct xdma_desc *sw_desc, u64 src_addr,
                                  u64 dst_addr, u32 size, u32 filled_descs_num)
@@ -704,7 +713,7 @@ xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address,
        desc_num = 0;
        for (i = 0; i < periods; i++) {
                desc_num += xdma_fill_descs(sw_desc, *src, *dst, period_size, desc_num);
-               addr += i * period_size;
+               addr += period_size;
        }
 
        tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags);
@@ -876,6 +885,9 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
        u32 st;
        bool repeat_tx;
 
+       if (xchan->stop_requested)
+               complete(&xchan->last_interrupt);
+
        spin_lock(&xchan->vchan.lock);
 
        /* get submitted request */
index b82815e64d24e8352ac025bc1bd52de497530d66..eb0637d90342a6727d28c300394e81aa6fa44b74 100644 (file)
@@ -214,7 +214,8 @@ struct xilinx_dpdma_tx_desc {
  * @running: true if the channel is running
  * @first_frame: flag for the first frame of stream
  * @video_group: flag if multi-channel operation is needed for video channels
- * @lock: lock to access struct xilinx_dpdma_chan
+ * @lock: lock to access struct xilinx_dpdma_chan. Must be taken before
+ *        @vchan.lock, if both are to be held.
  * @desc_pool: descriptor allocation pool
  * @err_task: error IRQ bottom half handler
  * @desc: References to descriptors being processed
@@ -1097,12 +1098,14 @@ static void xilinx_dpdma_chan_vsync_irq(struct  xilinx_dpdma_chan *chan)
         * Complete the active descriptor, if any, promote the pending
         * descriptor to active, and queue the next transfer, if any.
         */
+       spin_lock(&chan->vchan.lock);
        if (chan->desc.active)
                vchan_cookie_complete(&chan->desc.active->vdesc);
        chan->desc.active = pending;
        chan->desc.pending = NULL;
 
        xilinx_dpdma_chan_queue_transfer(chan);
+       spin_unlock(&chan->vchan.lock);
 
 out:
        spin_unlock_irqrestore(&chan->lock, flags);
@@ -1264,10 +1267,12 @@ static void xilinx_dpdma_issue_pending(struct dma_chan *dchan)
        struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
        unsigned long flags;
 
-       spin_lock_irqsave(&chan->vchan.lock, flags);
+       spin_lock_irqsave(&chan->lock, flags);
+       spin_lock(&chan->vchan.lock);
        if (vchan_issue_pending(&chan->vchan))
                xilinx_dpdma_chan_queue_transfer(chan);
-       spin_unlock_irqrestore(&chan->vchan.lock, flags);
+       spin_unlock(&chan->vchan.lock);
+       spin_unlock_irqrestore(&chan->lock, flags);
 }
 
 static int xilinx_dpdma_config(struct dma_chan *dchan,
@@ -1495,7 +1500,9 @@ static void xilinx_dpdma_chan_err_task(struct tasklet_struct *t)
                    XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id);
 
        spin_lock_irqsave(&chan->lock, flags);
+       spin_lock(&chan->vchan.lock);
        xilinx_dpdma_chan_queue_transfer(chan);
+       spin_unlock(&chan->vchan.lock);
        spin_unlock_irqrestore(&chan->lock, flags);
 }
 
index 64eaca80d736c5652958ddb5e21bc64ff3a6bc65..d0f6693ca142623af740bf69ee8664fc88926fcb 100644 (file)
@@ -42,6 +42,7 @@ struct dpll_pin_registration {
        struct list_head list;
        const struct dpll_pin_ops *ops;
        void *priv;
+       void *cookie;
 };
 
 struct dpll_device *dpll_device_get_by_id(int id)
@@ -54,12 +55,14 @@ struct dpll_device *dpll_device_get_by_id(int id)
 
 static struct dpll_pin_registration *
 dpll_pin_registration_find(struct dpll_pin_ref *ref,
-                          const struct dpll_pin_ops *ops, void *priv)
+                          const struct dpll_pin_ops *ops, void *priv,
+                          void *cookie)
 {
        struct dpll_pin_registration *reg;
 
        list_for_each_entry(reg, &ref->registration_list, list) {
-               if (reg->ops == ops && reg->priv == priv)
+               if (reg->ops == ops && reg->priv == priv &&
+                   reg->cookie == cookie)
                        return reg;
        }
        return NULL;
@@ -67,7 +70,8 @@ dpll_pin_registration_find(struct dpll_pin_ref *ref,
 
 static int
 dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
-                   const struct dpll_pin_ops *ops, void *priv)
+                   const struct dpll_pin_ops *ops, void *priv,
+                   void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -78,7 +82,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
        xa_for_each(xa_pins, i, ref) {
                if (ref->pin != pin)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (reg) {
                        refcount_inc(&ref->refcount);
                        return 0;
@@ -111,6 +115,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
        }
        reg->ops = ops;
        reg->priv = priv;
+       reg->cookie = cookie;
        if (ref_exists)
                refcount_inc(&ref->refcount);
        list_add_tail(&reg->list, &ref->registration_list);
@@ -119,7 +124,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
 }
 
 static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
-                              const struct dpll_pin_ops *ops, void *priv)
+                              const struct dpll_pin_ops *ops, void *priv,
+                              void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -128,7 +134,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
        xa_for_each(xa_pins, i, ref) {
                if (ref->pin != pin)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (WARN_ON(!reg))
                        return -EINVAL;
                list_del(&reg->list);
@@ -146,7 +152,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
 
 static int
 dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
-                    const struct dpll_pin_ops *ops, void *priv)
+                    const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -157,7 +163,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
        xa_for_each(xa_dplls, i, ref) {
                if (ref->dpll != dpll)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (reg) {
                        refcount_inc(&ref->refcount);
                        return 0;
@@ -190,6 +196,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
        }
        reg->ops = ops;
        reg->priv = priv;
+       reg->cookie = cookie;
        if (ref_exists)
                refcount_inc(&ref->refcount);
        list_add_tail(&reg->list, &ref->registration_list);
@@ -199,7 +206,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
 
 static void
 dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
-                    const struct dpll_pin_ops *ops, void *priv)
+                    const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        struct dpll_pin_registration *reg;
        struct dpll_pin_ref *ref;
@@ -208,7 +215,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
        xa_for_each(xa_dplls, i, ref) {
                if (ref->dpll != dpll)
                        continue;
-               reg = dpll_pin_registration_find(ref, ops, priv);
+               reg = dpll_pin_registration_find(ref, ops, priv, cookie);
                if (WARN_ON(!reg))
                        return;
                list_del(&reg->list);
@@ -594,14 +601,14 @@ EXPORT_SYMBOL_GPL(dpll_pin_put);
 
 static int
 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
-                   const struct dpll_pin_ops *ops, void *priv)
+                   const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        int ret;
 
-       ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv);
+       ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie);
        if (ret)
                return ret;
-       ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv);
+       ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie);
        if (ret)
                goto ref_pin_del;
        xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
@@ -610,7 +617,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
        return ret;
 
 ref_pin_del:
-       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
+       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
        return ret;
 }
 
@@ -642,7 +649,7 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
                      dpll->clock_id == pin->clock_id)))
                ret = -EINVAL;
        else
-               ret = __dpll_pin_register(dpll, pin, ops, priv);
+               ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
        mutex_unlock(&dpll_lock);
 
        return ret;
@@ -651,11 +658,11 @@ EXPORT_SYMBOL_GPL(dpll_pin_register);
 
 static void
 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
-                     const struct dpll_pin_ops *ops, void *priv)
+                     const struct dpll_pin_ops *ops, void *priv, void *cookie)
 {
        ASSERT_DPLL_PIN_REGISTERED(pin);
-       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
-       dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv);
+       dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
+       dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
        if (xa_empty(&pin->dpll_refs))
                xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
 }
@@ -680,7 +687,7 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
 
        mutex_lock(&dpll_lock);
        dpll_pin_delete_ntf(pin);
-       __dpll_pin_unregister(dpll, pin, ops, priv);
+       __dpll_pin_unregister(dpll, pin, ops, priv, NULL);
        mutex_unlock(&dpll_lock);
 }
 EXPORT_SYMBOL_GPL(dpll_pin_unregister);
@@ -716,12 +723,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
                return -EINVAL;
 
        mutex_lock(&dpll_lock);
-       ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv);
+       ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin);
        if (ret)
                goto unlock;
        refcount_inc(&pin->refcount);
        xa_for_each(&parent->dpll_refs, i, ref) {
-               ret = __dpll_pin_register(ref->dpll, pin, ops, priv);
+               ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent);
                if (ret) {
                        stop = i;
                        goto dpll_unregister;
@@ -735,11 +742,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
 dpll_unregister:
        xa_for_each(&parent->dpll_refs, i, ref)
                if (i < stop) {
-                       __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+                       __dpll_pin_unregister(ref->dpll, pin, ops, priv,
+                                             parent);
                        dpll_pin_delete_ntf(pin);
                }
        refcount_dec(&pin->refcount);
-       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
 unlock:
        mutex_unlock(&dpll_lock);
        return ret;
@@ -764,10 +772,10 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
 
        mutex_lock(&dpll_lock);
        dpll_pin_delete_ntf(pin);
-       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
+       dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
        refcount_dec(&pin->refcount);
        xa_for_each(&pin->dpll_refs, i, ref)
-               __dpll_pin_unregister(ref->dpll, pin, ops, priv);
+               __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
        mutex_unlock(&dpll_lock);
 }
 EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);
index b0d671db178a85b6ab98de29f05b994db99a8697..ea31ac7ac1ca931a569af239dbaa2052448e8df5 100644 (file)
@@ -148,10 +148,12 @@ packet_buffer_get(struct client *client, char __user *data, size_t user_length)
        if (atomic_read(&buffer->size) == 0)
                return -ENODEV;
 
-       /* FIXME: Check length <= user_length. */
+       length = buffer->head->length;
+
+       if (length > user_length)
+               return 0;
 
        end = buffer->data + buffer->capacity;
-       length = buffer->head->length;
 
        if (&buffer->head->data[length] < end) {
                if (copy_to_user(data, buffer->head->data, length))
index 38d19410a2be68cab9f382d48ab7f15493c42af0..b9ae0340b8a70343185fe97364229dab4f72101c 100644 (file)
@@ -1556,6 +1556,8 @@ static int handle_at_packet(struct context *context,
 #define HEADER_GET_DATA_LENGTH(q)      (((q) >> 16) & 0xffff)
 #define HEADER_GET_EXTENDED_TCODE(q)   (((q) >> 0) & 0xffff)
 
+static u32 get_cycle_time(struct fw_ohci *ohci);
+
 static void handle_local_rom(struct fw_ohci *ohci,
                             struct fw_packet *packet, u32 csr)
 {
@@ -1580,6 +1582,8 @@ static void handle_local_rom(struct fw_ohci *ohci,
                                 (void *) ohci->config_rom + i, length);
        }
 
+       // Timestamping on behalf of the hardware.
+       response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
        fw_core_handle_response(&ohci->card, &response);
 }
 
@@ -1628,6 +1632,8 @@ static void handle_local_lock(struct fw_ohci *ohci,
        fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);
 
  out:
+       // Timestamping on behalf of the hardware.
+       response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
        fw_core_handle_response(&ohci->card, &response);
 }
 
@@ -1670,8 +1676,6 @@ static void handle_local_request(struct context *ctx, struct fw_packet *packet)
        }
 }
 
-static u32 get_cycle_time(struct fw_ohci *ohci);
-
 static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
 {
        unsigned long flags;
index 5b439d04079c841e1bd698f63d96d1b428f6b2ed..50f6503fe49f5e44474b99a1cc53edf0fa97d283 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/crash_dump.h>
+#include <linux/nmi.h>
 #include <asm/unaccepted_memory.h>
 
 /* Protects unaccepted memory bitmap and accepting_list */
@@ -149,6 +150,9 @@ retry:
        }
 
        list_del(&range.list);
+
+       touch_softlockup_watchdog();
+
        spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
 }
 
index 32188f098ef3497eadebab991ed956a57eb6768a..bc550ad0dbe0c7f57c05508382ae5f626ebe6db1 100644 (file)
@@ -221,6 +221,19 @@ struct qsee_rsp_uefi_query_variable_info {
  * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
  * however, has an alignment of 4 byte (32 bits). So far, this seems to work
  * fine here. See also the comment on the typedef of efi_guid_t.
+ *
+ * Note: It looks like uefisecapp is quite picky about how the memory passed to
+ * it is structured and aligned. In particular the request/response setup used
+ * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory,
+ * accepts separate buffers/addresses for the request and response parts, in
+ * practice, however, it seems to expect them to be both part of a larger
+ * contiguous block. We initially allocated separate buffers for the request
+ * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to
+ * either not write any response to the response buffer or outright crash the
+ * device. Therefore, we now allocate a single contiguous block of DMA memory
+ * for both and properly align the data using the macros below. In particular,
+ * request and response structs are aligned at 8 byte (via __reqdata_offs()),
+ * following the driver that this has been reverse-engineered from.
  */
 #define qcuefi_buf_align_fields(fields...)                                     \
        ({                                                                      \
@@ -244,6 +257,12 @@ struct qsee_rsp_uefi_query_variable_info {
 #define __array_offs(type, count, offset)                                      \
        __field_impl(sizeof(type) * (count), __alignof__(type), offset)
 
+#define __array_offs_aligned(type, count, align, offset)                       \
+       __field_impl(sizeof(type) * (count), align, offset)
+
+#define __reqdata_offs(size, offset)                                           \
+       __array_offs_aligned(u8, size, 8, offset)
+
 #define __array(type, count)           __array_offs(type, count, NULL)
 #define __field_offs(type, offset)     __array_offs(type, 1, offset)
 #define __field(type)                  __array_offs(type, 1, NULL)
@@ -277,10 +296,15 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
        unsigned long buffer_size = *data_size;
        efi_status_t efi_status = EFI_SUCCESS;
        unsigned long name_length;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
        size_t guid_offs;
        size_t name_offs;
        size_t req_size;
        size_t rsp_size;
+       size_t req_offs;
+       size_t rsp_offs;
        ssize_t status;
 
        if (!name || !guid)
@@ -304,17 +328,19 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
                __array(u8, buffer_size)
        );
 
-       req_data = kzalloc(req_size, GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(req_size, &req_offs)
+               __reqdata_offs(rsp_size, &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(rsp_size, GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE;
        req_data->data_size = buffer_size;
@@ -332,7 +358,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
 
        memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, req_size,
+                                      cmd_buf_dma + rsp_offs, rsp_size);
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -407,9 +435,7 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
        memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
@@ -422,10 +448,15 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
        struct qsee_rsp_uefi_set_variable *rsp_data;
        efi_status_t efi_status = EFI_SUCCESS;
        unsigned long name_length;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
        size_t name_offs;
        size_t guid_offs;
        size_t data_offs;
        size_t req_size;
+       size_t req_offs;
+       size_t rsp_offs;
        ssize_t status;
 
        if (!name || !guid)
@@ -450,17 +481,19 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
                __array_offs(u8, data_size, &data_offs)
        );
 
-       req_data = kzalloc(req_size, GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(req_size, &req_offs)
+               __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE;
        req_data->attributes = attributes;
@@ -483,8 +516,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
        if (data_size)
                memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size);
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data,
-                                      sizeof(*rsp_data));
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, req_size,
+                                      cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -507,9 +541,7 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
        }
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
@@ -521,10 +553,15 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
        struct qsee_req_uefi_get_next_variable *req_data;
        struct qsee_rsp_uefi_get_next_variable *rsp_data;
        efi_status_t efi_status = EFI_SUCCESS;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
        size_t guid_offs;
        size_t name_offs;
        size_t req_size;
        size_t rsp_size;
+       size_t req_offs;
+       size_t rsp_offs;
        ssize_t status;
 
        if (!name_size || !name || !guid)
@@ -545,17 +582,19 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
                __array(*name, *name_size / sizeof(*name))
        );
 
-       req_data = kzalloc(req_size, GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(req_size, &req_offs)
+               __reqdata_offs(rsp_size, &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(rsp_size, GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE;
        req_data->guid_offset = guid_offs;
@@ -572,7 +611,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
                goto out_free;
        }
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, req_size,
+                                      cmd_buf_dma + rsp_offs, rsp_size);
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -645,9 +686,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
        }
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
@@ -659,26 +698,34 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
        struct qsee_req_uefi_query_variable_info *req_data;
        struct qsee_rsp_uefi_query_variable_info *rsp_data;
        efi_status_t efi_status = EFI_SUCCESS;
+       dma_addr_t cmd_buf_dma;
+       size_t cmd_buf_size;
+       void *cmd_buf;
+       size_t req_offs;
+       size_t rsp_offs;
        int status;
 
-       req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
-       if (!req_data) {
+       cmd_buf_size = qcuefi_buf_align_fields(
+               __reqdata_offs(sizeof(*req_data), &req_offs)
+               __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
+       );
+
+       cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
+       if (!cmd_buf) {
                efi_status = EFI_OUT_OF_RESOURCES;
                goto out;
        }
 
-       rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
-       if (!rsp_data) {
-               efi_status = EFI_OUT_OF_RESOURCES;
-               goto out_free_req;
-       }
+       req_data = cmd_buf + req_offs;
+       rsp_data = cmd_buf + rsp_offs;
 
        req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO;
        req_data->attributes = attr;
        req_data->length = sizeof(*req_data);
 
-       status = qcom_qseecom_app_send(qcuefi->client, req_data, sizeof(*req_data), rsp_data,
-                                      sizeof(*rsp_data));
+       status = qcom_qseecom_app_send(qcuefi->client,
+                                      cmd_buf_dma + req_offs, sizeof(*req_data),
+                                      cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
        if (status) {
                efi_status = EFI_DEVICE_ERROR;
                goto out_free;
@@ -711,9 +758,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
                *max_variable_size = rsp_data->max_variable_size;
 
 out_free:
-       kfree(rsp_data);
-out_free_req:
-       kfree(req_data);
+       qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
 out:
        return efi_status;
 }
index 520de9b5633abc5aab075400b7feb6b97dcef97c..90283f160a2286d8a12b9b0e313f1dfbbbbd9055 100644 (file)
@@ -1576,9 +1576,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
 /**
  * qcom_scm_qseecom_app_send() - Send to and receive data from a given QSEE app.
  * @app_id:   The ID of the target app.
- * @req:      Request buffer sent to the app (must be DMA-mappable).
+ * @req:      DMA address of the request buffer sent to the app.
  * @req_size: Size of the request buffer.
- * @rsp:      Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp:      DMA address of the response buffer, written to by the app.
  * @rsp_size: Size of the response buffer.
  *
  * Sends a request to the QSEE app associated with the given ID and read back
@@ -1589,33 +1589,13 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
  *
  * Return: Zero on success, nonzero on failure.
  */
-int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
-                             size_t rsp_size)
+int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
+                             dma_addr_t rsp, size_t rsp_size)
 {
        struct qcom_scm_qseecom_resp res = {};
        struct qcom_scm_desc desc = {};
-       dma_addr_t req_phys;
-       dma_addr_t rsp_phys;
        int status;
 
-       /* Map request buffer */
-       req_phys = dma_map_single(__scm->dev, req, req_size, DMA_TO_DEVICE);
-       status = dma_mapping_error(__scm->dev, req_phys);
-       if (status) {
-               dev_err(__scm->dev, "qseecom: failed to map request buffer\n");
-               return status;
-       }
-
-       /* Map response buffer */
-       rsp_phys = dma_map_single(__scm->dev, rsp, rsp_size, DMA_FROM_DEVICE);
-       status = dma_mapping_error(__scm->dev, rsp_phys);
-       if (status) {
-               dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
-               dev_err(__scm->dev, "qseecom: failed to map response buffer\n");
-               return status;
-       }
-
-       /* Set up SCM call data */
        desc.owner = QSEECOM_TZ_OWNER_TZ_APPS;
        desc.svc = QSEECOM_TZ_SVC_APP_ID_PLACEHOLDER;
        desc.cmd = QSEECOM_TZ_CMD_APP_SEND;
@@ -1623,18 +1603,13 @@ int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
                                     QCOM_SCM_RW, QCOM_SCM_VAL,
                                     QCOM_SCM_RW, QCOM_SCM_VAL);
        desc.args[0] = app_id;
-       desc.args[1] = req_phys;
+       desc.args[1] = req;
        desc.args[2] = req_size;
-       desc.args[3] = rsp_phys;
+       desc.args[3] = rsp;
        desc.args[4] = rsp_size;
 
-       /* Perform call */
        status = qcom_scm_qseecom_call(&desc, &res);
 
-       /* Unmap buffers */
-       dma_unmap_single(__scm->dev, rsp_phys, rsp_size, DMA_FROM_DEVICE);
-       dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
-
        if (status)
                return status;
 
index 98b8fd16183e41068cc6108d19a6ef1704ade44e..80cac3a5f97678593ae790b761af661a3149d761 100644 (file)
@@ -78,6 +78,7 @@ static void cci_pci_free_irq(struct pci_dev *pcidev)
 #define PCIE_DEVICE_ID_SILICOM_PAC_N5011       0x1001
 #define PCIE_DEVICE_ID_INTEL_DFL               0xbcce
 /* PCI Subdevice ID for PCIE_DEVICE_ID_INTEL_DFL */
+#define PCIE_SUBDEVICE_ID_INTEL_D5005          0x138d
 #define PCIE_SUBDEVICE_ID_INTEL_N6000          0x1770
 #define PCIE_SUBDEVICE_ID_INTEL_N6001          0x1771
 #define PCIE_SUBDEVICE_ID_INTEL_C6100          0x17d4
@@ -101,6 +102,8 @@ static struct pci_device_id cci_pcie_id_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),},
        {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5010),},
        {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5011),},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL,
+                       PCI_VENDOR_ID_INTEL, PCIE_SUBDEVICE_ID_INTEL_D5005),},
        {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL,
                        PCI_VENDOR_ID_INTEL, PCIE_SUBDEVICE_ID_INTEL_N6000),},
        {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL_VF,
index b75e0b12087ac78f9b50bc9ef77d4f06813ca72a..4b29abafecf6a466e5a81f6c8eeea70395e84823 100644 (file)
@@ -195,7 +195,8 @@ static int tng_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
 
 static void tng_irq_ack(struct irq_data *d)
 {
-       struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tng_gpio *priv = gpiochip_get_data(gc);
        irq_hw_number_t gpio = irqd_to_hwirq(d);
        void __iomem *gisr;
        u8 shift;
@@ -227,7 +228,8 @@ static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask)
 
 static void tng_irq_mask(struct irq_data *d)
 {
-       struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tng_gpio *priv = gpiochip_get_data(gc);
        irq_hw_number_t gpio = irqd_to_hwirq(d);
 
        tng_irq_unmask_mask(priv, gpio, false);
@@ -236,7 +238,8 @@ static void tng_irq_mask(struct irq_data *d)
 
 static void tng_irq_unmask(struct irq_data *d)
 {
-       struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tng_gpio *priv = gpiochip_get_data(gc);
        irq_hw_number_t gpio = irqd_to_hwirq(d);
 
        gpiochip_enable_irq(&priv->chip, gpio);
index d87dd06db40d07a5dd6fc1c0fa83be06d8e291f5..9130c691a2dd324f3e9ef3c57ff7c4f31fccee6f 100644 (file)
 #define  TEGRA186_GPIO_SCR_SEC_REN             BIT(27)
 #define  TEGRA186_GPIO_SCR_SEC_G1W             BIT(9)
 #define  TEGRA186_GPIO_SCR_SEC_G1R             BIT(1)
-#define  TEGRA186_GPIO_FULL_ACCESS             (TEGRA186_GPIO_SCR_SEC_WEN | \
-                                                TEGRA186_GPIO_SCR_SEC_REN | \
-                                                TEGRA186_GPIO_SCR_SEC_G1R | \
-                                                TEGRA186_GPIO_SCR_SEC_G1W)
-#define  TEGRA186_GPIO_SCR_SEC_ENABLE          (TEGRA186_GPIO_SCR_SEC_WEN | \
-                                                TEGRA186_GPIO_SCR_SEC_REN)
 
 /* control registers */
 #define TEGRA186_GPIO_ENABLE_CONFIG 0x00
@@ -177,10 +171,18 @@ static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned
 
        value = __raw_readl(secure + TEGRA186_GPIO_SCR);
 
-       if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0)
-               return true;
+       /*
+        * When SCR_SEC_[R|W]EN is unset, then we have full read/write access to all the
+        * registers for given GPIO pin.
+        * When SCR_SEC[R|W]EN is set, then there is need to further check the accompanying
+        * SCR_SEC_G1[R|W] bit to determine read/write access to all the registers for given
+        * GPIO pin.
+        */
 
-       if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS)
+       if (((value & TEGRA186_GPIO_SCR_SEC_REN) == 0 ||
+            ((value & TEGRA186_GPIO_SCR_SEC_REN) && (value & TEGRA186_GPIO_SCR_SEC_G1R))) &&
+            ((value & TEGRA186_GPIO_SCR_SEC_WEN) == 0 ||
+            ((value & TEGRA186_GPIO_SCR_SEC_WEN) && (value & TEGRA186_GPIO_SCR_SEC_G1W))))
                return true;
 
        return false;
index df58a6a1a67ec51f1bb81ff1bd8364be8a46cc13..e4d4e55c08ad5a3a11b7133e3f717110c958b09f 100644 (file)
@@ -220,7 +220,7 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
            (kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
             kfd_mem_limit.max_ttm_mem_limit) ||
            (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed >
-            vram_size - reserved_for_pt)) {
+            vram_size - reserved_for_pt - atomic64_read(&adev->vram_pin_size))) {
                ret = -ENOMEM;
                goto release;
        }
@@ -1854,6 +1854,7 @@ err_node_allow:
 err_bo_create:
        amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id);
 err_reserve_limit:
+       amdgpu_sync_free(&(*mem)->sync);
        mutex_destroy(&(*mem)->lock);
        if (gobj)
                drm_gem_object_put(gobj);
@@ -2900,13 +2901,12 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
 
        amdgpu_sync_create(&sync_obj);
 
-       /* Validate BOs and map them to GPUVM (update VM page tables). */
+       /* Validate BOs managed by KFD */
        list_for_each_entry(mem, &process_info->kfd_bo_list,
                            validate_list) {
 
                struct amdgpu_bo *bo = mem->bo;
                uint32_t domain = mem->domain;
-               struct kfd_mem_attachment *attachment;
                struct dma_resv_iter cursor;
                struct dma_fence *fence;
 
@@ -2931,6 +2931,25 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
                                goto validate_map_fail;
                        }
                }
+       }
+
+       if (failed_size)
+               pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
+
+       /* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
+        * validations above would invalidate DMABuf imports again.
+        */
+       ret = process_validate_vms(process_info, &exec.ticket);
+       if (ret) {
+               pr_debug("Validating VMs failed, ret: %d\n", ret);
+               goto validate_map_fail;
+       }
+
+       /* Update mappings managed by KFD. */
+       list_for_each_entry(mem, &process_info->kfd_bo_list,
+                           validate_list) {
+               struct kfd_mem_attachment *attachment;
+
                list_for_each_entry(attachment, &mem->attachments, list) {
                        if (!attachment->is_mapped)
                                continue;
@@ -2947,18 +2966,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu *
                }
        }
 
-       if (failed_size)
-               pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size);
-
-       /* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO
-        * validations above would invalidate DMABuf imports again.
-        */
-       ret = process_validate_vms(process_info, &exec.ticket);
-       if (ret) {
-               pr_debug("Validating VMs failed, ret: %d\n", ret);
-               goto validate_map_fail;
-       }
-
        /* Update mappings not managed by KFD */
        list_for_each_entry(peer_vm, &process_info->vm_list_head,
                        vm_list_node) {
index a00cf4756ad0e2f371742e760183882773a80243..1569bef030eac166ea6194427ca9c8489cc62796 100644 (file)
@@ -1132,6 +1132,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev,
                return;
 
        amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id);
+       del_timer_sync(&ring->fence_drv.fallback_timer);
        amdgpu_ring_fini(ring);
        kfree(ring);
 }
index 2099159a693fa02e7c508c3aecdc9f695498cecd..f6d503432a9ef966b2748acfd801ff04730cad6e 100644 (file)
@@ -605,6 +605,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
        else
                amdgpu_bo_placement_from_domain(bo, bp->domain);
        if (bp->type == ttm_bo_type_kernel)
+               bo->tbo.priority = 2;
+       else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE))
                bo->tbo.priority = 1;
 
        if (!bp->destroy)
@@ -1241,14 +1243,18 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
  * amdgpu_bo_move_notify - notification about a memory move
  * @bo: pointer to a buffer object
  * @evict: if this move is evicting the buffer from the graphics address space
+ * @new_mem: new resource for backing the BO
  *
  * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs
  * bookkeeping.
  * TTM driver callback which is called when ttm moves a buffer.
  */
-void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
+void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
+                          bool evict,
+                          struct ttm_resource *new_mem)
 {
        struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
+       struct ttm_resource *old_mem = bo->resource;
        struct amdgpu_bo *abo;
 
        if (!amdgpu_bo_is_amdgpu_bo(bo))
@@ -1260,12 +1266,12 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
        amdgpu_bo_kunmap(abo);
 
        if (abo->tbo.base.dma_buf && !abo->tbo.base.import_attach &&
-           bo->resource->mem_type != TTM_PL_SYSTEM)
+           old_mem && old_mem->mem_type != TTM_PL_SYSTEM)
                dma_buf_move_notify(abo->tbo.base.dma_buf);
 
-       /* remember the eviction */
-       if (evict)
-               atomic64_inc(&adev->num_evictions);
+       /* move_notify is called before move happens */
+       trace_amdgpu_bo_move(abo, new_mem ? new_mem->mem_type : -1,
+                            old_mem ? old_mem->mem_type : -1);
 }
 
 void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
index fa03d9e4874cc65b39e038014ab15fc4e58ba858..bc42ccbde659ac5ef1854b3a90d5561916faf422 100644 (file)
@@ -328,7 +328,9 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
 int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
                           size_t buffer_size, uint32_t *metadata_size,
                           uint64_t *flags);
-void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict);
+void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
+                          bool evict,
+                          struct ttm_resource *new_mem);
 void amdgpu_bo_release_notify(struct ttm_buffer_object *bo);
 vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
 void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
index 1d71729e3f6bcef2c02f9e1ce252dc6cd6461b94..109fe557a02bc85d562310bdc5fff082ecf8f2ba 100644 (file)
@@ -419,7 +419,7 @@ bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
                return false;
 
        if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT ||
-           res->mem_type == AMDGPU_PL_PREEMPT)
+           res->mem_type == AMDGPU_PL_PREEMPT || res->mem_type == AMDGPU_PL_DOORBELL)
                return true;
 
        if (res->mem_type != TTM_PL_VRAM)
@@ -481,14 +481,16 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
 
        if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
                         bo->ttm == NULL)) {
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_bo_move_null(bo, new_mem);
-               goto out;
+               return 0;
        }
        if (old_mem->mem_type == TTM_PL_SYSTEM &&
            (new_mem->mem_type == TTM_PL_TT ||
             new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_bo_move_null(bo, new_mem);
-               goto out;
+               return 0;
        }
        if ((old_mem->mem_type == TTM_PL_TT ||
             old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
@@ -498,9 +500,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
                        return r;
 
                amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_resource_free(bo, &bo->resource);
                ttm_bo_assign_mem(bo, new_mem);
-               goto out;
+               return 0;
        }
 
        if (old_mem->mem_type == AMDGPU_PL_GDS ||
@@ -512,8 +515,9 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
            new_mem->mem_type == AMDGPU_PL_OA ||
            new_mem->mem_type == AMDGPU_PL_DOORBELL) {
                /* Nothing to save here */
+               amdgpu_bo_move_notify(bo, evict, new_mem);
                ttm_bo_move_null(bo, new_mem);
-               goto out;
+               return 0;
        }
 
        if (bo->type == ttm_bo_type_device &&
@@ -525,22 +529,23 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
                abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
        }
 
-       if (adev->mman.buffer_funcs_enabled) {
-               if (((old_mem->mem_type == TTM_PL_SYSTEM &&
-                     new_mem->mem_type == TTM_PL_VRAM) ||
-                    (old_mem->mem_type == TTM_PL_VRAM &&
-                     new_mem->mem_type == TTM_PL_SYSTEM))) {
-                       hop->fpfn = 0;
-                       hop->lpfn = 0;
-                       hop->mem_type = TTM_PL_TT;
-                       hop->flags = TTM_PL_FLAG_TEMPORARY;
-                       return -EMULTIHOP;
-               }
+       if (adev->mman.buffer_funcs_enabled &&
+           ((old_mem->mem_type == TTM_PL_SYSTEM &&
+             new_mem->mem_type == TTM_PL_VRAM) ||
+            (old_mem->mem_type == TTM_PL_VRAM &&
+             new_mem->mem_type == TTM_PL_SYSTEM))) {
+               hop->fpfn = 0;
+               hop->lpfn = 0;
+               hop->mem_type = TTM_PL_TT;
+               hop->flags = TTM_PL_FLAG_TEMPORARY;
+               return -EMULTIHOP;
+       }
 
+       amdgpu_bo_move_notify(bo, evict, new_mem);
+       if (adev->mman.buffer_funcs_enabled)
                r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
-       } else {
+       else
                r = -ENODEV;
-       }
 
        if (r) {
                /* Check that all memory is CPU accessible */
@@ -555,11 +560,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
                        return r;
        }
 
-       trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
-out:
-       /* update statistics */
+       /* update statistics after the move */
+       if (evict)
+               atomic64_inc(&adev->num_evictions);
        atomic64_add(bo->base.size, &adev->num_bytes_moved);
-       amdgpu_bo_move_notify(bo, evict);
        return 0;
 }
 
@@ -1559,7 +1563,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
 static void
 amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo)
 {
-       amdgpu_bo_move_notify(bo, false);
+       amdgpu_bo_move_notify(bo, false, NULL);
 }
 
 static struct ttm_device_funcs amdgpu_bo_driver = {
index 0df97c3e3a700dccc7bc84d4688e1dc8e1b8a1e2..f7c73533e336fac3358c58e387cb27e102ac2684 100644 (file)
@@ -774,6 +774,9 @@ static int umsch_mm_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (amdgpu_in_reset(adev) || adev->in_s0ix || adev->in_suspend)
+               return 0;
+
        return umsch_mm_test(adev);
 }
 
index 6695481f870f8a0dc61edfbe0d9947b19288bc25..c23d97d34b7ec55e90f2f9f2f81f9a87e7c7ff26 100644 (file)
@@ -205,7 +205,7 @@ disable_dpm:
        dpm_ctl &= 0xfffffffe; /* Disable DPM */
        WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl);
        dev_dbg(adev->dev, "%s: disable vpe dpm\n", __func__);
-       return 0;
+       return -EINVAL;
 }
 
 int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev)
index f90905ef32c76d62c3d490445b71388e9e0dc6bb..701146d649c353c9ace940af21a52c48fd37523c 100644 (file)
@@ -9186,7 +9186,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
                7 + /* PIPELINE_SYNC */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* VM_FLUSH */
+               4 + /* VM_FLUSH */
                8 + /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                4 + /* double SWITCH_BUFFER,
@@ -9276,7 +9276,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = {
                7 + /* gfx_v10_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v10_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v10_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_compute */
        .emit_ib = gfx_v10_0_ring_emit_ib_compute,
index f7325b02a191f726196d4ad0ac6fa3d090ab9977..f00e05aba46a4e40b97ef0cbfe093a3b17ef350f 100644 (file)
@@ -6192,7 +6192,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
                7 + /* PIPELINE_SYNC */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* VM_FLUSH */
+               4 + /* VM_FLUSH */
                8 + /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                5 + /* COND_EXEC */
@@ -6278,7 +6278,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_kiq = {
                7 + /* gfx_v11_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v11_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v11_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 7, /* gfx_v11_0_ring_emit_ib_compute */
        .emit_ib = gfx_v11_0_ring_emit_ib_compute,
index 6f97a6d0e6d0525cd6b7db25611d71506b3b0da6..99dbd2341120db5fa82b653daf76758052f7e306 100644 (file)
@@ -6981,7 +6981,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
                7 + /* gfx_v9_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v9_0_ring_emit_vm_flush */
                8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */
                7 + /* gfx_v9_0_emit_mem_sync */
                5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */
@@ -7019,7 +7018,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
                7 + /* gfx_v9_0_ring_emit_pipeline_sync */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
                SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
-               2 + /* gfx_v9_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */
        .emit_fence = gfx_v9_0_ring_emit_fence_kiq,
index 82eab49be82bb99807e5caabf5079b32dfd4cb26..e708468ac54dd57fbe8fd46b250ff1bc6dd42bb2 100644 (file)
@@ -368,7 +368,8 @@ static void sdma_v4_4_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        u32 ref_and_mask = 0;
        const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
-       ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
+       ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0
+                      << (ring->me % adev->sdma.num_inst_per_aid);
 
        sdma_v4_4_2_wait_reg_mem(ring, 0, 1,
                               adev->nbio.funcs->get_hdp_flush_done_offset(adev),
index 42f4bd250def622d490d355bac4883772def9c7a..da01b524b9f2a91dac57e75f7b1f1702116f6893 100644 (file)
@@ -280,17 +280,21 @@ static void sdma_v5_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
        u32 ref_and_mask = 0;
        const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
 
-       ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
-
-       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
-                         SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
-                         SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
-       amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
-       amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
-       amdgpu_ring_write(ring, ref_and_mask); /* reference */
-       amdgpu_ring_write(ring, ref_and_mask); /* mask */
-       amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
-                         SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
+       if (ring->me > 1) {
+               amdgpu_asic_flush_hdp(adev, ring);
+       } else {
+               ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
+
+               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
+                                 SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
+                                 SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
+               amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
+               amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
+               amdgpu_ring_write(ring, ref_and_mask); /* reference */
+               amdgpu_ring_write(ring, ref_and_mask); /* mask */
+               amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
+                                 SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
+       }
 }
 
 /**
index 769eb8f7bb3c570c90fb6325ecaeb0f49368ec24..09315dd5a1ec95a896ff62e3010746f1750757f8 100644 (file)
@@ -144,6 +144,12 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
                        WREG32(vpe_get_reg_offset(vpe, j, regVPEC_CNTL), ret);
        }
 
+       /* setup collaborate mode */
+       vpe_v6_1_set_collaborate_mode(vpe, true);
+       /* setup DPM */
+       if (amdgpu_vpe_configure_dpm(vpe))
+               dev_warn(adev->dev, "VPE failed to enable DPM\n");
+
        /*
         * For VPE 6.1.1, still only need to add master's offset, and psp will apply it to slave as well.
         * Here use instance 0 as master.
@@ -159,11 +165,7 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
                adev->vpe.cmdbuf_cpu_addr[0] = f32_offset;
                adev->vpe.cmdbuf_cpu_addr[1] = f32_cntl;
 
-               amdgpu_vpe_psp_update_sram(adev);
-               vpe_v6_1_set_collaborate_mode(vpe, true);
-               amdgpu_vpe_configure_dpm(vpe);
-
-               return 0;
+               return amdgpu_vpe_psp_update_sram(adev);
        }
 
        vpe_hdr = (const struct vpe_firmware_header_v1_0 *)adev->vpe.fw->data;
@@ -196,8 +198,6 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe)
        }
 
        vpe_v6_1_halt(vpe, false);
-       vpe_v6_1_set_collaborate_mode(vpe, true);
-       amdgpu_vpe_configure_dpm(vpe);
 
        return 0;
 }
index bdc01ca9609a7e57fac05ee60d6866a5950e2b07..5c8d81bfce7ab14938c9a45cc23f3ab6beac1dd0 100644 (file)
@@ -509,10 +509,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
        start = start_mgr << PAGE_SHIFT;
        end = (last_mgr + 1) << PAGE_SHIFT;
 
+       r = amdgpu_amdkfd_reserve_mem_limit(node->adev,
+                                       prange->npages * PAGE_SIZE,
+                                       KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
+                                       node->xcp ? node->xcp->id : 0);
+       if (r) {
+               dev_dbg(node->adev->dev, "failed to reserve VRAM, r: %ld\n", r);
+               return -ENOSPC;
+       }
+
        r = svm_range_vram_node_new(node, prange, true);
        if (r) {
                dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r);
-               return r;
+               goto out;
        }
        ttm_res_offset = (start_mgr - prange->start + prange->offset) << PAGE_SHIFT;
 
@@ -545,6 +554,11 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
                svm_range_vram_node_free(prange);
        }
 
+out:
+       amdgpu_amdkfd_unreserve_mem_limit(node->adev,
+                                       prange->npages * PAGE_SIZE,
+                                       KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
+                                       node->xcp ? node->xcp->id : 0);
        return r < 0 ? r : 0;
 }
 
index b79986412cd839bc89741a0b3bc1986daa2b10e4..451bb058cc62039eaf98c0e90487c0884042dfa4 100644 (file)
@@ -829,6 +829,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
        if (process) {
                pr_debug("Process already found\n");
        } else {
+               /* If the process just called exec(3), it is possible that the
+                * cleanup of the kfd_process (following the release of the mm
+                * of the old process image) is still in the cleanup work queue.
+                * Make sure to drain any job before trying to recreate any
+                * resource for this process.
+                */
+               flush_workqueue(kfd_process_wq);
+
                process = create_process(thread);
                if (IS_ERR(process))
                        goto out;
@@ -1922,6 +1930,8 @@ static int signal_eviction_fence(struct kfd_process *p)
        rcu_read_lock();
        ef = dma_fence_get_rcu_safe(&p->ef);
        rcu_read_unlock();
+       if (!ef)
+               return -EINVAL;
 
        ret = dma_fence_signal(ef);
        dma_fence_put(ef);
@@ -1949,10 +1959,9 @@ static void evict_process_worker(struct work_struct *work)
                 * they are responsible stopping the queues and scheduling
                 * the restore work.
                 */
-               if (!signal_eviction_fence(p))
-                       queue_delayed_work(kfd_restore_wq, &p->restore_work,
-                               msecs_to_jiffies(PROCESS_RESTORE_TIME_MS));
-               else
+               if (signal_eviction_fence(p) ||
+                   mod_delayed_work(kfd_restore_wq, &p->restore_work,
+                                    msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
                        kfd_process_restore_queues(p);
 
                pr_debug("Finished evicting pasid 0x%x\n", p->pasid);
@@ -2011,9 +2020,9 @@ static void restore_process_worker(struct work_struct *work)
        if (ret) {
                pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n",
                         p->pasid, PROCESS_BACK_OFF_TIME_MS);
-               ret = queue_delayed_work(kfd_restore_wq, &p->restore_work,
-                               msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS));
-               WARN(!ret, "reschedule restore work failed\n");
+               if (mod_delayed_work(kfd_restore_wq, &p->restore_work,
+                                    msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
+                       kfd_process_restore_queues(p);
        }
 }
 
index f0f7f48af4137acb088e2e903f803c345babc3ec..386875e6eb96bacb6585ae58c5620db1f41fde92 100644 (file)
@@ -3426,7 +3426,7 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
                                mm, KFD_MIGRATE_TRIGGER_PREFETCH);
        *migrated = !r;
 
-       return r;
+       return 0;
 }
 
 int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence)
index 6d2f60c61decc36711953fa5b0dd67888c652a32..d6e71aa808d881f544053aa2b9c54e5d367cda79 100644 (file)
@@ -3029,6 +3029,7 @@ static int dm_resume(void *handle)
                        dc_stream_release(dm_new_crtc_state->stream);
                        dm_new_crtc_state->stream = NULL;
                }
+               dm_new_crtc_state->base.color_mgmt_changed = true;
        }
 
        for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) {
@@ -4536,15 +4537,18 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
        /* Determine whether to enable Replay support by default. */
        if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) {
                switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
-               case IP_VERSION(3, 1, 4):
-               case IP_VERSION(3, 1, 5):
-               case IP_VERSION(3, 1, 6):
-               case IP_VERSION(3, 2, 0):
-               case IP_VERSION(3, 2, 1):
-               case IP_VERSION(3, 5, 0):
-               case IP_VERSION(3, 5, 1):
-                       replay_feature_enabled = true;
-                       break;
+/*
+ * Disabled by default due to https://gitlab.freedesktop.org/drm/amd/-/issues/3344
+ *             case IP_VERSION(3, 1, 4):
+ *             case IP_VERSION(3, 1, 5):
+ *             case IP_VERSION(3, 1, 6):
+ *             case IP_VERSION(3, 2, 0):
+ *             case IP_VERSION(3, 2, 1):
+ *             case IP_VERSION(3, 5, 0):
+ *             case IP_VERSION(3, 5, 1):
+ *                     replay_feature_enabled = true;
+ *                     break;
+ */
                default:
                        replay_feature_enabled = amdgpu_dc_feature_mask & DC_REPLAY_MASK;
                        break;
index eee4945653e2d18d09f8bfc8175251499950f53c..c7715a17f388b34f3c2b9b0c3f2a26916f8bb509 100644 (file)
@@ -1495,7 +1495,9 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1596,7 +1598,9 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1681,7 +1685,9 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1780,7 +1786,9 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1865,7 +1873,9 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -1964,7 +1974,9 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2045,7 +2057,9 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2141,7 +2155,9 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2220,7 +2236,9 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2276,7 +2294,9 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2347,7 +2367,9 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
@@ -2418,7 +2440,9 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
        for (i = 0; i < MAX_PIPES; i++) {
                pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
                if (pipe_ctx->stream &&
-                   pipe_ctx->stream->link == aconnector->dc_link)
+                   pipe_ctx->stream->link == aconnector->dc_link &&
+                   pipe_ctx->stream->sink &&
+                   pipe_ctx->stream->sink == aconnector->dc_sink)
                        break;
        }
 
index 05f392501c0ae3572250061b31defef7cde51fb5..ab31643b109698ec95a11da1aabdfa258705989a 100644 (file)
@@ -2948,6 +2948,7 @@ static enum bp_result construct_integrated_info(
                                result = get_integrated_info_v2_1(bp, info);
                                break;
                        case 2:
+                       case 3:
                                result = get_integrated_info_v2_2(bp, info);
                                break;
                        default:
index 644da463732093f9d3798b3de9565b5f7fd9ea0b..5506cf9b3672f80992c846b8686613427976bb81 100644 (file)
@@ -145,6 +145,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
         */
        clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
        if (safe_to_lower) {
+               if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
+                       dcn315_smu_set_dtbclk(clk_mgr, false);
+                       clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+               }
                /* check that we're not already in lower */
                if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
                        display_count = dcn315_get_active_display_cnt_wa(dc, context);
@@ -160,6 +164,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
                        }
                }
        } else {
+               if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
+                       dcn315_smu_set_dtbclk(clk_mgr, true);
+                       clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+               }
                /* check that we're not already in D0 */
                if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) {
                        union display_idle_optimization_u idle_info = { 0 };
index bec252e1dd27a98263b5bd3299cc3dfd8ed089e9..e506e4f969ca9ffc90bdf8714c936a72aa9c2b17 100644 (file)
@@ -712,8 +712,12 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                                         * since we calculate mode support based on softmax being the max UCLK
                                         * frequency.
                                         */
-                                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
-                                                       dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
+                                       if (dc->debug.disable_dc_mode_overwrite) {
+                                               dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+                                               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+                                       } else
+                                               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                                                               dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
                                } else {
                                        dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
                                }
@@ -746,8 +750,13 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
                if (clk_mgr_base->clks.p_state_change_support &&
                                (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support) &&
-                               !dc->work_arounds.clock_update_disable_mask.uclk)
+                               !dc->work_arounds.clock_update_disable_mask.uclk) {
+                       if (dc->clk_mgr->dc_mode_softmax_enabled && dc->debug.disable_dc_mode_overwrite)
+                               dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
+                                               max((int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)));
+
                        dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
+               }
 
                if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
                                clk_mgr_base->clks.num_ways > new_clocks->num_ways) {
index 03b554e912a20d4ae58e5161d55943eb0bb7a0d9..d68c83e40d4d6c3bd89e66cc5ecc63ca14c010d0 100644 (file)
@@ -1801,6 +1801,9 @@ bool dc_validate_boot_timing(const struct dc *dc,
                return false;
        }
 
+       if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)
+               return false;
+
        if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) {
                DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n");
                return false;
index 5b7ad38f85e08f422c32e48bdb4b384b8bb75e08..65e45a0b4ff34351013a6e7f5debe0eb8c676e8d 100644 (file)
@@ -395,6 +395,12 @@ void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
                                x),
                        25));
 
+       // If y rounds up to integer, carry it over to x.
+       if (y >> 25) {
+               x += 1;
+               y = 0;
+       }
+
        switch (stream_encoder_inst) {
        case 0:
                REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0,
index deb6d162a2d5c00df00b069a57e885b34a18e939..7307b7b8d8ad7595bcfbf09e0a39786df389398f 100644 (file)
@@ -291,6 +291,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
        .do_urgent_latency_adjustment = false,
        .urgent_latency_adjustment_fabric_clock_component_us = 0,
        .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+       .dispclk_dppclk_vco_speed_mhz = 2400.0,
        .num_chans = 4,
        .dummy_pstate_latency_us = 10.0
 };
@@ -438,6 +439,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
        .do_urgent_latency_adjustment = false,
        .urgent_latency_adjustment_fabric_clock_component_us = 0,
        .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+       .dispclk_dppclk_vco_speed_mhz = 2500.0,
 };
 
 void dcn31_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
index 5491b707cec881b9854ab96834503c1e88053380..5a965c26bf2095fa44c5f81e89c0feded2b99b38 100644 (file)
@@ -270,7 +270,7 @@ static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
 
        /* Error check whether requested and allocated are equal */
        req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
-       if (req_bw == link->dpia_bw_alloc_config.allocated_bw) {
+       if (req_bw && (req_bw == link->dpia_bw_alloc_config.allocated_bw)) {
                DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n",
                        __func__, link->link_index);
        }
@@ -341,6 +341,14 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
                        ret = true;
                        init_usb4_bw_struct(link);
                        link->dpia_bw_alloc_config.bw_alloc_enabled = true;
+
+                       /*
+                        * During DP tunnel creation, CM preallocates BW and reduces estimated BW of other
+                        * DPIA. CM release preallocation only when allocation is complete. Do zero alloc
+                        * to make the CM to release preallocation and update estimated BW correctly for
+                        * all DPIAs per host router
+                        */
+                       link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, 0);
                }
        }
 
index a2387cea1af9a184124121b3d631740e01c41484..622214b365a25aa50fc21a6dde5b7e6f192a55b7 100644 (file)
@@ -2449,6 +2449,7 @@ static bool dcn20_resource_construct(
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
        dc->caps.extended_aux_timeout_support = true;
+       dc->caps.dmcub_support = true;
 
        /* Color pipeline capabilities */
        dc->caps.color.dpp.dcn_arch = 1;
index f09b9d49297e815f469cc54be1c1130711576a12..bbd0169010c2d50a2454e64f53342a9304ac6e89 100644 (file)
@@ -4261,6 +4261,13 @@ static int amdgpu_od_set_init(struct amdgpu_device *adev)
                }
        }
 
+       /*
+        * If gpu_od is the only member in the list, that means gpu_od is an
+        * empty directory, so remove it.
+        */
+       if (list_is_singular(&adev->pm.od_kobj_list))
+               goto err_out;
+
        return 0;
 
 err_out:
index 3957af057d54ff1ed8d5f5f9545e51562cb3973c..c977ebe88001df958c74dab7cd771c39807f6c62 100644 (file)
@@ -2294,6 +2294,17 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
        return sizeof(*gpu_metrics);
 }
 
+static void smu_v13_0_6_restore_pci_config(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+       int i;
+
+       for (i = 0; i < 16; i++)
+               pci_write_config_dword(adev->pdev, i * 4,
+                                      adev->pdev->saved_config_space[i]);
+       pci_restore_msi_state(adev->pdev);
+}
+
 static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
 {
        int ret = 0, index;
@@ -2315,6 +2326,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
        /* Restore the config space saved during init */
        amdgpu_device_load_pci_state(adev->pdev);
 
+       /* Certain platforms have switches which assign virtual BAR values to
+        * devices. OS uses the virtual BAR values and device behind the switch
+        * is assgined another BAR value. When device's config space registers
+        * are queried, switch returns the virtual BAR values. When mode-2 reset
+        * is performed, switch is unaware of it, and will continue to return
+        * the same virtual values to the OS.This affects
+        * pci_restore_config_space() API as it doesn't write the value saved if
+        * the current value read from config space is the same as what is
+        * saved. As a workaround, make sure the config space is restored
+        * always.
+        */
+       if (!(adev->flags & AMD_IS_APU))
+               smu_v13_0_6_restore_pci_config(smu);
+
        dev_dbg(smu->adev->dev, "wait for reset ack\n");
        do {
                ret = smu_cmn_wait_for_response(smu);
index e440f458b6633d71ab5c49c5e07c3687b6b025e8..93337543aac32b50121f1698c3c79950e3e67f4f 100644 (file)
@@ -224,8 +224,8 @@ __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
 
        __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
 
-       drm_format_conv_state_copy(&shadow_plane_state->fmtcnv_state,
-                                  &new_shadow_plane_state->fmtcnv_state);
+       drm_format_conv_state_copy(&new_shadow_plane_state->fmtcnv_state,
+                                  &shadow_plane_state->fmtcnv_state);
 }
 EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
 
index 734412aae94dde5c08e6e575c405fd9805e98d8d..a9bf426f69b365caa5b335e167109b7c7f5be90e 100644 (file)
@@ -164,26 +164,6 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value)
                *value = gpu->identity.eco_id;
                break;
 
-       case ETNAVIV_PARAM_GPU_NN_CORE_COUNT:
-               *value = gpu->identity.nn_core_count;
-               break;
-
-       case ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE:
-               *value = gpu->identity.nn_mad_per_core;
-               break;
-
-       case ETNAVIV_PARAM_GPU_TP_CORE_COUNT:
-               *value = gpu->identity.tp_core_count;
-               break;
-
-       case ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE:
-               *value = gpu->identity.on_chip_sram_size;
-               break;
-
-       case ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE:
-               *value = gpu->identity.axi_sram_size;
-               break;
-
        default:
                DBG("%s: invalid param: %u", dev_name(gpu->dev), param);
                return -EINVAL;
@@ -663,8 +643,8 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
        /* Disable TX clock gating on affected core revisions. */
        if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
            etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
-           etnaviv_is_model_rev(gpu, GC2000, 0x6202) ||
-           etnaviv_is_model_rev(gpu, GC2000, 0x6203))
+           etnaviv_is_model_rev(gpu, GC7000, 0x6202) ||
+           etnaviv_is_model_rev(gpu, GC7000, 0x6203))
                pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
 
        /* Disable SE and RA clock gating on affected core revisions. */
index 7d5e9158e13c1aca6df49f254b00dd72d3a27a9e..197e0037732ec84998aba60b1769a2fc305ea1bf 100644 (file)
@@ -54,18 +54,6 @@ struct etnaviv_chip_identity {
        /* Number of Neural Network cores. */
        u32 nn_core_count;
 
-       /* Number of MAD units per Neural Network core. */
-       u32 nn_mad_per_core;
-
-       /* Number of Tensor Processing cores. */
-       u32 tp_core_count;
-
-       /* Size in bytes of the SRAM inside the NPU. */
-       u32 on_chip_sram_size;
-
-       /* Size in bytes of the SRAM across the AXI bus. */
-       u32 axi_sram_size;
-
        /* Size of the vertex cache. */
        u32 vertex_cache_size;
 
index d8e7334de8ceac8d608ad97c04c8c3184db9267b..8665f2658d51b302f7e2e8ad9f52a438ccbc5d6f 100644 (file)
@@ -17,10 +17,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 128,
                .shader_core_count = 1,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 8,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -52,11 +48,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .register_max = 64,
                .thread_count = 256,
                .shader_core_count = 1,
-               .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 8,
                .vertex_output_buffer_size = 512,
                .pixel_pipes = 1,
@@ -89,10 +80,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 512,
                .shader_core_count = 2,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -125,10 +112,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 512,
                .shader_core_count = 2,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -160,11 +143,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .register_max = 64,
                .thread_count = 512,
                .shader_core_count = 2,
-               .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -197,10 +175,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 1024,
                .shader_core_count = 4,
                .nn_core_count = 0,
-               .nn_mad_per_core = 0,
-               .tp_core_count = 0,
-               .on_chip_sram_size = 0,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 2,
@@ -233,10 +207,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 256,
                .shader_core_count = 1,
                .nn_core_count = 8,
-               .nn_mad_per_core = 64,
-               .tp_core_count = 4,
-               .on_chip_sram_size = 524288,
-               .axi_sram_size = 1048576,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
@@ -269,10 +239,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
                .thread_count = 256,
                .shader_core_count = 1,
                .nn_core_count = 6,
-               .nn_mad_per_core = 64,
-               .tp_core_count = 3,
-               .on_chip_sram_size = 262144,
-               .axi_sram_size = 0,
                .vertex_cache_size = 16,
                .vertex_output_buffer_size = 1024,
                .pixel_pipes = 1,
index 4f302cd5e1a6ca3a6fb1f15241c9568fc5ea74e7..58fed80c7392a02c317011365c9ce3165412bf3d 100644 (file)
@@ -34,7 +34,6 @@ gma500_gfx-y += \
          psb_intel_lvds.o \
          psb_intel_modes.o \
          psb_intel_sdvo.o \
-         psb_lid.o \
          psb_irq.o
 
 gma500_gfx-$(CONFIG_ACPI) +=  opregion.o
index dcfcd7b89d4a1dfe9fb5092b7aa63a111785b7fc..6dece8f0e380f7a447d582d6f914caa8d3d3704a 100644 (file)
@@ -73,8 +73,7 @@ static int psb_backlight_setup(struct drm_device *dev)
        }
 
        psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS);
-       /* This must occur after the backlight is properly initialised */
-       psb_lid_timer_init(dev_priv);
+
        return 0;
 }
 
@@ -259,8 +258,6 @@ static int psb_chip_setup(struct drm_device *dev)
 
 static void psb_chip_teardown(struct drm_device *dev)
 {
-       struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
-       psb_lid_timer_takedown(dev_priv);
        gma_intel_teardown_gmbus(dev);
 }
 
index c5edfa4aa4ccdd526fa39a53e30f24a0fee41d28..83c17689c454f7c27955ad37dcf7ae2a6399c95c 100644 (file)
 #define PSB_NUM_VBLANKS 2
 
 #define PSB_WATCHDOG_DELAY (HZ * 2)
-#define PSB_LID_DELAY (HZ / 10)
 
 #define PSB_MAX_BRIGHTNESS             100
 
@@ -491,11 +490,7 @@ struct drm_psb_private {
        /* Hotplug handling */
        struct work_struct hotplug_work;
 
-       /* LID-Switch */
-       spinlock_t lid_lock;
-       struct timer_list lid_timer;
        struct psb_intel_opregion opregion;
-       u32 lid_last_state;
 
        /* Watchdog */
        uint32_t apm_reg;
@@ -591,10 +586,6 @@ struct psb_ops {
        int i2c_bus;            /* I2C bus identifier for Moorestown */
 };
 
-/* psb_lid.c */
-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
-
 /* modesetting */
 extern void psb_modeset_init(struct drm_device *dev);
 extern void psb_modeset_cleanup(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c
deleted file mode 100644 (file)
index 58a7fe3..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- **************************************************************************/
-
-#include <linux/spinlock.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_reg.h"
-
-static void psb_lid_timer_func(struct timer_list *t)
-{
-       struct drm_psb_private *dev_priv = from_timer(dev_priv, t, lid_timer);
-       struct drm_device *dev = (struct drm_device *)&dev_priv->dev;
-       struct timer_list *lid_timer = &dev_priv->lid_timer;
-       unsigned long irq_flags;
-       u32 __iomem *lid_state = dev_priv->opregion.lid_state;
-       u32 pp_status;
-
-       if (readl(lid_state) == dev_priv->lid_last_state)
-               goto lid_timer_schedule;
-
-       if ((readl(lid_state)) & 0x01) {
-               /*lid state is open*/
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0 &&
-                        (pp_status & PP_SEQUENCE_MASK) != 0);
-
-               if (REG_READ(PP_STATUS) & PP_ON) {
-                       /*FIXME: should be backlight level before*/
-                       psb_intel_lvds_set_brightness(dev, 100);
-               } else {
-                       DRM_DEBUG("LVDS panel never powered up");
-                       return;
-               }
-       } else {
-               psb_intel_lvds_set_brightness(dev, 0);
-
-               REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
-               do {
-                       pp_status = REG_READ(PP_STATUS);
-               } while ((pp_status & PP_ON) == 0);
-       }
-       dev_priv->lid_last_state =  readl(lid_state);
-
-lid_timer_schedule:
-       spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-       if (!timer_pending(lid_timer)) {
-               lid_timer->expires = jiffies + PSB_LID_DELAY;
-               add_timer(lid_timer);
-       }
-       spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_init(struct drm_psb_private *dev_priv)
-{
-       struct timer_list *lid_timer = &dev_priv->lid_timer;
-       unsigned long irq_flags;
-
-       spin_lock_init(&dev_priv->lid_lock);
-       spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-
-       timer_setup(lid_timer, psb_lid_timer_func, 0);
-
-       lid_timer->expires = jiffies + PSB_LID_DELAY;
-
-       add_timer(lid_timer);
-       spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
-{
-       del_timer_sync(&dev_priv->lid_timer);
-}
-
index 408dbe63a90cfd5c5a5b51aa80fdd8bf7aaadde5..a0c5c41c8aa24a454c7c6ec10529ef8062ee3e9d 100644 (file)
@@ -7,13 +7,14 @@
 #include "pvr_rogue_mips.h"
 
 #include <asm/page.h>
+#include <linux/math.h>
 #include <linux/types.h>
 
 /* Forward declaration from pvr_gem.h. */
 struct pvr_gem_object;
 
-#define PVR_MIPS_PT_PAGE_COUNT ((ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K) \
-                               >> PAGE_SHIFT)
+#define PVR_MIPS_PT_PAGE_COUNT DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
+
 /**
  * struct pvr_fw_mips_data - MIPS-specific data
  */
index 6f5d376d8fcc1ecb6d9faa80b4b06ba4cd1b21e4..a11d16a16c3b25d288c07bba8ce4f545b3bda32d 100644 (file)
@@ -15,7 +15,9 @@ struct nvkm_gsp_mem {
 };
 
 struct nvkm_gsp_radix3 {
-       struct nvkm_gsp_mem mem[3];
+       struct nvkm_gsp_mem lvl0;
+       struct nvkm_gsp_mem lvl1;
+       struct sg_table lvl2;
 };
 
 int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
index adc60b25f8e6c61e51c7db37805fa24a89378fae..141b0a513bf52814e1977e916d81593b215de0d9 100644 (file)
@@ -205,7 +205,9 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw)
                break;
        case NVKM_FIRMWARE_IMG_DMA:
                nvkm_memory_unref(&memory);
-               dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys);
+               dma_unmap_single(fw->device->dev, fw->phys, sg_dma_len(&fw->mem.sgl),
+                                DMA_TO_DEVICE);
+               kfree(fw->img);
                break;
        case NVKM_FIRMWARE_IMG_SGT:
                nvkm_memory_unref(&memory);
@@ -235,14 +237,17 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name,
                fw->img = kmemdup(src, fw->len, GFP_KERNEL);
                break;
        case NVKM_FIRMWARE_IMG_DMA: {
-               dma_addr_t addr;
-
                len = ALIGN(fw->len, PAGE_SIZE);
 
-               fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL);
-               if (fw->img) {
-                       memcpy(fw->img, src, fw->len);
-                       fw->phys = addr;
+               fw->img = kmalloc(len, GFP_KERNEL);
+               if (!fw->img)
+                       return -ENOMEM;
+
+               memcpy(fw->img, src, fw->len);
+               fw->phys = dma_map_single(fw->device->dev, fw->img, len, DMA_TO_DEVICE);
+               if (dma_mapping_error(fw->device->dev, fw->phys)) {
+                       kfree(fw->img);
+                       return -EFAULT;
                }
 
                sg_init_one(&fw->mem.sgl, fw->img, len);
index 9858c1438aa7feda7d84ff5442f611b23f101b2d..abe41f7a34045531e90ca98b74ab03aedf5538c5 100644 (file)
@@ -1624,7 +1624,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
        meta->magic = GSP_FW_WPR_META_MAGIC;
        meta->revision = GSP_FW_WPR_META_REVISION;
 
-       meta->sysmemAddrOfRadix3Elf = gsp->radix3.mem[0].addr;
+       meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
        meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size;
 
        meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
@@ -1919,8 +1919,9 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct sg_table *sgt)
 static void
 nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3)
 {
-       for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--)
-               nvkm_gsp_mem_dtor(gsp, &rx3->mem[i]);
+       nvkm_gsp_sg_free(gsp->subdev.device, &rx3->lvl2);
+       nvkm_gsp_mem_dtor(gsp, &rx3->lvl1);
+       nvkm_gsp_mem_dtor(gsp, &rx3->lvl0);
 }
 
 /**
@@ -1960,36 +1961,60 @@ static int
 nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
                   struct nvkm_gsp_radix3 *rx3)
 {
-       u64 addr;
+       struct sg_dma_page_iter sg_dma_iter;
+       struct scatterlist *sg;
+       size_t bufsize;
+       u64 *pte;
+       int ret, i, page_idx = 0;
 
-       for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) {
-               u64 *ptes;
-               size_t bufsize;
-               int ret, idx;
+       ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl0);
+       if (ret)
+               return ret;
 
-               bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
-               ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]);
-               if (ret)
-                       return ret;
+       ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl1);
+       if (ret)
+               goto lvl1_fail;
 
-               ptes = rx3->mem[i].data;
-               if (i == 2) {
-                       struct scatterlist *sgl;
+       // Allocate level 2
+       bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
+       ret = nvkm_gsp_sg(gsp->subdev.device, bufsize, &rx3->lvl2);
+       if (ret)
+               goto lvl2_fail;
 
-                       for_each_sgtable_dma_sg(sgt, sgl, idx) {
-                               for (int j = 0; j < sg_dma_len(sgl) / GSP_PAGE_SIZE; j++)
-                                       *ptes++ = sg_dma_address(sgl) + (GSP_PAGE_SIZE * j);
-                       }
-               } else {
-                       for (int j = 0; j < size / GSP_PAGE_SIZE; j++)
-                               *ptes++ = addr + GSP_PAGE_SIZE * j;
+       // Write the bus address of level 1 to level 0
+       pte = rx3->lvl0.data;
+       *pte = rx3->lvl1.addr;
+
+       // Write the bus address of each page in level 2 to level 1
+       pte = rx3->lvl1.data;
+       for_each_sgtable_dma_page(&rx3->lvl2, &sg_dma_iter, 0)
+               *pte++ = sg_page_iter_dma_address(&sg_dma_iter);
+
+       // Finally, write the bus address of each page in sgt to level 2
+       for_each_sgtable_sg(&rx3->lvl2, sg, i) {
+               void *sgl_end;
+
+               pte = sg_virt(sg);
+               sgl_end = (void *)pte + sg->length;
+
+               for_each_sgtable_dma_page(sgt, &sg_dma_iter, page_idx) {
+                       *pte++ = sg_page_iter_dma_address(&sg_dma_iter);
+                       page_idx++;
+
+                       // Go to the next scatterlist for level 2 if we've reached the end
+                       if ((void *)pte >= sgl_end)
+                               break;
                }
+       }
 
-               size = rx3->mem[i].size;
-               addr = rx3->mem[i].addr;
+       if (ret) {
+lvl2_fail:
+               nvkm_gsp_mem_dtor(gsp, &rx3->lvl1);
+lvl1_fail:
+               nvkm_gsp_mem_dtor(gsp, &rx3->lvl0);
        }
 
-       return 0;
+       return ret;
 }
 
 int
@@ -2021,7 +2046,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
                sr = gsp->sr.meta.data;
                sr->magic = GSP_FW_SR_META_MAGIC;
                sr->revision = GSP_FW_SR_META_REVISION;
-               sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.mem[0].addr;
+               sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
                sr->sizeOfSuspendResumeData = len;
 
                mbox0 = lower_32_bits(gsp->sr.meta.addr);
index d037b3b8b9993458a8f1615902363a6663a94052..5b15d0294836756a1e3cfced716b86cd4e093e76 100644 (file)
@@ -177,7 +177,7 @@ config DRM_PANEL_ILITEK_IL9322
 
 config DRM_PANEL_ILITEK_ILI9341
        tristate "Ilitek ILI9341 240x320 QVGA panels"
-       depends on OF && SPI
+       depends on SPI
        select DRM_KMS_HELPER
        select DRM_GEM_DMA_HELPER
        depends on BACKLIGHT_CLASS_DEVICE
index 3574681891e816f5f32a012814e22f7335f687d2..b933380b7eb783fad1d1101b61d7a630ade11315 100644 (file)
@@ -22,8 +22,9 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 
@@ -421,7 +422,7 @@ static int ili9341_dpi_prepare(struct drm_panel *panel)
 
        ili9341_dpi_init(ili);
 
-       return ret;
+       return 0;
 }
 
 static int ili9341_dpi_enable(struct drm_panel *panel)
@@ -691,7 +692,7 @@ static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc,
         * Every new incarnation of this display must have a unique
         * data entry for the system in this driver.
         */
-       ili->conf = of_device_get_match_data(dev);
+       ili->conf = device_get_match_data(dev);
        if (!ili->conf) {
                dev_err(dev, "missing device configuration\n");
                return -ENODEV;
@@ -714,18 +715,18 @@ static int ili9341_probe(struct spi_device *spi)
 
        reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(reset))
-               dev_err(dev, "Failed to get gpio 'reset'\n");
+               return dev_err_probe(dev, PTR_ERR(reset), "Failed to get gpio 'reset'\n");
 
        dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
        if (IS_ERR(dc))
-               dev_err(dev, "Failed to get gpio 'dc'\n");
+               return dev_err_probe(dev, PTR_ERR(dc), "Failed to get gpio 'dc'\n");
 
        if (!strcmp(id->name, "sf-tc240t-9370-t"))
                return ili9341_dpi_probe(spi, dc, reset);
        else if (!strcmp(id->name, "yx240qv29"))
                return ili9341_dbi_probe(spi, dc, reset);
 
-       return -1;
+       return -ENODEV;
 }
 
 static void ili9341_remove(struct spi_device *spi)
index 578a7c37f00bd7a3c8a5f1d5e93d4cd80fdc6cc9..d776e3f87064fa2e86387fb69a0570259ac95fe7 100644 (file)
@@ -92,7 +92,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
         */
        if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
                page_flags |= TTM_TT_FLAG_DECRYPTED;
-               drm_info(ddev, "TT memory decryption enabled.");
+               drm_info_once(ddev, "TT memory decryption enabled.");
        }
 
        bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
index e5eb21a471a6010aa956c811522956f27b99a096..00144632c600ebb6a63ab80c55eae90eed95375f 100644 (file)
@@ -204,6 +204,7 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
                             VMW_BO_DOMAIN_VRAM,
                             VMW_BO_DOMAIN_VRAM);
        buf->places[0].lpfn = PFN_UP(bo->resource->size);
+       buf->busy_places[0].lpfn = PFN_UP(bo->resource->size);
        ret = ttm_bo_validate(bo, &buf->placement, &ctx);
 
        /* For some reason we didn't end up at the start of vram */
index 2a0cda324703147ef36ff83cd891c70c3395c11d..5efc6a766f64e467a68223376b2a97aa62b278e6 100644 (file)
@@ -991,7 +991,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv,
        }
 
        event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
-       event->event.base.length = sizeof(*event);
+       event->event.base.length = sizeof(event->event);
        event->event.user_data = user_data;
 
        ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
index 420eba0e4be00b8d241bfe2d344837b262095785..854a7bb53567495a4cade766f62c985e8106a70d 100644 (file)
@@ -84,7 +84,8 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev)
 #define IS_ROCKETLAKE(dev_priv)        IS_PLATFORM(dev_priv, XE_ROCKETLAKE)
 #define IS_DG1(dev_priv)        IS_PLATFORM(dev_priv, XE_DG1)
 #define IS_ALDERLAKE_S(dev_priv) IS_PLATFORM(dev_priv, XE_ALDERLAKE_S)
-#define IS_ALDERLAKE_P(dev_priv) IS_PLATFORM(dev_priv, XE_ALDERLAKE_P)
+#define IS_ALDERLAKE_P(dev_priv) (IS_PLATFORM(dev_priv, XE_ALDERLAKE_P) || \
+                                 IS_PLATFORM(dev_priv, XE_ALDERLAKE_N))
 #define IS_XEHPSDV(dev_priv) (dev_priv && 0)
 #define IS_DG2(dev_priv)       IS_PLATFORM(dev_priv, XE_DG2)
 #define IS_PONTEVECCHIO(dev_priv) IS_PLATFORM(dev_priv, XE_PVC)
index a0afe1ba6dd5ce2cb6c3dfd53b60874ebb9c747c..f9705430ada93057c3094c1cb20ec400ae64ffdd 100644 (file)
@@ -378,7 +378,9 @@ static int gt_fw_domain_init(struct xe_gt *gt)
                         err);
 
        /* Initialize CCS mode sysfs after early initialization of HW engines */
-       xe_gt_ccs_mode_sysfs_init(gt);
+       err = xe_gt_ccs_mode_sysfs_init(gt);
+       if (err)
+               goto err_force_wake;
 
        /*
         * Stash hardware-reported version.  Since this register does not exist
index 529fc286cd06c6d46bcfde3b39bcd0e0befb8b44..396aeb5b992424b24ceeabeee9d76581ef404dbe 100644 (file)
@@ -167,25 +167,20 @@ static void xe_gt_ccs_mode_sysfs_fini(struct drm_device *drm, void *arg)
  * and it is expected that there are no open drm clients while doing so.
  * The number of available compute slices is exposed to user through a per-gt
  * 'num_cslices' sysfs interface.
+ *
+ * Returns: Returns error value for failure and 0 for success.
  */
-void xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt)
+int xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt)
 {
        struct xe_device *xe = gt_to_xe(gt);
        int err;
 
        if (!xe_gt_ccs_mode_enabled(gt))
-               return;
+               return 0;
 
        err = sysfs_create_files(gt->sysfs, gt_ccs_mode_attrs);
-       if (err) {
-               drm_warn(&xe->drm, "Sysfs creation for ccs_mode failed err: %d\n", err);
-               return;
-       }
+       if (err)
+               return err;
 
-       err = drmm_add_action_or_reset(&xe->drm, xe_gt_ccs_mode_sysfs_fini, gt);
-       if (err) {
-               sysfs_remove_files(gt->sysfs, gt_ccs_mode_attrs);
-               drm_warn(&xe->drm, "%s: drmm_add_action_or_reset failed, err: %d\n",
-                        __func__, err);
-       }
+       return drmm_add_action_or_reset(&xe->drm, xe_gt_ccs_mode_sysfs_fini, gt);
 }
index f39975aaaab0db1c62e06cc912afd74d668b1303..f8779852cf0d26587e3b579f351dcdeaf93efa5d 100644 (file)
@@ -12,7 +12,7 @@
 #include "xe_platform_types.h"
 
 void xe_gt_apply_ccs_mode(struct xe_gt *gt);
-void xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt);
+int xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt);
 
 static inline bool xe_gt_ccs_mode_enabled(const struct xe_gt *gt)
 {
index 355edd4d758af7cf1e4c15daf00ed86bbd4de898..7f32547f94b266092afc75bd387f8b6b59f18cec 100644 (file)
@@ -1054,10 +1054,10 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
                                                           adj_len);
                break;
        case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
-               ret = xe_guc_relay_process_guc2pf(&guc->relay, payload, adj_len);
+               ret = xe_guc_relay_process_guc2pf(&guc->relay, hxg, hxg_len);
                break;
        case XE_GUC_ACTION_GUC2VF_RELAY_FROM_PF:
-               ret = xe_guc_relay_process_guc2vf(&guc->relay, payload, adj_len);
+               ret = xe_guc_relay_process_guc2vf(&guc->relay, hxg, hxg_len);
                break;
        default:
                drm_err(&xe->drm, "unexpected action 0x%04x\n", action);
index b545f850087cd8b9a7ae0031a2feb1fadba9458b..6b9b1cbedd379e35f78d6b943d46991f85caefa5 100644 (file)
@@ -53,7 +53,6 @@ static int huc_alloc_gsc_pkt(struct xe_huc *huc)
        struct xe_gt *gt = huc_to_gt(huc);
        struct xe_device *xe = gt_to_xe(gt);
        struct xe_bo *bo;
-       int err;
 
        /* we use a single object for both input and output */
        bo = xe_bo_create_pin_map(xe, gt_to_tile(gt), NULL,
@@ -66,13 +65,7 @@ static int huc_alloc_gsc_pkt(struct xe_huc *huc)
 
        huc->gsc_pkt = bo;
 
-       err = drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc);
-       if (err) {
-               free_gsc_pkt(&xe->drm, huc);
-               return err;
-       }
-
-       return 0;
+       return drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc);
 }
 
 int xe_huc_init(struct xe_huc *huc)
index 3d4c8f342e215ed39263ba5c4c01079072dfcbbd..32cd0c978aa289efadec2f047dec7dd08b103de3 100644 (file)
@@ -1606,6 +1606,9 @@ static void vm_destroy_work_func(struct work_struct *w)
        /* xe_vm_close_and_put was not called? */
        xe_assert(xe, !vm->size);
 
+       if (xe_vm_in_preempt_fence_mode(vm))
+               flush_work(&vm->preempt.rebind_work);
+
        mutex_destroy(&vm->snap_mutex);
 
        if (!(vm->flags & XE_VM_FLAG_MIGRATION))
index e6a8b6d8eab707da539cbc209f205d0ef02bba67..3c3c497b6b91141bb2948b1a124b1a144f1a4fdf 100644 (file)
@@ -965,9 +965,7 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
                }
                break;
        case REPORT_TYPE_MOUSE:
-               workitem->reports_supported |= STD_MOUSE | HIDPP;
-               if (djrcv_dev->type == recvr_type_mouse_only)
-                       workitem->reports_supported |= MULTIMEDIA;
+               workitem->reports_supported |= STD_MOUSE | HIDPP | MULTIMEDIA;
                break;
        }
 }
index f9cceaeffd0814411d6024a3dd714444953a80db..da5ea5a23b087cde332ed28bf21a542c758e8919 100644 (file)
@@ -944,9 +944,11 @@ static void mcp2221_hid_unregister(void *ptr)
 /* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */
 static void mcp2221_remove(struct hid_device *hdev)
 {
+#if IS_REACHABLE(CONFIG_IIO)
        struct mcp2221 *mcp = hid_get_drvdata(hdev);
 
        cancel_delayed_work_sync(&mcp->init_work);
+#endif
 }
 
 #if IS_REACHABLE(CONFIG_IIO)
index ab5953fc24367afb075bd82756f57878e75d38c2..80e0f23c1c33ec698f107ee6f8ed942020142dbf 100644 (file)
@@ -481,10 +481,10 @@ static const struct joycon_ctlr_button_mapping n64con_button_mappings[] = {
        { BTN_TR,               JC_BTN_R,       },
        { BTN_TR2,              JC_BTN_LSTICK,  }, /* ZR */
        { BTN_START,            JC_BTN_PLUS,    },
-       { BTN_FORWARD,          JC_BTN_Y,       }, /* C UP */
-       { BTN_BACK,             JC_BTN_ZR,      }, /* C DOWN */
-       { BTN_LEFT,             JC_BTN_X,       }, /* C LEFT */
-       { BTN_RIGHT,            JC_BTN_MINUS,   }, /* C RIGHT */
+       { BTN_SELECT,           JC_BTN_Y,       }, /* C UP */
+       { BTN_X,                JC_BTN_ZR,      }, /* C DOWN */
+       { BTN_Y,                JC_BTN_X,       }, /* C LEFT */
+       { BTN_C,                JC_BTN_MINUS,   }, /* C RIGHT */
        { BTN_MODE,             JC_BTN_HOME,    },
        { BTN_Z,                JC_BTN_CAP,     },
        { /* sentinel */ },
index 2df1ab3c31cc54da812ee653face224f32e69fc2..d965382196c69e87cd79d1aad49deeab7da1bba5 100644 (file)
@@ -64,7 +64,6 @@
 /* flags */
 #define I2C_HID_STARTED                0
 #define I2C_HID_RESET_PENDING  1
-#define I2C_HID_READ_PENDING   2
 
 #define I2C_HID_PWR_ON         0x00
 #define I2C_HID_PWR_SLEEP      0x01
@@ -190,15 +189,10 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
                msgs[n].len = recv_len;
                msgs[n].buf = recv_buf;
                n++;
-
-               set_bit(I2C_HID_READ_PENDING, &ihid->flags);
        }
 
        ret = i2c_transfer(client->adapter, msgs, n);
 
-       if (recv_len)
-               clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
-
        if (ret != n)
                return ret < 0 ? ret : -EIO;
 
@@ -556,9 +550,6 @@ static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
 {
        struct i2c_hid *ihid = dev_id;
 
-       if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
-               return IRQ_HANDLED;
-
        i2c_hid_get_input(ihid);
 
        return IRQ_HANDLED;
@@ -735,12 +726,15 @@ static int i2c_hid_parse(struct hid_device *hid)
        mutex_lock(&ihid->reset_lock);
        do {
                ret = i2c_hid_start_hwreset(ihid);
-               if (ret)
+               if (ret == 0)
+                       ret = i2c_hid_finish_hwreset(ihid);
+               else
                        msleep(1000);
        } while (tries-- > 0 && ret);
+       mutex_unlock(&ihid->reset_lock);
 
        if (ret)
-               goto abort_reset;
+               return ret;
 
        use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
                                                                &rsize);
@@ -750,11 +744,8 @@ static int i2c_hid_parse(struct hid_device *hid)
                i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
        } else {
                rdesc = kzalloc(rsize, GFP_KERNEL);
-
-               if (!rdesc) {
-                       ret = -ENOMEM;
-                       goto abort_reset;
-               }
+               if (!rdesc)
+                       return -ENOMEM;
 
                i2c_hid_dbg(ihid, "asking HID report descriptor\n");
 
@@ -763,23 +754,10 @@ static int i2c_hid_parse(struct hid_device *hid)
                                            rdesc, rsize);
                if (ret) {
                        hid_err(hid, "reading report descriptor failed\n");
-                       goto abort_reset;
+                       goto out;
                }
        }
 
-       /*
-        * Windows directly reads the report-descriptor after sending reset
-        * and then waits for resets completion afterwards. Some touchpads
-        * actually wait for the report-descriptor to be read before signalling
-        * reset completion.
-        */
-       ret = i2c_hid_finish_hwreset(ihid);
-abort_reset:
-       clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
-       mutex_unlock(&ihid->reset_lock);
-       if (ret)
-               goto out;
-
        i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
 
        ret = hid_parse_report(hid, rdesc, rsize);
index a49c6affd7c4c48cdd09e3bdcca95139d0c066b8..dd5fc60874ba1d4f507e99fb5f28d87c16fdca9b 100644 (file)
@@ -948,6 +948,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
        if (!dev)
                return NULL;
 
+       dev->devc = &pdev->dev;
        ishtp_device_init(dev);
 
        init_waitqueue_head(&dev->wait_hw_ready);
@@ -983,7 +984,6 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
        }
 
        dev->ops = &ish_hw_ops;
-       dev->devc = &pdev->dev;
        dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);
        return dev;
 }
index ff5c486a1dbb1fa4a17d0d3f74885a7e3a0a69ec..db0d1ac82910e558b8df2e4e7f1c1f6535a06eaf 100644 (file)
@@ -2200,13 +2200,18 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
  * Returns negative errno, else the number of messages executed.
  *
  * Adapter lock must be held when calling this function. No debug logging
- * takes place. adap->algo->master_xfer existence isn't checked.
+ * takes place.
  */
 int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
        unsigned long orig_jiffies;
        int ret, try;
 
+       if (!adap->algo->master_xfer) {
+               dev_dbg(&adap->dev, "I2C level transfers not supported\n");
+               return -EOPNOTSUPP;
+       }
+
        if (WARN_ON(!msgs || num < 1))
                return -EINVAL;
 
@@ -2273,11 +2278,6 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
        int ret;
 
-       if (!adap->algo->master_xfer) {
-               dev_dbg(&adap->dev, "I2C level transfers not supported\n");
-               return -EOPNOTSUPP;
-       }
-
        /* REVISIT the fault reporting model here is weak:
         *
         *  - When we get an error after receiving N bytes from a slave,
index 61839be501c21a023790c15c40f55a48cd8d3da3..63c3566a533bd89429b0104a563f1acc72280ad7 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2014, Intel Corporation.
  */
 
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #define MXC4005_REG_ZOUT_UPPER         0x07
 #define MXC4005_REG_ZOUT_LOWER         0x08
 
+#define MXC4005_REG_INT_MASK0          0x0A
+
 #define MXC4005_REG_INT_MASK1          0x0B
 #define MXC4005_REG_INT_MASK1_BIT_DRDYE        0x01
 
+#define MXC4005_REG_INT_CLR0           0x00
+
 #define MXC4005_REG_INT_CLR1           0x01
 #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01
+#define MXC4005_REG_INT_CLR1_SW_RST    0x10
 
 #define MXC4005_REG_CONTROL            0x0D
 #define MXC4005_REG_CONTROL_MASK_FSR   GENMASK(6, 5)
@@ -39,6 +45,9 @@
 
 #define MXC4005_REG_DEVICE_ID          0x0E
 
+/* Datasheet does not specify a reset time, this is a conservative guess */
+#define MXC4005_RESET_TIME_US          2000
+
 enum mxc4005_axis {
        AXIS_X,
        AXIS_Y,
@@ -62,6 +71,8 @@ struct mxc4005_data {
                s64 timestamp __aligned(8);
        } scan;
        bool trigger_enabled;
+       unsigned int control;
+       unsigned int int_mask1;
 };
 
 /*
@@ -113,7 +124,9 @@ static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)
 static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
+       case MXC4005_REG_INT_CLR0:
        case MXC4005_REG_INT_CLR1:
+       case MXC4005_REG_INT_MASK0:
        case MXC4005_REG_INT_MASK1:
        case MXC4005_REG_CONTROL:
                return true;
@@ -330,23 +343,20 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
 {
        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
        struct mxc4005_data *data = iio_priv(indio_dev);
+       unsigned int val;
        int ret;
 
        mutex_lock(&data->mutex);
-       if (state) {
-               ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
-                                  MXC4005_REG_INT_MASK1_BIT_DRDYE);
-       } else {
-               ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
-                                  ~MXC4005_REG_INT_MASK1_BIT_DRDYE);
-       }
 
+       val = state ? MXC4005_REG_INT_MASK1_BIT_DRDYE : 0;
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, val);
        if (ret < 0) {
                mutex_unlock(&data->mutex);
                dev_err(data->dev, "failed to update reg_int_mask1");
                return ret;
        }
 
+       data->int_mask1 = val;
        data->trigger_enabled = state;
        mutex_unlock(&data->mutex);
 
@@ -382,6 +392,21 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
 
        dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
 
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
+                          MXC4005_REG_INT_CLR1_SW_RST);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "resetting chip\n");
+
+       fsleep(MXC4005_RESET_TIME_US);
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, 0);
+       if (ret < 0)
+               return dev_err_probe(data->dev, ret, "writing INT_MASK1\n");
+
        return 0;
 }
 
@@ -469,6 +494,58 @@ static int mxc4005_probe(struct i2c_client *client)
        return devm_iio_device_register(&client->dev, indio_dev);
 }
 
+static int mxc4005_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct mxc4005_data *data = iio_priv(indio_dev);
+       int ret;
+
+       /* Save control to restore it on resume */
+       ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
+       if (ret < 0)
+               dev_err(data->dev, "failed to read reg_control\n");
+
+       return ret;
+}
+
+static int mxc4005_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct mxc4005_data *data = iio_priv(indio_dev);
+       int ret;
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
+                          MXC4005_REG_INT_CLR1_SW_RST);
+       if (ret) {
+               dev_err(data->dev, "failed to reset chip: %d\n", ret);
+               return ret;
+       }
+
+       fsleep(MXC4005_RESET_TIME_US);
+
+       ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
+       if (ret) {
+               dev_err(data->dev, "failed to restore control register\n");
+               return ret;
+       }
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
+       if (ret) {
+               dev_err(data->dev, "failed to restore interrupt 0 mask\n");
+               return ret;
+       }
+
+       ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
+       if (ret) {
+               dev_err(data->dev, "failed to restore interrupt 1 mask\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
+
 static const struct acpi_device_id mxc4005_acpi_match[] = {
        {"MXC4005",     0},
        {"MXC6655",     0},
@@ -496,6 +573,7 @@ static struct i2c_driver mxc4005_driver = {
                .name = MXC4005_DRV_NAME,
                .acpi_match_table = mxc4005_acpi_match,
                .of_match_table = mxc4005_of_match,
+               .pm = pm_sleep_ptr(&mxc4005_pm_ops),
        },
        .probe          = mxc4005_probe,
        .id_table       = mxc4005_id,
index 01f55cc902faad356acb1e3f52ea80ea500a4bdb..060a21c70460d290811c28fc9325a6e42df9bb01 100644 (file)
@@ -1289,6 +1289,7 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
        struct device *dev = &st->adis.spi->dev;
        const struct adis16475_sync *sync;
        u32 sync_mode;
+       u16 val;
 
        /* default to internal clk */
        st->clk_freq = st->info->int_clk * 1000;
@@ -1350,8 +1351,9 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
         * I'm keeping this for simplicity and avoiding extra variables
         * in chip_info.
         */
+       val = ADIS16475_SYNC_MODE(sync->sync_mode);
        ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
-                                ADIS16475_SYNC_MODE_MASK, sync->sync_mode);
+                                ADIS16475_SYNC_MODE_MASK, val);
        if (ret)
                return ret;
 
index fe8734468ed352589a0d09ddc9c3a3509b3d3fad..62e9e93d915dc8662b672b4aecb44d3ebf3e8081 100644 (file)
@@ -1233,6 +1233,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
        .chip_id = bmp380_chip_ids,
        .num_chip_id = ARRAY_SIZE(bmp380_chip_ids),
        .regmap_config = &bmp380_regmap_config,
+       .spi_read_extra_byte = true,
        .start_up_time = 2000,
        .channels = bmp380_channels,
        .num_channels = 2,
index a444d4b2978b581ed8f4cd63b6821e23a45a0560..4e19ea0b4d398404340338db851b3033db8ab816 100644 (file)
@@ -96,15 +96,10 @@ static int bmp280_spi_probe(struct spi_device *spi)
 
        chip_info = spi_get_device_match_data(spi);
 
-       switch (chip_info->chip_id[0]) {
-       case BMP380_CHIP_ID:
-       case BMP390_CHIP_ID:
+       if (chip_info->spi_read_extra_byte)
                bmp_regmap_bus = &bmp380_regmap_bus;
-               break;
-       default:
+       else
                bmp_regmap_bus = &bmp280_regmap_bus;
-               break;
-       }
 
        regmap = devm_regmap_init(&spi->dev,
                                  bmp_regmap_bus,
@@ -127,7 +122,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
        { .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
        { .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
        { .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
-       { .compatible = "bosch,bme280", .data = &bmp280_chip_info },
+       { .compatible = "bosch,bme280", .data = &bme280_chip_info },
        { .compatible = "bosch,bmp380", .data = &bmp380_chip_info },
        { .compatible = "bosch,bmp580", .data = &bmp580_chip_info },
        { },
@@ -139,7 +134,7 @@ static const struct spi_device_id bmp280_spi_id[] = {
        { "bmp180", (kernel_ulong_t)&bmp180_chip_info },
        { "bmp181", (kernel_ulong_t)&bmp180_chip_info },
        { "bmp280", (kernel_ulong_t)&bmp280_chip_info },
-       { "bme280", (kernel_ulong_t)&bmp280_chip_info },
+       { "bme280", (kernel_ulong_t)&bme280_chip_info },
        { "bmp380", (kernel_ulong_t)&bmp380_chip_info },
        { "bmp580", (kernel_ulong_t)&bmp580_chip_info },
        { }
index 4012387d79565631e9c8fdd0152f859c80eac485..5812a344ed8e889c441e9b21fc623f98a2e23333 100644 (file)
@@ -423,6 +423,7 @@ struct bmp280_chip_info {
        int num_chip_id;
 
        const struct regmap_config *regmap_config;
+       bool spi_read_extra_byte;
 
        const struct iio_chan_spec *channels;
        int num_channels;
index f50848ed5575dbe143b159f5c16864fc0cc7b25c..6fadaddb2b908f0b0a2ed5cdd9c8382f08cacae8 100644 (file)
@@ -208,6 +208,7 @@ static const struct xpad_device {
        { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 },
        { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 },
        { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 },
+       { 0x0b05, 0x1a38, "ASUS ROG RAIKIRI", 0, XTYPE_XBOXONE },
        { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX },
        { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX },
        { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
@@ -487,6 +488,7 @@ static const struct usb_device_id xpad_table[] = {
        { USB_DEVICE(0x0738, 0x4540) },         /* Mad Catz Beat Pad */
        XPAD_XBOXONE_VENDOR(0x0738),            /* Mad Catz FightStick TE 2 */
        XPAD_XBOX360_VENDOR(0x07ff),            /* Mad Catz Gamepad */
+       XPAD_XBOXONE_VENDOR(0x0b05),            /* ASUS controllers */
        XPAD_XBOX360_VENDOR(0x0c12),            /* Zeroplus X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f Xbox 360 controllers */
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f Xbox One controllers */
index cda0c3ff5a288df0840011442442e0995330287a..2fbbaeb76d708284e1512ed89fc5a7806c177f1f 100644 (file)
@@ -132,7 +132,13 @@ static void __exit amimouse_remove(struct platform_device *pdev)
        input_unregister_device(dev);
 }
 
-static struct platform_driver amimouse_driver = {
+/*
+ * amimouse_remove() lives in .exit.text. For drivers registered via
+ * module_platform_driver_probe() this is ok because they cannot get unbound at
+ * runtime. So mark the driver struct with __refdata to prevent modpost
+ * triggering a section mismatch warning.
+ */
+static struct platform_driver amimouse_driver __refdata = {
        .remove_new = __exit_p(amimouse_remove),
        .driver   = {
                .name   = "amiga-mouse",
index 2a537cbfcb077246c0aee43a5b9f1885a3e0b5f2..5f7d3db3afd8248e43e6fc86b677fb0fdc587a84 100644 (file)
@@ -4567,13 +4567,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
                irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i));
        }
 
-       if (err) {
-               if (i > 0)
-                       its_vpe_irq_domain_free(domain, virq, i);
-
-               its_lpi_free(bitmap, base, nr_ids);
-               its_free_prop_table(vprop_page);
-       }
+       if (err)
+               its_vpe_irq_domain_free(domain, virq, i);
 
        return err;
 }
index 01d2743444ec6cc7eec0945b69ba1c63195f09b1..3a989efae1420a0f2e5b965b55555fe8a85a4037 100644 (file)
@@ -137,7 +137,7 @@ void murmurhash3_128(const void *key, const int len, const u32 seed, void *out)
                        break;
                default:
                        break;
-               };
+               }
        }
        /* finalization */
 
index 56aa2a8b9d7153ac0792bbdc626ab5250cf074c7..7d0746b37c8ec791f111d6e589476eb2b500e9d4 100644 (file)
@@ -765,7 +765,7 @@ static struct table_device *open_table_device(struct mapped_device *md,
        return td;
 
 out_blkdev_put:
-       fput(bdev_file);
+       __fput_sync(bdev_file);
 out_free_td:
        kfree(td);
        return ERR_PTR(r);
@@ -778,7 +778,13 @@ static void close_table_device(struct table_device *td, struct mapped_device *md
 {
        if (md->disk->slave_dir)
                bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
-       fput(td->dm_dev.bdev_file);
+
+       /* Leverage async fput() if DMF_DEFERRED_REMOVE set */
+       if (unlikely(test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
+               fput(td->dm_dev.bdev_file);
+       else
+               __fput_sync(td->dm_dev.bdev_file);
+
        put_dax(td->dm_dev.dax_dev);
        list_del(&td->list);
        kfree(td);
index 572333ead5fb8b002b87957dfe1dc9ea26330efb..4bd4f32bcdabb8f98d2b764f04bb2ac9f8270d83 100644 (file)
@@ -758,15 +758,6 @@ static int at24_probe(struct i2c_client *client)
        }
        pm_runtime_enable(dev);
 
-       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
-       if (IS_ERR(at24->nvmem)) {
-               pm_runtime_disable(dev);
-               if (!pm_runtime_status_suspended(dev))
-                       regulator_disable(at24->vcc_reg);
-               return dev_err_probe(dev, PTR_ERR(at24->nvmem),
-                                    "failed to register nvmem\n");
-       }
-
        /*
         * Perform a one-byte test read to verify that the chip is functional,
         * unless powering on the device is to be avoided during probe (i.e.
@@ -782,6 +773,15 @@ static int at24_probe(struct i2c_client *client)
                }
        }
 
+       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
+       if (IS_ERR(at24->nvmem)) {
+               pm_runtime_disable(dev);
+               if (!pm_runtime_status_suspended(dev))
+                       regulator_disable(at24->vcc_reg);
+               return dev_err_probe(dev, PTR_ERR(at24->nvmem),
+                                    "failed to register nvmem\n");
+       }
+
        /* If this a SPD EEPROM, probe for DDR3 thermal sensor */
        if (cdata == &at24_data_spd)
                at24_probe_temp_sensor(client);
index aac36750d2c54a658debcca55063d2e2a02bf1ce..c3a6657dcd4a291a09d2f5abf1b0f1d740c10703 100644 (file)
 #define MEI_DEV_ID_ARL_S      0x7F68  /* Arrow Lake Point S */
 #define MEI_DEV_ID_ARL_H      0x7770  /* Arrow Lake Point H */
 
+#define MEI_DEV_ID_LNL_M      0xA870  /* Lunar Lake Point M */
+
 /*
  * MEI HW Section
  */
index c39718042e2e0c9b76da57cfde39f0a0b8801b09..7f59dd38c32f52dccf632fb4bb06066972d26862 100644 (file)
@@ -122,6 +122,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_H, MEI_ME_PCH15_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)},
+
        /* required last entry */
        {0, }
 };
index b1e4c23b31a32957c616f0edcdf74dc086c44a89..49abc95677cdac6a74d673cbf5444ccc82deee74 100644 (file)
@@ -236,8 +236,11 @@ static int mei_pxp_component_match(struct device *dev, int subcomponent,
 
        pdev = to_pci_dev(dev);
 
-       if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) ||
-           pdev->vendor != PCI_VENDOR_ID_INTEL)
+       if (pdev->vendor != PCI_VENDOR_ID_INTEL)
+               return 0;
+
+       if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) &&
+           pdev->class != (PCI_CLASS_DISPLAY_OTHER << 8))
                return 0;
 
        if (subcomponent != I915_COMPONENT_PXP)
index 9ad20e82785bcd6ade57d493e31152ecff334178..b21598a18f6da81568dedb0817bf74da55f81a15 100644 (file)
@@ -44,8 +44,6 @@ static struct pci_driver pvpanic_pci_driver = {
        .name =         "pvpanic-pci",
        .id_table =     pvpanic_pci_id_tbl,
        .probe =        pvpanic_pci_probe,
-       .driver = {
-               .dev_groups = pvpanic_dev_groups,
-       },
+       .dev_groups =   pvpanic_dev_groups,
 };
 module_pci_driver(pvpanic_pci_driver);
index b88d6dec209f5722df79c3d269070939aa2d72da..9a5f75163acaeef8226ee122dde79c60fd9b7d8c 100644 (file)
@@ -300,6 +300,7 @@ static void moxart_transfer_pio(struct moxart_host *host)
        remain = sgm->length;
        if (remain > host->data_len)
                remain = host->data_len;
+       sgm->consumed = 0;
 
        if (data->flags & MMC_DATA_WRITE) {
                while (remain > 0) {
index 668e0aceeebac9caecb84af355eb08d51c71de0b..e113b99a3eab592dfdd24bbd6c371c2756c2b6c9 100644 (file)
@@ -2694,6 +2694,11 @@ static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev)
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->runtime_suspended = true;
+       spin_unlock_irqrestore(&host->lock, flags);
 
        /* Drop the performance vote */
        dev_pm_opp_set_rate(dev, 0);
@@ -2708,6 +2713,7 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+       unsigned long flags;
        int ret;
 
        ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),
@@ -2726,7 +2732,15 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
 
        dev_pm_opp_set_rate(dev, msm_host->clk_rate);
 
-       return sdhci_msm_ice_resume(msm_host);
+       ret = sdhci_msm_ice_resume(msm_host);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->runtime_suspended = false;
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       return ret;
 }
 
 static const struct dev_pm_ops sdhci_msm_pm_ops = {
index 1d8f5a76096aeb3c836722b3f97226d7dd2c5201..f2e4a93ed1d61a22d4601fefe2a120caf2b19333 100644 (file)
@@ -626,6 +626,7 @@ static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
 
        /* perform tuning */
        sdhci_start_tuning(host);
+       host->tuning_loop_count = 128;
        host->tuning_err = __sdhci_execute_tuning(host, opcode);
        if (host->tuning_err) {
                /* disable auto-tuning upon tuning error */
index 5887feb347a4e42aa1dcc779bc7f5b252402b16e..0de87bc63840546d8a11dfe959874a5af7835ac6 100644 (file)
@@ -900,7 +900,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd,
        config.name = compatible;
        config.id = NVMEM_DEVID_AUTO;
        config.owner = THIS_MODULE;
-       config.add_legacy_fixed_of_cells = true;
+       config.add_legacy_fixed_of_cells = !mtd_type_is_nand(mtd);
        config.type = NVMEM_TYPE_OTP;
        config.root_only = true;
        config.ignore_wp = true;
index a8d12c71f987be95817a69b4ee92c229ec8bf814..1b2ec0fec60c7a19e76f67dc5db47e98f4ad8a28 100644 (file)
@@ -857,7 +857,7 @@ static inline void brcmnand_read_data_bus(struct brcmnand_controller *ctrl,
        struct brcmnand_soc *soc = ctrl->soc;
        int i;
 
-       if (soc->read_data_bus) {
+       if (soc && soc->read_data_bus) {
                soc->read_data_bus(soc, flash_cache, buffer, fc_words);
        } else {
                for (i = 0; i < fc_words; i++)
index 5243fab9face0034ecf54838345624b816f91906..8db7fc424571116abb467def163d2f1725c49b9f 100644 (file)
@@ -53,7 +53,7 @@ static unsigned long doc_locations[] __initdata = {
        0xe8000, 0xea000, 0xec000, 0xee000,
 #endif
 #endif
-       0xffffffff };
+};
 
 static struct mtd_info *doclist = NULL;
 
@@ -1554,7 +1554,7 @@ static int __init init_nanddoc(void)
                if (ret < 0)
                        return ret;
        } else {
-               for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
+               for (i = 0; i < ARRAY_SIZE(doc_locations); i++) {
                        doc_probe(doc_locations[i]);
                }
        }
index b079605c84d38204971834ea2c26d2858165b506..b8cff9240b286c7ac789bf4216611b54bee05dd3 100644 (file)
@@ -2815,7 +2815,7 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
                              host->cfg0_raw & ~(7 << CW_PER_PAGE));
                nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw);
                instrs = 3;
-       } else {
+       } else if (q_op.cmd_reg != OP_RESET_DEVICE) {
                return 0;
        }
 
@@ -2830,9 +2830,8 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
        nandc_set_reg(chip, NAND_EXEC_CMD, 1);
 
        write_reg_dma(nandc, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
-       (q_op.cmd_reg == OP_BLOCK_ERASE) ? write_reg_dma(nandc, NAND_DEV0_CFG0,
-       2, NAND_BAM_NEXT_SGL) : read_reg_dma(nandc,
-       NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
+       if (q_op.cmd_reg == OP_BLOCK_ERASE)
+               write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
 
        write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
        read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
index c95787cb908673c6ab1b236e9c447952e5e8e452..14daf432f30b5c9f01502d4d2b44909930c8e75a 100644 (file)
@@ -566,13 +566,61 @@ static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)
                phy_interface_set_rgmii(supported);
 }
 
-static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
-                                      struct phylink_config *config)
+static void
+mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,
+                                    struct phylink_config *config)
 {
        unsigned long *supported = config->supported_interfaces;
+       int err;
+       u16 reg;
 
-       /* Translate the default cmode */
-       mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
+       err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
+       if (err) {
+               dev_err(chip->dev, "p%d: failed to read port status\n", port);
+               return;
+       }
+
+       switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY:
+               __set_bit(PHY_INTERFACE_MODE_REVMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_HALF:
+       case MV88E6250_PORT_STS_PORTMODE_MII_FULL:
+               __set_bit(PHY_INTERFACE_MODE_MII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY:
+               __set_bit(PHY_INTERFACE_MODE_REVRMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL:
+       case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL:
+               __set_bit(PHY_INTERFACE_MODE_RMII, supported);
+               break;
+
+       case MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII:
+               __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
+               break;
+
+       default:
+               dev_err(chip->dev,
+                       "p%d: invalid port mode in status register: %04x\n",
+                       port, reg);
+       }
+}
+
+static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+                                      struct phylink_config *config)
+{
+       if (!mv88e6xxx_phy_is_internal(chip, port))
+               mv88e6250_setup_supported_interfaces(chip, port, config);
 
        config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
 }
@@ -5657,7 +5705,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
                .family = MV88E6XXX_FAMILY_6341,
                .name = "Marvell 88E6141",
-               .num_databases = 4096,
+               .num_databases = 256,
                .num_macs = 2048,
                .num_ports = 6,
                .num_internal_phys = 5,
@@ -6116,7 +6164,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
                .family = MV88E6XXX_FAMILY_6341,
                .name = "Marvell 88E6341",
-               .num_databases = 4096,
+               .num_databases = 256,
                .num_macs = 2048,
                .num_internal_phys = 5,
                .num_ports = 6,
index 86deeb347cbc1d82526f362f719c57ac17039bf0..ddadeb9bfdaeed6978d85d55ccd2e52710971529 100644 (file)
 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF       0x0900
 #define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL                0x0a00
 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL       0x0b00
-#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF                0x0c00
-#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF       0x0d00
-#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL                0x0e00
-#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL       0x0f00
+/* - Modes with PHY suffix use output instead of input clock
+ * - Modes without RMII or RGMII use MII
+ * - Modes without speed do not have a fixed speed specified in the manual
+ *   ("DC to x MHz" - variable clock support?)
+ */
+#define MV88E6250_PORT_STS_PORTMODE_MII_DISABLED               0x0000
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII              0x0100
+#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY 0x0200
+#define MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY      0x0400
+#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL     0x0600
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL       0x0700
+#define MV88E6250_PORT_STS_PORTMODE_MII_HALF                   0x0800
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY   0x0900
+#define MV88E6250_PORT_STS_PORTMODE_MII_FULL                   0x0a00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY   0x0b00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY            0x0c00
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY           0x0d00
+#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY            0x0e00
+#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY           0x0f00
 #define MV88E6XXX_PORT_STS_LINK                        0x0800
 #define MV88E6XXX_PORT_STS_DUPLEX              0x0400
 #define MV88E6XXX_PORT_STS_SPEED_MASK          0x0300
index 72ea97c5d5d424482fe6812cef1a013158319a70..82768b0e90262b80b949b959b40151a0ddd0b6a9 100644 (file)
@@ -436,10 +436,8 @@ static void umac_init(struct bcmasp_intf *intf)
        umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ);
 }
 
-static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+static int bcmasp_tx_reclaim(struct bcmasp_intf *intf)
 {
-       struct bcmasp_intf *intf =
-               container_of(napi, struct bcmasp_intf, tx_napi);
        struct bcmasp_intf_stats64 *stats = &intf->stats64;
        struct device *kdev = &intf->parent->pdev->dev;
        unsigned long read, released = 0;
@@ -482,10 +480,16 @@ static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
                                                        DESC_RING_COUNT);
        }
 
-       /* Ensure all descriptors have been written to DRAM for the hardware
-        * to see updated contents.
-        */
-       wmb();
+       return released;
+}
+
+static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+{
+       struct bcmasp_intf *intf =
+               container_of(napi, struct bcmasp_intf, tx_napi);
+       int released = 0;
+
+       released = bcmasp_tx_reclaim(intf);
 
        napi_complete(&intf->tx_napi);
 
@@ -797,6 +801,7 @@ static void bcmasp_init_tx(struct bcmasp_intf *intf)
        intf->tx_spb_dma_read = intf->tx_spb_dma_addr;
        intf->tx_spb_index = 0;
        intf->tx_spb_clean_index = 0;
+       memset(intf->tx_cbs, 0, sizeof(struct bcmasp_tx_cb) * DESC_RING_COUNT);
 
        /* Make sure channels are disabled */
        tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE);
@@ -885,6 +890,8 @@ static void bcmasp_netif_deinit(struct net_device *dev)
        } while (timeout-- > 0);
        tx_spb_dma_wl(intf, 0x0, TX_SPB_DMA_FIFO_CTRL);
 
+       bcmasp_tx_reclaim(intf);
+
        umac_enable_set(intf, UMC_CMD_TX_EN, 0);
 
        phy_stop(dev->phydev);
index 3e4fb3c3e8342ad3dbf7aa32df03fc4ce57e3cad..1be6d14030bcffc0fd149b6be0af819964284a4e 100644 (file)
@@ -2009,12 +2009,14 @@ static int b44_set_pauseparam(struct net_device *dev,
                bp->flags |= B44_FLAG_TX_PAUSE;
        else
                bp->flags &= ~B44_FLAG_TX_PAUSE;
-       if (bp->flags & B44_FLAG_PAUSE_AUTO) {
-               b44_halt(bp);
-               b44_init_rings(bp);
-               b44_init_hw(bp, B44_FULL_RESET);
-       } else {
-               __b44_set_flow_ctrl(bp, bp->flags);
+       if (netif_running(dev)) {
+               if (bp->flags & B44_FLAG_PAUSE_AUTO) {
+                       b44_halt(bp);
+                       b44_init_rings(bp);
+                       b44_init_hw(bp, B44_FULL_RESET);
+               } else {
+                       __b44_set_flow_ctrl(bp, bp->flags);
+               }
        }
        spin_unlock_irq(&bp->lock);
 
index 57e61f9631678edf31a2ff237fe0301254a396e5..2c2ee79c4d77957761d8f3d9ca85bcecedd5fd0f 100644 (file)
@@ -1778,7 +1778,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping);
                if (!skb) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        } else {
@@ -1788,7 +1788,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
                if (!new_data) {
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
 
@@ -1804,7 +1804,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                if (!skb) {
                        skb_free_frag(data);
                        bnxt_abort_tpa(cpr, idx, agg_bufs);
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
                skb_reserve(skb, bp->rx_offset);
@@ -1815,7 +1815,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, idx, agg_bufs, true);
                if (!skb) {
                        /* Page reuse already handled by bnxt_rx_pages(). */
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
+                       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
                        return NULL;
                }
        }
@@ -2094,11 +2094,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp,
                                                             cp_cons, agg_bufs,
                                                             false);
-                       if (!frag_len) {
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
-                       }
+                       if (!frag_len)
+                               goto oom_next_rx;
                }
                xdp_active = true;
        }
@@ -2121,9 +2118,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                                else
                                        bnxt_xdp_buff_frags_free(rxr, &xdp);
                        }
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
-                       rc = -ENOMEM;
-                       goto next_rx;
+                       goto oom_next_rx;
                }
        } else {
                u32 payload;
@@ -2134,29 +2129,21 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                        payload = 0;
                skb = bp->rx_skb_func(bp, rxr, cons, data, data_ptr, dma_addr,
                                      payload | len);
-               if (!skb) {
-                       cpr->sw_stats.rx.rx_oom_discards += 1;
-                       rc = -ENOMEM;
-                       goto next_rx;
-               }
+               if (!skb)
+                       goto oom_next_rx;
        }
 
        if (agg_bufs) {
                if (!xdp_active) {
                        skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, cp_cons, agg_bufs, false);
-                       if (!skb) {
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
-                       }
+                       if (!skb)
+                               goto oom_next_rx;
                } else {
                        skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1);
                        if (!skb) {
                                /* we should be able to free the old skb here */
                                bnxt_xdp_buff_frags_free(rxr, &xdp);
-                               cpr->sw_stats.rx.rx_oom_discards += 1;
-                               rc = -ENOMEM;
-                               goto next_rx;
+                               goto oom_next_rx;
                        }
                }
        }
@@ -2234,6 +2221,11 @@ next_rx_no_prod_no_len:
        *raw_cons = tmp_raw_cons;
 
        return rc;
+
+oom_next_rx:
+       cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+       rc = -ENOMEM;
+       goto next_rx;
 }
 
 /* In netpoll mode, if we are using a combined completion ring, we need to
@@ -2280,7 +2272,7 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
        }
        rc = bnxt_rx_pkt(bp, cpr, raw_cons, event);
        if (rc && rc != -EBUSY)
-               cpr->sw_stats.rx.rx_netpoll_discards += 1;
+               cpr->bnapi->cp_ring.sw_stats.rx.rx_netpoll_discards += 1;
        return rc;
 }
 
@@ -9089,7 +9081,7 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
                                             BNXT_FW_HEALTH_WIN_BASE +
                                             BNXT_GRC_REG_CHIP_NUM);
                }
-               if (!BNXT_CHIP_P5(bp))
+               if (!BNXT_CHIP_P5_PLUS(bp))
                        return;
 
                status_loc = BNXT_GRC_REG_STATUS_P5 |
@@ -13037,6 +13029,16 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
        bnxt_rtnl_unlock_sp(bp);
 }
 
+static void bnxt_fw_fatal_close(struct bnxt *bp)
+{
+       bnxt_tx_disable(bp);
+       bnxt_disable_napi(bp);
+       bnxt_disable_int_sync(bp);
+       bnxt_free_irq(bp);
+       bnxt_clear_int_mode(bp);
+       pci_disable_device(bp->pdev);
+}
+
 static void bnxt_fw_reset_close(struct bnxt *bp)
 {
        bnxt_ulp_stop(bp);
@@ -13050,12 +13052,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
                pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, &val);
                if (val == 0xffff)
                        bp->fw_reset_min_dsecs = 0;
-               bnxt_tx_disable(bp);
-               bnxt_disable_napi(bp);
-               bnxt_disable_int_sync(bp);
-               bnxt_free_irq(bp);
-               bnxt_clear_int_mode(bp);
-               pci_disable_device(bp->pdev);
+               bnxt_fw_fatal_close(bp);
        }
        __bnxt_close_nic(bp, true, false);
        bnxt_vf_reps_free(bp);
@@ -15373,6 +15370,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct bnxt *bp = netdev_priv(netdev);
+       bool abort = false;
 
        netdev_info(netdev, "PCI I/O error detected\n");
 
@@ -15381,16 +15379,27 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
 
        bnxt_ulp_stop(bp);
 
-       if (state == pci_channel_io_perm_failure) {
+       if (test_and_set_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+               netdev_err(bp->dev, "Firmware reset already in progress\n");
+               abort = true;
+       }
+
+       if (abort || state == pci_channel_io_perm_failure) {
                rtnl_unlock();
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
-       if (state == pci_channel_io_frozen)
+       /* Link is not reliable anymore if state is pci_channel_io_frozen
+        * so we disable bus master to prevent any potential bad DMAs before
+        * freeing kernel memory.
+        */
+       if (state == pci_channel_io_frozen) {
                set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
+               bnxt_fw_fatal_close(bp);
+       }
 
        if (netif_running(netdev))
-               bnxt_close(netdev);
+               __bnxt_close_nic(bp, true, true);
 
        if (pci_is_enabled(pdev))
                pci_disable_device(pdev);
@@ -15474,6 +15483,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
        }
 
 reset_exit:
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
        bnxt_clear_reservations(bp, true);
        rtnl_unlock();
 
index b1f84b37032a7833d7e4f3d045e8755ace6f79d3..c7e7dac057a336d086bdf9569286fadec7e1d3be 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET (Gigabit Ethernet) controller driver
  *
- * Copyright (c) 2014-2020 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #define pr_fmt(fmt)                            "bcmgenet: " fmt
@@ -2467,14 +2467,18 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
 {
        u32 reg;
 
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-       if (reg & CMD_SW_RESET)
+       if (reg & CMD_SW_RESET) {
+               spin_unlock_bh(&priv->reg_lock);
                return;
+       }
        if (enable)
                reg |= mask;
        else
                reg &= ~mask;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 
        /* UniMAC stops on a packet boundary, wait for a full-size packet
         * to be processed
@@ -2490,8 +2494,10 @@ static void reset_umac(struct bcmgenet_priv *priv)
        udelay(10);
 
        /* issue soft reset and disable MAC while updating its registers */
+       spin_lock_bh(&priv->reg_lock);
        bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
        udelay(2);
+       spin_unlock_bh(&priv->reg_lock);
 }
 
 static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
@@ -3334,7 +3340,9 @@ static void bcmgenet_netif_start(struct net_device *dev)
        struct bcmgenet_priv *priv = netdev_priv(dev);
 
        /* Start the network engine */
+       netif_addr_lock_bh(dev);
        bcmgenet_set_rx_mode(dev);
+       netif_addr_unlock_bh(dev);
        bcmgenet_enable_rx_napi(priv);
 
        umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
@@ -3595,16 +3603,19 @@ static void bcmgenet_set_rx_mode(struct net_device *dev)
         * 3. The number of filters needed exceeds the number filters
         *    supported by the hardware.
        */
+       spin_lock(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
            (nfilter > MAX_MDF_FILTER)) {
                reg |= CMD_PROMISC;
                bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+               spin_unlock(&priv->reg_lock);
                bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL);
                return;
        } else {
                reg &= ~CMD_PROMISC;
                bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+               spin_unlock(&priv->reg_lock);
        }
 
        /* update MDF filter */
@@ -4003,6 +4014,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
                goto err;
        }
 
+       spin_lock_init(&priv->reg_lock);
        spin_lock_init(&priv->lock);
 
        /* Set default pause parameters */
index 7523b60b3c1c016de74fd74b7d1e286596aac1ae..43b923c48b14f40e0cf9cdd6b6f3ac16c301ef97 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2014-2020 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #ifndef __BCMGENET_H__
@@ -573,6 +573,8 @@ struct bcmgenet_rxnfc_rule {
 /* device context */
 struct bcmgenet_priv {
        void __iomem *base;
+       /* reg_lock: lock to serialize access to shared registers */
+       spinlock_t reg_lock;
        enum bcmgenet_version version;
        struct net_device *dev;
 
index 7a41cad5788f4edd6691552901f4b2eb8fdebc36..1248792d7fd4d2f98847889c499277a92229d785 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
  *
- * Copyright (c) 2014-2020 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #define pr_fmt(fmt)                            "bcmgenet_wol: " fmt
@@ -151,6 +151,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        }
 
        /* Can't suspend with WoL if MAC is still in reset */
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        if (reg & CMD_SW_RESET)
                reg &= ~CMD_SW_RESET;
@@ -158,6 +159,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        /* disable RX */
        reg &= ~CMD_RX_EN;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
        mdelay(10);
 
        if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
@@ -203,6 +205,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        }
 
        /* Enable CRC forward */
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        priv->crc_fwd_en = 1;
        reg |= CMD_CRC_FWD;
@@ -210,6 +213,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
        /* Receiver must be enabled for WOL MP detection */
        reg |= CMD_RX_EN;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 
        reg = UMAC_IRQ_MPD_R;
        if (hfb_enable)
@@ -256,7 +260,9 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
        }
 
        /* Disable CRC Forward */
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        reg &= ~CMD_CRC_FWD;
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 }
index 9ada89355747554dc458c311f96333866cf7bc66..c4a3698cef66f61d775c783b334a035589d55bdd 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Broadcom GENET MDIO routines
  *
- * Copyright (c) 2014-2017 Broadcom
+ * Copyright (c) 2014-2024 Broadcom
  */
 
 #include <linux/acpi.h>
@@ -76,6 +76,7 @@ static void bcmgenet_mac_config(struct net_device *dev)
        reg |= RGMII_LINK;
        bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
 
+       spin_lock_bh(&priv->reg_lock);
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
                       CMD_HD_EN |
@@ -88,6 +89,7 @@ static void bcmgenet_mac_config(struct net_device *dev)
                reg |= CMD_TX_EN | CMD_RX_EN;
        }
        bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+       spin_unlock_bh(&priv->reg_lock);
 
        active = phy_init_eee(phydev, 0) >= 0;
        bcmgenet_eee_enable_set(dev,
@@ -275,6 +277,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
         * block for the interface to work, unconditionally clear the
         * Out-of-band disable since we do not need it.
         */
+       mutex_lock(&phydev->lock);
        reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
        reg &= ~OOB_DISABLE;
        if (priv->ext_phy) {
@@ -286,6 +289,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
                        reg |= RGMII_MODE_EN;
        }
        bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
+       mutex_unlock(&phydev->lock);
 
        if (init)
                dev_info(kdev, "configuring instance for %s\n", phy_name);
index 7246e13dd559fc37170c791644cf5a8fd8d04fcf..97291bfbeea589e8ca8ab637db8bcff7e573322f 100644 (file)
@@ -312,7 +312,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
        void *kern_buf;
 
        /* Copy the user space buf */
-       kern_buf = memdup_user(buf, nbytes);
+       kern_buf = memdup_user_nul(buf, nbytes);
        if (IS_ERR(kern_buf))
                return PTR_ERR(kern_buf);
 
@@ -372,7 +372,7 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
        void *kern_buf;
 
        /* Copy the user space buf */
-       kern_buf = memdup_user(buf, nbytes);
+       kern_buf = memdup_user_nul(buf, nbytes);
        if (IS_ERR(kern_buf))
                return PTR_ERR(kern_buf);
 
index 49d5808b7d11d281796debc6be5f9b3a9b1f60e3..de52bcb884c417098ff5aff6aea77753d055c671 100644 (file)
@@ -2670,12 +2670,12 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev)
        lb->loopback = 1;
 
        q = &adap->sge.ethtxq[pi->first_qset];
-       __netif_tx_lock(q->txq, smp_processor_id());
+       __netif_tx_lock_bh(q->txq);
 
        reclaim_completed_tx(adap, &q->q, -1, true);
        credits = txq_avail(&q->q) - ndesc;
        if (unlikely(credits < 0)) {
-               __netif_tx_unlock(q->txq);
+               __netif_tx_unlock_bh(q->txq);
                return -ENOMEM;
        }
 
@@ -2710,7 +2710,7 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev)
        init_completion(&lb->completion);
        txq_advance(&q->q, ndesc);
        cxgb4_ring_tx_db(adap, &q->q, ndesc);
-       __netif_tx_unlock(q->txq);
+       __netif_tx_unlock_bh(q->txq);
 
        /* wait for the pkt to return */
        ret = wait_for_completion_timeout(&lb->completion, 10 * HZ);
index 93544f1cc2a51be0c84c33391211bf47d2675edb..f7ae0e0aa4a4f52d7ff720c11fb906cac00f7c5a 100644 (file)
@@ -157,7 +157,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                 * the lower time out
                 */
                for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-                       usleep_range(50, 60);
+                       udelay(50);
                        mdic = er32(MDIC);
                        if (mdic & E1000_MDIC_READY)
                                break;
@@ -181,7 +181,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                 * reading duplicate data in the next MDIC transaction.
                 */
                if (hw->mac.type == e1000_pch2lan)
-                       usleep_range(100, 150);
+                       udelay(100);
 
                if (success) {
                        *data = (u16)mdic;
@@ -237,7 +237,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                 * the lower time out
                 */
                for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-                       usleep_range(50, 60);
+                       udelay(50);
                        mdic = er32(MDIC);
                        if (mdic & E1000_MDIC_READY)
                                break;
@@ -261,7 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                 * reading duplicate data in the next MDIC transaction.
                 */
                if (hw->mac.type == e1000_pch2lan)
-                       usleep_range(100, 150);
+                       udelay(100);
 
                if (success)
                        return 0;
index 48b9ddb2b1b38b385527f137124ce86a36ac036d..ffb9f9f15c5232e2aeb4a45c1209b6a0763062d7 100644 (file)
@@ -16107,8 +16107,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK,
                        rd32(&pf->hw, I40E_PRTGL_SAH));
        if (val < MAX_FRAME_SIZE_DEFAULT)
-               dev_warn(&pdev->dev, "MFS for port %x has been set below the default: %x\n",
-                        pf->hw.port, val);
+               dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n",
+                        pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT);
 
        /* Add a filter to drop all Flow control frames from any VSI from being
         * transmitted. By doing so we stop a malicious VF from sending out
@@ -16650,7 +16650,7 @@ static int __init i40e_init_module(void)
         * since we need to be able to guarantee forward progress even under
         * memory pressure.
         */
-       i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name);
+       i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name);
        if (!i40e_wq) {
                pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
                return -ENOMEM;
index ef2440f3abf8b6aed9f47e5948f67a5dec52b51e..166832a4213a289f17198d748f4abea1d5e4efc4 100644 (file)
@@ -3502,6 +3502,34 @@ static void iavf_del_all_cloud_filters(struct iavf_adapter *adapter)
        spin_unlock_bh(&adapter->cloud_filter_list_lock);
 }
 
+/**
+ * iavf_is_tc_config_same - Compare the mqprio TC config with the
+ * TC config already configured on this adapter.
+ * @adapter: board private structure
+ * @mqprio_qopt: TC config received from kernel.
+ *
+ * This function compares the TC config received from the kernel
+ * with the config already configured on the adapter.
+ *
+ * Return: True if configuration is same, false otherwise.
+ **/
+static bool iavf_is_tc_config_same(struct iavf_adapter *adapter,
+                                  struct tc_mqprio_qopt *mqprio_qopt)
+{
+       struct virtchnl_channel_info *ch = &adapter->ch_config.ch_info[0];
+       int i;
+
+       if (adapter->num_tc != mqprio_qopt->num_tc)
+               return false;
+
+       for (i = 0; i < adapter->num_tc; i++) {
+               if (ch[i].count != mqprio_qopt->count[i] ||
+                   ch[i].offset != mqprio_qopt->offset[i])
+                       return false;
+       }
+       return true;
+}
+
 /**
  * __iavf_setup_tc - configure multiple traffic classes
  * @netdev: network interface device structure
@@ -3559,7 +3587,7 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data)
                if (ret)
                        return ret;
                /* Return if same TC config is requested */
-               if (adapter->num_tc == num_tc)
+               if (iavf_is_tc_config_same(adapter, &mqprio_qopt->qopt))
                        return 0;
                adapter->num_tc = num_tc;
 
index d252d98218d084e9782d899d4f854c0bf7101622..9fc0fd95a13d8f2c40475a94f38d3a2c088ab6f4 100644 (file)
@@ -171,7 +171,7 @@ ice_debugfs_module_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 8)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
@@ -257,7 +257,7 @@ ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 4)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
@@ -332,7 +332,7 @@ ice_debugfs_enable_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 2)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
@@ -428,7 +428,7 @@ ice_debugfs_log_size_write(struct file *filp, const char __user *buf,
        if (*ppos != 0 || count > 5)
                return -EINVAL;
 
-       cmd_buf = memdup_user(buf, count);
+       cmd_buf = memdup_user_nul(buf, count);
        if (IS_ERR(cmd_buf))
                return PTR_ERR(cmd_buf);
 
index 21d26e19338a69acb265a279bfc633bbfea0cad2..d10a4be965b591027c357be2c5ede2ab3269a7da 100644 (file)
@@ -856,6 +856,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                return 0;
        }
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_lock(&vf->cfg_lock);
+       else
+               lockdep_assert_held(&vf->cfg_lock);
+
        lag = pf->lag;
        mutex_lock(&pf->lag_mutex);
        if (lag && lag->bonded && lag->primary) {
@@ -867,11 +872,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
                        act_prt = ICE_LAG_INVALID_PORT;
        }
 
-       if (flags & ICE_VF_RESET_LOCK)
-               mutex_lock(&vf->cfg_lock);
-       else
-               lockdep_assert_held(&vf->cfg_lock);
-
        if (ice_is_vf_disabled(vf)) {
                vsi = ice_get_vf_vsi(vf);
                if (!vsi) {
@@ -956,14 +956,14 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
        ice_mbx_clear_malvf(&vf->mbx_info);
 
 out_unlock:
-       if (flags & ICE_VF_RESET_LOCK)
-               mutex_unlock(&vf->cfg_lock);
-
        if (lag && lag->bonded && lag->primary &&
            act_prt != ICE_LAG_INVALID_PORT)
                ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
        mutex_unlock(&pf->lag_mutex);
 
+       if (flags & ICE_VF_RESET_LOCK)
+               mutex_unlock(&vf->cfg_lock);
+
        return err;
 }
 
index 90316dc58630874d98aeb4095dc991c259a593f4..6bc56c7c181e4882d3ec99ea86e01c8188682175 100644 (file)
@@ -298,6 +298,7 @@ struct igc_adapter {
 
        /* LEDs */
        struct mutex led_mutex;
+       struct igc_led_classdev *leds;
 };
 
 void igc_up(struct igc_adapter *adapter);
@@ -723,6 +724,7 @@ void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
 void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter);
 
 int igc_led_setup(struct igc_adapter *adapter);
+void igc_led_free(struct igc_adapter *adapter);
 
 #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
 
index bf240c5daf8657b3f9dd89f58fda05f87e57e5ae..3929b25b6ae6eb55335a5a6eb7b6494c4cc21982 100644 (file)
@@ -236,8 +236,8 @@ static void igc_led_get_name(struct igc_adapter *adapter, int index, char *buf,
                 pci_dev_id(adapter->pdev), index);
 }
 
-static void igc_setup_ldev(struct igc_led_classdev *ldev,
-                          struct net_device *netdev, int index)
+static int igc_setup_ldev(struct igc_led_classdev *ldev,
+                         struct net_device *netdev, int index)
 {
        struct igc_adapter *adapter = netdev_priv(netdev);
        struct led_classdev *led_cdev = &ldev->led;
@@ -257,24 +257,46 @@ static void igc_setup_ldev(struct igc_led_classdev *ldev,
        led_cdev->hw_control_get = igc_led_hw_control_get;
        led_cdev->hw_control_get_device = igc_led_hw_control_get_device;
 
-       devm_led_classdev_register(&netdev->dev, led_cdev);
+       return led_classdev_register(&netdev->dev, led_cdev);
 }
 
 int igc_led_setup(struct igc_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       struct device *dev = &netdev->dev;
        struct igc_led_classdev *leds;
-       int i;
+       int i, err;
 
        mutex_init(&adapter->led_mutex);
 
-       leds = devm_kcalloc(dev, IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
+       leds = kcalloc(IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
        if (!leds)
                return -ENOMEM;
 
-       for (i = 0; i < IGC_NUM_LEDS; i++)
-               igc_setup_ldev(leds + i, netdev, i);
+       for (i = 0; i < IGC_NUM_LEDS; i++) {
+               err = igc_setup_ldev(leds + i, netdev, i);
+               if (err)
+                       goto err;
+       }
+
+       adapter->leds = leds;
 
        return 0;
+
+err:
+       for (i--; i >= 0; i--)
+               led_classdev_unregister(&((leds + i)->led));
+
+       kfree(leds);
+       return err;
+}
+
+void igc_led_free(struct igc_adapter *adapter)
+{
+       struct igc_led_classdev *leds = adapter->leds;
+       int i;
+
+       for (i = 0; i < IGC_NUM_LEDS; i++)
+               led_classdev_unregister(&((leds + i)->led));
+
+       kfree(leds);
 }
index 35ad40a803cb64a66b983b3a2103a8f15b808df5..4d975d620a8e4b925fe3798a792f2a365877c5a8 100644 (file)
@@ -7021,6 +7021,9 @@ static void igc_remove(struct pci_dev *pdev)
        cancel_work_sync(&adapter->watchdog_task);
        hrtimer_cancel(&adapter->hrtimer);
 
+       if (IS_ENABLED(CONFIG_IGC_LEDS))
+               igc_led_free(adapter);
+
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
         */
index 2500f5ba4f5a42b43ee5de8d64d7f06fb70cdd87..881d704644fbee77cf5c9f7137d539463c08c2dd 100644 (file)
@@ -999,12 +999,10 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
        u16 pcifunc;
        int ret, lf;
 
-       cmd_buf = memdup_user(buffer, count + 1);
+       cmd_buf = memdup_user_nul(buffer, count);
        if (IS_ERR(cmd_buf))
                return -ENOMEM;
 
-       cmd_buf[count] = '\0';
-
        cmd_buf_tmp = strchr(cmd_buf, '\n');
        if (cmd_buf_tmp) {
                *cmd_buf_tmp = '\0';
index be709f83f3318cd8766ca6a2e6b51b88fa8a30e3..e8b73b9d75e3118f56ee42a322d05491b0c325f0 100644 (file)
@@ -2181,7 +2181,6 @@ void rvu_npc_freemem(struct rvu *rvu)
 
        kfree(pkind->rsrc.bmap);
        npc_mcam_rsrcs_deinit(rvu);
-       kfree(mcam->counters.bmap);
        if (rvu->kpu_prfl_addr)
                iounmap(rvu->kpu_prfl_addr);
        else
index b2cabd6ab86cb9044f8d0dc404fa8a052d31938c..cc9bcc420032428eee5188e692991d50aaffc684 100644 (file)
@@ -1640,6 +1640,7 @@ static const struct macsec_ops macsec_offload_ops = {
        .mdo_add_secy = mlx5e_macsec_add_secy,
        .mdo_upd_secy = mlx5e_macsec_upd_secy,
        .mdo_del_secy = mlx5e_macsec_del_secy,
+       .rx_uses_md_dst = true,
 };
 
 bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb)
index e4d7739bd7c888fc774aeb82a5ece0ed894497d8..4a79c0d7e7ad8546aae5e51f7c23ce7ee8642674 100644 (file)
@@ -849,7 +849,7 @@ free_skb:
 
 static const struct mlxsw_listener mlxsw_emad_rx_listener =
        MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
-                 EMAD, DISCARD);
+                 EMAD, FORWARD);
 
 static int mlxsw_emad_tlv_enable(struct mlxsw_core *mlxsw_core)
 {
index 53b150b7ae4e708080cf152c1260983f4cbfc54e..6c06b0592760845f19311fdf4f91672f9209daef 100644 (file)
@@ -1357,24 +1357,20 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
        .got_inactive = mlxsw_env_got_inactive,
 };
 
-static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
+static void mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
 {
        char mcam_pl[MLXSW_REG_MCAM_LEN];
-       bool mcia_128b_supported;
+       bool mcia_128b_supported = false;
        int err;
 
        mlxsw_reg_mcam_pack(mcam_pl,
                            MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
        err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl);
-       if (err)
-               return err;
-
-       mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
-                             &mcia_128b_supported);
+       if (!err)
+               mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
+                                     &mcia_128b_supported);
 
        mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48;
-
-       return 0;
 }
 
 int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
@@ -1445,15 +1441,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
        if (err)
                goto err_type_set;
 
-       err = mlxsw_env_max_module_eeprom_len_query(env);
-       if (err)
-               goto err_eeprom_len_query;
-
+       mlxsw_env_max_module_eeprom_len_query(env);
        env->line_cards[0]->active = true;
 
        return 0;
 
-err_eeprom_len_query:
 err_type_set:
        mlxsw_env_module_event_disable(env, 0);
 err_mlxsw_env_module_event_enable:
index af99bf17eb36de0793b008c063c2a93c6c5b22c8..f42a1b1c9368733d2623643ac6abdd8ffe9b9aff 100644 (file)
@@ -1530,7 +1530,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
 {
        struct pci_dev *pdev = mlxsw_pci->pdev;
        char mcam_pl[MLXSW_REG_MCAM_LEN];
-       bool pci_reset_supported;
+       bool pci_reset_supported = false;
        u32 sys_status;
        int err;
 
@@ -1548,11 +1548,9 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
        mlxsw_reg_mcam_pack(mcam_pl,
                            MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
        err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl);
-       if (err)
-               return err;
-
-       mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
-                             &pci_reset_supported);
+       if (!err)
+               mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
+                                     &pci_reset_supported);
 
        if (pci_reset_supported) {
                pci_dbg(pdev, "Starting PCI reset flow\n");
index f20052776b3f2e9a3ac7181921a12c3858abea4b..92a406f02eae746b4244ca56619fb75c1a2f9d93 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/mutex.h>
 #include <linux/refcount.h>
+#include <linux/idr.h>
 #include <net/devlink.h>
 #include <trace/events/mlxsw.h>
 
@@ -58,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
 static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam,
                                           u16 *p_id)
 {
-       u16 id;
+       int id;
 
-       id = find_first_zero_bit(tcam->used_regions, tcam->max_regions);
-       if (id < tcam->max_regions) {
-               __set_bit(id, tcam->used_regions);
-               *p_id = id;
-               return 0;
-       }
-       return -ENOBUFS;
+       id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1,
+                          GFP_KERNEL);
+       if (id < 0)
+               return id;
+
+       *p_id = id;
+
+       return 0;
 }
 
 static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam,
                                            u16 id)
 {
-       __clear_bit(id, tcam->used_regions);
+       ida_free(&tcam->used_regions, id);
 }
 
 static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam,
                                          u16 *p_id)
 {
-       u16 id;
+       int id;
 
-       id = find_first_zero_bit(tcam->used_groups, tcam->max_groups);
-       if (id < tcam->max_groups) {
-               __set_bit(id, tcam->used_groups);
-               *p_id = id;
-               return 0;
-       }
-       return -ENOBUFS;
+       id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1,
+                          GFP_KERNEL);
+       if (id < 0)
+               return id;
+
+       *p_id = id;
+
+       return 0;
 }
 
 static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam,
                                           u16 id)
 {
-       __clear_bit(id, tcam->used_groups);
+       ida_free(&tcam->used_groups, id);
 }
 
 struct mlxsw_sp_acl_tcam_pattern {
@@ -715,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
                             rehash.dw.work);
        int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
 
+       mutex_lock(&vregion->lock);
        mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
+       mutex_unlock(&vregion->lock);
        if (credits < 0)
                /* Rehash gone out of credits so it was interrupted.
                 * Schedule the work as soon as possible to continue.
@@ -725,6 +730,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
                mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
 }
 
+static void
+mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+       /* The entry markers are relative to the current chunk and therefore
+        * needs to be reset together with the chunk marker.
+        */
+       ctx->current_vchunk = NULL;
+       ctx->start_ventry = NULL;
+       ctx->stop_ventry = NULL;
+}
+
 static void
 mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
 {
@@ -747,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v
         * the current chunk pointer to make sure all chunks
         * are properly migrated.
         */
-       vregion->rehash.ctx.current_vchunk = NULL;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx);
 }
 
 static struct mlxsw_sp_acl_tcam_vregion *
@@ -820,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
 
        if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+               struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
+
                mutex_lock(&tcam->lock);
                list_del(&vregion->tlist);
                mutex_unlock(&tcam->lock);
-               cancel_delayed_work_sync(&vregion->rehash.dw);
+               if (cancel_delayed_work_sync(&vregion->rehash.dw) &&
+                   ctx->hints_priv)
+                       ops->region_rehash_hints_put(ctx->hints_priv);
        }
        mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
        if (vregion->region2)
@@ -1154,8 +1174,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
                                      struct mlxsw_sp_acl_tcam_ventry *ventry,
                                      bool *activity)
 {
-       return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp,
-                                                   ventry->entry, activity);
+       struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion;
+       int err;
+
+       mutex_lock(&vregion->lock);
+       err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry,
+                                                  activity);
+       mutex_unlock(&vregion->lock);
+       return err;
 }
 
 static int
@@ -1189,6 +1215,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
 {
        struct mlxsw_sp_acl_tcam_chunk *new_chunk;
 
+       WARN_ON(vchunk->chunk2);
+
        new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
        if (IS_ERR(new_chunk))
                return PTR_ERR(new_chunk);
@@ -1207,7 +1235,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
 {
        mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
        vchunk->chunk2 = NULL;
-       ctx->current_vchunk = NULL;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 }
 
 static int
@@ -1230,6 +1258,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                return 0;
        }
 
+       if (list_empty(&vchunk->ventry_list))
+               goto out;
+
        /* If the migration got interrupted, we have the ventry to start from
         * stored in context.
         */
@@ -1239,6 +1270,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                ventry = list_first_entry(&vchunk->ventry_list,
                                          typeof(*ventry), list);
 
+       WARN_ON(ventry->vchunk != vchunk);
+
        list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
                /* During rollback, once we reach the ventry that failed
                 * to migrate, we are done.
@@ -1279,6 +1312,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
                }
        }
 
+out:
        mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
        return 0;
 }
@@ -1292,6 +1326,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
        struct mlxsw_sp_acl_tcam_vchunk *vchunk;
        int err;
 
+       if (list_empty(&vregion->vchunk_list))
+               return 0;
+
        /* If the migration got interrupted, we have the vchunk
         * we are working on stored in context.
         */
@@ -1320,16 +1357,17 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
        int err, err2;
 
        trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
-       mutex_lock(&vregion->lock);
        err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
                                                   ctx, credits);
        if (err) {
+               if (ctx->this_is_rollback)
+                       return err;
                /* In case migration was not successful, we need to swap
                 * so the original region pointer is assigned again
                 * to vregion->region.
                 */
                swap(vregion->region, vregion->region2);
-               ctx->current_vchunk = NULL;
+               mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
                ctx->this_is_rollback = true;
                err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
                                                            ctx, credits);
@@ -1340,7 +1378,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
                        /* Let the rollback to be continued later on. */
                }
        }
-       mutex_unlock(&vregion->lock);
        trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
        return err;
 }
@@ -1389,6 +1426,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
 
        ctx->hints_priv = hints_priv;
        ctx->this_is_rollback = false;
+       mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 
        return 0;
 
@@ -1441,7 +1479,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
        err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
                                                ctx, credits);
        if (err) {
-               dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+               return;
        }
 
        if (*credits >= 0)
@@ -1549,19 +1588,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
        if (max_tcam_regions < max_regions)
                max_regions = max_tcam_regions;
 
-       tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL);
-       if (!tcam->used_regions) {
-               err = -ENOMEM;
-               goto err_alloc_used_regions;
-       }
+       ida_init(&tcam->used_regions);
        tcam->max_regions = max_regions;
 
        max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
-       tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL);
-       if (!tcam->used_groups) {
-               err = -ENOMEM;
-               goto err_alloc_used_groups;
-       }
+       ida_init(&tcam->used_groups);
        tcam->max_groups = max_groups;
        tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
                                                  ACL_MAX_GROUP_SIZE);
@@ -1575,10 +1606,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
        return 0;
 
 err_tcam_init:
-       bitmap_free(tcam->used_groups);
-err_alloc_used_groups:
-       bitmap_free(tcam->used_regions);
-err_alloc_used_regions:
+       ida_destroy(&tcam->used_groups);
+       ida_destroy(&tcam->used_regions);
        mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
 err_rehash_params_register:
        mutex_destroy(&tcam->lock);
@@ -1591,8 +1620,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
        const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
 
        ops->fini(mlxsw_sp, tcam->priv);
-       bitmap_free(tcam->used_groups);
-       bitmap_free(tcam->used_regions);
+       ida_destroy(&tcam->used_groups);
+       ida_destroy(&tcam->used_regions);
        mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
        mutex_destroy(&tcam->lock);
 }
index 462bf448497d33b74618c1f78001c0924c666dd5..79a1d8606512531730c2da490e01f47ac0fc6399 100644 (file)
@@ -6,15 +6,16 @@
 
 #include <linux/list.h>
 #include <linux/parman.h>
+#include <linux/idr.h>
 
 #include "reg.h"
 #include "spectrum.h"
 #include "core_acl_flex_keys.h"
 
 struct mlxsw_sp_acl_tcam {
-       unsigned long *used_regions; /* bit array */
+       struct ida used_regions;
        unsigned int max_regions;
-       unsigned long *used_groups;  /* bit array */
+       struct ida used_groups;
        unsigned int max_groups;
        unsigned int max_group_size;
        struct mutex lock; /* guards vregion list */
index a5ac21a0ee33ff01e8bcdcf5757a76a863d6543b..cb6b33a228ea2063edd4f795a1f3368d1fbc483a 100644 (file)
@@ -1868,8 +1868,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
                            struct flow_cls_offload *f)
 {
        struct qede_arfs_fltr_node *n;
-       int min_hlen, rc = -EINVAL;
        struct qede_arfs_tuple t;
+       int min_hlen, rc;
 
        __qede_lock(edev);
 
@@ -1879,7 +1879,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
        }
 
        /* parse flower attribute and prepare filter */
-       if (qede_parse_flow_attr(edev, proto, f->rule, &t))
+       rc = qede_parse_flow_attr(edev, proto, f->rule, &t);
+       if (rc)
                goto unlock;
 
        /* Validate profile mode and number of filters */
@@ -1888,11 +1889,13 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
                DP_NOTICE(edev,
                          "Filter configuration invalidated, filter mode=0x%x, configured mode=0x%x, filter count=0x%x\n",
                          t.mode, edev->arfs->mode, edev->arfs->filter_count);
+               rc = -EINVAL;
                goto unlock;
        }
 
        /* parse tc actions and get the vf_id */
-       if (qede_parse_actions(edev, &f->rule->action, f->common.extack))
+       rc = qede_parse_actions(edev, &f->rule->action, f->common.extack);
+       if (rc)
                goto unlock;
 
        if (qede_flow_find_fltr(edev, &t)) {
@@ -1998,10 +2001,9 @@ static int qede_flow_spec_to_rule(struct qede_dev *edev,
        if (IS_ERR(flow))
                return PTR_ERR(flow);
 
-       if (qede_parse_flow_attr(edev, proto, flow->rule, t)) {
-               err = -EINVAL;
+       err = qede_parse_flow_attr(edev, proto, flow->rule, t);
+       if (err)
                goto err_out;
-       }
 
        /* Make sure location is valid and filter isn't already set */
        err = qede_flow_spec_validate(edev, &flow->rule->action, t,
index fcb756d77681cbaf2a17d3e21ddffa5543bc9a84..9b1f639f64a10cfe89255996bb43d68771f38e5e 100644 (file)
@@ -2722,19 +2722,18 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
        struct platform_device *pdev = priv->pdev;
        struct net_device *ndev = priv->ndev;
        struct device *dev = &pdev->dev;
-       const char *dev_name;
+       const char *devname = dev_name(dev);
        unsigned long flags;
        int error, irq_num;
 
        if (irq_name) {
-               dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
-               if (!dev_name)
+               devname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", devname, ch);
+               if (!devname)
                        return -ENOMEM;
 
                irq_num = platform_get_irq_byname(pdev, irq_name);
                flags = 0;
        } else {
-               dev_name = ndev->name;
                irq_num = platform_get_irq(pdev, 0);
                flags = IRQF_SHARED;
        }
@@ -2744,9 +2743,9 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name,
        if (irq)
                *irq = irq_num;
 
-       error = devm_request_irq(dev, irq_num, handler, flags, dev_name, ndev);
+       error = devm_request_irq(dev, irq_num, handler, flags, devname, ndev);
        if (error)
-               netdev_err(ndev, "cannot request IRQ %s\n", dev_name);
+               netdev_err(ndev, "cannot request IRQ %s\n", devname);
 
        return error;
 }
index c66618d91c28fe2bdf9886b3c476bdb014cd5fe5..f89716b1cfb640577d7ca009adfb99e9b9f00c54 100644 (file)
@@ -784,6 +784,11 @@ static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts,
                struct am65_cpts_skb_cb_data *skb_cb =
                                        (struct am65_cpts_skb_cb_data *)skb->cb;
 
+               if ((ptp_classify_raw(skb) & PTP_CLASS_V1) &&
+                   ((mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK) ==
+                    (skb_cb->skb_mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK)))
+                       mtype_seqid = skb_cb->skb_mtype_seqid;
+
                if (mtype_seqid == skb_cb->skb_mtype_seqid) {
                        u64 ns = event->timestamp;
 
index cf7b73f8f450728930587dc0646a0bbaa1d2b476..b69af69a1ccd3614ab0051b3c7675ab6a42a7872 100644 (file)
@@ -421,12 +421,14 @@ static int prueth_init_rx_chns(struct prueth_emac *emac,
                if (!i)
                        fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn,
                                                                     i);
-               rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
-               if (rx_chn->irq[i] <= 0) {
-                       ret = rx_chn->irq[i];
+               ret = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
+               if (ret <= 0) {
+                       if (!ret)
+                               ret = -ENXIO;
                        netdev_err(ndev, "Failed to get rx dma irq");
                        goto fail;
                }
+               rx_chn->irq[i] = ret;
        }
 
        return 0;
index 6dff2c85682d8bcdd97ca614447e205919d5decd..6fae161cbcb822614a8f36935559f364ee0a7dc8 100644 (file)
@@ -1598,7 +1598,7 @@ static void wx_set_num_queues(struct wx *wx)
  */
 static int wx_acquire_msix_vectors(struct wx *wx)
 {
-       struct irq_affinity affd = {0, };
+       struct irq_affinity affd = { .pre_vectors = 1 };
        int nvecs, i;
 
        /* We start by asking for one vector per queue pair */
index 2fa511227eac8490314c09821c7b6f1e1fdfed43..93295916b1d2b80751637dee4a0006688958c428 100644 (file)
@@ -20,8 +20,6 @@
 #include "txgbe_phy.h"
 #include "txgbe_hw.h"
 
-#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw"
-
 static int txgbe_swnodes_register(struct txgbe *txgbe)
 {
        struct txgbe_nodes *nodes = &txgbe->nodes;
@@ -573,8 +571,8 @@ static int txgbe_clock_register(struct txgbe *txgbe)
        char clk_name[32];
        struct clk *clk;
 
-       snprintf(clk_name, sizeof(clk_name), "%s.%d",
-                TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev));
+       snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
+                pci_dev_id(pdev));
 
        clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
        if (IS_ERR(clk))
@@ -636,7 +634,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe)
 
        info.parent = &pdev->dev;
        info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
-       info.name = TXGBE_I2C_CLK_DEV_NAME;
+       info.name = "i2c_designware";
        info.id = pci_dev_id(pdev);
 
        info.res = &DEFINE_RES_IRQ(pdev->irq);
index ba4704c2c640b860c55655607f8dd5cc044cfa3e..e62d6cbdf9bc6458064c7c0852fc23db095ae642 100644 (file)
@@ -1098,11 +1098,12 @@ out_hashtable:
 static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
        struct gtp_dev *gtp = netdev_priv(dev);
+       struct hlist_node *next;
        struct pdp_ctx *pctx;
        int i;
 
        for (i = 0; i < gtp->hash_size; i++)
-               hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
+               hlist_for_each_entry_safe(pctx, next, &gtp->tid_hash[i], hlist_tid)
                        pdp_context_delete(pctx);
 
        list_del_rcu(&gtp->list);
index 0206b84284ab5e0c95981ff86fa4b2a2a14c5c51..ff016c11b4a0383b6653a37ef4bc6344fff3f703 100644 (file)
@@ -999,10 +999,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
        struct metadata_dst *md_dst;
        struct macsec_rxh_data *rxd;
        struct macsec_dev *macsec;
+       bool is_macsec_md_dst;
 
        rcu_read_lock();
        rxd = macsec_data_rcu(skb->dev);
        md_dst = skb_metadata_dst(skb);
+       is_macsec_md_dst = md_dst && md_dst->type == METADATA_MACSEC;
 
        list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
                struct sk_buff *nskb;
@@ -1013,14 +1015,42 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                 * the SecTAG, so we have to deduce which port to deliver to.
                 */
                if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
-                       struct macsec_rx_sc *rx_sc = NULL;
+                       const struct macsec_ops *ops;
 
-                       if (md_dst && md_dst->type == METADATA_MACSEC)
-                               rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci);
+                       ops = macsec_get_ops(macsec, NULL);
 
-                       if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc)
+                       if (ops->rx_uses_md_dst && !is_macsec_md_dst)
                                continue;
 
+                       if (is_macsec_md_dst) {
+                               struct macsec_rx_sc *rx_sc;
+
+                               /* All drivers that implement MACsec offload
+                                * support using skb metadata destinations must
+                                * indicate that they do so.
+                                */
+                               DEBUG_NET_WARN_ON_ONCE(!ops->rx_uses_md_dst);
+                               rx_sc = find_rx_sc(&macsec->secy,
+                                                  md_dst->u.macsec_info.sci);
+                               if (!rx_sc)
+                                       continue;
+                               /* device indicated macsec offload occurred */
+                               skb->dev = ndev;
+                               skb->pkt_type = PACKET_HOST;
+                               eth_skb_pkt_type(skb, ndev);
+                               ret = RX_HANDLER_ANOTHER;
+                               goto out;
+                       }
+
+                       /* This datapath is insecure because it is unable to
+                        * enforce isolation of broadcast/multicast traffic and
+                        * unicast traffic with promiscuous mode on the macsec
+                        * netdev. Since the core stack has no mechanism to
+                        * check that the hardware did indeed receive MACsec
+                        * traffic, it is possible that the response handling
+                        * done by the MACsec port was to a plaintext packet.
+                        * This violates the MACsec protocol standard.
+                        */
                        if (ether_addr_equal_64bits(hdr->h_dest,
                                                    ndev->dev_addr)) {
                                /* exact match, divert skb to this port */
@@ -1036,14 +1066,10 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
                                        break;
 
                                nskb->dev = ndev;
-                               if (ether_addr_equal_64bits(hdr->h_dest,
-                                                           ndev->broadcast))
-                                       nskb->pkt_type = PACKET_BROADCAST;
-                               else
-                                       nskb->pkt_type = PACKET_MULTICAST;
+                               eth_skb_pkt_type(nskb, ndev);
 
                                __netif_rx(nskb);
-                       } else if (rx_sc || ndev->flags & IFF_PROMISC) {
+                       } else if (ndev->flags & IFF_PROMISC) {
                                skb->dev = ndev;
                                skb->pkt_type = PACKET_HOST;
                                ret = RX_HANDLER_ANOTHER;
index fa8c6fdcf30181067c7c3f164e997171908a70b8..d7aaefb5226b62ad5de3c3783c189b8f45b1a7c2 100644 (file)
@@ -695,7 +695,8 @@ static int dp83869_configure_mode(struct phy_device *phydev,
        phy_ctrl_val = dp83869->mode;
        if (phydev->interface == PHY_INTERFACE_MODE_MII) {
                if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
-                   dp83869->mode == DP83869_RGMII_100_BASE) {
+                   dp83869->mode == DP83869_RGMII_100_BASE ||
+                   dp83869->mode == DP83869_RGMII_COPPER_ETHERNET) {
                        phy_ctrl_val |= DP83869_OP_MODE_MII;
                } else {
                        phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
index 0f3a1538a8b8ee045953a3c5ff308dc824ea7c0a..f4f9412d0cd7e256f4b2e962dd18974e1120c0fb 100644 (file)
 #define   MTK_PHY_LED_ON_LINK1000              BIT(0)
 #define   MTK_PHY_LED_ON_LINK100               BIT(1)
 #define   MTK_PHY_LED_ON_LINK10                        BIT(2)
+#define   MTK_PHY_LED_ON_LINK                  (MTK_PHY_LED_ON_LINK10 |\
+                                                MTK_PHY_LED_ON_LINK100 |\
+                                                MTK_PHY_LED_ON_LINK1000)
 #define   MTK_PHY_LED_ON_LINKDOWN              BIT(3)
 #define   MTK_PHY_LED_ON_FDX                   BIT(4) /* Full duplex */
 #define   MTK_PHY_LED_ON_HDX                   BIT(5) /* Half duplex */
 #define   MTK_PHY_LED_BLINK_100RX              BIT(3)
 #define   MTK_PHY_LED_BLINK_10TX               BIT(4)
 #define   MTK_PHY_LED_BLINK_10RX               BIT(5)
+#define   MTK_PHY_LED_BLINK_RX                 (MTK_PHY_LED_BLINK_10RX |\
+                                                MTK_PHY_LED_BLINK_100RX |\
+                                                MTK_PHY_LED_BLINK_1000RX)
+#define   MTK_PHY_LED_BLINK_TX                 (MTK_PHY_LED_BLINK_10TX |\
+                                                MTK_PHY_LED_BLINK_100TX |\
+                                                MTK_PHY_LED_BLINK_1000TX)
 #define   MTK_PHY_LED_BLINK_COLLISION          BIT(6)
 #define   MTK_PHY_LED_BLINK_RX_CRC_ERR         BIT(7)
 #define   MTK_PHY_LED_BLINK_RX_IDLE_ERR                BIT(8)
@@ -1247,11 +1256,9 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (blink < 0)
                return -EIO;
 
-       if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 |
-                  MTK_PHY_LED_ON_LINK10)) ||
-           (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX |
-                     MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX |
-                     MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)))
+       if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
+                  MTK_PHY_LED_ON_LINKDOWN)) ||
+           (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
                set_bit(bit_netdev, &priv->led_state);
        else
                clear_bit(bit_netdev, &priv->led_state);
@@ -1269,7 +1276,7 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (!rules)
                return 0;
 
-       if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10))
+       if (on & MTK_PHY_LED_ON_LINK)
                *rules |= BIT(TRIGGER_NETDEV_LINK);
 
        if (on & MTK_PHY_LED_ON_LINK10)
@@ -1287,10 +1294,10 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
        if (on & MTK_PHY_LED_ON_HDX)
                *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
 
-       if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX))
+       if (blink & MTK_PHY_LED_BLINK_RX)
                *rules |= BIT(TRIGGER_NETDEV_RX);
 
-       if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))
+       if (blink & MTK_PHY_LED_BLINK_TX)
                *rules |= BIT(TRIGGER_NETDEV_TX);
 
        return 0;
@@ -1323,15 +1330,19 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
                on |= MTK_PHY_LED_ON_LINK1000;
 
        if (rules & BIT(TRIGGER_NETDEV_RX)) {
-               blink |= MTK_PHY_LED_BLINK_10RX  |
-                        MTK_PHY_LED_BLINK_100RX |
-                        MTK_PHY_LED_BLINK_1000RX;
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+                         (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
+                         MTK_PHY_LED_BLINK_RX;
        }
 
        if (rules & BIT(TRIGGER_NETDEV_TX)) {
-               blink |= MTK_PHY_LED_BLINK_10TX  |
-                        MTK_PHY_LED_BLINK_100TX |
-                        MTK_PHY_LED_BLINK_1000TX;
+               blink |= (on & MTK_PHY_LED_ON_LINK) ?
+                         (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
+                          ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
+                         MTK_PHY_LED_BLINK_TX;
        }
 
        if (blink || on)
@@ -1344,9 +1355,7 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
                                MTK_PHY_LED0_ON_CTRL,
                             MTK_PHY_LED_ON_FDX     |
                             MTK_PHY_LED_ON_HDX     |
-                            MTK_PHY_LED_ON_LINK10  |
-                            MTK_PHY_LED_ON_LINK100 |
-                            MTK_PHY_LED_ON_LINK1000,
+                            MTK_PHY_LED_ON_LINK,
                             on);
 
        if (ret)
index 752f821a19901f313a1aca51fe332539ce82385b..df9d767cb524241848c744504d6e2999efc42ed5 100644 (file)
@@ -1456,21 +1456,16 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        /* Skip IP alignment pseudo header */
                        skb_pull(skb, 2);
 
-                       skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
                        ax88179_rx_checksum(skb, pkt_hdr);
                        return 1;
                }
 
-               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               ax_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
                if (!ax_skb)
                        return 0;
-               skb_trim(ax_skb, pkt_len);
+               skb_put(ax_skb, pkt_len);
+               memcpy(ax_skb->data, skb->data + 2, pkt_len);
 
-               /* Skip IP alignment pseudo header */
-               skb_pull(ax_skb, 2);
-
-               skb->truesize = pkt_len_plus_padd +
-                               SKB_DATA_ALIGN(sizeof(struct sk_buff));
                ax88179_rx_checksum(ax_skb, pkt_hdr);
                usbnet_skb_return(dev, ax_skb);
 
index edc34402e787f9ff84a345ecb892cc7b720ef312..a5469cf5cf6706de2c3ded24f675f504c794227c 100644 (file)
@@ -1368,6 +1368,9 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
        {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},    /* Telit ME910 */
        {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)},    /* Telit ME910 dual modem */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
index 3495591a5c29b2aa929fcf307c2970c661ec2ea6..3a9148fb1422ba5bedcbfe368fb611fc60732f66 100644 (file)
@@ -1615,6 +1615,10 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
        if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
                return false;
 
+       /* Ignore packets from invalid src-address */
+       if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+               return false;
+
        /* Get address from the outer IP header */
        if (vxlan_get_sk_family(vs) == AF_INET) {
                saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
@@ -1670,6 +1674,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
        bool raw_proto = false;
        void *oiph;
        __be32 vni = 0;
+       int nh;
 
        /* Need UDP and VXLAN header to be present */
        if (!pskb_may_pull(skb, VXLAN_HLEN))
@@ -1758,12 +1763,28 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
                skb->pkt_type = PACKET_HOST;
        }
 
-       oiph = skb_network_header(skb);
+       /* Save offset of outer header relative to skb->head,
+        * because we are going to reset the network header to the inner header
+        * and might change skb->head.
+        */
+       nh = skb_network_header(skb) - skb->head;
+
        skb_reset_network_header(skb);
 
+       if (!pskb_inet_may_pull(skb)) {
+               DEV_STATS_INC(vxlan->dev, rx_length_errors);
+               DEV_STATS_INC(vxlan->dev, rx_errors);
+               vxlan_vnifilter_count(vxlan, vni, vninode,
+                                     VXLAN_VNI_STATS_RX_ERRORS, 0);
+               goto drop;
+       }
+
+       /* Get the outer header. */
+       oiph = skb->head + nh;
+
        if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
-               ++vxlan->dev->stats.rx_frame_errors;
-               ++vxlan->dev->stats.rx_errors;
+               DEV_STATS_INC(vxlan->dev, rx_frame_errors);
+               DEV_STATS_INC(vxlan->dev, rx_errors);
                vxlan_vnifilter_count(vxlan, vni, vninode,
                                      VXLAN_VNI_STATS_RX_ERRORS, 0);
                goto drop;
@@ -1833,7 +1854,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
                goto out;
 
        if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
-               dev->stats.tx_dropped++;
+               dev_core_stats_tx_dropped_inc(dev);
+               vxlan_vnifilter_count(vxlan, vni, NULL,
+                                     VXLAN_VNI_STATS_TX_DROPS, 0);
                goto out;
        }
        parp = arp_hdr(skb);
@@ -1889,7 +1912,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
                reply->pkt_type = PACKET_HOST;
 
                if (netif_rx(reply) == NET_RX_DROP) {
-                       dev->stats.rx_dropped++;
+                       dev_core_stats_rx_dropped_inc(dev);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_RX_DROPS, 0);
                }
@@ -2048,7 +2071,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
                        goto out;
 
                if (netif_rx(reply) == NET_RX_DROP) {
-                       dev->stats.rx_dropped++;
+                       dev_core_stats_rx_dropped_inc(dev);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_RX_DROPS, 0);
                }
@@ -2259,7 +2282,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                                      len);
        } else {
 drop:
-               dev->stats.rx_dropped++;
+               dev_core_stats_rx_dropped_inc(dev);
                vxlan_vnifilter_count(dst_vxlan, vni, NULL,
                                      VXLAN_VNI_STATS_RX_DROPS, 0);
        }
@@ -2291,7 +2314,7 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
                                           addr_family, dst_port,
                                           vxlan->cfg.flags);
                if (!dst_vxlan) {
-                       dev->stats.tx_errors++;
+                       DEV_STATS_INC(dev, tx_errors);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_TX_ERRORS, 0);
                        kfree_skb(skb);
@@ -2555,7 +2578,7 @@ out_unlock:
        return;
 
 drop:
-       dev->stats.tx_dropped++;
+       dev_core_stats_tx_dropped_inc(dev);
        vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
        dev_kfree_skb(skb);
        return;
@@ -2563,11 +2586,11 @@ drop:
 tx_error:
        rcu_read_unlock();
        if (err == -ELOOP)
-               dev->stats.collisions++;
+               DEV_STATS_INC(dev, collisions);
        else if (err == -ENETUNREACH)
-               dev->stats.tx_carrier_errors++;
+               DEV_STATS_INC(dev, tx_carrier_errors);
        dst_release(ndst);
-       dev->stats.tx_errors++;
+       DEV_STATS_INC(dev, tx_errors);
        vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
        kfree_skb(skb);
 }
@@ -2600,7 +2623,7 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
        return;
 
 drop:
-       dev->stats.tx_dropped++;
+       dev_core_stats_tx_dropped_inc(dev);
        vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
                              VXLAN_VNI_STATS_TX_DROPS, 0);
        dev_kfree_skb(skb);
@@ -2638,7 +2661,7 @@ static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev,
        return NETDEV_TX_OK;
 
 drop:
-       dev->stats.tx_dropped++;
+       dev_core_stats_tx_dropped_inc(dev);
        vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
                              VXLAN_VNI_STATS_TX_DROPS, 0);
        dev_kfree_skb(skb);
@@ -2735,7 +2758,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
                            !is_multicast_ether_addr(eth->h_dest))
                                vxlan_fdb_miss(vxlan, eth->h_dest);
 
-                       dev->stats.tx_dropped++;
+                       dev_core_stats_tx_dropped_inc(dev);
                        vxlan_vnifilter_count(vxlan, vni, NULL,
                                              VXLAN_VNI_STATS_TX_DROPS, 0);
                        kfree_skb(skb);
index a6a37d67a50ad552b4185af654289d635c2cfd70..9f4bf41a3d41e4e1395aa77fb6874130e5783d96 100644 (file)
@@ -9020,6 +9020,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
        offload = &arvif->arp_ns_offload;
        count = 0;
 
+       /* Note: read_lock_bh() calls rcu_read_lock() */
        read_lock_bh(&idev->lock);
 
        memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr));
@@ -9050,7 +9051,8 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
        }
 
        /* get anycast address */
-       for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) {
+       for (ifaca6 = rcu_dereference(idev->ac_list); ifaca6;
+            ifaca6 = rcu_dereference(ifaca6->aca_next)) {
                if (count >= ATH11K_IPV6_MAX_COUNT)
                        goto generate;
 
index 072b0a5827d19f801d9f0da38933aef21044b7fc..eca1457caa0cad9eb13edce501beba6d5540fe57 100644 (file)
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware API version supported */
-#define IWL_BZ_UCODE_API_MAX   90
+#define IWL_BZ_UCODE_API_MAX   89
 
 /* Lowest firmware API version supported */
 #define IWL_BZ_UCODE_API_MIN   80
index 9b79279fd76cad94170d28614b7eee0729ac02f8..dbbcb2d0968c0992d15f652409cf651dc625428c 100644 (file)
@@ -10,7 +10,7 @@
 #include "fw/api/txq.h"
 
 /* Highest firmware API version supported */
-#define IWL_SC_UCODE_API_MAX   90
+#define IWL_SC_UCODE_API_MAX   89
 
 /* Lowest firmware API version supported */
 #define IWL_SC_UCODE_API_MIN   82
index 4863a3c746406ed70a398d8939e080e72636fa0b..d84d7e955bb021fc1994d1b5fa9e21183e01027a 100644 (file)
@@ -53,6 +53,8 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        if (!pasn)
                return -ENOBUFS;
 
+       iwl_mvm_ftm_remove_pasn_sta(mvm, addr);
+
        pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher);
 
        switch (pasn->cipher) {
index 9f69e04594e49cb59f3102071c905bd75b93f825..fe5bba8561d0c69abeef30221c5cc040f64c7b96 100644 (file)
@@ -279,6 +279,7 @@ int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
                         NULL);
+       iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
        return 0;
 }
 
@@ -296,7 +297,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                return 0;
 
        cmd.link_id = cpu_to_le32(link_info->fw_link_id);
-       iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
        link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
        cmd.spec_link_id = link_conf->link_id;
        cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID);
index f3e3986b4c72f2aabfd9ff67edf8c11a1bebc03c..11559563ae38162e8c138dddc79e0cc89f3b349d 100644 (file)
@@ -2813,7 +2813,8 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
                if (ver_handler->version != scan_ver)
                        continue;
 
-               return ver_handler->handler(mvm, vif, params, type, uid);
+               err = ver_handler->handler(mvm, vif, params, type, uid);
+               return err ? : uid;
        }
 
        err = iwl_mvm_scan_umac(mvm, vif, params, type, uid);
index b55fe320633c74b42618d37be6bc40a951f0c898..59e1fc0018df3f32d60e3e52341350c10a44d0f0 100644 (file)
@@ -3899,7 +3899,7 @@ static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info)
        }
 
        nla_for_each_nested(peer, peers, rem) {
-               struct cfg80211_pmsr_result result;
+               struct cfg80211_pmsr_result result = {};
 
                err = mac80211_hwsim_parse_pmsr_result(peer, &result, info);
                if (err)
index 7eb17f46a8153d88705603e421f350b0fd091c2b..9e1a34e23af26e0a2bd7e18b4e3fe5f6726f560d 100644 (file)
@@ -424,7 +424,8 @@ struct trf7970a {
        enum trf7970a_state             state;
        struct device                   *dev;
        struct spi_device               *spi;
-       struct regulator                *regulator;
+       struct regulator                *vin_regulator;
+       struct regulator                *vddio_regulator;
        struct nfc_digital_dev          *ddev;
        u32                             quirks;
        bool                            is_initiator;
@@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
        if (trf->state != TRF7970A_ST_PWR_OFF)
                return 0;
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
                return ret;
@@ -1926,7 +1927,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
        if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
                gpiod_set_value_cansleep(trf->en2_gpiod, 0);
 
-       ret = regulator_disable(trf->regulator);
+       ret = regulator_disable(trf->vin_regulator);
        if (ret)
                dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
                        ret);
@@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi)
        mutex_init(&trf->lock);
        INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vin");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
+       if (IS_ERR(trf->vin_regulator)) {
+               ret = PTR_ERR(trf->vin_regulator);
                dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vin_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
                goto err_destroy_lock;
        }
 
-       uvolts = regulator_get_voltage(trf->regulator);
+       uvolts = regulator_get_voltage(trf->vin_regulator);
        if (uvolts > 4000000)
                trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
 
-       trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
-       if (IS_ERR(trf->regulator)) {
-               ret = PTR_ERR(trf->regulator);
+       trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
+       if (IS_ERR(trf->vddio_regulator)) {
+               ret = PTR_ERR(trf->vddio_regulator);
                dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
-               goto err_destroy_lock;
+               goto err_disable_vin_regulator;
        }
 
-       ret = regulator_enable(trf->regulator);
+       ret = regulator_enable(trf->vddio_regulator);
        if (ret) {
                dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
-               goto err_destroy_lock;
+               goto err_disable_vin_regulator;
        }
 
-       if (regulator_get_voltage(trf->regulator) == 1800000) {
+       if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
                trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
                dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
        }
@@ -2108,7 +2109,7 @@ static int trf7970a_probe(struct spi_device *spi)
        if (!trf->ddev) {
                dev_err(trf->dev, "Can't allocate NFC digital device\n");
                ret = -ENOMEM;
-               goto err_disable_regulator;
+               goto err_disable_vddio_regulator;
        }
 
        nfc_digital_set_parent_dev(trf->ddev, trf->dev);
@@ -2137,8 +2138,10 @@ err_shutdown:
        trf7970a_shutdown(trf);
 err_free_ddev:
        nfc_digital_free_device(trf->ddev);
-err_disable_regulator:
-       regulator_disable(trf->regulator);
+err_disable_vddio_regulator:
+       regulator_disable(trf->vddio_regulator);
+err_disable_vin_regulator:
+       regulator_disable(trf->vin_regulator);
 err_destroy_lock:
        mutex_destroy(&trf->lock);
        return ret;
@@ -2157,7 +2160,8 @@ static void trf7970a_remove(struct spi_device *spi)
        nfc_digital_unregister_device(trf->ddev);
        nfc_digital_free_device(trf->ddev);
 
-       regulator_disable(trf->regulator);
+       regulator_disable(trf->vddio_regulator);
+       regulator_disable(trf->vin_regulator);
 
        mutex_destroy(&trf->lock);
 }
index 27281a9a8951dbd53f30a27a14e0ac0be9a35c5d..095f59e7aa937aa3ae9d8e3fc3f1a25608c99f25 100644 (file)
@@ -628,27 +628,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 }
 EXPORT_SYMBOL_GPL(nvme_change_ctrl_state);
 
-/*
- * Returns true for sink states that can't ever transition back to live.
- */
-static bool nvme_state_terminal(struct nvme_ctrl *ctrl)
-{
-       switch (nvme_ctrl_state(ctrl)) {
-       case NVME_CTRL_NEW:
-       case NVME_CTRL_LIVE:
-       case NVME_CTRL_RESETTING:
-       case NVME_CTRL_CONNECTING:
-               return false;
-       case NVME_CTRL_DELETING:
-       case NVME_CTRL_DELETING_NOIO:
-       case NVME_CTRL_DEAD:
-               return true;
-       default:
-               WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
-               return true;
-       }
-}
-
 /*
  * Waits for the controller state to be resetting, or returns false if it is
  * not possible to ever transition to that state.
@@ -3681,7 +3660,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
                                "Found shared namespace %d, but multipathing not supported.\n",
                                info->nsid);
                        dev_warn_once(ctrl->device,
-                               "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0\n.");
+                               "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0.\n");
                }
        }
 
index 5397fb428b242cea36f8c36997e134f6463e9f39..d16e976ae1a4732efef32a9da1da88be6567f621 100644 (file)
@@ -247,7 +247,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
                if (nvme_path_is_disabled(ns))
                        continue;
 
-               if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
+               if (ns->ctrl->numa_node != NUMA_NO_NODE &&
+                   READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
                        distance = node_distance(node, ns->ctrl->numa_node);
                else
                        distance = LOCAL_DISTANCE;
index d0ed64dc7380e51577bc6ece92db1d0a273905a7..b564c5f1450c6a506302c482882d2be31a8eb5c6 100644 (file)
@@ -741,6 +741,27 @@ static inline bool nvme_is_aen_req(u16 qid, __u16 command_id)
                nvme_tag_from_cid(command_id) >= NVME_AQ_BLK_MQ_DEPTH;
 }
 
+/*
+ * Returns true for sink states that can't ever transition back to live.
+ */
+static inline bool nvme_state_terminal(struct nvme_ctrl *ctrl)
+{
+       switch (nvme_ctrl_state(ctrl)) {
+       case NVME_CTRL_NEW:
+       case NVME_CTRL_LIVE:
+       case NVME_CTRL_RESETTING:
+       case NVME_CTRL_CONNECTING:
+               return false;
+       case NVME_CTRL_DELETING:
+       case NVME_CTRL_DELETING_NOIO:
+       case NVME_CTRL_DEAD:
+               return true;
+       default:
+               WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
+               return true;
+       }
+}
+
 void nvme_complete_rq(struct request *req);
 void nvme_complete_batch_req(struct request *req);
 
index 8e0bb9692685d4638bd21dad44fe1fbbbb147a77..e393f6947ce493f8674a7bb971dc4d4abae192ca 100644 (file)
@@ -1286,6 +1286,9 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
        u32 csts = readl(dev->bar + NVME_REG_CSTS);
        u8 opcode;
 
+       if (nvme_state_terminal(&dev->ctrl))
+               goto disable;
+
        /* If PCI error recovery process is happening, we cannot reset or
         * the recovery mechanism will surely fail.
         */
@@ -1390,8 +1393,11 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
        return BLK_EH_RESET_TIMER;
 
 disable:
-       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) {
+               if (nvme_state_terminal(&dev->ctrl))
+                       nvme_dev_disable(dev, true);
                return BLK_EH_DONE;
+       }
 
        nvme_dev_disable(dev, false);
        if (nvme_try_sched_reset(&dev->ctrl))
index fdbcdcedcee99f064cc7258d22b7fe737d285eda..28bc2f373cfa0e715040a7d4f5a18db4690ca5dc 100644 (file)
@@ -360,12 +360,18 @@ static inline void nvme_tcp_send_all(struct nvme_tcp_queue *queue)
        } while (ret > 0);
 }
 
-static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
+static inline bool nvme_tcp_queue_has_pending(struct nvme_tcp_queue *queue)
 {
        return !list_empty(&queue->send_list) ||
                !llist_empty(&queue->req_list);
 }
 
+static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
+{
+       return !nvme_tcp_tls(&queue->ctrl->ctrl) &&
+               nvme_tcp_queue_has_pending(queue);
+}
+
 static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
                bool sync, bool last)
 {
@@ -386,7 +392,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
                mutex_unlock(&queue->send_mutex);
        }
 
-       if (last && nvme_tcp_queue_more(queue))
+       if (last && nvme_tcp_queue_has_pending(queue))
                queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work);
 }
 
index 3ddbc3880cac8d327074fe8f923b9f257979c8bd..fb518b00f71f6034a74be5746fc30b5bb090b972 100644 (file)
@@ -285,9 +285,9 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
        }
 
        if (shash_len != crypto_shash_digestsize(shash_tfm)) {
-               pr_debug("%s: hash len mismatch (len %d digest %d)\n",
-                        __func__, shash_len,
-                        crypto_shash_digestsize(shash_tfm));
+               pr_err("%s: hash len mismatch (len %d digest %d)\n",
+                       __func__, shash_len,
+                       crypto_shash_digestsize(shash_tfm));
                ret = -EINVAL;
                goto out_free_tfm;
        }
@@ -370,7 +370,7 @@ out_free_response:
        nvme_auth_free_key(transformed_key);
 out_free_tfm:
        crypto_free_shash(shash_tfm);
-       return 0;
+       return ret;
 }
 
 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
index a2325330bf22145202837aa5cf89d9ec6543ab59..89a001101a7fca08bf047405aac92704bdd9a4c9 100644 (file)
@@ -754,6 +754,19 @@ static struct configfs_attribute *nvmet_ns_attrs[] = {
        NULL,
 };
 
+bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid)
+{
+       struct config_item *ns_item;
+       char name[4] = {};
+
+       if (sprintf(name, "%u", nsid) <= 0)
+               return false;
+       mutex_lock(&subsys->namespaces_group.cg_subsys->su_mutex);
+       ns_item = config_group_find_item(&subsys->namespaces_group, name);
+       mutex_unlock(&subsys->namespaces_group.cg_subsys->su_mutex);
+       return ns_item != NULL;
+}
+
 static void nvmet_ns_release(struct config_item *item)
 {
        struct nvmet_ns *ns = to_nvmet_ns(item);
index 8860a3eb71ec891e948a34060f34b4b148553418..e06013c5dace94d8b91960451b868fe6eaac2137 100644 (file)
@@ -437,10 +437,13 @@ void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl)
 u16 nvmet_req_find_ns(struct nvmet_req *req)
 {
        u32 nsid = le32_to_cpu(req->cmd->common.nsid);
+       struct nvmet_subsys *subsys = nvmet_req_subsys(req);
 
-       req->ns = xa_load(&nvmet_req_subsys(req)->namespaces, nsid);
+       req->ns = xa_load(&subsys->namespaces, nsid);
        if (unlikely(!req->ns)) {
                req->error_loc = offsetof(struct nvme_common_command, nsid);
+               if (nvmet_subsys_nsid_exists(subsys, nsid))
+                       return NVME_SC_INTERNAL_PATH_ERROR;
                return NVME_SC_INVALID_NS | NVME_SC_DNR;
        }
 
index f460728e1df1fd87e24969e782203c7684a23326..c1306de1f4ddf650c2ee66167559f27e4004e837 100644 (file)
@@ -543,6 +543,7 @@ void nvmet_subsys_disc_changed(struct nvmet_subsys *subsys,
                struct nvmet_host *host);
 void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
                u8 event_info, u8 log_page);
+bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid);
 
 #define NVMET_MIN_QUEUE_SIZE   16
 #define NVMET_MAX_QUEUE_SIZE   1024
index a5422e2c979addca1f219777b47f61f5817e302a..380f22ee3ebba3ef5fe50108b39ea78345c1f1ba 100644 (file)
@@ -348,6 +348,7 @@ static int nvmet_tcp_check_ddgst(struct nvmet_tcp_queue *queue, void *pdu)
        return 0;
 }
 
+/* If cmd buffers are NULL, no operation is performed */
 static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
 {
        kfree(cmd->iov);
@@ -1581,13 +1582,9 @@ static void nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue *queue)
        struct nvmet_tcp_cmd *cmd = queue->cmds;
        int i;
 
-       for (i = 0; i < queue->nr_cmds; i++, cmd++) {
-               if (nvmet_tcp_need_data_in(cmd))
-                       nvmet_tcp_free_cmd_buffers(cmd);
-       }
-
-       if (!queue->nr_cmds && nvmet_tcp_need_data_in(&queue->connect))
-               nvmet_tcp_free_cmd_buffers(&queue->connect);
+       for (i = 0; i < queue->nr_cmds; i++, cmd++)
+               nvmet_tcp_free_cmd_buffers(cmd);
+       nvmet_tcp_free_cmd_buffers(&queue->connect);
 }
 
 static void nvmet_tcp_release_queue_work(struct work_struct *w)
index b700f52b7b6799f92c1c66f8c737efaae7a47dfc..11fcb1867118c3662c9a9b7f6c103dca5af4c768 100644 (file)
@@ -110,8 +110,10 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
                /* Source clock from SoC internal PLL */
                writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
                       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
-               writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
-                      imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+               if (imx8_phy->drvdata->variant != IMX8MM) {
+                       writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+                              imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+               }
                val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
                writel(val | ANA_AUX_RX_TERM_GND_EN,
                       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
index 41162d7228c919dadc65c526657e120eff268f59..1d1db1737422a8edd29cf63201ee244270ee1e69 100644 (file)
@@ -603,7 +603,7 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
        u16 val;
 
        fix_idx = 0;
-       for (addr = 0; addr < 512; addr++) {
+       for (addr = 0; addr < ARRAY_SIZE(gbe_phy_init); addr++) {
                /*
                 * All PHY register values are defined in full for 3.125Gbps
                 * SERDES speed. The values required for 1.25 Gbps are almost
@@ -611,11 +611,12 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
                 * comparison to 3.125 Gbps values. These register values are
                 * stored in "gbe_phy_init_fix" array.
                 */
-               if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) {
+               if (!is_1gbps &&
+                   fix_idx < ARRAY_SIZE(gbe_phy_init_fix) &&
+                   gbe_phy_init_fix[fix_idx].addr == addr) {
                        /* Use new value */
                        val = gbe_phy_init_fix[fix_idx].value;
-                       if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix))
-                               fix_idx++;
+                       fix_idx++;
                } else {
                        val = gbe_phy_init[addr];
                }
index 03fb0d4b75d744492e4646af65287f61e7927f1b..20d4c020a83c1f7566533e0e8de5b7cd796415ad 100644 (file)
@@ -297,7 +297,7 @@ static int m31usb_phy_probe(struct platform_device *pdev)
                return dev_err_probe(dev, PTR_ERR(qphy->phy),
                                     "failed to create phy\n");
 
-       qphy->vreg = devm_regulator_get(dev, "vdda-phy");
+       qphy->vreg = devm_regulator_get(dev, "vdd");
        if (IS_ERR(qphy->vreg))
                return dev_err_probe(dev, PTR_ERR(qphy->vreg),
                                     "failed to get vreg\n");
index 7d585a4bbbba950c803412d829bed4140d57d898..c21cdb8dbfe746061acea9b9ec1ab516d05cd3d3 100644 (file)
@@ -77,6 +77,7 @@ enum qphy_reg_layout {
        QPHY_COM_BIAS_EN_CLKBUFLR_EN,
 
        QPHY_DP_PHY_STATUS,
+       QPHY_DP_PHY_VCO_DIV,
 
        QPHY_TX_TX_POL_INV,
        QPHY_TX_TX_DRV_LVL,
@@ -102,6 +103,7 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V3_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V3_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V3_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V3_TX_TX_DRV_LVL,
@@ -126,6 +128,7 @@ static const unsigned int qmp_v45_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V4_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V4_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V4_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V4_TX_TX_DRV_LVL,
@@ -150,6 +153,7 @@ static const unsigned int qmp_v5_5nm_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V5_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V5_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V5_5NM_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V5_5NM_TX_TX_DRV_LVL,
@@ -174,6 +178,7 @@ static const unsigned int qmp_v6_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
        [QPHY_COM_BIAS_EN_CLKBUFLR_EN]  = QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN,
 
        [QPHY_DP_PHY_STATUS]            = QSERDES_V6_DP_PHY_STATUS,
+       [QPHY_DP_PHY_VCO_DIV]           = QSERDES_V6_DP_PHY_VCO_DIV,
 
        [QPHY_TX_TX_POL_INV]            = QSERDES_V6_TX_TX_POL_INV,
        [QPHY_TX_TX_DRV_LVL]            = QSERDES_V6_TX_TX_DRV_LVL,
@@ -2150,9 +2155,9 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
        writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
 
        if (reverse)
-               writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
+               writel(0x4c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
        else
-               writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
+               writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
 
        return reverse;
 }
@@ -2162,6 +2167,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
        const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
        u32 phy_vco_div;
        unsigned long pixel_freq;
+       const struct qmp_phy_cfg *cfg = qmp->cfg;
 
        switch (dp_opts->link_rate) {
        case 1620:
@@ -2184,7 +2190,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
                /* Other link rates aren't supported */
                return -EINVAL;
        }
-       writel(phy_vco_div, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_VCO_DIV);
+       writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]);
 
        clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000);
        clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq);
index f5cfacf9be964ea9068eace03dcd1d9b58e187a2..181057421c113f90c929fa64a12ff85d35c550c9 100644 (file)
@@ -7,6 +7,7 @@
 #define QCOM_PHY_QMP_DP_PHY_V5_H_
 
 /* Only for QMP V5 PHY - DP PHY registers */
+#define QSERDES_V5_DP_PHY_VCO_DIV                      0x070
 #define QSERDES_V5_DP_PHY_AUX_INTERRUPT_STATUS         0x0d8
 #define QSERDES_V5_DP_PHY_STATUS                       0x0dc
 
index 01a20d3be4b812c33fc0869a79601cdc6e89d606..fa967a1af058f7d5c568adf5173f04c6c12127aa 100644 (file)
@@ -7,6 +7,7 @@
 #define QCOM_PHY_QMP_DP_PHY_V6_H_
 
 /* Only for QMP V6 PHY - DP PHY registers */
+#define QSERDES_V6_DP_PHY_VCO_DIV                      0x070
 #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS         0x0e0
 #define QSERDES_V6_DP_PHY_STATUS                       0x0e4
 
index a34f67bb7e61ad7b23cfc2d510054bb4348b8a36..b60a4b60451e5c1cda026c1565e87e5c5c7f86fe 100644 (file)
@@ -87,6 +87,7 @@ config PHY_ROCKCHIP_SAMSUNG_HDPTX
        tristate "Rockchip Samsung HDMI/eDP Combo PHY driver"
        depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
        select GENERIC_PHY
+       select RATIONAL
        help
          Enable this to support the Rockchip HDMI/eDP Combo PHY
          with Samsung IP block.
index 76b9cf417591de0b7d9f5887dc78b075bd71e6bf..bf74e429ff46e71dccb7da3b6640014e2ba67159 100644 (file)
@@ -125,12 +125,15 @@ struct rockchip_combphy_grfcfg {
 };
 
 struct rockchip_combphy_cfg {
+       unsigned int num_phys;
+       unsigned int phy_ids[3];
        const struct rockchip_combphy_grfcfg *grfcfg;
        int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
 };
 
 struct rockchip_combphy_priv {
        u8 type;
+       int id;
        void __iomem *mmio;
        int num_clks;
        struct clk_bulk_data *clks;
@@ -320,7 +323,7 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
        struct rockchip_combphy_priv *priv;
        const struct rockchip_combphy_cfg *phy_cfg;
        struct resource *res;
-       int ret;
+       int ret, id;
 
        phy_cfg = of_device_get_match_data(dev);
        if (!phy_cfg) {
@@ -338,6 +341,15 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
                return ret;
        }
 
+       /* find the phy-id from the io address */
+       priv->id = -ENODEV;
+       for (id = 0; id < phy_cfg->num_phys; id++) {
+               if (res->start == phy_cfg->phy_ids[id]) {
+                       priv->id = id;
+                       break;
+               }
+       }
+
        priv->dev = dev;
        priv->type = PHY_NONE;
        priv->cfg = phy_cfg;
@@ -562,6 +574,12 @@ static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
 };
 
 static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
+       .num_phys = 3,
+       .phy_ids = {
+               0xfe820000,
+               0xfe830000,
+               0xfe840000,
+       },
        .grfcfg         = &rk3568_combphy_grfcfgs,
        .combphy_cfg    = rk3568_combphy_cfg,
 };
@@ -578,8 +596,14 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
                rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
                rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
                rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
-               rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
-               rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
+               switch (priv->id) {
+               case 1:
+                       rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
+                       break;
+               case 2:
+                       rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
+                       break;
+               }
                break;
        case PHY_TYPE_USB3:
                /* Set SSC downward spread spectrum */
@@ -736,6 +760,12 @@ static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
 };
 
 static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
+       .num_phys = 3,
+       .phy_ids = {
+               0xfee00000,
+               0xfee10000,
+               0xfee20000,
+       },
        .grfcfg         = &rk3588_combphy_grfcfgs,
        .combphy_cfg    = rk3588_combphy_cfg,
 };
index 121e5961ce11472ff1576dc83686072eb2f115e0..9857ee45b89e0de1e26d92ee5a8f748edc34010f 100644 (file)
@@ -40,6 +40,8 @@
 #define RK3588_BIFURCATION_LANE_0_1            BIT(0)
 #define RK3588_BIFURCATION_LANE_2_3            BIT(1)
 #define RK3588_LANE_AGGREGATION                BIT(2)
+#define RK3588_PCIE1LN_SEL_EN                  (GENMASK(1, 0) << 16)
+#define RK3588_PCIE30_PHY_MODE_EN              (GENMASK(2, 0) << 16)
 
 struct rockchip_p3phy_ops;
 
@@ -132,7 +134,7 @@ static const struct rockchip_p3phy_ops rk3568_ops = {
 static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
 {
        u32 reg = 0;
-       u8 mode = 0;
+       u8 mode = RK3588_LANE_AGGREGATION; /* default */
        int ret;
 
        /* Deassert PCIe PMA output clamp mode */
@@ -140,31 +142,24 @@ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
 
        /* Set bifurcation if needed */
        for (int i = 0; i < priv->num_lanes; i++) {
-               if (!priv->lanes[i])
-                       mode |= (BIT(i) << 3);
-
                if (priv->lanes[i] > 1)
-                       mode |= (BIT(i) >> 1);
-       }
-
-       if (!mode)
-               reg = RK3588_LANE_AGGREGATION;
-       else {
-               if (mode & (BIT(0) | BIT(1)))
-                       reg |= RK3588_BIFURCATION_LANE_0_1;
-
-               if (mode & (BIT(2) | BIT(3)))
-                       reg |= RK3588_BIFURCATION_LANE_2_3;
+                       mode &= ~RK3588_LANE_AGGREGATION;
+               if (priv->lanes[i] == 3)
+                       mode |= RK3588_BIFURCATION_LANE_0_1;
+               if (priv->lanes[i] == 4)
+                       mode |= RK3588_BIFURCATION_LANE_2_3;
        }
 
-       regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
+       reg = mode;
+       regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+                    RK3588_PCIE30_PHY_MODE_EN | reg);
 
        /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
        if (!IS_ERR(priv->pipe_grf)) {
-               reg = (mode & (BIT(6) | BIT(7))) >> 6;
+               reg = mode & (RK3588_BIFURCATION_LANE_0_1 | RK3588_BIFURCATION_LANE_2_3);
                if (reg)
                        regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
-                                    (reg << 16) | reg);
+                                    RK3588_PCIE1LN_SEL_EN | reg);
        }
 
        reset_control_deassert(priv->p30phy);
index 13cd614e12a1d3c8ad98de07a40f63091409d228..751fecd466e3e3b5d8bd1faf3071812dd3df3cf2 100644 (file)
@@ -69,7 +69,6 @@ struct tusb1210 {
        struct delayed_work chg_det_work;
        struct notifier_block psy_nb;
        struct power_supply *psy;
-       struct power_supply *charger;
 #endif
 };
 
@@ -236,19 +235,24 @@ static const char * const tusb1210_chargers[] = {
 
 static bool tusb1210_get_online(struct tusb1210 *tusb)
 {
+       struct power_supply *charger = NULL;
        union power_supply_propval val;
-       int i;
+       bool online = false;
+       int i, ret;
 
-       for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !tusb->charger; i++)
-               tusb->charger = power_supply_get_by_name(tusb1210_chargers[i]);
+       for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !charger; i++)
+               charger = power_supply_get_by_name(tusb1210_chargers[i]);
 
-       if (!tusb->charger)
+       if (!charger)
                return false;
 
-       if (power_supply_get_property(tusb->charger, POWER_SUPPLY_PROP_ONLINE, &val))
-               return false;
+       ret = power_supply_get_property(charger, POWER_SUPPLY_PROP_ONLINE, &val);
+       if (ret == 0)
+               online = val.intval;
+
+       power_supply_put(charger);
 
-       return val.intval;
+       return online;
 }
 
 static void tusb1210_chg_det_work(struct work_struct *work)
@@ -473,9 +477,6 @@ static void tusb1210_remove_charger_detect(struct tusb1210 *tusb)
                cancel_delayed_work_sync(&tusb->chg_det_work);
                power_supply_unregister(tusb->psy);
        }
-
-       if (tusb->charger)
-               power_supply_put(tusb->charger);
 }
 #else
 static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) { }
index d376fa7114d1a024d63eba168a6809f0816acfba..029efe16f8cc29d04942ef4f420c37a25dc2f4b3 100644 (file)
@@ -43,7 +43,7 @@
 #define SCU614         0x614 /* Disable GPIO Internal Pull-Down #1 */
 #define SCU618         0x618 /* Disable GPIO Internal Pull-Down #2 */
 #define SCU61C         0x61c /* Disable GPIO Internal Pull-Down #3 */
-#define SCU620         0x620 /* Disable GPIO Internal Pull-Down #4 */
+#define SCU630         0x630 /* Disable GPIO Internal Pull-Down #4 */
 #define SCU634         0x634 /* Disable GPIO Internal Pull-Down #5 */
 #define SCU638         0x638 /* Disable GPIO Internal Pull-Down #6 */
 #define SCU690         0x690 /* Multi-function Pin Control #24 */
@@ -2495,38 +2495,38 @@ static struct aspeed_pin_config aspeed_g6_configs[] = {
        ASPEED_PULL_DOWN_PINCONF(D14, SCU61C, 0),
 
        /* GPIOS7 */
-       ASPEED_PULL_DOWN_PINCONF(T24, SCU620, 23),
+       ASPEED_PULL_DOWN_PINCONF(T24, SCU630, 23),
        /* GPIOS6 */
-       ASPEED_PULL_DOWN_PINCONF(P23, SCU620, 22),
+       ASPEED_PULL_DOWN_PINCONF(P23, SCU630, 22),
        /* GPIOS5 */
-       ASPEED_PULL_DOWN_PINCONF(P24, SCU620, 21),
+       ASPEED_PULL_DOWN_PINCONF(P24, SCU630, 21),
        /* GPIOS4 */
-       ASPEED_PULL_DOWN_PINCONF(R26, SCU620, 20),
+       ASPEED_PULL_DOWN_PINCONF(R26, SCU630, 20),
        /* GPIOS3*/
-       ASPEED_PULL_DOWN_PINCONF(R24, SCU620, 19),
+       ASPEED_PULL_DOWN_PINCONF(R24, SCU630, 19),
        /* GPIOS2 */
-       ASPEED_PULL_DOWN_PINCONF(T26, SCU620, 18),
+       ASPEED_PULL_DOWN_PINCONF(T26, SCU630, 18),
        /* GPIOS1 */
-       ASPEED_PULL_DOWN_PINCONF(T25, SCU620, 17),
+       ASPEED_PULL_DOWN_PINCONF(T25, SCU630, 17),
        /* GPIOS0 */
-       ASPEED_PULL_DOWN_PINCONF(R23, SCU620, 16),
+       ASPEED_PULL_DOWN_PINCONF(R23, SCU630, 16),
 
        /* GPIOR7 */
-       ASPEED_PULL_DOWN_PINCONF(U26, SCU620, 15),
+       ASPEED_PULL_DOWN_PINCONF(U26, SCU630, 15),
        /* GPIOR6 */
-       ASPEED_PULL_DOWN_PINCONF(W26, SCU620, 14),
+       ASPEED_PULL_DOWN_PINCONF(W26, SCU630, 14),
        /* GPIOR5 */
-       ASPEED_PULL_DOWN_PINCONF(T23, SCU620, 13),
+       ASPEED_PULL_DOWN_PINCONF(T23, SCU630, 13),
        /* GPIOR4 */
-       ASPEED_PULL_DOWN_PINCONF(U25, SCU620, 12),
+       ASPEED_PULL_DOWN_PINCONF(U25, SCU630, 12),
        /* GPIOR3*/
-       ASPEED_PULL_DOWN_PINCONF(V26, SCU620, 11),
+       ASPEED_PULL_DOWN_PINCONF(V26, SCU630, 11),
        /* GPIOR2 */
-       ASPEED_PULL_DOWN_PINCONF(V24, SCU620, 10),
+       ASPEED_PULL_DOWN_PINCONF(V24, SCU630, 10),
        /* GPIOR1 */
-       ASPEED_PULL_DOWN_PINCONF(U24, SCU620, 9),
+       ASPEED_PULL_DOWN_PINCONF(U24, SCU630, 9),
        /* GPIOR0 */
-       ASPEED_PULL_DOWN_PINCONF(V25, SCU620, 8),
+       ASPEED_PULL_DOWN_PINCONF(V25, SCU630, 8),
 
        /* GPIOX7 */
        ASPEED_PULL_DOWN_PINCONF(AB10, SCU634, 31),
index 6649357637ff337dc49c4e522287d2366dc36516..cffeb869130ddab486fb2ce00e4c1d5a27575875 100644 (file)
@@ -2124,13 +2124,7 @@ int pinctrl_enable(struct pinctrl_dev *pctldev)
 
        error = pinctrl_claim_hogs(pctldev);
        if (error) {
-               dev_err(pctldev->dev, "could not claim hogs: %i\n",
-                       error);
-               pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
-                                     pctldev->desc->npins);
-               mutex_destroy(&pctldev->mutex);
-               kfree(pctldev);
-
+               dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
                return error;
        }
 
index df1efc2e5202591d5f9f23d95f6008853b91e046..6a94ecd6a8deaeb6b7fc14c6387987f52ead306a 100644 (file)
@@ -220,14 +220,16 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
        for (state = 0; ; state++) {
                /* Retrieve the pinctrl-* property */
                propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
-               if (!propname)
-                       return -ENOMEM;
+               if (!propname) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
                prop = of_find_property(np, propname, &size);
                kfree(propname);
                if (!prop) {
                        if (state == 0) {
-                               of_node_put(np);
-                               return -ENODEV;
+                               ret = -ENODEV;
+                               goto err;
                        }
                        break;
                }
index ac97724c59bae9705e89c93246ec3f09580d663d..4e87f5b875c0e8f7089b9411c9b1610eaa2a8b9a 100644 (file)
@@ -231,6 +231,7 @@ static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
 /* SCORE groups */
 static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
 static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
+static const unsigned int byt_score_uart3_pins[] = { 57, 61 };
 
 static const unsigned int byt_score_pwm0_pins[] = { 94 };
 static const unsigned int byt_score_pwm1_pins[] = { 95 };
@@ -278,37 +279,38 @@ static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
 static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
 
 static const struct intel_pingroup byt_score_groups[] = {
-       PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
-       PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
-       PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
-       PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
-       PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
-       PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
-       PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
-       PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
-       PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
-       PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
-       PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
-       PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
-       PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
-       PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
-       PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
-       PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
-       PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
-       PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
-       PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
-       PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
-       PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
-       PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
-       PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
-       PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
-       PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
-       PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
-       PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
+       PIN_GROUP_GPIO("uart1_grp", byt_score_uart1_pins, 1),
+       PIN_GROUP_GPIO("uart2_grp", byt_score_uart2_pins, 1),
+       PIN_GROUP_GPIO("uart3_grp", byt_score_uart3_pins, 1),
+       PIN_GROUP_GPIO("pwm0_grp", byt_score_pwm0_pins, 1),
+       PIN_GROUP_GPIO("pwm1_grp", byt_score_pwm1_pins, 1),
+       PIN_GROUP_GPIO("ssp2_grp", byt_score_ssp2_pins, 1),
+       PIN_GROUP_GPIO("sio_spi_grp", byt_score_sio_spi_pins, 1),
+       PIN_GROUP_GPIO("i2c5_grp", byt_score_i2c5_pins, 1),
+       PIN_GROUP_GPIO("i2c6_grp", byt_score_i2c6_pins, 1),
+       PIN_GROUP_GPIO("i2c4_grp", byt_score_i2c4_pins, 1),
+       PIN_GROUP_GPIO("i2c3_grp", byt_score_i2c3_pins, 1),
+       PIN_GROUP_GPIO("i2c2_grp", byt_score_i2c2_pins, 1),
+       PIN_GROUP_GPIO("i2c1_grp", byt_score_i2c1_pins, 1),
+       PIN_GROUP_GPIO("i2c0_grp", byt_score_i2c0_pins, 1),
+       PIN_GROUP_GPIO("ssp0_grp", byt_score_ssp0_pins, 1),
+       PIN_GROUP_GPIO("ssp1_grp", byt_score_ssp1_pins, 1),
+       PIN_GROUP_GPIO("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
+       PIN_GROUP_GPIO("sdio_grp", byt_score_sdio_pins, 1),
+       PIN_GROUP_GPIO("emmc_grp", byt_score_emmc_pins, 1),
+       PIN_GROUP_GPIO("lpc_grp", byt_score_ilb_lpc_pins, 1),
+       PIN_GROUP_GPIO("sata_grp", byt_score_sata_pins, 1),
+       PIN_GROUP_GPIO("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
+       PIN_GROUP_GPIO("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
+       PIN_GROUP_GPIO("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
+       PIN_GROUP_GPIO("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
+       PIN_GROUP_GPIO("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
+       PIN_GROUP_GPIO("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
+       PIN_GROUP_GPIO("smbus_grp", byt_score_smbus_pins, 1),
 };
 
 static const char * const byt_score_uart_groups[] = {
-       "uart1_grp", "uart2_grp",
+       "uart1_grp", "uart2_grp", "uart3_grp",
 };
 static const char * const byt_score_pwm_groups[] = {
        "pwm0_grp", "pwm1_grp",
@@ -332,12 +334,14 @@ static const char * const byt_score_plt_clk_groups[] = {
 };
 static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
 static const char * const byt_score_gpio_groups[] = {
-       "uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
-       "ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
-       "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
-       "sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
-       "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
-       "plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
+       "uart1_grp_gpio", "uart2_grp_gpio", "uart3_grp_gpio", "pwm0_grp_gpio",
+       "pwm1_grp_gpio", "ssp0_grp_gpio", "ssp1_grp_gpio", "ssp2_grp_gpio",
+       "sio_spi_grp_gpio", "i2c0_grp_gpio", "i2c1_grp_gpio", "i2c2_grp_gpio",
+       "i2c3_grp_gpio", "i2c4_grp_gpio", "i2c5_grp_gpio", "i2c6_grp_gpio",
+       "sdcard_grp_gpio", "sdio_grp_gpio", "emmc_grp_gpio", "lpc_grp_gpio",
+       "sata_grp_gpio", "plt_clk0_grp_gpio", "plt_clk1_grp_gpio",
+       "plt_clk2_grp_gpio", "plt_clk3_grp_gpio", "plt_clk4_grp_gpio",
+       "plt_clk5_grp_gpio", "smbus_grp_gpio",
 };
 
 static const struct intel_function byt_score_functions[] = {
@@ -456,8 +460,8 @@ static const struct intel_pingroup byt_sus_groups[] = {
        PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
        PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
        PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
-       PIN_GROUP("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
-       PIN_GROUP("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
+       PIN_GROUP_GPIO("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
+       PIN_GROUP_GPIO("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
 };
 
 static const char * const byt_sus_usb_groups[] = {
@@ -469,7 +473,7 @@ static const char * const byt_sus_pmu_clk_groups[] = {
 };
 static const char * const byt_sus_gpio_groups[] = {
        "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
-       "pmu_clk1_grp", "pmu_clk2_grp",
+       "pmu_clk1_grp_gpio", "pmu_clk2_grp_gpio",
 };
 
 static const struct intel_function byt_sus_functions[] = {
index fde65e18cd145ecb1eb809f87ecec289067e44e8..6981e2fab93f34998b737ac39446c4eed5646923 100644 (file)
@@ -179,6 +179,10 @@ struct intel_community {
                .modes = __builtin_choose_expr(__builtin_constant_p((m)), NULL, (m)),   \
        }
 
+#define PIN_GROUP_GPIO(n, p, m)                                                \
+        PIN_GROUP(n, p, m),                                            \
+        PIN_GROUP(n "_gpio", p, 0)
+
 #define FUNCTION(n, g)                                                 \
        {                                                               \
                .func = PINCTRL_PINFUNCTION((n), (g), ARRAY_SIZE(g)),   \
index b6bc31abd2b068695dcfd5025c0f31ea0b3c679e..b19bc391705ee079939f34ab03d554160d97c234 100644 (file)
@@ -165,20 +165,21 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
                break;
        case PIN_CONFIG_INPUT_ENABLE:
-       case PIN_CONFIG_OUTPUT_ENABLE:
+               err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_IES, &ret);
+               if (!ret)
+                       err = -EINVAL;
+               break;
+       case PIN_CONFIG_OUTPUT:
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
                if (err)
                        break;
-               /*     CONFIG     Current direction return value
-                * -------------  ----------------- ----------------------
-                * OUTPUT_ENABLE       output       1 (= HW value)
-                *                     input        0 (= HW value)
-                * INPUT_ENABLE        output       0 (= reverse HW value)
-                *                     input        1 (= reverse HW value)
-                */
-               if (param == PIN_CONFIG_INPUT_ENABLE)
-                       ret = !ret;
 
+               if (!ret) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DO, &ret);
                break;
        case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
@@ -193,6 +194,8 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
                }
 
                err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
+               if (!ret)
+                       err = -EINVAL;
                break;
        case PIN_CONFIG_DRIVE_STRENGTH:
                if (!hw->soc->drive_get)
@@ -281,26 +284,9 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
                        break;
                err = hw->soc->bias_set_combo(hw, desc, 0, arg);
                break;
-       case PIN_CONFIG_OUTPUT_ENABLE:
-               err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
-                                      MTK_DISABLE);
-               /* Keep set direction to consider the case that a GPIO pin
-                *  does not have SMT control
-                */
-               if (err != -ENOTSUPP)
-                       break;
-
-               err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-                                      MTK_OUTPUT);
-               break;
        case PIN_CONFIG_INPUT_ENABLE:
                /* regard all non-zero value as enable */
                err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
-               if (err)
-                       break;
-
-               err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-                                      MTK_INPUT);
                break;
        case PIN_CONFIG_SLEW_RATE:
                /* regard all non-zero value as enable */
index 79f5d753d7e1a53df0da9bb0446bf8fdfbd3042c..50a87d9618a8e8e078424db33c7e13a7c7ed1dc6 100644 (file)
@@ -250,7 +250,7 @@ static const unsigned int pdm_dclk_x_pins[]         = { GPIOX_10 };
 static const unsigned int pdm_din2_a_pins[]            = { GPIOA_6 };
 static const unsigned int pdm_din1_a_pins[]            = { GPIOA_7 };
 static const unsigned int pdm_din0_a_pins[]            = { GPIOA_8 };
-static const unsigned int pdm_dclk_pins[]              = { GPIOA_9 };
+static const unsigned int pdm_dclk_a_pins[]            = { GPIOA_9 };
 
 /* gen_clk */
 static const unsigned int gen_clk_x_pins[]             = { GPIOX_7 };
@@ -591,7 +591,7 @@ static struct meson_pmx_group meson_a1_periphs_groups[] = {
        GROUP(pdm_din2_a,               3),
        GROUP(pdm_din1_a,               3),
        GROUP(pdm_din0_a,               3),
-       GROUP(pdm_dclk,                 3),
+       GROUP(pdm_dclk_a,               3),
        GROUP(pwm_c_a,                  3),
        GROUP(pwm_b_a,                  3),
 
@@ -755,7 +755,7 @@ static const char * const spi_a_groups[] = {
 
 static const char * const pdm_groups[] = {
        "pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
-       "pdm_din1_a", "pdm_din0_a", "pdm_dclk",
+       "pdm_din1_a", "pdm_din0_a", "pdm_dclk_a",
 };
 
 static const char * const gen_clk_groups[] = {
index eb5a8c65426061fec78bced9cf66243debbb561f..20425afc6b331b336c314d5a3f4c6dc9b813382d 100644 (file)
@@ -2045,7 +2045,9 @@ static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl)
 
        for (unsigned int i = 0; i < RZG2L_TINT_MAX_INTERRUPT; i++) {
                struct irq_data *data;
+               unsigned long flags;
                unsigned int virq;
+               int ret;
 
                if (!pctrl->hwirq[i])
                        continue;
@@ -2063,8 +2065,18 @@ static void rzg2l_gpio_irq_restore(struct rzg2l_pinctrl *pctrl)
                        continue;
                }
 
-               if (!irqd_irq_disabled(data))
+               /*
+                * This has to be atomically executed to protect against a concurrent
+                * interrupt.
+                */
+               raw_spin_lock_irqsave(&pctrl->lock.rlock, flags);
+               ret = rzg2l_gpio_irq_set_type(data, irqd_get_trigger_type(data));
+               if (!ret && !irqd_irq_disabled(data))
                        rzg2l_gpio_irq_enable(data);
+               raw_spin_unlock_irqrestore(&pctrl->lock.rlock, flags);
+
+               if (ret)
+                       dev_crit(pctrl->dev, "Failed to set IRQ type for virq=%u\n", virq);
        }
 }
 
index 30951f7131cd98bfdaffb70b2aa30ee3ceb7dbdd..1accdaaf282c5331495e51a6bd71a9203a7c0200 100644 (file)
@@ -721,6 +721,7 @@ static struct miscdevice isst_if_char_driver = {
 static const struct x86_cpu_id hpm_cpu_ids[] = {
        X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D,     NULL),
        X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X,     NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT,      NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X,    NULL),
        {}
 };
index 1305cba61edd4b957313d7d86fb05158975b3086..aca123783efccdcb73391214d20c3722975222ca 100644 (file)
@@ -588,7 +588,7 @@ static const struct regulator_ops mt6360_chg_otg_ops = {
 };
 
 static const struct regulator_desc mt6360_otg_rdesc = {
-       .of_match = "usb-otg-vbus",
+       .of_match = "usb-otg-vbus-regulator",
        .name = "usb-otg-vbus",
        .ops = &mt6360_chg_otg_ops,
        .owner = THIS_MODULE,
index c345a77f9f78c0a4a03f5a13a7151901b9945a03..e4dbacd50a437df3562b04d485ec38e11a89b216 100644 (file)
@@ -192,6 +192,7 @@ static const int rt9455_voreg_values[] = {
        4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000
 };
 
+#if IS_ENABLED(CONFIG_USB_PHY)
 /*
  * When the charger is in boost mode, REG02[7:2] represent boost output
  * voltage.
@@ -207,6 +208,7 @@ static const int rt9455_boost_voltage_values[] = {
        5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
        5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
 };
+#endif
 
 /* REG07[3:0] (VMREG) in uV */
 static const int rt9455_vmreg_values[] = {
index fe7ae0f3f46af985a87f4a0b5c33c3fd09f6b1a8..5ab1a0befe12f791389911651d8548fb3611b6f8 100644 (file)
@@ -352,6 +352,9 @@ void *regulator_irq_helper(struct device *dev,
 
        h->irq = irq;
        h->desc = *d;
+       h->desc.name = devm_kstrdup(dev, d->name, GFP_KERNEL);
+       if (!h->desc.name)
+               return ERR_PTR(-ENOMEM);
 
        ret = init_rdev_state(dev, h, rdev, common_errs, per_rdev_errs,
                              rdev_amount);
index ad6587a378d09cc52515475f96512ed5627880be..24cc9fc94e900a43a8bfa8c30c364cedb2b0b948 100644 (file)
@@ -319,15 +319,15 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
        }
 }
 
-#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg,        vmask,  \
-                             mreg, mmask, streg, stmask, vranges,      \
-                             vcnts, offon_delay, irq_tbls)             \
+#define MT6360_REGULATOR_DESC(match, _name, _sname, ereg, emask, vreg, \
+                             vmask, mreg, mmask, streg, stmask,        \
+                             vranges, vcnts, offon_delay, irq_tbls)    \
 {                                                                      \
        .desc = {                                                       \
                .name = #_name,                                         \
                .supply_name = #_sname,                                 \
                .id =  MT6360_REGULATOR_##_name,                        \
-               .of_match = of_match_ptr(#_name),                       \
+               .of_match = of_match_ptr(match),                        \
                .regulators_node = of_match_ptr("regulator"),           \
                .of_map_mode = mt6360_regulator_of_map_mode,            \
                .owner = THIS_MODULE,                                   \
@@ -351,21 +351,29 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
 }
 
 static const struct mt6360_regulator_desc mt6360_regulator_descs[] =  {
-       MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
+       MT6360_REGULATOR_DESC("buck1", BUCK1, BUCK1_VIN,
+                             0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
                              buck_vout_ranges, 256, 0, buck1_irq_tbls),
-       MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
+       MT6360_REGULATOR_DESC("buck2", BUCK2, BUCK2_VIN,
+                             0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
                              buck_vout_ranges, 256, 0, buck2_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
+       MT6360_REGULATOR_DESC("ldo6", LDO6, LDO_VIN3,
+                             0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
                              ldo_vout_ranges1, 256, 0, ldo6_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
+       MT6360_REGULATOR_DESC("ldo7", LDO7, LDO_VIN3,
+                             0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
                              ldo_vout_ranges1, 256, 0, ldo7_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
+       MT6360_REGULATOR_DESC("ldo1", LDO1, LDO_VIN1,
+                             0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
                              ldo_vout_ranges2, 256, 0, ldo1_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
+       MT6360_REGULATOR_DESC("ldo2", LDO2, LDO_VIN1,
+                             0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
                              ldo_vout_ranges2, 256, 0, ldo2_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
+       MT6360_REGULATOR_DESC("ldo3", LDO3, LDO_VIN1,
+                             0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
                              ldo_vout_ranges2, 256, 100, ldo3_irq_tbls),
-       MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
+       MT6360_REGULATOR_DESC("ldo5", LDO5, LDO_VIN2,
+                             0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
                              ldo_vout_ranges3, 128, 100, ldo5_irq_tbls),
 };
 
index 656fe330d38f0adbc953b8d42861088a6eaa757b..063e12c08e75f70c002e6f3e859a8bba5e8ef344 100644 (file)
@@ -140,6 +140,7 @@ static const struct of_device_id qcom_refgen_match_table[] = {
        { .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_refgen_desc },
        { }
 };
+MODULE_DEVICE_TABLE(of, qcom_refgen_match_table);
 
 static struct platform_driver qcom_refgen_driver = {
        .probe = qcom_refgen_probe,
index 086da36abc0b4917a26fc78745dfdb8a48b5cfd5..4955616517ce9caa22f652e9370e7d517098b378 100644 (file)
@@ -84,6 +84,7 @@ static const struct of_device_id regulator_ipq4019_of_match[] = {
        { .compatible = "qcom,vqmmc-ipq4019-regulator", },
        {},
 };
+MODULE_DEVICE_TABLE(of, regulator_ipq4019_of_match);
 
 static struct platform_driver ipq4019_regulator_driver = {
        .probe = ipq4019_regulator_probe,
index 37173cb0f5f5a222b936029b8ff8e7997c401d4d..c57694be9bd32ef8cb9dc8ad794379ef2da44640 100644 (file)
@@ -162,7 +162,8 @@ struct raw3270_request *raw3270_request_alloc(size_t size)
        /*
         * Setup ccw.
         */
-       rq->ccw.cda = virt_to_dma32(rq->buffer);
+       if (rq->buffer)
+               rq->ccw.cda = virt_to_dma32(rq->buffer);
        rq->ccw.flags = CCW_FLAG_SLI;
 
        return rq;
@@ -188,7 +189,8 @@ int raw3270_request_reset(struct raw3270_request *rq)
                return -EBUSY;
        rq->ccw.cmd_code = 0;
        rq->ccw.count = 0;
-       rq->ccw.cda = virt_to_dma32(rq->buffer);
+       if (rq->buffer)
+               rq->ccw.cda = virt_to_dma32(rq->buffer);
        rq->ccw.flags = CCW_FLAG_SLI;
        rq->rescnt = 0;
        rq->rc = 0;
index 8613fa937237bde02368523577a485b62b07c5dc..a2e771ebae8ebd55e1cb841f76b44a69ebb2bea7 100644 (file)
@@ -95,7 +95,7 @@ static ssize_t crw_inject_write(struct file *file, const char __user *buf,
                return -EINVAL;
        }
 
-       buffer = vmemdup_user(buf, lbuf);
+       buffer = memdup_user_nul(buf, lbuf);
        if (IS_ERR(buffer))
                return -ENOMEM;
 
index 0a3a678ffc7eedb237f3bc72e21ffe4c076c1444..6087547328ce91271eeab7a13c02059299c0c39a 100644 (file)
@@ -658,7 +658,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
                               (int)prepcblk->ccp_rtcode,
                               (int)prepcblk->ccp_rscode);
                if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
-                       rc = -EAGAIN;
+                       rc = -EBUSY;
                else
                        rc = -EIO;
                goto out;
@@ -1263,7 +1263,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
                               (int)prepcblk->ccp_rtcode,
                               (int)prepcblk->ccp_rscode);
                if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
-                       rc = -EAGAIN;
+                       rc = -EBUSY;
                else
                        rc = -EIO;
                goto out;
@@ -1426,7 +1426,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
                               (int)prepcblk->ccp_rtcode,
                               (int)prepcblk->ccp_rscode);
                if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
-                       rc = -EAGAIN;
+                       rc = -EBUSY;
                else
                        rc = -EIO;
                goto out;
index eb7f5489ccf95962034a2a135dbc30fa83599973..9bcf8fc69ebe428bff07458406f70be0407d0b39 100644 (file)
@@ -556,13 +556,29 @@ static int check_reply_pl(const u8 *pl, const char *func)
        pl += 2;
        ret = *((u32 *)pl);
        if (ret != 0) {
-               ZCRYPT_DBF_ERR("%s return value 0x%04x != 0\n", func, ret);
+               ZCRYPT_DBF_ERR("%s return value 0x%08x != 0\n", func, ret);
                return -EIO;
        }
 
        return 0;
 }
 
+/* Check ep11 reply cprb, return 0 or suggested errno value. */
+static int check_reply_cprb(const struct ep11_cprb *rep, const char *func)
+{
+       /* check ep11 reply return code field */
+       if (rep->ret_code) {
+               ZCRYPT_DBF_ERR("%s ep11 reply ret_code=0x%08x\n", __func__,
+                              rep->ret_code);
+               if (rep->ret_code == 0x000c0003)
+                       return -EBUSY;
+               else
+                       return -EIO;
+       }
+
+       return 0;
+}
+
 /*
  * Helper function which does an ep11 query with given query type.
  */
@@ -627,6 +643,12 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -877,6 +899,12 @@ static int _ep11_genaeskey(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -1028,6 +1056,12 @@ static int ep11_cryptsingle(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -1185,6 +1219,12 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
@@ -1339,6 +1379,12 @@ static int _ep11_wrapkey(u16 card, u16 domain,
                goto out;
        }
 
+       /* check ep11 reply cprb */
+       rc = check_reply_cprb(rep, __func__);
+       if (rc)
+               goto out;
+
+       /* check payload */
        rc = check_reply_pl((u8 *)rep_pl, __func__);
        if (rc)
                goto out;
index f0b8b709649f29691c3d0976b8a1156da1f6bd81..a3adaec5504e45384eeedf8f82ee160317fcbbf5 100644 (file)
@@ -364,30 +364,33 @@ out:
        return rc;
 }
 
+static void qeth_free_cq(struct qeth_card *card)
+{
+       if (card->qdio.c_q) {
+               qeth_free_qdio_queue(card->qdio.c_q);
+               card->qdio.c_q = NULL;
+       }
+}
+
 static int qeth_alloc_cq(struct qeth_card *card)
 {
        if (card->options.cq == QETH_CQ_ENABLED) {
                QETH_CARD_TEXT(card, 2, "cqon");
-               card->qdio.c_q = qeth_alloc_qdio_queue();
                if (!card->qdio.c_q) {
-                       dev_err(&card->gdev->dev, "Failed to create completion queue\n");
-                       return -ENOMEM;
+                       card->qdio.c_q = qeth_alloc_qdio_queue();
+                       if (!card->qdio.c_q) {
+                               dev_err(&card->gdev->dev,
+                                       "Failed to create completion queue\n");
+                               return -ENOMEM;
+                       }
                }
        } else {
                QETH_CARD_TEXT(card, 2, "nocq");
-               card->qdio.c_q = NULL;
+               qeth_free_cq(card);
        }
        return 0;
 }
 
-static void qeth_free_cq(struct qeth_card *card)
-{
-       if (card->qdio.c_q) {
-               qeth_free_qdio_queue(card->qdio.c_q);
-               card->qdio.c_q = NULL;
-       }
-}
-
 static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
                                                        int delayed)
 {
@@ -2628,6 +2631,10 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
 
        QETH_CARD_TEXT(card, 2, "allcqdbf");
 
+       /* completion */
+       if (qeth_alloc_cq(card))
+               goto out_err;
+
        if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
                QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
                return 0;
@@ -2663,10 +2670,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
                queue->priority = QETH_QIB_PQUE_PRIO_DEFAULT;
        }
 
-       /* completion */
-       if (qeth_alloc_cq(card))
-               goto out_freeoutq;
-
        return 0;
 
 out_freeoutq:
@@ -2677,6 +2680,8 @@ out_freeoutq:
        qeth_free_buffer_pool(card);
 out_buffer_pool:
        atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
+       qeth_free_cq(card);
+out_err:
        return -ENOMEM;
 }
 
@@ -2684,11 +2689,12 @@ static void qeth_free_qdio_queues(struct qeth_card *card)
 {
        int i, j;
 
+       qeth_free_cq(card);
+
        if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
                QETH_QDIO_UNINITIALIZED)
                return;
 
-       qeth_free_cq(card);
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
                if (card->qdio.in_q->bufs[j].rx_skb) {
                        consume_skb(card->qdio.in_q->bufs[j].rx_skb);
@@ -3742,24 +3748,11 @@ static void qeth_qdio_poll(struct ccw_device *cdev, unsigned long card_ptr)
 
 int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
 {
-       int rc;
-
-       if (card->options.cq ==  QETH_CQ_NOTAVAILABLE) {
-               rc = -1;
-               goto out;
-       } else {
-               if (card->options.cq == cq) {
-                       rc = 0;
-                       goto out;
-               }
-
-               qeth_free_qdio_queues(card);
-               card->options.cq = cq;
-               rc = 0;
-       }
-out:
-       return rc;
+       if (card->options.cq == QETH_CQ_NOTAVAILABLE)
+               return -1;
 
+       card->options.cq = cq;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(qeth_configure_cq);
 
index 58fdf679341dc64ee1768f1d09dc7ce4d549b4bd..65cdc8b77e358546fd1768fe4ec1bb4588c4b692 100644 (file)
@@ -3120,6 +3120,7 @@ static void sd_read_io_hints(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        struct scsi_device *sdp = sdkp->device;
        const struct scsi_io_group_descriptor *desc, *start, *end;
+       u16 permanent_stream_count_old;
        struct scsi_sense_hdr sshdr;
        struct scsi_mode_data data;
        int res;
@@ -3140,12 +3141,13 @@ static void sd_read_io_hints(struct scsi_disk *sdkp, unsigned char *buffer)
        for (desc = start; desc < end; desc++)
                if (!desc->st_enble || !sd_is_perm_stream(sdkp, desc - start))
                        break;
+       permanent_stream_count_old = sdkp->permanent_stream_count;
        sdkp->permanent_stream_count = desc - start;
        if (sdkp->rscs && sdkp->permanent_stream_count < 2)
                sd_printk(KERN_INFO, sdkp,
                          "Unexpected: RSCS has been set and the permanent stream count is %u\n",
                          sdkp->permanent_stream_count);
-       else if (sdkp->permanent_stream_count)
+       else if (sdkp->permanent_stream_count != permanent_stream_count_old)
                sd_printk(KERN_INFO, sdkp, "permanent stream count = %d\n",
                          sdkp->permanent_stream_count);
 }
index efeba8275a6691e20be511e4dcef6ce15e087b61..a09a26bf4988ff200e4f9aa177edd0eb04e9e62f 100644 (file)
@@ -1451,7 +1451,11 @@ static void qcom_slim_ngd_up_worker(struct work_struct *work)
        ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
 
        /* Make sure qmi service is up before continuing */
-       wait_for_completion_interruptible(&ctrl->qmi_up);
+       if (!wait_for_completion_interruptible_timeout(&ctrl->qmi_up,
+                                                      msecs_to_jiffies(MSEC_PER_SEC))) {
+               dev_err(ctrl->dev, "QMI wait timeout\n");
+               return;
+       }
 
        mutex_lock(&ctrl->ssr_lock);
        qcom_slim_ngd_enable(ctrl, true);
index 50c664b65f4d44ada7892098029ee25b7a3af876..1b7afb19ccd637471ad82ad833f589cb0f9405b1 100644 (file)
@@ -72,6 +72,7 @@ config MTK_SOCINFO
        tristate "MediaTek SoC Information"
        default y
        depends on NVMEM_MTK_EFUSE
+       select SOC_BUS
        help
          The MediaTek SoC Information (mtk-socinfo) driver provides
          information about the SoC to the userspace including the
index c832f5c670bcf00bcc6faae0ee0b8802405a9ce0..9a91298c125397c7aa1649d008fbab5c810a4575 100644 (file)
@@ -1768,6 +1768,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
        const struct svs_bank_pdata *bdata;
        struct svs_bank *svsb;
        struct dev_pm_opp *opp;
+       char tz_name_buf[20];
        unsigned long freq;
        int count, ret;
        u32 idx, i;
@@ -1819,10 +1820,12 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
                }
 
                if (!IS_ERR_OR_NULL(bdata->tzone_name)) {
-                       svsb->tzd = thermal_zone_get_zone_by_name(bdata->tzone_name);
+                       snprintf(tz_name_buf, ARRAY_SIZE(tz_name_buf),
+                                "%s-thermal", bdata->tzone_name);
+                       svsb->tzd = thermal_zone_get_zone_by_name(tz_name_buf);
                        if (IS_ERR(svsb->tzd)) {
                                dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
-                                       bdata->tzone_name);
+                                       tz_name_buf);
                                return PTR_ERR(svsb->tzd);
                        }
                }
index 7cd24bd8e2248ef9c0e5fece95b3fb58e94f4e1e..6bcf8e75273c4e03cff5823dd77bc5ac38fd2360 100644 (file)
@@ -130,6 +130,19 @@ static void amd_sdw_set_frameshape(struct amd_sdw_manager *amd_manager)
        writel(frame_size, amd_manager->mmio + ACP_SW_FRAMESIZE);
 }
 
+static void amd_sdw_wake_enable(struct amd_sdw_manager *amd_manager, bool enable)
+{
+       u32 wake_ctrl;
+
+       wake_ctrl = readl(amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
+       if (enable)
+               wake_ctrl |= AMD_SDW_WAKE_INTR_MASK;
+       else
+               wake_ctrl &= ~AMD_SDW_WAKE_INTR_MASK;
+
+       writel(wake_ctrl, amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
+}
+
 static void amd_sdw_ctl_word_prep(u32 *lower_word, u32 *upper_word, struct sdw_msg *msg,
                                  int cmd_offset)
 {
@@ -1095,6 +1108,7 @@ static int __maybe_unused amd_suspend(struct device *dev)
        }
 
        if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
+               amd_sdw_wake_enable(amd_manager, false);
                return amd_sdw_clock_stop(amd_manager);
        } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
                /*
@@ -1121,6 +1135,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev)
                return 0;
        }
        if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
+               amd_sdw_wake_enable(amd_manager, true);
                return amd_sdw_clock_stop(amd_manager);
        } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
                ret = amd_sdw_clock_stop(amd_manager);
index 418b679e0b1a684e0a3ac502d94f74d24d24c00d..707065468e05a038acb1a1c893133b5d757a4de8 100644 (file)
 #define AMD_SDW0_EXT_INTR_MASK         0x200000
 #define AMD_SDW1_EXT_INTR_MASK         4
 #define AMD_SDW_IRQ_MASK_0TO7          0x77777777
-#define AMD_SDW_IRQ_MASK_8TO11         0x000d7777
+#define AMD_SDW_IRQ_MASK_8TO11         0x000c7777
 #define AMD_SDW_IRQ_ERROR_MASK         0xff
 #define AMD_SDW_MAX_FREQ_NUM           1
 #define AMD_SDW0_MAX_TX_PORTS          3
 #define AMD_SDW_CLK_RESUME_REQ                         2
 #define AMD_SDW_CLK_RESUME_DONE                                3
 #define AMD_SDW_WAKE_STAT_MASK                         BIT(16)
+#define AMD_SDW_WAKE_INTR_MASK                         BIT(16)
 
 static u32 amd_sdw_freq_tbl[AMD_SDW_MAX_FREQ_NUM] = {
        AMD_SDW_DEFAULT_CLK_FREQ,
index 7cc219d78551adbcd99e10e4d59f50653276cac1..e358ac5b4509777e0827630e2f6e58c385f9a54c 100644 (file)
@@ -623,7 +623,7 @@ static int spi_engine_probe(struct platform_device *pdev)
 
        version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
        if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
-               dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n",
+               dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n",
                        ADI_AXI_PCORE_VER_MAJOR(version),
                        ADI_AXI_PCORE_VER_MINOR(version),
                        ADI_AXI_PCORE_VER_PATCH(version));
index 35ef5e8e2ffd253ce16ea0594b2cabcf579cff77..77e9738e42f60ec844c74f09dddf5d90e898d87d 100644 (file)
@@ -151,8 +151,6 @@ static const struct debugfs_reg32 hisi_spi_regs[] = {
        HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR),
        HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC),
        HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR),
-       HISI_SPI_DBGFS_REG("DIN", HISI_SPI_DIN),
-       HISI_SPI_DBGFS_REG("DOUT", HISI_SPI_DOUT),
        HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR),
        HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR),
        HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR),
index ff75838c1b5dfa44fccca525c3a8a334051167fb..a2c467d9e92f59c46eea6ec78b3b12a9ae5a6caf 100644 (file)
@@ -4523,6 +4523,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
                wait_for_completion(&done);
                status = message->status;
        }
+       message->complete = NULL;
        message->context = NULL;
 
        return status;
index d78d54ae2605e8ab3050dd7a1e68fb13688a78c5..5693cc8b231aacdcf0a90f363a89e15f7bcd93f8 100644 (file)
@@ -139,11 +139,13 @@ struct tz_episode {
  * we keep track of the current position in the history array.
  *
  * @tz_episodes: a list of thermal mitigation episodes
+ * @tz: thermal zone this object belongs to
  * @trips_crossed: an array of trip points crossed by id
  * @nr_trips: the number of trip points currently being crossed
  */
 struct tz_debugfs {
        struct list_head tz_episodes;
+       struct thermal_zone_device *tz;
        int *trips_crossed;
        int nr_trips;
 };
@@ -503,15 +505,23 @@ void thermal_debug_cdev_add(struct thermal_cooling_device *cdev)
  */
 void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev)
 {
-       struct thermal_debugfs *thermal_dbg = cdev->debugfs;
+       struct thermal_debugfs *thermal_dbg;
 
-       if (!thermal_dbg)
+       mutex_lock(&cdev->lock);
+
+       thermal_dbg = cdev->debugfs;
+       if (!thermal_dbg) {
+               mutex_unlock(&cdev->lock);
                return;
+       }
+
+       cdev->debugfs = NULL;
+
+       mutex_unlock(&cdev->lock);
 
        mutex_lock(&thermal_dbg->lock);
 
        thermal_debugfs_cdev_clear(&thermal_dbg->cdev_dbg);
-       cdev->debugfs = NULL;
 
        mutex_unlock(&thermal_dbg->lock);
 
@@ -716,8 +726,7 @@ out:
 
 static void *tze_seq_start(struct seq_file *s, loff_t *pos)
 {
-       struct thermal_zone_device *tz = s->private;
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg = s->private;
        struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg;
 
        mutex_lock(&thermal_dbg->lock);
@@ -727,8 +736,7 @@ static void *tze_seq_start(struct seq_file *s, loff_t *pos)
 
 static void *tze_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct thermal_zone_device *tz = s->private;
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg = s->private;
        struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg;
 
        return seq_list_next(v, &tz_dbg->tz_episodes, pos);
@@ -736,15 +744,15 @@ static void *tze_seq_next(struct seq_file *s, void *v, loff_t *pos)
 
 static void tze_seq_stop(struct seq_file *s, void *v)
 {
-       struct thermal_zone_device *tz = s->private;
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg = s->private;
 
        mutex_unlock(&thermal_dbg->lock);
 }
 
 static int tze_seq_show(struct seq_file *s, void *v)
 {
-       struct thermal_zone_device *tz = s->private;
+       struct thermal_debugfs *thermal_dbg = s->private;
+       struct thermal_zone_device *tz = thermal_dbg->tz_dbg.tz;
        struct thermal_trip *trip;
        struct tz_episode *tze;
        const char *type;
@@ -810,6 +818,8 @@ void thermal_debug_tz_add(struct thermal_zone_device *tz)
 
        tz_dbg = &thermal_dbg->tz_dbg;
 
+       tz_dbg->tz = tz;
+
        tz_dbg->trips_crossed = kzalloc(sizeof(int) * tz->num_trips, GFP_KERNEL);
        if (!tz_dbg->trips_crossed) {
                thermal_debugfs_remove_id(thermal_dbg);
@@ -818,23 +828,44 @@ void thermal_debug_tz_add(struct thermal_zone_device *tz)
 
        INIT_LIST_HEAD(&tz_dbg->tz_episodes);
 
-       debugfs_create_file("mitigations", 0400, thermal_dbg->d_top, tz, &tze_fops);
+       debugfs_create_file("mitigations", 0400, thermal_dbg->d_top,
+                           thermal_dbg, &tze_fops);
 
        tz->debugfs = thermal_dbg;
 }
 
 void thermal_debug_tz_remove(struct thermal_zone_device *tz)
 {
-       struct thermal_debugfs *thermal_dbg = tz->debugfs;
+       struct thermal_debugfs *thermal_dbg;
+       struct tz_episode *tze, *tmp;
+       struct tz_debugfs *tz_dbg;
+       int *trips_crossed;
 
-       if (!thermal_dbg)
+       mutex_lock(&tz->lock);
+
+       thermal_dbg = tz->debugfs;
+       if (!thermal_dbg) {
+               mutex_unlock(&tz->lock);
                return;
+       }
+
+       tz->debugfs = NULL;
+
+       mutex_unlock(&tz->lock);
+
+       tz_dbg = &thermal_dbg->tz_dbg;
 
        mutex_lock(&thermal_dbg->lock);
 
-       tz->debugfs = NULL;
+       trips_crossed = tz_dbg->trips_crossed;
+
+       list_for_each_entry_safe(tze, tmp, &tz_dbg->tz_episodes, node) {
+               list_del(&tze->node);
+               kfree(tze);
+       }
 
        mutex_unlock(&thermal_dbg->lock);
 
        thermal_debugfs_remove_id(thermal_dbg);
+       kfree(trips_crossed);
 }
index 9446660e231bb3f9a79b5cdf1503b13377539227..008053039875a4c6d3fc9b8822491c97eadd0abe 100644 (file)
@@ -5110,9 +5110,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
        }
        if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
                ;       /* Initial ep0 maxpacket guess is right */
-       } else if ((udev->speed == USB_SPEED_FULL ||
+       } else if (((udev->speed == USB_SPEED_FULL ||
                                udev->speed == USB_SPEED_HIGH) &&
-                       (i == 8 || i == 16 || i == 32 || i == 64)) {
+                       (i == 8 || i == 16 || i == 32 || i == 64)) ||
+                       (udev->speed >= USB_SPEED_SUPER && i > 0)) {
                /* Initial guess is wrong; use the descriptor's value */
                if (udev->speed == USB_SPEED_FULL)
                        dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
index 0e1262a077aea38ed9f56b8724d748d2c64663e1..e7da2fca11a48cf9c3d53cd53d124d65a1cd751f 100644 (file)
@@ -51,13 +51,15 @@ static ssize_t disable_show(struct device *dev,
        struct usb_port *port_dev = to_usb_port(dev);
        struct usb_device *hdev = to_usb_device(dev->parent->parent);
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
-       struct usb_interface *intf = to_usb_interface(hub->intfdev);
+       struct usb_interface *intf = to_usb_interface(dev->parent);
        int port1 = port_dev->portnum;
        u16 portstatus, unused;
        bool disabled;
        int rc;
        struct kernfs_node *kn;
 
+       if (!hub)
+               return -ENODEV;
        hub_get(hub);
        rc = usb_autopm_get_interface(intf);
        if (rc < 0)
@@ -101,12 +103,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
        struct usb_port *port_dev = to_usb_port(dev);
        struct usb_device *hdev = to_usb_device(dev->parent->parent);
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
-       struct usb_interface *intf = to_usb_interface(hub->intfdev);
+       struct usb_interface *intf = to_usb_interface(dev->parent);
        int port1 = port_dev->portnum;
        bool disabled;
        int rc;
        struct kernfs_node *kn;
 
+       if (!hub)
+               return -ENODEV;
        rc = kstrtobool(buf, &disabled);
        if (rc)
                return rc;
index 31684cdaaae3056c6cf9b16d31cc0eb4f217b7bb..100041320e8dd2e80488b7dfdc372d373ea0d251 100644 (file)
@@ -104,6 +104,27 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
        return 0;
 }
 
+void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
+{
+       u32 reg;
+
+       reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+       if (enable && !dwc->dis_u3_susphy_quirk)
+               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+       else
+               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+
+       dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+
+       reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+       if (enable && !dwc->dis_u2_susphy_quirk)
+               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+       else
+               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+       dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+}
+
 void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
 {
        u32 reg;
@@ -585,11 +606,8 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc)
  */
 static int dwc3_phy_setup(struct dwc3 *dwc)
 {
-       unsigned int hw_mode;
        u32 reg;
 
-       hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
-
        reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 
        /*
@@ -599,21 +617,16 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
 
        /*
-        * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
-        * to '0' during coreConsultant configuration. So default value
-        * will be '0' when the core is reset. Application needs to set it
-        * to '1' after the core initialization is completed.
-        */
-       if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
-               reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-
-       /*
-        * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after
-        * power-on reset, and it can be set after core initialization, which is
-        * after device soft-reset during initialization.
+        * Above DWC_usb3.0 1.94a, it is recommended to set
+        * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
+        * So default value will be '0' when the core is reset. Application
+        * needs to set it to '1' after the core initialization is completed.
+        *
+        * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
+        * cleared after power-on reset, and it can be set after core
+        * initialization.
         */
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
-               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+       reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
 
        if (dwc->u2ss_inp3_quirk)
                reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
@@ -639,9 +652,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        if (dwc->tx_de_emphasis_quirk)
                reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
 
-       if (dwc->dis_u3_susphy_quirk)
-               reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
-
        if (dwc->dis_del_phy_power_chg_quirk)
                reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
 
@@ -689,24 +699,15 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        }
 
        /*
-        * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
-        * '0' during coreConsultant configuration. So default value will
-        * be '0' when the core is reset. Application needs to set it to
-        * '1' after the core initialization is completed.
-        */
-       if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
-               reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-
-       /*
-        * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after
-        * power-on reset, and it can be set after core initialization, which is
-        * after device soft-reset during initialization.
+        * Above DWC_usb3.0 1.94a, it is recommended to set
+        * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
+        * So default value will be '0' when the core is reset. Application
+        * needs to set it to '1' after the core initialization is completed.
+        *
+        * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
+        * after power-on reset, and it can be set after core initialization.
         */
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
-               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
-
-       if (dwc->dis_u2_susphy_quirk)
-               reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+       reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 
        if (dwc->dis_enblslpm_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
@@ -1227,21 +1228,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
        if (ret)
                goto err_exit_phy;
 
-       if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
-           !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) {
-               if (!dwc->dis_u3_susphy_quirk) {
-                       reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
-                       reg |= DWC3_GUSB3PIPECTL_SUSPHY;
-                       dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
-               }
-
-               if (!dwc->dis_u2_susphy_quirk) {
-                       reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
-                       reg |= DWC3_GUSB2PHYCFG_SUSPHY;
-                       dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
-               }
-       }
-
        dwc3_core_setup_global_control(dwc);
        dwc3_core_num_eps(dwc);
 
index 7e80dd3d466b88538f597a5f1534fd020ac23763..180dd8d29287c6851581e0a0d194a8c79c0959c2 100644 (file)
@@ -1580,6 +1580,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc);
 void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
 
 int dwc3_core_soft_reset(struct dwc3 *dwc);
+void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
 
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
index 4df2661f66751bd56a3717d9f0d2705a29f07738..f94f68f1e7d2b7ccab8f565048a41950a34aa464 100644 (file)
@@ -2924,6 +2924,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
        dwc3_ep0_out_start(dwc);
 
        dwc3_gadget_enable_irq(dwc);
+       dwc3_enable_susphy(dwc, true);
 
        return 0;
 
@@ -4690,6 +4691,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
        if (!dwc->gadget)
                return;
 
+       dwc3_enable_susphy(dwc, false);
        usb_del_gadget(dwc->gadget);
        dwc3_gadget_free_endpoints(dwc);
        usb_put_gadget(dwc->gadget);
index 0204787df81d50b9291b1701c554795c3d97bca8..a171b27a7845af9ceb92d567d380a540e3ad0ef8 100644 (file)
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
 #include "../host/xhci-port.h"
 #include "../host/xhci-ext-caps.h"
 #include "../host/xhci-caps.h"
+#include "../host/xhci-plat.h"
 #include "core.h"
 
 #define XHCI_HCSPARAMS1                0x4
@@ -57,6 +60,24 @@ static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc)
        }
 }
 
+static void dwc3_xhci_plat_start(struct usb_hcd *hcd)
+{
+       struct platform_device *pdev;
+       struct dwc3 *dwc;
+
+       if (!usb_hcd_is_primary_hcd(hcd))
+               return;
+
+       pdev = to_platform_device(hcd->self.controller);
+       dwc = dev_get_drvdata(pdev->dev.parent);
+
+       dwc3_enable_susphy(dwc, true);
+}
+
+static const struct xhci_plat_priv dwc3_xhci_plat_quirk = {
+       .plat_start = dwc3_xhci_plat_start,
+};
+
 static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
                                        int irq, char *name)
 {
@@ -167,6 +188,11 @@ int dwc3_host_init(struct dwc3 *dwc)
                }
        }
 
+       ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk,
+                                      sizeof(struct xhci_plat_priv));
+       if (ret)
+               goto err;
+
        ret = platform_device_add(xhci);
        if (ret) {
                dev_err(dwc->dev, "failed to register xHCI device\n");
@@ -192,6 +218,7 @@ void dwc3_host_exit(struct dwc3 *dwc)
        if (dwc->sys_wakeup)
                device_init_wakeup(&dwc->xhci->dev, false);
 
+       dwc3_enable_susphy(dwc, false);
        platform_device_unregister(dwc->xhci);
        dwc->xhci = NULL;
 }
index 0ace45b66a31c417f7e6da9f811c3d8b5c736246..0e151b54aae82a3677dbbd0487d91e403f83e7b5 100644 (file)
@@ -2112,7 +2112,7 @@ unknown:
                        buf[5] = 0x01;
                        switch (ctrl->bRequestType & USB_RECIP_MASK) {
                        case USB_RECIP_DEVICE:
-                               if (w_index != 0x4 || (w_value >> 8))
+                               if (w_index != 0x4 || (w_value & 0xff))
                                        break;
                                buf[6] = w_index;
                                /* Number of ext compat interfaces */
@@ -2128,9 +2128,9 @@ unknown:
                                }
                                break;
                        case USB_RECIP_INTERFACE:
-                               if (w_index != 0x5 || (w_value >> 8))
+                               if (w_index != 0x5 || (w_value & 0xff))
                                        break;
-                               interface = w_value & 0xFF;
+                               interface = w_value >> 8;
                                if (interface >= MAX_CONFIG_INTERFACES ||
                                    !os_desc_cfg->interface[interface])
                                        break;
index f855f1fc8e5e14d253a61382a692a9173c2e2c26..a057cbedf3c9b30430eeb3a8749975e58cec54da 100644 (file)
@@ -852,6 +852,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
                                                   work);
        int ret = io_data->status;
        bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
+       unsigned long flags;
 
        if (io_data->read && ret > 0) {
                kthread_use_mm(io_data->mm);
@@ -864,6 +865,11 @@ static void ffs_user_copy_worker(struct work_struct *work)
        if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
                eventfd_signal(io_data->ffs->ffs_eventfd);
 
+       spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
+       usb_ep_free_request(io_data->ep, io_data->req);
+       io_data->req = NULL;
+       spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
+
        if (io_data->read)
                kfree(io_data->to_free);
        ffs_free_buffer(io_data);
@@ -877,7 +883,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
        struct ffs_data *ffs = io_data->ffs;
 
        io_data->status = req->status ? req->status : req->actual;
-       usb_ep_free_request(_ep, req);
 
        INIT_WORK(&io_data->work, ffs_user_copy_worker);
        queue_work(ffs->io_completion_wq, &io_data->work);
@@ -3806,7 +3811,7 @@ static int ffs_func_setup(struct usb_function *f,
        __ffs_event_add(ffs, FUNCTIONFS_SETUP);
        spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
 
-       return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
+       return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
 }
 
 static bool ffs_func_req_match(struct usb_function *f,
index 7e704b2bcfd1ce5a2c28a4f318fca6633a7072f8..a4377df612f51e12760195cd1fbe89ec9c541fbe 100644 (file)
@@ -92,10 +92,10 @@ static int __uvcg_iter_item_entries(const char *page, size_t len,
 
        while (pg - page < len) {
                i = 0;
-               while (i < sizeof(buf) && (pg - page < len) &&
+               while (i < bufsize && (pg - page < len) &&
                       *pg != '\0' && *pg != '\n')
                        buf[i++] = *pg++;
-               if (i == sizeof(buf)) {
+               if (i == bufsize) {
                        ret = -EINVAL;
                        goto out_free_buf;
                }
index 4f9982ecfb583e60e0f5b9cfff4c8001b2bf598f..5cec7640e913c8bac477f67c517304bb0afe5941 100644 (file)
@@ -888,6 +888,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
        /* Check for an all 1's result which is a typical consequence
         * of dead, unclocked, or unplugged (CardBus...) devices
         */
+again:
        if (ints == ~(u32)0) {
                ohci->rh_state = OHCI_RH_HALTED;
                ohci_dbg (ohci, "device removed!\n");
@@ -982,6 +983,13 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
        }
        spin_unlock(&ohci->lock);
 
+       /* repeat until all enabled interrupts are handled */
+       if (ohci->rh_state != OHCI_RH_HALTED) {
+               ints = ohci_readl(ohci, &regs->intrstatus);
+               if (ints && (ints & ohci_readl(ohci, &regs->intrenable)))
+                       goto again;
+       }
+
        return IRQ_HANDLED;
 }
 
index 2d15386f2c504b7aa8b1798f1b41b1e81b1498c1..6475130eac4b38061ea038ad14b00a48f269d4e0 100644 (file)
@@ -8,7 +8,9 @@
 #ifndef _XHCI_PLAT_H
 #define _XHCI_PLAT_H
 
-#include "xhci.h"      /* for hcd_to_xhci() */
+struct device;
+struct platform_device;
+struct usb_hcd;
 
 struct xhci_plat_priv {
        const char *firmware_name;
index ec65b24eafa868dafe6bafaf1c3c27b16550f31d..4f59867d7117cfda924d151e35b8faeb13dd0bec 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/usb/rzv2m_usb3drd.h>
+#include "xhci.h"
 #include "xhci-plat.h"
 #include "xhci-rzv2m.h"
 
index e48412cdcb0fb5b5562afb2ce65af38a1d31840c..d3958c061a972ccbde85c07595132793e80afc94 100644 (file)
@@ -104,14 +104,18 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
 
        ret = tcpm->port_start(tcpm, tcpm->tcpm_port);
        if (ret)
-               goto fwnode_remove;
+               goto port_unregister;
 
        ret = tcpm->pdphy_start(tcpm, tcpm->tcpm_port);
        if (ret)
-               goto fwnode_remove;
+               goto port_stop;
 
        return 0;
 
+port_stop:
+       tcpm->port_stop(tcpm);
+port_unregister:
+       tcpm_unregister_port(tcpm->tcpm_port);
 fwnode_remove:
        fwnode_remove_software_node(tcpm->tcpc.fwnode);
 
index 6560f4fc98d5a3444ab33cc2ab29cd83890ac06b..5b7f52b74a40aa70096499e34d6c32a38c08fd48 100644 (file)
@@ -475,10 +475,8 @@ static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdph
 
        qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy);
 done:
-       if (ret) {
-               regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+       if (ret)
                dev_err(dev, "pdphy_enable fail %d\n", ret);
-       }
 
        return ret;
 }
@@ -524,12 +522,17 @@ static int qcom_pmic_typec_pdphy_start(struct pmic_typec *tcpm,
 
        ret = pmic_typec_pdphy_reset(pmic_typec_pdphy);
        if (ret)
-               return ret;
+               goto err_disable_vdd_pdhy;
 
        for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
                enable_irq(pmic_typec_pdphy->irq_data[i].irq);
 
        return 0;
+
+err_disable_vdd_pdhy:
+       regulator_disable(pmic_typec_pdphy->vdd_pdphy);
+
+       return ret;
 }
 
 static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
index ab6ed6111ed05ce44f1fc94202299faf143bd79c..8a1af08f71b6450710e4ae7ff2e891f490a036ca 100644 (file)
@@ -1564,8 +1564,12 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
 static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header,
                                    const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type)
 {
+       if (port->state != SRC_READY && port->state != SNK_READY &&
+           port->state != SRC_VDM_IDENTITY_REQUEST)
+               return;
+
        mutex_lock(&port->lock);
-       tcpm_queue_vdm(port, header, data, cnt, TCPC_TX_SOP);
+       tcpm_queue_vdm(port, header, data, cnt, tx_sop_type);
        mutex_unlock(&port->lock);
 }
 
@@ -1580,7 +1584,8 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
        port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];
        port->partner_ident.product = product;
 
-       typec_partner_set_identity(port->partner);
+       if (port->partner)
+               typec_partner_set_identity(port->partner);
 
        tcpm_log(port, "Identity: %04x:%04x.%04x",
                 PD_IDH_VID(vdo),
@@ -1742,6 +1747,9 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
        struct typec_altmode *altmode;
        int i;
 
+       if (!port->partner)
+               return;
+
        for (i = 0; i < modep->altmodes; i++) {
                altmode = typec_partner_register_altmode(port->partner,
                                                &modep->altmode_desc[i]);
@@ -2996,7 +3004,7 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
 {
        struct usb_power_delivery_desc desc = { port->negotiated_rev };
        struct usb_power_delivery_capabilities_desc caps = { };
-       struct usb_power_delivery_capabilities *cap;
+       struct usb_power_delivery_capabilities *cap = port->partner_source_caps;
 
        if (!port->partner_pd)
                port->partner_pd = usb_power_delivery_register(NULL, &desc);
@@ -3006,6 +3014,9 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
        memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps);
        caps.role = TYPEC_SOURCE;
 
+       if (cap)
+               usb_power_delivery_unregister_capabilities(cap);
+
        cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
        if (IS_ERR(cap))
                return PTR_ERR(cap);
@@ -4231,7 +4242,10 @@ static int tcpm_init_vconn(struct tcpm_port *port)
 
 static void tcpm_typec_connect(struct tcpm_port *port)
 {
+       struct typec_partner *partner;
+
        if (!port->connected) {
+               port->connected = true;
                /* Make sure we don't report stale identity information */
                memset(&port->partner_ident, 0, sizeof(port->partner_ident));
                port->partner_desc.usb_pd = port->pd_capable;
@@ -4241,9 +4255,13 @@ static void tcpm_typec_connect(struct tcpm_port *port)
                        port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO;
                else
                        port->partner_desc.accessory = TYPEC_ACCESSORY_NONE;
-               port->partner = typec_register_partner(port->typec_port,
-                                                      &port->partner_desc);
-               port->connected = true;
+               partner = typec_register_partner(port->typec_port, &port->partner_desc);
+               if (IS_ERR(partner)) {
+                       dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner));
+                       return;
+               }
+
+               port->partner = partner;
                typec_partner_set_usb_power_delivery(port->partner, port->partner_pd);
        }
 }
@@ -4323,9 +4341,11 @@ static void tcpm_typec_disconnect(struct tcpm_port *port)
        port->plug_prime = NULL;
        port->cable = NULL;
        if (port->connected) {
-               typec_partner_set_usb_power_delivery(port->partner, NULL);
-               typec_unregister_partner(port->partner);
-               port->partner = NULL;
+               if (port->partner) {
+                       typec_partner_set_usb_power_delivery(port->partner, NULL);
+                       typec_unregister_partner(port->partner);
+                       port->partner = NULL;
+               }
                port->connected = false;
        }
 }
@@ -4549,6 +4569,9 @@ static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode)
 
 static void tcpm_set_initial_svdm_version(struct tcpm_port *port)
 {
+       if (!port->partner)
+               return;
+
        switch (port->negotiated_rev) {
        case PD_REV30:
                break;
@@ -5605,6 +5628,7 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case PORT_RESET:
                tcpm_reset_port(port);
+               port->pd_events = 0;
                if (port->self_powered)
                        tcpm_set_cc(port, TYPEC_CC_OPEN);
                else
index b246067e074bc0718ad49ad582b3ad9e382c9af0..6cb96a1e8b7df453c00ac0eaf9a568908f743c9f 100644 (file)
@@ -967,7 +967,7 @@ vdpa_dev_blk_seg_size_config_fill(struct sk_buff *msg, u64 features,
 
        val_u32 = __virtio32_to_cpu(true, config->size_max);
 
-       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE, val_u32);
+       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SIZE_MAX, val_u32);
 }
 
 /* fill the block size*/
@@ -1089,7 +1089,7 @@ static int vdpa_dev_blk_ro_config_fill(struct sk_buff *msg, u64 features)
        u8 ro;
 
        ro = ((features & BIT_ULL(VIRTIO_BLK_F_RO)) == 0) ? 0 : 1;
-       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_READ_ONLY, ro))
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_READ_ONLY, ro))
                return -EMSGSIZE;
 
        return 0;
@@ -1100,7 +1100,7 @@ static int vdpa_dev_blk_flush_config_fill(struct sk_buff *msg, u64 features)
        u8 flush;
 
        flush = ((features & BIT_ULL(VIRTIO_BLK_F_FLUSH)) == 0) ? 0 : 1;
-       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_FLUSH, flush))
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_FLUSH, flush))
                return -EMSGSIZE;
 
        return 0;
index dae96c9f61cf8766cfe1e781f83c81e962691673..806ecd32219b691327d9620e41316404624a73ae 100644 (file)
@@ -196,7 +196,7 @@ err_mutex_unlock:
  */
 static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_info *info, struct vm_fault *vmf)
 {
-       unsigned long offset = vmf->address - vmf->vma->vm_start;
+       unsigned long offset = vmf->pgoff << PAGE_SHIFT;
        struct page *page = vmf->page;
 
        file_update_time(vmf->vma->vm_file);
index 9defa12208f98a715e5b894119f044fca50b3dc5..1775fcc7f0e8efa8b22f4c14e6886d85a22faeb5 100644 (file)
@@ -179,13 +179,14 @@ extern int v9fs_vfs_rename(struct mnt_idmap *idmap,
                           struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry,
                           unsigned int flags);
-extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid);
+extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid,
+                                               bool new);
 extern const struct inode_operations v9fs_dir_inode_operations_dotl;
 extern const struct inode_operations v9fs_file_inode_operations_dotl;
 extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
 extern const struct netfs_request_ops v9fs_req_ops;
 extern struct inode *v9fs_fid_iget_dotl(struct super_block *sb,
-                                       struct p9_fid *fid);
+                                               struct p9_fid *fid, bool new);
 
 /* other default globals */
 #define V9FS_PORT      564
@@ -224,12 +225,12 @@ static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
  */
 static inline struct inode *
 v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-                       struct super_block *sb)
+                       struct super_block *sb, bool new)
 {
        if (v9fs_proto_dotl(v9ses))
-               return v9fs_fid_iget_dotl(sb, fid);
+               return v9fs_fid_iget_dotl(sb, fid, new);
        else
-               return v9fs_fid_iget(sb, fid);
+               return v9fs_fid_iget(sb, fid, new);
 }
 
 #endif
index 47bd77199e20c83a3c7554d5dc592697080b7885..7a3308d776060e2e2565af09d358f2cf33416b6b 100644 (file)
@@ -364,7 +364,8 @@ void v9fs_evict_inode(struct inode *inode)
                clear_inode(inode);
 }
 
-struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
+struct inode *
+v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new)
 {
        dev_t rdev;
        int retval;
@@ -376,8 +377,18 @@ struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
        inode = iget_locked(sb, QID2INO(&fid->qid));
        if (unlikely(!inode))
                return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
-               return inode;
+       if (!(inode->i_state & I_NEW)) {
+               if (!new) {
+                       goto done;
+               } else {
+                       p9_debug(P9_DEBUG_VFS, "WARNING: Inode collision %ld\n",
+                                               inode->i_ino);
+                       iput(inode);
+                       remove_inode_hash(inode);
+                       inode = iget_locked(sb, QID2INO(&fid->qid));
+                       WARN_ON(!(inode->i_state & I_NEW));
+               }
+       }
 
        /*
         * initialize the inode with the stat info
@@ -401,11 +412,11 @@ struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
        v9fs_set_netfs_context(inode);
        v9fs_cache_inode_get_cookie(inode);
        unlock_new_inode(inode);
+done:
        return inode;
 error:
        iget_failed(inode);
        return ERR_PTR(retval);
-
 }
 
 /**
@@ -437,8 +448,15 @@ static int v9fs_at_to_dotl_flags(int flags)
  */
 static void v9fs_dec_count(struct inode *inode)
 {
-       if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
-               drop_nlink(inode);
+       if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) {
+               if (inode->i_nlink) {
+                       drop_nlink(inode);
+               } else {
+                       p9_debug(P9_DEBUG_VFS,
+                                               "WARNING: unexpected i_nlink zero %d inode %ld\n",
+                                               inode->i_nlink, inode->i_ino);
+               }
+       }
 }
 
 /**
@@ -489,6 +507,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
                } else
                        v9fs_dec_count(inode);
 
+               if (inode->i_nlink <= 0)        /* no more refs unhash it */
+                       remove_inode_hash(inode);
+
                v9fs_invalidate_inode_attr(inode);
                v9fs_invalidate_inode_attr(dir);
 
@@ -554,7 +575,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
                /*
                 * instantiate inode and assign the unopened fid to the dentry
                 */
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, true);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        p9_debug(P9_DEBUG_VFS,
@@ -683,7 +704,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        else if (IS_ERR(fid))
                inode = ERR_CAST(fid);
        else
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, false);
        /*
         * If we had a rename on the server and a parallel lookup
         * for the new name, then make sure we instantiate with
index 55dde186041a38d98c997e2ea728e2004c2a9606..c61b97bd13b9a7875b14f9af6e109b85143c79da 100644 (file)
@@ -52,7 +52,10 @@ static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
        return current_fsgid();
 }
 
-struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
+
+
+struct inode *
+v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new)
 {
        int retval;
        struct inode *inode;
@@ -62,8 +65,18 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
        inode = iget_locked(sb, QID2INO(&fid->qid));
        if (unlikely(!inode))
                return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
-               return inode;
+       if (!(inode->i_state & I_NEW)) {
+               if (!new) {
+                       goto done;
+               } else { /* deal with race condition in inode number reuse */
+                       p9_debug(P9_DEBUG_ERROR, "WARNING: Inode collision %lx\n",
+                                               inode->i_ino);
+                       iput(inode);
+                       remove_inode_hash(inode);
+                       inode = iget_locked(sb, QID2INO(&fid->qid));
+                       WARN_ON(!(inode->i_state & I_NEW));
+               }
+       }
 
        /*
         * initialize the inode with the stat info
@@ -90,12 +103,11 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
                goto error;
 
        unlock_new_inode(inode);
-
+done:
        return inode;
 error:
        iget_failed(inode);
        return ERR_PTR(retval);
-
 }
 
 struct dotl_openflag_map {
@@ -247,7 +259,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
                goto out;
        }
-       inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
+       inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -340,7 +352,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
        }
 
        /* instantiate inode and assign the unopened fid to the dentry */
-       inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
+       inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -776,7 +788,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir,
                         err);
                goto error;
        }
-       inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
+       inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
index 55e67e36ae682bcf33a66c2f5e7d936e975e8f6f..f52fdf42945cf15d21fe55f01da21967714ed07c 100644 (file)
@@ -139,7 +139,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
        else
                sb->s_d_op = &v9fs_dentry_operations;
 
-       inode = v9fs_get_inode_from_fid(v9ses, fid, sb);
+       inode = v9fs_get_inode_from_fid(v9ses, fid, sb, true);
        if (IS_ERR(inode)) {
                retval = PTR_ERR(inode);
                goto release_sb;
index fadb1078903d291ce6ce3c7928d79c71c1eb18f8..a200442010025a0d8ee7b421d12edb32ff5c5a01 100644 (file)
@@ -470,7 +470,7 @@ found:
                goto err;
        }
 
-       bio = bio_alloc(ca->disk_sb.bdev, 1, REQ_OP_READ, GFP_KERNEL);
+       bio = bio_alloc(ca->disk_sb.bdev, buf_pages(data_buf, bytes), REQ_OP_READ, GFP_KERNEL);
        bio->bi_iter.bi_sector = p.ptr.offset;
        bch2_bio_map(bio, data_buf, bytes);
        ret = submit_bio_wait(bio);
index 085987435a5ea3cfc7354db7ee5392ce62241f05..f7fbfccd2b1e4d7e6bafabd839a6917de906edf9 100644 (file)
@@ -1504,7 +1504,8 @@ enum btree_id_flags {
          BIT_ULL(KEY_TYPE_stripe))                                             \
        x(reflink,              7,      BTREE_ID_EXTENTS|BTREE_ID_DATA,         \
          BIT_ULL(KEY_TYPE_reflink_v)|                                          \
-         BIT_ULL(KEY_TYPE_indirect_inline_data))                               \
+         BIT_ULL(KEY_TYPE_indirect_inline_data)|                               \
+         BIT_ULL(KEY_TYPE_error))                                              \
        x(subvolumes,           8,      0,                                      \
          BIT_ULL(KEY_TYPE_subvolume))                                          \
        x(snapshots,            9,      0,                                      \
index ecbd9598f69fd00e86efbe7537a134d6d4c4db06..791470b0c654553e2fbb9216fb60df1eb8c5fec2 100644 (file)
@@ -1587,7 +1587,7 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans,
                struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k);
                ret = PTR_ERR_OR_ZERO(new);
                if (ret)
-                       return ret;
+                       goto out;
 
                if (!r->refcount)
                        new->k.type = KEY_TYPE_deleted;
@@ -1595,6 +1595,7 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans,
                        *bkey_refcount(bkey_i_to_s(new)) = cpu_to_le64(r->refcount);
                ret = bch2_trans_update(trans, iter, new, 0);
        }
+out:
 fsck_err:
        printbuf_exit(&buf);
        return ret;
index 9678b2375bedde868e7a168435c9a17fc74eb26a..debb0edc3455afa661c0104e6e29fe232bcd18b8 100644 (file)
@@ -888,7 +888,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                                 -BCH_ERR_btree_node_read_err_fixable,
                                 c, NULL, b, i,
                                 btree_node_bkey_bad_u64s,
-                                "bad k->u64s %u (min %u max %lu)", k->u64s,
+                                "bad k->u64s %u (min %u max %zu)", k->u64s,
                                 bkeyp_key_u64s(&b->format, k),
                                 U8_MAX - BKEY_U64s + bkeyp_key_u64s(&b->format, k)))
                        goto drop_this_key;
index 88a3582a32757e34a28eb37143f9ff78a88a4085..e8c1c530cd95f5bb1c34cb39f848cd842b0a88c6 100644 (file)
@@ -842,8 +842,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
         * Newest freed entries are at the end of the list - once we hit one
         * that's too new to be freed, we can bail out:
         */
-       scanned += bc->nr_freed_nonpcpu;
-
        list_for_each_entry_safe(ck, t, &bc->freed_nonpcpu, list) {
                if (!poll_state_synchronize_srcu(&c->btree_trans_barrier,
                                                 ck->btree_trans_barrier_seq))
@@ -857,11 +855,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
                bc->nr_freed_nonpcpu--;
        }
 
-       if (scanned >= nr)
-               goto out;
-
-       scanned += bc->nr_freed_pcpu;
-
        list_for_each_entry_safe(ck, t, &bc->freed_pcpu, list) {
                if (!poll_state_synchronize_srcu(&c->btree_trans_barrier,
                                                 ck->btree_trans_barrier_seq))
@@ -875,9 +868,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
                bc->nr_freed_pcpu--;
        }
 
-       if (scanned >= nr)
-               goto out;
-
        rcu_read_lock();
        tbl = rht_dereference_rcu(bc->table.tbl, &bc->table);
        if (bc->shrink_iter >= tbl->size)
@@ -893,12 +883,12 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink,
                        next = rht_dereference_bucket_rcu(pos->next, tbl, bc->shrink_iter);
                        ck = container_of(pos, struct bkey_cached, hash);
 
-                       if (test_bit(BKEY_CACHED_DIRTY, &ck->flags))
+                       if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
                                goto next;
-
-                       if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags))
+                       } else if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags)) {
                                clear_bit(BKEY_CACHED_ACCESSED, &ck->flags);
-                       else if (bkey_cached_lock_for_evict(ck)) {
+                               goto next;
+                       } else if (bkey_cached_lock_for_evict(ck)) {
                                bkey_cached_evict(bc, ck);
                                bkey_cached_free(bc, ck);
                        }
@@ -916,7 +906,6 @@ next:
        } while (scanned < nr && bc->shrink_iter != start);
 
        rcu_read_unlock();
-out:
        memalloc_nofs_restore(flags);
        srcu_read_unlock(&c->btree_trans_barrier, srcu_idx);
        mutex_unlock(&bc->lock);
index 866bd278439f8bb72a0b1e31e672953ff9b3f839..45cb8149d374c2878e8c607282ca4e5e7875f063 100644 (file)
@@ -57,13 +57,14 @@ static void found_btree_node_to_key(struct bkey_i *k, const struct found_btree_n
        bp->v.seq               = cpu_to_le64(f->cookie);
        bp->v.sectors_written   = 0;
        bp->v.flags             = 0;
+       bp->v.sectors_written   = cpu_to_le16(f->sectors_written);
        bp->v.min_key           = f->min_key;
        SET_BTREE_PTR_RANGE_UPDATED(&bp->v, f->range_updated);
        memcpy(bp->v.start, f->ptrs, sizeof(struct bch_extent_ptr) * f->nr_ptrs);
 }
 
 static bool found_btree_node_is_readable(struct btree_trans *trans,
-                                        const struct found_btree_node *f)
+                                        struct found_btree_node *f)
 {
        struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } k;
 
@@ -71,8 +72,10 @@ static bool found_btree_node_is_readable(struct btree_trans *trans,
 
        struct btree *b = bch2_btree_node_get_noiter(trans, &k.k, f->btree_id, f->level, false);
        bool ret = !IS_ERR_OR_NULL(b);
-       if (ret)
+       if (ret) {
+               f->sectors_written = b->written;
                six_unlock_read(&b->c.lock);
+       }
 
        /*
         * We might update this node's range; if that happens, we need the node
@@ -302,6 +305,8 @@ again:
 
                        start->max_key = bpos_predecessor(n->min_key);
                        start->range_updated = true;
+               } else if (n->level) {
+                       n->overwritten = true;
                } else {
                        struct printbuf buf = PRINTBUF;
 
index abb7b27d556a9ff0f09e797494437a513122d8d3..5cfaeb5ac831b6396399d71858d2934e7d63c544 100644 (file)
@@ -9,6 +9,7 @@ struct found_btree_node {
        bool                    overwritten:1;
        u8                      btree_id;
        u8                      level;
+       unsigned                sectors_written;
        u32                     seq;
        u64                     cookie;
 
index e0c982a4195c764ab8a415b5f7f80cbff88c1935..c69b233c41bb3d07a02ca296c03429360ff2294e 100644 (file)
@@ -321,9 +321,9 @@ struct bkey_cached {
        struct btree_bkey_cached_common c;
 
        unsigned long           flags;
+       unsigned long           btree_trans_barrier_seq;
        u16                     u64s;
        bool                    valid;
-       u32                     btree_trans_barrier_seq;
        struct bkey_cached_key  key;
 
        struct rhash_head       hash;
index 6030c396754f6f494c3c137abd313f6bf80c2ffb..b4efd8cc4d1a2bfc62a9742d6f4df3e9a0f0aac5 100644 (file)
@@ -1960,7 +1960,11 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
        if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates)
                return 0;
 
-       flags &= ~BCH_WATERMARK_MASK;
+       if ((flags & BCH_WATERMARK_MASK) <= BCH_WATERMARK_reclaim) {
+               flags &= ~BCH_WATERMARK_MASK;
+               flags |= BCH_WATERMARK_btree;
+               flags |= BCH_TRANS_COMMIT_journal_reclaim;
+       }
 
        b = trans->paths[path].l[level].b;
 
index 941401a210f56993359548e51b5095d0db45e691..82f179258867b7b1b6e5f21905f0bc3d3eaee41c 100644 (file)
@@ -525,7 +525,6 @@ int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
                        "different types of data in same bucket: %s, %s",
                        bch2_data_type_str(g->data_type),
                        bch2_data_type_str(data_type))) {
-               BUG();
                ret = -EIO;
                goto err;
        }
@@ -629,7 +628,6 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
                        bch2_data_type_str(ptr_data_type),
                        (printbuf_reset(&buf),
                         bch2_bkey_val_to_text(&buf, c, k), buf.buf));
-               BUG();
                ret = -EIO;
                goto err;
        }
index 72781aad6ba70ccc774b688c6a9d50b2dc21f133..4d14f19f51850e9d024ee69bd1f68d5a3743a2b0 100644 (file)
@@ -232,13 +232,15 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a
        /* We need request_key() to be called before we punt to kthread: */
        opt_set(thr->opts, nostart, true);
 
+       bch2_thread_with_stdio_init(&thr->thr, &bch2_offline_fsck_ops);
+
        thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts);
 
        if (!IS_ERR(thr->c) &&
            thr->c->opts.errors == BCH_ON_ERROR_panic)
                thr->c->opts.errors = BCH_ON_ERROR_ro;
 
-       ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops);
+       ret = __bch2_run_thread_with_stdio(&thr->thr);
 out:
        darray_for_each(devs, i)
                kfree(*i);
index b5ea9fa1259d1462e9033318466fc914911672ce..fce690007edfce089f054d81cc862c04c132c2b3 100644 (file)
@@ -188,7 +188,8 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino
        BUG_ON(!old);
 
        if (unlikely(old != inode)) {
-               discard_new_inode(&inode->v);
+               __destroy_inode(&inode->v);
+               kmem_cache_free(bch2_inode_cache, inode);
                inode = old;
        } else {
                mutex_lock(&c->vfs_inodes_lock);
@@ -225,8 +226,10 @@ static struct bch_inode_info *bch2_new_inode(struct btree_trans *trans)
 
        if (unlikely(!inode)) {
                int ret = drop_locks_do(trans, (inode = to_bch_ei(new_inode(c->vfs_sb))) ? 0 : -ENOMEM);
-               if (ret && inode)
-                       discard_new_inode(&inode->v);
+               if (ret && inode) {
+                       __destroy_inode(&inode->v);
+                       kmem_cache_free(bch2_inode_cache, inode);
+               }
                if (ret)
                        return ERR_PTR(ret);
        }
index ca4a066e9a5428aa68f88d77f59e9c365a580d6c..0f95d7fb5ec0bddf755299a70908a3520c307f69 100644 (file)
@@ -606,7 +606,7 @@ int bch2_trigger_inode(struct btree_trans *trans,
                       struct bkey_s new,
                       unsigned flags)
 {
-       s64 nr = bkey_is_inode(new.k) - bkey_is_inode(old.k);
+       s64 nr = (s64) bkey_is_inode(new.k) - (s64) bkey_is_inode(old.k);
 
        if (flags & BTREE_TRIGGER_TRANSACTIONAL) {
                if (nr) {
index 9aa28b52ab926c567f49e0bb68b9c6791fb326e5..eb1f9d6f5a196e55aebf5b74f485bfa634169da5 100644 (file)
@@ -1723,7 +1723,7 @@ static void journal_write_endio(struct bio *bio)
        percpu_ref_put(&ca->io_ref);
 }
 
-static CLOSURE_CALLBACK(do_journal_write)
+static CLOSURE_CALLBACK(journal_write_submit)
 {
        closure_type(w, struct journal_buf, io);
        struct journal *j = container_of(w, struct journal, buf[w->idx]);
@@ -1768,6 +1768,44 @@ static CLOSURE_CALLBACK(do_journal_write)
        continue_at(cl, journal_write_done, j->wq);
 }
 
+static CLOSURE_CALLBACK(journal_write_preflush)
+{
+       closure_type(w, struct journal_buf, io);
+       struct journal *j = container_of(w, struct journal, buf[w->idx]);
+       struct bch_fs *c = container_of(j, struct bch_fs, journal);
+
+       if (j->seq_ondisk + 1 != le64_to_cpu(w->data->seq)) {
+               spin_lock(&j->lock);
+               closure_wait(&j->async_wait, cl);
+               spin_unlock(&j->lock);
+
+               continue_at(cl, journal_write_preflush, j->wq);
+               return;
+       }
+
+       if (w->separate_flush) {
+               for_each_rw_member(c, ca) {
+                       percpu_ref_get(&ca->io_ref);
+
+                       struct journal_device *ja = &ca->journal;
+                       struct bio *bio = &ja->bio[w->idx]->bio;
+                       bio_reset(bio, ca->disk_sb.bdev,
+                                 REQ_OP_WRITE|REQ_SYNC|REQ_META|REQ_PREFLUSH);
+                       bio->bi_end_io          = journal_write_endio;
+                       bio->bi_private         = ca;
+                       closure_bio_submit(bio, cl);
+               }
+
+               continue_at(cl, journal_write_submit, j->wq);
+       } else {
+               /*
+                * no need to punt to another work item if we're not waiting on
+                * preflushes
+                */
+               journal_write_submit(&cl->work);
+       }
+}
+
 static int bch2_journal_write_prep(struct journal *j, struct journal_buf *w)
 {
        struct bch_fs *c = container_of(j, struct bch_fs, journal);
@@ -2033,23 +2071,9 @@ CLOSURE_CALLBACK(bch2_journal_write)
                goto err;
 
        if (!JSET_NO_FLUSH(w->data))
-               closure_wait_event(&j->async_wait, j->seq_ondisk + 1 == le64_to_cpu(w->data->seq));
-
-       if (!JSET_NO_FLUSH(w->data) && w->separate_flush) {
-               for_each_rw_member(c, ca) {
-                       percpu_ref_get(&ca->io_ref);
-
-                       struct journal_device *ja = &ca->journal;
-                       struct bio *bio = &ja->bio[w->idx]->bio;
-                       bio_reset(bio, ca->disk_sb.bdev,
-                                 REQ_OP_WRITE|REQ_SYNC|REQ_META|REQ_PREFLUSH);
-                       bio->bi_end_io          = journal_write_endio;
-                       bio->bi_private         = ca;
-                       closure_bio_submit(bio, cl);
-               }
-       }
-
-       continue_at(cl, do_journal_write, j->wq);
+               continue_at(cl, journal_write_preflush, j->wq);
+       else
+               continue_at(cl, journal_write_submit, j->wq);
        return;
 no_io:
        continue_at(cl, journal_write_done, j->wq);
index 0f328aba9760ba0e89fd015ee757239b6d8bd8c4..be5b47619327001ac8191c026575f6ac18d74d16 100644 (file)
@@ -249,7 +249,10 @@ int bch2_journal_replay(struct bch_fs *c)
 
                struct journal_key *k = *kp;
 
-               replay_now_at(j, k->journal_seq);
+               if (k->journal_seq)
+                       replay_now_at(j, k->journal_seq);
+               else
+                       replay_now_at(j, j->replay_journal_seq_end);
 
                ret = commit_do(trans, NULL, NULL,
                                BCH_TRANS_COMMIT_no_enospc|
index 5980ba2563fe9fa159ba9d87fe08ab2dc53a78fb..35ca3f138de6fad2428f347c704c03992e2bc05a 100644 (file)
@@ -29,6 +29,14 @@ int bch2_sb_clean_validate_late(struct bch_fs *c, struct bch_sb_field_clean *cle
        for (entry = clean->start;
             entry < (struct jset_entry *) vstruct_end(&clean->field);
             entry = vstruct_next(entry)) {
+               if (vstruct_end(entry) > vstruct_end(&clean->field)) {
+                       bch_err(c, "journal entry (u64s %u) overran end of superblock clean section (u64s %u) by %zu",
+                               le16_to_cpu(entry->u64s), le32_to_cpu(clean->field.u64s),
+                               (u64 *) vstruct_end(entry) - (u64 *) vstruct_end(&clean->field));
+                       bch2_sb_error_count(c, BCH_FSCK_ERR_sb_clean_entry_overrun);
+                       return -BCH_ERR_fsck_repair_unimplemented;
+               }
+
                ret = bch2_journal_entry_validate(c, NULL, entry,
                                                  le16_to_cpu(c->disk_sb.sb->version),
                                                  BCH_SB_BIG_ENDIAN(c->disk_sb.sb),
index 4ca6e7b0d8aaed2c4b95fff82c2ed964c6a102ad..06c7a644f4a44279f587a3cffb39473982b3392e 100644 (file)
        x(btree_root_unreadable_and_scan_found_nothing,         263)    \
        x(snapshot_node_missing,                                264)    \
        x(dup_backpointer_to_bad_csum_extent,                   265)    \
-       x(btree_bitmap_not_marked,                              266)
+       x(btree_bitmap_not_marked,                              266)    \
+       x(sb_clean_entry_overrun,                               267)
 
 enum bch_sb_error_id {
 #define x(t, n) BCH_FSCK_ERR_##t = n,
index 522a969345e5289ac87cf53b5f5a735e3b5f8d67..5b8e621ac5eb5780bb0c2e241196737bc0076e2e 100644 (file)
@@ -463,8 +463,8 @@ static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, uns
                m->btree_bitmap_shift += resize;
        }
 
-       for (unsigned bit = sectors >> m->btree_bitmap_shift;
-            bit << m->btree_bitmap_shift < end;
+       for (unsigned bit = start >> m->btree_bitmap_shift;
+            (u64) bit << m->btree_bitmap_shift < end;
             bit++)
                bitmap |= BIT_ULL(bit);
 
index b27c3e4467cf288d67587143e5343d57d5aa41c9..5efa64eca5f85af5637faa12aa85b83fbcde6ad3 100644 (file)
@@ -235,11 +235,11 @@ static inline bool bch2_dev_btree_bitmap_marked_sectors(struct bch_dev *ca, u64
 {
        u64 end = start + sectors;
 
-       if (end > 64 << ca->mi.btree_bitmap_shift)
+       if (end > 64ULL << ca->mi.btree_bitmap_shift)
                return false;
 
-       for (unsigned bit = sectors >> ca->mi.btree_bitmap_shift;
-            bit << ca->mi.btree_bitmap_shift < end;
+       for (unsigned bit = start >> ca->mi.btree_bitmap_shift;
+            (u64) bit << ca->mi.btree_bitmap_shift < end;
             bit++)
                if (!(ca->mi.btree_allocated_bitmap & BIT_ULL(bit)))
                        return false;
index 8daf80a38d60c6e4fa97b97345d3d4ecb80e7e88..88e214c609bb2b6beab65b604acf1053596f3a8a 100644 (file)
@@ -544,6 +544,7 @@ static void __bch2_fs_free(struct bch_fs *c)
 
        bch2_find_btree_nodes_exit(&c->found_btree_nodes);
        bch2_free_pending_node_rewrites(c);
+       bch2_fs_allocator_background_exit(c);
        bch2_fs_sb_errors_exit(c);
        bch2_fs_counters_exit(c);
        bch2_fs_snapshots_exit(c);
index 940db15d6a939bf93281627e9759904e4a6531f3..b1af7ac430f662aa2b827d0c6550ef6187089352 100644 (file)
@@ -294,16 +294,27 @@ static int thread_with_stdio_fn(void *arg)
        return 0;
 }
 
-int bch2_run_thread_with_stdio(struct thread_with_stdio *thr,
-                              const struct thread_with_stdio_ops *ops)
+void bch2_thread_with_stdio_init(struct thread_with_stdio *thr,
+                                const struct thread_with_stdio_ops *ops)
 {
        stdio_buf_init(&thr->stdio.input);
        stdio_buf_init(&thr->stdio.output);
        thr->ops = ops;
+}
 
+int __bch2_run_thread_with_stdio(struct thread_with_stdio *thr)
+{
        return bch2_run_thread_with_file(&thr->thr, &thread_with_stdio_fops, thread_with_stdio_fn);
 }
 
+int bch2_run_thread_with_stdio(struct thread_with_stdio *thr,
+                              const struct thread_with_stdio_ops *ops)
+{
+       bch2_thread_with_stdio_init(thr, ops);
+
+       return __bch2_run_thread_with_stdio(thr);
+}
+
 int bch2_run_thread_with_stdout(struct thread_with_stdio *thr,
                                const struct thread_with_stdio_ops *ops)
 {
index af54ea8f5b0ff85871c915e275187c29b7b0c6f1..1d63d14d7dcae811a21e49a0cc509407daf7584c 100644 (file)
@@ -63,6 +63,9 @@ struct thread_with_stdio {
        const struct thread_with_stdio_ops      *ops;
 };
 
+void bch2_thread_with_stdio_init(struct thread_with_stdio *,
+                                const struct thread_with_stdio_ops *);
+int __bch2_run_thread_with_stdio(struct thread_with_stdio *);
 int bch2_run_thread_with_stdio(struct thread_with_stdio *,
                               const struct thread_with_stdio_ops *);
 int bch2_run_thread_with_stdout(struct thread_with_stdio *,
index c1e6a5bbeeaffe16b93846d5c8c0e90d4cc37659..58110c96866736ad9bf74b0e40c42e3bd9de81a3 100644 (file)
@@ -2776,20 +2776,14 @@ struct btrfs_data_container *init_data_container(u32 total_bytes)
        size_t alloc_bytes;
 
        alloc_bytes = max_t(size_t, total_bytes, sizeof(*data));
-       data = kvmalloc(alloc_bytes, GFP_KERNEL);
+       data = kvzalloc(alloc_bytes, GFP_KERNEL);
        if (!data)
                return ERR_PTR(-ENOMEM);
 
-       if (total_bytes >= sizeof(*data)) {
+       if (total_bytes >= sizeof(*data))
                data->bytes_left = total_bytes - sizeof(*data);
-               data->bytes_missing = 0;
-       } else {
+       else
                data->bytes_missing = sizeof(*data) - total_bytes;
-               data->bytes_left = 0;
-       }
-
-       data->elem_cnt = 0;
-       data->elem_missed = 0;
 
        return data;
 }
index 445f7716f1e2f70b3f780e7c1f03d020f0eb6346..24a048210b15719db5ae76f09ac114e227ff0ac0 100644 (file)
@@ -817,7 +817,7 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
                                        split->block_len = em->block_len;
                                        split->orig_start = em->orig_start;
                                } else {
-                                       const u64 diff = start + len - em->start;
+                                       const u64 diff = end - em->start;
 
                                        split->block_len = split->len;
                                        split->block_start += diff;
index c65fe5de40220d3b51003bb73b3e6414eaefba08..7fed887e700c4e8e07b6ff7932434a384790b8da 100644 (file)
@@ -1145,13 +1145,13 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
                                   0, *alloc_hint, &ins, 1, 1);
        if (ret) {
                /*
-                * Here we used to try again by going back to non-compressed
-                * path for ENOSPC.  But we can't reserve space even for
-                * compressed size, how could it work for uncompressed size
-                * which requires larger size?  So here we directly go error
-                * path.
+                * We can't reserve contiguous space for the compressed size.
+                * Unlikely, but it's possible that we could have enough
+                * non-contiguous space for the uncompressed size instead.  So
+                * fall back to uncompressed.
                 */
-               goto out_free;
+               submit_uncompressed_range(inode, async_extent, locked_page);
+               goto done;
        }
 
        /* Here we're doing allocation and writeback of the compressed pages */
@@ -1203,7 +1203,6 @@ done:
 out_free_reserve:
        btrfs_dec_block_group_reservations(fs_info, ins.objectid);
        btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
-out_free:
        mapping_set_error(inode->vfs_inode.i_mapping, -EIO);
        extent_clear_unlock_delalloc(inode, start, end,
                                     NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
index 55f3ba6a831ca194e2d8405dbf7caa60fbd81dfc..0493272a7668ed0eb0104284e572503855645ca8 100644 (file)
@@ -3758,15 +3758,43 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
                goto drop_write;
        }
 
-       down_write(&fs_info->subvol_sem);
-
        switch (sa->cmd) {
        case BTRFS_QUOTA_CTL_ENABLE:
        case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA:
+               down_write(&fs_info->subvol_sem);
                ret = btrfs_quota_enable(fs_info, sa);
+               up_write(&fs_info->subvol_sem);
                break;
        case BTRFS_QUOTA_CTL_DISABLE:
+               /*
+                * Lock the cleaner mutex to prevent races with concurrent
+                * relocation, because relocation may be building backrefs for
+                * blocks of the quota root while we are deleting the root. This
+                * is like dropping fs roots of deleted snapshots/subvolumes, we
+                * need the same protection.
+                *
+                * This also prevents races between concurrent tasks trying to
+                * disable quotas, because we will unlock and relock
+                * qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes.
+                *
+                * We take this here because we have the dependency of
+                *
+                * inode_lock -> subvol_sem
+                *
+                * because of rename.  With relocation we can prealloc extents,
+                * so that makes the dependency chain
+                *
+                * cleaner_mutex -> inode_lock -> subvol_sem
+                *
+                * so we must take the cleaner_mutex here before we take the
+                * subvol_sem.  The deadlock can't actually happen, but this
+                * quiets lockdep.
+                */
+               mutex_lock(&fs_info->cleaner_mutex);
+               down_write(&fs_info->subvol_sem);
                ret = btrfs_quota_disable(fs_info);
+               up_write(&fs_info->subvol_sem);
+               mutex_unlock(&fs_info->cleaner_mutex);
                break;
        default:
                ret = -EINVAL;
@@ -3774,7 +3802,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
        }
 
        kfree(sa);
-       up_write(&fs_info->subvol_sem);
 drop_write:
        mnt_drop_write_file(file);
        return ret;
index c96dd66fd0f7224c9a413c4d61d51420c5a9060b..210d9c82e2ae05976fc75325562f25cd7f9dc0b2 100644 (file)
@@ -7,7 +7,7 @@
 
 #ifdef CONFIG_PRINTK
 
-#define STATE_STRING_PREFACE   ": state "
+#define STATE_STRING_PREFACE   " state "
 #define STATE_STRING_BUF_LEN   (sizeof(STATE_STRING_PREFACE) + BTRFS_FS_STATE_COUNT + 1)
 
 /*
index b749ba45da2ba2b13d75695e882ab343dda9439c..c2a42bcde98e0ee4edc4ed171f44800cf53d7284 100644 (file)
@@ -1188,6 +1188,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent(
        ordered->disk_bytenr += len;
        ordered->num_bytes -= len;
        ordered->disk_num_bytes -= len;
+       ordered->ram_bytes -= len;
 
        if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) {
                ASSERT(ordered->bytes_left == 0);
index cf8820ce7aa2979920c6daafc1071c26571ecee6..364acc9bbe730c131a3e4f9b6c8387e6645e300a 100644 (file)
@@ -1342,16 +1342,10 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
        lockdep_assert_held_write(&fs_info->subvol_sem);
 
        /*
-        * Lock the cleaner mutex to prevent races with concurrent relocation,
-        * because relocation may be building backrefs for blocks of the quota
-        * root while we are deleting the root. This is like dropping fs roots
-        * of deleted snapshots/subvolumes, we need the same protection.
-        *
-        * This also prevents races between concurrent tasks trying to disable
-        * quotas, because we will unlock and relock qgroup_ioctl_lock across
-        * BTRFS_FS_QUOTA_ENABLED changes.
+        * Relocation will mess with backrefs, so make sure we have the
+        * cleaner_mutex held to protect us from relocate.
         */
-       mutex_lock(&fs_info->cleaner_mutex);
+       lockdep_assert_held(&fs_info->cleaner_mutex);
 
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (!fs_info->quota_root)
@@ -1373,9 +1367,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
        clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
        btrfs_qgroup_wait_for_completion(fs_info, false);
 
+       /*
+        * We have nothing held here and no trans handle, just return the error
+        * if there is one.
+        */
        ret = flush_reservations(fs_info);
        if (ret)
-               goto out_unlock_cleaner;
+               return ret;
 
        /*
         * 1 For the root item
@@ -1439,9 +1437,6 @@ out:
                btrfs_end_transaction(trans);
        else if (trans)
                ret = btrfs_commit_transaction(trans);
-out_unlock_cleaner:
-       mutex_unlock(&fs_info->cleaner_mutex);
-
        return ret;
 }
 
index fa25004ab04e7b28d73dee024303c0dab4077db6..4b22cfe9a98cb0244288d0a961fc7f0e1c7daf4e 100644 (file)
@@ -1012,6 +1012,7 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
        struct btrfs_fs_info *fs_info = sctx->fs_info;
        int num_copies = btrfs_num_copies(fs_info, stripe->bg->start,
                                          stripe->bg->length);
+       unsigned long repaired;
        int mirror;
        int i;
 
@@ -1078,16 +1079,15 @@ out:
         * Submit the repaired sectors.  For zoned case, we cannot do repair
         * in-place, but queue the bg to be relocated.
         */
-       if (btrfs_is_zoned(fs_info)) {
-               if (!bitmap_empty(&stripe->error_bitmap, stripe->nr_sectors))
+       bitmap_andnot(&repaired, &stripe->init_error_bitmap, &stripe->error_bitmap,
+                     stripe->nr_sectors);
+       if (!sctx->readonly && !bitmap_empty(&repaired, stripe->nr_sectors)) {
+               if (btrfs_is_zoned(fs_info)) {
                        btrfs_repair_one_zone(fs_info, sctx->stripes[0].bg->start);
-       } else if (!sctx->readonly) {
-               unsigned long repaired;
-
-               bitmap_andnot(&repaired, &stripe->init_error_bitmap,
-                             &stripe->error_bitmap, stripe->nr_sectors);
-               scrub_write_sectors(sctx, stripe, repaired, false);
-               wait_scrub_stripe_io(stripe);
+               } else {
+                       scrub_write_sectors(sctx, stripe, repaired, false);
+                       wait_scrub_stripe_io(stripe);
+               }
        }
 
        scrub_stripe_report_errors(sctx, stripe);
index 253cce7ffecfe5acaa81d9b574f8398f5c134300..47b5d301038eed0f040958771b8846ecbd672f65 100644 (file)
@@ -847,6 +847,11 @@ static int test_case_7(struct btrfs_fs_info *fs_info)
                goto out;
        }
 
+       if (em->block_start != SZ_32K + SZ_4K) {
+               test_err("em->block_start is %llu, expected 36K", em->block_start);
+               goto out;
+       }
+
        free_extent_map(em);
 
        read_lock(&em_tree->lock);
index f15591f3e54fa4cd7e92103e17b0ae74eb1a54f9..ef6bd2f4251b523ecfa4e0c31fc3c7eb0d26d332 100644 (file)
@@ -3455,6 +3455,7 @@ again:
                         * alignment and size).
                         */
                        ret = -EUCLEAN;
+                       mutex_unlock(&fs_info->reclaim_bgs_lock);
                        goto error;
                }
 
index 8aff1a724805a67ad3733fbce2127a39e563e01d..62da538d91cbd47cea44f4d021096c6a3a654908 100644 (file)
@@ -151,7 +151,7 @@ static int erofs_fscache_read_io_async(struct fscache_cookie *cookie,
                if (WARN_ON(len == 0))
                        source = NETFS_INVALID_READ;
                if (source != NETFS_READ_FROM_CACHE) {
-                       erofs_err(NULL, "prepare_read failed (source %d)", source);
+                       erofs_err(NULL, "prepare_ondemand_read failed (source %d)", source);
                        return -EIO;
                }
 
index 39c67119f43bfd762aa204a1edcaa77916f5fb76..d28ccfc0352b1ae4728fb25fdf8672bd0ee81789 100644 (file)
@@ -84,13 +84,6 @@ struct erofs_dev_context {
        bool flatdev;
 };
 
-struct erofs_fs_context {
-       struct erofs_mount_opts opt;
-       struct erofs_dev_context *devs;
-       char *fsid;
-       char *domain_id;
-};
-
 /* all filesystem-wide lz4 configurations */
 struct erofs_sb_lz4_info {
        /* # of pages needed for EROFS lz4 rolling decompression */
index c0eb139adb07a8ce852edd56370a79e5760036d9..30b49b2eee53409a0b4b293a4ff579eceb2d5087 100644 (file)
@@ -370,18 +370,18 @@ out:
        return ret;
 }
 
-static void erofs_default_options(struct erofs_fs_context *ctx)
+static void erofs_default_options(struct erofs_sb_info *sbi)
 {
 #ifdef CONFIG_EROFS_FS_ZIP
-       ctx->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
-       ctx->opt.max_sync_decompress_pages = 3;
-       ctx->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
+       sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
+       sbi->opt.max_sync_decompress_pages = 3;
+       sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
 #endif
 #ifdef CONFIG_EROFS_FS_XATTR
-       set_opt(&ctx->opt, XATTR_USER);
+       set_opt(&sbi->opt, XATTR_USER);
 #endif
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
-       set_opt(&ctx->opt, POSIX_ACL);
+       set_opt(&sbi->opt, POSIX_ACL);
 #endif
 }
 
@@ -426,16 +426,16 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
 static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
 {
 #ifdef CONFIG_FS_DAX
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
 
        switch (mode) {
        case EROFS_MOUNT_DAX_ALWAYS:
-               set_opt(&ctx->opt, DAX_ALWAYS);
-               clear_opt(&ctx->opt, DAX_NEVER);
+               set_opt(&sbi->opt, DAX_ALWAYS);
+               clear_opt(&sbi->opt, DAX_NEVER);
                return true;
        case EROFS_MOUNT_DAX_NEVER:
-               set_opt(&ctx->opt, DAX_NEVER);
-               clear_opt(&ctx->opt, DAX_ALWAYS);
+               set_opt(&sbi->opt, DAX_NEVER);
+               clear_opt(&sbi->opt, DAX_ALWAYS);
                return true;
        default:
                DBG_BUGON(1);
@@ -450,7 +450,7 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
 static int erofs_fc_parse_param(struct fs_context *fc,
                                struct fs_parameter *param)
 {
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
        struct fs_parse_result result;
        struct erofs_device_info *dif;
        int opt, ret;
@@ -463,9 +463,9 @@ static int erofs_fc_parse_param(struct fs_context *fc,
        case Opt_user_xattr:
 #ifdef CONFIG_EROFS_FS_XATTR
                if (result.boolean)
-                       set_opt(&ctx->opt, XATTR_USER);
+                       set_opt(&sbi->opt, XATTR_USER);
                else
-                       clear_opt(&ctx->opt, XATTR_USER);
+                       clear_opt(&sbi->opt, XATTR_USER);
 #else
                errorfc(fc, "{,no}user_xattr options not supported");
 #endif
@@ -473,16 +473,16 @@ static int erofs_fc_parse_param(struct fs_context *fc,
        case Opt_acl:
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
                if (result.boolean)
-                       set_opt(&ctx->opt, POSIX_ACL);
+                       set_opt(&sbi->opt, POSIX_ACL);
                else
-                       clear_opt(&ctx->opt, POSIX_ACL);
+                       clear_opt(&sbi->opt, POSIX_ACL);
 #else
                errorfc(fc, "{,no}acl options not supported");
 #endif
                break;
        case Opt_cache_strategy:
 #ifdef CONFIG_EROFS_FS_ZIP
-               ctx->opt.cache_strategy = result.uint_32;
+               sbi->opt.cache_strategy = result.uint_32;
 #else
                errorfc(fc, "compression not supported, cache_strategy ignored");
 #endif
@@ -504,27 +504,27 @@ static int erofs_fc_parse_param(struct fs_context *fc,
                        kfree(dif);
                        return -ENOMEM;
                }
-               down_write(&ctx->devs->rwsem);
-               ret = idr_alloc(&ctx->devs->tree, dif, 0, 0, GFP_KERNEL);
-               up_write(&ctx->devs->rwsem);
+               down_write(&sbi->devs->rwsem);
+               ret = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
+               up_write(&sbi->devs->rwsem);
                if (ret < 0) {
                        kfree(dif->path);
                        kfree(dif);
                        return ret;
                }
-               ++ctx->devs->extra_devices;
+               ++sbi->devs->extra_devices;
                break;
 #ifdef CONFIG_EROFS_FS_ONDEMAND
        case Opt_fsid:
-               kfree(ctx->fsid);
-               ctx->fsid = kstrdup(param->string, GFP_KERNEL);
-               if (!ctx->fsid)
+               kfree(sbi->fsid);
+               sbi->fsid = kstrdup(param->string, GFP_KERNEL);
+               if (!sbi->fsid)
                        return -ENOMEM;
                break;
        case Opt_domain_id:
-               kfree(ctx->domain_id);
-               ctx->domain_id = kstrdup(param->string, GFP_KERNEL);
-               if (!ctx->domain_id)
+               kfree(sbi->domain_id);
+               sbi->domain_id = kstrdup(param->string, GFP_KERNEL);
+               if (!sbi->domain_id)
                        return -ENOMEM;
                break;
 #else
@@ -581,8 +581,7 @@ static const struct export_operations erofs_export_ops = {
 static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 {
        struct inode *inode;
-       struct erofs_sb_info *sbi;
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
        int err;
 
        sb->s_magic = EROFS_SUPER_MAGIC;
@@ -590,19 +589,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
        sb->s_maxbytes = MAX_LFS_FILESIZE;
        sb->s_op = &erofs_sops;
 
-       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-       if (!sbi)
-               return -ENOMEM;
-
-       sb->s_fs_info = sbi;
-       sbi->opt = ctx->opt;
-       sbi->devs = ctx->devs;
-       ctx->devs = NULL;
-       sbi->fsid = ctx->fsid;
-       ctx->fsid = NULL;
-       sbi->domain_id = ctx->domain_id;
-       ctx->domain_id = NULL;
-
        sbi->blkszbits = PAGE_SHIFT;
        if (erofs_is_fscache_mode(sb)) {
                sb->s_blocksize = PAGE_SIZE;
@@ -706,9 +692,9 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 
 static int erofs_fc_get_tree(struct fs_context *fc)
 {
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
 
-       if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && ctx->fsid)
+       if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
                return get_tree_nodev(fc, erofs_fc_fill_super);
 
        return get_tree_bdev(fc, erofs_fc_fill_super);
@@ -718,19 +704,19 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
 {
        struct super_block *sb = fc->root->d_sb;
        struct erofs_sb_info *sbi = EROFS_SB(sb);
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *new_sbi = fc->s_fs_info;
 
        DBG_BUGON(!sb_rdonly(sb));
 
-       if (ctx->fsid || ctx->domain_id)
+       if (new_sbi->fsid || new_sbi->domain_id)
                erofs_info(sb, "ignoring reconfiguration for fsid|domain_id.");
 
-       if (test_opt(&ctx->opt, POSIX_ACL))
+       if (test_opt(&new_sbi->opt, POSIX_ACL))
                fc->sb_flags |= SB_POSIXACL;
        else
                fc->sb_flags &= ~SB_POSIXACL;
 
-       sbi->opt = ctx->opt;
+       sbi->opt = new_sbi->opt;
 
        fc->sb_flags |= SB_RDONLY;
        return 0;
@@ -761,12 +747,15 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs)
 
 static void erofs_fc_free(struct fs_context *fc)
 {
-       struct erofs_fs_context *ctx = fc->fs_private;
+       struct erofs_sb_info *sbi = fc->s_fs_info;
 
-       erofs_free_dev_context(ctx->devs);
-       kfree(ctx->fsid);
-       kfree(ctx->domain_id);
-       kfree(ctx);
+       if (!sbi)
+               return;
+
+       erofs_free_dev_context(sbi->devs);
+       kfree(sbi->fsid);
+       kfree(sbi->domain_id);
+       kfree(sbi);
 }
 
 static const struct fs_context_operations erofs_context_ops = {
@@ -778,38 +767,35 @@ static const struct fs_context_operations erofs_context_ops = {
 
 static int erofs_init_fs_context(struct fs_context *fc)
 {
-       struct erofs_fs_context *ctx;
+       struct erofs_sb_info *sbi;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+       if (!sbi)
                return -ENOMEM;
-       ctx->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
-       if (!ctx->devs) {
-               kfree(ctx);
+
+       sbi->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
+       if (!sbi->devs) {
+               kfree(sbi);
                return -ENOMEM;
        }
-       fc->fs_private = ctx;
+       fc->s_fs_info = sbi;
 
-       idr_init(&ctx->devs->tree);
-       init_rwsem(&ctx->devs->rwsem);
-       erofs_default_options(ctx);
+       idr_init(&sbi->devs->tree);
+       init_rwsem(&sbi->devs->rwsem);
+       erofs_default_options(sbi);
        fc->ops = &erofs_context_ops;
        return 0;
 }
 
 static void erofs_kill_sb(struct super_block *sb)
 {
-       struct erofs_sb_info *sbi;
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
 
-       if (erofs_is_fscache_mode(sb))
+       if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
                kill_anon_super(sb);
        else
                kill_block_super(sb);
 
-       sbi = EROFS_SB(sb);
-       if (!sbi)
-               return;
-
        erofs_free_dev_context(sbi->devs);
        fs_put_dax(sbi->dax_dev, NULL);
        erofs_fscache_unregister_fs(sb);
index 1d5abfdf0f22a626560b9ae6bb95309f8c146be5..fb0628e680c40f16fbee3b1b38b8bfcd70d1c980 100644 (file)
@@ -769,7 +769,7 @@ static int ioctl_getfsuuid(struct file *file, void __user *argp)
        struct fsuuid2 u = { .len = sb->s_uuid_len, };
 
        if (!sb->s_uuid_len)
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
 
        memcpy(&u.uuid[0], &sb->s_uuid, sb->s_uuid_len);
 
@@ -781,7 +781,7 @@ static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
        struct super_block *sb = file_inode(file)->i_sb;
 
        if (!strlen(sb->s_sysfs_name))
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
 
        struct fs_sysfs_path u = {};
 
index 9a0d32e4b422ad09518a6c6143638d0c68fb8b84..267b622d923b1fc63507300831c3163ba38d8a19 100644 (file)
@@ -164,7 +164,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
        enum netfs_how_to_modify howto;
        enum netfs_folio_trace trace;
        unsigned int bdp_flags = (iocb->ki_flags & IOCB_SYNC) ? 0: BDP_ASYNC;
-       ssize_t written = 0, ret;
+       ssize_t written = 0, ret, ret2;
        loff_t i_size, pos = iocb->ki_pos, from, to;
        size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER;
        bool maybe_trouble = false;
@@ -172,15 +172,14 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
        if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) ||
                     iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC))
            ) {
-               if (pos < i_size_read(inode)) {
-                       ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
-                       if (ret < 0) {
-                               goto out;
-                       }
-               }
-
                wbc_attach_fdatawrite_inode(&wbc, mapping->host);
 
+               ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
+               if (ret < 0) {
+                       wbc_detach_inode(&wbc);
+                       goto out;
+               }
+
                wreq = netfs_begin_writethrough(iocb, iter->count);
                if (IS_ERR(wreq)) {
                        wbc_detach_inode(&wbc);
@@ -395,10 +394,12 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
 
 out:
        if (unlikely(wreq)) {
-               ret = netfs_end_writethrough(wreq, iocb);
+               ret2 = netfs_end_writethrough(wreq, iocb);
                wbc_detach_inode(&wbc);
-               if (ret == -EIOCBQUEUED)
-                       return ret;
+               if (ret2 == -EIOCBQUEUED)
+                       return ret2;
+               if (ret == 0)
+                       ret = ret2;
        }
 
        iocb->ki_pos += written;
index c709c296ea9a49e0ccecdae975a5287aea5759fe..acef52ecb1bb7ee01ff448f0c066d4bc1c9df932 100644 (file)
@@ -2429,7 +2429,12 @@ static int nfs_net_init(struct net *net)
        struct nfs_net *nn = net_generic(net, nfs_net_id);
 
        nfs_clients_init(net);
-       rpc_proc_register(net, &nn->rpcstats);
+
+       if (!rpc_proc_register(net, &nn->rpcstats)) {
+               nfs_clients_exit(net);
+               return -ENOMEM;
+       }
+
        return nfs_fs_proc_net_init(net);
 }
 
index 87c9547989f69ec8cb38b73da6868f52a84ff673..e88aca0c6e8ef17a613800f0a321a4c403d9e8e2 100644 (file)
@@ -983,15 +983,7 @@ static struct workqueue_struct *callback_wq;
 static bool nfsd4_queue_cb(struct nfsd4_callback *cb)
 {
        trace_nfsd_cb_queue(cb->cb_clp, cb);
-       return queue_delayed_work(callback_wq, &cb->cb_work, 0);
-}
-
-static void nfsd4_queue_cb_delayed(struct nfsd4_callback *cb,
-                                  unsigned long msecs)
-{
-       trace_nfsd_cb_queue(cb->cb_clp, cb);
-       queue_delayed_work(callback_wq, &cb->cb_work,
-                          msecs_to_jiffies(msecs));
+       return queue_work(callback_wq, &cb->cb_work);
 }
 
 static void nfsd41_cb_inflight_begin(struct nfs4_client *clp)
@@ -1490,7 +1482,7 @@ static void
 nfsd4_run_cb_work(struct work_struct *work)
 {
        struct nfsd4_callback *cb =
-               container_of(work, struct nfsd4_callback, cb_work.work);
+               container_of(work, struct nfsd4_callback, cb_work);
        struct nfs4_client *clp = cb->cb_clp;
        struct rpc_clnt *clnt;
        int flags;
@@ -1502,16 +1494,8 @@ nfsd4_run_cb_work(struct work_struct *work)
 
        clnt = clp->cl_cb_client;
        if (!clnt) {
-               if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
-                       nfsd41_destroy_cb(cb);
-               else {
-                       /*
-                        * XXX: Ideally, we could wait for the client to
-                        *      reconnect, but I haven't figured out how
-                        *      to do that yet.
-                        */
-                       nfsd4_queue_cb_delayed(cb, 25);
-               }
+               /* Callback channel broken, or client killed; give up: */
+               nfsd41_destroy_cb(cb);
                return;
        }
 
@@ -1544,7 +1528,7 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
        cb->cb_msg.rpc_argp = cb;
        cb->cb_msg.rpc_resp = cb;
        cb->cb_ops = ops;
-       INIT_DELAYED_WORK(&cb->cb_work, nfsd4_run_cb_work);
+       INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
        cb->cb_status = 0;
        cb->cb_need_restart = false;
        cb->cb_holds_slot = false;
index 1955481832e03796170ea8f80361bc25cc452ca6..a644460f3a5e7a7e3f8574ab922fef1e94ccb753 100644 (file)
@@ -3515,6 +3515,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        args.exp = exp;
        args.dentry = dentry;
        args.ignore_crossmnt = (ignore_crossmnt != 0);
+       args.acl = NULL;
 
        /*
         * Make a local copy of the attribute bitmap that can be modified.
@@ -3573,7 +3574,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        } else
                args.fhp = fhp;
 
-       args.acl = NULL;
        if (attrmask[0] & FATTR4_WORD0_ACL) {
                err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
                if (err == -EOPNOTSUPP)
index 01c6f344564693dd0987413c0ed116458782a677..2ed0fcf879fd17be57d1d963ad74e864d73315f5 100644 (file)
@@ -68,7 +68,7 @@ struct nfsd4_callback {
        struct nfs4_client *cb_clp;
        struct rpc_message cb_msg;
        const struct nfsd4_callback_ops *cb_ops;
-       struct delayed_work cb_work;
+       struct work_struct cb_work;
        int cb_seq_status;
        int cb_status;
        bool cb_need_restart;
index cdfdf51e55d797e0e5fecc349e2f157f09fea7d8..7bc31d69f680dd996f8503c9d06f0a0b96522e80 100644 (file)
@@ -46,3 +46,12 @@ config NTFS3_FS_POSIX_ACL
          NOTE: this is linux only feature. Windows will ignore these ACLs.
 
          If you don't know what Access Control Lists are, say N.
+
+config NTFS_FS
+       tristate "NTFS file system support"
+       select NTFS3_FS
+       select BUFFER_HEAD
+       select NLS
+       help
+         This config option is here only for backward compatibility. NTFS
+         filesystem is now handled by the NTFS3 driver.
index 5cf3d9decf646b1935517e8b564d807626e60e0f..263635199b60d38a23b98c10f31d2105d832eda4 100644 (file)
@@ -616,4 +616,11 @@ const struct file_operations ntfs_dir_operations = {
        .compat_ioctl   = ntfs_compat_ioctl,
 #endif
 };
+
+const struct file_operations ntfs_legacy_dir_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .iterate_shared = ntfs_readdir,
+       .open           = ntfs_file_open,
+};
 // clang-format on
index 5418662c80d8878afe72a8b8e8ffc43cc834b176..b73969e05052ae8bcd49740057405e3e71c0852a 100644 (file)
@@ -1236,4 +1236,12 @@ const struct file_operations ntfs_file_operations = {
        .fallocate      = ntfs_fallocate,
        .release        = ntfs_file_release,
 };
+
+const struct file_operations ntfs_legacy_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read_iter      = ntfs_file_read_iter,
+       .splice_read    = ntfs_file_splice_read,
+       .open           = ntfs_file_open,
+       .release        = ntfs_file_release,
+};
 // clang-format on
index eb7a8c9fba0183f40096d673473be4dffaa7c4c8..d273eda1cf45d68e90cc56866fe689a629be43b5 100644 (file)
@@ -440,7 +440,10 @@ end_enum:
                 * Usually a hard links to directories are disabled.
                 */
                inode->i_op = &ntfs_dir_inode_operations;
-               inode->i_fop = &ntfs_dir_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_dir_operations;
+               else
+                       inode->i_fop = &ntfs_dir_operations;
                ni->i_valid = 0;
        } else if (S_ISLNK(mode)) {
                ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
@@ -450,7 +453,10 @@ end_enum:
        } else if (S_ISREG(mode)) {
                ni->std_fa &= ~FILE_ATTRIBUTE_DIRECTORY;
                inode->i_op = &ntfs_file_inode_operations;
-               inode->i_fop = &ntfs_file_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_file_operations;
+               else
+                       inode->i_fop = &ntfs_file_operations;
                inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
                                                              &ntfs_aops;
                if (ino != MFT_REC_MFT)
@@ -1614,7 +1620,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
 
        if (S_ISDIR(mode)) {
                inode->i_op = &ntfs_dir_inode_operations;
-               inode->i_fop = &ntfs_dir_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_dir_operations;
+               else
+                       inode->i_fop = &ntfs_dir_operations;
        } else if (S_ISLNK(mode)) {
                inode->i_op = &ntfs_link_inode_operations;
                inode->i_fop = NULL;
@@ -1623,7 +1632,10 @@ struct inode *ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
                inode_nohighmem(inode);
        } else if (S_ISREG(mode)) {
                inode->i_op = &ntfs_file_inode_operations;
-               inode->i_fop = &ntfs_file_operations;
+               if (is_legacy_ntfs(inode->i_sb))
+                       inode->i_fop = &ntfs_legacy_file_operations;
+               else
+                       inode->i_fop = &ntfs_file_operations;
                inode->i_mapping->a_ops = is_compressed(ni) ? &ntfs_aops_cmpr :
                                                              &ntfs_aops;
                init_rwsem(&ni->file.run_lock);
index 79356fd29a14141de34ed006517b153fd9e4872b..5f4d288c6adfb955fb21bc513cae69f80cb61b20 100644 (file)
@@ -493,6 +493,7 @@ struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
                           struct ntfs_fnd *fnd);
 bool dir_is_empty(struct inode *dir);
 extern const struct file_operations ntfs_dir_operations;
+extern const struct file_operations ntfs_legacy_dir_operations;
 
 /* Globals from file.c */
 int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
@@ -507,6 +508,7 @@ long ntfs_compat_ioctl(struct file *filp, u32 cmd, unsigned long arg);
 extern const struct inode_operations ntfs_special_inode_operations;
 extern const struct inode_operations ntfs_file_inode_operations;
 extern const struct file_operations ntfs_file_operations;
+extern const struct file_operations ntfs_legacy_file_operations;
 
 /* Globals from frecord.c */
 void ni_remove_mi(struct ntfs_inode *ni, struct mft_inode *mi);
@@ -1154,4 +1156,6 @@ static inline void le64_sub_cpu(__le64 *var, u64 val)
        *var = cpu_to_le64(le64_to_cpu(*var) - val);
 }
 
+bool is_legacy_ntfs(struct super_block *sb);
+
 #endif /* _LINUX_NTFS3_NTFS_FS_H */
index 9df7c20d066f6125dda2406a0481e4eab300bb80..b26d95a8d3274d061fc2f0dc2ba7f19cd385db8a 100644 (file)
@@ -408,6 +408,12 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
        struct ntfs_mount_options *new_opts = fc->fs_private;
        int ro_rw;
 
+       /* If ntfs3 is used as legacy ntfs enforce read-only mode. */
+       if (is_legacy_ntfs(sb)) {
+               fc->sb_flags |= SB_RDONLY;
+               goto out;
+       }
+
        ro_rw = sb_rdonly(sb) && !(fc->sb_flags & SB_RDONLY);
        if (ro_rw && (sbi->flags & NTFS_FLAGS_NEED_REPLAY)) {
                errorf(fc,
@@ -427,8 +433,6 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
                        fc,
                        "ntfs3: Cannot use different iocharset when remounting!");
 
-       sync_filesystem(sb);
-
        if (ro_rw && (sbi->volume.flags & VOLUME_FLAG_DIRTY) &&
            !new_opts->force) {
                errorf(fc,
@@ -436,6 +440,8 @@ static int ntfs_fs_reconfigure(struct fs_context *fc)
                return -EINVAL;
        }
 
+out:
+       sync_filesystem(sb);
        swap(sbi->options, fc->fs_private);
 
        return 0;
@@ -1613,6 +1619,8 @@ load_root:
        }
 #endif
 
+       if (is_legacy_ntfs(sb))
+               sb->s_flags |= SB_RDONLY;
        return 0;
 
 put_inode_out:
@@ -1730,7 +1738,7 @@ static const struct fs_context_operations ntfs_context_ops = {
  * This will called when mount/remount. We will first initialize
  * options so that if remount we can use just that.
  */
-static int ntfs_init_fs_context(struct fs_context *fc)
+static int __ntfs_init_fs_context(struct fs_context *fc)
 {
        struct ntfs_mount_options *opts;
        struct ntfs_sb_info *sbi;
@@ -1778,6 +1786,11 @@ free_opts:
        return -ENOMEM;
 }
 
+static int ntfs_init_fs_context(struct fs_context *fc)
+{
+       return __ntfs_init_fs_context(fc);
+}
+
 static void ntfs3_kill_sb(struct super_block *sb)
 {
        struct ntfs_sb_info *sbi = sb->s_fs_info;
@@ -1798,6 +1811,50 @@ static struct file_system_type ntfs_fs_type = {
        .kill_sb                = ntfs3_kill_sb,
        .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
 };
+
+#if IS_ENABLED(CONFIG_NTFS_FS)
+static int ntfs_legacy_init_fs_context(struct fs_context *fc)
+{
+       int ret;
+
+       ret = __ntfs_init_fs_context(fc);
+       /* If ntfs3 is used as legacy ntfs enforce read-only mode. */
+       fc->sb_flags |= SB_RDONLY;
+       return ret;
+}
+
+static struct file_system_type ntfs_legacy_fs_type = {
+       .owner                  = THIS_MODULE,
+       .name                   = "ntfs",
+       .init_fs_context        = ntfs_legacy_init_fs_context,
+       .parameters             = ntfs_fs_parameters,
+       .kill_sb                = ntfs3_kill_sb,
+       .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
+};
+MODULE_ALIAS_FS("ntfs");
+
+static inline void register_as_ntfs_legacy(void)
+{
+       int err = register_filesystem(&ntfs_legacy_fs_type);
+       if (err)
+               pr_warn("ntfs3: Failed to register legacy ntfs filesystem driver: %d\n", err);
+}
+
+static inline void unregister_as_ntfs_legacy(void)
+{
+       unregister_filesystem(&ntfs_legacy_fs_type);
+}
+bool is_legacy_ntfs(struct super_block *sb)
+{
+       return sb->s_type == &ntfs_legacy_fs_type;
+}
+#else
+static inline void register_as_ntfs_legacy(void) {}
+static inline void unregister_as_ntfs_legacy(void) {}
+bool is_legacy_ntfs(struct super_block *sb) { return false; }
+#endif
+
+
 // clang-format on
 
 static int __init init_ntfs_fs(void)
@@ -1832,6 +1889,7 @@ static int __init init_ntfs_fs(void)
                goto out1;
        }
 
+       register_as_ntfs_legacy();
        err = register_filesystem(&ntfs_fs_type);
        if (err)
                goto out;
@@ -1849,6 +1907,7 @@ static void __exit exit_ntfs_fs(void)
        rcu_barrier();
        kmem_cache_destroy(ntfs_inode_cachep);
        unregister_filesystem(&ntfs_fs_type);
+       unregister_as_ntfs_legacy();
        ntfs3_exit_bitmap();
 
 #ifdef CONFIG_PROC_FS
index 195b077c0facbf8159b706361172c91a74c8815c..9223856c934b40e66132f99fcccf937cb14cbe6a 100644 (file)
@@ -67,7 +67,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
                 */
                ppage = pfn_to_online_page(pfn);
 
-               if (!ppage || PageSlab(ppage) || page_has_type(ppage))
+               if (!ppage)
                        pcount = 0;
                else
                        pcount = page_mapcount(ppage);
@@ -124,11 +124,8 @@ u64 stable_page_flags(struct page *page)
 
        /*
         * pseudo flags for the well known (anonymous) memory mapped pages
-        *
-        * Note that page->_mapcount is overloaded in SLAB, so the
-        * simple test in page_mapped() is not enough.
         */
-       if (!PageSlab(page) && page_mapped(page))
+       if (page_mapped(page))
                u |= 1 << KPF_MMAP;
        if (PageAnon(page))
                u |= 1 << KPF_ANON;
index d41eedbff674abb0e62e52ae6cc585aaa5d83d77..39277c37185cac3327c0f002849b1f5fc621cd05 100644 (file)
@@ -389,6 +389,7 @@ cifs_alloc_inode(struct super_block *sb)
         * server, can not assume caching of file data or metadata.
         */
        cifs_set_oplock_level(cifs_inode, 0);
+       cifs_inode->lease_granted = false;
        cifs_inode->flags = 0;
        spin_lock_init(&cifs_inode->writers_lock);
        cifs_inode->writers = 0;
@@ -739,6 +740,8 @@ static void cifs_umount_begin(struct super_block *sb)
 
        spin_lock(&cifs_tcp_ses_lock);
        spin_lock(&tcon->tc_lock);
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                           netfs_trace_tcon_ref_see_umount);
        if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
                /* we have other mounts to same share or we have
                   already tried to umount this and woken up
index d6669ce4ae87f07415b150eaffcbf429c4fe74bd..6ff35570db813a533ef9221fad6a7aea99e6d1d2 100644 (file)
@@ -1190,6 +1190,7 @@ struct cifs_fattr {
  */
 struct cifs_tcon {
        struct list_head tcon_list;
+       int debug_id;           /* Debugging for tracing */
        int tc_count;
        struct list_head rlist; /* reconnect list */
        spinlock_t tc_lock;  /* protect anything here that is not protected */
@@ -1276,7 +1277,9 @@ struct cifs_tcon {
        __u32 max_cached_dirs;
 #ifdef CONFIG_CIFS_FSCACHE
        u64 resource_id;                /* server resource id */
+       bool fscache_acquired;          /* T if we've tried acquiring a cookie */
        struct fscache_volume *fscache; /* cookie for share */
+       struct mutex fscache_lock;      /* Prevent regetting a cookie */
 #endif
        struct list_head pending_opens; /* list of incomplete opens */
        struct cached_fids *cfids;
index c0513fbb8a59d4dbafa0738c28038048c785a5ae..c46d418c1c0c3ea065eaa5d4f4f751750df90080 100644 (file)
@@ -882,7 +882,7 @@ typedef struct smb_com_open_rsp {
        __u8 OplockLevel;
        __u16 Fid;
        __le32 CreateAction;
-       struct_group(common_attributes,
+       struct_group_attr(common_attributes, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
@@ -2266,7 +2266,7 @@ typedef struct {
 /* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
 /******************************************************************************/
 typedef struct { /* data block encoding of response to level 263 QPathInfo */
-       struct_group(common_attributes,
+       struct_group_attr(common_attributes, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
index 8e0a348f1f660ebc14498c7fd7d342693411c106..fbc358c09da3b1d7ffc495d0c461e32509f95c1c 100644 (file)
@@ -303,7 +303,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
                     struct TCP_Server_Info *primary_server);
 extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
                                 int from_reconnect);
-extern void cifs_put_tcon(struct cifs_tcon *tcon);
+extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
 
 extern void cifs_release_automount_timer(void);
 
@@ -530,8 +530,9 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
 
 extern struct cifs_ses *sesInfoAlloc(void);
 extern void sesInfoFree(struct cifs_ses *);
-extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled);
-extern void tconInfoFree(struct cifs_tcon *);
+extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled,
+                                        enum smb3_tcon_ref_trace trace);
+extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
 
 extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
                   __u32 *pexpected_response_sequence_number);
@@ -721,8 +722,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
                return options;
 }
 
-struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
-void cifs_put_tcon_super(struct super_block *sb);
 int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
 
 /* Put references of @ses and its children */
index 4e35970681bf052dc343c23935549600f5ce8859..7a16e12f5da879bbbb8ace98a4ec4f30aafec33e 100644 (file)
@@ -1943,7 +1943,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        }
 
        /* no need to setup directory caching on IPC share, so pass in false */
-       tcon = tcon_info_alloc(false);
+       tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc);
        if (tcon == NULL)
                return -ENOMEM;
 
@@ -1960,7 +1960,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 
        if (rc) {
                cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
-               tconInfoFree(tcon);
+               tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
                goto out;
        }
 
@@ -2043,7 +2043,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses)
         * files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
         * SMB2 LOGOFF Request.
         */
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc);
        if (do_logoff) {
                xid = get_xid();
                rc = server->ops->logoff(xid, ses);
@@ -2432,6 +2432,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                        continue;
                }
                ++tcon->tc_count;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_get_find);
                spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
                return tcon;
@@ -2441,7 +2443,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 }
 
 void
-cifs_put_tcon(struct cifs_tcon *tcon)
+cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
 {
        unsigned int xid;
        struct cifs_ses *ses;
@@ -2457,6 +2459,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
        spin_lock(&cifs_tcp_ses_lock);
        spin_lock(&tcon->tc_lock);
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace);
        if (--tcon->tc_count > 0) {
                spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
@@ -2493,7 +2496,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        _free_xid(xid);
 
        cifs_fscache_release_super_cookie(tcon);
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free);
        cifs_put_smb_ses(ses);
 }
 
@@ -2547,7 +2550,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                nohandlecache = ctx->nohandlecache;
        else
                nohandlecache = true;
-       tcon = tcon_info_alloc(!nohandlecache);
+       tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new);
        if (tcon == NULL) {
                rc = -ENOMEM;
                goto out_fail;
@@ -2737,7 +2740,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        return tcon;
 
 out_fail:
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail);
        return ERR_PTR(rc);
 }
 
@@ -2754,7 +2757,7 @@ cifs_put_tlink(struct tcon_link *tlink)
        }
 
        if (!IS_ERR(tlink_tcon(tlink)))
-               cifs_put_tcon(tlink_tcon(tlink));
+               cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink);
        kfree(tlink);
 }
 
@@ -3319,7 +3322,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
        int rc = 0;
 
        if (mnt_ctx->tcon)
-               cifs_put_tcon(mnt_ctx->tcon);
+               cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx);
        else if (mnt_ctx->ses)
                cifs_put_smb_ses(mnt_ctx->ses);
        else if (mnt_ctx->server)
index 6c727d8c31e870ddd0f809db12b21aae76ac80cd..3bbac925d0766b8c456d731355e71b1594b94af3 100644 (file)
@@ -748,6 +748,16 @@ static int smb3_fs_context_validate(struct fs_context *fc)
        /* set the port that we got earlier */
        cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
 
+       if (ctx->uid_specified && !ctx->forceuid_specified) {
+               ctx->override_uid = 1;
+               pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
+       }
+
+       if (ctx->gid_specified && !ctx->forcegid_specified) {
+               ctx->override_gid = 1;
+               pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
+       }
+
        if (ctx->override_uid && !ctx->uid_specified) {
                ctx->override_uid = 0;
                pr_notice("ignoring forceuid mount option specified with no uid= option\n");
@@ -1019,12 +1029,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                        ctx->override_uid = 0;
                else
                        ctx->override_uid = 1;
+               ctx->forceuid_specified = true;
                break;
        case Opt_forcegid:
                if (result.negated)
                        ctx->override_gid = 0;
                else
                        ctx->override_gid = 1;
+               ctx->forcegid_specified = true;
                break;
        case Opt_perm:
                if (result.negated)
index a947bddeba273ea850b3502f07555a19316266a6..cf577ec0dd0ac4a8f5a3131e8ed0c3ce9574a4d7 100644 (file)
@@ -165,6 +165,8 @@ enum cifs_param {
 };
 
 struct smb3_fs_context {
+       bool forceuid_specified;
+       bool forcegid_specified;
        bool uid_specified;
        bool cruid_specified;
        bool gid_specified;
index 340efce8f052951a308329b70b5846d9e57477f5..1a895e6243ee9aaf21fc8405893ce52ed14303a2 100644 (file)
@@ -43,12 +43,23 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
        char *key;
        int ret = -ENOMEM;
 
+       if (tcon->fscache_acquired)
+               return 0;
+
+       mutex_lock(&tcon->fscache_lock);
+       if (tcon->fscache_acquired) {
+               mutex_unlock(&tcon->fscache_lock);
+               return 0;
+       }
+       tcon->fscache_acquired = true;
+
        tcon->fscache = NULL;
        switch (sa->sa_family) {
        case AF_INET:
        case AF_INET6:
                break;
        default:
+               mutex_unlock(&tcon->fscache_lock);
                cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
                return -EINVAL;
        }
@@ -57,6 +68,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
 
        sharename = extract_sharename(tcon->tree_name);
        if (IS_ERR(sharename)) {
+               mutex_unlock(&tcon->fscache_lock);
                cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
                return PTR_ERR(sharename);
        }
@@ -82,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
                }
                pr_err("Cache volume key already in use (%s)\n", key);
                vcookie = NULL;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_see_fscache_collision);
+       } else {
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_see_fscache_okay);
        }
 
        tcon->fscache = vcookie;
@@ -90,6 +107,7 @@ out_2:
        kfree(key);
 out:
        kfree(sharename);
+       mutex_unlock(&tcon->fscache_lock);
        return ret;
 }
 
@@ -102,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
        cifs_fscache_fill_volume_coherency(tcon, &cd);
        fscache_relinquish_volume(tcon->fscache, &cd, false);
        tcon->fscache = NULL;
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                           netfs_trace_tcon_ref_see_fscache_relinq);
 }
 
 void cifs_fscache_get_inode_cookie(struct inode *inode)
index 7d15a1969b818439515b5188e8662a3b8f1276ce..07c468ddb88a89d65f8a48433a055759deb3da26 100644 (file)
@@ -111,9 +111,10 @@ sesInfoFree(struct cifs_ses *buf_to_free)
 }
 
 struct cifs_tcon *
-tcon_info_alloc(bool dir_leases_enabled)
+tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
 {
        struct cifs_tcon *ret_buf;
+       static atomic_t tcon_debug_id;
 
        ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
        if (!ret_buf)
@@ -130,7 +131,8 @@ tcon_info_alloc(bool dir_leases_enabled)
 
        atomic_inc(&tconInfoAllocCount);
        ret_buf->status = TID_NEW;
-       ++ret_buf->tc_count;
+       ret_buf->debug_id = atomic_inc_return(&tcon_debug_id);
+       ret_buf->tc_count = 1;
        spin_lock_init(&ret_buf->tc_lock);
        INIT_LIST_HEAD(&ret_buf->openFileList);
        INIT_LIST_HEAD(&ret_buf->tcon_list);
@@ -139,17 +141,22 @@ tcon_info_alloc(bool dir_leases_enabled)
        atomic_set(&ret_buf->num_local_opens, 0);
        atomic_set(&ret_buf->num_remote_opens, 0);
        ret_buf->stats_from_time = ktime_get_real_seconds();
+#ifdef CONFIG_CIFS_FSCACHE
+       mutex_init(&ret_buf->fscache_lock);
+#endif
+       trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
 
        return ret_buf;
 }
 
 void
-tconInfoFree(struct cifs_tcon *tcon)
+tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
 {
        if (tcon == NULL) {
                cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
                return;
        }
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
        free_cached_dirs(tcon->cfids);
        atomic_dec(&tconInfoAllocCount);
        kfree(tcon->nativeFileSystem);
index cc72be5a93a933b09c45256c2a7d7615478f54c0..677ef6f99a5be407fb9c73baba7918cf5e28244e 100644 (file)
@@ -767,7 +767,7 @@ smb2_cancelled_close_fid(struct work_struct *work)
        if (rc)
                cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
 
-       cifs_put_tcon(tcon);
+       cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid);
        kfree(cancelled);
 }
 
@@ -811,6 +811,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
        if (tcon->tc_count <= 0) {
                struct TCP_Server_Info *server = NULL;
 
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_see_cancelled_close);
                WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
                spin_unlock(&cifs_tcp_ses_lock);
 
@@ -823,12 +825,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
                return 0;
        }
        tcon->tc_count++;
+       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                           netfs_trace_tcon_ref_get_cancelled_close);
        spin_unlock(&cifs_tcp_ses_lock);
 
        rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
                                         persistent_fid, volatile_fid);
        if (rc)
-               cifs_put_tcon(tcon);
+               cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close);
 
        return rc;
 }
@@ -856,7 +860,7 @@ smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *serve
                                         rsp->PersistentFileId,
                                         rsp->VolatileFileId);
        if (rc)
-               cifs_put_tcon(tcon);
+               cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid);
 
        return rc;
 }
index 78c94d0350fe9970fab31564aeba6870d71859bd..28f0b7d19d534b18bff680bb739247889ac7675b 100644 (file)
@@ -2915,8 +2915,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
                tcon = list_first_entry_or_null(&ses->tcon_list,
                                                struct cifs_tcon,
                                                tcon_list);
-               if (tcon)
+               if (tcon) {
                        tcon->tc_count++;
+                       trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                           netfs_trace_tcon_ref_get_dfs_refer);
+               }
                spin_unlock(&cifs_tcp_ses_lock);
        }
 
@@ -2980,6 +2983,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
                /* ipc tcons are not refcounted */
                spin_lock(&cifs_tcp_ses_lock);
                tcon->tc_count--;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_dec_dfs_refer);
                /* tc_count can never go negative */
                WARN_ON(tcon->tc_count < 0);
                spin_unlock(&cifs_tcp_ses_lock);
index 86c647a947ccd1065a8edb0712e113351839b96f..a5efce03cb58e2d995862f8c3b0cc081f8beed5b 100644 (file)
@@ -4138,6 +4138,8 @@ void smb2_reconnect_server(struct work_struct *work)
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
                        if (tcon->need_reconnect || tcon->need_reopen_files) {
                                tcon->tc_count++;
+                               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                                   netfs_trace_tcon_ref_get_reconnect_server);
                                list_add_tail(&tcon->rlist, &tmp_list);
                                tcon_selected = true;
                        }
@@ -4176,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work)
                if (tcon->ipc)
                        cifs_put_smb_ses(tcon->ses);
                else
-                       cifs_put_tcon(tcon);
+                       cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server);
        }
 
        if (!ses_exist)
                goto done;
 
        /* allocate a dummy tcon struct used for reconnect */
-       tcon = tcon_info_alloc(false);
+       tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server);
        if (!tcon) {
                resched = true;
                list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
@@ -4206,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work)
                list_del_init(&ses->rlist);
                cifs_put_smb_ses(ses);
        }
-       tconInfoFree(tcon);
+       tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server);
 
 done:
        cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
index c72a3b2886b7ff6333b19312198eba060d01507f..2fccf0d4f53d2743153f973b9c31c5c700e27170 100644 (file)
@@ -320,7 +320,7 @@ struct smb2_file_reparse_point_info {
 } __packed;
 
 struct smb2_file_network_open_info {
-       struct_group(network_open_info,
+       struct_group_attr(network_open_info, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
index 1d6e54f7879e6a5e8034a90d30471fecc02d2d1b..02135a6053051ee6848f8df90be30fc2c805af6d 100644 (file)
@@ -189,6 +189,8 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32  tid)
                if (tcon->tid != tid)
                        continue;
                ++tcon->tc_count;
+               trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+                                   netfs_trace_tcon_ref_get_find_sess_tcon);
                return tcon;
        }
 
index 5e83cb9da9028e0d15383e6e19413ea1da31e553..604e52876cd2d98e9a86941b0c527dbe6d8abe6a 100644 (file)
@@ -3,6 +3,9 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
+ *
+ * Please use this 3-part article as a reference for writing new tracepoints:
+ * https://lwn.net/Articles/379903/
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM cifs
 #include <linux/inet.h>
 
 /*
- * Please use this 3-part article as a reference for writing new tracepoints:
- * https://lwn.net/Articles/379903/
+ * Specify enums for tracing information.
+ */
+#define smb3_tcon_ref_traces                                         \
+       EM(netfs_trace_tcon_ref_dec_dfs_refer,          "DEC DfsRef") \
+       EM(netfs_trace_tcon_ref_free,                   "FRE       ") \
+       EM(netfs_trace_tcon_ref_free_fail,              "FRE Fail  ") \
+       EM(netfs_trace_tcon_ref_free_ipc,               "FRE Ipc   ") \
+       EM(netfs_trace_tcon_ref_free_ipc_fail,          "FRE Ipc-F ") \
+       EM(netfs_trace_tcon_ref_free_reconnect_server,  "FRE Reconn") \
+       EM(netfs_trace_tcon_ref_get_cancelled_close,    "GET Cn-Cls") \
+       EM(netfs_trace_tcon_ref_get_dfs_refer,          "GET DfsRef") \
+       EM(netfs_trace_tcon_ref_get_find,               "GET Find  ") \
+       EM(netfs_trace_tcon_ref_get_find_sess_tcon,     "GET FndSes") \
+       EM(netfs_trace_tcon_ref_get_reconnect_server,   "GET Reconn") \
+       EM(netfs_trace_tcon_ref_new,                    "NEW       ") \
+       EM(netfs_trace_tcon_ref_new_ipc,                "NEW Ipc   ") \
+       EM(netfs_trace_tcon_ref_new_reconnect_server,   "NEW Reconn") \
+       EM(netfs_trace_tcon_ref_put_cancelled_close,    "PUT Cn-Cls") \
+       EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
+       EM(netfs_trace_tcon_ref_put_cancelled_mid,      "PUT Cn-Mid") \
+       EM(netfs_trace_tcon_ref_put_mnt_ctx,            "PUT MntCtx") \
+       EM(netfs_trace_tcon_ref_put_reconnect_server,   "PUT Reconn") \
+       EM(netfs_trace_tcon_ref_put_tlink,              "PUT Tlink ") \
+       EM(netfs_trace_tcon_ref_see_cancelled_close,    "SEE Cn-Cls") \
+       EM(netfs_trace_tcon_ref_see_fscache_collision,  "SEE FV-CO!") \
+       EM(netfs_trace_tcon_ref_see_fscache_okay,       "SEE FV-Ok ") \
+       EM(netfs_trace_tcon_ref_see_fscache_relinq,     "SEE FV-Rlq") \
+       E_(netfs_trace_tcon_ref_see_umount,             "SEE Umount")
+
+#undef EM
+#undef E_
+
+/*
+ * Define those tracing enums.
+ */
+#ifndef __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
+#define __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
+
+#define EM(a, b) a,
+#define E_(a, b) a
+
+enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte);
+
+#undef EM
+#undef E_
+#endif
+
+/*
+ * Export enum symbols via userspace.
+ */
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define E_(a, b) TRACE_DEFINE_ENUM(a);
+
+smb3_tcon_ref_traces;
+
+#undef EM
+#undef E_
+
+/*
+ * Now redefine the EM() and E_() macros to map the enums to the strings that
+ * will be printed in the output.
  */
+#define EM(a, b)       { a, b },
+#define E_(a, b)       { a, b }
 
 /* For logging errors in read or write */
 DECLARE_EVENT_CLASS(smb3_rw_err_class,
@@ -1125,6 +1189,30 @@ DEFINE_SMB3_CREDIT_EVENT(waitff_credits);
 DEFINE_SMB3_CREDIT_EVENT(overflow_credits);
 DEFINE_SMB3_CREDIT_EVENT(set_credits);
 
+
+TRACE_EVENT(smb3_tcon_ref,
+           TP_PROTO(unsigned int tcon_debug_id, int ref,
+                    enum smb3_tcon_ref_trace trace),
+           TP_ARGS(tcon_debug_id, ref, trace),
+           TP_STRUCT__entry(
+                   __field(unsigned int,               tcon)
+                   __field(int,                        ref)
+                   __field(enum smb3_tcon_ref_trace,   trace)
+                            ),
+           TP_fast_assign(
+                   __entry->tcon       = tcon_debug_id;
+                   __entry->ref        = ref;
+                   __entry->trace      = trace;
+                          ),
+           TP_printk("TC=%08x %s r=%u",
+                     __entry->tcon,
+                     __print_symbolic(__entry->trace, smb3_tcon_ref_traces),
+                     __entry->ref)
+           );
+
+
+#undef EM
+#undef E_
 #endif /* _CIFS_TRACE_H */
 
 #undef TRACE_INCLUDE_PATH
index 994d70193432978de213a19a0f9933bd90e63671..ddf1a3aafee5c6f1e4f9c6ed4db54c48fcc8a84a 100644 (file)
@@ -909,12 +909,15 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
                        list_del_init(&mid->qhead);
                        mid->mid_flags |= MID_DELETED;
                }
+               spin_unlock(&server->mid_lock);
                cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
                         __func__, mid->mid, mid->mid_state);
                rc = -EIO;
+               goto sync_mid_done;
        }
        spin_unlock(&server->mid_lock);
 
+sync_mid_done:
        release_mid(mid);
        return rc;
 }
@@ -1057,9 +1060,11 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
                index = (uint)atomic_inc_return(&ses->chan_seq);
                index %= ses->chan_count;
        }
+
+       server = ses->chans[index].server;
        spin_unlock(&ses->chan_lock);
 
-       return ses->chans[index].server;
+       return server;
 }
 
 int
index 1b594307c9d5a01e0b9d62b47b331dbd31c6dfaf..202ff912815604bd7b22700fc5ff598dd0a769ac 100644 (file)
@@ -711,7 +711,7 @@ struct smb2_close_rsp {
        __le16 StructureSize; /* 60 */
        __le16 Flags;
        __le32 Reserved;
-       struct_group(network_open_info,
+       struct_group_attr(network_open_info, __packed,
                __le64 CreationTime;
                __le64 LastAccessTime;
                __le64 LastWriteTime;
index 686b321c5a8bb5f0a1189023a3311e85aaf84c9e..f4e55199938d58023672fcd3006f7e97502fa6a5 100644 (file)
@@ -340,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS {
 /*
  * Share config flags.
  */
-#define KSMBD_SHARE_FLAG_INVALID               (0)
-#define KSMBD_SHARE_FLAG_AVAILABLE             BIT(0)
-#define KSMBD_SHARE_FLAG_BROWSEABLE            BIT(1)
-#define KSMBD_SHARE_FLAG_WRITEABLE             BIT(2)
-#define KSMBD_SHARE_FLAG_READONLY              BIT(3)
-#define KSMBD_SHARE_FLAG_GUEST_OK              BIT(4)
-#define KSMBD_SHARE_FLAG_GUEST_ONLY            BIT(5)
-#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS       BIT(6)
-#define KSMBD_SHARE_FLAG_OPLOCKS               BIT(7)
-#define KSMBD_SHARE_FLAG_PIPE                  BIT(8)
-#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES                BIT(9)
-#define KSMBD_SHARE_FLAG_INHERIT_OWNER         BIT(10)
-#define KSMBD_SHARE_FLAG_STREAMS               BIT(11)
-#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS       BIT(12)
-#define KSMBD_SHARE_FLAG_ACL_XATTR             BIT(13)
-#define KSMBD_SHARE_FLAG_UPDATE                        BIT(14)
-#define KSMBD_SHARE_FLAG_CROSSMNT              BIT(15)
+#define KSMBD_SHARE_FLAG_INVALID                       (0)
+#define KSMBD_SHARE_FLAG_AVAILABLE                     BIT(0)
+#define KSMBD_SHARE_FLAG_BROWSEABLE                    BIT(1)
+#define KSMBD_SHARE_FLAG_WRITEABLE                     BIT(2)
+#define KSMBD_SHARE_FLAG_READONLY                      BIT(3)
+#define KSMBD_SHARE_FLAG_GUEST_OK                      BIT(4)
+#define KSMBD_SHARE_FLAG_GUEST_ONLY                    BIT(5)
+#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS               BIT(6)
+#define KSMBD_SHARE_FLAG_OPLOCKS                       BIT(7)
+#define KSMBD_SHARE_FLAG_PIPE                          BIT(8)
+#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES                        BIT(9)
+#define KSMBD_SHARE_FLAG_INHERIT_OWNER                 BIT(10)
+#define KSMBD_SHARE_FLAG_STREAMS                       BIT(11)
+#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS               BIT(12)
+#define KSMBD_SHARE_FLAG_ACL_XATTR                     BIT(13)
+#define KSMBD_SHARE_FLAG_UPDATE                                BIT(14)
+#define KSMBD_SHARE_FLAG_CROSSMNT                      BIT(15)
+#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY       BIT(16)
 
 /*
  * Tree connect request flags.
index c0788188aa82fa39211f0be694a13f925408580c..c67fbc8d6683ef957b2b39601031c0aa25d22ac7 100644 (file)
@@ -167,20 +167,17 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
        int rc;
        bool is_chained = false;
 
-       if (conn->ops->allocate_rsp_buf(work))
-               return;
-
        if (conn->ops->is_transform_hdr &&
            conn->ops->is_transform_hdr(work->request_buf)) {
                rc = conn->ops->decrypt_req(work);
-               if (rc < 0) {
-                       conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
-                       goto send;
-               }
-
+               if (rc < 0)
+                       return;
                work->encrypted = true;
        }
 
+       if (conn->ops->allocate_rsp_buf(work))
+               return;
+
        rc = conn->ops->init_rsp_hdr(work);
        if (rc) {
                /* either uid or tid is not correct */
index 5723bbf372d7cc93c9e1b2dbdd5082c2824f85f8..355824151c2d88194b7013c2ffeabc074fbe6b87 100644 (file)
@@ -535,6 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
        if (cmd == SMB2_QUERY_INFO_HE) {
                struct smb2_query_info_req *req;
 
+               if (get_rfc1002_len(work->request_buf) <
+                   offsetof(struct smb2_query_info_req, OutputBufferLength))
+                       return -EINVAL;
+
                req = smb2_get_msg(work->request_buf);
                if ((req->InfoType == SMB2_O_INFO_FILE &&
                     (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
@@ -1984,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work)
        write_unlock(&sess->tree_conns_lock);
        rsp->StructureSize = cpu_to_le16(16);
 out_err1:
-       rsp->Capabilities = 0;
+       if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
+           test_share_config_flag(share,
+                                  KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
+               rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
+       else
+               rsp->Capabilities = 0;
        rsp->Reserved = 0;
        /* default manual caching */
        rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
@@ -3498,7 +3507,9 @@ int smb2_open(struct ksmbd_work *work)
        memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
 
        if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) {
-               if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent)
+               if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent &&
+                   test_share_config_flag(work->tcon->share_conf,
+                                          KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
                        fp->is_persistent = true;
                else
                        fp->is_durable = true;
index 22f0f3db3ac92df2447e6b62646447d5ca1895a0..51b1b0bed616eea98a19e5e470f6aa929c8884b5 100644 (file)
@@ -754,10 +754,15 @@ retry:
                goto out4;
        }
 
+       /*
+        * explicitly handle file overwrite case, for compatibility with
+        * filesystems that may not support rename flags (e.g: fuse)
+        */
        if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
                err = -EEXIST;
                goto out4;
        }
+       flags &= ~(RENAME_NOREPLACE);
 
        if (old_child == trap) {
                err = -EINVAL;
index 894c6ca1e5002015b378ad8d6ec598de44c25ebe..a878cea70f4c9077612e0eefea159746e729fe5c 100644 (file)
@@ -37,6 +37,7 @@ static DEFINE_MUTEX(eventfs_mutex);
 
 struct eventfs_root_inode {
        struct eventfs_inode            ei;
+       struct inode                    *parent_inode;
        struct dentry                   *events_dir;
 };
 
@@ -68,11 +69,25 @@ enum {
        EVENTFS_SAVE_MODE       = BIT(16),
        EVENTFS_SAVE_UID        = BIT(17),
        EVENTFS_SAVE_GID        = BIT(18),
-       EVENTFS_TOPLEVEL        = BIT(19),
 };
 
 #define EVENTFS_MODE_MASK      (EVENTFS_SAVE_MODE - 1)
 
+static void free_ei_rcu(struct rcu_head *rcu)
+{
+       struct eventfs_inode *ei = container_of(rcu, struct eventfs_inode, rcu);
+       struct eventfs_root_inode *rei;
+
+       kfree(ei->entry_attrs);
+       kfree_const(ei->name);
+       if (ei->is_events) {
+               rei = get_root_inode(ei);
+               kfree(rei);
+       } else {
+               kfree(ei);
+       }
+}
+
 /*
  * eventfs_inode reference count management.
  *
@@ -84,18 +99,17 @@ enum {
 static void release_ei(struct kref *ref)
 {
        struct eventfs_inode *ei = container_of(ref, struct eventfs_inode, kref);
-       struct eventfs_root_inode *rei;
+       const struct eventfs_entry *entry;
 
        WARN_ON_ONCE(!ei->is_freed);
 
-       kfree(ei->entry_attrs);
-       kfree_const(ei->name);
-       if (ei->is_events) {
-               rei = get_root_inode(ei);
-               kfree_rcu(rei, ei.rcu);
-       } else {
-               kfree_rcu(ei, rcu);
+       for (int i = 0; i < ei->nr_entries; i++) {
+               entry = &ei->entries[i];
+               if (entry->release)
+                       entry->release(entry->name, ei->data);
        }
+
+       call_rcu(&ei->rcu, free_ei_rcu);
 }
 
 static inline void put_ei(struct eventfs_inode *ei)
@@ -112,6 +126,18 @@ static inline void free_ei(struct eventfs_inode *ei)
        }
 }
 
+/*
+ * Called when creation of an ei fails, do not call release() functions.
+ */
+static inline void cleanup_ei(struct eventfs_inode *ei)
+{
+       if (ei) {
+               /* Set nr_entries to 0 to prevent release() function being called */
+               ei->nr_entries = 0;
+               free_ei(ei);
+       }
+}
+
 static inline struct eventfs_inode *get_ei(struct eventfs_inode *ei)
 {
        if (ei)
@@ -181,21 +207,7 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
         * determined by the parent directory.
         */
        if (dentry->d_inode->i_mode & S_IFDIR) {
-               /*
-                * The events directory dentry is never freed, unless its
-                * part of an instance that is deleted. It's attr is the
-                * default for its child files and directories.
-                * Do not update it. It's not used for its own mode or ownership.
-                */
-               if (ei->is_events) {
-                       /* But it still needs to know if it was modified */
-                       if (iattr->ia_valid & ATTR_UID)
-                               ei->attr.mode |= EVENTFS_SAVE_UID;
-                       if (iattr->ia_valid & ATTR_GID)
-                               ei->attr.mode |= EVENTFS_SAVE_GID;
-               } else {
-                       update_attr(&ei->attr, iattr);
-               }
+               update_attr(&ei->attr, iattr);
 
        } else {
                name = dentry->d_name.name;
@@ -213,18 +225,25 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
        return ret;
 }
 
-static void update_top_events_attr(struct eventfs_inode *ei, struct super_block *sb)
+static void update_events_attr(struct eventfs_inode *ei, struct super_block *sb)
 {
-       struct inode *root;
+       struct eventfs_root_inode *rei;
+       struct inode *parent;
 
-       /* Only update if the "events" was on the top level */
-       if (!ei || !(ei->attr.mode & EVENTFS_TOPLEVEL))
-               return;
+       rei = get_root_inode(ei);
 
-       /* Get the tracefs root inode. */
-       root = d_inode(sb->s_root);
-       ei->attr.uid = root->i_uid;
-       ei->attr.gid = root->i_gid;
+       /* Use the parent inode permissions unless root set its permissions */
+       parent = rei->parent_inode;
+
+       if (rei->ei.attr.mode & EVENTFS_SAVE_UID)
+               ei->attr.uid = rei->ei.attr.uid;
+       else
+               ei->attr.uid = parent->i_uid;
+
+       if (rei->ei.attr.mode & EVENTFS_SAVE_GID)
+               ei->attr.gid = rei->ei.attr.gid;
+       else
+               ei->attr.gid = parent->i_gid;
 }
 
 static void set_top_events_ownership(struct inode *inode)
@@ -233,10 +252,10 @@ static void set_top_events_ownership(struct inode *inode)
        struct eventfs_inode *ei = ti->private;
 
        /* The top events directory doesn't get automatically updated */
-       if (!ei || !ei->is_events || !(ei->attr.mode & EVENTFS_TOPLEVEL))
+       if (!ei || !ei->is_events)
                return;
 
-       update_top_events_attr(ei, inode->i_sb);
+       update_events_attr(ei, inode->i_sb);
 
        if (!(ei->attr.mode & EVENTFS_SAVE_UID))
                inode->i_uid = ei->attr.uid;
@@ -265,7 +284,7 @@ static int eventfs_permission(struct mnt_idmap *idmap,
        return generic_permission(idmap, inode, mask);
 }
 
-static const struct inode_operations eventfs_root_dir_inode_operations = {
+static const struct inode_operations eventfs_dir_inode_operations = {
        .lookup         = eventfs_root_lookup,
        .setattr        = eventfs_set_attr,
        .getattr        = eventfs_get_attr,
@@ -282,6 +301,35 @@ static const struct file_operations eventfs_file_operations = {
        .llseek         = generic_file_llseek,
 };
 
+/*
+ * On a remount of tracefs, if UID or GID options are set, then
+ * the mount point inode permissions should be used.
+ * Reset the saved permission flags appropriately.
+ */
+void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid)
+{
+       struct eventfs_inode *ei = ti->private;
+
+       if (!ei)
+               return;
+
+       if (update_uid)
+               ei->attr.mode &= ~EVENTFS_SAVE_UID;
+
+       if (update_gid)
+               ei->attr.mode &= ~EVENTFS_SAVE_GID;
+
+       if (!ei->entry_attrs)
+               return;
+
+       for (int i = 0; i < ei->nr_entries; i++) {
+               if (update_uid)
+                       ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_UID;
+               if (update_gid)
+                       ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_GID;
+       }
+}
+
 /* Return the evenfs_inode of the "events" directory */
 static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
 {
@@ -304,7 +352,7 @@ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
                // Walk upwards until you find the events inode
        } while (!ei->is_events);
 
-       update_top_events_attr(ei, dentry->d_sb);
+       update_events_attr(ei, dentry->d_sb);
 
        return ei;
 }
@@ -410,7 +458,7 @@ static struct dentry *lookup_dir_entry(struct dentry *dentry,
        update_inode_attr(dentry, inode, &ei->attr,
                          S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
 
-       inode->i_op = &eventfs_root_dir_inode_operations;
+       inode->i_op = &eventfs_dir_inode_operations;
        inode->i_fop = &eventfs_file_operations;
 
        /* All directories will have the same inode number */
@@ -734,7 +782,7 @@ struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode
 
        /* Was the parent freed? */
        if (list_empty(&ei->list)) {
-               free_ei(ei);
+               cleanup_ei(ei);
                ei = NULL;
        }
        return ei;
@@ -781,6 +829,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
        // Note: we have a ref to the dentry from tracefs_start_creating()
        rei = get_root_inode(ei);
        rei->events_dir = dentry;
+       rei->parent_inode = d_inode(dentry->d_sb->s_root);
 
        ei->entries = entries;
        ei->nr_entries = size;
@@ -790,29 +839,26 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
        uid = d_inode(dentry->d_parent)->i_uid;
        gid = d_inode(dentry->d_parent)->i_gid;
 
-       /*
-        * If the events directory is of the top instance, then parent
-        * is NULL. Set the attr.mode to reflect this and its permissions will
-        * default to the tracefs root dentry.
-        */
-       if (!parent)
-               ei->attr.mode = EVENTFS_TOPLEVEL;
-
-       /* This is used as the default ownership of the files and directories */
        ei->attr.uid = uid;
        ei->attr.gid = gid;
 
+       /*
+        * When the "events" directory is created, it takes on the
+        * permissions of its parent. But can be reset on remount.
+        */
+       ei->attr.mode |= EVENTFS_SAVE_UID | EVENTFS_SAVE_GID;
+
        INIT_LIST_HEAD(&ei->children);
        INIT_LIST_HEAD(&ei->list);
 
        ti = get_tracefs(inode);
-       ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE;
+       ti->flags |= TRACEFS_EVENT_INODE;
        ti->private = ei;
 
        inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
        inode->i_uid = uid;
        inode->i_gid = gid;
-       inode->i_op = &eventfs_root_dir_inode_operations;
+       inode->i_op = &eventfs_dir_inode_operations;
        inode->i_fop = &eventfs_file_operations;
 
        dentry->d_fsdata = get_ei(ei);
@@ -835,7 +881,7 @@ struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry
        return ei;
 
  fail:
-       free_ei(ei);
+       cleanup_ei(ei);
        tracefs_failed_creating(dentry);
        return ERR_PTR(-ENOMEM);
 }
index 5545e6bf7d26c4300b70802f40d1f796263624df..417c840e6403338f0708640527442c87bfe492e7 100644 (file)
@@ -30,20 +30,47 @@ static struct vfsmount *tracefs_mount;
 static int tracefs_mount_count;
 static bool tracefs_registered;
 
+/*
+ * Keep track of all tracefs_inodes in order to update their
+ * flags if necessary on a remount.
+ */
+static DEFINE_SPINLOCK(tracefs_inode_lock);
+static LIST_HEAD(tracefs_inodes);
+
 static struct inode *tracefs_alloc_inode(struct super_block *sb)
 {
        struct tracefs_inode *ti;
+       unsigned long flags;
 
        ti = kmem_cache_alloc(tracefs_inode_cachep, GFP_KERNEL);
        if (!ti)
                return NULL;
 
+       spin_lock_irqsave(&tracefs_inode_lock, flags);
+       list_add_rcu(&ti->list, &tracefs_inodes);
+       spin_unlock_irqrestore(&tracefs_inode_lock, flags);
+
        return &ti->vfs_inode;
 }
 
+static void tracefs_free_inode_rcu(struct rcu_head *rcu)
+{
+       struct tracefs_inode *ti;
+
+       ti = container_of(rcu, struct tracefs_inode, rcu);
+       kmem_cache_free(tracefs_inode_cachep, ti);
+}
+
 static void tracefs_free_inode(struct inode *inode)
 {
-       kmem_cache_free(tracefs_inode_cachep, get_tracefs(inode));
+       struct tracefs_inode *ti = get_tracefs(inode);
+       unsigned long flags;
+
+       spin_lock_irqsave(&tracefs_inode_lock, flags);
+       list_del_rcu(&ti->list);
+       spin_unlock_irqrestore(&tracefs_inode_lock, flags);
+
+       call_rcu(&ti->rcu, tracefs_free_inode_rcu);
 }
 
 static ssize_t default_read_file(struct file *file, char __user *buf,
@@ -153,16 +180,39 @@ static void set_tracefs_inode_owner(struct inode *inode)
 {
        struct tracefs_inode *ti = get_tracefs(inode);
        struct inode *root_inode = ti->private;
+       kuid_t uid;
+       kgid_t gid;
+
+       uid = root_inode->i_uid;
+       gid = root_inode->i_gid;
+
+       /*
+        * If the root is not the mount point, then check the root's
+        * permissions. If it was never set, then default to the
+        * mount point.
+        */
+       if (root_inode != d_inode(root_inode->i_sb->s_root)) {
+               struct tracefs_inode *rti;
+
+               rti = get_tracefs(root_inode);
+               root_inode = d_inode(root_inode->i_sb->s_root);
+
+               if (!(rti->flags & TRACEFS_UID_PERM_SET))
+                       uid = root_inode->i_uid;
+
+               if (!(rti->flags & TRACEFS_GID_PERM_SET))
+                       gid = root_inode->i_gid;
+       }
 
        /*
         * If this inode has never been referenced, then update
         * the permissions to the superblock.
         */
        if (!(ti->flags & TRACEFS_UID_PERM_SET))
-               inode->i_uid = root_inode->i_uid;
+               inode->i_uid = uid;
 
        if (!(ti->flags & TRACEFS_GID_PERM_SET))
-               inode->i_gid = root_inode->i_gid;
+               inode->i_gid = gid;
 }
 
 static int tracefs_permission(struct mnt_idmap *idmap,
@@ -313,6 +363,8 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
        struct tracefs_fs_info *fsi = sb->s_fs_info;
        struct inode *inode = d_inode(sb->s_root);
        struct tracefs_mount_opts *opts = &fsi->mount_opts;
+       struct tracefs_inode *ti;
+       bool update_uid, update_gid;
        umode_t tmp_mode;
 
        /*
@@ -332,6 +384,25 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
        if (!remount || opts->opts & BIT(Opt_gid))
                inode->i_gid = opts->gid;
 
+       if (remount && (opts->opts & BIT(Opt_uid) || opts->opts & BIT(Opt_gid))) {
+
+               update_uid = opts->opts & BIT(Opt_uid);
+               update_gid = opts->opts & BIT(Opt_gid);
+
+               rcu_read_lock();
+               list_for_each_entry_rcu(ti, &tracefs_inodes, list) {
+                       if (update_uid)
+                               ti->flags &= ~TRACEFS_UID_PERM_SET;
+
+                       if (update_gid)
+                               ti->flags &= ~TRACEFS_GID_PERM_SET;
+
+                       if (ti->flags & TRACEFS_EVENT_INODE)
+                               eventfs_remount(ti, update_uid, update_gid);
+               }
+               rcu_read_unlock();
+       }
+
        return 0;
 }
 
@@ -398,7 +469,22 @@ static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags)
        return !(ei && ei->is_freed);
 }
 
+static void tracefs_d_iput(struct dentry *dentry, struct inode *inode)
+{
+       struct tracefs_inode *ti = get_tracefs(inode);
+
+       /*
+        * This inode is being freed and cannot be used for
+        * eventfs. Clear the flag so that it doesn't call into
+        * eventfs during the remount flag updates. The eventfs_inode
+        * gets freed after an RCU cycle, so the content will still
+        * be safe if the iteration is going on now.
+        */
+       ti->flags &= ~TRACEFS_EVENT_INODE;
+}
+
 static const struct dentry_operations tracefs_dentry_operations = {
+       .d_iput = tracefs_d_iput,
        .d_revalidate = tracefs_d_revalidate,
        .d_release = tracefs_d_release,
 };
index 15c26f9aaad4df1fe3d509061ba6cd3b437ae76e..f704d8348357ed8f8a2a11195718b716e7277244 100644 (file)
@@ -4,15 +4,18 @@
 
 enum {
        TRACEFS_EVENT_INODE             = BIT(1),
-       TRACEFS_EVENT_TOP_INODE         = BIT(2),
-       TRACEFS_GID_PERM_SET            = BIT(3),
-       TRACEFS_UID_PERM_SET            = BIT(4),
-       TRACEFS_INSTANCE_INODE          = BIT(5),
+       TRACEFS_GID_PERM_SET            = BIT(2),
+       TRACEFS_UID_PERM_SET            = BIT(3),
+       TRACEFS_INSTANCE_INODE          = BIT(4),
 };
 
 struct tracefs_inode {
-       struct inode            vfs_inode;
+       union {
+               struct inode            vfs_inode;
+               struct rcu_head         rcu;
+       };
        /* The below gets initialized with memset_after(ti, 0, vfs_inode) */
+       struct list_head        list;
        unsigned long           flags;
        void                    *private;
 };
@@ -73,6 +76,7 @@ struct dentry *tracefs_end_creating(struct dentry *dentry);
 struct dentry *tracefs_failed_creating(struct dentry *dentry);
 struct inode *tracefs_get_inode(struct super_block *sb);
 
+void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid);
 void eventfs_d_release(struct dentry *dentry);
 
 #endif /* _TRACEFS_INTERNAL_H */
index 272e4e79e15c48db487feba3b7e6103e71b21e8d..861c3bfc5f1700db69d90168c239a935ebad76ca 100644 (file)
@@ -221,7 +221,18 @@ void cpuhp_report_idle_dead(void);
 static inline void cpuhp_report_idle_dead(void) { }
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
+#ifdef CONFIG_CPU_MITIGATIONS
 extern bool cpu_mitigations_off(void);
 extern bool cpu_mitigations_auto_nosmt(void);
+#else
+static inline bool cpu_mitigations_off(void)
+{
+       return true;
+}
+static inline bool cpu_mitigations_auto_nosmt(void)
+{
+       return false;
+}
+#endif
 
 #endif /* _LINUX_CPU_H_ */
index 224645f17c333b2311573197a28b41701eb35f92..297231854ada51ebeb5a8976db22e0e4702e5adb 100644 (file)
@@ -607,6 +607,31 @@ static inline void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr,
        eth_hw_addr_set(dev, addr);
 }
 
+/**
+ * eth_skb_pkt_type - Assign packet type if destination address does not match
+ * @skb: Assigned a packet type if address does not match @dev address
+ * @dev: Network device used to compare packet address against
+ *
+ * If the destination MAC address of the packet does not match the network
+ * device address, assign an appropriate packet type.
+ */
+static inline void eth_skb_pkt_type(struct sk_buff *skb,
+                                   const struct net_device *dev)
+{
+       const struct ethhdr *eth = eth_hdr(skb);
+
+       if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr))) {
+               if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
+                       if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
+                               skb->pkt_type = PACKET_BROADCAST;
+                       else
+                               skb->pkt_type = PACKET_MULTICAST;
+               } else {
+                       skb->pkt_type = PACKET_OTHERHOST;
+               }
+       }
+}
+
 /**
  * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
  * @skb: Buffer to pad
index c99bc3df2d28e35f73b21d62ca50f4a53c515e1b..219ee7a76874439e9a2ecda7a402a7a9e741e0be 100644 (file)
@@ -963,6 +963,7 @@ bool bpf_jit_supports_far_kfunc_call(void);
 bool bpf_jit_supports_exceptions(void);
 bool bpf_jit_supports_ptr_xchg(void);
 bool bpf_jit_supports_arena(void);
+u64 bpf_arch_uaddress_limit(void);
 void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie);
 bool bpf_helper_changes_pkt_data(void *func);
 
index 5c28298a98bec8146e8b2dad45aa946aff780f03..366243ee96096d6fc134ae73a6d3209c8e4df4a1 100644 (file)
@@ -10,6 +10,7 @@
 #define __QCOM_QSEECOM_H
 
 #include <linux/auxiliary_bus.h>
+#include <linux/dma-mapping.h>
 #include <linux/types.h>
 
 #include <linux/firmware/qcom/qcom_scm.h>
@@ -24,12 +25,57 @@ struct qseecom_client {
        u32 app_id;
 };
 
+/**
+ * qseecom_scm_dev() - Get the SCM device associated with the QSEECOM client.
+ * @client: The QSEECOM client device.
+ *
+ * Returns the SCM device under which the provided QSEECOM client device
+ * operates. This function is intended to be used for DMA allocations.
+ */
+static inline struct device *qseecom_scm_dev(struct qseecom_client *client)
+{
+       return client->aux_dev.dev.parent->parent;
+}
+
+/**
+ * qseecom_dma_alloc() - Allocate DMA memory for a QSEECOM client.
+ * @client:     The QSEECOM client to allocate the memory for.
+ * @size:       The number of bytes to allocate.
+ * @dma_handle: Pointer to where the DMA address should be stored.
+ * @gfp:        Allocation flags.
+ *
+ * Wrapper function for dma_alloc_coherent(), allocating DMA memory usable for
+ * TZ/QSEECOM communication. Refer to dma_alloc_coherent() for details.
+ */
+static inline void *qseecom_dma_alloc(struct qseecom_client *client, size_t size,
+                                     dma_addr_t *dma_handle, gfp_t gfp)
+{
+       return dma_alloc_coherent(qseecom_scm_dev(client), size, dma_handle, gfp);
+}
+
+/**
+ * dma_free_coherent() - Free QSEECOM DMA memory.
+ * @client:     The QSEECOM client for which the memory has been allocated.
+ * @size:       The number of bytes allocated.
+ * @cpu_addr:   Virtual memory address to free.
+ * @dma_handle: DMA memory address to free.
+ *
+ * Wrapper function for dma_free_coherent(), freeing memory previously
+ * allocated with qseecom_dma_alloc(). Refer to dma_free_coherent() for
+ * details.
+ */
+static inline void qseecom_dma_free(struct qseecom_client *client, size_t size,
+                                   void *cpu_addr, dma_addr_t dma_handle)
+{
+       return dma_free_coherent(qseecom_scm_dev(client), size, cpu_addr, dma_handle);
+}
+
 /**
  * qcom_qseecom_app_send() - Send to and receive data from a given QSEE app.
  * @client:   The QSEECOM client associated with the target app.
- * @req:      Request buffer sent to the app (must be DMA-mappable).
+ * @req:      DMA address of the request buffer sent to the app.
  * @req_size: Size of the request buffer.
- * @rsp:      Response buffer, written to by the app (must be DMA-mappable).
+ * @rsp:      DMA address of the response buffer, written to by the app.
  * @rsp_size: Size of the response buffer.
  *
  * Sends a request to the QSEE app associated with the given client and read
@@ -43,8 +89,9 @@ struct qseecom_client {
  *
  * Return: Zero on success, nonzero on failure.
  */
-static inline int qcom_qseecom_app_send(struct qseecom_client *client, void *req, size_t req_size,
-                                       void *rsp, size_t rsp_size)
+static inline int qcom_qseecom_app_send(struct qseecom_client *client,
+                                       dma_addr_t req, size_t req_size,
+                                       dma_addr_t rsp, size_t rsp_size)
 {
        return qcom_scm_qseecom_app_send(client->app_id, req, req_size, rsp, rsp_size);
 }
index ccaf288460546a8617a9c7efc5132de8d5fca4e7..aaa19f93ac4306f33e817163cc4eca075cf0b4d4 100644 (file)
@@ -118,8 +118,8 @@ bool qcom_scm_lmh_dcvsh_available(void);
 #ifdef CONFIG_QCOM_QSEECOM
 
 int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id);
-int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
-                             size_t rsp_size);
+int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
+                             dma_addr_t rsp, size_t rsp_size);
 
 #else /* CONFIG_QCOM_QSEECOM */
 
@@ -128,9 +128,9 @@ static inline int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
        return -EINVAL;
 }
 
-static inline int qcom_scm_qseecom_app_send(u32 app_id, void *req,
-                                           size_t req_size, void *rsp,
-                                           size_t rsp_size)
+static inline int qcom_scm_qseecom_app_send(u32 app_id,
+                                           dma_addr_t req, size_t req_size,
+                                           dma_addr_t rsp, size_t rsp_size)
 {
        return -EINVAL;
 }
index 7b0ee64225de9cefebaf63e0d759c082684e3ab5..b6bdaa18b9e9d44583cd245c662e6c2bfdae3825 100644 (file)
@@ -1223,14 +1223,16 @@ static inline void page_mapcount_reset(struct page *page)
  * a large folio, it includes the number of times this page is mapped
  * as part of that folio.
  *
- * The result is undefined for pages which cannot be mapped into userspace.
- * For example SLAB or special types of pages. See function page_has_type().
- * They use this field in struct page differently.
+ * Will report 0 for pages which cannot be mapped into userspace, eg
+ * slab, page tables and similar.
  */
 static inline int page_mapcount(struct page *page)
 {
        int mapcount = atomic_read(&page->_mapcount) + 1;
 
+       /* Handle page_has_type() pages */
+       if (mapcount < 0)
+               mapcount = 0;
        if (unlikely(PageCompound(page)))
                mapcount += folio_entire_mapcount(page_folio(page));
 
index 652d77805e99dfb2adf31def151a26466eff571c..4bf1c25fd1dc566cccf51742286243bace192dad 100644 (file)
@@ -190,7 +190,6 @@ enum pageflags {
 
        /* At least one page in this folio has the hwpoison flag set */
        PG_has_hwpoisoned = PG_error,
-       PG_hugetlb = PG_active,
        PG_large_rmappable = PG_workingset, /* anon or file-backed */
 };
 
@@ -458,30 +457,51 @@ static __always_inline int TestClearPage##uname(struct page *page)        \
        TESTSETFLAG(uname, lname, policy)                               \
        TESTCLEARFLAG(uname, lname, policy)
 
+#define FOLIO_TEST_FLAG_FALSE(name)                                    \
+static inline bool folio_test_##name(const struct folio *folio)                \
+{ return false; }
+#define FOLIO_SET_FLAG_NOOP(name)                                      \
+static inline void folio_set_##name(struct folio *folio) { }
+#define FOLIO_CLEAR_FLAG_NOOP(name)                                    \
+static inline void folio_clear_##name(struct folio *folio) { }
+#define __FOLIO_SET_FLAG_NOOP(name)                                    \
+static inline void __folio_set_##name(struct folio *folio) { }
+#define __FOLIO_CLEAR_FLAG_NOOP(name)                                  \
+static inline void __folio_clear_##name(struct folio *folio) { }
+#define FOLIO_TEST_SET_FLAG_FALSE(name)                                        \
+static inline bool folio_test_set_##name(struct folio *folio)          \
+{ return false; }
+#define FOLIO_TEST_CLEAR_FLAG_FALSE(name)                              \
+static inline bool folio_test_clear_##name(struct folio *folio)                \
+{ return false; }
+
+#define FOLIO_FLAG_FALSE(name)                                         \
+FOLIO_TEST_FLAG_FALSE(name)                                            \
+FOLIO_SET_FLAG_NOOP(name)                                              \
+FOLIO_CLEAR_FLAG_NOOP(name)
+
 #define TESTPAGEFLAG_FALSE(uname, lname)                               \
-static inline bool folio_test_##lname(const struct folio *folio) { return false; } \
+FOLIO_TEST_FLAG_FALSE(lname)                                           \
 static inline int Page##uname(const struct page *page) { return 0; }
 
 #define SETPAGEFLAG_NOOP(uname, lname)                                 \
-static inline void folio_set_##lname(struct folio *folio) { }          \
+FOLIO_SET_FLAG_NOOP(lname)                                             \
 static inline void SetPage##uname(struct page *page) {  }
 
 #define CLEARPAGEFLAG_NOOP(uname, lname)                               \
-static inline void folio_clear_##lname(struct folio *folio) { }                \
+FOLIO_CLEAR_FLAG_NOOP(lname)                                           \
 static inline void ClearPage##uname(struct page *page) {  }
 
 #define __CLEARPAGEFLAG_NOOP(uname, lname)                             \
-static inline void __folio_clear_##lname(struct folio *folio) { }      \
+__FOLIO_CLEAR_FLAG_NOOP(lname)                                         \
 static inline void __ClearPage##uname(struct page *page) {  }
 
 #define TESTSETFLAG_FALSE(uname, lname)                                        \
-static inline bool folio_test_set_##lname(struct folio *folio)         \
-{ return 0; }                                                          \
+FOLIO_TEST_SET_FLAG_FALSE(lname)                                       \
 static inline int TestSetPage##uname(struct page *page) { return 0; }
 
 #define TESTCLEARFLAG_FALSE(uname, lname)                              \
-static inline bool folio_test_clear_##lname(struct folio *folio)       \
-{ return 0; }                                                          \
+FOLIO_TEST_CLEAR_FLAG_FALSE(lname)                                     \
 static inline int TestClearPage##uname(struct page *page) { return 0; }
 
 #define PAGEFLAG_FALSE(uname, lname) TESTPAGEFLAG_FALSE(uname, lname)  \
@@ -855,29 +875,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)
 
 #define PG_head_mask ((1UL << PG_head))
 
-#ifdef CONFIG_HUGETLB_PAGE
-int PageHuge(const struct page *page);
-SETPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
-CLEARPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
-
-/**
- * folio_test_hugetlb - Determine if the folio belongs to hugetlbfs
- * @folio: The folio to test.
- *
- * Context: Any context.  Caller should have a reference on the folio to
- * prevent it from being turned into a tail page.
- * Return: True for hugetlbfs folios, false for anon folios or folios
- * belonging to other filesystems.
- */
-static inline bool folio_test_hugetlb(const struct folio *folio)
-{
-       return folio_test_large(folio) &&
-               test_bit(PG_hugetlb, const_folio_flags(folio, 1));
-}
-#else
-TESTPAGEFLAG_FALSE(Huge, hugetlb)
-#endif
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 /*
  * PageHuge() only returns true for hugetlbfs pages, but not for
@@ -933,34 +930,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
        TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
 #endif
 
-/*
- * Check if a page is currently marked HWPoisoned. Note that this check is
- * best effort only and inherently racy: there is no way to synchronize with
- * failing hardware.
- */
-static inline bool is_page_hwpoison(struct page *page)
-{
-       if (PageHWPoison(page))
-               return true;
-       return PageHuge(page) && PageHWPoison(compound_head(page));
-}
-
 /*
  * For pages that are never mapped to userspace (and aren't PageSlab),
  * page_type may be used.  Because it is initialised to -1, we invert the
  * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and
  * __ClearPageFoo *sets* the bit used for PageFoo.  We reserve a few high and
- * low bits so that an underflow or overflow of page_mapcount() won't be
+ * low bits so that an underflow or overflow of _mapcount won't be
  * mistaken for a page type value.
  */
 
 #define PAGE_TYPE_BASE 0xf0000000
-/* Reserve             0x0000007f to catch underflows of page_mapcount */
+/* Reserve             0x0000007f to catch underflows of _mapcount */
 #define PAGE_MAPCOUNT_RESERVE  -128
 #define PG_buddy       0x00000080
 #define PG_offline     0x00000100
 #define PG_table       0x00000200
 #define PG_guard       0x00000400
+#define PG_hugetlb     0x00000800
 
 #define PageType(page, flag)                                           \
        ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
@@ -977,35 +963,38 @@ static inline int page_has_type(const struct page *page)
        return page_type_has_type(page->page_type);
 }
 
+#define FOLIO_TYPE_OPS(lname, fname)                                   \
+static __always_inline bool folio_test_##fname(const struct folio *folio)\
+{                                                                      \
+       return folio_test_type(folio, PG_##lname);                      \
+}                                                                      \
+static __always_inline void __folio_set_##fname(struct folio *folio)   \
+{                                                                      \
+       VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio);             \
+       folio->page.page_type &= ~PG_##lname;                           \
+}                                                                      \
+static __always_inline void __folio_clear_##fname(struct folio *folio) \
+{                                                                      \
+       VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio);             \
+       folio->page.page_type |= PG_##lname;                            \
+}
+
 #define PAGE_TYPE_OPS(uname, lname, fname)                             \
+FOLIO_TYPE_OPS(lname, fname)                                           \
 static __always_inline int Page##uname(const struct page *page)                \
 {                                                                      \
        return PageType(page, PG_##lname);                              \
 }                                                                      \
-static __always_inline int folio_test_##fname(const struct folio *folio)\
-{                                                                      \
-       return folio_test_type(folio, PG_##lname);                      \
-}                                                                      \
 static __always_inline void __SetPage##uname(struct page *page)                \
 {                                                                      \
        VM_BUG_ON_PAGE(!PageType(page, 0), page);                       \
        page->page_type &= ~PG_##lname;                                 \
 }                                                                      \
-static __always_inline void __folio_set_##fname(struct folio *folio)   \
-{                                                                      \
-       VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio);             \
-       folio->page.page_type &= ~PG_##lname;                           \
-}                                                                      \
 static __always_inline void __ClearPage##uname(struct page *page)      \
 {                                                                      \
        VM_BUG_ON_PAGE(!Page##uname(page), page);                       \
        page->page_type |= PG_##lname;                                  \
-}                                                                      \
-static __always_inline void __folio_clear_##fname(struct folio *folio) \
-{                                                                      \
-       VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio);             \
-       folio->page.page_type |= PG_##lname;                            \
-}                                                                      \
+}
 
 /*
  * PageBuddy() indicates that the page is free and in the buddy system
@@ -1052,6 +1041,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)
  */
 PAGE_TYPE_OPS(Guard, guard, guard)
 
+#ifdef CONFIG_HUGETLB_PAGE
+FOLIO_TYPE_OPS(hugetlb, hugetlb)
+#else
+FOLIO_TEST_FLAG_FALSE(hugetlb)
+#endif
+
+/**
+ * PageHuge - Determine if the page belongs to hugetlbfs
+ * @page: The page to test.
+ *
+ * Context: Any context.
+ * Return: True for hugetlbfs pages, false for anon pages or pages
+ * belonging to other filesystems.
+ */
+static inline bool PageHuge(const struct page *page)
+{
+       return folio_test_hugetlb(page_folio(page));
+}
+
+/*
+ * Check if a page is currently marked HWPoisoned. Note that this check is
+ * best effort only and inherently racy: there is no way to synchronize with
+ * failing hardware.
+ */
+static inline bool is_page_hwpoison(struct page *page)
+{
+       if (PageHWPoison(page))
+               return true;
+       return PageHuge(page) && PageHWPoison(compound_head(page));
+}
+
 extern bool is_free_buddy_page(struct page *page);
 
 PAGEFLAG(Isolated, isolated, PF_ANY);
@@ -1118,7 +1138,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 #define PAGE_FLAGS_SECOND                                              \
        (0xffUL /* order */             | 1UL << PG_has_hwpoisoned |    \
-        1UL << PG_hugetlb              | 1UL << PG_large_rmappable)
+        1UL << PG_large_rmappable)
 
 #define PAGE_FLAGS_PRIVATE                             \
        (1UL << PG_private | 1UL << PG_private_2)
index 11db1ec516e272ab030716b6206340b43a44dac8..04ae5ebcb637aa2d3c11184307a68c026753a375 100644 (file)
@@ -18,13 +18,8 @@ struct proc_dir_entry;
 struct notifier_block;
 
 #if defined(CONFIG_PROFILING) && defined(CONFIG_PROC_FS)
-void create_prof_cpu_mask(void);
 int create_proc_profile(void);
 #else
-static inline void create_prof_cpu_mask(void)
-{
-}
-
 static inline int create_proc_profile(void)
 {
        return 0;
index b743241cfb7caa22da0e12098da3ea7dead08a9b..d470303b1bbbbe9d3e468cab99cdb3e72067d66f 100644 (file)
@@ -1230,6 +1230,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map,
 int regmap_raw_write_async(struct regmap *map, unsigned int reg,
                           const void *val, size_t val_len);
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
+int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val);
 int regmap_raw_read(struct regmap *map, unsigned int reg,
                    void *val, size_t val_len);
 int regmap_noinc_read(struct regmap *map, unsigned int reg,
@@ -1739,6 +1740,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg,
        return -EINVAL;
 }
 
+static inline int regmap_read_bypassed(struct regmap *map, unsigned int reg,
+                                      unsigned int *val)
+{
+       WARN_ONCE(1, "regmap API is disabled");
+       return -EINVAL;
+}
+
 static inline int regmap_raw_read(struct regmap *map, unsigned int reg,
                                  void *val, size_t val_len)
 {
index 4660582a33022fc15946a811105318199ccaca42..ed180ca419dad94d6e7db7eae820a26f8dcc5e48 100644 (file)
@@ -320,13 +320,13 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
 
 static inline int devm_regulator_get_enable(struct device *dev, const char *id)
 {
-       return -ENODEV;
+       return 0;
 }
 
 static inline int devm_regulator_get_enable_optional(struct device *dev,
                                                     const char *id)
 {
-       return -ENODEV;
+       return 0;
 }
 
 static inline struct regulator *__must_check
index e65ec3fd27998a5b82fc2c4597c575125e653056..a509caf823d6188070d17da6c7724f6d07eb0997 100644 (file)
@@ -461,10 +461,12 @@ static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock)
 
 static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock)
 {
+       read_lock_bh(&sk->sk_callback_lock);
        if (psock->saved_data_ready)
                psock->saved_data_ready(sk);
        else
                sk->sk_data_ready(sk);
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static inline void psock_set_prog(struct bpf_prog **pprog,
index 24cd199dd6f3a972f44344eb3994334201145e63..d33bab33099ab0fe4db1a889117307510e1035fa 100644 (file)
@@ -210,7 +210,6 @@ struct svc_rdma_recv_ctxt {
  */
 struct svc_rdma_write_info {
        struct svcxprt_rdma     *wi_rdma;
-       struct list_head        wi_list;
 
        const struct svc_rdma_chunk     *wi_chunk;
 
@@ -239,10 +238,7 @@ struct svc_rdma_send_ctxt {
        struct ib_cqe           sc_cqe;
        struct xdr_buf          sc_hdrbuf;
        struct xdr_stream       sc_stream;
-
-       struct list_head        sc_write_info_list;
        struct svc_rdma_write_info sc_reply_info;
-
        void                    *sc_xprt_buf;
        int                     sc_page_count;
        int                     sc_cur_sge_no;
@@ -274,14 +270,11 @@ extern void svc_rdma_cc_init(struct svcxprt_rdma *rdma,
 extern void svc_rdma_cc_release(struct svcxprt_rdma *rdma,
                                struct svc_rdma_chunk_ctxt *cc,
                                enum dma_data_direction dir);
-extern void svc_rdma_write_chunk_release(struct svcxprt_rdma *rdma,
-                                        struct svc_rdma_send_ctxt *ctxt);
 extern void svc_rdma_reply_chunk_release(struct svcxprt_rdma *rdma,
                                         struct svc_rdma_send_ctxt *ctxt);
-extern int svc_rdma_prepare_write_list(struct svcxprt_rdma *rdma,
-                                      const struct svc_rdma_pcl *write_pcl,
-                                      struct svc_rdma_send_ctxt *sctxt,
-                                      const struct xdr_buf *xdr);
+extern int svc_rdma_send_write_list(struct svcxprt_rdma *rdma,
+                                   const struct svc_rdma_recv_ctxt *rctxt,
+                                   const struct xdr_buf *xdr);
 extern int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma,
                                        const struct svc_rdma_pcl *write_pcl,
                                        const struct svc_rdma_pcl *reply_pcl,
index 7a5fe17b6bf9c628bc669d82ad16d7cc9abdb88f..d03f746587167e3c26b19b62f6704f15e96abb66 100644 (file)
@@ -62,6 +62,8 @@ struct eventfs_file;
 typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data,
                                const struct file_operations **fops);
 
+typedef void (*eventfs_release)(const char *name, void *data);
+
 /**
  * struct eventfs_entry - dynamically created eventfs file call back handler
  * @name:      Then name of the dynamic file in an eventfs directory
@@ -72,6 +74,7 @@ typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data,
 struct eventfs_entry {
        const char                      *name;
        eventfs_callback                callback;
+       eventfs_release                 release;
 };
 
 struct eventfs_inode;
index 627ea8e2d915984091944cf114c4d46d4631f6f4..3dee0b2721aa402ce020fcbda72250980afc52ad 100644 (file)
@@ -85,6 +85,9 @@ enum unix_socket_lock_class {
        U_LOCK_NORMAL,
        U_LOCK_SECOND,  /* for double locking, see unix_state_double_lock(). */
        U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
+       U_LOCK_GC_LISTENER, /* used for listening socket while determining gc
+                            * candidates to close a small race window.
+                            */
 };
 
 static inline void unix_state_lock_nested(struct sock *sk,
index 56fb42df44a3331f3665499f5e81cdcdf2c2f64d..e8f581f3f3ce6d4fe3d0d6db8c8a9688daf4addb 100644 (file)
@@ -738,6 +738,8 @@ struct hci_conn {
        __u8            le_per_adv_data[HCI_MAX_PER_AD_TOT_LEN];
        __u16           le_per_adv_data_len;
        __u16           le_per_adv_data_offset;
+       __u8            le_adv_phy;
+       __u8            le_adv_sec_phy;
        __u8            le_tx_phy;
        __u8            le_rx_phy;
        __s8            rssi;
@@ -1512,7 +1514,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
                                     enum conn_reasons conn_reason);
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                u8 dst_type, bool dst_resolved, u8 sec_level,
-                               u16 conn_timeout, u8 role);
+                               u16 conn_timeout, u8 role, u8 phy, u8 sec_phy);
 void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status);
 struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
                                 u8 sec_level, u8 auth_type,
@@ -1905,6 +1907,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
                                   (hdev->commands[39] & 0x04))
 
+#define read_key_size_capable(dev) \
+       ((dev)->commands[20] & 0x10 && \
+        !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))
+
 /* Use enhanced synchronous connection if command is supported and its quirk
  * has not been set.
  */
index 50f1e403dbbb3805277d74ff80b504677e9a7aa0..c1d4ca0463a178736d2416e172784e35e333e126 100644 (file)
@@ -87,6 +87,15 @@ struct napi_gro_cb {
 
        /* used to support CHECKSUM_COMPLETE for tunneling protocols */
        __wsum  csum;
+
+       /* L3 offsets */
+       union {
+               struct {
+                       u16 network_offset;
+                       u16 inner_network_offset;
+               };
+               u16 network_offsets[2];
+       };
 };
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
index 353488ab94a294fd1fb2a985d015f9c8b59d421d..2d7f87bc5324b4823a8f70b960f0545bab8549c4 100644 (file)
@@ -953,6 +953,8 @@ enum mac80211_tx_info_flags {
  *     of their QoS TID or other priority field values.
  * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally
  *     for sequence number assignment
+ * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted
+ *     due to scanning, not in normal operation on the interface.
  * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
  *     frame should be transmitted on the specific link. This really is
  *     only relevant for frames that do not have data present, and is
@@ -973,6 +975,7 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_CTRL_NO_SEQNO              = BIT(7),
        IEEE80211_TX_CTRL_DONT_REORDER          = BIT(8),
        IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX    = BIT(9),
+       IEEE80211_TX_CTRL_SCAN_TX               = BIT(10),
        IEEE80211_TX_CTRL_MLO_LINK              = 0xf0000000,
 };
 
index dbd22180cc5c3418cfa47261639d3ab7bbf55bee..de216cbc6b059fba9f795f83c6be43f5169c8649 100644 (file)
@@ -321,6 +321,7 @@ struct macsec_context {
  *     for the TX tag
  * @needed_tailroom: number of bytes reserved at the end of the sk_buff for the
  *     TX tag
+ * @rx_uses_md_dst: whether MACsec device offload supports sk_buff md_dst
  */
 struct macsec_ops {
        /* Device wide */
@@ -352,6 +353,7 @@ struct macsec_ops {
                                 struct sk_buff *skb);
        unsigned int needed_headroom;
        unsigned int needed_tailroom;
+       bool rx_uses_md_dst;
 };
 
 void macsec_pn_wrapped(struct macsec_secy *secy, struct macsec_tx_sa *tx_sa);
index f57bfd8a2ad2deaedf3f351325ab9336ae040504..b4b553df7870c0290ae632c51828ad7161ba332d 100644 (file)
@@ -1410,32 +1410,34 @@ sk_memory_allocated(const struct sock *sk)
 #define SK_MEMORY_PCPU_RESERVE (1 << (20 - PAGE_SHIFT))
 extern int sysctl_mem_pcpu_rsv;
 
+static inline void proto_memory_pcpu_drain(struct proto *proto)
+{
+       int val = this_cpu_xchg(*proto->per_cpu_fw_alloc, 0);
+
+       if (val)
+               atomic_long_add(val, proto->memory_allocated);
+}
+
 static inline void
-sk_memory_allocated_add(struct sock *sk, int amt)
+sk_memory_allocated_add(const struct sock *sk, int val)
 {
-       int local_reserve;
+       struct proto *proto = sk->sk_prot;
 
-       preempt_disable();
-       local_reserve = __this_cpu_add_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
-       if (local_reserve >= READ_ONCE(sysctl_mem_pcpu_rsv)) {
-               __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
-               atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
-       }
-       preempt_enable();
+       val = this_cpu_add_return(*proto->per_cpu_fw_alloc, val);
+
+       if (unlikely(val >= READ_ONCE(sysctl_mem_pcpu_rsv)))
+               proto_memory_pcpu_drain(proto);
 }
 
 static inline void
-sk_memory_allocated_sub(struct sock *sk, int amt)
+sk_memory_allocated_sub(const struct sock *sk, int val)
 {
-       int local_reserve;
+       struct proto *proto = sk->sk_prot;
 
-       preempt_disable();
-       local_reserve = __this_cpu_sub_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
-       if (local_reserve <= -READ_ONCE(sysctl_mem_pcpu_rsv)) {
-               __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
-               atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
-       }
-       preempt_enable();
+       val = this_cpu_sub_return(*proto->per_cpu_fw_alloc, val);
+
+       if (unlikely(val <= -READ_ONCE(sysctl_mem_pcpu_rsv)))
+               proto_memory_pcpu_drain(proto);
 }
 
 #define SK_ALLOC_PERCPU_COUNTER_BATCH 16
index 340ad43971e4711d8091a6397bb5cf3c3c4ef0fd..33f657d3c0510a0bd9e9899bc2530f9d035ce366 100644 (file)
@@ -111,7 +111,8 @@ struct tls_strparser {
        u32 stopped : 1;
        u32 copy_mode : 1;
        u32 mixed_decrypted : 1;
-       u32 msg_ready : 1;
+
+       bool msg_ready;
 
        struct strp_msg stm;
 
index e0629699b56338a76b69616dcc2a79dece2e51f4..1a3c6f66f6205597cb46b3c7cc826802fc35c740 100644 (file)
@@ -267,6 +267,7 @@ struct cs35l56_base {
        bool fw_patched;
        bool secured;
        bool can_hibernate;
+       bool fw_owns_asp1;
        bool cal_data_valid;
        s8 cal_index;
        struct cirrus_amp_cal_data cal_data;
@@ -283,6 +284,7 @@ extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];
 extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC];
 
 int cs35l56_set_patch(struct cs35l56_base *cs35l56_base);
+int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base);
 int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base);
 int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command);
 int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base);
index 1af9e68193920d062f3c9cce40eba41dc8d74292..234b5baea69c8e6154c3c048fe002bf99337e245 100644 (file)
@@ -1684,8 +1684,8 @@ struct snd_emu1010 {
        unsigned int clock_fallback;
        unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
        unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
-       struct work_struct firmware_work;
-       struct work_struct clock_work;
+       struct work_struct work;
+       struct mutex lock;
 };
 
 struct snd_emu10k1 {
@@ -1834,6 +1834,9 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg,
 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
+static inline void snd_emu1010_fpga_lock(struct snd_emu10k1 *emu) { mutex_lock(&emu->emu1010.lock); };
+static inline void snd_emu1010_fpga_unlock(struct snd_emu10k1 *emu) { mutex_unlock(&emu->emu1010.lock); };
+void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value);
 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
 void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value);
 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src);
index d801409b33cfec29c84150173908c9522b4cfa60..d55e53ac91bd2cbb3cc24836a96a4d38af752c9d 100644 (file)
@@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3)
 #define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) }
 
 #define __def_pagetype_names                                           \
+       DEF_PAGETYPE_NAME(hugetlb),                                     \
        DEF_PAGETYPE_NAME(offline),                                     \
        DEF_PAGETYPE_NAME(guard),                                       \
        DEF_PAGETYPE_NAME(table),                                       \
index d87410a8443aaeadd86966e86a8bec59c8fd9f87..af024d90453ddc5376892b13efd8e6c51043e97e 100644 (file)
@@ -77,11 +77,6 @@ struct drm_etnaviv_timespec {
 #define ETNAVIV_PARAM_GPU_PRODUCT_ID                0x1c
 #define ETNAVIV_PARAM_GPU_CUSTOMER_ID               0x1d
 #define ETNAVIV_PARAM_GPU_ECO_ID                    0x1e
-#define ETNAVIV_PARAM_GPU_NN_CORE_COUNT             0x1f
-#define ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE           0x20
-#define ETNAVIV_PARAM_GPU_TP_CORE_COUNT             0x21
-#define ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE         0x22
-#define ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE             0x23
 
 #define ETNA_MAX_PIPES 4
 
index 43c51698195ceb0619e5b2787428be675b007a7f..842bf1201ac4142813d2ea3a90e8f34e20ea5fd5 100644 (file)
@@ -57,7 +57,7 @@ enum vdpa_attr {
        VDPA_ATTR_DEV_FEATURES,                 /* u64 */
 
        VDPA_ATTR_DEV_BLK_CFG_CAPACITY,         /* u64 */
-       VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE,         /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_SIZE_MAX,         /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_BLK_SIZE,         /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_SEG_MAX,          /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_NUM_QUEUES,       /* u16 */
@@ -70,8 +70,8 @@ enum vdpa_attr {
        VDPA_ATTR_DEV_BLK_CFG_DISCARD_SEC_ALIGN,/* u32 */
        VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEC,     /* u32 */
        VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEG,     /* u32 */
-       VDPA_ATTR_DEV_BLK_CFG_READ_ONLY,                /* u8 */
-       VDPA_ATTR_DEV_BLK_CFG_FLUSH,            /* u8 */
+       VDPA_ATTR_DEV_BLK_READ_ONLY,            /* u8 */
+       VDPA_ATTR_DEV_BLK_FLUSH,                /* u8 */
 
        /* new attributes must be added above here */
        VDPA_ATTR_MAX,
index aa02aec6aa7d29432f1974003900fce14bf14452..664bedb9a71fbe97c9726c1397d5c8b2043d1da4 100644 (file)
@@ -1899,11 +1899,11 @@ config RUST
        bool "Rust support"
        depends on HAVE_RUST
        depends on RUST_IS_AVAILABLE
+       depends on !CFI_CLANG
        depends on !MODVERSIONS
        depends on !GCC_PLUGINS
        depends on !RANDSTRUCT
        depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
-       select CONSTRUCTORS
        help
          Enables Rust support in the kernel.
 
index c5a9fcd2d622819cc1f5b0f5cfd772514ee5f423..29b2cd00df2ccf2b991b9b78f4514b76c87ee354 100644 (file)
@@ -19,7 +19,7 @@ int main(void)
        DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
        DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
 #ifdef CONFIG_SMP
-       DEFINE(NR_CPUS_BITS, bits_per(CONFIG_NR_CPUS));
+       DEFINE(NR_CPUS_BITS, order_base_2(CONFIG_NR_CPUS));
 #endif
        DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
 #ifdef CONFIG_LRU_GEN
index 696bc55de8e82ea9358ede9c222b4927871e60be..1ea5ce5bb59933ac4449567c52f1981c8df8a139 100644 (file)
@@ -2942,6 +2942,15 @@ bool __weak bpf_jit_supports_arena(void)
        return false;
 }
 
+u64 __weak bpf_arch_uaddress_limit(void)
+{
+#if defined(CONFIG_64BIT) && defined(CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE)
+       return TASK_SIZE;
+#else
+       return 0;
+#endif
+}
+
 /* Return TRUE if the JIT backend satisfies the following two conditions:
  * 1) JIT backend supports atomic_xchg() on pointer-sized words.
  * 2) Under the specific arch, the implementation of xchg() is the same
index 98188379d5c77d79d3a5e764659ed4426f931d14..cb7ad1f795e18b1abec57dc5e40f2d852416bb04 100644 (file)
@@ -18289,8 +18289,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env)
                        f = fdget(fd);
                        map = __bpf_map_get(f);
                        if (IS_ERR(map)) {
-                               verbose(env, "fd %d is not pointing to valid bpf_map\n",
-                                       insn[0].imm);
+                               verbose(env, "fd %d is not pointing to valid bpf_map\n", fd);
                                return PTR_ERR(map);
                        }
 
@@ -19676,6 +19675,36 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
                        goto next_insn;
                }
 
+               /* Make it impossible to de-reference a userspace address */
+               if (BPF_CLASS(insn->code) == BPF_LDX &&
+                   (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
+                    BPF_MODE(insn->code) == BPF_PROBE_MEMSX)) {
+                       struct bpf_insn *patch = &insn_buf[0];
+                       u64 uaddress_limit = bpf_arch_uaddress_limit();
+
+                       if (!uaddress_limit)
+                               goto next_insn;
+
+                       *patch++ = BPF_MOV64_REG(BPF_REG_AX, insn->src_reg);
+                       if (insn->off)
+                               *patch++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_AX, insn->off);
+                       *patch++ = BPF_ALU64_IMM(BPF_RSH, BPF_REG_AX, 32);
+                       *patch++ = BPF_JMP_IMM(BPF_JLE, BPF_REG_AX, uaddress_limit >> 32, 2);
+                       *patch++ = *insn;
+                       *patch++ = BPF_JMP_IMM(BPF_JA, 0, 0, 1);
+                       *patch++ = BPF_MOV64_IMM(insn->dst_reg, 0);
+
+                       cnt = patch - insn_buf;
+                       new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
+                       if (!new_prog)
+                               return -ENOMEM;
+
+                       delta    += cnt - 1;
+                       env->prog = prog = new_prog;
+                       insn      = new_prog->insnsi + i + delta;
+                       goto next_insn;
+               }
+
                /* Implement LD_ABS and LD_IND with a rewrite, if supported by the program type. */
                if (BPF_CLASS(insn->code) == BPF_LD &&
                    (BPF_MODE(insn->code) == BPF_ABS ||
index 07ad53b7f11952080e890ed91f99f3e762bf984d..63447eb85dab6bd0fa2ab23c25bffdf788a2b9c1 100644 (file)
@@ -3196,6 +3196,7 @@ void __init boot_cpu_hotplug_init(void)
        this_cpu_write(cpuhp_state.target, CPUHP_ONLINE);
 }
 
+#ifdef CONFIG_CPU_MITIGATIONS
 /*
  * These are used for a global "mitigations=" cmdline option for toggling
  * optional CPU mitigations.
@@ -3206,9 +3207,7 @@ enum cpu_mitigations {
        CPU_MITIGATIONS_AUTO_NOSMT,
 };
 
-static enum cpu_mitigations cpu_mitigations __ro_after_init =
-       IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
-                                                    CPU_MITIGATIONS_OFF;
+static enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
 
 static int __init mitigations_parse_cmdline(char *arg)
 {
@@ -3224,7 +3223,6 @@ static int __init mitigations_parse_cmdline(char *arg)
 
        return 0;
 }
-early_param("mitigations", mitigations_parse_cmdline);
 
 /* mitigations=off */
 bool cpu_mitigations_off(void)
@@ -3239,3 +3237,11 @@ bool cpu_mitigations_auto_nosmt(void)
        return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
 }
 EXPORT_SYMBOL_GPL(cpu_mitigations_auto_nosmt);
+#else
+static int __init mitigations_parse_cmdline(char *arg)
+{
+       pr_crit("Kernel compiled without mitigations, ignoring 'mitigations'; system may still be vulnerable\n");
+       return 0;
+}
+#endif
+early_param("mitigations", mitigations_parse_cmdline);
index a5e0dfc44d24e22641e72bb0362511a33b23a1fd..0de66f0ff43aba1f64505d70b86d9faac8bc43ff 100644 (file)
@@ -1798,6 +1798,7 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem,
                mem->for_alloc = true;
 #ifdef CONFIG_SWIOTLB_DYNAMIC
                spin_lock_init(&mem->lock);
+               INIT_LIST_HEAD_RCU(&mem->pools);
 #endif
                add_mem_pool(mem, pool);
 
index 8a77769bc4b4cbb655244fd163fc72a860b4bcdd..2b775cc5c28f96cebe33e6d9c55a001d0debd6ce 100644 (file)
@@ -344,49 +344,6 @@ void profile_tick(int type)
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 
-static int prof_cpu_mask_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%*pb\n", cpumask_pr_args(prof_cpu_mask));
-       return 0;
-}
-
-static int prof_cpu_mask_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, prof_cpu_mask_proc_show, NULL);
-}
-
-static ssize_t prof_cpu_mask_proc_write(struct file *file,
-       const char __user *buffer, size_t count, loff_t *pos)
-{
-       cpumask_var_t new_value;
-       int err;
-
-       if (!zalloc_cpumask_var(&new_value, GFP_KERNEL))
-               return -ENOMEM;
-
-       err = cpumask_parse_user(buffer, count, new_value);
-       if (!err) {
-               cpumask_copy(prof_cpu_mask, new_value);
-               err = count;
-       }
-       free_cpumask_var(new_value);
-       return err;
-}
-
-static const struct proc_ops prof_cpu_mask_proc_ops = {
-       .proc_open      = prof_cpu_mask_proc_open,
-       .proc_read      = seq_read,
-       .proc_lseek     = seq_lseek,
-       .proc_release   = single_release,
-       .proc_write     = prof_cpu_mask_proc_write,
-};
-
-void create_prof_cpu_mask(void)
-{
-       /* create /proc/irq/prof_cpu_mask */
-       proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_ops);
-}
-
 /*
  * This function accesses profiling information. The returned data is
  * binary: the sampling step and the actual contents of the profile
index 03be0d1330a6b22336c91cd4cfeae7fd82838692..c62805dbd6088b3bd63ac07766b92443f35f0e36 100644 (file)
@@ -696,15 +696,21 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
  *
  * XXX could add max_slice to the augmented data to track this.
  */
-static void update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
+static s64 entity_lag(u64 avruntime, struct sched_entity *se)
 {
-       s64 lag, limit;
+       s64 vlag, limit;
+
+       vlag = avruntime - se->vruntime;
+       limit = calc_delta_fair(max_t(u64, 2*se->slice, TICK_NSEC), se);
 
+       return clamp(vlag, -limit, limit);
+}
+
+static void update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
        SCHED_WARN_ON(!se->on_rq);
-       lag = avg_vruntime(cfs_rq) - se->vruntime;
 
-       limit = calc_delta_fair(max_t(u64, 2*se->slice, TICK_NSEC), se);
-       se->vlag = clamp(lag, -limit, limit);
+       se->vlag = entity_lag(avg_vruntime(cfs_rq), se);
 }
 
 /*
@@ -3676,11 +3682,10 @@ static inline void
 dequeue_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
 #endif
 
-static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
+static void reweight_eevdf(struct sched_entity *se, u64 avruntime,
                           unsigned long weight)
 {
        unsigned long old_weight = se->load.weight;
-       u64 avruntime = avg_vruntime(cfs_rq);
        s64 vlag, vslice;
 
        /*
@@ -3761,7 +3766,7 @@ static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
         *         = V  - vl'
         */
        if (avruntime != se->vruntime) {
-               vlag = (s64)(avruntime - se->vruntime);
+               vlag = entity_lag(avruntime, se);
                vlag = div_s64(vlag * old_weight, weight);
                se->vruntime = avruntime - vlag;
        }
@@ -3787,25 +3792,26 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
                            unsigned long weight)
 {
        bool curr = cfs_rq->curr == se;
+       u64 avruntime;
 
        if (se->on_rq) {
                /* commit outstanding execution time */
-               if (curr)
-                       update_curr(cfs_rq);
-               else
+               update_curr(cfs_rq);
+               avruntime = avg_vruntime(cfs_rq);
+               if (!curr)
                        __dequeue_entity(cfs_rq, se);
                update_load_sub(&cfs_rq->load, se->load.weight);
        }
        dequeue_load_avg(cfs_rq, se);
 
-       if (!se->on_rq) {
+       if (se->on_rq) {
+               reweight_eevdf(se, avruntime, weight);
+       } else {
                /*
                 * Because we keep se->vlag = V - v_i, while: lag_i = w_i*(V - v_i),
                 * we need to scale se->vlag when w_i changes.
                 */
                se->vlag = div_s64(se->vlag * se->load.weight, weight);
-       } else {
-               reweight_eevdf(cfs_rq, se, weight);
        }
 
        update_load_set(&se->load, weight);
index 373d42c707bc5d65d70c18d66e0ffd1621d33f5b..5891e715f00d028b0d2f4fd157e99f319b899a1d 100644 (file)
@@ -46,7 +46,16 @@ int housekeeping_any_cpu(enum hk_type type)
                        if (cpu < nr_cpu_ids)
                                return cpu;
 
-                       return cpumask_any_and(housekeeping.cpumasks[type], cpu_online_mask);
+                       cpu = cpumask_any_and(housekeeping.cpumasks[type], cpu_online_mask);
+                       if (likely(cpu < nr_cpu_ids))
+                               return cpu;
+                       /*
+                        * Unless we have another problem this can only happen
+                        * at boot time before start_secondary() brings the 1st
+                        * housekeeping CPU up.
+                        */
+                       WARN_ON_ONCE(system_state == SYSTEM_RUNNING ||
+                                    type != HK_TYPE_TIMER);
                }
        }
        return smp_processor_id();
@@ -109,6 +118,7 @@ static void __init housekeeping_setup_type(enum hk_type type,
 static int __init housekeeping_setup(char *str, unsigned long flags)
 {
        cpumask_var_t non_housekeeping_mask, housekeeping_staging;
+       unsigned int first_cpu;
        int err = 0;
 
        if ((flags & HK_FLAG_TICK) && !(housekeeping.flags & HK_FLAG_TICK)) {
@@ -129,7 +139,8 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
        cpumask_andnot(housekeeping_staging,
                       cpu_possible_mask, non_housekeeping_mask);
 
-       if (!cpumask_intersects(cpu_present_mask, housekeeping_staging)) {
+       first_cpu = cpumask_first_and(cpu_present_mask, housekeeping_staging);
+       if (first_cpu >= nr_cpu_ids || first_cpu >= setup_max_cpus) {
                __cpumask_set_cpu(smp_processor_id(), housekeeping_staging);
                __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
                if (!housekeeping.flags) {
@@ -138,6 +149,9 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
                }
        }
 
+       if (cpumask_empty(non_housekeeping_mask))
+               goto free_housekeeping_staging;
+
        if (!housekeeping.flags) {
                /* First setup call ("nohz_full=" or "isolcpus=") */
                enum hk_type type;
index b315b21fb28cd281fc38d1a8a00ed9f9527e2f53..02582017759a2ce3bfb42faf4be904a7b432595b 100644 (file)
@@ -508,7 +508,7 @@ static inline bool lockdep_softirq_start(void) { return false; }
 static inline void lockdep_softirq_end(bool in_hardirq) { }
 #endif
 
-asmlinkage __visible void __softirq_entry __do_softirq(void)
+static void handle_softirqs(bool ksirqd)
 {
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
        unsigned long old_flags = current->flags;
@@ -563,8 +563,7 @@ restart:
                pending >>= softirq_bit;
        }
 
-       if (!IS_ENABLED(CONFIG_PREEMPT_RT) &&
-           __this_cpu_read(ksoftirqd) == current)
+       if (!IS_ENABLED(CONFIG_PREEMPT_RT) && ksirqd)
                rcu_softirq_qs();
 
        local_irq_disable();
@@ -584,6 +583,11 @@ restart:
        current_restore_flags(old_flags, PF_MEMALLOC);
 }
 
+asmlinkage __visible void __softirq_entry __do_softirq(void)
+{
+       handle_softirqs(false);
+}
+
 /**
  * irq_enter_rcu - Enter an interrupt context with RCU watching
  */
@@ -921,7 +925,7 @@ static void run_ksoftirqd(unsigned int cpu)
                 * We can safely run softirq on inline stack, as we are not deep
                 * in the task stack here.
                 */
-               __do_softirq();
+               handle_softirqs(true);
                ksoftirqd_run_end();
                cond_resched();
                return;
index 52f75c36bbca4922bec786815bb70ff409f62a61..6ef29eba90ceb7e06774171d79c7ea244ecaa72a 100644 (file)
@@ -2552,6 +2552,14 @@ static int event_callback(const char *name, umode_t *mode, void **data,
        return 0;
 }
 
+/* The file is incremented on creation and freeing the enable file decrements it */
+static void event_release(const char *name, void *data)
+{
+       struct trace_event_file *file = data;
+
+       event_file_put(file);
+}
+
 static int
 event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
 {
@@ -2566,6 +2574,7 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
                {
                        .name           = "enable",
                        .callback       = event_callback,
+                       .release        = event_release,
                },
                {
                        .name           = "filter",
@@ -2634,6 +2643,9 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
                return ret;
        }
 
+       /* Gets decremented on freeing of the "enable" file */
+       event_file_get(file);
+
        return 0;
 }
 
index dfe3ee6035ecc74da70ebd8104d23f1ef2a25cde..42bc0f3622263b60618fbc8fd39f2f3beedf44a3 100644 (file)
@@ -1466,7 +1466,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
                parg->fmt = kmalloc(len, GFP_KERNEL);
                if (!parg->fmt) {
                        ret = -ENOMEM;
-                       goto out;
+                       goto fail;
                }
                snprintf(parg->fmt, len, "%s[%d]", parg->type->fmttype,
                         parg->count);
index f95516cd45bbe29661adc4da4c530c813ad209fe..23c125c2e2436c935a6e35b256d81866777ef35e 100644 (file)
@@ -205,11 +205,10 @@ static int __init crash_save_vmcoreinfo_init(void)
        VMCOREINFO_NUMBER(PG_head_mask);
 #define PAGE_BUDDY_MAPCOUNT_VALUE      (~PG_buddy)
        VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
-#ifdef CONFIG_HUGETLB_PAGE
-       VMCOREINFO_NUMBER(PG_hugetlb);
+#define PAGE_HUGETLB_MAPCOUNT_VALUE    (~PG_hugetlb)
+       VMCOREINFO_NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE);
 #define PAGE_OFFLINE_MAPCOUNT_VALUE    (~PG_offline)
        VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE);
-#endif
 
 #ifdef CONFIG_KALLSYMS
        VMCOREINFO_SYMBOL(kallsyms_names);
index 0066c8f6c15442641889c87995410ac82d078423..d2dbe099286b95ca5f0b745e577af0e6ed297062 100644 (file)
@@ -1277,8 +1277,12 @@ static bool kick_pool(struct worker_pool *pool)
            !cpumask_test_cpu(p->wake_cpu, pool->attrs->__pod_cpumask)) {
                struct work_struct *work = list_first_entry(&pool->worklist,
                                                struct work_struct, entry);
-               p->wake_cpu = cpumask_any_distribute(pool->attrs->__pod_cpumask);
-               get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
+               int wake_cpu = cpumask_any_and_distribute(pool->attrs->__pod_cpumask,
+                                                         cpu_online_mask);
+               if (wake_cpu < nr_cpu_ids) {
+                       p->wake_cpu = wake_cpu;
+                       get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
+               }
        }
 #endif
        wake_up_process(p);
@@ -1594,6 +1598,15 @@ static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
        if (off_cpu >= 0)
                total_cpus--;
 
+       /* If all CPUs of the wq get offline, use the default values */
+       if (unlikely(!total_cpus)) {
+               for_each_node(node)
+                       wq_node_nr_active(wq, node)->max = min_active;
+
+               wq_node_nr_active(wq, NUMA_NO_NODE)->max = max_active;
+               return;
+       }
+
        for_each_node(node) {
                int node_cpus;
 
@@ -1606,7 +1619,7 @@ static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
                              min_active, max_active);
        }
 
-       wq_node_nr_active(wq, NUMA_NO_NODE)->max = min_active;
+       wq_node_nr_active(wq, NUMA_NO_NODE)->max = max_active;
 }
 
 /**
index c63a5fbf1f1c2b45b67603886ef9e6f07510f61d..291185f54ee4c217d04b8040b339dc1ad47f9cf6 100644 (file)
@@ -375,7 +375,7 @@ config DEBUG_INFO_SPLIT
          Incompatible with older versions of ccache.
 
 config DEBUG_INFO_BTF
-       bool "Generate BTF typeinfo"
+       bool "Generate BTF type information"
        depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED
        depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST
        depends on BPF_SYSCALL
@@ -408,7 +408,8 @@ config PAHOLE_HAS_LANG_EXCLUDE
          using DEBUG_INFO_BTF_MODULES.
 
 config DEBUG_INFO_BTF_MODULES
-       def_bool y
+       bool "Generate BTF type information for kernel modules"
+       default y
        depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF
        help
          Generate compact split BTF type information for kernel modules.
index c78f335fa98137664745e6593c98b707a528bf34..f2c5e7910bb19122f29d93b0c1e896638738b1a3 100644 (file)
@@ -302,7 +302,11 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
                } else {
                        for (end = buf; *end && !isspace(*end); end++)
                                ;
-                       BUG_ON(end == buf);
+                       if (end == buf) {
+                               pr_err("parse err after word:%d=%s\n", nwords,
+                                      nwords ? words[nwords - 1] : "<none>");
+                               return -EINVAL;
+                       }
                }
 
                /* `buf' is start of word, `end' is one past its end */
index 68b45c82c37a6981bb72cc79ab4c4fcac8e2e489..7bc2220fea805855fadd0a1ed347ea2b9195e9e9 100644 (file)
@@ -1124,7 +1124,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter,
        do {
                res = iov_iter_extract_pages(iter, &pages, maxsize, sg_max,
                                             extraction_flags, &off);
-               if (res < 0)
+               if (res <= 0)
                        goto failed;
 
                len = res;
index 68c97387aa54e2728b79b2cacf23815fcb2f90ca..cd8f23455285100036cc4f6971c81017cc0849ad 100644 (file)
@@ -627,10 +627,10 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
                /*
                 * Zero out zone modifiers, as we don't have specific zone
                 * requirements. Keep the flags related to allocation in atomic
-                * contexts and I/O.
+                * contexts, I/O, nolockdep.
                 */
                alloc_flags &= ~GFP_ZONEMASK;
-               alloc_flags &= (GFP_ATOMIC | GFP_KERNEL);
+               alloc_flags &= (GFP_ATOMIC | GFP_KERNEL | __GFP_NOLOCKDEP);
                alloc_flags |= __GFP_NOWARN;
                page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER);
                if (page)
index 31d00eee028f1179b99405f0fdd3461b16e17d2e..ce7be5c244429f71bc686399889fba7f4b6e1cf8 100644 (file)
@@ -1624,7 +1624,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h,
 {
        lockdep_assert_held(&hugetlb_lock);
 
-       folio_clear_hugetlb(folio);
+       __folio_clear_hugetlb(folio);
 }
 
 /*
@@ -1711,7 +1711,7 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio,
                h->surplus_huge_pages_node[nid]++;
        }
 
-       folio_set_hugetlb(folio);
+       __folio_set_hugetlb(folio);
        folio_change_private(folio, NULL);
        /*
         * We have to set hugetlb_vmemmap_optimized again as above
@@ -1781,7 +1781,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
         * If vmemmap pages were allocated above, then we need to clear the
         * hugetlb destructor under the hugetlb lock.
         */
-       if (clear_dtor) {
+       if (folio_test_hugetlb(folio)) {
                spin_lock_irq(&hugetlb_lock);
                __clear_hugetlb_destructor(h, folio);
                spin_unlock_irq(&hugetlb_lock);
@@ -2049,7 +2049,7 @@ static void __prep_account_new_huge_page(struct hstate *h, int nid)
 
 static void init_new_hugetlb_folio(struct hstate *h, struct folio *folio)
 {
-       folio_set_hugetlb(folio);
+       __folio_set_hugetlb(folio);
        INIT_LIST_HEAD(&folio->lru);
        hugetlb_set_folio_subpool(folio, NULL);
        set_hugetlb_cgroup(folio, NULL);
@@ -2159,22 +2159,6 @@ static bool prep_compound_gigantic_folio_for_demote(struct folio *folio,
        return __prep_compound_gigantic_folio(folio, order, true);
 }
 
-/*
- * PageHuge() only returns true for hugetlbfs pages, but not for normal or
- * transparent huge pages.  See the PageTransHuge() documentation for more
- * details.
- */
-int PageHuge(const struct page *page)
-{
-       const struct folio *folio;
-
-       if (!PageCompound(page))
-               return 0;
-       folio = page_folio(page);
-       return folio_test_hugetlb(folio);
-}
-EXPORT_SYMBOL_GPL(PageHuge);
-
 /*
  * Find and lock address space (mapping) in write mode.
  *
@@ -3268,9 +3252,12 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
 
                rsv_adjust = hugepage_subpool_put_pages(spool, 1);
                hugetlb_acct_memory(h, -rsv_adjust);
-               if (deferred_reserve)
+               if (deferred_reserve) {
+                       spin_lock_irq(&hugetlb_lock);
                        hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h),
                                        pages_per_huge_page(h), folio);
+                       spin_unlock_irq(&hugetlb_lock);
+               }
        }
 
        if (!memcg_charge_ret)
@@ -6274,6 +6261,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
                                                        VM_UFFD_MISSING);
                }
 
+               if (!(vma->vm_flags & VM_MAYSHARE)) {
+                       ret = vmf_anon_prepare(vmf);
+                       if (unlikely(ret))
+                               goto out;
+               }
+
                folio = alloc_hugetlb_folio(vma, haddr, 0);
                if (IS_ERR(folio)) {
                        /*
@@ -6310,15 +6303,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
                                 */
                                restore_reserve_on_error(h, vma, haddr, folio);
                                folio_put(folio);
+                               ret = VM_FAULT_SIGBUS;
                                goto out;
                        }
                        new_pagecache_folio = true;
                } else {
                        folio_lock(folio);
-
-                       ret = vmf_anon_prepare(vmf);
-                       if (unlikely(ret))
-                               goto backout_unlocked;
                        anon_rmap = 1;
                }
        } else {
index caed028945b046cf4caa4c842abfc900ef0a45fb..6f8850c44b6166d363d20813732d9b1befc22c61 100644 (file)
@@ -1331,15 +1331,22 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker,
        if (!gfp_has_io_fs(sc->gfp_mask))
                return 0;
 
-#ifdef CONFIG_MEMCG_KMEM
-       mem_cgroup_flush_stats(memcg);
-       nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
-       nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED);
-#else
-       /* use pool stats instead of memcg stats */
-       nr_backing = zswap_pool_total_size >> PAGE_SHIFT;
-       nr_stored = atomic_read(&zswap_nr_stored);
-#endif
+       /*
+        * For memcg, use the cgroup-wide ZSWAP stats since we don't
+        * have them per-node and thus per-lruvec. Careful if memcg is
+        * runtime-disabled: we can get sc->memcg == NULL, which is ok
+        * for the lruvec, but not for memcg_page_state().
+        *
+        * Without memcg, use the zswap pool-wide metrics.
+        */
+       if (!mem_cgroup_disabled()) {
+               mem_cgroup_flush_stats(memcg);
+               nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
+               nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED);
+       } else {
+               nr_backing = zswap_pool_total_size >> PAGE_SHIFT;
+               nr_stored = atomic_read(&zswap_nr_stored);
+       }
 
        if (!nr_stored)
                return 0;
index f001582345052f8c26e008058ae5f721f8bc224d..9404dd551dfd2850117d4edf9b7fd25e3ba84322 100644 (file)
@@ -478,6 +478,8 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
        if (unlikely(!vhdr))
                goto out;
 
+       NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = hlen;
+
        type = vhdr->h_vlan_encapsulated_proto;
 
        ptype = gro_find_receive_by_type(type);
index 558e158c98d01075b7614b754a256124c3700a84..9169efb2f43aa9151131410496d3de24af1f1ccd 100644 (file)
@@ -103,7 +103,7 @@ again:
                        s->ax25_dev = NULL;
                        if (sk->sk_socket) {
                                netdev_put(ax25_dev->dev,
-                                          &ax25_dev->dev_tracker);
+                                          &s->dev_tracker);
                                ax25_dev_put(ax25_dev);
                        }
                        ax25_cb_del(s);
index 3ad74f76983b2426ffda03ac038daea0ea34662a..05346250f7195be3e01b11a0a671193f30316c5e 100644 (file)
@@ -1263,7 +1263,7 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
 
 struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                u8 dst_type, bool dst_resolved, u8 sec_level,
-                               u16 conn_timeout, u8 role)
+                               u16 conn_timeout, u8 role, u8 phy, u8 sec_phy)
 {
        struct hci_conn *conn;
        struct smp_irk *irk;
@@ -1326,6 +1326,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
        conn->dst_type = dst_type;
        conn->sec_level = BT_SECURITY_LOW;
        conn->conn_timeout = conn_timeout;
+       conn->le_adv_phy = phy;
+       conn->le_adv_sec_phy = sec_phy;
 
        err = hci_connect_le_sync(hdev, conn);
        if (err) {
@@ -2273,7 +2275,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
                le = hci_connect_le(hdev, dst, dst_type, false,
                                    BT_SECURITY_LOW,
                                    HCI_LE_CONN_TIMEOUT,
-                                   HCI_ROLE_SLAVE);
+                                   HCI_ROLE_SLAVE, 0, 0);
        else
                le = hci_connect_le_scan(hdev, dst, dst_type,
                                         BT_SECURITY_LOW,
index a8b8cfebe0180cce2fb661e8e5f21a79bf7a7656..4a27e4a17a67449ffd8a37cb057357e20881667c 100644 (file)
@@ -3218,7 +3218,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
                        if (key) {
                                set_bit(HCI_CONN_ENCRYPT, &conn->flags);
 
-                               if (!(hdev->commands[20] & 0x10)) {
+                               if (!read_key_size_capable(hdev)) {
                                        conn->enc_key_size = HCI_LINK_KEY_SIZE;
                                } else {
                                        cp.handle = cpu_to_le16(conn->handle);
@@ -3666,8 +3666,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
                 * controller really supports it. If it doesn't, assume
                 * the default size (16).
                 */
-               if (!(hdev->commands[20] & 0x10) ||
-                   test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) {
+               if (!read_key_size_capable(hdev)) {
                        conn->enc_key_size = HCI_LINK_KEY_SIZE;
                        goto notify;
                }
@@ -6038,7 +6037,7 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
 static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
                                              bdaddr_t *addr,
                                              u8 addr_type, bool addr_resolved,
-                                             u8 adv_type)
+                                             u8 adv_type, u8 phy, u8 sec_phy)
 {
        struct hci_conn *conn;
        struct hci_conn_params *params;
@@ -6093,7 +6092,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
        conn = hci_connect_le(hdev, addr, addr_type, addr_resolved,
                              BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout,
-                             HCI_ROLE_MASTER);
+                             HCI_ROLE_MASTER, phy, sec_phy);
        if (!IS_ERR(conn)) {
                /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
                 * by higher layer that tried to connect, if no then
@@ -6128,8 +6127,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
 
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
                               u8 bdaddr_type, bdaddr_t *direct_addr,
-                              u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
-                              bool ext_adv, bool ctl_time, u64 instant)
+                              u8 direct_addr_type, u8 phy, u8 sec_phy, s8 rssi,
+                              u8 *data, u8 len, bool ext_adv, bool ctl_time,
+                              u64 instant)
 {
        struct discovery_state *d = &hdev->discovery;
        struct smp_irk *irk;
@@ -6217,7 +6217,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
         * for advertising reports) and is already verified to be RPA above.
         */
        conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
-                                    type);
+                                    type, phy, sec_phy);
        if (!ext_adv && conn && type == LE_ADV_IND &&
            len <= max_adv_len(hdev)) {
                /* Store report for later inclusion by
@@ -6363,7 +6363,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
                if (info->length <= max_adv_len(hdev)) {
                        rssi = info->data[info->length];
                        process_adv_report(hdev, info->type, &info->bdaddr,
-                                          info->bdaddr_type, NULL, 0, rssi,
+                                          info->bdaddr_type, NULL, 0,
+                                          HCI_ADV_PHY_1M, 0, rssi,
                                           info->data, info->length, false,
                                           false, instant);
                } else {
@@ -6448,6 +6449,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
                if (legacy_evt_type != LE_ADV_INVALID) {
                        process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
                                           info->bdaddr_type, NULL, 0,
+                                          info->primary_phy,
+                                          info->secondary_phy,
                                           info->rssi, info->data, info->length,
                                           !(evt_type & LE_EXT_ADV_LEGACY_PDU),
                                           false, instant);
@@ -6730,8 +6733,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
 
                process_adv_report(hdev, info->type, &info->bdaddr,
                                   info->bdaddr_type, &info->direct_addr,
-                                  info->direct_addr_type, info->rssi, NULL, 0,
-                                  false, false, instant);
+                                  info->direct_addr_type, HCI_ADV_PHY_1M, 0,
+                                  info->rssi, NULL, 0, false, false, instant);
        }
 
        hci_dev_unlock(hdev);
index c5d8799046ccffbf798e6f47ffaef3dddcb364ca..4c707eb64e6f63d8e2ea85a7ac12a31060dcf7e4 100644 (file)
@@ -6346,7 +6346,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
 
        plen = sizeof(*cp);
 
-       if (scan_1m(hdev)) {
+       if (scan_1m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_1M ||
+                             conn->le_adv_sec_phy == HCI_ADV_PHY_1M)) {
                cp->phys |= LE_SCAN_PHY_1M;
                set_ext_conn_params(conn, p);
 
@@ -6354,7 +6355,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
                plen += sizeof(*p);
        }
 
-       if (scan_2m(hdev)) {
+       if (scan_2m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_2M ||
+                             conn->le_adv_sec_phy == HCI_ADV_PHY_2M)) {
                cp->phys |= LE_SCAN_PHY_2M;
                set_ext_conn_params(conn, p);
 
@@ -6362,7 +6364,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
                plen += sizeof(*p);
        }
 
-       if (scan_coded(hdev)) {
+       if (scan_coded(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_CODED ||
+                                conn->le_adv_sec_phy == HCI_ADV_PHY_CODED)) {
                cp->phys |= LE_SCAN_PHY_CODED;
                set_ext_conn_params(conn, p);
 
index dc089740879363dd0d6d973dcdb4fc05cfc7070a..84fc70862d78aeef25d6ca9e6df7fb468338852e 100644 (file)
@@ -7018,7 +7018,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
                        hcon = hci_connect_le(hdev, dst, dst_type, false,
                                              chan->sec_level, timeout,
-                                             HCI_ROLE_SLAVE);
+                                             HCI_ROLE_SLAVE, 0, 0);
                else
                        hcon = hci_connect_le_scan(hdev, dst, dst_type,
                                                   chan->sec_level, timeout,
index e7d810b23082f5ffd8ea4b506366b2684f2e1ece..5cc83f906c123ffa7349d26a41c310005920aca5 100644 (file)
@@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
        struct l2cap_options opts;
        struct l2cap_conninfo cinfo;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
        u32 opt;
 
        BT_DBG("sk %p", sk);
@@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 
                BT_DBG("mode 0x%2.2x", chan->mode);
 
-               len = min_t(unsigned int, len, sizeof(opts));
+               len = min(len, sizeof(opts));
                if (copy_to_user(optval, (char *) &opts, len))
                        err = -EFAULT;
 
@@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
                cinfo.hci_handle = chan->conn->hcon->handle;
                memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
 
-               len = min_t(unsigned int, len, sizeof(cinfo));
+               len = min(len, sizeof(cinfo));
                if (copy_to_user(optval, (char *) &cinfo, len))
                        err = -EFAULT;
 
index 32ed6e9245a307483e69ccb1cb1dd8c30c023130..965f621ef865adb607a6ccf71f6b2e7429a10a99 100644 (file)
@@ -2623,7 +2623,11 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
                goto failed;
        }
 
-       err = hci_cmd_sync_queue(hdev, add_uuid_sync, cmd, mgmt_class_complete);
+       /* MGMT_OP_ADD_UUID don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, add_uuid_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0) {
                mgmt_pending_free(cmd);
                goto failed;
@@ -2717,8 +2721,11 @@ update_class:
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, remove_uuid_sync, cmd,
-                                mgmt_class_complete);
+       /* MGMT_OP_REMOVE_UUID don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, remove_uuid_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0)
                mgmt_pending_free(cmd);
 
@@ -2784,8 +2791,11 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, set_class_sync, cmd,
-                                mgmt_class_complete);
+       /* MGMT_OP_SET_DEV_CLASS don't require adapter the UP/Running so use
+        * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
+        */
+       err = hci_cmd_sync_submit(hdev, set_class_sync, cmd,
+                                 mgmt_class_complete);
        if (err < 0)
                mgmt_pending_free(cmd);
 
@@ -5475,8 +5485,8 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
                goto unlock;
        }
 
-       err = hci_cmd_sync_queue(hdev, mgmt_remove_adv_monitor_sync, cmd,
-                                mgmt_remove_adv_monitor_complete);
+       err = hci_cmd_sync_submit(hdev, mgmt_remove_adv_monitor_sync, cmd,
+                                 mgmt_remove_adv_monitor_complete);
 
        if (err) {
                mgmt_pending_remove(cmd);
index 368e026f4d15ca4711737af941ad30c7b48b827f..5d03c5440b06f843e654ddb0e3d3f83d4dd0cfd9 100644 (file)
@@ -964,7 +964,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
        struct sock *sk = sock->sk;
        struct sco_options opts;
        struct sco_conninfo cinfo;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
 
        BT_DBG("sk %p", sk);
 
@@ -986,7 +987,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
 
                BT_DBG("mtu %u", opts.mtu);
 
-               len = min_t(unsigned int, len, sizeof(opts));
+               len = min(len, sizeof(opts));
                if (copy_to_user(optval, (char *)&opts, len))
                        err = -EFAULT;
 
@@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
                cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
                memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
 
-               len = min_t(unsigned int, len, sizeof(cinfo));
+               len = min(len, sizeof(cinfo));
                if (copy_to_user(optval, (char *)&cinfo, len))
                        err = -EFAULT;
 
index 7431f89e897b9549a0c35d9431e36b6de2e80022..d7c35f55bd69fb5e7d3add82a4ce7c48c83b8332 100644 (file)
@@ -266,7 +266,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
        if (skb->dev == p->dev && ether_addr_equal(src, addr))
                return;
 
-       skb = skb_copy(skb, GFP_ATOMIC);
+       skb = pskb_copy(skb, GFP_ATOMIC);
        if (!skb) {
                DEV_STATS_INC(dev, tx_dropped);
                return;
index 2cf4fc756263992eefe6a3580410766fea0c2c1f..f17dbac7d82843091f9131acc68a5a9132fa2eda 100644 (file)
@@ -667,7 +667,7 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
 {
        u32 filter = RTEXT_FILTER_BRVLAN_COMPRESSED;
 
-       return br_info_notify(event, br, port, filter);
+       br_info_notify(event, br, port, filter);
 }
 
 /*
index 8adf95765cdd967a15b2661dfb454db0ccf350b0..ae5254f712c94b0c656fda5fe065ee635252a67e 100644 (file)
@@ -4360,10 +4360,12 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
        enum bpf_map_type map_type = ri->map_type;
        void *fwd = ri->tgt_value;
        u32 map_id = ri->map_id;
+       u32 flags = ri->flags;
        struct bpf_map *map;
        int err;
 
        ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */
+       ri->flags = 0;
        ri->map_type = BPF_MAP_TYPE_UNSPEC;
 
        if (unlikely(!xdpf)) {
@@ -4375,11 +4377,20 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
        case BPF_MAP_TYPE_DEVMAP:
                fallthrough;
        case BPF_MAP_TYPE_DEVMAP_HASH:
-               map = READ_ONCE(ri->map);
-               if (unlikely(map)) {
+               if (unlikely(flags & BPF_F_BROADCAST)) {
+                       map = READ_ONCE(ri->map);
+
+                       /* The map pointer is cleared when the map is being torn
+                        * down by bpf_clear_redirect_map()
+                        */
+                       if (unlikely(!map)) {
+                               err = -ENOENT;
+                               break;
+                       }
+
                        WRITE_ONCE(ri->map, NULL);
                        err = dev_map_enqueue_multi(xdpf, dev, map,
-                                                   ri->flags & BPF_F_EXCLUDE_INGRESS);
+                                                   flags & BPF_F_EXCLUDE_INGRESS);
                } else {
                        err = dev_map_enqueue(fwd, xdpf, dev);
                }
@@ -4442,9 +4453,9 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect_frame);
 static int xdp_do_generic_redirect_map(struct net_device *dev,
                                       struct sk_buff *skb,
                                       struct xdp_buff *xdp,
-                                      struct bpf_prog *xdp_prog,
-                                      void *fwd,
-                                      enum bpf_map_type map_type, u32 map_id)
+                                      struct bpf_prog *xdp_prog, void *fwd,
+                                      enum bpf_map_type map_type, u32 map_id,
+                                      u32 flags)
 {
        struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
        struct bpf_map *map;
@@ -4454,11 +4465,20 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
        case BPF_MAP_TYPE_DEVMAP:
                fallthrough;
        case BPF_MAP_TYPE_DEVMAP_HASH:
-               map = READ_ONCE(ri->map);
-               if (unlikely(map)) {
+               if (unlikely(flags & BPF_F_BROADCAST)) {
+                       map = READ_ONCE(ri->map);
+
+                       /* The map pointer is cleared when the map is being torn
+                        * down by bpf_clear_redirect_map()
+                        */
+                       if (unlikely(!map)) {
+                               err = -ENOENT;
+                               break;
+                       }
+
                        WRITE_ONCE(ri->map, NULL);
                        err = dev_map_redirect_multi(dev, skb, xdp_prog, map,
-                                                    ri->flags & BPF_F_EXCLUDE_INGRESS);
+                                                    flags & BPF_F_EXCLUDE_INGRESS);
                } else {
                        err = dev_map_generic_redirect(fwd, skb, xdp_prog);
                }
@@ -4495,9 +4515,11 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
        enum bpf_map_type map_type = ri->map_type;
        void *fwd = ri->tgt_value;
        u32 map_id = ri->map_id;
+       u32 flags = ri->flags;
        int err;
 
        ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */
+       ri->flags = 0;
        ri->map_type = BPF_MAP_TYPE_UNSPEC;
 
        if (map_type == BPF_MAP_TYPE_UNSPEC && map_id == INT_MAX) {
@@ -4517,7 +4539,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
                return 0;
        }
 
-       return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id);
+       return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id, flags);
 err:
        _trace_xdp_redirect_err(dev, xdp_prog, ri->tgt_index, err);
        return err;
index 83f35d99a682c21dae11683fec72074a898fbac2..c7901253a1a8fc1e9425add77014e15b363a1623 100644 (file)
@@ -371,6 +371,7 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
        const skb_frag_t *frag0;
        unsigned int headlen;
 
+       NAPI_GRO_CB(skb)->network_offset = 0;
        NAPI_GRO_CB(skb)->data_offset = 0;
        headlen = skb_headlen(skb);
        NAPI_GRO_CB(skb)->frag0 = skb->data;
index b99127712e6704dda41636014db46096da171bfd..4096e679f61c76041223b894e3ee4f9a8a051000 100644 (file)
@@ -2123,11 +2123,17 @@ static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
 
 struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
 {
-       int headerlen = skb_headroom(skb);
-       unsigned int size = skb_end_offset(skb) + skb->data_len;
-       struct sk_buff *n = __alloc_skb(size, gfp_mask,
-                                       skb_alloc_rx_flag(skb), NUMA_NO_NODE);
+       struct sk_buff *n;
+       unsigned int size;
+       int headerlen;
+
+       if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
+               return NULL;
 
+       headerlen = skb_headroom(skb);
+       size = skb_end_offset(skb) + skb->data_len;
+       n = __alloc_skb(size, gfp_mask,
+                       skb_alloc_rx_flag(skb), NUMA_NO_NODE);
        if (!n)
                return NULL;
 
@@ -2455,12 +2461,17 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
        /*
         *      Allocate the copy buffer
         */
-       struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom,
-                                       gfp_mask, skb_alloc_rx_flag(skb),
-                                       NUMA_NO_NODE);
-       int oldheadroom = skb_headroom(skb);
        int head_copy_len, head_copy_off;
+       struct sk_buff *n;
+       int oldheadroom;
+
+       if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
+               return NULL;
 
+       oldheadroom = skb_headroom(skb);
+       n = __alloc_skb(newheadroom + skb->len + newtailroom,
+                       gfp_mask, skb_alloc_rx_flag(skb),
+                       NUMA_NO_NODE);
        if (!n)
                return NULL;
 
index 4d75ef9d24bfa7cbffe642448f5116ac0b943ed2..fd20aae30be23cc2241f081a1d56215f9693cab0 100644 (file)
@@ -1226,11 +1226,8 @@ static void sk_psock_verdict_data_ready(struct sock *sk)
 
                rcu_read_lock();
                psock = sk_psock(sk);
-               if (psock) {
-                       read_lock_bh(&sk->sk_callback_lock);
+               if (psock)
                        sk_psock_data_ready(sk, psock);
-                       read_unlock_bh(&sk->sk_callback_lock);
-               }
                rcu_read_unlock();
        }
 }
index 2edc8b796a4e7326aa44128a0618e15b9aa817de..049c3adeb85044ac78e5adf7dcfb389d21e75652 100644 (file)
@@ -164,17 +164,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        eth = (struct ethhdr *)skb->data;
        skb_pull_inline(skb, ETH_HLEN);
 
-       if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
-                                             dev->dev_addr))) {
-               if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
-                       if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
-                               skb->pkt_type = PACKET_BROADCAST;
-                       else
-                               skb->pkt_type = PACKET_MULTICAST;
-               } else {
-                       skb->pkt_type = PACKET_OTHERHOST;
-               }
-       }
+       eth_skb_pkt_type(skb, dev);
 
        /*
         * Some variants of DSA tagging don't have an ethertype field
index 55bd72997b31063b7baad350fdcff40e938aecb8..fafb123f798be346c247dac0f9dc8e498e034349 100644 (file)
@@ -1572,6 +1572,7 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
        /* The above will be needed by the transport layer if there is one
         * immediately following this IP hdr.
         */
+       NAPI_GRO_CB(skb)->inner_network_offset = off;
 
        /* Note : No need to call skb_gro_postpull_rcsum() here,
         * as we already checked checksum over ipv4 header was 0
index e63a3bf99617627e17669f9b3aaee1cbbf178ebf..437e782b9663bb59acb900c0558137ddd401cd02 100644 (file)
@@ -92,6 +92,7 @@
 #include <net/inet_common.h>
 #include <net/ip_fib.h>
 #include <net/l3mdev.h>
+#include <net/addrconf.h>
 
 /*
  *     Build xmit assembly blocks
@@ -1032,6 +1033,8 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
        struct icmp_ext_hdr *ext_hdr, _ext_hdr;
        struct icmp_ext_echo_iio *iio, _iio;
        struct net *net = dev_net(skb->dev);
+       struct inet6_dev *in6_dev;
+       struct in_device *in_dev;
        struct net_device *dev;
        char buff[IFNAMSIZ];
        u16 ident_len;
@@ -1115,10 +1118,15 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
        /* Fill bits in reply message */
        if (dev->flags & IFF_UP)
                status |= ICMP_EXT_ECHOREPLY_ACTIVE;
-       if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list)
+
+       in_dev = __in_dev_get_rcu(dev);
+       if (in_dev && rcu_access_pointer(in_dev->ifa_list))
                status |= ICMP_EXT_ECHOREPLY_IPV4;
-       if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list))
+
+       in6_dev = __in6_dev_get(dev);
+       if (in6_dev && !list_empty(&in6_dev->addr_list))
                status |= ICMP_EXT_ECHOREPLY_IPV6;
+
        dev_put(dev);
        icmphdr->un.echo.sequence |= htons(status);
        return true;
index 1fe794967211e249016df00dc3c2ae230d71dcff..39229fd0601a11c3f2e58cd1e75db165a443b1a2 100644 (file)
@@ -1473,7 +1473,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
                 * by icmp_hdr(skb)->type.
                 */
                if (sk->sk_type == SOCK_RAW &&
-                   !inet_test_bit(HDRINCL, sk))
+                   !(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH))
                        icmp_type = fl4->fl4_icmp_type;
                else
                        icmp_type = icmp_hdr(skb)->type;
index dcb11f22cbf2b437405d1b373dd0ebc37d02c9ec..4cb43401e0e06c5003c268c28bf0882ac4e8b4e0 100644 (file)
@@ -612,6 +612,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                            (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0, sk->sk_uid);
 
+       fl4.fl4_icmp_type = 0;
+       fl4.fl4_icmp_code = 0;
+
        if (!hdrincl) {
                rfv.msg = msg;
                rfv.hlen = 0;
index d36ace160d426f6224f8e692f3b438ae863bb9b9..b814fdab19f710d066d323970be6ce57a3b583c5 100644 (file)
@@ -2166,6 +2166,9 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        int err = -EINVAL;
        u32 tag = 0;
 
+       if (!in_dev)
+               return -EINVAL;
+
        if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
                goto martian_source;
 
index 3afeeb68e8a7e2a30ce9c4d92dcc8b150314b669..781b67a525719a42f21b713eb424427670d7afb2 100644 (file)
@@ -1068,6 +1068,7 @@ void tcp_ao_connect_init(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_ao_info *ao_info;
+       struct hlist_node *next;
        union tcp_ao_addr *addr;
        struct tcp_ao_key *key;
        int family, l3index;
@@ -1090,7 +1091,7 @@ void tcp_ao_connect_init(struct sock *sk)
        l3index = l3mdev_master_ifindex_by_index(sock_net(sk),
                                                 sk->sk_bound_dev_if);
 
-       hlist_for_each_entry_rcu(key, &ao_info->head, node) {
+       hlist_for_each_entry_safe(key, next, &ao_info->head, node) {
                if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1))
                        continue;
 
index c02bf011d4a6f487b2c69e48e5032068eed3debc..b32cf2eeeb41d1fc0bbe24e4888301f344ec8488 100644 (file)
@@ -532,7 +532,8 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
 struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
                                 __be16 sport, __be16 dport)
 {
-       const struct iphdr *iph = ip_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
        struct net *net = dev_net(skb->dev);
        int iif, sdif;
 
@@ -1123,16 +1124,17 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        if (msg->msg_controllen) {
                err = udp_cmsg_send(sk, msg, &ipc.gso_size);
-               if (err > 0)
+               if (err > 0) {
                        err = ip_cmsg_send(sk, msg, &ipc,
                                           sk->sk_family == AF_INET6);
+                       connected = 0;
+               }
                if (unlikely(err < 0)) {
                        kfree(ipc.opt);
                        return err;
                }
                if (ipc.opt)
                        free = 1;
-               connected = 0;
        }
        if (!ipc.opt) {
                struct ip_options_rcu *inet_opt;
index 3498dd1d0694dc3ddb984177d2ddffb7b8abd0b9..8721fe5beca2bea692eb2cfa454e724e649cea6d 100644 (file)
@@ -471,6 +471,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
        struct sk_buff *p;
        unsigned int ulen;
        int ret = 0;
+       int flush;
 
        /* requires non zero csum, for symmetry with GSO */
        if (!uh->check) {
@@ -504,13 +505,22 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
                        return p;
                }
 
+               flush = NAPI_GRO_CB(p)->flush;
+
+               if (NAPI_GRO_CB(p)->flush_id != 1 ||
+                   NAPI_GRO_CB(p)->count != 1 ||
+                   !NAPI_GRO_CB(p)->is_atomic)
+                       flush |= NAPI_GRO_CB(p)->flush_id;
+               else
+                       NAPI_GRO_CB(p)->is_atomic = false;
+
                /* Terminate the flow on len mismatch or if it grow "too much".
                 * Under small packet flood GRO count could elsewhere grow a lot
                 * leading to excessive truesize values.
                 * On len mismatch merge the first packet shorter than gso_size,
                 * otherwise complete the GRO packet.
                 */
-               if (ulen > ntohs(uh2->len)) {
+               if (ulen > ntohs(uh2->len) || flush) {
                        pp = p;
                } else {
                        if (NAPI_GRO_CB(skb)->is_flist) {
@@ -718,7 +728,8 @@ EXPORT_SYMBOL(udp_gro_complete);
 
 INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
 {
-       const struct iphdr *iph = ip_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
        struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
 
        /* do fraglist only if there is no outer UDP encap (or we already processed it) */
index b41e35af69ea2835aa47d6ca01d9b109d4092462..c8b909a9904f321b91c9cfef46da9bb491c18a7d 100644 (file)
@@ -237,6 +237,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
                goto out;
 
        skb_set_network_header(skb, off);
+       NAPI_GRO_CB(skb)->inner_network_offset = off;
 
        flush += ntohs(iph->payload_len) != skb->len - hlen;
 
index 8b1dd7f512491d806e4d0a9fc5297a255dafd5a4..8f7aa8bac1e7b1eb330e4a6a9086b88e509886be 100644 (file)
@@ -272,7 +272,8 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
 struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
                                 __be16 sport, __be16 dport)
 {
-       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + offset);
        struct net *net = dev_net(skb->dev);
        int iif, sdif;
 
@@ -1474,9 +1475,11 @@ do_udp_sendmsg:
                ipc6.opt = opt;
 
                err = udp_cmsg_send(sk, msg, &ipc6.gso_size);
-               if (err > 0)
+               if (err > 0) {
                        err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, fl6,
                                                    &ipc6);
+                       connected = false;
+               }
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -1488,7 +1491,6 @@ do_udp_sendmsg:
                }
                if (!(opt->opt_nflen|opt->opt_flen))
                        opt = NULL;
-               connected = false;
        }
        if (!opt) {
                opt = txopt_get(np);
index bbd347de00b450bb3ecbbfa41c4dab9d36bb79d9..b41152dd424697a9fc3cef13fbb430de49dcb913 100644 (file)
@@ -164,7 +164,8 @@ flush:
 
 INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff)
 {
-       const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+       const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
+       const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + offset);
        struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
 
        /* do fraglist only if there is no outer UDP encap (or we already processed it) */
index 39e487ccc46881b2ede597672b0e3df63ba8b05a..8ba00ad433c21bfc8f6566bed1360cb8e4cf4944 100644 (file)
@@ -127,6 +127,9 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
        /* checksums verified by L2TP */
        skb->ip_summed = CHECKSUM_NONE;
 
+       /* drop outer flow-hash */
+       skb_clear_hash(skb);
+
        skb_dst_drop(skb);
        nf_reset_ct(skb);
 
index 80e4b9784131d149c6acf27f79be0b0c16edec85..ccacaed32817aed59240034f85753c47a353501a 100644 (file)
@@ -797,6 +797,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_chanctx_conf *conf;
        struct ieee80211_chanctx *curr_ctx = NULL;
+       bool new_idle;
        int ret = 0;
 
        if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
@@ -829,8 +830,6 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
 out:
        rcu_assign_pointer(link->conf->chanctx_conf, conf);
 
-       sdata->vif.cfg.idle = !conf;
-
        if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
                ieee80211_recalc_chanctx_chantype(local, curr_ctx);
                ieee80211_recalc_smps_chanctx(local, curr_ctx);
@@ -843,9 +842,27 @@ out:
                ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL);
        }
 
-       if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
-           sdata->vif.type != NL80211_IFTYPE_MONITOR)
-               ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
+       if (conf) {
+               new_idle = false;
+       } else {
+               struct ieee80211_link_data *tmp;
+
+               new_idle = true;
+               for_each_sdata_link(local, tmp) {
+                       if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
+                               new_idle = false;
+                               break;
+                       }
+               }
+       }
+
+       if (new_idle != sdata->vif.cfg.idle) {
+               sdata->vif.cfg.idle = new_idle;
+
+               if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
+                   sdata->vif.type != NL80211_IFTYPE_MONITOR)
+                       ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
+       }
 
        ieee80211_check_fast_xmit_iface(sdata);
 
index 32475da98d739cbe66d200f6bd8e8b0542f3cb04..cbc9b5e40cb35e81fb80dd55016c3afc8c31deb7 100644 (file)
@@ -747,6 +747,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                              struct sk_buff *skb, u32 ctrl_flags)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+       struct ieee80211_mesh_fast_tx_key key = {
+               .type = MESH_FAST_TX_TYPE_LOCAL
+       };
        struct ieee80211_mesh_fast_tx *entry;
        struct ieee80211s_hdr *meshhdr;
        u8 sa[ETH_ALEN] __aligned(2);
@@ -782,7 +785,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                        return false;
        }
 
-       entry = mesh_fast_tx_get(sdata, skb->data);
+       ether_addr_copy(key.addr, skb->data);
+       if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
+               key.type = MESH_FAST_TX_TYPE_PROXIED;
+       entry = mesh_fast_tx_get(sdata, &key);
        if (!entry)
                return false;
 
index d913ce7ba72ef897fb6857f55df3fb20bc871b5e..3f9664e4e00c6c2e51faaa43d1a23860a6d22e4c 100644 (file)
@@ -134,10 +134,39 @@ struct mesh_path {
 #define MESH_FAST_TX_CACHE_THRESHOLD_SIZE      384
 #define MESH_FAST_TX_CACHE_TIMEOUT             8000 /* msecs */
 
+/**
+ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
+ *
+ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
+ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
+ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
+ * @NUM_MESH_FAST_TX_TYPE: number of entry types
+ */
+enum ieee80211_mesh_fast_tx_type {
+       MESH_FAST_TX_TYPE_LOCAL,
+       MESH_FAST_TX_TYPE_PROXIED,
+       MESH_FAST_TX_TYPE_FORWARDED,
+
+       /* must be last */
+       NUM_MESH_FAST_TX_TYPE
+};
+
+
+/**
+ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
+ *
+ * @addr: The Ethernet DA for this entry
+ * @type: cache entry type
+ */
+struct ieee80211_mesh_fast_tx_key {
+       u8 addr[ETH_ALEN] __aligned(2);
+       u16 type;
+};
+
 /**
  * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
  * @rhash: rhashtable pointer
- * @addr_key: The Ethernet DA which is the key for this entry
+ * @key: the lookup key for this cache entry
  * @fast_tx: base fast_tx data
  * @hdr: cached mesh and rfc1042 headers
  * @hdrlen: length of mesh + rfc1042
@@ -148,7 +177,7 @@ struct mesh_path {
  */
 struct ieee80211_mesh_fast_tx {
        struct rhash_head rhash;
-       u8 addr_key[ETH_ALEN] __aligned(2);
+       struct ieee80211_mesh_fast_tx_key key;
 
        struct ieee80211_fast_tx fast_tx;
        u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
@@ -334,7 +363,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
 
 bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
 struct ieee80211_mesh_fast_tx *
-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_mesh_fast_tx_key *key);
 bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
                              struct sk_buff *skb, u32 ctrl_flags);
 void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
index 91b55d6a68b9739f9d22786bf403c801fc34d864..a6b62169f08483c5aa481f4f8f59f67fa56a4ef7 100644 (file)
@@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = {
 static const struct rhashtable_params fast_tx_rht_params = {
        .nelem_hint = 10,
        .automatic_shrinking = true,
-       .key_len = ETH_ALEN,
-       .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
+       .key_len = sizeof_field(struct ieee80211_mesh_fast_tx, key),
+       .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
        .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
        .hashfn = mesh_table_hash,
 };
@@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
 }
 
 struct ieee80211_mesh_fast_tx *
-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
+mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_mesh_fast_tx_key *key)
 {
        struct ieee80211_mesh_fast_tx *entry;
        struct mesh_tx_cache *cache;
 
        cache = &sdata->u.mesh.tx_cache;
-       entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+       entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
        if (!entry)
                return NULL;
 
        if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
            mpath_expired(entry->mpath)) {
                spin_lock_bh(&cache->walk_lock);
-               entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+               entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
                if (entry)
                    mesh_fast_tx_entry_free(cache, entry);
                spin_unlock_bh(&cache->walk_lock);
@@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
        if (!sta)
                return;
 
+       build.key.type = MESH_FAST_TX_TYPE_LOCAL;
        if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
                /* This is required to keep the mppath alive */
                mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
                if (!mppath)
                        return;
                build.mppath = mppath;
+               if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
+                       build.key.type = MESH_FAST_TX_TYPE_PROXIED;
        } else if (ieee80211_has_a4(hdr->frame_control)) {
                mppath = mpath;
        } else {
                return;
        }
 
+       if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
+               build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
+
        /* rate limit, in case fast xmit can't be enabled */
        if (mppath->fast_tx_check == jiffies)
                return;
@@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       memcpy(build.addr_key, mppath->dst, ETH_ALEN);
+       memcpy(build.key.addr, mppath->dst, ETH_ALEN);
        build.timestamp = jiffies;
        build.fast_tx.band = info->band;
        build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
@@ -646,12 +653,18 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
                             const u8 *addr)
 {
        struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
+       struct ieee80211_mesh_fast_tx_key key = {};
        struct ieee80211_mesh_fast_tx *entry;
+       int i;
 
+       ether_addr_copy(key.addr, addr);
        spin_lock_bh(&cache->walk_lock);
-       entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
-       if (entry)
-               mesh_fast_tx_entry_free(cache, entry);
+       for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) {
+               key.type = i;
+               entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
+               if (entry)
+                       mesh_fast_tx_entry_free(cache, entry);
+       }
        spin_unlock_bh(&cache->walk_lock);
 }
 
index 96b70006b7fc0b11b12f423fb74ec32a030d91af..3bbb216a0fc8ce58138420d13008b2240e260a77 100644 (file)
@@ -616,7 +616,6 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
                .from_ap = true,
                .start = ies->data,
                .len = ies->len,
-               .mode = conn->mode,
        };
        struct ieee802_11_elems *elems;
        struct ieee80211_supported_band *sband;
@@ -625,6 +624,7 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
        int ret;
 
 again:
+       parse_params.mode = conn->mode;
        elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                return ERR_PTR(-ENOMEM);
@@ -632,15 +632,21 @@ again:
        ap_mode = ieee80211_determine_ap_chan(sdata, channel, bss->vht_cap_info,
                                              elems, false, conn, &ap_chandef);
 
-       mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n",
-                        cbss->bssid, ieee80211_conn_mode_str(ap_mode));
-
        /* this should be impossible since parsing depends on our mode */
        if (WARN_ON(ap_mode > conn->mode)) {
                ret = -EINVAL;
                goto free;
        }
 
+       if (conn->mode != ap_mode) {
+               conn->mode = ap_mode;
+               kfree(elems);
+               goto again;
+       }
+
+       mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n",
+                        cbss->bssid, ieee80211_conn_mode_str(ap_mode));
+
        sband = sdata->local->hw.wiphy->bands[channel->band];
 
        switch (channel->band) {
@@ -691,7 +697,6 @@ again:
                break;
        }
 
-       conn->mode = ap_mode;
        chanreq->oper = ap_chandef;
 
        /* wider-bandwidth OFDMA is only done in EHT */
@@ -753,8 +758,10 @@ again:
        }
 
        /* the mode can only decrease, so this must terminate */
-       if (ap_mode != conn->mode)
+       if (ap_mode != conn->mode) {
+               kfree(elems);
                goto again;
+       }
 
        mlme_link_id_dbg(sdata, link_id,
                         "connecting with %s mode, max bandwidth %d MHz\n",
@@ -5812,7 +5819,7 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
                 */
                if (control &
                    IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT)
-                       link_removal_timeout[link_id] = le16_to_cpu(*(__le16 *)pos);
+                       link_removal_timeout[link_id] = get_unaligned_le16(pos);
        }
 
        removed_links &= sdata->vif.valid_links;
@@ -5837,8 +5844,11 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
                        continue;
                }
 
-               link_delay = link_conf->beacon_int *
-                       link_removal_timeout[link_id];
+               if (link_removal_timeout[link_id] < 1)
+                       link_delay = 0;
+               else
+                       link_delay = link_conf->beacon_int *
+                               (link_removal_timeout[link_id] - 1);
 
                if (!delay)
                        delay = link_delay;
@@ -6193,7 +6203,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
                        link->u.mgd.dtim_period = elems->dtim_period;
                link->u.mgd.have_beacon = true;
                ifmgd->assoc_data->need_beacon = false;
-               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
+               if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
+                   !ieee80211_is_s1g_beacon(hdr->frame_control)) {
                        link->conf->sync_tsf =
                                le64_to_cpu(mgmt->u.beacon.timestamp);
                        link->conf->sync_device_ts =
index 23404b275457a74868cd935653bc1a6192ec4cb5..4dc1def695486567b486fdada893557752f8df43 100644 (file)
@@ -877,6 +877,7 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_supported_band *sband;
+       u32 mask = ~0;
 
        rate_control_fill_sta_table(sta, info, dest, max_rates);
 
@@ -889,9 +890,12 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
        if (ieee80211_is_tx_data(skb))
                rate_control_apply_mask(sdata, sta, sband, dest, max_rates);
 
+       if (!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX))
+               mask = sdata->rc_rateidx_mask[info->band];
+
        if (dest[0].idx < 0)
                __rate_control_send_low(&sdata->local->hw, sband, sta, info,
-                                       sdata->rc_rateidx_mask[info->band]);
+                                       mask);
 
        if (sta)
                rate_fixup_ratelist(vif, sband, info, dest, max_rates);
index c1f8501384056d3ebbb9ba7ddbd5c659c579d582..6e24864f9a40ba1b8d689263cf905cc0ff5d3d69 100644 (file)
@@ -2763,7 +2763,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
                               struct sk_buff *skb, int hdrlen)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       struct ieee80211_mesh_fast_tx *entry = NULL;
+       struct ieee80211_mesh_fast_tx_key key = {
+               .type = MESH_FAST_TX_TYPE_FORWARDED
+       };
+       struct ieee80211_mesh_fast_tx *entry;
        struct ieee80211s_hdr *mesh_hdr;
        struct tid_ampdu_tx *tid_tx;
        struct sta_info *sta;
@@ -2772,9 +2775,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
 
        mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
        if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-               entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
+               ether_addr_copy(key.addr, mesh_hdr->eaddr1);
        else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
-               entry = mesh_fast_tx_get(sdata, skb->data);
+               ether_addr_copy(key.addr, skb->data);
+       else
+               return false;
+
+       entry = mesh_fast_tx_get(sdata, &key);
        if (!entry)
                return false;
 
@@ -3780,6 +3787,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_PROTECTED_EHT:
+               if (len < offsetofend(typeof(*mgmt),
+                                     u.action.u.ttlm_req.action_code))
+                       break;
+
                switch (mgmt->u.action.u.ttlm_req.action_code) {
                case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ:
                        if (sdata->vif.type != NL80211_IFTYPE_STATION)
index 0429e59ba387c931f42ae1e74255a7deb5ebf5d6..73850312580f7054c60550dd5a2486583ab48f0a 100644 (file)
@@ -648,6 +648,7 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata,
                                cpu_to_le16(IEEE80211_SN_TO_SEQ(sn));
                }
                IEEE80211_SKB_CB(skb)->flags |= tx_flags;
+               IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_SCAN_TX;
                ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
        }
 }
index 6bf223e6cd1a54aa432ef0bd41da48cd9316ffc5..cfd0a62d0152bd28f32fbb022cdbd094defefca4 100644 (file)
@@ -698,11 +698,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
        txrc.bss_conf = &tx->sdata->vif.bss_conf;
        txrc.skb = tx->skb;
        txrc.reported_rate.idx = -1;
-       txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
 
-       if (tx->sdata->rc_has_mcs_mask[info->band])
-               txrc.rate_idx_mcs_mask =
-                       tx->sdata->rc_rateidx_mcs_mask[info->band];
+       if (unlikely(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) {
+               txrc.rate_idx_mask = ~0;
+       } else {
+               txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
+
+               if (tx->sdata->rc_has_mcs_mask[info->band])
+                       txrc.rate_idx_mcs_mask =
+                               tx->sdata->rc_rateidx_mcs_mask[info->band];
+       }
 
        txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
                    tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
index 7e74b812e366ae311f52615e9b304d6fe8b924b8..965eb69dc5de32b0d0ec01e5270b20a4fcb436b3 100644 (file)
@@ -3723,6 +3723,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT);
                mptcp_subflow_early_fallback(msk, subflow);
        }
+
+       WRITE_ONCE(msk->write_seq, subflow->idsn);
+       WRITE_ONCE(msk->snd_nxt, subflow->idsn);
        if (likely(!__mptcp_check_fallback(msk)))
                MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE);
 
index a0921adc31a9ffe7db09d18e7ae54213a79a8fd7..1e689c71412716e04f417cdb62d9fb56b730a1ab 100644 (file)
@@ -126,7 +126,8 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
        if (sctph->source != cp->vport || payload_csum ||
            skb->ip_summed == CHECKSUM_PARTIAL) {
                sctph->source = cp->vport;
-               sctp_nat_csum(skb, sctph, sctphoff);
+               if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
+                       sctp_nat_csum(skb, sctph, sctphoff);
        } else {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
@@ -174,7 +175,8 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
            (skb->ip_summed == CHECKSUM_PARTIAL &&
             !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) {
                sctph->dest = cp->dport;
-               sctp_nat_csum(skb, sctph, sctphoff);
+               if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
+                       sctp_nat_csum(skb, sctph, sctphoff);
        } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
index 274b6f7e6bb57e4f270262ef923ebf8d7f1cf02c..d170758a1eb5d08929cc4cd8e8acd350e793524e 100644 (file)
@@ -338,7 +338,9 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
                return;
 
        if (n > 1) {
-               nf_unregister_net_hook(ctx->net, &found->ops);
+               if (!(ctx->chain->table->flags & NFT_TABLE_F_DORMANT))
+                       nf_unregister_net_hook(ctx->net, &found->ops);
+
                list_del_rcu(&found->list);
                kfree_rcu(found, rcu);
                return;
index f4a38bd6a7e04f5944f8fa3d7f3cdc43caffed41..bfb7758063f315f4d13a6c17f8b01739933a6cf3 100644 (file)
@@ -77,13 +77,15 @@ EXPORT_SYMBOL_GPL(nsh_pop);
 static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
+       unsigned int outer_hlen, mac_len, nsh_len;
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        u16 mac_offset = skb->mac_header;
-       unsigned int nsh_len, mac_len;
-       __be16 proto;
+       __be16 outer_proto, proto;
 
        skb_reset_network_header(skb);
 
+       outer_proto = skb->protocol;
+       outer_hlen = skb_mac_header_len(skb);
        mac_len = skb->mac_len;
 
        if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
@@ -113,10 +115,10 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
        }
 
        for (skb = segs; skb; skb = skb->next) {
-               skb->protocol = htons(ETH_P_NSH);
-               __skb_push(skb, nsh_len);
-               skb->mac_header = mac_offset;
-               skb->network_header = skb->mac_header + mac_len;
+               skb->protocol = outer_proto;
+               __skb_push(skb, nsh_len + outer_hlen);
+               skb_reset_mac_header(skb);
+               skb_set_network_header(skb, outer_hlen);
                skb->mac_len = mac_len;
        }
 
index 74b63cdb59923a95dd03a9c2c540af702564873a..2928c142a2ddb3a0d9b1937fdb4ddd37322b3f45 100644 (file)
@@ -1593,9 +1593,9 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
        for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
                struct hlist_head *head = &info->limits[i];
                struct ovs_ct_limit *ct_limit;
+               struct hlist_node *next;
 
-               hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
-                                        lockdep_ovsl_is_held())
+               hlist_for_each_entry_safe(ct_limit, next, head, hlist_node)
                        kfree_rcu(ct_limit, rcu);
        }
        kfree(info->limits);
index 0af4642aeec4bcba890cfe0723b4ae001b378cf8..1539d315afe74ace265dd7ac32ffc7031d0b2323 100644 (file)
@@ -119,18 +119,13 @@ struct rxrpc_connection *rxrpc_find_client_connection_rcu(struct rxrpc_local *lo
        switch (srx->transport.family) {
        case AF_INET:
                if (peer->srx.transport.sin.sin_port !=
-                   srx->transport.sin.sin_port ||
-                   peer->srx.transport.sin.sin_addr.s_addr !=
-                   srx->transport.sin.sin_addr.s_addr)
+                   srx->transport.sin.sin_port)
                        goto not_found;
                break;
 #ifdef CONFIG_AF_RXRPC_IPV6
        case AF_INET6:
                if (peer->srx.transport.sin6.sin6_port !=
-                   srx->transport.sin6.sin6_port ||
-                   memcmp(&peer->srx.transport.sin6.sin6_addr,
-                          &srx->transport.sin6.sin6_addr,
-                          sizeof(struct in6_addr)) != 0)
+                   srx->transport.sin6.sin6_port)
                        goto not_found;
                break;
 #endif
index f2701068ed9e4ce48c52848901e983f21de459c7..6716c021a532e184e5e09e50c958e4128d9f97bf 100644 (file)
@@ -19,7 +19,7 @@ static int none_init_connection_security(struct rxrpc_connection *conn,
  */
 static struct rxrpc_txbuf *none_alloc_txbuf(struct rxrpc_call *call, size_t remain, gfp_t gfp)
 {
-       return rxrpc_alloc_data_txbuf(call, min_t(size_t, remain, RXRPC_JUMBO_DATALEN), 0, gfp);
+       return rxrpc_alloc_data_txbuf(call, min_t(size_t, remain, RXRPC_JUMBO_DATALEN), 1, gfp);
 }
 
 static int none_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
index f1a68270862db9715801594e754f48d7a77d822d..48a1475e6b0634cc806641f4d5a134684d1c56cf 100644 (file)
@@ -155,7 +155,7 @@ static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t rem
        switch (call->conn->security_level) {
        default:
                space = min_t(size_t, remain, RXRPC_JUMBO_DATALEN);
-               return rxrpc_alloc_data_txbuf(call, space, 0, gfp);
+               return rxrpc_alloc_data_txbuf(call, space, 1, gfp);
        case RXRPC_SECURITY_AUTH:
                shdr = sizeof(struct rxkad_level1_hdr);
                break;
index e0679658d9de0e62edd777cad0b7e4281cfe2384..c3913d8a50d340bff0636f144f6c65afbe755cdd 100644 (file)
@@ -21,20 +21,20 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
 {
        struct rxrpc_wire_header *whdr;
        struct rxrpc_txbuf *txb;
-       size_t total, hoff = 0;
+       size_t total, hoff;
        void *buf;
 
        txb = kmalloc(sizeof(*txb), gfp);
        if (!txb)
                return NULL;
 
-       if (data_align)
-               hoff = round_up(sizeof(*whdr), data_align) - sizeof(*whdr);
+       hoff = round_up(sizeof(*whdr), data_align) - sizeof(*whdr);
        total = hoff + sizeof(*whdr) + data_size;
 
+       data_align = umax(data_align, L1_CACHE_BYTES);
        mutex_lock(&call->conn->tx_data_alloc_lock);
-       buf = __page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp,
-                                     ~(data_align - 1) & ~(L1_CACHE_BYTES - 1));
+       buf = page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp,
+                                   data_align);
        mutex_unlock(&call->conn->tx_data_alloc_lock);
        if (!buf) {
                kfree(txb);
index f2a100c4c81f12e8ed91d0400938b53e3dd0dc46..40797114d50a49a4e10cb30c182f094fc8e7313d 100644 (file)
@@ -230,28 +230,6 @@ static void svc_rdma_write_info_free(struct svc_rdma_write_info *info)
        queue_work(svcrdma_wq, &info->wi_work);
 }
 
-/**
- * svc_rdma_write_chunk_release - Release Write chunk I/O resources
- * @rdma: controlling transport
- * @ctxt: Send context that is being released
- */
-void svc_rdma_write_chunk_release(struct svcxprt_rdma *rdma,
-                                 struct svc_rdma_send_ctxt *ctxt)
-{
-       struct svc_rdma_write_info *info;
-       struct svc_rdma_chunk_ctxt *cc;
-
-       while (!list_empty(&ctxt->sc_write_info_list)) {
-               info = list_first_entry(&ctxt->sc_write_info_list,
-                                       struct svc_rdma_write_info, wi_list);
-               list_del(&info->wi_list);
-
-               cc = &info->wi_cc;
-               svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount);
-               svc_rdma_write_info_free(info);
-       }
-}
-
 /**
  * svc_rdma_reply_chunk_release - Release Reply chunk I/O resources
  * @rdma: controlling transport
@@ -308,11 +286,13 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
        struct ib_cqe *cqe = wc->wr_cqe;
        struct svc_rdma_chunk_ctxt *cc =
                        container_of(cqe, struct svc_rdma_chunk_ctxt, cc_cqe);
+       struct svc_rdma_write_info *info =
+                       container_of(cc, struct svc_rdma_write_info, wi_cc);
 
        switch (wc->status) {
        case IB_WC_SUCCESS:
                trace_svcrdma_wc_write(&cc->cc_cid);
-               return;
+               break;
        case IB_WC_WR_FLUSH_ERR:
                trace_svcrdma_wc_write_flush(wc, &cc->cc_cid);
                break;
@@ -320,11 +300,12 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
                trace_svcrdma_wc_write_err(wc, &cc->cc_cid);
        }
 
-       /* The RDMA Write has flushed, so the client won't get
-        * some of the outgoing RPC message. Signal the loss
-        * to the client by closing the connection.
-        */
-       svc_xprt_deferred_close(&rdma->sc_xprt);
+       svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount);
+
+       if (unlikely(wc->status != IB_WC_SUCCESS))
+               svc_xprt_deferred_close(&rdma->sc_xprt);
+
+       svc_rdma_write_info_free(info);
 }
 
 /**
@@ -620,19 +601,13 @@ static int svc_rdma_xb_write(const struct xdr_buf *xdr, void *data)
        return xdr->len;
 }
 
-/* Link Write WRs for @chunk onto @sctxt's WR chain.
- */
-static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
-                                       struct svc_rdma_send_ctxt *sctxt,
-                                       const struct svc_rdma_chunk *chunk,
-                                       const struct xdr_buf *xdr)
+static int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma,
+                                    const struct svc_rdma_chunk *chunk,
+                                    const struct xdr_buf *xdr)
 {
        struct svc_rdma_write_info *info;
        struct svc_rdma_chunk_ctxt *cc;
-       struct ib_send_wr *first_wr;
        struct xdr_buf payload;
-       struct list_head *pos;
-       struct ib_cqe *cqe;
        int ret;
 
        if (xdr_buf_subsegment(xdr, &payload, chunk->ch_position,
@@ -648,25 +623,10 @@ static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma,
        if (ret != payload.len)
                goto out_err;
 
-       ret = -EINVAL;
-       if (unlikely(cc->cc_sqecount > rdma->sc_sq_depth))
-               goto out_err;
-
-       first_wr = sctxt->sc_wr_chain;
-       cqe = &cc->cc_cqe;
-       list_for_each(pos, &cc->cc_rwctxts) {
-               struct svc_rdma_rw_ctxt *rwc;
-
-               rwc = list_entry(pos, struct svc_rdma_rw_ctxt, rw_list);
-               first_wr = rdma_rw_ctx_wrs(&rwc->rw_ctx, rdma->sc_qp,
-                                          rdma->sc_port_num, cqe, first_wr);
-               cqe = NULL;
-       }
-       sctxt->sc_wr_chain = first_wr;
-       sctxt->sc_sqecount += cc->cc_sqecount;
-       list_add(&info->wi_list, &sctxt->sc_write_info_list);
-
        trace_svcrdma_post_write_chunk(&cc->cc_cid, cc->cc_sqecount);
+       ret = svc_rdma_post_chunk_ctxt(rdma, cc);
+       if (ret < 0)
+               goto out_err;
        return 0;
 
 out_err:
@@ -675,27 +635,25 @@ out_err:
 }
 
 /**
- * svc_rdma_prepare_write_list - Construct WR chain for sending Write list
+ * svc_rdma_send_write_list - Send all chunks on the Write list
  * @rdma: controlling RDMA transport
- * @write_pcl: Write list provisioned by the client
- * @sctxt: Send WR resources
+ * @rctxt: Write list provisioned by the client
  * @xdr: xdr_buf containing an RPC Reply message
  *
  * Returns zero on success, or a negative errno if one or more
  * Write chunks could not be sent.
  */
-int svc_rdma_prepare_write_list(struct svcxprt_rdma *rdma,
-                               const struct svc_rdma_pcl *write_pcl,
-                               struct svc_rdma_send_ctxt *sctxt,
-                               const struct xdr_buf *xdr)
+int svc_rdma_send_write_list(struct svcxprt_rdma *rdma,
+                            const struct svc_rdma_recv_ctxt *rctxt,
+                            const struct xdr_buf *xdr)
 {
        struct svc_rdma_chunk *chunk;
        int ret;
 
-       pcl_for_each_chunk(chunk, write_pcl) {
+       pcl_for_each_chunk(chunk, &rctxt->rc_write_pcl) {
                if (!chunk->ch_payload_length)
                        break;
-               ret = svc_rdma_prepare_write_chunk(rdma, sctxt, chunk, xdr);
+               ret = svc_rdma_send_write_chunk(rdma, chunk, xdr);
                if (ret < 0)
                        return ret;
        }
index dfca39abd16c8860ade9a8f3fc0be4bc023361cd..bb5436b719e05126e250596b61b39230204620c3 100644 (file)
@@ -142,7 +142,6 @@ svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma)
        ctxt->sc_send_wr.sg_list = ctxt->sc_sges;
        ctxt->sc_send_wr.send_flags = IB_SEND_SIGNALED;
        ctxt->sc_cqe.done = svc_rdma_wc_send;
-       INIT_LIST_HEAD(&ctxt->sc_write_info_list);
        ctxt->sc_xprt_buf = buffer;
        xdr_buf_init(&ctxt->sc_hdrbuf, ctxt->sc_xprt_buf,
                     rdma->sc_max_req_size);
@@ -228,7 +227,6 @@ static void svc_rdma_send_ctxt_release(struct svcxprt_rdma *rdma,
        struct ib_device *device = rdma->sc_cm_id->device;
        unsigned int i;
 
-       svc_rdma_write_chunk_release(rdma, ctxt);
        svc_rdma_reply_chunk_release(rdma, ctxt);
 
        if (ctxt->sc_page_count)
@@ -1015,8 +1013,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        if (!p)
                goto put_ctxt;
 
-       ret = svc_rdma_prepare_write_list(rdma, &rctxt->rc_write_pcl, sctxt,
-                                         &rqstp->rq_res);
+       ret = svc_rdma_send_write_list(rdma, rctxt, &rqstp->rq_res);
        if (ret < 0)
                goto put_ctxt;
 
index bb9b747d58a1afac3619b80cff3e8196e36d96c3..ce18716491c8fed0cbe234f2044e3539c3bac6a3 100644 (file)
@@ -2664,6 +2664,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
                .xprtsec        = {
                        .policy         = RPC_XPRTSEC_NONE,
                },
+               .stats          = upper_clnt->cl_stats,
        };
        unsigned int pflags = current->flags;
        struct rpc_clnt *lower_clnt;
index 5c9fd4791c4ba1976f1d3d7fcb9ad458df1436f7..76284fc538ebdd38d52c879bd4fc58c84abc6371 100644 (file)
@@ -142,9 +142,9 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (fragid == FIRST_FRAGMENT) {
                if (unlikely(head))
                        goto err;
-               *buf = NULL;
                if (skb_has_frag_list(frag) && __skb_linearize(frag))
                        goto err;
+               *buf = NULL;
                frag = skb_unshare(frag, GFP_ATOMIC);
                if (unlikely(!frag))
                        goto err;
@@ -156,6 +156,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (!head)
                goto err;
 
+       /* Either the input skb ownership is transferred to headskb
+        * or the input skb is freed, clear the reference to avoid
+        * bad access on error path.
+        */
+       *buf = NULL;
        if (skb_try_coalesce(head, frag, &headstolen, &delta)) {
                kfree_skb_partial(frag, headstolen);
        } else {
@@ -179,7 +184,6 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
                *headbuf = NULL;
                return 1;
        }
-       *buf = NULL;
        return 0;
 err:
        kfree_skb(*buf);
index 762f424ff2d59c51ba176bc9dff81b499542fb5c..e5e47452308ab713032d58eedbff68bee9dc3a8d 100644 (file)
@@ -215,7 +215,7 @@ static inline struct sk_buff *tls_strp_msg(struct tls_sw_context_rx *ctx)
 
 static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
 {
-       return ctx->strp.msg_ready;
+       return READ_ONCE(ctx->strp.msg_ready);
 }
 
 static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
index ca1e0e198ceb452fac72dd48f22ea0a1dcddee6b..5df08d848b5c9c9cf36e21a78c7bc59f38a8f22b 100644 (file)
@@ -360,7 +360,7 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
        if (strp->stm.full_len && strp->stm.full_len == skb->len) {
                desc->count = 0;
 
-               strp->msg_ready = 1;
+               WRITE_ONCE(strp->msg_ready, 1);
                tls_rx_msg_ready(strp);
        }
 
@@ -528,7 +528,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
        if (!tls_strp_check_queue_ok(strp))
                return tls_strp_read_copy(strp, false);
 
-       strp->msg_ready = 1;
+       WRITE_ONCE(strp->msg_ready, 1);
        tls_rx_msg_ready(strp);
 
        return 0;
@@ -580,7 +580,7 @@ void tls_strp_msg_done(struct tls_strparser *strp)
        else
                tls_strp_flush_anchor_copy(strp);
 
-       strp->msg_ready = 0;
+       WRITE_ONCE(strp->msg_ready, 0);
        memset(&strp->stm, 0, sizeof(strp->stm));
 
        tls_strp_check_rcv(strp);
index 6433a414acf8624a1d98727f4e309b7c040710b9..0104be9d4704563791b1c1558fcbf166649fee25 100644 (file)
@@ -299,7 +299,7 @@ static void __unix_gc(struct work_struct *work)
                        __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
 
                        if (sk->sk_state == TCP_LISTEN) {
-                               unix_state_lock(sk);
+                               unix_state_lock_nested(sk, U_LOCK_GC_LISTENER);
                                unix_state_unlock(sk);
                        }
                }
index b4edba6b0b7ba0bf3200c7ce966a3e286a6fdf24..30ff9a47081348d1b14d1db520aeedf9c9ffdd09 100644 (file)
@@ -14030,6 +14030,8 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
 error:
        for (i = 0; i < new_coalesce.n_rules; i++) {
                tmp_rule = &new_coalesce.rules[i];
+               if (!tmp_rule)
+                       continue;
                for (j = 0; j < tmp_rule->n_patterns; j++)
                        kfree(tmp_rule->patterns[j].mask);
                kfree(tmp_rule->patterns);
index cbbf347c6b2e099802b135266ca7fae59bd467f9..df013c98b80dfb0e06a86a78415e51d79cd76693 100644 (file)
@@ -1758,7 +1758,7 @@ TRACE_EVENT(rdev_return_void_tx_rx,
 
 DECLARE_EVENT_CLASS(tx_rx_evt,
        TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
-       TP_ARGS(wiphy, rx, tx),
+       TP_ARGS(wiphy, tx, rx),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                __field(u32, tx)
@@ -1775,7 +1775,7 @@ DECLARE_EVENT_CLASS(tx_rx_evt,
 
 DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
        TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
-       TP_ARGS(wiphy, rx, tx)
+       TP_ARGS(wiphy, tx, rx)
 );
 
 DECLARE_EVENT_CLASS(wiphy_netdev_id_evt,
index 846e6ab9d5a9b660fd871a13c8f984260a1b105a..86a125c4243cb2e5eba7f906417be4602bd8b738 100644 (file)
@@ -175,7 +175,6 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
        mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
        OBJTREE=$(abspath $(objtree)) \
        $(RUSTDOC) --test $(rust_flags) \
-               @$(objtree)/include/generated/rustc_cfg \
                -L$(objtree)/$(obj) --extern alloc --extern kernel \
                --extern build_error --extern macros \
                --extern bindings --extern uapi \
index 424257284d167b5caa23ed880353abbd7ef2de34..09004b56fb65c7aadcf857a41086159b6fa1f550 100644 (file)
@@ -1292,8 +1292,15 @@ impl_zeroable! {
     i8, i16, i32, i64, i128, isize,
     f32, f64,
 
-    // SAFETY: These are ZSTs, there is nothing to zero.
-    {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, Infallible, (),
+    // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
+    // creating an instance of an uninhabited type is immediate undefined behavior. For more on
+    // uninhabited/empty types, consult The Rustonomicon:
+    // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
+    // also has information on undefined behavior:
+    // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
+    //
+    // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
+    {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
 
     // SAFETY: Type is allowed to take any value, including all zeros.
     {<T>} MaybeUninit<T>,
index be68d5e567b1a1f7a181e08586ed05f2ca008cd6..6858e2f8a3ed976ce644eb2f8ea4d9fbb40edc3b 100644 (file)
@@ -65,7 +65,7 @@ const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
 /// The top level entrypoint to implementing a kernel module.
 ///
 /// For any teardown or cleanup operations, your type may implement [`Drop`].
-pub trait Module: Sized + Sync {
+pub trait Module: Sized + Sync + Send {
     /// Called at module initialization time.
     ///
     /// Use this method to perform whatever setup or registration your module
index 96e09c6e8530b4d108e6a664e93ab41436c797dc..265d0e1c13710a53a9f9d0b5af12b24402eb4741 100644 (file)
@@ -640,6 +640,10 @@ pub struct Registration {
     drivers: Pin<&'static mut [DriverVTable]>,
 }
 
+// SAFETY: The only action allowed in a `Registration` instance is dropping it, which is safe to do
+// from any thread because `phy_drivers_unregister` can be called from any thread context.
+unsafe impl Send for Registration {}
+
 impl Registration {
     /// Registers a PHY driver.
     pub fn register(
index f489f3157383239d81c0badd5085627d431e6c4c..520eae5fd792810069d8018d922f6c56c0bcc101 100644 (file)
@@ -35,18 +35,6 @@ use proc_macro::TokenStream;
 ///     author: "Rust for Linux Contributors",
 ///     description: "My very own kernel module!",
 ///     license: "GPL",
-///     params: {
-///        my_i32: i32 {
-///            default: 42,
-///            permissions: 0o000,
-///            description: "Example of i32",
-///        },
-///        writeable_i32: i32 {
-///            default: 42,
-///            permissions: 0o644,
-///            description: "Example of i32",
-///        },
-///    },
 /// }
 ///
 /// struct MyModule;
index 27979e582e4b943b963a88ee7cecdea4f345b83f..acd0393b509574b0989bedcf1ed244532ab63a29 100644 (file)
@@ -199,17 +199,6 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
             /// Used by the printing macros, e.g. [`info!`].
             const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
 
-            /// The \"Rust loadable module\" mark.
-            //
-            // This may be best done another way later on, e.g. as a new modinfo
-            // key or a new section. For the moment, keep it simple.
-            #[cfg(MODULE)]
-            #[doc(hidden)]
-            #[used]
-            static __IS_RUST_MODULE: () = ();
-
-            static mut __MOD: Option<{type_}> = None;
-
             // SAFETY: `__this_module` is constructed by the kernel at load time and will not be
             // freed until the module is unloaded.
             #[cfg(MODULE)]
@@ -221,81 +210,132 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
                 kernel::ThisModule::from_ptr(core::ptr::null_mut())
             }};
 
-            // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
-            /// # Safety
-            ///
-            /// This function must not be called after module initialization, because it may be
-            /// freed after that completes.
-            #[cfg(MODULE)]
-            #[doc(hidden)]
-            #[no_mangle]
-            #[link_section = \".init.text\"]
-            pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
-                __init()
-            }}
-
-            #[cfg(MODULE)]
-            #[doc(hidden)]
-            #[no_mangle]
-            pub extern \"C\" fn cleanup_module() {{
-                __exit()
-            }}
+            // Double nested modules, since then nobody can access the public items inside.
+            mod __module_init {{
+                mod __module_init {{
+                    use super::super::{type_};
+
+                    /// The \"Rust loadable module\" mark.
+                    //
+                    // This may be best done another way later on, e.g. as a new modinfo
+                    // key or a new section. For the moment, keep it simple.
+                    #[cfg(MODULE)]
+                    #[doc(hidden)]
+                    #[used]
+                    static __IS_RUST_MODULE: () = ();
+
+                    static mut __MOD: Option<{type_}> = None;
+
+                    // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
+                    /// # Safety
+                    ///
+                    /// This function must not be called after module initialization, because it may be
+                    /// freed after that completes.
+                    #[cfg(MODULE)]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    #[link_section = \".init.text\"]
+                    pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
+                        // SAFETY: This function is inaccessible to the outside due to the double
+                        // module wrapping it. It is called exactly once by the C side via its
+                        // unique name.
+                        unsafe {{ __init() }}
+                    }}
 
-            // Built-in modules are initialized through an initcall pointer
-            // and the identifiers need to be unique.
-            #[cfg(not(MODULE))]
-            #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
-            #[doc(hidden)]
-            #[link_section = \"{initcall_section}\"]
-            #[used]
-            pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
+                    #[cfg(MODULE)]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    pub extern \"C\" fn cleanup_module() {{
+                        // SAFETY:
+                        // - This function is inaccessible to the outside due to the double
+                        //   module wrapping it. It is called exactly once by the C side via its
+                        //   unique name,
+                        // - furthermore it is only called after `init_module` has returned `0`
+                        //   (which delegates to `__init`).
+                        unsafe {{ __exit() }}
+                    }}
 
-            #[cfg(not(MODULE))]
-            #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
-            core::arch::global_asm!(
-                r#\".section \"{initcall_section}\", \"a\"
-                __{name}_initcall:
-                    .long   __{name}_init - .
-                    .previous
-                \"#
-            );
+                    // Built-in modules are initialized through an initcall pointer
+                    // and the identifiers need to be unique.
+                    #[cfg(not(MODULE))]
+                    #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
+                    #[doc(hidden)]
+                    #[link_section = \"{initcall_section}\"]
+                    #[used]
+                    pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
+
+                    #[cfg(not(MODULE))]
+                    #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
+                    core::arch::global_asm!(
+                        r#\".section \"{initcall_section}\", \"a\"
+                        __{name}_initcall:
+                            .long   __{name}_init - .
+                            .previous
+                        \"#
+                    );
+
+                    #[cfg(not(MODULE))]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
+                        // SAFETY: This function is inaccessible to the outside due to the double
+                        // module wrapping it. It is called exactly once by the C side via its
+                        // placement above in the initcall section.
+                        unsafe {{ __init() }}
+                    }}
 
-            #[cfg(not(MODULE))]
-            #[doc(hidden)]
-            #[no_mangle]
-            pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
-                __init()
-            }}
+                    #[cfg(not(MODULE))]
+                    #[doc(hidden)]
+                    #[no_mangle]
+                    pub extern \"C\" fn __{name}_exit() {{
+                        // SAFETY:
+                        // - This function is inaccessible to the outside due to the double
+                        //   module wrapping it. It is called exactly once by the C side via its
+                        //   unique name,
+                        // - furthermore it is only called after `__{name}_init` has returned `0`
+                        //   (which delegates to `__init`).
+                        unsafe {{ __exit() }}
+                    }}
 
-            #[cfg(not(MODULE))]
-            #[doc(hidden)]
-            #[no_mangle]
-            pub extern \"C\" fn __{name}_exit() {{
-                __exit()
-            }}
+                    /// # Safety
+                    ///
+                    /// This function must only be called once.
+                    unsafe fn __init() -> core::ffi::c_int {{
+                        match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
+                            Ok(m) => {{
+                                // SAFETY: No data race, since `__MOD` can only be accessed by this
+                                // module and there only `__init` and `__exit` access it. These
+                                // functions are only called once and `__exit` cannot be called
+                                // before or during `__init`.
+                                unsafe {{
+                                    __MOD = Some(m);
+                                }}
+                                return 0;
+                            }}
+                            Err(e) => {{
+                                return e.to_errno();
+                            }}
+                        }}
+                    }}
 
-            fn __init() -> core::ffi::c_int {{
-                match <{type_} as kernel::Module>::init(&THIS_MODULE) {{
-                    Ok(m) => {{
+                    /// # Safety
+                    ///
+                    /// This function must
+                    /// - only be called once,
+                    /// - be called after `__init` has been called and returned `0`.
+                    unsafe fn __exit() {{
+                        // SAFETY: No data race, since `__MOD` can only be accessed by this module
+                        // and there only `__init` and `__exit` access it. These functions are only
+                        // called once and `__init` was already called.
                         unsafe {{
-                            __MOD = Some(m);
+                            // Invokes `drop()` on `__MOD`, which should be used for cleanup.
+                            __MOD = None;
                         }}
-                        return 0;
-                    }}
-                    Err(e) => {{
-                        return e.to_errno();
                     }}
-                }}
-            }}
 
-            fn __exit() {{
-                unsafe {{
-                    // Invokes `drop()` on `__MOD`, which should be used for cleanup.
-                    __MOD = None;
+                    {modinfo}
                 }}
             }}
-
-            {modinfo}
         ",
         type_ = info.type_,
         name = info.name,
index baf86c0880b6d7d548f4a6a21cd6305acc717078..533a7799fdfe6d1848ab6c5c6f7ef67990f8c9b0 100644 (file)
@@ -273,7 +273,7 @@ rust_common_cmd = \
        -Zallow-features=$(rust_allowed_features) \
        -Zcrate-attr=no_std \
        -Zcrate-attr='feature($(rust_allowed_features))' \
-       --extern alloc --extern kernel \
+       -Zunstable-options --extern force:alloc --extern kernel \
        --crate-type rlib -L $(objtree)/rust/ \
        --crate-name $(basename $(notdir $@)) \
        --sysroot=/dev/null \
index 6a384b922e4fada5bfed7fa8b7e0f95ea7e3457a..d1f6cdcf1866e4162286b32072f7a21dc93ea94f 100644 (file)
@@ -557,9 +557,32 @@ static const struct config_entry *snd_intel_dsp_find_config
                if (table->codec_hid) {
                        int i;
 
-                       for (i = 0; i < table->codec_hid->num_codecs; i++)
-                               if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
+                       for (i = 0; i < table->codec_hid->num_codecs; i++) {
+                               struct nhlt_acpi_table *nhlt;
+                               bool ssp_found = false;
+
+                               if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
+                                       continue;
+
+                               nhlt = intel_nhlt_init(&pci->dev);
+                               if (!nhlt) {
+                                       dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n",
+                                                __func__, table->codec_hid->codecs[i]);
+                                       continue;
+                               }
+
+                               if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) &&
+                                   intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S))
+                                       ssp_found = true;
+
+                               intel_nhlt_free(nhlt);
+
+                               if (ssp_found)
                                        break;
+
+                               dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n",
+                                        __func__, table->codec_hid->codecs[i]);
+                       }
                        if (i == table->codec_hid->num_codecs)
                                continue;
                }
index 5f60658c6051c90bf06b42c8d39a53e3dd54c1f1..d7417a40392b2dc02647ff3ffb0802cfada6fa35 100644 (file)
@@ -45,6 +45,8 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx)
                                 "intel-quirk-mask",
                                 &quirk_mask);
 
+       fwnode_handle_put(link);
+
        if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
                return false;
 
index fe72e7d7724127418b0b5351e64f6dc0d8b2c831..dadeda7758ceebce94d6205d38b0807b1e6c5587 100644 (file)
@@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev)
 
        emu->suspend = 1;
 
-       cancel_work_sync(&emu->emu1010.firmware_work);
-       cancel_work_sync(&emu->emu1010.clock_work);
+       cancel_work_sync(&emu->emu1010.work);
 
        snd_ac97_suspend(emu->ac97);
 
index de5c41e578e1f4ac3cf085f1c8b20c75a545fce8..8ccc0178360ce8c0a5d70b920d212ca299310fd6 100644 (file)
@@ -732,69 +732,67 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
        return snd_emu1010_load_firmware_entry(emu, *fw);
 }
 
-static void emu1010_firmware_work(struct work_struct *work)
+static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu)
 {
-       struct snd_emu10k1 *emu;
-       u32 tmp, tmp2, reg;
+       u32 tmp, tmp2;
        int err;
 
-       emu = container_of(work, struct snd_emu10k1,
-                          emu1010.firmware_work);
-       if (emu->card->shutdown)
+       // The docking events clearly arrive prematurely - while the
+       // Dock's FPGA seems to be successfully programmed, the Dock
+       // fails to initialize subsequently if we don't give it some
+       // time to "warm up" here.
+       msleep(200);
+
+       dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n");
+       /* Return to Audio Dock programming mode */
+       snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
+                              EMU_HANA_FPGA_CONFIG_AUDIODOCK);
+       err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
+       if (err < 0)
                return;
-#ifdef CONFIG_PM_SLEEP
-       if (emu->suspend)
+       snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
+
+       snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
+       dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
+       if ((tmp & 0x1f) != 0x15) {
+               /* FPGA failed to be programmed */
+               dev_err(emu->card->dev,
+                       "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n",
+                       tmp);
                return;
-#endif
+       }
+       dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n");
+
+       snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
+       snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
+       dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
+
+       /* Allow DLL to settle, to sync clocking between 1010 and Dock */
+       msleep(10);
+}
+
+static void emu1010_dock_event(struct snd_emu10k1 *emu)
+{
+       u32 reg;
+
        snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
        if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
                /* Audio Dock attached */
-               /* Return to Audio Dock programming mode */
-               dev_info(emu->card->dev,
-                        "emu1010: Loading Audio Dock Firmware\n");
-               snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
-                                      EMU_HANA_FPGA_CONFIG_AUDIODOCK);
-               err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
-               if (err < 0)
-                       return;
-               snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
-               snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
-               dev_info(emu->card->dev,
-                        "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
-               if ((tmp & 0x1f) != 0x15) {
-                       /* FPGA failed to be programmed */
-                       dev_info(emu->card->dev,
-                                "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
-                                tmp);
-                       return;
-               }
-               dev_info(emu->card->dev,
-                        "emu1010: Audio Dock Firmware loaded\n");
-               snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
-               snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
-               dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
-               /* Sync clocking between 1010 and Dock */
-               /* Allow DLL to settle */
-               msleep(10);
+               snd_emu1010_load_dock_firmware(emu);
                /* Unmute all. Default is muted after a firmware load */
                snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
+       } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) {
+               /* Audio Dock removed */
+               dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
+               /* The hardware auto-mutes all, so we unmute again */
+               snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
        }
 }
 
-static void emu1010_clock_work(struct work_struct *work)
+static void emu1010_clock_event(struct snd_emu10k1 *emu)
 {
-       struct snd_emu10k1 *emu;
        struct snd_ctl_elem_id id;
 
-       emu = container_of(work, struct snd_emu10k1,
-                          emu1010.clock_work);
-       if (emu->card->shutdown)
-               return;
-#ifdef CONFIG_PM_SLEEP
-       if (emu->suspend)
-               return;
-#endif
-
        spin_lock_irq(&emu->reg_lock);
        // This is the only thing that can actually happen.
        emu->emu1010.clock_source = emu->emu1010.clock_fallback;
@@ -805,21 +803,44 @@ static void emu1010_clock_work(struct work_struct *work)
        snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
 }
 
-static void emu1010_interrupt(struct snd_emu10k1 *emu)
+static void emu1010_work(struct work_struct *work)
 {
+       struct snd_emu10k1 *emu;
        u32 sts;
 
+       emu = container_of(work, struct snd_emu10k1, emu1010.work);
+       if (emu->card->shutdown)
+               return;
+#ifdef CONFIG_PM_SLEEP
+       if (emu->suspend)
+               return;
+#endif
+
+       snd_emu1010_fpga_lock(emu);
+
        snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts);
-       if (sts & EMU_HANA_IRQ_DOCK_LOST) {
-               /* Audio Dock removed */
-               dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
-               /* The hardware auto-mutes all, so we unmute again */
-               snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
-       } else if (sts & EMU_HANA_IRQ_DOCK) {
-               schedule_work(&emu->emu1010.firmware_work);
-       }
+
+       // The distinction of the IRQ status bits is unreliable,
+       // so we dispatch later based on option card status.
+       if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST))
+               emu1010_dock_event(emu);
+
        if (sts & EMU_HANA_IRQ_WCLK_CHANGED)
-               schedule_work(&emu->emu1010.clock_work);
+               emu1010_clock_event(emu);
+
+       snd_emu1010_fpga_unlock(emu);
+}
+
+static void emu1010_interrupt(struct snd_emu10k1 *emu)
+{
+       // We get an interrupt on each GPIO input pin change, but we
+       // care only about the ones triggered by the dedicated pin.
+       u16 sts = inw(emu->port + A_GPIO);
+       u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000;
+       if (!(sts & bit))
+               return;
+
+       schedule_work(&emu->emu1010.work);
 }
 
 /*
@@ -841,6 +862,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
         * Proper init follows in snd_emu10k1_init(). */
        outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
 
+       snd_emu1010_fpga_lock(emu);
+
        /* Disable 48Volt power to Audio Dock */
        snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
 
@@ -866,7 +889,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
        if (err < 0) {
                dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
-               return err;
+               goto fail;
        }
 
        /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
@@ -876,7 +899,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
                dev_info(emu->card->dev,
                         "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n",
                         reg);
-               return -ENODEV;
+               err = -ENODEV;
+               goto fail;
        }
 
        dev_info(emu->card->dev, "emu1010: Hana Firmware loaded\n");
@@ -889,7 +913,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
        dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
        if (reg & EMU_HANA_OPTION_DOCK_OFFLINE)
-               schedule_work(&emu->emu1010.firmware_work);
+               snd_emu1010_load_dock_firmware(emu);
        if (emu->card_capabilities->no_adat) {
                emu->emu1010.optical_in = 0; /* IN_SPDIF */
                emu->emu1010.optical_out = 0; /* OUT_SPDIF */
@@ -936,7 +960,9 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
        // so it is safe to simply enable the outputs.
        snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
 
-       return 0;
+fail:
+       snd_emu1010_fpga_unlock(emu);
+       return err;
 }
 /*
  *  Create the EMU10K1 instance
@@ -958,10 +984,10 @@ static void snd_emu10k1_free(struct snd_card *card)
        }
        if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
                /* Disable 48Volt power to Audio Dock */
-               snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_DOCK_PWR, 0);
        }
-       cancel_work_sync(&emu->emu1010.firmware_work);
-       cancel_work_sync(&emu->emu1010.clock_work);
+       cancel_work_sync(&emu->emu1010.work);
+       mutex_destroy(&emu->emu1010.lock);
        release_firmware(emu->firmware);
        release_firmware(emu->dock_fw);
        snd_util_memhdr_free(emu->memhdr);
@@ -1540,8 +1566,8 @@ int snd_emu10k1_create(struct snd_card *card,
        emu->irq = -1;
        emu->synth = NULL;
        emu->get_synth_voice = NULL;
-       INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
-       INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work);
+       INIT_WORK(&emu->emu1010.work, emu1010_work);
+       mutex_init(&emu->emu1010.lock);
        /* read revision & serial */
        emu->revision = pci->revision;
        pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
index 0a32ea53d8c648a78f44227579a76c5e111eda89..05b98d9b547b2a9ffd063649311887693b1b20de 100644 (file)
@@ -661,7 +661,9 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
        change = (emu->emu1010.output_source[channel] != val);
        if (change) {
                emu->emu1010.output_source[channel] = val;
+               snd_emu1010_fpga_lock(emu);
                snd_emu1010_output_source_apply(emu, channel, val);
+               snd_emu1010_fpga_unlock(emu);
        }
        return change;
 }
@@ -705,7 +707,9 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
        change = (emu->emu1010.input_source[channel] != val);
        if (change) {
                emu->emu1010.input_source[channel] = val;
+               snd_emu1010_fpga_lock(emu);
                snd_emu1010_input_source_apply(emu, channel, val);
+               snd_emu1010_fpga_unlock(emu);
        }
        return change;
 }
@@ -774,7 +778,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
                cache = cache & ~mask;
        change = (cache != emu->emu1010.adc_pads);
        if (change) {
-               snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache );
                emu->emu1010.adc_pads = cache;
        }
 
@@ -832,7 +836,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
                cache = cache & ~mask;
        change = (cache != emu->emu1010.dac_pads);
        if (change) {
-               snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache );
                emu->emu1010.dac_pads = cache;
        }
 
@@ -980,6 +984,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
        val = ucontrol->value.enumerated.item[0] ;
        if (val >= emu_ci->num)
                return -EINVAL;
+       snd_emu1010_fpga_lock(emu);
        spin_lock_irq(&emu->reg_lock);
        change = (emu->emu1010.clock_source != val);
        if (change) {
@@ -996,6 +1001,7 @@ static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
        } else {
                spin_unlock_irq(&emu->reg_lock);
        }
+       snd_emu1010_fpga_unlock(emu);
        return change;
 }
 
@@ -1041,7 +1047,7 @@ static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol,
        change = (emu->emu1010.clock_fallback != val);
        if (change) {
                emu->emu1010.clock_fallback = val;
-               snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 1 - val);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val);
        }
        return change;
 }
@@ -1093,7 +1099,7 @@ static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
                emu->emu1010.optical_out = val;
                tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
                        (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
-               snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
        }
        return change;
 }
@@ -1144,7 +1150,7 @@ static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
                emu->emu1010.optical_in = val;
                tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
                        (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
-               snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
+               snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
        }
        return change;
 }
@@ -2323,7 +2329,9 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                for (i = 0; i < emu_ri->n_outs; i++)
                        emu->emu1010.output_source[i] =
                                emu1010_map_source(emu_ri, emu_ri->out_dflts[i]);
+               snd_emu1010_fpga_lock(emu);
                snd_emu1010_apply_sources(emu);
+               snd_emu1010_fpga_unlock(emu);
 
                kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu);
                err = snd_ctl_add(card, kctl);
index 2f80fd91017c3994e40017f9a9bb5c22ea21603a..737c28d31b41a39a4ca1ddb335df6b907c8e8a30 100644 (file)
@@ -165,6 +165,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
        u32 value2;
 
        if (emu->card_capabilities->emu_model) {
+               snd_emu1010_fpga_lock(emu);
+
                // This represents the S/PDIF lock status on 0404b, which is
                // kinda weird and unhelpful, because monitoring it via IRQ is
                // impractical (one gets an IRQ flood as long as it is desynced).
@@ -197,6 +199,8 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
                        snd_iprintf(buffer, "\nS/PDIF mode: %s%s\n",
                                    value & EMU_HANA_SPDIF_MODE_RX_PRO ? "professional" : "consumer",
                                    value & EMU_HANA_SPDIF_MODE_RX_NOCOPY ? ", no copy" : "");
+
+               snd_emu1010_fpga_unlock(emu);
        } else {
                snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
                snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
@@ -458,6 +462,9 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
        int i;
+
+       snd_emu1010_fpga_lock(emu);
+
        snd_iprintf(buffer, "EMU1010 Registers:\n\n");
 
        for(i = 0; i < 0x40; i+=1) {
@@ -496,6 +503,8 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
                        snd_emu_proc_emu1010_link_read(emu, buffer, 0x701);
                }
        }
+
+       snd_emu1010_fpga_unlock(emu);
 }
 
 static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
index 74df2330015f66ef3930d05884092d74e4b100af..f4a1c2d4b0787518634dac52ebae9c41a01f05dc 100644 (file)
@@ -285,24 +285,33 @@ static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32
        outw(value, emu->port + A_GPIO);
        udelay(10);
        outw(value | 0x80 , emu->port + A_GPIO);  /* High bit clocks the value into the fpga. */
+       udelay(10);
 }
 
 void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
 {
-       unsigned long flags;
+       if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
+               return;
+       snd_emu1010_fpga_write_locked(emu, reg, value);
+}
 
-       spin_lock_irqsave(&emu->emu_lock, flags);
+void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value)
+{
+       snd_emu1010_fpga_lock(emu);
        snd_emu1010_fpga_write_locked(emu, reg, value);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
+       snd_emu1010_fpga_unlock(emu);
 }
 
-static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *value)
+void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
 {
        // The higest input pin is used as the designated interrupt trigger,
        // so it needs to be masked out.
        // But note that any other input pin change will also cause an IRQ,
        // so using this function often causes an IRQ as a side effect.
        u32 mask = emu->card_capabilities->ca0108_chip ? 0x1f : 0x7f;
+
+       if (snd_BUG_ON(!mutex_is_locked(&emu->emu1010.lock)))
+               return;
        if (snd_BUG_ON(reg > 0x3f))
                return;
        reg += 0x40; /* 0x40 upwards are registers. */
@@ -313,47 +322,31 @@ static void snd_emu1010_fpga_read_locked(struct snd_emu10k1 *emu, u32 reg, u32 *
        *value = ((inw(emu->port + A_GPIO) >> 8) & mask);
 }
 
-void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&emu->emu_lock, flags);
-       snd_emu1010_fpga_read_locked(emu, reg, value);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
-}
-
 /* Each Destination has one and only one Source,
  * but one Source can feed any number of Destinations simultaneously.
  */
 void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src)
 {
-       unsigned long flags;
-
        if (snd_BUG_ON(dst & ~0x71f))
                return;
        if (snd_BUG_ON(src & ~0x71f))
                return;
-       spin_lock_irqsave(&emu->emu_lock, flags);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCHI, src >> 8);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_SRCLO, src & 0x1f);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
+       snd_emu1010_fpga_write(emu, EMU_HANA_SRCHI, src >> 8);
+       snd_emu1010_fpga_write(emu, EMU_HANA_SRCLO, src & 0x1f);
 }
 
 u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst)
 {
-       unsigned long flags;
        u32 hi, lo;
 
        if (snd_BUG_ON(dst & ~0x71f))
                return 0;
-       spin_lock_irqsave(&emu->emu_lock, flags);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTHI, dst >> 8);
-       snd_emu1010_fpga_write_locked(emu, EMU_HANA_DESTLO, dst & 0x1f);
-       snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCHI, &hi);
-       snd_emu1010_fpga_read_locked(emu, EMU_HANA_SRCLO, &lo);
-       spin_unlock_irqrestore(&emu->emu_lock, flags);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTHI, dst >> 8);
+       snd_emu1010_fpga_write(emu, EMU_HANA_DESTLO, dst & 0x1f);
+       snd_emu1010_fpga_read(emu, EMU_HANA_SRCHI, &hi);
+       snd_emu1010_fpga_read(emu, EMU_HANA_SRCLO, &lo);
        return (hi << 8) | lo;
 }
 
index 1a3f84599cb584331f9766ca6bd5b00bacaa580d..558c1f38fe971859d809e25d774069e73cc642b1 100644 (file)
@@ -644,6 +644,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
                ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
                if (ret)
                        goto err_powered_up;
+
+               regcache_cache_only(cs35l56->base.regmap, false);
        }
 
        /* Disable auto-hibernate so that runtime_pm has control */
@@ -1002,6 +1004,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
        if (ret)
                goto err;
 
+       regcache_cache_only(cs35l56->base.regmap, false);
+
        ret = cs35l56_set_patch(&cs35l56->base);
        if (ret)
                goto err;
index 70d80b6af3fe370aa9c6f9fd471676ba9c18da72..b29739bd330b1331848553d1f2854694a1be369a 100644 (file)
@@ -920,6 +920,8 @@ static void alc_pre_init(struct hda_codec *codec)
        ((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME)
 #define is_s4_resume(codec) \
        ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE)
+#define is_s4_suspend(codec) \
+       ((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE)
 
 static int alc_init(struct hda_codec *codec)
 {
@@ -7183,6 +7185,46 @@ static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
        alc245_fixup_hp_gpio_led(codec, fix, action);
 }
 
+/*
+ * ALC287 PCM hooks
+ */
+static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream,
+                                  int action)
+{
+       alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
+       switch (action) {
+       case HDA_GEN_PCM_ACT_OPEN:
+               alc_write_coefex_idx(codec, 0x5a, 0x00, 0x954f); /* write gpio3 to high */
+               break;
+       case HDA_GEN_PCM_ACT_CLOSE:
+               alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
+               break;
+       }
+}
+
+static void __maybe_unused alc287_s4_power_gpio3_default(struct hda_codec *codec)
+{
+       if (is_s4_suspend(codec)) {
+               alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */
+               alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */
+       }
+}
+
+static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
+                              const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+#ifdef CONFIG_PM
+       spec->power_hook = alc287_s4_power_gpio3_default;
+#endif
+       spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
+}
+
 
 enum {
        ALC269_FIXUP_GPIO2,
@@ -7426,6 +7468,7 @@ enum {
        ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
        ALC298_FIXUP_LENOVO_C940_DUET7,
        ALC287_FIXUP_LENOVO_14IRP8_DUETITL,
+       ALC287_FIXUP_LENOVO_LEGION_7,
        ALC287_FIXUP_13S_GEN2_SPEAKERS,
        ALC256_FIXUP_SET_COEF_DEFAULTS,
        ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
@@ -7470,7 +7513,8 @@ enum {
        ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
        ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
        ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
-       ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1
+       ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1,
+       ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318,
 };
 
 /* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -7510,6 +7554,23 @@ static void alc287_fixup_lenovo_14irp8_duetitl(struct hda_codec *codec,
        __snd_hda_apply_fixup(codec, id, action, 0);
 }
 
+/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with
+ * TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec);
+ * we apply a corresponding fixup depending on the codec SSID instead
+ */
+static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec,
+                                        const struct hda_fixup *fix,
+                                        int action)
+{
+       int id;
+
+       if (codec->core.subsystem_id == 0x17aa38a8)
+               id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */
+       else
+               id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */
+       __snd_hda_apply_fixup(codec, id, action, 0);
+}
+
 static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_GPIO2] = {
                .type = HDA_FIXUP_FUNC,
@@ -9404,6 +9465,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc287_fixup_lenovo_14irp8_duetitl,
        },
+       [ALC287_FIXUP_LENOVO_LEGION_7] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc287_fixup_lenovo_legion_7,
+       },
        [ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -9726,6 +9791,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC285_FIXUP_ASUS_GA403U,
        },
+       [ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc287_fixup_lenovo_thinkpad_with_alc1318,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -9937,6 +10008,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
        SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
        SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
@@ -10393,6 +10465,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x231e, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
+       SND_PCI_QUIRK(0x17aa, 0x231f, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@@ -10422,7 +10496,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
        SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
        SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
-       SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7),
        SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
        SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
index 69c68d8e7a6b54fc1fcfc3fac3a73d58403071f5..1760b5d42460afe83f3d50dbcdd73daf9455fc12 100644 (file)
@@ -430,6 +430,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "MRID6"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MDC"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"),
+               }
+       },
        {
                .driver_data = &acp6x_card,
                .matches = {
index dfb4ce53491bbaa8800b8e7b3e2737a0a1be47bc..f8e57a2fc3e324fcf4cdefde12b3a8db24239af5 100644 (file)
@@ -1094,6 +1094,7 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf
 static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
 {
        struct wm_adsp *dsp;
+       uint32_t dsp1rx5_src;
        int ret;
 
        dsp = &cs35l41->dsp;
@@ -1113,16 +1114,29 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
                return ret;
        }
 
-       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC,
-                          CS35L41_INPUT_SRC_VPMON);
+       switch (cs35l41->hw_cfg.bst_type) {
+       case CS35L41_INT_BOOST:
+       case CS35L41_SHD_BOOST_ACTV:
+               dsp1rx5_src = CS35L41_INPUT_SRC_VPMON;
+               break;
+       case CS35L41_EXT_BOOST:
+       case CS35L41_SHD_BOOST_PASS:
+               dsp1rx5_src = CS35L41_INPUT_SRC_VBSTMON;
+               break;
+       default:
+               dev_err(cs35l41->dev, "wm_halo_init failed - Invalid Boost Type: %d\n",
+                       cs35l41->hw_cfg.bst_type);
+               goto err_dsp;
+       }
+
+       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC, dsp1rx5_src);
        if (ret < 0) {
-               dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret);
+               dev_err(cs35l41->dev, "Write DSP1RX5_SRC: %d failed: %d\n", dsp1rx5_src, ret);
                goto err_dsp;
        }
-       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC,
-                          CS35L41_INPUT_SRC_CLASSH);
+       ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC, CS35L41_INPUT_SRC_VBSTMON);
        if (ret < 0) {
-               dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret);
+               dev_err(cs35l41->dev, "Write CS35L41_INPUT_SRC_VBSTMON failed: %d\n", ret);
                goto err_dsp;
        }
        ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC,
index 14a5f86019aad47390ee8f3962a596296dfbf437..70ff55c1517fe02d2a75e7d683e58edcb01947d0 100644 (file)
@@ -188,8 +188,6 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
                        goto out;
        }
 
-       regcache_cache_only(cs35l56->base.regmap, false);
-
        ret = cs35l56_init(cs35l56);
        if (ret < 0) {
                regcache_cache_only(cs35l56->base.regmap, true);
index 08cac58e3ab2223c82b4da10314f04b2f055b5b6..fd02b621da52c0c68420f995764e752b6a789597 100644 (file)
@@ -40,16 +40,11 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
 static const struct reg_default cs35l56_reg_defaults[] = {
        /* no defaults for OTP_MEM - first read populates cache */
 
-       { CS35L56_ASP1_ENABLES1,                0x00000000 },
-       { CS35L56_ASP1_CONTROL1,                0x00000028 },
-       { CS35L56_ASP1_CONTROL2,                0x18180200 },
-       { CS35L56_ASP1_CONTROL3,                0x00000002 },
-       { CS35L56_ASP1_FRAME_CONTROL1,          0x03020100 },
-       { CS35L56_ASP1_FRAME_CONTROL5,          0x00020100 },
-       { CS35L56_ASP1_DATA_CONTROL1,           0x00000018 },
-       { CS35L56_ASP1_DATA_CONTROL5,           0x00000018 },
-
-       /* no defaults for ASP1TX mixer */
+       /*
+        * No defaults for ASP1 control or ASP1TX mixer. See
+        * cs35l56_populate_asp1_register_defaults() and
+        * cs35l56_sync_asp1_mixer_widgets_with_firmware().
+        */
 
        { CS35L56_SWIRE_DP3_CH1_INPUT,          0x00000018 },
        { CS35L56_SWIRE_DP3_CH2_INPUT,          0x00000019 },
@@ -210,6 +205,36 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
        }
 }
 
+static const struct reg_sequence cs35l56_asp1_defaults[] = {
+       REG_SEQ0(CS35L56_ASP1_ENABLES1,         0x00000000),
+       REG_SEQ0(CS35L56_ASP1_CONTROL1,         0x00000028),
+       REG_SEQ0(CS35L56_ASP1_CONTROL2,         0x18180200),
+       REG_SEQ0(CS35L56_ASP1_CONTROL3,         0x00000002),
+       REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL1,   0x03020100),
+       REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5,   0x00020100),
+       REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1,    0x00000018),
+       REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5,    0x00000018),
+};
+
+/*
+ * The firmware can have control of the ASP so we don't provide regmap
+ * with defaults for these registers, to prevent a regcache_sync() from
+ * overwriting the firmware settings. But if the machine driver hooks up
+ * the ASP it means the driver is taking control of the ASP, so then the
+ * registers are populated with the defaults.
+ */
+int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base)
+{
+       if (!cs35l56_base->fw_owns_asp1)
+               return 0;
+
+       cs35l56_base->fw_owns_asp1 = false;
+
+       return regmap_multi_reg_write(cs35l56_base->regmap, cs35l56_asp1_defaults,
+                                     ARRAY_SIZE(cs35l56_asp1_defaults));
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_init_asp1_regs_for_driver_control, SND_SOC_CS35L56_SHARED);
+
 /*
  * The firmware boot sequence can overwrite the ASP1 config registers so that
  * they don't match regmap's view of their values. Rewrite the values from the
@@ -217,19 +242,15 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
  */
 int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
 {
-       struct reg_sequence asp1_regs[] = {
-               { .reg = CS35L56_ASP1_ENABLES1 },
-               { .reg = CS35L56_ASP1_CONTROL1 },
-               { .reg = CS35L56_ASP1_CONTROL2 },
-               { .reg = CS35L56_ASP1_CONTROL3 },
-               { .reg = CS35L56_ASP1_FRAME_CONTROL1 },
-               { .reg = CS35L56_ASP1_FRAME_CONTROL5 },
-               { .reg = CS35L56_ASP1_DATA_CONTROL1 },
-               { .reg = CS35L56_ASP1_DATA_CONTROL5 },
-       };
+       struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)];
        int i, ret;
 
-       /* Read values from regmap cache into a write sequence */
+       if (cs35l56_base->fw_owns_asp1)
+               return 0;
+
+       memcpy(asp1_regs, cs35l56_asp1_defaults, sizeof(asp1_regs));
+
+       /* Read current values from regmap cache into the write sequence */
        for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {
                ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def);
                if (ret)
@@ -307,10 +328,10 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
                reg = CS35L56_DSP1_HALO_STATE;
 
        /*
-        * This can't be a regmap_read_poll_timeout() because cs35l56 will NAK
-        * I2C until it has booted which would terminate the poll
+        * The regmap must remain in cache-only until the chip has
+        * booted, so use a bypassed read of the status register.
         */
-       poll_ret = read_poll_timeout(regmap_read, read_ret,
+       poll_ret = read_poll_timeout(regmap_read_bypassed, read_ret,
                                     (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
                                     CS35L56_HALO_STATE_POLL_US,
                                     CS35L56_HALO_STATE_TIMEOUT_US,
@@ -362,7 +383,8 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
                return;
 
        cs35l56_wait_control_port_ready();
-       regcache_cache_only(cs35l56_base->regmap, false);
+
+       /* Leave in cache-only. This will be revoked when the chip has rebooted. */
 }
 EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
 
@@ -577,14 +599,14 @@ int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_sou
                cs35l56_issue_wake_event(cs35l56_base);
 
 out_sync:
-       regcache_cache_only(cs35l56_base->regmap, false);
-
        ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
        if (ret) {
                dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
                goto err;
        }
 
+       regcache_cache_only(cs35l56_base->regmap, false);
+
        ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
        if (ret)
                goto err;
@@ -684,7 +706,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED);
 
 int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
 {
-       u64 silicon_uid;
+       u64 silicon_uid = 0;
        int ret;
 
        /* Driver can't apply calibration to a secured part, so skip */
@@ -757,7 +779,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
         * devices so the REVID needs to be determined before waiting for the
         * firmware to boot.
         */
-       ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid);
+       ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid);
        if (ret < 0) {
                dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
                return ret;
@@ -768,7 +790,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
        if (ret)
                return ret;
 
-       ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid);
+       ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_DEVID, &devid);
        if (ret < 0) {
                dev_err(cs35l56_base->dev, "Get Device ID failed\n");
                return ret;
@@ -787,6 +809,9 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
 
        cs35l56_base->type = devid & 0xFF;
 
+       /* Silicon is now identified and booted so exit cache-only */
+       regcache_cache_only(cs35l56_base->regmap, false);
+
        ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
        if (ret) {
                dev_err(cs35l56_base->dev, "Get Secure status failed\n");
index 8d2f021fb362812a73d07d10565a23d2b77f6a38..4986e78105daf9ca949815835c94321ad19dfb68 100644 (file)
@@ -454,9 +454,14 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f
 {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component);
        unsigned int val;
+       int ret;
 
        dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt);
 
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
+
        switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
        case SND_SOC_DAIFMT_CBC_CFC:
                break;
@@ -530,6 +535,11 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx
                                        unsigned int rx_mask, int slots, int slot_width)
 {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
+       int ret;
+
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
 
        if ((slots == 0) || (slot_width == 0)) {
                dev_dbg(cs35l56->base.dev, "tdm config cleared\n");
@@ -578,6 +588,11 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream,
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
        unsigned int rate = params_rate(params);
        u8 asp_width, asp_wl;
+       int ret;
+
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
 
        asp_wl = params_width(params);
        if (cs35l56->asp_slot_width)
@@ -634,7 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai,
                                      int clk_id, unsigned int freq, int dir)
 {
        struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
-       int freq_id;
+       int freq_id, ret;
+
+       ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base);
+       if (ret)
+               return ret;
 
        if (freq == 0) {
                cs35l56->sysclk_set = false;
@@ -1341,6 +1360,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
                                    "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj);
        if (ret) {
                dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret);
+               fwnode_handle_put(af01_fwnode);
                return -ENOENT;
        }
 
@@ -1348,6 +1368,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
        if (obj->package.count != 4) {
                dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n",
                         obj->package.count);
+               fwnode_handle_put(af01_fwnode);
                return -ENOENT;
        }
 
@@ -1362,6 +1383,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
                 */
                ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping);
                if (ret) {
+                       fwnode_handle_put(af01_fwnode);
                        return dev_err_probe(cs35l56->base.dev, ret,
                                             "Failed to add gpio mapping to AF01\n");
                }
@@ -1369,14 +1391,17 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
                ret = devm_add_action_or_reset(cs35l56->base.dev,
                                               cs35l56_acpi_dev_release_driver_gpios,
                                               adev);
-               if (ret)
+               if (ret) {
+                       fwnode_handle_put(af01_fwnode);
                        return ret;
+               }
 
                dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n");
        }
 
        desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL);
        if (IS_ERR(desc)) {
+               fwnode_handle_put(af01_fwnode);
                ret = PTR_ERR(desc);
                return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n");
        }
@@ -1385,9 +1410,12 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
        gpiod_put(desc);
 
        if (ret < 0) {
+               fwnode_handle_put(af01_fwnode);
                dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n");
                return ret;
-               }
+       }
+
+       fwnode_handle_put(af01_fwnode);
 
        dev_info(cs35l56->base.dev, "Got spk-id from AF01\n");
 
@@ -1403,6 +1431,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
        cs35l56->base.cal_index = -1;
        cs35l56->speaker_id = -ENOENT;
 
+       /* Assume that the firmware owns ASP1 until we know different */
+       cs35l56->base.fw_owns_asp1 = true;
+
        dev_set_drvdata(cs35l56->base.dev, cs35l56);
 
        cs35l56_fill_supply_names(cs35l56->supplies);
@@ -1531,6 +1562,8 @@ post_soft_reset:
                        return ret;
 
                dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n");
+
+               regcache_cache_only(cs35l56->base.regmap, false);
        }
 
        /* Disable auto-hibernate so that runtime_pm has control */
index 6bc068cdcbe2a89e1488530bfa4e6e9c49c0651c..15e5e3eb592b3008fb47ea4372fed71a08375f01 100644 (file)
@@ -671,8 +671,10 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
                return NULL;
 
        aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL);
-       if (!aad_pdata)
+       if (!aad_pdata) {
+               fwnode_handle_put(aad_np);
                return NULL;
+       }
 
        aad_pdata->irq = i2c->irq;
 
@@ -753,6 +755,8 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
        else
                aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
 
+       fwnode_handle_put(aad_np);
+
        return aad_pdata;
 }
 
index e3ba04484813a21904727a09725c608bf27c34a2..d0d24a53df7462cfe88d5d2457078fc1f144f22b 100644 (file)
@@ -444,6 +444,7 @@ struct rt5645_priv {
        struct regmap *regmap;
        struct i2c_client *i2c;
        struct gpio_desc *gpiod_hp_det;
+       struct gpio_desc *gpiod_cbj_sleeve;
        struct snd_soc_jack *hp_jack;
        struct snd_soc_jack *mic_jack;
        struct snd_soc_jack *btn_jack;
@@ -3186,6 +3187,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
                regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
                        RT5645_CBJ_MN_JD, 0);
 
+               if (rt5645->gpiod_cbj_sleeve)
+                       gpiod_set_value(rt5645->gpiod_cbj_sleeve, 1);
+
                msleep(600);
                regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val);
                val &= 0x7;
@@ -3202,6 +3206,8 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
                        snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
                        snd_soc_dapm_sync(dapm);
                        rt5645->jack_type = SND_JACK_HEADPHONE;
+                       if (rt5645->gpiod_cbj_sleeve)
+                               gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
                }
                if (rt5645->pdata.level_trigger_irq)
                        regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
@@ -3229,6 +3235,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
                if (rt5645->pdata.level_trigger_irq)
                        regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
                                RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
+
+               if (rt5645->gpiod_cbj_sleeve)
+                       gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
        }
 
        return rt5645->jack_type;
@@ -4012,6 +4021,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
                        return ret;
        }
 
+       rt5645->gpiod_cbj_sleeve = devm_gpiod_get_optional(&i2c->dev, "cbj-sleeve",
+                                                          GPIOD_OUT_LOW);
+
+       if (IS_ERR(rt5645->gpiod_cbj_sleeve)) {
+               ret = PTR_ERR(rt5645->gpiod_cbj_sleeve);
+               dev_info(&i2c->dev, "failed to initialize gpiod, ret=%d\n", ret);
+               if (ret != -ENOENT)
+                       return ret;
+       }
+
        for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
                rt5645->supplies[i].supply = rt5645_supply_names[i];
 
@@ -4259,6 +4278,9 @@ static void rt5645_i2c_remove(struct i2c_client *i2c)
        cancel_delayed_work_sync(&rt5645->jack_detect_work);
        cancel_delayed_work_sync(&rt5645->rcclock_work);
 
+       if (rt5645->gpiod_cbj_sleeve)
+               gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
+
        regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
 }
 
@@ -4274,6 +4296,9 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c)
                0);
        msleep(20);
        regmap_write(rt5645->regmap, RT5645_RESET, 0);
+
+       if (rt5645->gpiod_cbj_sleeve)
+               gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
 }
 
 static int __maybe_unused rt5645_sys_suspend(struct device *dev)
index 3fb7b9adb61de628705d784fbe64e259bf031089..bc3579203c7a4770cb657b22965a12bc2becefe8 100644 (file)
@@ -316,7 +316,7 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
 static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
 
 static int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol,
@@ -477,7 +477,7 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
                        RT715_SDCA_FU_VOL_CTRL, CH_01),
                SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL,
                        RT715_SDCA_FU_VOL_CTRL, CH_02),
-                       0x2f, 0x7f, 0,
+                       0x2f, 0x3f, 0,
                rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put,
                in_vol_tlv),
        RT715_SDCA_EXT_TLV("FU02 Capture Volume",
@@ -485,13 +485,13 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
                        RT715_SDCA_FU_VOL_CTRL, CH_01),
                rt715_sdca_set_amp_gain_4ch_get,
                rt715_sdca_set_amp_gain_4ch_put,
-               in_vol_tlv, 4, 0x7f),
+               in_vol_tlv, 4, 0x3f),
        RT715_SDCA_EXT_TLV("FU06 Capture Volume",
                SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL,
                        RT715_SDCA_FU_VOL_CTRL, CH_01),
                rt715_sdca_set_amp_gain_4ch_get,
                rt715_sdca_set_amp_gain_4ch_put,
-               in_vol_tlv, 4, 0x7f),
+               in_vol_tlv, 4, 0x3f),
        /* MIC Boost Control */
        RT715_SDCA_BOOST_EXT_TLV("FU0E Boost",
                SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN,
index 7e13868ff99f03110c165dcd706cff46a8eeba5d..f012fe0ded6d2871217f5fa02c49ee0158ad5101 100644 (file)
@@ -111,6 +111,7 @@ static bool rt715_readable_register(struct device *dev, unsigned int reg)
        case 0x839d:
        case 0x83a7:
        case 0x83a9:
+       case 0x752001:
        case 0x752039:
                return true;
        default:
index e0ea3a23f7cc6844691338ff8daae7f2843d2c6e..e5bd9ef812de13378801d82356b54ee4144f219a 100644 (file)
@@ -1330,7 +1330,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = {
                .capture = {
                        .stream_name = "DP6 DMic Capture",
                        .channels_min = 1,
-                       .channels_max = 2,
+                       .channels_max = 4,
                        .rates = RT722_STEREO_RATES,
                        .formats = RT722_FORMATS,
                },
@@ -1439,9 +1439,12 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
        int loop_check, chk_cnt = 100, ret;
        unsigned int calib_status = 0;
 
-       /* Read eFuse */
-       rt722_sdca_index_write(rt722, RT722_VENDOR_SPK_EFUSE, RT722_DC_CALIB_CTRL,
-               0x4808);
+       /* Config analog bias */
+       rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3,
+               0xa081);
+       /* GE related settings */
+       rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2,
+               0xa009);
        /* Button A, B, C, D bypass mode */
        rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4,
                0xcf00);
@@ -1475,9 +1478,6 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
                if ((calib_status & 0x0040) == 0x0)
                        break;
        }
-       /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
-       rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
-               0x0010);
        /* Set ADC09 power entity floating control */
        rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
                0x2a12);
@@ -1490,8 +1490,21 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
        /* Set DAC03 and HP power entity floating control */
        rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL,
                0x4040);
+       rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1,
+               0x4141);
+       rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1,
+               0x0101);
        /* Fine tune PDE40 latency */
        regmap_write(rt722->regmap, 0x2f58, 0x07);
+       regmap_write(rt722->regmap, 0x2f03, 0x06);
+       /* MIC VRefo */
+       rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+               RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200);
+       rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+               RT722_VREFO_GAT, 0x4000, 0x4000);
+       /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
+       rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
+               0x0010);
 }
 
 int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)
index 44af8901352eb6817e9a6dddd76fc7325a3660ba..2464361a7958c6904d1eca01fb148166a4743eff 100644 (file)
@@ -69,6 +69,7 @@ struct rt722_sdca_dmic_kctrl_priv {
 #define RT722_COMBO_JACK_AUTO_CTL2             0x46
 #define RT722_COMBO_JACK_AUTO_CTL3             0x47
 #define RT722_DIGITAL_MISC_CTRL4               0x4a
+#define RT722_VREFO_GAT                                0x63
 #define RT722_FSM_CTL                          0x67
 #define RT722_SDCA_INTR_REC                    0x82
 #define RT722_SW_CONFIG1                       0x8a
@@ -127,6 +128,8 @@ struct rt722_sdca_dmic_kctrl_priv {
 #define RT722_UMP_HID_CTL6                     0x66
 #define RT722_UMP_HID_CTL7                     0x67
 #define RT722_UMP_HID_CTL8                     0x68
+#define RT722_FLOAT_CTRL_1                     0x70
+#define RT722_ENT_FLOAT_CTRL_1         0x76
 
 /* Parameter & Verb control 01 (0x1a)(NID:20h) */
 #define RT722_HIDDEN_REG_SW_RESET (0x1 << 14)
index 3c025dabaf7a47f180b6f5bdaf6d6f67d128956d..1253695bebd863cab4accfef0616250fb3006830 100644 (file)
@@ -1155,6 +1155,7 @@ static int wsa881x_probe(struct sdw_slave *pdev,
        pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0);
        pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
        pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
+       pdev->prop.clk_stop_mode1 = true;
        gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
 
        wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
index 9d9921e1cd4dedcb2ff4f8e9b59a3b4560d7fa4c..d2554c8577326b533764862829e84b8e001f7016 100644 (file)
@@ -64,7 +64,7 @@ struct avs_icl_memwnd2_desc {
 struct avs_icl_memwnd2 {
        union {
                struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
-               u8 rsvd[PAGE_SIZE];
+               u8 rsvd[SZ_4K];
        };
        u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE];
 } __packed;
index 13061bd1488bb4dd506b14aed5c87967bc19aee6..42b42903ae9de7919c6620a5bfba2ef3b54ffb2c 100644 (file)
@@ -1582,6 +1582,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
        if (!le32_to_cpu(dw->priv.size))
                return 0;
 
+       w->no_wname_in_kcontrol_name = true;
+
        if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) {
                dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
                w->ignore_suspend = false;
index 05f38d1f7d824dc0f46c5262e0f6616dce1b7411..b41a1147f1c3455de581c729efc72517b35bc6c7 100644 (file)
@@ -636,28 +636,30 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_USE_AMCR0F28),
        },
        {
+               /* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
                },
                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
                                        BYT_RT5640_JD_SRC_JD2_IN4N |
                                        BYT_RT5640_OVCD_TH_2000UA |
                                        BYT_RT5640_OVCD_SF_0P75 |
+                                       BYT_RT5640_MONO_SPEAKER |
+                                       BYT_RT5640_DIFF_MIC |
+                                       BYT_RT5640_SSP0_AIF2 |
                                        BYT_RT5640_MCLK_EN),
        },
        {
+               /* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */
                .matches = {
-                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
                },
                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
                                        BYT_RT5640_JD_SRC_JD2_IN4N |
                                        BYT_RT5640_OVCD_TH_2000UA |
                                        BYT_RT5640_OVCD_SF_0P75 |
-                                       BYT_RT5640_MONO_SPEAKER |
-                                       BYT_RT5640_DIFF_MIC |
-                                       BYT_RT5640_SSP0_AIF2 |
                                        BYT_RT5640_MCLK_EN),
        },
        {
index b93ea33739f29ddd9b987d7896e9fa2f37c58ccf..6458d5dc4902f665211bb9e4ae7d274e4bff2fdc 100644 (file)
@@ -99,6 +99,7 @@ config SND_MESON_AXG_PDM
 
 config SND_MESON_CARD_UTILS
        tristate
+       select SND_DYNAMIC_MINORS
 
 config SND_MESON_CODEC_GLUE
        tristate
index 3180aa4d3a157e2718b7b3b4bf34a239a68f33e1..8c5605c1e34e8a1bf29e4256ba9625b94205c762 100644 (file)
@@ -318,6 +318,7 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
 
        dai_link->cpus = cpu;
        dai_link->num_cpus = 1;
+       dai_link->nonatomic = true;
 
        ret = meson_card_parse_dai(card, np, dai_link->cpus);
        if (ret)
index bebee0ca8e3889a920a486b01c1a8730eb1988d4..ecb3eb7a9723ddf60e565b95e46b7f31ce1544cb 100644 (file)
@@ -204,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
        unsigned int status;
 
        regmap_read(fifo->map, FIFO_STATUS1, &status);
-
        status = FIELD_GET(STATUS1_INT_STS, status);
+       axg_fifo_ack_irq(fifo, status);
+
+       /* Use the thread to call period elapsed on nonatomic links */
        if (status & FIFO_INT_COUNT_REPEAT)
-               snd_pcm_period_elapsed(ss);
-       else
-               dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
-                       status);
+               return IRQ_WAKE_THREAD;
 
-       /* Ack irqs */
-       axg_fifo_ack_irq(fifo, status);
+       dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
+               status);
+
+       return IRQ_NONE;
+}
+
+static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id)
+{
+       struct snd_pcm_substream *ss = dev_id;
+
+       snd_pcm_period_elapsed(ss);
 
-       return IRQ_RETVAL(status);
+       return IRQ_HANDLED;
 }
 
 int axg_fifo_pcm_open(struct snd_soc_component *component,
@@ -243,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
        if (ret)
                return ret;
 
-       ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0,
-                         dev_name(dev), ss);
+       ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block,
+                                  axg_fifo_pcm_irq_block_thread,
+                                  IRQF_ONESHOT, dev_name(dev), ss);
        if (ret)
                return ret;
 
index 63333a2b0a9c363d6882d3fe50ecff78da390316..a6579efd37750db01add3c491bb7a8443a76dde7 100644 (file)
@@ -392,6 +392,46 @@ void axg_tdm_stream_free(struct axg_tdm_stream *ts)
 }
 EXPORT_SYMBOL_GPL(axg_tdm_stream_free);
 
+int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
+                                  unsigned int fmt)
+{
+       int ret = 0;
+
+       if (fmt & SND_SOC_DAIFMT_CONT) {
+               /* Clock are already enabled - skipping */
+               if (ts->clk_enabled)
+                       return 0;
+
+               ret = clk_prepare_enable(ts->iface->mclk);
+               if (ret)
+                       return ret;
+
+               ret = clk_prepare_enable(ts->iface->sclk);
+               if (ret)
+                       goto err_sclk;
+
+               ret = clk_prepare_enable(ts->iface->lrclk);
+               if (ret)
+                       goto err_lrclk;
+
+               ts->clk_enabled = true;
+               return 0;
+       }
+
+       /* Clocks are already disabled - skipping */
+       if (!ts->clk_enabled)
+               return 0;
+
+       clk_disable_unprepare(ts->iface->lrclk);
+err_lrclk:
+       clk_disable_unprepare(ts->iface->sclk);
+err_sclk:
+       clk_disable_unprepare(ts->iface->mclk);
+       ts->clk_enabled = false;
+       return ret;
+}
+EXPORT_SYMBOL_GPL(axg_tdm_stream_set_cont_clocks);
+
 MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver");
 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
 MODULE_LICENSE("GPL v2");
index bf708717635bf6531195a1039aee41c3166d8154..62057c71f742e68e4555428281157ebb265b1cc2 100644 (file)
@@ -309,6 +309,7 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
                                   struct snd_soc_dai *dai)
 {
        struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai);
+       struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
        int ret;
 
        switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -346,7 +347,11 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
                        return ret;
        }
 
-       return 0;
+       ret = axg_tdm_stream_set_cont_clocks(ts, iface->fmt);
+       if (ret)
+               dev_err(dai->dev, "failed to apply continuous clock setting\n");
+
+       return ret;
 }
 
 static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
@@ -354,19 +359,32 @@ static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
 {
        struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
 
-       /* Stop all attached formatters */
-       axg_tdm_stream_stop(ts);
-
-       return 0;
+       return axg_tdm_stream_set_cont_clocks(ts, 0);
 }
 
-static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream,
+static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream,
+                                int cmd,
                                 struct snd_soc_dai *dai)
 {
-       struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+       struct axg_tdm_stream *ts =
+               snd_soc_dai_get_dma_data(dai, substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               axg_tdm_stream_start(ts);
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+       case SNDRV_PCM_TRIGGER_STOP:
+               axg_tdm_stream_stop(ts);
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       /* Force all attached formatters to update */
-       return axg_tdm_stream_reset(ts);
+       return 0;
 }
 
 static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai)
@@ -412,8 +430,8 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = {
        .set_fmt        = axg_tdm_iface_set_fmt,
        .startup        = axg_tdm_iface_startup,
        .hw_params      = axg_tdm_iface_hw_params,
-       .prepare        = axg_tdm_iface_prepare,
        .hw_free        = axg_tdm_iface_hw_free,
+       .trigger        = axg_tdm_iface_trigger,
 };
 
 /* TDM Backend DAIs */
index 42f7470b9a7f41fd948948c54d58ea30c49831be..daaca10fec9e2bff82164ccccea75f1aefadaba1 100644 (file)
@@ -58,12 +58,17 @@ struct axg_tdm_stream {
        unsigned int physical_width;
        u32 *mask;
        bool ready;
+
+       /* For continuous clock tracking */
+       bool clk_enabled;
 };
 
 struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
 void axg_tdm_stream_free(struct axg_tdm_stream *ts);
 int axg_tdm_stream_start(struct axg_tdm_stream *ts);
 void axg_tdm_stream_stop(struct axg_tdm_stream *ts);
+int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts,
+                                  unsigned int fmt);
 
 static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
 {
index cc84d4c81be9d363d701b1d5c658e26a62079435..238bda5f6b76fa48b186514398840af05644f279 100644 (file)
@@ -350,7 +350,9 @@ static int sof_init_environment(struct snd_sof_dev *sdev)
        }
 
        ret = sof_select_ipc_and_paths(sdev);
-       if (!ret && plat_data->ipc_type != base_profile->ipc_type) {
+       if (ret) {
+               goto err_machine_check;
+       } else if (plat_data->ipc_type != base_profile->ipc_type) {
                /* IPC type changed, re-initialize the ops */
                sof_ops_free(sdev);
 
index 7c8aafca8fdef8eb65211dcd8cbead13077a6068..7275437ea8d8a59433e4aab0429acb4ce66cdf4a 100644 (file)
@@ -330,14 +330,32 @@ EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init);
 
 int snd_sof_dbg_init(struct snd_sof_dev *sdev)
 {
+       struct snd_sof_pdata *plat_data = sdev->pdata;
        struct snd_sof_dsp_ops *ops = sof_ops(sdev);
        const struct snd_sof_debugfs_map *map;
+       struct dentry *fw_profile;
        int i;
        int err;
 
        /* use "sof" as top level debugFS dir */
        sdev->debugfs_root = debugfs_create_dir("sof", NULL);
 
+       /* expose firmware/topology prefix/names for test purposes */
+       fw_profile = debugfs_create_dir("fw_profile", sdev->debugfs_root);
+
+       debugfs_create_str("fw_path", 0444, fw_profile,
+                          (char **)&plat_data->fw_filename_prefix);
+       debugfs_create_str("fw_lib_path", 0444, fw_profile,
+                          (char **)&plat_data->fw_lib_prefix);
+       debugfs_create_str("tplg_path", 0444, fw_profile,
+                          (char **)&plat_data->tplg_filename_prefix);
+       debugfs_create_str("fw_name", 0444, fw_profile,
+                          (char **)&plat_data->fw_filename);
+       debugfs_create_str("tplg_name", 0444, fw_profile,
+                          (char **)&plat_data->tplg_filename);
+       debugfs_create_u32("ipc_type", 0444, fw_profile,
+                          (u32 *)&plat_data->ipc_type);
+
        /* init dfsentry list */
        INIT_LIST_HEAD(&sdev->dfsentry_list);
 
index b26ffe767fab553467897b4facc13931668b27fe..b14e508f1f315b19585ad6851f8fc5f4b1d3891a 100644 (file)
@@ -35,6 +35,9 @@ static const struct sof_dev_desc lnl_desc = {
        .default_fw_path = {
                [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl",
        },
+       .default_lib_path = {
+               [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/lnl",
+       },
        .default_tplg_path = {
                [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
        },
index 35769dd7905ebe6f66492f650a72d8624712f28a..af0bf354cb209e216b60ec0097ac88fb08b21475 100644 (file)
@@ -434,4 +434,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = {
        .trigger = sof_ipc3_pcm_trigger,
        .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup,
        .reset_hw_params_during_stop = true,
+       .d0i3_supported_in_s0ix = true,
 };
index e915f9f87a6c35d74f1cf7096accca70dce688da..4594470ed08b1e6e95af6e2aaa62da418281ce97 100644 (file)
@@ -37,6 +37,25 @@ struct sof_ipc4_timestamp_info {
        snd_pcm_sframes_t delay;
 };
 
+/**
+ * struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
+ * @time_info: pointer to time info struct if it is supported, otherwise NULL
+ * @chain_dma_allocated: indicates the ChainDMA allocation state
+ */
+struct sof_ipc4_pcm_stream_priv {
+       struct sof_ipc4_timestamp_info *time_info;
+
+       bool chain_dma_allocated;
+};
+
+static inline struct sof_ipc4_timestamp_info *
+sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps)
+{
+       struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private;
+
+       return stream_priv->time_info;
+}
+
 static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
                                             struct ipc4_pipeline_set_state_data *trigger_list)
 {
@@ -253,14 +272,17 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd,
  */
 
 static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
-                                     int direction,
+                                     struct snd_sof_pcm *spcm, int direction,
                                      struct snd_sof_pcm_stream_pipeline_list *pipeline_list,
                                      int state, int cmd)
 {
        struct sof_ipc4_fw_data *ipc4_data = sdev->private;
+       struct sof_ipc4_pcm_stream_priv *stream_priv;
        bool allocate, enable, set_fifo_size;
        struct sof_ipc4_msg msg = {{ 0 }};
-       int i;
+       int ret, i;
+
+       stream_priv = spcm->stream[direction].private;
 
        switch (state) {
        case SOF_IPC4_PIPE_RUNNING: /* Allocate and start chained dma */
@@ -281,6 +303,11 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
                set_fifo_size = false;
                break;
        case SOF_IPC4_PIPE_RESET: /* Disable and free chained DMA. */
+
+               /* ChainDMA can only be reset if it has been allocated */
+               if (!stream_priv->chain_dma_allocated)
+                       return 0;
+
                allocate = false;
                enable = false;
                set_fifo_size = false;
@@ -338,7 +365,12 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
        if (enable)
                msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK;
 
-       return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
+       ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
+       /* Update the ChainDMA allocation state */
+       if (!ret)
+               stream_priv->chain_dma_allocated = allocate;
+
+       return ret;
 }
 
 static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
@@ -378,7 +410,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
         * trigger function that handles the rest for the substream.
         */
        if (pipeline->use_chain_dma)
-               return sof_ipc4_chain_dma_trigger(sdev, substream->stream,
+               return sof_ipc4_chain_dma_trigger(sdev, spcm, substream->stream,
                                                  pipeline_list, state, cmd);
 
        /* allocate memory for the pipeline data */
@@ -452,7 +484,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
                 * Invalidate the stream_start_offset to make sure that it is
                 * going to be updated if the stream resumes
                 */
-               time_info = spcm->stream[substream->stream].private;
+               time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
                if (time_info)
                        time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
 
@@ -706,12 +738,16 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
 static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm)
 {
        struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
+       struct sof_ipc4_pcm_stream_priv *stream_priv;
        int stream;
 
        for_each_pcm_streams(stream) {
                pipeline_list = &spcm->stream[stream].pipeline_list;
                kfree(pipeline_list->pipelines);
                pipeline_list->pipelines = NULL;
+
+               stream_priv = spcm->stream[stream].private;
+               kfree(stream_priv->time_info);
                kfree(spcm->stream[stream].private);
                spcm->stream[stream].private = NULL;
        }
@@ -721,7 +757,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
 {
        struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
        struct sof_ipc4_fw_data *ipc4_data = sdev->private;
-       struct sof_ipc4_timestamp_info *stream_info;
+       struct sof_ipc4_pcm_stream_priv *stream_priv;
+       struct sof_ipc4_timestamp_info *time_info;
        bool support_info = true;
        u32 abi_version;
        u32 abi_offset;
@@ -749,33 +786,41 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
                        return -ENOMEM;
                }
 
+               stream_priv = kzalloc(sizeof(*stream_priv), GFP_KERNEL);
+               if (!stream_priv) {
+                       sof_ipc4_pcm_free(sdev, spcm);
+                       return -ENOMEM;
+               }
+
+               spcm->stream[stream].private = stream_priv;
+
                if (!support_info)
                        continue;
 
-               stream_info = kzalloc(sizeof(*stream_info), GFP_KERNEL);
-               if (!stream_info) {
+               time_info = kzalloc(sizeof(*time_info), GFP_KERNEL);
+               if (!time_info) {
                        sof_ipc4_pcm_free(sdev, spcm);
                        return -ENOMEM;
                }
 
-               spcm->stream[stream].private = stream_info;
+               stream_priv->time_info = time_info;
        }
 
        return 0;
 }
 
-static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *spcm)
+static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps)
 {
        struct sof_ipc4_copier *host_copier = NULL;
        struct sof_ipc4_copier *dai_copier = NULL;
        struct sof_ipc4_llp_reading_slot llp_slot;
-       struct sof_ipc4_timestamp_info *info;
+       struct sof_ipc4_timestamp_info *time_info;
        struct snd_soc_dapm_widget *widget;
        struct snd_sof_dai *dai;
        int i;
 
        /* find host & dai to locate info in memory window */
-       for_each_dapm_widgets(spcm->list, i, widget) {
+       for_each_dapm_widgets(sps->list, i, widget) {
                struct snd_sof_widget *swidget = widget->dobj.private;
 
                if (!swidget)
@@ -795,44 +840,44 @@ static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pc
                return;
        }
 
-       info = spcm->private;
-       info->host_copier = host_copier;
-       info->dai_copier = dai_copier;
-       info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_gpdma_reading_slots) +
-                                   sdev->fw_info_box.offset;
+       time_info = sof_ipc4_sps_to_time_info(sps);
+       time_info->host_copier = host_copier;
+       time_info->dai_copier = dai_copier;
+       time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
+                                        llp_gpdma_reading_slots) + sdev->fw_info_box.offset;
 
        /* find llp slot used by current dai */
        for (i = 0; i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS; i++) {
-               sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
+               sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
                if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
                        break;
 
-               info->llp_offset += sizeof(llp_slot);
+               time_info->llp_offset += sizeof(llp_slot);
        }
 
        if (i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS)
                return;
 
        /* if no llp gpdma slot is used, check aggregated sdw slot */
-       info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_sndw_reading_slots) +
-                                       sdev->fw_info_box.offset;
+       time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
+                                        llp_sndw_reading_slots) + sdev->fw_info_box.offset;
        for (i = 0; i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS; i++) {
-               sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
+               sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
                if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
                        break;
 
-               info->llp_offset += sizeof(llp_slot);
+               time_info->llp_offset += sizeof(llp_slot);
        }
 
        if (i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS)
                return;
 
        /* check EVAD slot */
-       info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_evad_reading_slot) +
-                                       sdev->fw_info_box.offset;
-       sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
+       time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
+                                        llp_evad_reading_slot) + sdev->fw_info_box.offset;
+       sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
        if (llp_slot.node_id != dai_copier->data.gtw_cfg.node_id)
-               info->llp_offset = 0;
+               time_info->llp_offset = 0;
 }
 
 static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
@@ -849,7 +894,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
        if (!spcm)
                return -EINVAL;
 
-       time_info = spcm->stream[substream->stream].private;
+       time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
        /* delay calculation is not supported by current fw_reg ABI */
        if (!time_info)
                return 0;
@@ -864,7 +909,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
 
 static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
                                            struct snd_pcm_substream *substream,
-                                           struct snd_sof_pcm_stream *stream,
+                                           struct snd_sof_pcm_stream *sps,
                                            struct sof_ipc4_timestamp_info *time_info)
 {
        struct sof_ipc4_copier *host_copier = time_info->host_copier;
@@ -918,7 +963,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
        struct sof_ipc4_timestamp_info *time_info;
        struct sof_ipc4_llp_reading_slot llp;
        snd_pcm_uframes_t head_cnt, tail_cnt;
-       struct snd_sof_pcm_stream *stream;
+       struct snd_sof_pcm_stream *sps;
        u64 dai_cnt, host_cnt, host_ptr;
        struct snd_sof_pcm *spcm;
        int ret;
@@ -927,8 +972,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
        if (!spcm)
                return -EOPNOTSUPP;
 
-       stream = &spcm->stream[substream->stream];
-       time_info = stream->private;
+       sps = &spcm->stream[substream->stream];
+       time_info = sof_ipc4_sps_to_time_info(sps);
        if (!time_info)
                return -EOPNOTSUPP;
 
@@ -938,7 +983,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
         * the statistics is complete. And it will not change after the first initiailization.
         */
        if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
-               ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
+               ret = sof_ipc4_get_stream_start_offset(sdev, substream, sps, time_info);
                if (ret < 0)
                        return -EOPNOTSUPP;
        }
@@ -1030,15 +1075,13 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
 {
        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
        struct sof_ipc4_timestamp_info *time_info;
-       struct snd_sof_pcm_stream *stream;
        struct snd_sof_pcm *spcm;
 
        spcm = snd_sof_find_spcm_dai(component, rtd);
        if (!spcm)
                return 0;
 
-       stream = &spcm->stream[substream->stream];
-       time_info = stream->private;
+       time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
        /*
         * Report the stored delay value calculated in the pointer callback.
         * In the unlikely event that the calculation was skipped/aborted, the
index f03cee94bce62642e3c419d4f956a2011ea4dd3f..8804e00e7251b9724054b119509698a3a12899bf 100644 (file)
@@ -325,14 +325,13 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
                        ipc_first = true;
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               if (sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
+               /*
+                * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
+                * D0I3-compatible streams to keep the firmware pipeline running
+                */
+               if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix &&
+                   sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
                    spcm->stream[substream->stream].d0i3_compatible) {
-                       /*
-                        * trap the event, not sending trigger stop to
-                        * prevent the FW pipelines from being stopped,
-                        * and mark the flag to ignore the upcoming DAPM
-                        * PM events.
-                        */
                        spcm->stream[substream->stream].suspend_ignored = true;
                        return 0;
                }
index 86bbb531e142c72be1ca5d710c466d16c9058734..499b6084b52637f12623172b0b17d027a41c08d4 100644 (file)
@@ -116,6 +116,7 @@ struct snd_sof_dai_config_data {
  *                               triggers. The FW keeps the host DMA running in this case and
  *                               therefore the host must do the same and should stop the DMA during
  *                               hw_free.
+ * @d0i3_supported_in_s0ix: Allow DSP D0I3 during S0iX
  */
 struct sof_ipc_pcm_ops {
        int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
@@ -135,6 +136,7 @@ struct sof_ipc_pcm_ops {
        bool reset_hw_params_during_stop;
        bool ipc_first_on_start;
        bool platform_stop_during_hw_free;
+       bool d0i3_supported_in_s0ix;
 };
 
 /**
index aa37c4ab0adbd9b47d2228cb4977e78ebf97b576..21cd41fec7a9cb932ecdc479ca41394349c48ffc 100644 (file)
@@ -1,8 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 //
 // tegra186_dspk.c - Tegra186 DSPK driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
 
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -241,14 +240,14 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       cif_conf.client_bits = TEGRA_ACIF_BITS_24;
-
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
+               cif_conf.client_bits = TEGRA_ACIF_BITS_16;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+               cif_conf.client_bits = TEGRA_ACIF_BITS_24;
                break;
        default:
                dev_err(dev, "unsupported format!\n");
index b892d66f78470a6430b7096efdafab202992dbd2..1e760c3155213db093ff09a12b922eb43c3ba4c4 100644 (file)
@@ -2417,12 +2417,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        mcasp_reparent_fck(pdev);
 
-       ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
-                                             &davinci_mcasp_dai[mcasp->op_mode], 1);
-
-       if (ret != 0)
-               goto err;
-
        ret = davinci_mcasp_get_dma_type(mcasp);
        switch (ret) {
        case PCM_EDMA:
@@ -2449,6 +2443,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                goto err;
        }
 
+       ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
+                                             &davinci_mcasp_dai[mcasp->op_mode], 1);
+
+       if (ret != 0)
+               goto err;
+
 no_audio:
        ret = davinci_mcasp_init_gpiochip(mcasp);
        if (ret) {
index 5fa7957f6e0f56646249c278b7434f300754df77..25810e18b0a73272f42ff3a8d9335ee79699b6a0 100644 (file)
@@ -182,6 +182,7 @@ class NlMsg:
             self.done = 1
             extack_off = 20
         elif self.nl_type == Netlink.NLMSG_DONE:
+            self.error = struct.unpack("i", self.raw[0:4])[0]
             self.done = 1
             extack_off = 4
 
index 4a41856938a8889403278a4ad44c599d835b887a..1b29030021eeba71e34eeb8adcf69278f11a1dda 100644 (file)
@@ -41,7 +41,7 @@ static char *_get_cpuid(void)
        char *mimpid = NULL;
        char *cpuid = NULL;
        int read;
-       unsigned long line_sz;
+       size_t line_sz;
        FILE *cpuinfo;
 
        cpuinfo = fopen(CPUINFO, "r");
index 61c69297e7978fceed700be3ad43a7a870d20de2..3482248aa34424e1d690ecea1faef822d152edd3 100644 (file)
@@ -1001,6 +1001,7 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
        struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
        struct cxl_dev_state *cxlds = cxlmd->cxlds;
        struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
+       struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
        struct range pmem_range = {
                .start = cxlds->pmem_res.start,
                .end = cxlds->pmem_res.end,
@@ -1020,6 +1021,12 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
                dpa_perf_setup(port, &pmem_range, &mds->pmem_perf);
 
        cxl_memdev_update_perf(cxlmd);
+
+       /*
+        * This function is here to only test the topology iterator. It serves
+        * no other purpose.
+        */
+       cxl_endpoint_get_perf_coordinates(port, ep_c);
 }
 
 static struct cxl_mock_ops cxl_mock_ops = {
index 39ad96a18123f626c311aaa2fdf8213594b7d67d..edcd26106557b478eea1527077ffde97347c9012 100644 (file)
@@ -205,6 +205,9 @@ __weak noinline struct file *bpf_testmod_return_ptr(int arg)
        case 5: return (void *)~(1ull << 30);   /* trigger extable */
        case 6: return &f;                      /* valid addr */
        case 7: return (void *)((long)&f | 1);  /* kernel tricks */
+#ifdef CONFIG_X86_64
+       case 8: return (void *)VSYSCALL_ADDR;   /* vsyscall page address */
+#endif
        default: return NULL;
        }
 }
index ba3ddeda24bf527295acaf32159097c03ac52153..d98702b6955df24e72366f2246ad5b3da7951b5a 100644 (file)
@@ -56,7 +56,6 @@
 #include <asm/types.h>
 #include <ctype.h>
 #include <errno.h>
-#include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -1159,7 +1158,7 @@ void __run_test(struct __fixture_metadata *f,
                struct __test_metadata *t)
 {
        struct __test_xfail *xfail;
-       char test_name[LINE_MAX];
+       char *test_name;
        const char *diagnostic;
 
        /* reset test struct */
@@ -1167,8 +1166,12 @@ void __run_test(struct __fixture_metadata *f,
        t->trigger = 0;
        memset(t->results->reason, 0, sizeof(t->results->reason));
 
-       snprintf(test_name, sizeof(test_name), "%s%s%s.%s",
-                f->name, variant->name[0] ? "." : "", variant->name, t->name);
+       if (asprintf(&test_name, "%s%s%s.%s", f->name,
+               variant->name[0] ? "." : "", variant->name, t->name) == -1) {
+               ksft_print_msg("ERROR ALLOCATING MEMORY\n");
+               t->exit_code = KSFT_FAIL;
+               _exit(t->exit_code);
+       }
 
        ksft_print_msg(" RUN           %s ...\n", test_name);
 
@@ -1206,6 +1209,7 @@ void __run_test(struct __fixture_metadata *f,
 
        ksft_test_result_code(t->exit_code, test_name,
                              diagnostic ? "%s" : NULL, diagnostic);
+       free(test_name);
 }
 
 static int test_harness_run(int argc, char **argv)
index eef816b80993f528569f0de79b5f5e5fcda0e289..ca917c71ff602da5ab0805c4cee51e0df5d185e5 100644 (file)
@@ -84,6 +84,18 @@ static struct vm_gic vm_gic_create_with_vcpus(uint32_t gic_dev_type,
        return v;
 }
 
+static struct vm_gic vm_gic_create_barebones(uint32_t gic_dev_type)
+{
+       struct vm_gic v;
+
+       v.gic_dev_type = gic_dev_type;
+       v.vm = vm_create_barebones();
+       v.gic_fd = kvm_create_device(v.vm, gic_dev_type);
+
+       return v;
+}
+
+
 static void vm_gic_destroy(struct vm_gic *v)
 {
        close(v->gic_fd);
@@ -357,6 +369,40 @@ static void test_vcpus_then_vgic(uint32_t gic_dev_type)
        vm_gic_destroy(&v);
 }
 
+#define KVM_VGIC_V2_ATTR(offset, cpu) \
+       (FIELD_PREP(KVM_DEV_ARM_VGIC_OFFSET_MASK, offset) | \
+        FIELD_PREP(KVM_DEV_ARM_VGIC_CPUID_MASK, cpu))
+
+#define GIC_CPU_CTRL   0x00
+
+static void test_v2_uaccess_cpuif_no_vcpus(void)
+{
+       struct vm_gic v;
+       u64 val = 0;
+       int ret;
+
+       v = vm_gic_create_barebones(KVM_DEV_TYPE_ARM_VGIC_V2);
+       subtest_dist_rdist(&v);
+
+       ret = __kvm_has_device_attr(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+                                   KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0));
+       TEST_ASSERT(ret && errno == EINVAL,
+                   "accessed non-existent CPU interface, want errno: %i",
+                   EINVAL);
+       ret = __kvm_device_attr_get(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+                                   KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0), &val);
+       TEST_ASSERT(ret && errno == EINVAL,
+                   "accessed non-existent CPU interface, want errno: %i",
+                   EINVAL);
+       ret = __kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+                                   KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0), &val);
+       TEST_ASSERT(ret && errno == EINVAL,
+                   "accessed non-existent CPU interface, want errno: %i",
+                   EINVAL);
+
+       vm_gic_destroy(&v);
+}
+
 static void test_v3_new_redist_regions(void)
 {
        struct kvm_vcpu *vcpus[NR_VCPUS];
@@ -675,6 +721,9 @@ void run_tests(uint32_t gic_dev_type)
        test_vcpus_then_vgic(gic_dev_type);
        test_vgic_then_vcpus(gic_dev_type);
 
+       if (VGIC_DEV_IS_V2(gic_dev_type))
+               test_v2_uaccess_cpuif_no_vcpus();
+
        if (VGIC_DEV_IS_V3(gic_dev_type)) {
                test_v3_new_redist_regions();
                test_v3_typer_accesses();
index 200bedcdc32e9cf0fd834ad39bd0cab435743987..1e01d3ddc11c58ffb5af9c8733c93ec17297fed6 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mman.h>
 #include <linux/prctl.h>
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/auxv.h>
index 374a308174d2ba7c17f496a4c94364e34815e355..48dc151f8fca8ab8a1ef300860cb59e0f491a2a8 100644 (file)
@@ -54,7 +54,6 @@ int test_nr;
 u64 shadow_pkey_reg;
 int dprint_in_signal;
 char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE];
-char buf[256];
 
 void cat_into_file(char *str, char *file)
 {
@@ -1745,42 +1744,6 @@ void pkey_setup_shadow(void)
        shadow_pkey_reg = __read_pkey_reg();
 }
 
-pid_t parent_pid;
-
-void restore_settings_atexit(void)
-{
-       if (parent_pid == getpid())
-               cat_into_file(buf, "/proc/sys/vm/nr_hugepages");
-}
-
-void save_settings(void)
-{
-       int fd;
-       int err;
-
-       if (geteuid())
-               return;
-
-       fd = open("/proc/sys/vm/nr_hugepages", O_RDONLY);
-       if (fd < 0) {
-               fprintf(stderr, "error opening\n");
-               perror("error: ");
-               exit(__LINE__);
-       }
-
-       /* -1 to guarantee leaving the trailing \0 */
-       err = read(fd, buf, sizeof(buf)-1);
-       if (err < 0) {
-               fprintf(stderr, "error reading\n");
-               perror("error: ");
-               exit(__LINE__);
-       }
-
-       parent_pid = getpid();
-       atexit(restore_settings_atexit);
-       close(fd);
-}
-
 int main(void)
 {
        int nr_iterations = 22;
@@ -1788,7 +1751,6 @@ int main(void)
 
        srand((unsigned int)time(NULL));
 
-       save_settings();
        setup_handlers();
 
        printf("has pkeys: %d\n", pkeys_supported);
index c2c542fe7b17bb6a8b8b59b4a4de79ba26a07043..4bdb3a0c7a606e4201e445002eb6795390d8b374 100755 (executable)
@@ -385,6 +385,7 @@ CATEGORY="ksm_numa" run_test ./ksm_tests -N -m 0
 CATEGORY="ksm" run_test ./ksm_functional_tests
 
 # protection_keys tests
+nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages)
 if [ -x ./protection_keys_32 ]
 then
        CATEGORY="pkey" run_test ./protection_keys_32
@@ -394,6 +395,7 @@ if [ -x ./protection_keys_64 ]
 then
        CATEGORY="pkey" run_test ./protection_keys_64
 fi
+echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
 
 if [ -x ./soft-dirty ]
 then
index 6c988bd2f335677b9b87af1594407e63f907e542..d3c7f5fb3e7b778dc5e0e36eb71da09372f9acef 100644 (file)
@@ -300,7 +300,7 @@ int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd,
                char **addr)
 {
        size_t i;
-       int dummy;
+       int __attribute__((unused)) dummy = 0;
 
        srand(time(NULL));
 
index c537d52fafc586d5644ca6f7ec13a4358b4051c0..a40541bb7c7dee55baf1ec3e40c0727907a1c98d 100644 (file)
@@ -19,7 +19,7 @@
 #include "hwprobe.h"
 #include "../../kselftest.h"
 
-#define MK_CBO(fn) cpu_to_le32((fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)
+#define MK_CBO(fn) le32_bswap((uint32_t)(fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)
 
 static char mem[4096] __aligned(4096) = { [0 ... 4095] = 0xa5 };
 
index e3fccb390c4dc94d0c224223192f767606b4da17..f3de970c32227bcfc6c9ce8608ba497724326b1c 100644 (file)
@@ -4,6 +4,16 @@
 #include <stddef.h>
 #include <asm/hwprobe.h>
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define le32_bswap(_x)                                \
+       ((((_x) & 0x000000ffU) << 24) |         \
+        (((_x) & 0x0000ff00U) <<  8) |         \
+        (((_x) & 0x00ff0000U) >>  8) |         \
+        (((_x) & 0xff000000U) >> 24))
+#else
+# define le32_bswap(_x) (_x)
+#endif
+
 /*
  * Rather than relying on having a new enough libc to define this, just do it
  * ourselves.  This way we don't need to be coupled to a new-enough libc to
index b5d592d4099e85c6ad9d19d36de055eb27415409..d975a67673299fe7fd617c4568e1c3afca93a96e 100644 (file)
@@ -158,6 +158,20 @@ static void handle_sigsys(int sig, siginfo_t *info, void *ucontext)
 
        /* In preparation for sigreturn. */
        SYSCALL_DISPATCH_OFF(glob_sel);
+
+       /*
+        * The tests for argument handling assume that `syscall(x) == x`. This
+        * is a NOP on x86 because the syscall number is passed in %rax, which
+        * happens to also be the function ABI return register.  Other
+        * architectures may need to swizzle the arguments around.
+        */
+#if defined(__riscv)
+/* REG_A7 is not defined in libc headers */
+# define REG_A7 (REG_A0 + 7)
+
+       ((ucontext_t *)ucontext)->uc_mcontext.__gregs[REG_A0] =
+                       ((ucontext_t *)ucontext)->uc_mcontext.__gregs[REG_A7];
+#endif
 }
 
 TEST(dispatch_and_return)