Merge tag 'for-6.5/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Jul 2023 17:08:49 +0000 (10:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Jul 2023 17:08:49 +0000 (10:08 -0700)
Pull device mapper fixes from Mike Snitzer:

 - Fix double free on memory allocation failure in DM integrity target's
   integrity_recalc()

 - Fix locking in DM raid target's raid_ctr() and around call to
   md_stop()

 - Fix DM cache target's cleaner policy to always allow work to be
   queued for writeback; even if cache isn't idle.

* tag 'for-6.5/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm cache policy smq: ensure IO doesn't prevent cleaner policy progress
  dm raid: protect md_stop() with 'reconfig_mutex'
  dm raid: clean up four equivalent goto tags in raid_ctr()
  dm raid: fix missing reconfig_mutex unlock in raid_ctr() error paths
  dm integrity: fix double free on memory allocation failure

491 files changed:
.mailmap
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
Documentation/devicetree/bindings/serial/cavium-uart.txt [deleted file]
Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt [deleted file]
Documentation/devicetree/bindings/sound/audio-graph-card2.yaml
Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
Documentation/networking/napi.rst
MAINTAINERS
Makefile
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_pgtable.h
arch/arm64/include/asm/virt.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/vdso/vgettimeofday.c
arch/arm64/kvm/arch_timer.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/nvhe/host.S
arch/arm64/kvm/hyp/nvhe/psci-relay.c
arch/arm64/kvm/hyp/pgtable.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pkvm.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/vgic/vgic-v3.c
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/mm/trans_pgd.c
arch/arm64/net/bpf_jit_comp.c
arch/arm64/tools/sysreg
arch/ia64/kernel/sys_ia64.c
arch/m68k/fpsp040/skeleton.S
arch/m68k/ifpsp060/os.S
arch/m68k/kernel/relocate_kernel.S
arch/parisc/kernel/sys_parisc.c
arch/powerpc/crypto/.gitignore [new file with mode: 0644]
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/elf.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/kernel/traps.c
arch/powerpc/mm/kasan/Makefile
arch/powerpc/platforms/512x/mpc512x_lpbfifo.c
arch/powerpc/platforms/pseries/vas.c
arch/s390/crypto/paes_s390.c
arch/s390/kvm/pv.c
arch/s390/mm/fault.c
arch/s390/mm/gmap.c
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_amd.h
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/traps.c
block/blk-core.c
block/blk-iocost.c
block/blk-mq.c
drivers/accel/habanalabs/common/habanalabs.h
drivers/accel/qaic/qaic_control.c
drivers/ata/pata_parport/aten.c
drivers/ata/pata_parport/bpck.c
drivers/ata/pata_parport/bpck6.c
drivers/ata/pata_parport/comm.c
drivers/ata/pata_parport/dstr.c
drivers/ata/pata_parport/epat.c
drivers/ata/pata_parport/epia.c
drivers/ata/pata_parport/fit2.c
drivers/ata/pata_parport/fit3.c
drivers/ata/pata_parport/friq.c
drivers/ata/pata_parport/frpw.c
drivers/ata/pata_parport/kbic.c
drivers/ata/pata_parport/ktti.c
drivers/ata/pata_parport/on20.c
drivers/ata/pata_parport/on26.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-i2c.c
drivers/base/regmap/regmap-kunit.c
drivers/base/regmap/regmap-spi-avmm.c
drivers/base/regmap/regmap.c
drivers/block/loop.c
drivers/bluetooth/btusb.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_tis.c
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_core.h
drivers/char/tpm/tpm_tis_i2c.c
drivers/char/tpm/tpm_tis_spi_main.c
drivers/char/tpm/tpm_vtpm_proxy.c
drivers/cxl/Kconfig
drivers/cxl/acpi.c
drivers/cxl/cxlmem.h
drivers/dma-buf/dma-resv.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-tps68470.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
drivers/gpu/drm/amd/amdkfd/kfd_debug.c
drivers/gpu/drm/amd/amdkfd/kfd_debug.h
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
drivers/gpu/drm/amd/display/dc/dcn301/Makefile
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_display_device.c
drivers/gpu/drm/i915/display/intel_dpt.c
drivers/gpu/drm/i915/display/intel_fbdev.c
drivers/gpu/drm/i915/gem/selftests/huge_pages.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
drivers/gpu/drm/msm/adreno/adreno_device.c
drivers/gpu/drm/msm/adreno/adreno_gpu.h
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
drivers/gpu/drm/msm/msm_fence.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_mdss.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
drivers/idle/intel_idle.c
drivers/media/cec/usb/pulse8/pulse8-cec.c
drivers/media/i2c/tc358746.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/platform/amphion/vpu_core.c
drivers/media/platform/amphion/vpu_mbox.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
drivers/media/platform/verisilicon/hantro.h
drivers/media/platform/verisilicon/hantro_postproc.c
drivers/net/bonding/bond_main.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/can/spi/mcp251xfd/mcp251xfd.h
drivers/net/can/usb/gs_usb.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/qca/ar9331.c
drivers/net/dsa/qca/qca8k-8xxx.c
drivers/net/dsa/qca/qca8k-common.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/brocade/bna/bnad_debugfs.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice_base.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
drivers/net/ethernet/mscc/ocelot_fdma.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
drivers/net/ethernet/ti/cpsw_ale.c
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ipa/ipa_table.c
drivers/net/macvlan.c
drivers/net/phy/marvell10g.c
drivers/net/phy/phy_device.c
drivers/net/team/team.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vrf.c
drivers/net/vxlan/vxlan_core.c
drivers/of/Kconfig
drivers/of/platform.c
drivers/phy/hisilicon/phy-hisi-inno-usb2.c
drivers/phy/mediatek/phy-mtk-dp.c
drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
drivers/platform/x86/amd/pmc-quirks.c
drivers/platform/x86/amd/pmf/acpi.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/amd/pmf/sps.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/huawei-wmi.c
drivers/platform/x86/intel/hid.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/serial-multi-instantiate.c
drivers/platform/x86/think-lmi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/regulator/da9063-regulator.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/scsi/sg.c
drivers/soundwire/amd_manager.c
drivers/soundwire/bus.c
drivers/soundwire/qcom.c
drivers/staging/media/atomisp/Kconfig
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/fbdev/au1200fb.c
drivers/video/fbdev/bw2.c
drivers/video/fbdev/cg14.c
drivers/video/fbdev/cg3.c
drivers/video/fbdev/cg6.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/ep93xx-fb.c
drivers/video/fbdev/ffb.c
drivers/video/fbdev/grvga.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/kyro/STG4000InitDevice.c
drivers/video/fbdev/leo.c
drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
drivers/video/fbdev/p9100.c
drivers/video/fbdev/platinumfb.c
drivers/video/fbdev/sbuslib.c
drivers/video/fbdev/sunxvr1000.c
drivers/video/fbdev/sunxvr2500.c
drivers/video/fbdev/sunxvr500.c
drivers/video/fbdev/tcx.c
drivers/video/fbdev/xilinxfb.c
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/block-rsv.c
fs/btrfs/disk-io.c
fs/btrfs/free-space-tree.c
fs/btrfs/inode.c
fs/btrfs/qgroup.c
fs/btrfs/raid56.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/ext4/mballoc.c
fs/ext4/xattr.c
fs/file.c
fs/fuse/dir.c
fs/fuse/inode.c
fs/fuse/ioctl.c
fs/iomap/buffered-io.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/transaction.c
fs/nfsd/nfs4state.c
fs/overlayfs/super.c
fs/smb/client/cifsfs.h
fs/smb/client/ioctl.c
fs/smb/server/ksmbd_netlink.h
fs/smb/server/server.c
fs/smb/server/smb2pdu.c
fs/smb/server/smb_common.c
fs/smb/server/smb_common.h
fs/smb/server/vfs.c
fs/smb/server/vfs.h
fs/splice.c
fs/xfs/libxfs/xfs_da_format.h
fs/xfs/libxfs/xfs_fs.h
fs/xfs/xfs_ondisk.h
include/drm/drm_fb_helper.h
include/kvm/arm_vgic.h
include/linux/blk-mq.h
include/linux/jbd2.h
include/linux/tcp.h
include/net/bluetooth/hci_core.h
include/net/bonding.h
include/net/cfg802154.h
include/net/codel.h
include/net/devlink.h
include/net/inet_frag.h
include/net/ipv6.h
include/net/llc_conn.h
include/net/llc_pdu.h
include/net/nsh.h
include/net/pie.h
include/net/rsi_91x.h
include/net/tcp.h
include/net/vxlan.h
include/trace/events/jbd2.h
include/uapi/linux/fuse.h
include/uapi/linux/if_packet.h
io_uring/io_uring.c
kernel/bpf/verifier.c
kernel/signal.c
kernel/sys.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
kernel/trace/tracing_map.h
lib/maple_tree.c
lib/sbitmap.c
lib/test_maple_tree.c
mm/memory.c
mm/mempolicy.c
mm/mlock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/mgmt.c
net/bluetooth/sco.c
net/can/bcm.c
net/can/raw.c
net/ipv4/esp4.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_gre.c
net/ipv4/tcp.c
net/ipv4/tcp_fastopen.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp_offload.c
net/llc/af_llc.c
net/llc/llc_conn.c
net/llc/llc_if.c
net/llc/llc_input.c
net/llc/llc_sap.c
net/mptcp/protocol.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_immediate.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/packet/af_packet.c
net/sched/cls_bpf.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sched/cls_u32.c
net/sched/sch_mqprio.c
net/tipc/crypto.c
net/tipc/node.c
net/unix/af_unix.c
scripts/Makefile.build
scripts/Makefile.host
scripts/clang-tools/gen_compile_commands.py
scripts/kconfig/gconf.c
security/keys/request_key.c
security/keys/trusted-keys/trusted_tpm2.c
sound/core/seq/seq_ports.c
sound/core/seq/seq_ump_client.c
sound/drivers/pcmtest.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/acp/amd.h
sound/soc/amd/ps/acp63.h
sound/soc/amd/ps/pci-ps.c
sound/soc/amd/ps/ps-sdw-dma.c
sound/soc/atmel/atmel-i2s.c
sound/soc/codecs/Kconfig
sound/soc/codecs/cs42l51-i2c.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42l51.h
sound/soc/codecs/da7219-aad.c
sound/soc/codecs/es8316.c
sound/soc/codecs/nau8821.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5682-sdw.c
sound/soc/codecs/rt711-sdca-sdw.c
sound/soc/codecs/rt711-sdw.c
sound/soc/codecs/rt712-sdca-sdw.c
sound/soc/codecs/rt722-sdca-sdw.c
sound/soc/codecs/wcd-mbhc-v2.c
sound/soc/codecs/wcd934x.c
sound/soc/codecs/wcd938x.c
sound/soc/codecs/wm8904.c
sound/soc/fsl/fsl_sai.c
sound/soc/fsl/fsl_sai.h
sound/soc/fsl/fsl_spdif.c
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/qdsp6/q6apm-dai.c
sound/soc/qcom/qdsp6/q6apm.c
sound/soc/qcom/qdsp6/topology.c
sound/soc/soc-core.c
sound/soc/soc-topology.c
sound/soc/sof/amd/acp.c
sound/soc/sof/ipc3-dtrace.c
sound/soc/tegra/tegra210_adx.c
sound/soc/tegra/tegra210_amx.c
sound/usb/mixer_maps.c
sound/usb/quirks.c
tools/arch/arm64/include/asm/cputype.h
tools/build/feature/Makefile
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fcntl.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/mman.h
tools/include/uapi/linux/mount.h
tools/include/uapi/linux/prctl.h
tools/include/uapi/linux/vhost.h
tools/include/uapi/sound/asound.h
tools/lib/subcmd/help.c
tools/net/ynl/lib/ynl.py
tools/perf/Makefile.config
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
tools/perf/arch/s390/entry/syscalls/syscall.tbl
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/pmu-events/arch/x86/amdzen1/recommended.json
tools/perf/pmu-events/arch/x86/amdzen2/recommended.json
tools/perf/pmu-events/arch/x86/amdzen3/recommended.json
tools/perf/tests/shell/test_uprobe_from_different_cu.sh [new file with mode: 0755]
tools/perf/tests/task-exit.c
tools/perf/trace/beauty/include/linux/socket.h
tools/perf/trace/beauty/move_mount_flags.sh
tools/perf/trace/beauty/msg_flags.c
tools/perf/util/dwarf-aux.c
tools/perf/util/parse-events.c
tools/testing/cxl/test/cxl.c
tools/testing/radix-tree/maple.c
tools/testing/selftests/alsa/.gitignore
tools/testing/selftests/alsa/test-pcmtest-driver.c
tools/testing/selftests/arm64/Makefile
tools/testing/selftests/bpf/progs/async_stack_depth.c
tools/testing/selftests/mincore/mincore_selftest.c
tools/testing/selftests/mm/charge_reserved_hugetlb.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/check_config.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/hugetlb_reparenting_test.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/mkdirty.c
tools/testing/selftests/mm/run_vmtests.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/test_hmm.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/test_vmalloc.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/va_high_addr_switch.sh [changed mode: 0644->0755]
tools/testing/selftests/mm/write_hugetlb_memory.sh [changed mode: 0644->0755]
tools/testing/selftests/net/mptcp/mptcp_join.sh
tools/testing/selftests/riscv/Makefile
tools/testing/selftests/tc-testing/config
tools/testing/selftests/tc-testing/settings [new file with mode: 0644]
tools/testing/selftests/timers/raw_skew.c

index 89b7f33..a33b9f5 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -241,6 +241,7 @@ Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
 Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
 Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
 John Crispin <john@phrozen.org> <blogic@openwrt.org>
+John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
 John Keeping <john@keeping.me.uk> <john@metanate.com>
 John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
 John Stultz <johnstul@us.ibm.com>
@@ -454,6 +455,8 @@ Sebastian Reichel <sre@kernel.org> <sre@debian.org>
 Sedat Dilek <sedat.dilek@gmail.com> <sedat.dilek@credativ.de>
 Seth Forshee <sforshee@kernel.org> <seth.forshee@canonical.com>
 Shannon Nelson <shannon.nelson@amd.com> <snelson@pensando.io>
+Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@intel.com>
+Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@oracle.com>
 Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
 Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com>
 Shuah Khan <shuah@kernel.org> <shuah.khan@hp.com>
index ae4f68d..bd67cfe 100644 (file)
@@ -105,7 +105,7 @@ properties:
       G coefficient for temperature equation.
       Default for series 5 = 60000
       Default for series 6 = 57400
-    multipleOf: 1000
+    multipleOf: 100
     minimum: 1000
     $ref: /schemas/types.yaml#/definitions/uint32
 
@@ -114,7 +114,7 @@ properties:
       H coefficient for temperature equation.
       Default for series 5 = 200000
       Default for series 6 = 249400
-    multipleOf: 1000
+    multipleOf: 100
     minimum: 1000
     $ref: /schemas/types.yaml#/definitions/uint32
 
@@ -131,7 +131,7 @@ properties:
       J coefficient for temperature equation.
       Default for series 5 = -100
       Default for series 6 = 0
-    multipleOf: 1000
+    multipleOf: 100
     maximum: 0
     $ref: /schemas/types.yaml#/definitions/int32
 
diff --git a/Documentation/devicetree/bindings/serial/cavium-uart.txt b/Documentation/devicetree/bindings/serial/cavium-uart.txt
deleted file mode 100644 (file)
index 87a6c37..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-* Universal Asynchronous Receiver/Transmitter (UART)
-
-- compatible: "cavium,octeon-3860-uart"
-
-  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
-
-- reg: The base address of the UART register bank.
-
-- interrupts: A single interrupt specifier.
-
-- current-speed: Optional, the current bit rate in bits per second.
-
-Example:
-       uart1: serial@1180000000c00 {
-               compatible = "cavium,octeon-3860-uart","ns16550";
-               reg = <0x11800 0x00000c00 0x0 0x400>;
-               current-speed = <115200>;
-               interrupts = <0 35>;
-       };
diff --git a/Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt b/Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt
deleted file mode 100644 (file)
index 04e23e6..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-* NXP LPC1850 UART
-
-Required properties:
-- compatible   : "nxp,lpc1850-uart", "ns16550a".
-- reg          : offset and length of the register set for the device.
-- interrupts   : should contain uart interrupt.
-- clocks       : phandle to the input clocks.
-- clock-names  : required elements: "uartclk", "reg".
-
-Optional properties:
-- dmas         : Two or more DMA channel specifiers following the
-                 convention outlined in bindings/dma/dma.txt
-- dma-names    : Names for the dma channels, if present. There must
-                 be at least one channel named "tx" for transmit
-                 and named "rx" for receive.
-
-Since it's also possible to also use the of_serial.c driver all
-parameters from 8250.txt also apply but are optional.
-
-Example:
-uart0: serial@40081000 {
-       compatible = "nxp,lpc1850-uart", "ns16550a";
-       reg = <0x40081000 0x1000>;
-       reg-shift = <2>;
-       interrupts = <24>;
-       clocks = <&ccu2 CLK_APB0_UART0>, <&ccu1 CLK_CPU_UART0>;
-       clock-names = "uartclk", "reg";
-};
index 3de7b36..d3ce4de 100644 (file)
@@ -39,22 +39,4 @@ required:
 
 additionalProperties: false
 
-examples:
-  - |
-    sound {
-        compatible = "audio-graph-card2";
-
-        links = <&cpu_port>;
-    };
-
-    cpu {
-        compatible = "cpu-driver";
-
-        cpu_port: port { cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
-    };
-
-    codec {
-        compatible = "codec-driver";
-
-        port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
-    };
+...
index 666a95a..ba5b772 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Google SC7180-Trogdor ASoC sound card driver
 
 maintainers:
-  - Rohit kumar <rohitkr@codeaurora.org>
+  - Rohit kumar <quic_rohkumar@quicinc.com>
   - Cheng-Yi Chiang <cychiang@chromium.org>
 
 description:
index 6cc8f86..3a559bd 100644 (file)
@@ -8,7 +8,7 @@ title: Qualcomm Technologies Inc. LPASS CPU dai driver
 
 maintainers:
   - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-  - Rohit kumar <rohitkr@codeaurora.org>
+  - Rohit kumar <quic_rohkumar@quicinc.com>
 
 description: |
   Qualcomm Technologies Inc. SOC Low-Power Audio SubSystem (LPASS) that consist
index a7a0477..7bf7b95 100644 (file)
@@ -65,15 +65,16 @@ argument - drivers can process completions for any number of Tx
 packets but should only process up to ``budget`` number of
 Rx packets. Rx processing is usually much more expensive.
 
-In other words, it is recommended to ignore the budget argument when
-performing TX buffer reclamation to ensure that the reclamation is not
-arbitrarily bounded; however, it is required to honor the budget argument
-for RX processing.
+In other words for Rx processing the ``budget`` argument limits how many
+packets driver can process in a single poll. Rx specific APIs like page
+pool or XDP cannot be used at all when ``budget`` is 0.
+skb Tx processing should happen regardless of the ``budget``, but if
+the argument is 0 driver cannot call any XDP (or page pool) APIs.
 
 .. warning::
 
-   The ``budget`` argument may be 0 if core tries to only process Tx completions
-   and no Rx packets.
+   The ``budget`` argument may be 0 if core tries to only process
+   skb Tx completions and no Rx or XDP packets.
 
 The poll method returns the amount of work done. If the driver still
 has outstanding work to do (e.g. ``budget`` was exhausted)
index aee3406..b87fbce 100644 (file)
@@ -1865,9 +1865,11 @@ M:       Martin PoviÅ¡er <povik+lin@cutebit.org>
 L:     asahi@lists.linux.dev
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
+F:     Documentation/devicetree/bindings/sound/adi,ssm3515.yaml
 F:     Documentation/devicetree/bindings/sound/apple,*
 F:     sound/soc/apple/*
 F:     sound/soc/codecs/cs42l83-i2c.c
+F:     sound/soc/codecs/ssm3515.c
 
 ARM/APPLE MACHINE SUPPORT
 M:     Hector Martin <marcan@marcan.st>
@@ -5147,10 +5149,12 @@ S:      Maintained
 F:     include/linux/compiler_attributes.h
 
 COMPUTE EXPRESS LINK (CXL)
+M:     Davidlohr Bueso <dave@stgolabs.net>
+M:     Jonathan Cameron <jonathan.cameron@huawei.com>
+M:     Dave Jiang <dave.jiang@intel.com>
 M:     Alison Schofield <alison.schofield@intel.com>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Ira Weiny <ira.weiny@intel.com>
-M:     Ben Widawsky <bwidawsk@kernel.org>
 M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-cxl@vger.kernel.org
 S:     Maintained
index 658ec2b..22e3926 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
@@ -555,11 +555,23 @@ LINUXINCLUDE    := \
                $(USERINCLUDE)
 
 KBUILD_AFLAGS   := -D__ASSEMBLY__ -fno-PIE
-KBUILD_CFLAGS   := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-                  -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \
-                  -Werror=implicit-function-declaration -Werror=implicit-int \
-                  -Werror=return-type -Wno-format-security -funsigned-char \
-                  -std=gnu11
+
+KBUILD_CFLAGS :=
+KBUILD_CFLAGS += -std=gnu11
+KBUILD_CFLAGS += -fshort-wchar
+KBUILD_CFLAGS += -funsigned-char
+KBUILD_CFLAGS += -fno-common
+KBUILD_CFLAGS += -fno-PIE
+KBUILD_CFLAGS += -fno-strict-aliasing
+KBUILD_CFLAGS += -Wall
+KBUILD_CFLAGS += -Wundef
+KBUILD_CFLAGS += -Werror=implicit-function-declaration
+KBUILD_CFLAGS += -Werror=implicit-int
+KBUILD_CFLAGS += -Werror=return-type
+KBUILD_CFLAGS += -Werror=strict-prototypes
+KBUILD_CFLAGS += -Wno-format-security
+KBUILD_CFLAGS += -Wno-trigraphs
+
 KBUILD_CPPFLAGS := -D__KERNEL__
 KBUILD_RUSTFLAGS := $(rust_common_flags) \
                    --target=$(objtree)/scripts/target.json \
index 8b60967..d3dd05b 100644 (file)
@@ -727,6 +727,8 @@ struct kvm_vcpu_arch {
 #define DBG_SS_ACTIVE_PENDING  __vcpu_single_flag(sflags, BIT(5))
 /* PMUSERENR for the guest EL0 is on physical CPU */
 #define PMUSERENR_ON_CPU       __vcpu_single_flag(sflags, BIT(6))
+/* WFI instruction trapped */
+#define IN_WFI                 __vcpu_single_flag(sflags, BIT(7))
 
 
 /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
index 8294a9a..929d355 100644 (file)
@@ -608,22 +608,26 @@ int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size);
 kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr);
 
 /**
- * kvm_pgtable_stage2_mkold() - Clear the access flag in a page-table entry.
+ * kvm_pgtable_stage2_test_clear_young() - Test and optionally clear the access
+ *                                        flag in a page-table entry.
  * @pgt:       Page-table structure initialised by kvm_pgtable_stage2_init*().
  * @addr:      Intermediate physical address to identify the page-table entry.
+ * @size:      Size of the address range to visit.
+ * @mkold:     True if the access flag should be cleared.
  *
  * The offset of @addr within a page is ignored.
  *
- * If there is a valid, leaf page-table entry used to translate @addr, then
- * clear the access flag in that entry.
+ * Tests and conditionally clears the access flag for every valid, leaf
+ * page-table entry used to translate the range [@addr, @addr + @size).
  *
  * Note that it is the caller's responsibility to invalidate the TLB after
  * calling this function to ensure that the updated permissions are visible
  * to the CPUs.
  *
- * Return: The old page-table entry prior to clearing the flag, 0 on failure.
+ * Return: True if any of the visited PTEs had the access flag set.
  */
-kvm_pte_t kvm_pgtable_stage2_mkold(struct kvm_pgtable *pgt, u64 addr);
+bool kvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr,
+                                        u64 size, bool mkold);
 
 /**
  * kvm_pgtable_stage2_relax_perms() - Relax the permissions enforced by a
@@ -646,18 +650,6 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
                                   enum kvm_pgtable_prot prot);
 
 /**
- * kvm_pgtable_stage2_is_young() - Test whether a page-table entry has the
- *                                access flag set.
- * @pgt:       Page-table structure initialised by kvm_pgtable_stage2_init*().
- * @addr:      Intermediate physical address to identify the page-table entry.
- *
- * The offset of @addr within a page is ignored.
- *
- * Return: True if the page-table entry has the access flag set, false otherwise.
- */
-bool kvm_pgtable_stage2_is_young(struct kvm_pgtable *pgt, u64 addr);
-
-/**
  * kvm_pgtable_stage2_flush_range() - Clean and invalidate data cache to Point
  *                                   of Coherency for guest stage-2 address
  *                                   range.
index 5227db7..261d6e9 100644 (file)
@@ -78,6 +78,7 @@ extern u32 __boot_cpu_mode[2];
 
 void __hyp_set_vectors(phys_addr_t phys_vector_base);
 void __hyp_reset_vectors(void);
+bool is_kvm_arm_initialised(void);
 
 DECLARE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
 
index 7a1aeb9..89d54a5 100644 (file)
@@ -847,6 +847,8 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
 int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                          unsigned long vl, unsigned long flags)
 {
+       bool free_sme = false;
+
        if (flags & ~(unsigned long)(PR_SVE_VL_INHERIT |
                                     PR_SVE_SET_VL_ONEXEC))
                return -EINVAL;
@@ -897,21 +899,36 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                task->thread.fp_type = FP_STATE_FPSIMD;
        }
 
-       if (system_supports_sme() && type == ARM64_VEC_SME) {
-               task->thread.svcr &= ~(SVCR_SM_MASK |
-                                      SVCR_ZA_MASK);
-               clear_thread_flag(TIF_SME);
+       if (system_supports_sme()) {
+               if (type == ARM64_VEC_SME ||
+                   !(task->thread.svcr & (SVCR_SM_MASK | SVCR_ZA_MASK))) {
+                       /*
+                        * We are changing the SME VL or weren't using
+                        * SME anyway, discard the state and force a
+                        * reallocation.
+                        */
+                       task->thread.svcr &= ~(SVCR_SM_MASK |
+                                              SVCR_ZA_MASK);
+                       clear_thread_flag(TIF_SME);
+                       free_sme = true;
+               }
        }
 
        if (task == current)
                put_cpu_fpsimd_context();
 
        /*
-        * Force reallocation of task SVE and SME state to the correct
-        * size on next use:
+        * Free the changed states if they are not in use, SME will be
+        * reallocated to the correct size on next use and we just
+        * allocate SVE now in case it is needed for use in streaming
+        * mode.
         */
-       sve_free(task);
-       if (system_supports_sme() && type == ARM64_VEC_SME)
+       if (system_supports_sve()) {
+               sve_free(task);
+               sve_alloc(task, true);
+       }
+
+       if (free_sme)
                sme_free(task);
 
        task_set_vl(task, type, vl);
index 4236cf3..9941c5b 100644 (file)
@@ -6,6 +6,10 @@
  *
  */
 
+int __kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts);
+int __kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz);
+int __kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res);
+
 int __kernel_clock_gettime(clockid_t clock,
                           struct __kernel_timespec *ts)
 {
index 0696732..6dcdae4 100644 (file)
@@ -827,8 +827,8 @@ static void timer_set_traps(struct kvm_vcpu *vcpu, struct timer_map *map)
        assign_clear_set_bit(tpt, CNTHCTL_EL1PCEN << 10, set, clr);
        assign_clear_set_bit(tpc, CNTHCTL_EL1PCTEN << 10, set, clr);
 
-       /* This only happens on VHE, so use the CNTKCTL_EL1 accessor */
-       sysreg_clear_set(cntkctl_el1, clr, set);
+       /* This only happens on VHE, so use the CNTHCTL_EL2 accessor. */
+       sysreg_clear_set(cnthctl_el2, clr, set);
 }
 
 void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
@@ -1563,7 +1563,7 @@ no_vgic:
 void kvm_timer_init_vhe(void)
 {
        if (cpus_have_final_cap(ARM64_HAS_ECV_CNTPOFF))
-               sysreg_clear_set(cntkctl_el1, 0, CNTHCTL_ECV);
+               sysreg_clear_set(cnthctl_el2, 0, CNTHCTL_ECV);
 }
 
 int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
index c2c1405..72dc53a 100644 (file)
@@ -53,11 +53,16 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
 
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 
-static bool vgic_present;
+static bool vgic_present, kvm_arm_initialised;
 
 static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
 DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
+bool is_kvm_arm_initialised(void)
+{
+       return kvm_arm_initialised;
+}
+
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -713,13 +718,15 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
         */
        preempt_disable();
        kvm_vgic_vmcr_sync(vcpu);
-       vgic_v4_put(vcpu, true);
+       vcpu_set_flag(vcpu, IN_WFI);
+       vgic_v4_put(vcpu);
        preempt_enable();
 
        kvm_vcpu_halt(vcpu);
        vcpu_clear_flag(vcpu, IN_WFIT);
 
        preempt_disable();
+       vcpu_clear_flag(vcpu, IN_WFI);
        vgic_v4_load(vcpu);
        preempt_enable();
 }
@@ -787,7 +794,7 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
                if (kvm_check_request(KVM_REQ_RELOAD_GICv4, vcpu)) {
                        /* The distributor enable bits were changed */
                        preempt_disable();
-                       vgic_v4_put(vcpu, false);
+                       vgic_v4_put(vcpu);
                        vgic_v4_load(vcpu);
                        preempt_enable();
                }
@@ -1867,8 +1874,17 @@ static void _kvm_arch_hardware_enable(void *discard)
 
 int kvm_arch_hardware_enable(void)
 {
-       int was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
+       int was_enabled;
+
+       /*
+        * Most calls to this function are made with migration
+        * disabled, but not with preemption disabled. The former is
+        * enough to ensure correctness, but most of the helpers
+        * expect the later and will throw a tantrum otherwise.
+        */
+       preempt_disable();
 
+       was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
        _kvm_arch_hardware_enable(NULL);
 
        if (!was_enabled) {
@@ -1876,6 +1892,8 @@ int kvm_arch_hardware_enable(void)
                kvm_timer_cpu_up();
        }
 
+       preempt_enable();
+
        return 0;
 }
 
@@ -2482,6 +2500,8 @@ static __init int kvm_arm_init(void)
        if (err)
                goto out_subs;
 
+       kvm_arm_initialised = true;
+
        return 0;
 
 out_subs:
index 8f3f93f..03f97d7 100644 (file)
@@ -154,6 +154,12 @@ SYM_CODE_END(\label)
        esb
        stp     x0, x1, [sp, #-16]!
 662:
+       /*
+        * spectre vectors __bp_harden_hyp_vecs generate br instructions at runtime
+        * that jump at offset 8 at __kvm_hyp_vector.
+        * As hyp .text is guarded section, it needs bti j.
+        */
+       bti j
        b       \target
 
 check_preamble_length 661b, 662b
@@ -165,6 +171,8 @@ check_preamble_length 661b, 662b
        nop
        stp     x0, x1, [sp, #-16]!
 662:
+       /* Check valid_vect */
+       bti j
        b       \target
 
 check_preamble_length 661b, 662b
index c87c631..7693a67 100644 (file)
@@ -297,3 +297,13 @@ SYM_CODE_START(__kvm_hyp_host_forward_smc)
 
        ret
 SYM_CODE_END(__kvm_hyp_host_forward_smc)
+
+/*
+ * kvm_host_psci_cpu_entry is called through br instruction, which requires
+ * bti j instruction as compilers (gcc and llvm) doesn't insert bti j for external
+ * functions, but bti c instead.
+ */
+SYM_CODE_START(kvm_host_psci_cpu_entry)
+       bti j
+       b __kvm_host_psci_cpu_entry
+SYM_CODE_END(kvm_host_psci_cpu_entry)
index 0850878..24543d2 100644 (file)
@@ -200,7 +200,7 @@ static int psci_system_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
                         __hyp_pa(init_params), 0);
 }
 
-asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on)
+asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on)
 {
        struct psci_boot_args *boot_args;
        struct kvm_cpu_context *host_ctxt;
index aa740a9..f7a93ef 100644 (file)
@@ -1195,25 +1195,54 @@ kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr)
        return pte;
 }
 
-kvm_pte_t kvm_pgtable_stage2_mkold(struct kvm_pgtable *pgt, u64 addr)
+struct stage2_age_data {
+       bool    mkold;
+       bool    young;
+};
+
+static int stage2_age_walker(const struct kvm_pgtable_visit_ctx *ctx,
+                            enum kvm_pgtable_walk_flags visit)
 {
-       kvm_pte_t pte = 0;
-       stage2_update_leaf_attrs(pgt, addr, 1, 0, KVM_PTE_LEAF_ATTR_LO_S2_AF,
-                                &pte, NULL, 0);
+       kvm_pte_t new = ctx->old & ~KVM_PTE_LEAF_ATTR_LO_S2_AF;
+       struct stage2_age_data *data = ctx->arg;
+
+       if (!kvm_pte_valid(ctx->old) || new == ctx->old)
+               return 0;
+
+       data->young = true;
+
+       /*
+        * stage2_age_walker() is always called while holding the MMU lock for
+        * write, so this will always succeed. Nonetheless, this deliberately
+        * follows the race detection pattern of the other stage-2 walkers in
+        * case the locking mechanics of the MMU notifiers is ever changed.
+        */
+       if (data->mkold && !stage2_try_set_pte(ctx, new))
+               return -EAGAIN;
+
        /*
         * "But where's the TLBI?!", you scream.
         * "Over in the core code", I sigh.
         *
         * See the '->clear_flush_young()' callback on the KVM mmu notifier.
         */
-       return pte;
+       return 0;
 }
 
-bool kvm_pgtable_stage2_is_young(struct kvm_pgtable *pgt, u64 addr)
+bool kvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr,
+                                        u64 size, bool mkold)
 {
-       kvm_pte_t pte = 0;
-       stage2_update_leaf_attrs(pgt, addr, 1, 0, 0, &pte, NULL, 0);
-       return pte & KVM_PTE_LEAF_ATTR_LO_S2_AF;
+       struct stage2_age_data data = {
+               .mkold          = mkold,
+       };
+       struct kvm_pgtable_walker walker = {
+               .cb             = stage2_age_walker,
+               .arg            = &data,
+               .flags          = KVM_PGTABLE_WALK_LEAF,
+       };
+
+       WARN_ON(kvm_pgtable_walk(pgt, addr, size, &walker));
+       return data.young;
 }
 
 int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
index 6db9ef2..d3b4fee 100644 (file)
@@ -1756,27 +1756,25 @@ bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        u64 size = (range->end - range->start) << PAGE_SHIFT;
-       kvm_pte_t kpte;
-       pte_t pte;
 
        if (!kvm->arch.mmu.pgt)
                return false;
 
-       WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE);
-
-       kpte = kvm_pgtable_stage2_mkold(kvm->arch.mmu.pgt,
-                                       range->start << PAGE_SHIFT);
-       pte = __pte(kpte);
-       return pte_valid(pte) && pte_young(pte);
+       return kvm_pgtable_stage2_test_clear_young(kvm->arch.mmu.pgt,
+                                                  range->start << PAGE_SHIFT,
+                                                  size, true);
 }
 
 bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
+       u64 size = (range->end - range->start) << PAGE_SHIFT;
+
        if (!kvm->arch.mmu.pgt)
                return false;
 
-       return kvm_pgtable_stage2_is_young(kvm->arch.mmu.pgt,
-                                          range->start << PAGE_SHIFT);
+       return kvm_pgtable_stage2_test_clear_young(kvm->arch.mmu.pgt,
+                                                  range->start << PAGE_SHIFT,
+                                                  size, false);
 }
 
 phys_addr_t kvm_mmu_get_httbr(void)
index 994a494..6ff3ec1 100644 (file)
@@ -244,7 +244,7 @@ static int __init finalize_pkvm(void)
 {
        int ret;
 
-       if (!is_protected_kvm_enabled())
+       if (!is_protected_kvm_enabled() || !is_kvm_arm_initialised())
                return 0;
 
        /*
index bd34318..2ca2973 100644 (file)
@@ -986,7 +986,6 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
        if (p->is_write) {
                kvm_pmu_set_counter_event_type(vcpu, p->regval, idx);
-               __vcpu_sys_reg(vcpu, reg) = p->regval & ARMV8_PMU_EVTYPE_MASK;
                kvm_vcpu_pmu_restore_guest(vcpu);
        } else {
                p->regval = __vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_MASK;
@@ -1115,18 +1114,19 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        { SYS_DESC(SYS_DBGWCRn_EL1(n)),                                 \
          trap_wcr, reset_wcr, 0, 0,  get_wcr, set_wcr }
 
-#define PMU_SYS_REG(r)                                         \
-       SYS_DESC(r), .reset = reset_pmu_reg, .visibility = pmu_visibility
+#define PMU_SYS_REG(name)                                              \
+       SYS_DESC(SYS_##name), .reset = reset_pmu_reg,                   \
+       .visibility = pmu_visibility
 
 /* Macro to expand the PMEVCNTRn_EL0 register */
 #define PMU_PMEVCNTR_EL0(n)                                            \
-       { PMU_SYS_REG(SYS_PMEVCNTRn_EL0(n)),                            \
+       { PMU_SYS_REG(PMEVCNTRn_EL0(n)),                                \
          .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,          \
          .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
 #define PMU_PMEVTYPER_EL0(n)                                           \
-       { PMU_SYS_REG(SYS_PMEVTYPERn_EL0(n)),                           \
+       { PMU_SYS_REG(PMEVTYPERn_EL0(n)),                               \
          .reset = reset_pmevtyper,                                     \
          .access = access_pmu_evtyper, .reg = (PMEVTYPER0_EL0 + n), }
 
@@ -2115,9 +2115,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_PMBSR_EL1), undef_access },
        /* PMBIDR_EL1 is not trapped */
 
-       { PMU_SYS_REG(SYS_PMINTENSET_EL1),
+       { PMU_SYS_REG(PMINTENSET_EL1),
          .access = access_pminten, .reg = PMINTENSET_EL1 },
-       { PMU_SYS_REG(SYS_PMINTENCLR_EL1),
+       { PMU_SYS_REG(PMINTENCLR_EL1),
          .access = access_pminten, .reg = PMINTENSET_EL1 },
        { SYS_DESC(SYS_PMMIR_EL1), trap_raz_wi },
 
@@ -2164,41 +2164,41 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_CTR_EL0), access_ctr },
        { SYS_DESC(SYS_SVCR), undef_access },
 
-       { PMU_SYS_REG(SYS_PMCR_EL0), .access = access_pmcr,
+       { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr,
          .reset = reset_pmcr, .reg = PMCR_EL0 },
-       { PMU_SYS_REG(SYS_PMCNTENSET_EL0),
+       { PMU_SYS_REG(PMCNTENSET_EL0),
          .access = access_pmcnten, .reg = PMCNTENSET_EL0 },
-       { PMU_SYS_REG(SYS_PMCNTENCLR_EL0),
+       { PMU_SYS_REG(PMCNTENCLR_EL0),
          .access = access_pmcnten, .reg = PMCNTENSET_EL0 },
-       { PMU_SYS_REG(SYS_PMOVSCLR_EL0),
+       { PMU_SYS_REG(PMOVSCLR_EL0),
          .access = access_pmovs, .reg = PMOVSSET_EL0 },
        /*
         * PM_SWINC_EL0 is exposed to userspace as RAZ/WI, as it was
         * previously (and pointlessly) advertised in the past...
         */
-       { PMU_SYS_REG(SYS_PMSWINC_EL0),
+       { PMU_SYS_REG(PMSWINC_EL0),
          .get_user = get_raz_reg, .set_user = set_wi_reg,
          .access = access_pmswinc, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMSELR_EL0),
+       { PMU_SYS_REG(PMSELR_EL0),
          .access = access_pmselr, .reset = reset_pmselr, .reg = PMSELR_EL0 },
-       { PMU_SYS_REG(SYS_PMCEID0_EL0),
+       { PMU_SYS_REG(PMCEID0_EL0),
          .access = access_pmceid, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMCEID1_EL0),
+       { PMU_SYS_REG(PMCEID1_EL0),
          .access = access_pmceid, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMCCNTR_EL0),
+       { PMU_SYS_REG(PMCCNTR_EL0),
          .access = access_pmu_evcntr, .reset = reset_unknown,
          .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
-       { PMU_SYS_REG(SYS_PMXEVTYPER_EL0),
+       { PMU_SYS_REG(PMXEVTYPER_EL0),
          .access = access_pmu_evtyper, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMXEVCNTR_EL0),
+       { PMU_SYS_REG(PMXEVCNTR_EL0),
          .access = access_pmu_evcntr, .reset = NULL },
        /*
         * PMUSERENR_EL0 resets as unknown in 64bit mode while it resets as zero
         * in 32bit mode. Here we choose to reset it as zero for consistency.
         */
-       { PMU_SYS_REG(SYS_PMUSERENR_EL0), .access = access_pmuserenr,
+       { PMU_SYS_REG(PMUSERENR_EL0), .access = access_pmuserenr,
          .reset = reset_val, .reg = PMUSERENR_EL0, .val = 0 },
-       { PMU_SYS_REG(SYS_PMOVSSET_EL0),
+       { PMU_SYS_REG(PMOVSSET_EL0),
          .access = access_pmovs, .reg = PMOVSSET_EL0 },
 
        { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
@@ -2354,7 +2354,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
         * PMCCFILTR_EL0 resets as unknown in 64bit mode while it resets as zero
         * in 32bit mode. Here we choose to reset it as zero for consistency.
         */
-       { PMU_SYS_REG(SYS_PMCCFILTR_EL0), .access = access_pmu_evtyper,
+       { PMU_SYS_REG(PMCCFILTR_EL0), .access = access_pmu_evtyper,
          .reset = reset_val, .reg = PMCCFILTR_EL0, .val = 0 },
 
        EL2_REG(VPIDR_EL2, access_rw, reset_unknown, 0),
index c3b8e13..3dfc8b8 100644 (file)
@@ -749,7 +749,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 
-       WARN_ON(vgic_v4_put(vcpu, false));
+       WARN_ON(vgic_v4_put(vcpu));
 
        vgic_v3_vmcr_sync(vcpu);
 
index c1c28fe..339a551 100644 (file)
@@ -336,14 +336,14 @@ void vgic_v4_teardown(struct kvm *kvm)
        its_vm->vpes = NULL;
 }
 
-int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db)
+int vgic_v4_put(struct kvm_vcpu *vcpu)
 {
        struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
 
        if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
                return 0;
 
-       return its_make_vpe_non_resident(vpe, need_db);
+       return its_make_vpe_non_resident(vpe, !!vcpu_get_flag(vcpu, IN_WFI));
 }
 
 int vgic_v4_load(struct kvm_vcpu *vcpu)
@@ -354,6 +354,9 @@ int vgic_v4_load(struct kvm_vcpu *vcpu)
        if (!vgic_supports_direct_msis(vcpu->kvm) || vpe->resident)
                return 0;
 
+       if (vcpu_get_flag(vcpu, IN_WFI))
+               return 0;
+
        /*
         * Before making the VPE resident, make sure the redistributor
         * corresponding to our current CPU expects us here. See the
index 4ea2eef..e9ad391 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
+#include <linux/kfence.h>
 
 static void *trans_alloc(struct trans_pgd_info *info)
 {
@@ -41,7 +42,8 @@ static void _copy_pte(pte_t *dst_ptep, pte_t *src_ptep, unsigned long addr)
                 * the temporary mappings we use during restore.
                 */
                set_pte(dst_ptep, pte_mkwrite(pte));
-       } else if (debug_pagealloc_enabled() && !pte_none(pte)) {
+       } else if ((debug_pagealloc_enabled() ||
+                  is_kfence_address((void *)addr)) && !pte_none(pte)) {
                /*
                 * debug_pagealloc will removed the PTE_VALID bit if
                 * the page isn't in use by the resume kernel. It may have
index 145b540..ec21748 100644 (file)
@@ -322,7 +322,13 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
         *
         */
 
-       emit_bti(A64_BTI_C, ctx);
+       /* bpf function may be invoked by 3 instruction types:
+        * 1. bl, attached via freplace to bpf prog via short jump
+        * 2. br, attached via freplace to bpf prog via long jump
+        * 3. blr, working as a function pointer, used by emit_call.
+        * So BTI_JC should used here to support both br and blr.
+        */
+       emit_bti(A64_BTI_JC, ctx);
 
        emit(A64_MOV(1, A64_R(9), A64_LR), ctx);
        emit(A64_NOP, ctx);
index 1ea4a3d..65866bf 100644 (file)
@@ -2017,7 +2017,7 @@ Field     0       SM
 EndSysreg
 
 SysregFields   HFGxTR_EL2
-Field  63      nAMIAIR2_EL1
+Field  63      nAMAIR2_EL1
 Field  62      nMAIR2_EL1
 Field  61      nS2POR_EL1
 Field  60      nPOR_EL1
@@ -2032,9 +2032,9 @@ Field     52      nGCS_EL0
 Res0   51
 Field  50      nACCDATA_EL1
 Field  49      ERXADDR_EL1
-Field  48      EXRPFGCDN_EL1
-Field  47      EXPFGCTL_EL1
-Field  46      EXPFGF_EL1
+Field  48      ERXPFGCDN_EL1
+Field  47      ERXPFGCTL_EL1
+Field  46      ERXPFGF_EL1
 Field  45      ERXMISCn_EL1
 Field  44      ERXSTATUS_EL1
 Field  43      ERXCTLR_EL1
@@ -2049,8 +2049,8 @@ Field     35      TPIDR_EL0
 Field  34      TPIDRRO_EL0
 Field  33      TPIDR_EL1
 Field  32      TCR_EL1
-Field  31      SCTXNUM_EL0
-Field  30      SCTXNUM_EL1
+Field  31      SCXTNUM_EL0
+Field  30      SCXTNUM_EL1
 Field  29      SCTLR_EL1
 Field  28      REVIDR_EL1
 Field  27      PAR_EL1
index 6e948d0..eb561cc 100644 (file)
@@ -63,7 +63,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
        info.low_limit = addr;
        info.high_limit = TASK_SIZE;
        info.align_mask = align_mask;
-       info.align_offset = 0;
+       info.align_offset = pgoff << PAGE_SHIFT;
        return vm_unmapped_area(&info);
 }
 
index 439395a..081922c 100644 (file)
@@ -499,13 +499,13 @@ in_ea:
        dbf     %d0,morein
        rts
 
-       .section .fixup,#alloc,#execinstr
+       .section .fixup,"ax"
        .even
 1:
        jbsr    fpsp040_die
        jbra    .Lnotkern
 
-       .section __ex_table,#alloc
+       .section __ex_table,"a"
        .align  4
 
        .long   in_ea,1b
index 7a0d6e4..89e2ec2 100644 (file)
@@ -379,11 +379,11 @@ _060_real_access:
 
 
 | Execption handling for movs access to illegal memory
-       .section .fixup,#alloc,#execinstr
+       .section .fixup,"ax"
        .even
 1:     moveq           #-1,%d1
        rts
-.section __ex_table,#alloc
+.section __ex_table,"a"
        .align 4
        .long   dmrbuae,1b
        .long   dmrwuae,1b
index ab0f1e7..f766707 100644 (file)
@@ -26,7 +26,7 @@ ENTRY(relocate_new_kernel)
        lea %pc@(.Lcopy),%a4
 2:     addl #0x00000000,%a4            /* virt_to_phys() */
 
-       .section ".m68k_fixup","aw"
+       .section .m68k_fixup,"aw"
        .long M68K_FIXUP_MEMOFFSET, 2b+2
        .previous
 
@@ -49,7 +49,7 @@ ENTRY(relocate_new_kernel)
        lea %pc@(.Lcont040),%a4
 5:     addl #0x00000000,%a4            /* virt_to_phys() */
 
-       .section ".m68k_fixup","aw"
+       .section .m68k_fixup,"aw"
        .long M68K_FIXUP_MEMOFFSET, 5b+2
        .previous
 
index 9915062..ca2d537 100644 (file)
 #include <linux/elf-randomize.h>
 
 /*
- * Construct an artificial page offset for the mapping based on the physical
+ * Construct an artificial page offset for the mapping based on the virtual
  * address of the kernel file mapping variable.
+ * If filp is zero the calculated pgoff value aliases the memory of the given
+ * address. This is useful for io_uring where the mapping shall alias a kernel
+ * address and a userspace adress where both the kernel and the userspace
+ * access the same memory region.
  */
-#define GET_FILP_PGOFF(filp)           \
-       (filp ? (((unsigned long) filp->f_mapping) >> 8)        \
-                & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)
+#define GET_FILP_PGOFF(filp, addr)             \
+       ((filp ? (((unsigned long) filp->f_mapping) >> 8)       \
+                & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)        \
+         + (addr >> PAGE_SHIFT))
 
 static unsigned long shared_align_offset(unsigned long filp_pgoff,
                                         unsigned long pgoff)
@@ -112,7 +117,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
        do_color_align = 0;
        if (filp || (flags & MAP_SHARED))
                do_color_align = 1;
-       filp_pgoff = GET_FILP_PGOFF(filp);
+       filp_pgoff = GET_FILP_PGOFF(filp, addr);
 
        if (flags & MAP_FIXED) {
                /* Even MAP_FIXED mappings must reside within TASK_SIZE */
diff --git a/arch/powerpc/crypto/.gitignore b/arch/powerpc/crypto/.gitignore
new file mode 100644 (file)
index 0000000..e1094f0
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+aesp10-ppc.S
+ghashp10-ppc.S
index ef42adb..00c6b0b 100644 (file)
@@ -4,14 +4,13 @@
 #ifdef __KERNEL__
 
 #include <asm/asm-compat.h>
-#include <asm/extable.h>
 
 #ifdef CONFIG_BUG
 
 #ifdef __ASSEMBLY__
 #include <asm/asm-offsets.h>
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-.macro __EMIT_BUG_ENTRY addr,file,line,flags
+.macro EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"aw"
 5001:   .4byte \addr - .
         .4byte 5002f - .
@@ -23,7 +22,7 @@
         .previous
 .endm
 #else
-.macro __EMIT_BUG_ENTRY addr,file,line,flags
+.macro EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"aw"
 5001:   .4byte \addr - .
         .short \flags
 .endm
 #endif /* verbose */
 
-.macro EMIT_WARN_ENTRY addr,file,line,flags
-       EX_TABLE(\addr,\addr+4)
-       __EMIT_BUG_ENTRY \addr,\file,\line,\flags
-.endm
-
-.macro EMIT_BUG_ENTRY addr,file,line,flags
-       .if \flags & 1 /* BUGFLAG_WARNING */
-       .err /* Use EMIT_WARN_ENTRY for warnings */
-       .endif
-       __EMIT_BUG_ENTRY \addr,\file,\line,\flags
-.endm
-
 #else /* !__ASSEMBLY__ */
 /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
    sizeof(struct bug_entry), respectively */
                  "i" (sizeof(struct bug_entry)),       \
                  ##__VA_ARGS__)
 
-#define WARN_ENTRY(insn, flags, label, ...)            \
-       asm_volatile_goto(                              \
-               "1:     " insn "\n"                     \
-               EX_TABLE(1b, %l[label])                 \
-               _EMIT_BUG_ENTRY                         \
-               : : "i" (__FILE__), "i" (__LINE__),     \
-                 "i" (flags),                          \
-                 "i" (sizeof(struct bug_entry)),       \
-                 ##__VA_ARGS__ : : label)
-
 /*
  * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
  * optimisations. However depending on the complexity of the condition
 } while (0)
 #define HAVE_ARCH_BUG
 
-#define __WARN_FLAGS(flags) do {                               \
-       __label__ __label_warn_on;                              \
-                                                               \
-       WARN_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags), __label_warn_on); \
-       barrier_before_unreachable();                           \
-       __builtin_unreachable();                                \
-                                                               \
-__label_warn_on:                                               \
-       break;                                                  \
-} while (0)
+#define __WARN_FLAGS(flags) BUG_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags))
 
 #ifdef CONFIG_PPC64
 #define BUG_ON(x) do {                                         \
@@ -117,25 +85,15 @@ __label_warn_on:                                           \
 } while (0)
 
 #define WARN_ON(x) ({                                          \
-       bool __ret_warn_on = false;                             \
-       do {                                                    \
-               if (__builtin_constant_p((x))) {                \
-                       if (!(x))                               \
-                               break;                          \
+       int __ret_warn_on = !!(x);                              \
+       if (__builtin_constant_p(__ret_warn_on)) {              \
+               if (__ret_warn_on)                              \
                        __WARN();                               \
-                       __ret_warn_on = true;                   \
-               } else {                                        \
-                       __label__ __label_warn_on;              \
-                                                               \
-                       WARN_ENTRY(PPC_TLNEI " %4, 0",          \
-                                  BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN), \
-                                  __label_warn_on,             \
-                                  "r" ((__force long)(x)));    \
-                       break;                                  \
-__label_warn_on:                                               \
-                       __ret_warn_on = true;                   \
-               }                                               \
-       } while (0);                                            \
+       } else {                                                \
+               BUG_ENTRY(PPC_TLNEI " %4, 0",                   \
+                         BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN),  \
+                         "r" (__ret_warn_on)); \
+       }                                                       \
        unlikely(__ret_warn_on);                                \
 })
 
@@ -148,14 +106,13 @@ __label_warn_on:                                          \
 #ifdef __ASSEMBLY__
 .macro EMIT_BUG_ENTRY addr,file,line,flags
 .endm
-.macro EMIT_WARN_ENTRY addr,file,line,flags
-.endm
 #else /* !__ASSEMBLY__ */
 #define _EMIT_BUG_ENTRY
-#define _EMIT_WARN_ENTRY
 #endif
 #endif /* CONFIG_BUG */
 
+#define EMIT_WARN_ENTRY EMIT_BUG_ENTRY
+
 #include <asm-generic/bug.h>
 
 #ifndef __ASSEMBLY__
index a26ca09..79f1c48 100644 (file)
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
- * 64le only supports ELFv2 64-bit binaries (64be supports v1 and v2).
  */
-#if defined(CONFIG_PPC64) && defined(CONFIG_CPU_LITTLE_ENDIAN)
-#define elf_check_arch(x) (((x)->e_machine == ELF_ARCH) && \
-                          (((x)->e_flags & 0x3) == 0x2))
-#else
 #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
-#endif
 #define compat_elf_check_arch(x)       ((x)->e_machine == EM_PPC)
 
 #define CORE_DUMP_USE_REGSET
index bc5d39a..bf5dde1 100644 (file)
@@ -183,13 +183,9 @@ static inline bool test_thread_local_flags(unsigned int flags)
 #define clear_tsk_compat_task(tsk) do { } while (0)
 #endif
 
-#ifdef CONFIG_PPC64
-#ifdef CONFIG_CPU_BIG_ENDIAN
+#if defined(CONFIG_PPC64)
 #define is_elf2_task() (test_thread_flag(TIF_ELF2ABI))
 #else
-#define is_elf2_task() (1)
-#endif
-#else
 #define is_elf2_task() (0)
 #endif
 
index e59ec6d..7ef147e 100644 (file)
@@ -1508,13 +1508,8 @@ static void do_program_check(struct pt_regs *regs)
 
                if (!(regs->msr & MSR_PR) &&  /* not user-mode */
                    report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
-                       const struct exception_table_entry *entry;
-
-                       entry = search_exception_tables(bugaddr);
-                       if (entry) {
-                               regs_set_return_ip(regs, extable_fixup(entry) + regs->nip - bugaddr);
-                               return;
-                       }
+                       regs_add_return_ip(regs, 4);
+                       return;
                }
 
                if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && user_mode(regs)) {
index 699eeff..f9522fd 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 KASAN_SANITIZE := n
+KCOV_INSTRUMENT := n
 
 obj-$(CONFIG_PPC32)            += init_32.o
 obj-$(CONFIG_PPC_8xx)          += 8xx.o
index 1bfb295..c1e9816 100644 (file)
@@ -477,7 +477,7 @@ static int mpc512x_lpbfifo_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int mpc512x_lpbfifo_remove(struct platform_device *pdev)
+static void mpc512x_lpbfifo_remove(struct platform_device *pdev)
 {
        unsigned long flags;
        struct dma_device *dma_dev = lpbfifo.chan->device;
@@ -494,8 +494,6 @@ static int mpc512x_lpbfifo_remove(struct platform_device *pdev)
        free_irq(lpbfifo.irq, &pdev->dev);
        irq_dispose_mapping(lpbfifo.irq);
        dma_release_channel(lpbfifo.chan);
-
-       return 0;
 }
 
 static const struct of_device_id mpc512x_lpbfifo_match[] = {
@@ -506,7 +504,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_lpbfifo_match);
 
 static struct platform_driver mpc512x_lpbfifo_driver = {
        .probe = mpc512x_lpbfifo_probe,
-       .remove = mpc512x_lpbfifo_remove,
+       .remove_new = mpc512x_lpbfifo_remove,
        .driver = {
                .name = DRV_NAME,
                .of_match_table = mpc512x_lpbfifo_match,
index 9a44a98..3fbc2a6 100644 (file)
@@ -744,6 +744,12 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
                }
 
                task_ref = &win->vas_win.task_ref;
+               /*
+                * VAS mmap (coproc_mmap()) and its fault handler
+                * (vas_mmap_fault()) are called after holding mmap lock.
+                * So hold mmap mutex after mmap_lock to avoid deadlock.
+                */
+               mmap_write_lock(task_ref->mm);
                mutex_lock(&task_ref->mmap_mutex);
                vma = task_ref->vma;
                /*
@@ -752,7 +758,6 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
                 */
                win->vas_win.status |= flag;
 
-               mmap_write_lock(task_ref->mm);
                /*
                 * vma is set in the original mapping. But this mapping
                 * is done with mmap() after the window is opened with ioctl.
@@ -762,8 +767,8 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
                if (vma)
                        zap_vma_pages(vma);
 
-               mmap_write_unlock(task_ref->mm);
                mutex_unlock(&task_ref->mmap_mutex);
+               mmap_write_unlock(task_ref->mm);
                /*
                 * Close VAS window in the hypervisor, but do not
                 * free vas_window struct since it may be reused
index d29a9d9..3834915 100644 (file)
@@ -103,7 +103,7 @@ static inline void _free_kb_keybuf(struct key_blob *kb)
 {
        if (kb->key && kb->key != kb->keybuf
            && kb->keylen > sizeof(kb->keybuf)) {
-               kfree(kb->key);
+               kfree_sensitive(kb->key);
                kb->key = NULL;
        }
 }
index 2f34c7c..bf1fdc7 100644 (file)
@@ -411,8 +411,12 @@ int kvm_s390_pv_deinit_cleanup_all(struct kvm *kvm, u16 *rc, u16 *rrc)
        u16 _rc, _rrc;
        int cc = 0;
 
-       /* Make sure the counter does not reach 0 before calling s390_uv_destroy_range */
-       atomic_inc(&kvm->mm->context.protected_count);
+       /*
+        * Nothing to do if the counter was already 0. Otherwise make sure
+        * the counter does not reach 0 before calling s390_uv_destroy_range.
+        */
+       if (!atomic_inc_not_zero(&kvm->mm->context.protected_count))
+               return 0;
 
        *rc = 1;
        /* If the current VM is protected, destroy it */
index dbe8394..2f12342 100644 (file)
@@ -421,6 +421,8 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
        vma_end_read(vma);
        if (!(fault & VM_FAULT_RETRY)) {
                count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
+               if (likely(!(fault & VM_FAULT_ERROR)))
+                       fault = 0;
                goto out;
        }
        count_vm_vma_lock_event(VMA_LOCK_RETRY);
index 989ebd0..9c8af31 100644 (file)
@@ -2853,6 +2853,7 @@ int s390_replace_asce(struct gmap *gmap)
        page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
        if (!page)
                return -ENOMEM;
+       page->index = 0;
        table = page_to_virt(page);
        memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT));
 
index 320566a..66dbba1 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/cpu.h>
 #include <linux/earlycpio.h>
 #include <linux/initrd.h>
+#include <asm/microcode_amd.h>
 
 struct ucode_patch {
        struct list_head plist;
index e6662ad..9675c62 100644 (file)
@@ -48,11 +48,13 @@ extern void __init load_ucode_amd_bsp(unsigned int family);
 extern void load_ucode_amd_ap(unsigned int family);
 extern int __init save_microcode_in_initrd_amd(unsigned int family);
 void reload_ucode_amd(unsigned int cpu);
+extern void amd_check_microcode(void);
 #else
 static inline void __init load_ucode_amd_bsp(unsigned int family) {}
 static inline void load_ucode_amd_ap(unsigned int family) {}
 static inline int __init
 save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
 static inline void reload_ucode_amd(unsigned int cpu) {}
+static inline void amd_check_microcode(void) {}
 #endif
 #endif /* _ASM_X86_MICROCODE_AMD_H */
index 3aedae6..a00a53e 100644 (file)
 #define MSR_AMD64_DE_CFG               0xc0011029
 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT   1
 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE      BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT)
+#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9
 
 #define MSR_AMD64_BU_CFG2              0xc001102a
 #define MSR_AMD64_IBSFETCHCTL          0xc0011030
index 571abf8..26ad7ca 100644 (file)
 
 #include "cpu.h"
 
-static const int amd_erratum_383[];
-static const int amd_erratum_400[];
-static const int amd_erratum_1054[];
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
-
 /*
  * nodes_per_socket: Stores the number of nodes per socket.
  * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
@@ -39,6 +34,78 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
  */
 static u32 nodes_per_socket = 1;
 
+/*
+ * AMD errata checking
+ *
+ * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
+ * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
+ * have an OSVW id assigned, which it takes as first argument. Both take a
+ * variable number of family-specific model-stepping ranges created by
+ * AMD_MODEL_RANGE().
+ *
+ * Example:
+ *
+ * const int amd_erratum_319[] =
+ *     AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
+ *                        AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
+ *                        AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
+ */
+
+#define AMD_LEGACY_ERRATUM(...)                { -1, __VA_ARGS__, 0 }
+#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
+#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
+       ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
+#define AMD_MODEL_RANGE_FAMILY(range)  (((range) >> 24) & 0xff)
+#define AMD_MODEL_RANGE_START(range)   (((range) >> 12) & 0xfff)
+#define AMD_MODEL_RANGE_END(range)     ((range) & 0xfff)
+
+static const int amd_erratum_400[] =
+       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
+                           AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
+
+static const int amd_erratum_383[] =
+       AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
+
+/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
+static const int amd_erratum_1054[] =
+       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
+
+static const int amd_zenbleed[] =
+       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
+                          AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
+                          AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
+
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
+{
+       int osvw_id = *erratum++;
+       u32 range;
+       u32 ms;
+
+       if (osvw_id >= 0 && osvw_id < 65536 &&
+           cpu_has(cpu, X86_FEATURE_OSVW)) {
+               u64 osvw_len;
+
+               rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
+               if (osvw_id < osvw_len) {
+                       u64 osvw_bits;
+
+                       rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
+                           osvw_bits);
+                       return osvw_bits & (1ULL << (osvw_id & 0x3f));
+               }
+       }
+
+       /* OSVW unavailable or ID unknown, match family-model-stepping range */
+       ms = (cpu->x86_model << 4) | cpu->x86_stepping;
+       while ((range = *erratum++))
+               if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
+                   (ms >= AMD_MODEL_RANGE_START(range)) &&
+                   (ms <= AMD_MODEL_RANGE_END(range)))
+                       return true;
+
+       return false;
+}
+
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
        u32 gprs[8] = { 0 };
@@ -916,6 +983,47 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
        }
 }
 
+static bool cpu_has_zenbleed_microcode(void)
+{
+       u32 good_rev = 0;
+
+       switch (boot_cpu_data.x86_model) {
+       case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
+       case 0x60 ... 0x67: good_rev = 0x0860010b; break;
+       case 0x68 ... 0x6f: good_rev = 0x08608105; break;
+       case 0x70 ... 0x7f: good_rev = 0x08701032; break;
+       case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
+
+       default:
+               return false;
+               break;
+       }
+
+       if (boot_cpu_data.microcode < good_rev)
+               return false;
+
+       return true;
+}
+
+static void zenbleed_check(struct cpuinfo_x86 *c)
+{
+       if (!cpu_has_amd_erratum(c, amd_zenbleed))
+               return;
+
+       if (cpu_has(c, X86_FEATURE_HYPERVISOR))
+               return;
+
+       if (!cpu_has(c, X86_FEATURE_AVX))
+               return;
+
+       if (!cpu_has_zenbleed_microcode()) {
+               pr_notice_once("Zenbleed: please update your microcode for the most optimal fix\n");
+               msr_set_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
+       } else {
+               msr_clear_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
+       }
+}
+
 static void init_amd(struct cpuinfo_x86 *c)
 {
        early_init_amd(c);
@@ -1020,6 +1128,8 @@ static void init_amd(struct cpuinfo_x86 *c)
        if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
            cpu_has(c, X86_FEATURE_AUTOIBRS))
                WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
+
+       zenbleed_check(c);
 }
 
 #ifdef CONFIG_X86_32
@@ -1115,73 +1225,6 @@ static const struct cpu_dev amd_cpu_dev = {
 
 cpu_dev_register(amd_cpu_dev);
 
-/*
- * AMD errata checking
- *
- * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
- * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
- * have an OSVW id assigned, which it takes as first argument. Both take a
- * variable number of family-specific model-stepping ranges created by
- * AMD_MODEL_RANGE().
- *
- * Example:
- *
- * const int amd_erratum_319[] =
- *     AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
- *                        AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
- *                        AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
- */
-
-#define AMD_LEGACY_ERRATUM(...)                { -1, __VA_ARGS__, 0 }
-#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
-#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
-       ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
-#define AMD_MODEL_RANGE_FAMILY(range)  (((range) >> 24) & 0xff)
-#define AMD_MODEL_RANGE_START(range)   (((range) >> 12) & 0xfff)
-#define AMD_MODEL_RANGE_END(range)     ((range) & 0xfff)
-
-static const int amd_erratum_400[] =
-       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
-                           AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
-
-static const int amd_erratum_383[] =
-       AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
-
-/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
-static const int amd_erratum_1054[] =
-       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
-
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
-{
-       int osvw_id = *erratum++;
-       u32 range;
-       u32 ms;
-
-       if (osvw_id >= 0 && osvw_id < 65536 &&
-           cpu_has(cpu, X86_FEATURE_OSVW)) {
-               u64 osvw_len;
-
-               rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
-               if (osvw_id < osvw_len) {
-                       u64 osvw_bits;
-
-                       rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
-                           osvw_bits);
-                       return osvw_bits & (1ULL << (osvw_id & 0x3f));
-               }
-       }
-
-       /* OSVW unavailable or ID unknown, match family-model-stepping range */
-       ms = (cpu->x86_model << 4) | cpu->x86_stepping;
-       while ((range = *erratum++))
-               if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
-                   (ms >= AMD_MODEL_RANGE_START(range)) &&
-                   (ms <= AMD_MODEL_RANGE_END(range)))
-                       return true;
-
-       return false;
-}
-
 static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[4], amd_dr_addr_mask);
 
 static unsigned int amd_msr_dr_addr_masks[] = {
@@ -1235,3 +1278,15 @@ u32 amd_get_highest_perf(void)
        return 255;
 }
 EXPORT_SYMBOL_GPL(amd_get_highest_perf);
+
+static void zenbleed_check_cpu(void *unused)
+{
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+
+       zenbleed_check(c);
+}
+
+void amd_check_microcode(void)
+{
+       on_each_cpu(zenbleed_check_cpu, NULL, 1);
+}
index 52683fd..0ba1067 100644 (file)
@@ -2287,6 +2287,8 @@ void microcode_check(struct cpuinfo_x86 *prev_info)
 
        perf_check_microcode();
 
+       amd_check_microcode();
+
        store_cpu_caps(&curr_info);
 
        if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,
index 58b1f20..4a817d2 100644 (file)
@@ -697,9 +697,10 @@ static bool try_fixup_enqcmd_gp(void)
 }
 
 static bool gp_try_fixup_and_notify(struct pt_regs *regs, int trapnr,
-                                   unsigned long error_code, const char *str)
+                                   unsigned long error_code, const char *str,
+                                   unsigned long address)
 {
-       if (fixup_exception(regs, trapnr, error_code, 0))
+       if (fixup_exception(regs, trapnr, error_code, address))
                return true;
 
        current->thread.error_code = error_code;
@@ -759,7 +760,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
                goto exit;
        }
 
-       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc))
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc, 0))
                goto exit;
 
        if (error_code)
@@ -1357,17 +1358,20 @@ DEFINE_IDTENTRY(exc_device_not_available)
 
 #define VE_FAULT_STR "VE fault"
 
-static void ve_raise_fault(struct pt_regs *regs, long error_code)
+static void ve_raise_fault(struct pt_regs *regs, long error_code,
+                          unsigned long address)
 {
        if (user_mode(regs)) {
                gp_user_force_sig_segv(regs, X86_TRAP_VE, error_code, VE_FAULT_STR);
                return;
        }
 
-       if (gp_try_fixup_and_notify(regs, X86_TRAP_VE, error_code, VE_FAULT_STR))
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_VE, error_code,
+                                   VE_FAULT_STR, address)) {
                return;
+       }
 
-       die_addr(VE_FAULT_STR, regs, error_code, 0);
+       die_addr(VE_FAULT_STR, regs, error_code, address);
 }
 
 /*
@@ -1431,7 +1435,7 @@ DEFINE_IDTENTRY(exc_virtualization_exception)
         * it successfully, treat it as #GP(0) and handle it.
         */
        if (!tdx_handle_virt_exception(regs, &ve))
-               ve_raise_fault(regs, 0);
+               ve_raise_fault(regs, 0, ve.gla);
 
        cond_local_irq_disable(regs);
 }
index 99d8b98..90de500 100644 (file)
@@ -1144,8 +1144,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule)
 {
        if (!list_empty(&plug->cb_list))
                flush_plug_callbacks(plug, from_schedule);
-       if (!rq_list_empty(plug->mq_list))
-               blk_mq_flush_plug_list(plug, from_schedule);
+       blk_mq_flush_plug_list(plug, from_schedule);
        /*
         * Unconditionally flush out cached requests, even if the unplug
         * event came from schedule. Since we know hold references to the
index 9dfcf54..dd64e20 100644 (file)
@@ -2516,6 +2516,10 @@ static void calc_vtime_cost_builtin(struct bio *bio, struct ioc_gq *iocg,
        u64 seek_pages = 0;
        u64 cost = 0;
 
+       /* Can't calculate cost for empty bio */
+       if (!bio->bi_iter.bi_size)
+               goto out;
+
        switch (bio_op(bio)) {
        case REQ_OP_READ:
                coef_seqio      = ioc->params.lcoefs[LCOEF_RSEQIO];
index d50b1d6..b04ff6f 100644 (file)
@@ -2754,7 +2754,14 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 {
        struct request *rq;
 
-       if (rq_list_empty(plug->mq_list))
+       /*
+        * We may have been called recursively midway through handling
+        * plug->mq_list via a schedule() in the driver's queue_rq() callback.
+        * To avoid mq_list changing under our feet, clear rq_count early and
+        * bail out specifically if rq_count is 0 rather than checking
+        * whether the mq_list is empty.
+        */
+       if (plug->rq_count == 0)
                return;
        plug->rq_count = 0;
 
index d92ba2e..2f027d5 100644 (file)
@@ -3980,6 +3980,15 @@ static inline void hl_debugfs_fini(void)
 {
 }
 
+static inline int hl_debugfs_device_init(struct hl_device *hdev)
+{
+       return 0;
+}
+
+static inline void hl_debugfs_device_fini(struct hl_device *hdev)
+{
+}
+
 static inline void hl_debugfs_add_device(struct hl_device *hdev)
 {
 }
index 5c57f7b..cfbc92d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
+#include <linux/overflow.h>
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/types.h>
@@ -366,7 +367,7 @@ static int encode_passthrough(struct qaic_device *qdev, void *trans, struct wrap
        if (in_trans->hdr.len % 8 != 0)
                return -EINVAL;
 
-       if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_EXT_MSG_LENGTH)
+       if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_EXT_MSG_LENGTH)
                return -ENOSPC;
 
        trans_wrapper = add_wrapper(wrappers,
@@ -418,9 +419,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
        }
 
        ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list);
-       if (ret < 0 || ret != nr_pages) {
-               ret = -EFAULT;
+       if (ret < 0)
                goto free_page_list;
+       if (ret != nr_pages) {
+               nr_pages = ret;
+               ret = -EFAULT;
+               goto put_pages;
        }
 
        sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
@@ -557,11 +561,8 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
        msg = &wrapper->msg;
        msg_hdr_len = le32_to_cpu(msg->hdr.len);
 
-       if (msg_hdr_len > (UINT_MAX - QAIC_MANAGE_EXT_MSG_LENGTH))
-               return -EINVAL;
-
        /* There should be enough space to hold at least one ASP entry. */
-       if (msg_hdr_len + sizeof(*out_trans) + sizeof(struct wire_addr_size_pair) >
+       if (size_add(msg_hdr_len, sizeof(*out_trans) + sizeof(struct wire_addr_size_pair)) >
            QAIC_MANAGE_EXT_MSG_LENGTH)
                return -ENOMEM;
 
@@ -634,7 +635,7 @@ static int encode_activate(struct qaic_device *qdev, void *trans, struct wrapper
        msg = &wrapper->msg;
        msg_hdr_len = le32_to_cpu(msg->hdr.len);
 
-       if (msg_hdr_len + sizeof(*out_trans) > QAIC_MANAGE_MAX_MSG_LENGTH)
+       if (size_add(msg_hdr_len, sizeof(*out_trans)) > QAIC_MANAGE_MAX_MSG_LENGTH)
                return -ENOSPC;
 
        if (!in_trans->queue_size)
@@ -718,7 +719,7 @@ static int encode_status(struct qaic_device *qdev, void *trans, struct wrapper_l
        msg = &wrapper->msg;
        msg_hdr_len = le32_to_cpu(msg->hdr.len);
 
-       if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_MAX_MSG_LENGTH)
+       if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_MAX_MSG_LENGTH)
                return -ENOSPC;
 
        trans_wrapper = add_wrapper(wrappers, sizeof(*trans_wrapper));
@@ -748,7 +749,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
        int ret;
        int i;
 
-       if (!user_msg->count) {
+       if (!user_msg->count ||
+           user_msg->len < sizeof(*trans_hdr)) {
                ret = -EINVAL;
                goto out;
        }
@@ -765,12 +767,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
        }
 
        for (i = 0; i < user_msg->count; ++i) {
-               if (user_len >= user_msg->len) {
+               if (user_len > user_msg->len - sizeof(*trans_hdr)) {
                        ret = -EINVAL;
                        break;
                }
                trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len);
-               if (user_len + trans_hdr->len > user_msg->len) {
+               if (trans_hdr->len < sizeof(trans_hdr) ||
+                   size_add(user_len, trans_hdr->len) > user_msg->len) {
                        ret = -EINVAL;
                        break;
                }
@@ -953,15 +956,23 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
        int ret;
        int i;
 
-       if (msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
+       if (msg_hdr_len < sizeof(*trans_hdr) ||
+           msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
                return -EINVAL;
 
        user_msg->len = 0;
        user_msg->count = le32_to_cpu(msg->hdr.count);
 
        for (i = 0; i < user_msg->count; ++i) {
+               u32 hdr_len;
+
+               if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
+                       return -EINVAL;
+
                trans_hdr = (struct wire_trans_hdr *)(msg->data + msg_len);
-               if (msg_len + le32_to_cpu(trans_hdr->len) > msg_hdr_len)
+               hdr_len = le32_to_cpu(trans_hdr->len);
+               if (hdr_len < sizeof(*trans_hdr) ||
+                   size_add(msg_len, hdr_len) > msg_hdr_len)
                        return -EINVAL;
 
                switch (le32_to_cpu(trans_hdr->type)) {
index 8328a49..620ce6c 100644 (file)
@@ -139,4 +139,6 @@ static struct pi_protocol aten = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("ATEN EH-100 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(aten);
index 9f4309f..bba1eda 100644 (file)
@@ -502,4 +502,6 @@ static struct pi_protocol bpck = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("MicroSolutions BACKPACK parallel port IDE adapter protocol driver");
 module_pata_parport_driver(bpck);
index c6dbd14..62c2b53 100644 (file)
@@ -459,5 +459,6 @@ static struct pi_protocol bpck6 = {
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Micro Solutions Inc.");
-MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE");
+MODULE_DESCRIPTION("Micro Solutions BACKPACK parallel port IDE adapter "
+                  "(version 6 drives) protocol driver");
 module_pata_parport_driver(bpck6);
index cc5485b..4839bec 100644 (file)
@@ -201,4 +201,6 @@ static struct pi_protocol comm = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("DataStor Commuter parallel port IDE adapter protocol driver");
 module_pata_parport_driver(comm);
index 368d7c7..88930bb 100644 (file)
@@ -230,4 +230,6 @@ static struct pi_protocol dstr = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("DataStor EP2000 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(dstr);
index 016bd96..3cb54fc 100644 (file)
@@ -358,5 +358,8 @@ static void __exit epat_exit(void)
 }
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Shuttle Technologies EPAT parallel port IDE adapter "
+                  "protocol driver");
 module_init(epat_init)
 module_exit(epat_exit)
index 920e9f4..7aaba47 100644 (file)
@@ -306,4 +306,7 @@ static struct pi_protocol epia = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Shuttle Technologies EPIA parallel port IDE adapter "
+                  "protocol driver");
 module_pata_parport_driver(epia);
index 6524f30..de79cf9 100644 (file)
@@ -132,4 +132,7 @@ static struct pi_protocol fit2 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter"
+                  "(older models) protocol driver");
 module_pata_parport_driver(fit2);
index c172a38..bad7aa9 100644 (file)
@@ -193,4 +193,7 @@ static struct pi_protocol fit3 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter"
+                  "(newer models) protocol driver");
 module_pata_parport_driver(fit3);
index dc428f5..7abe2ff 100644 (file)
@@ -259,4 +259,6 @@ static struct pi_protocol friq = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Freecom IQ parallel port IDE adapter protocol driver");
 module_pata_parport_driver(friq);
index 28d9bb2..7fa9b98 100644 (file)
@@ -293,4 +293,6 @@ static struct pi_protocol frpw = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Freecom Power parallel port IDE adapter protocol driver");
 module_pata_parport_driver(frpw);
index 6023e07..fca3226 100644 (file)
@@ -301,5 +301,8 @@ static void __exit kbic_exit(void)
 }
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("KingByte Information Systems KBIC-951A and KBIC-971A "
+                  "parallel port IDE adapter protocol driver");
 module_init(kbic_init)
 module_exit(kbic_exit)
index bca6c20..c078d19 100644 (file)
@@ -106,4 +106,6 @@ static struct pi_protocol ktti = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("KT Technology parallel port IDE adapter protocol driver");
 module_pata_parport_driver(ktti);
index 34e69da..7c70e5b 100644 (file)
@@ -142,4 +142,6 @@ static struct pi_protocol on20 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Onspec 90c20 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(on20);
index 5da317b..c88e5d6 100644 (file)
@@ -310,4 +310,6 @@ static struct pi_protocol on26 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Onspec 90c26 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(on26);
index fabf870..584bcc5 100644 (file)
@@ -471,6 +471,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
        unsigned int start, end;
        int ret;
 
+       map->async = true;
+
        rbtree_ctx = map->cache;
        for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
                rbnode = rb_entry(node, struct regcache_rbtree_node, node);
@@ -499,6 +501,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
                        return ret;
        }
 
+       map->async = false;
+
        return regmap_async_complete(map);
 }
 
index 28bc3ae..7d3e474 100644 (file)
@@ -368,8 +368,6 @@ int regcache_sync(struct regmap *map)
        if (!map->cache_dirty)
                goto out;
 
-       map->async = true;
-
        /* Apply any patch first */
        map->cache_bypass = true;
        for (i = 0; i < map->patch_regs; i++) {
@@ -392,7 +390,6 @@ int regcache_sync(struct regmap *map)
 
 out:
        /* Restore the bypass state */
-       map->async = false;
        map->cache_bypass = bypass;
        map->no_sync_defaults = false;
        map->unlock(map->lock_arg);
index 980e5ce..3ec611d 100644 (file)
@@ -242,8 +242,8 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
 static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
        .write = regmap_i2c_smbus_i2c_write,
        .read = regmap_i2c_smbus_i2c_read,
-       .max_raw_read = I2C_SMBUS_BLOCK_MAX,
-       .max_raw_write = I2C_SMBUS_BLOCK_MAX,
+       .max_raw_read = I2C_SMBUS_BLOCK_MAX - 1,
+       .max_raw_write = I2C_SMBUS_BLOCK_MAX - 1,
 };
 
 static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data,
@@ -299,8 +299,8 @@ static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg,
 static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
        .write = regmap_i2c_smbus_i2c_write_reg16,
        .read = regmap_i2c_smbus_i2c_read_reg16,
-       .max_raw_read = I2C_SMBUS_BLOCK_MAX,
-       .max_raw_write = I2C_SMBUS_BLOCK_MAX,
+       .max_raw_read = I2C_SMBUS_BLOCK_MAX - 2,
+       .max_raw_write = I2C_SMBUS_BLOCK_MAX - 2,
 };
 
 static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
index 24257aa..9ff3018 100644 (file)
@@ -58,6 +58,9 @@ static struct regmap *gen_regmap(struct regmap_config *config,
        int i;
        struct reg_default *defaults;
 
+       config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
+                                       config->cache_type == REGCACHE_MAPLE;
+
        buf = kmalloc(size, GFP_KERNEL);
        if (!buf)
                return ERR_PTR(-ENOMEM);
@@ -889,6 +892,8 @@ static struct regmap *gen_raw_regmap(struct regmap_config *config,
 
        config->cache_type = test_type->cache_type;
        config->val_format_endian = test_type->val_endian;
+       config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
+                                       config->cache_type == REGCACHE_MAPLE;
 
        buf = kmalloc(size, GFP_KERNEL);
        if (!buf)
index 6af6928..4c2b94b 100644 (file)
@@ -660,7 +660,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = {
        .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
        .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
        .max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT,
-       .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
+       .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
        .free_context = spi_avmm_bridge_ctx_free,
 };
 
index 89a7f1c..1bfd172 100644 (file)
@@ -2082,8 +2082,6 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
        size_t val_count = val_len / val_bytes;
        size_t chunk_count, chunk_bytes;
        size_t chunk_regs = val_count;
-       size_t max_data = map->max_raw_write - map->format.reg_bytes -
-                       map->format.pad_bytes;
        int ret, i;
 
        if (!val_count)
@@ -2091,8 +2089,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 
        if (map->use_single_write)
                chunk_regs = 1;
-       else if (map->max_raw_write && val_len > max_data)
-               chunk_regs = max_data / val_bytes;
+       else if (map->max_raw_write && val_len > map->max_raw_write)
+               chunk_regs = map->max_raw_write / val_bytes;
 
        chunk_count = val_count / chunk_regs;
        chunk_bytes = chunk_regs * val_bytes;
index 37511d2..637c5bd 100644 (file)
@@ -1775,14 +1775,43 @@ static const struct block_device_operations lo_fops = {
 /*
  * If max_loop is specified, create that many devices upfront.
  * This also becomes a hard limit. If max_loop is not specified,
+ * the default isn't a hard limit (as before commit 85c50197716c
+ * changed the default value from 0 for max_loop=0 reasons), just
  * create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module
  * init time. Loop devices can be requested on-demand with the
  * /dev/loop-control interface, or be instantiated by accessing
  * a 'dead' device node.
  */
 static int max_loop = CONFIG_BLK_DEV_LOOP_MIN_COUNT;
-module_param(max_loop, int, 0444);
+
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
+static bool max_loop_specified;
+
+static int max_loop_param_set_int(const char *val,
+                                 const struct kernel_param *kp)
+{
+       int ret;
+
+       ret = param_set_int(val, kp);
+       if (ret < 0)
+               return ret;
+
+       max_loop_specified = true;
+       return 0;
+}
+
+static const struct kernel_param_ops max_loop_param_ops = {
+       .set = max_loop_param_set_int,
+       .get = param_get_int,
+};
+
+module_param_cb(max_loop, &max_loop_param_ops, &max_loop, 0444);
 MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
+#else
+module_param(max_loop, int, 0444);
+MODULE_PARM_DESC(max_loop, "Initial number of loop devices");
+#endif
+
 module_param(max_part, int, 0444);
 MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
 
@@ -2093,14 +2122,18 @@ static void loop_remove(struct loop_device *lo)
        put_disk(lo->lo_disk);
 }
 
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
 static void loop_probe(dev_t dev)
 {
        int idx = MINOR(dev) >> part_shift;
 
-       if (max_loop && idx >= max_loop)
+       if (max_loop_specified && max_loop && idx >= max_loop)
                return;
        loop_add(idx);
 }
+#else
+#define loop_probe NULL
+#endif /* !CONFIG_BLOCK_LEGACY_AUTOLOAD */
 
 static int loop_control_remove(int idx)
 {
@@ -2281,6 +2314,9 @@ module_exit(loop_exit);
 static int __init max_loop_setup(char *str)
 {
        max_loop = simple_strtol(str, NULL, 0);
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
+       max_loop_specified = true;
+#endif
        return 1;
 }
 
index 5ec4ad0..764d176 100644 (file)
@@ -4104,6 +4104,7 @@ static int btusb_probe(struct usb_interface *intf,
        BT_DBG("intf %p id %p", intf, id);
 
        if ((id->driver_info & BTUSB_IFNUM_2) &&
+           (intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
            (intf->cur_altsetting->desc.bInterfaceNumber != 2))
                return -ENODEV;
 
index cd48033..cf5499e 100644 (file)
@@ -518,6 +518,7 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
  * 6.x.y.z series: 6.0.18.6 +
  * 3.x.y.z series: 3.57.y.5 +
  */
+#ifdef CONFIG_X86
 static bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
 {
        u32 val1, val2;
@@ -566,6 +567,12 @@ release:
 
        return true;
 }
+#else
+static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
+{
+       return false;
+}
+#endif /* CONFIG_X86 */
 
 static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
index d43a0d7..1a5d09b 100644 (file)
@@ -563,15 +563,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
        u32 rsp_size;
        int ret;
 
-       INIT_LIST_HEAD(&acpi_resource_list);
-       ret = acpi_dev_get_resources(device, &acpi_resource_list,
-                                    crb_check_resource, iores_array);
-       if (ret < 0)
-               return ret;
-       acpi_dev_free_resource_list(&acpi_resource_list);
-
-       /* Pluton doesn't appear to define ACPI memory regions */
+       /*
+        * Pluton sometimes does not define ACPI memory regions.
+        * Mapping is then done in crb_map_pluton
+        */
        if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
+               INIT_LIST_HEAD(&acpi_resource_list);
+               ret = acpi_dev_get_resources(device, &acpi_resource_list,
+                                            crb_check_resource, iores_array);
+               if (ret < 0)
+                       return ret;
+               acpi_dev_free_resource_list(&acpi_resource_list);
+
                if (resource_type(iores_array) != IORESOURCE_MEM) {
                        dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
                        return -EINVAL;
index 7db3593..cc42cf3 100644 (file)
@@ -116,6 +116,22 @@ static int tpm_tis_disable_irq(const struct dmi_system_id *d)
 static const struct dmi_system_id tpm_tis_dmi_table[] = {
        {
                .callback = tpm_tis_disable_irq,
+               .ident = "Framework Laptop (12th Gen Intel Core)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (12th Gen Intel Core)"),
+               },
+       },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "Framework Laptop (13th Gen Intel Core)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (13th Gen Intel Core)"),
+               },
+       },
+       {
+               .callback = tpm_tis_disable_irq,
                .ident = "ThinkPad T490s",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -140,9 +156,18 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
        },
        {
                .callback = tpm_tis_disable_irq,
+               .ident = "ThinkPad L590",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"),
+               },
+       },
+       {
+               .callback = tpm_tis_disable_irq,
                .ident = "UPX-TGL",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "UPX-TGL"),
                },
        },
        {}
index 558144f..88a5384 100644 (file)
 #include <linux/wait.h>
 #include <linux/acpi.h>
 #include <linux/freezer.h>
+#include <linux/dmi.h>
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
+#define TPM_TIS_MAX_UNHANDLED_IRQS     1000
+
 static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value);
 
 static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
@@ -468,25 +471,29 @@ out_err:
        return rc;
 }
 
-static void disable_interrupts(struct tpm_chip *chip)
+static void __tpm_tis_disable_interrupts(struct tpm_chip *chip)
+{
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       u32 int_mask = 0;
+
+       tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &int_mask);
+       int_mask &= ~TPM_GLOBAL_INT_ENABLE;
+       tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), int_mask);
+
+       chip->flags &= ~TPM_CHIP_FLAG_IRQ;
+}
+
+static void tpm_tis_disable_interrupts(struct tpm_chip *chip)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
-       u32 intmask;
-       int rc;
 
        if (priv->irq == 0)
                return;
 
-       rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
-       if (rc < 0)
-               intmask = 0;
-
-       intmask &= ~TPM_GLOBAL_INT_ENABLE;
-       rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
+       __tpm_tis_disable_interrupts(chip);
 
        devm_free_irq(chip->dev.parent, priv->irq, chip);
        priv->irq = 0;
-       chip->flags &= ~TPM_CHIP_FLAG_IRQ;
 }
 
 /*
@@ -552,7 +559,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
        if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
                tpm_msleep(1);
        if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
-               disable_interrupts(chip);
+               tpm_tis_disable_interrupts(chip);
        set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
        return rc;
 }
@@ -752,6 +759,57 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
        return status == TPM_STS_COMMAND_READY;
 }
 
+static irqreturn_t tpm_tis_revert_interrupts(struct tpm_chip *chip)
+{
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       const char *product;
+       const char *vendor;
+
+       dev_warn(&chip->dev, FW_BUG
+                "TPM interrupt storm detected, polling instead\n");
+
+       vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+       product = dmi_get_system_info(DMI_PRODUCT_VERSION);
+
+       if (vendor && product) {
+               dev_info(&chip->dev,
+                       "Consider adding the following entry to tpm_tis_dmi_table:\n");
+               dev_info(&chip->dev, "\tDMI_SYS_VENDOR: %s\n", vendor);
+               dev_info(&chip->dev, "\tDMI_PRODUCT_VERSION: %s\n", product);
+       }
+
+       if (tpm_tis_request_locality(chip, 0) != 0)
+               return IRQ_NONE;
+
+       __tpm_tis_disable_interrupts(chip);
+       tpm_tis_relinquish_locality(chip, 0);
+
+       schedule_work(&priv->free_irq_work);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t tpm_tis_update_unhandled_irqs(struct tpm_chip *chip)
+{
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       irqreturn_t irqret = IRQ_HANDLED;
+
+       if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
+               return IRQ_HANDLED;
+
+       if (time_after(jiffies, priv->last_unhandled_irq + HZ/10))
+               priv->unhandled_irqs = 1;
+       else
+               priv->unhandled_irqs++;
+
+       priv->last_unhandled_irq = jiffies;
+
+       if (priv->unhandled_irqs > TPM_TIS_MAX_UNHANDLED_IRQS)
+               irqret = tpm_tis_revert_interrupts(chip);
+
+       return irqret;
+}
+
 static irqreturn_t tis_int_handler(int dummy, void *dev_id)
 {
        struct tpm_chip *chip = dev_id;
@@ -761,10 +819,10 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
 
        rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
        if (rc < 0)
-               return IRQ_NONE;
+               goto err;
 
        if (interrupt == 0)
-               return IRQ_NONE;
+               goto err;
 
        set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
        if (interrupt & TPM_INTF_DATA_AVAIL_INT)
@@ -780,10 +838,13 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
        rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
        tpm_tis_relinquish_locality(chip, 0);
        if (rc < 0)
-               return IRQ_NONE;
+               goto err;
 
        tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
        return IRQ_HANDLED;
+
+err:
+       return tpm_tis_update_unhandled_irqs(chip);
 }
 
 static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
@@ -804,6 +865,15 @@ static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
                chip->flags &= ~TPM_CHIP_FLAG_IRQ;
 }
 
+static void tpm_tis_free_irq_func(struct work_struct *work)
+{
+       struct tpm_tis_data *priv = container_of(work, typeof(*priv), free_irq_work);
+       struct tpm_chip *chip = priv->chip;
+
+       devm_free_irq(chip->dev.parent, priv->irq, chip);
+       priv->irq = 0;
+}
+
 /* Register the IRQ and issue a command that will cause an interrupt. If an
  * irq is seen then leave the chip setup for IRQ operation, otherwise reverse
  * everything and leave in polling mode. Returns 0 on success.
@@ -816,6 +886,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
        int rc;
        u32 int_status;
 
+       INIT_WORK(&priv->free_irq_work, tpm_tis_free_irq_func);
 
        rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
                                       tis_int_handler, IRQF_ONESHOT | flags,
@@ -918,6 +989,7 @@ void tpm_tis_remove(struct tpm_chip *chip)
                interrupt = 0;
 
        tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt);
+       flush_work(&priv->free_irq_work);
 
        tpm_tis_clkrun_enable(chip, false);
 
@@ -1021,6 +1093,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
        chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX);
        chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX);
        chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX);
+       priv->chip = chip;
        priv->timeout_min = TPM_TIMEOUT_USECS_MIN;
        priv->timeout_max = TPM_TIMEOUT_USECS_MAX;
        priv->phy_ops = phy_ops;
@@ -1179,7 +1252,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                        rc = tpm_tis_request_locality(chip, 0);
                        if (rc < 0)
                                goto out_err;
-                       disable_interrupts(chip);
+                       tpm_tis_disable_interrupts(chip);
                        tpm_tis_relinquish_locality(chip, 0);
                }
        }
index 610bfad..b1a169d 100644 (file)
@@ -91,11 +91,15 @@ enum tpm_tis_flags {
 };
 
 struct tpm_tis_data {
+       struct tpm_chip *chip;
        u16 manufacturer_id;
        struct mutex locality_count_mutex;
        unsigned int locality_count;
        int locality;
        int irq;
+       struct work_struct free_irq_work;
+       unsigned long last_unhandled_irq;
+       unsigned int unhandled_irqs;
        unsigned int int_mask;
        unsigned long flags;
        void __iomem *ilb_base_addr;
index c8c34ad..82fda48 100644 (file)
@@ -189,21 +189,28 @@ static int tpm_tis_i2c_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
        int ret;
 
        for (i = 0; i < TPM_RETRY; i++) {
-               /* write register */
-               msg.len = sizeof(reg);
-               msg.buf = &reg;
-               msg.flags = 0;
-               ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
-               if (ret < 0)
-                       return ret;
-
-               /* read data */
-               msg.buf = result;
-               msg.len = len;
-               msg.flags = I2C_M_RD;
-               ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
-               if (ret < 0)
-                       return ret;
+               u16 read = 0;
+
+               while (read < len) {
+                       /* write register */
+                       msg.len = sizeof(reg);
+                       msg.buf = &reg;
+                       msg.flags = 0;
+                       ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
+                       if (ret < 0)
+                               return ret;
+
+                       /* read data */
+                       msg.buf = result + read;
+                       msg.len = len - read;
+                       msg.flags = I2C_M_RD;
+                       if (msg.len > I2C_SMBUS_BLOCK_MAX)
+                               msg.len = I2C_SMBUS_BLOCK_MAX;
+                       ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
+                       if (ret < 0)
+                               return ret;
+                       read += msg.len;
+               }
 
                ret = tpm_tis_i2c_sanity_check_read(reg, len, result);
                if (ret == 0)
@@ -223,19 +230,27 @@ static int tpm_tis_i2c_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
        struct i2c_msg msg = { .addr = phy->i2c_client->addr };
        u8 reg = tpm_tis_i2c_address_to_register(addr);
        int ret;
+       u16 wrote = 0;
 
        if (len > TPM_BUFSIZE - 1)
                return -EIO;
 
-       /* write register and data in one go */
        phy->io_buf[0] = reg;
-       memcpy(phy->io_buf + sizeof(reg), value, len);
-
-       msg.len = sizeof(reg) + len;
        msg.buf = phy->io_buf;
-       ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
-       if (ret < 0)
-               return ret;
+       while (wrote < len) {
+               /* write register and data in one go */
+               msg.len = sizeof(reg) + len - wrote;
+               if (msg.len > I2C_SMBUS_BLOCK_MAX)
+                       msg.len = I2C_SMBUS_BLOCK_MAX;
+
+               memcpy(phy->io_buf + sizeof(reg), value + wrote,
+                      msg.len - sizeof(reg));
+
+               ret = tpm_tis_i2c_retry_transfer_until_ack(data, &msg);
+               if (ret < 0)
+                       return ret;
+               wrote += msg.len - sizeof(reg);
+       }
 
        return 0;
 }
index 1f52079..9bfaba0 100644 (file)
@@ -136,6 +136,14 @@ int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
        }
 
 exit:
+       if (ret < 0) {
+               /* Deactivate chip select */
+               memset(&spi_xfer, 0, sizeof(spi_xfer));
+               spi_message_init(&m);
+               spi_message_add_tail(&spi_xfer, &m);
+               spi_sync_locked(phy->spi_device, &m);
+       }
+
        spi_bus_unlock(phy->spi_device->master);
        return ret;
 }
index 5c86598..30e9539 100644 (file)
@@ -683,37 +683,21 @@ static struct miscdevice vtpmx_miscdev = {
        .fops = &vtpmx_fops,
 };
 
-static int vtpmx_init(void)
-{
-       return misc_register(&vtpmx_miscdev);
-}
-
-static void vtpmx_cleanup(void)
-{
-       misc_deregister(&vtpmx_miscdev);
-}
-
 static int __init vtpm_module_init(void)
 {
        int rc;
 
-       rc = vtpmx_init();
-       if (rc) {
-               pr_err("couldn't create vtpmx device\n");
-               return rc;
-       }
-
        workqueue = create_workqueue("tpm-vtpm");
        if (!workqueue) {
                pr_err("couldn't create workqueue\n");
-               rc = -ENOMEM;
-               goto err_vtpmx_cleanup;
+               return -ENOMEM;
        }
 
-       return 0;
-
-err_vtpmx_cleanup:
-       vtpmx_cleanup();
+       rc = misc_register(&vtpmx_miscdev);
+       if (rc) {
+               pr_err("couldn't create vtpmx device\n");
+               destroy_workqueue(workqueue);
+       }
 
        return rc;
 }
@@ -721,7 +705,7 @@ err_vtpmx_cleanup:
 static void __exit vtpm_module_exit(void)
 {
        destroy_workqueue(workqueue);
-       vtpmx_cleanup();
+       misc_deregister(&vtpmx_miscdev);
 }
 
 module_init(vtpm_module_init);
index fcbf829..8ea1d34 100644 (file)
@@ -2,6 +2,8 @@
 menuconfig CXL_BUS
        tristate "CXL (Compute Express Link) Devices Support"
        depends on PCI
+       select FW_LOADER
+       select FW_UPLOAD
        select PCI_DOE
        help
          CXL is a bus that is electrically compatible with PCI Express, but
@@ -82,7 +84,6 @@ config CXL_PMEM
 config CXL_MEM
        tristate "CXL: Memory Expansion"
        depends on CXL_PCI
-       select FW_UPLOAD
        default CXL_BUS
        help
          The CXL.mem protocol allows a device to act as a provider of "System
index 658e6b8..d1c5598 100644 (file)
@@ -296,9 +296,8 @@ err_xormap:
        else
                rc = cxl_decoder_autoremove(dev, cxld);
        if (rc) {
-               dev_err(dev, "Failed to add decode range [%#llx - %#llx]\n",
-                       cxld->hpa_range.start, cxld->hpa_range.end);
-               return 0;
+               dev_err(dev, "Failed to add decode range: %pr", res);
+               return rc;
        }
        dev_dbg(dev, "add: %s node: %d range [%#llx - %#llx]\n",
                dev_name(&cxld->dev),
index 79e99c8..4991133 100644 (file)
@@ -323,7 +323,7 @@ struct cxl_mbox_activate_fw {
 
 /* FW state bits */
 #define CXL_FW_STATE_BITS              32
-#define CXL_FW_CANCEL          BIT(0)
+#define CXL_FW_CANCEL                  0
 
 /**
  * struct cxl_fw_state - Firmware upload / activation state
index b6f71eb..38b4110 100644 (file)
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
        dma_resv_for_each_fence_unlocked(&cursor, fence) {
 
                if (dma_resv_iter_is_restarted(&cursor)) {
+                       struct dma_fence **new_fences;
                        unsigned int count;
 
                        while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
                        count = cursor.num_fences + 1;
 
                        /* Eventually re-allocate the array */
-                       *fences = krealloc_array(*fences, count,
-                                                sizeof(void *),
-                                                GFP_KERNEL);
-                       if (count && !*fences) {
+                       new_fences = krealloc_array(*fences, count,
+                                                   sizeof(void *),
+                                                   GFP_KERNEL);
+                       if (count && !new_fences) {
+                               kfree(*fences);
+                               *fences = NULL;
+                               *num_fences = 0;
                                dma_resv_iter_end(&cursor);
                                return -ENOMEM;
                        }
+                       *fences = new_fences;
                }
 
                (*fences)[(*num_fences)++] = dma_fence_get(fence);
index a68f682..6749711 100644 (file)
@@ -874,7 +874,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
 
        spin_lock_init(&mvpwm->lock);
 
-       return pwmchip_add(&mvpwm->chip);
+       return devm_pwmchip_add(dev, &mvpwm->chip);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -1112,6 +1112,13 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev,
        return 0;
 }
 
+static void mvebu_gpio_remove_irq_domain(void *data)
+{
+       struct irq_domain *domain = data;
+
+       irq_domain_remove(domain);
+}
+
 static int mvebu_gpio_probe(struct platform_device *pdev)
 {
        struct mvebu_gpio_chip *mvchip;
@@ -1243,17 +1250,21 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        if (!mvchip->domain) {
                dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
                        mvchip->chip.label);
-               err = -ENODEV;
-               goto err_pwm;
+               return -ENODEV;
        }
 
+       err = devm_add_action_or_reset(&pdev->dev, mvebu_gpio_remove_irq_domain,
+                                      mvchip->domain);
+       if (err)
+               return err;
+
        err = irq_alloc_domain_generic_chips(
            mvchip->domain, ngpios, 2, np->name, handle_level_irq,
            IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
        if (err) {
                dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
                        mvchip->chip.label);
-               goto err_domain;
+               return err;
        }
 
        /*
@@ -1293,13 +1304,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        }
 
        return 0;
-
-err_domain:
-       irq_domain_remove(mvchip->domain);
-err_pwm:
-       pwmchip_remove(&mvchip->mvpwm->chip);
-
-       return err;
 }
 
 static struct platform_driver mvebu_gpio_driver = {
index aaddcab..532dead 100644 (file)
@@ -91,13 +91,13 @@ static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
 
+       /* Set the initial value */
+       tps68470_gpio_set(gc, offset, value);
+
        /* rest are always outputs */
        if (offset >= TPS68470_N_REGULAR_GPIO)
                return 0;
 
-       /* Set the initial value */
-       tps68470_gpio_set(gc, offset, value);
-
        return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
                                 TPS68470_GPIO_MODE_MASK,
                                 TPS68470_GPIO_MODE_OUT_CMOS);
index a7f314d..d34c3ef 100644 (file)
@@ -1709,7 +1709,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
                        alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
                        AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
                }
-               xcp_id = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id;
+               xcp_id = fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION ?
+                                       0 : fpriv->xcp_id;
        } else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
                domain = alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
                alloc_flags = 0;
index cca5a49..12414a7 100644 (file)
@@ -1229,13 +1229,13 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                pasid = 0;
        }
 
-       r = amdgpu_vm_init(adev, &fpriv->vm);
+       r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
        if (r)
                goto error_pasid;
 
-       r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
+       r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id);
        if (r)
-               goto error_vm;
+               goto error_pasid;
 
        r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid);
        if (r)
index e9091eb..f808841 100644 (file)
@@ -1382,7 +1382,7 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
                goto error_pasid;
        }
 
-       r = amdgpu_vm_init(adev, vm);
+       r = amdgpu_vm_init(adev, vm, -1);
        if (r) {
                DRM_ERROR("failed to initialize vm\n");
                goto error_pasid;
index 6d676bd..78d1ee7 100644 (file)
@@ -498,11 +498,11 @@ static int psp_sw_init(void *handle)
        return 0;
 
 failed2:
-       amdgpu_bo_free_kernel(&psp->fw_pri_bo,
-                             &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
-failed1:
        amdgpu_bo_free_kernel(&psp->fence_buf_bo,
                              &psp->fence_buf_mc_addr, &psp->fence_buf);
+failed1:
+       amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+                             &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
        return ret;
 }
 
index 53ff91f..d0748bc 100644 (file)
@@ -55,8 +55,9 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
                DRM_WARN("%s: vblank timer overrun\n", __func__);
 
        ret = drm_crtc_handle_vblank(crtc);
+       /* Don't queue timer again when vblank is disabled. */
        if (!ret)
-               DRM_ERROR("amdgpu_vkms failure on handling vblank");
+               return HRTIMER_NORESTART;
 
        return HRTIMER_RESTART;
 }
@@ -81,7 +82,7 @@ static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
-       hrtimer_cancel(&amdgpu_crtc->vblank_timer);
+       hrtimer_try_to_cancel(&amdgpu_crtc->vblank_timer);
 }
 
 static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
index 291977b..ec1ec08 100644 (file)
@@ -2121,13 +2121,14 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
+ * @xcp_id: GPU partition selection id
  *
  * Init @vm fields.
  *
  * Returns:
  * 0 for success, error for failure.
  */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id)
 {
        struct amdgpu_bo *root_bo;
        struct amdgpu_bo_vm *root;
@@ -2177,7 +2178,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        vm->evicting = false;
 
        r = amdgpu_vm_pt_create(adev, vm, adev->vm_manager.root_level,
-                               false, &root);
+                               false, &root, xcp_id);
        if (r)
                goto error_free_delayed;
        root_bo = &root->bo;
index 9c85d49..ffac741 100644 (file)
@@ -392,7 +392,7 @@ int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                        u32 pasid);
 
 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id);
 int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
@@ -475,7 +475,8 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
 int amdgpu_vm_pt_clear(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                       struct amdgpu_bo_vm *vmbo, bool immediate);
 int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                       int level, bool immediate, struct amdgpu_bo_vm **vmbo);
+                       int level, bool immediate, struct amdgpu_bo_vm **vmbo,
+                       int32_t xcp_id);
 void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 bool amdgpu_vm_pt_is_root_clean(struct amdgpu_device *adev,
                                struct amdgpu_vm *vm);
index dea1a64..5431332 100644 (file)
@@ -498,11 +498,12 @@ exit:
  * @level: the page table level
  * @immediate: use a immediate update
  * @vmbo: pointer to the buffer object pointer
+ * @xcp_id: GPU partition id
  */
 int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                       int level, bool immediate, struct amdgpu_bo_vm **vmbo)
+                       int level, bool immediate, struct amdgpu_bo_vm **vmbo,
+                       int32_t xcp_id)
 {
-       struct amdgpu_fpriv *fpriv = container_of(vm, struct amdgpu_fpriv, vm);
        struct amdgpu_bo_param bp;
        struct amdgpu_bo *bo;
        struct dma_resv *resv;
@@ -535,7 +536,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
 
        bp.type = ttm_bo_type_kernel;
        bp.no_wait_gpu = immediate;
-       bp.xcp_id_plus1 = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id + 1;
+       bp.xcp_id_plus1 = xcp_id + 1;
 
        if (vm->root.bo)
                bp.resv = vm->root.bo->tbo.base.resv;
@@ -561,7 +562,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        bp.type = ttm_bo_type_kernel;
        bp.resv = bo->tbo.base.resv;
        bp.bo_ptr_size = sizeof(struct amdgpu_bo);
-       bp.xcp_id_plus1 = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id + 1;
+       bp.xcp_id_plus1 = xcp_id + 1;
 
        r = amdgpu_bo_create(adev, &bp, &(*vmbo)->shadow);
 
@@ -606,7 +607,8 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev,
                return 0;
 
        amdgpu_vm_eviction_unlock(vm);
-       r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt);
+       r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt,
+                               vm->root.bo->xcp_id);
        amdgpu_vm_eviction_lock(vm);
        if (r)
                return r;
index d175e86..9c9cca1 100644 (file)
@@ -363,7 +363,7 @@ int amdgpu_xcp_open_device(struct amdgpu_device *adev,
        if (!adev->xcp_mgr)
                return 0;
 
-       fpriv->xcp_id = ~0;
+       fpriv->xcp_id = AMDGPU_XCP_NO_PARTITION;
        for (i = 0; i < MAX_XCP; ++i) {
                if (!adev->xcp_mgr->xcp[i].ddev)
                        break;
@@ -381,7 +381,7 @@ int amdgpu_xcp_open_device(struct amdgpu_device *adev,
                }
        }
 
-       fpriv->vm.mem_id = fpriv->xcp_id == ~0 ? -1 :
+       fpriv->vm.mem_id = fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION ? -1 :
                                adev->xcp_mgr->xcp[fpriv->xcp_id].mem_id;
        return 0;
 }
index 0f8026d..9a1036a 100644 (file)
@@ -37,6 +37,8 @@
 #define AMDGPU_XCP_FL_NONE 0
 #define AMDGPU_XCP_FL_LOCKED (1 << 0)
 
+#define AMDGPU_XCP_NO_PARTITION (~0)
+
 struct amdgpu_fpriv;
 
 enum AMDGPU_XCP_IP_BLOCK {
index 16471b8..72b629a 100644 (file)
@@ -68,7 +68,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
        enum AMDGPU_XCP_IP_BLOCK ip_blk;
        uint32_t inst_mask;
 
-       ring->xcp_id = ~0;
+       ring->xcp_id = AMDGPU_XCP_NO_PARTITION;
        if (adev->xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
                return;
 
@@ -177,7 +177,7 @@ static int aqua_vanjaram_select_scheds(
        u32 sel_xcp_id;
        int i;
 
-       if (fpriv->xcp_id == ~0) {
+       if (fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION) {
                u32 least_ref_cnt = ~0;
 
                fpriv->xcp_id = 0;
index 9e3b835..4f883b9 100644 (file)
@@ -46,6 +46,7 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_3_rlc.bin");
 #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
 
 #define GOLDEN_GB_ADDR_CONFIG 0x2a114042
+#define CP_HQD_PERSISTENT_STATE_DEFAULT 0xbe05301
 
 struct amdgpu_gfx_ras gfx_v9_4_3_ras;
 
@@ -1736,7 +1737,7 @@ static int gfx_v9_4_3_xcc_q_fini_register(struct amdgpu_ring *ring,
 
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_IQ_TIMER, 0);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_IB_CONTROL, 0);
-       WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE, 0);
+       WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE, CP_HQD_PERSISTENT_STATE_DEFAULT);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL, 0x40000000);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL, 0);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR, 0);
index 4dabf91..d9f14dc 100644 (file)
@@ -402,18 +402,15 @@ static void gfxhub_v1_2_xcc_program_invalidation(struct amdgpu_device *adev,
 static int gfxhub_v1_2_xcc_gart_enable(struct amdgpu_device *adev,
                                       uint32_t xcc_mask)
 {
-       uint32_t tmp_mask;
        int i;
 
-       tmp_mask = xcc_mask;
        /*
         * MC_VM_FB_LOCATION_BASE/TOP is NULL for VF, because they are
         * VF copy registers so vbios post doesn't program them, for
         * SRIOV driver need to program them
         */
        if (amdgpu_sriov_vf(adev)) {
-               for_each_inst(i, tmp_mask) {
-                       i = ffs(tmp_mask) - 1;
+               for_each_inst(i, xcc_mask) {
                        WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_BASE,
                                     adev->gmc.vram_start >> 24);
                        WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_TOP,
index f9cb0d2..e1a392b 100644 (file)
@@ -49,6 +49,7 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_10_ta.bin");
 MODULE_FIRMWARE("amdgpu/psp_13_0_11_toc.bin");
 MODULE_FIRMWARE("amdgpu/psp_13_0_11_ta.bin");
 MODULE_FIRMWARE("amdgpu/psp_13_0_6_sos.bin");
+MODULE_FIRMWARE("amdgpu/psp_13_0_6_ta.bin");
 
 /* For large FW files the time to complete can be very long */
 #define USBC_PD_POLLING_LIMIT_S 240
index fff3ccc..9766076 100644 (file)
@@ -302,8 +302,7 @@ static int kfd_dbg_set_queue_workaround(struct queue *q, bool enable)
        if (!q)
                return 0;
 
-       if (KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
-           KFD_GC_VERSION(q->device) >= IP_VERSION(12, 0, 0))
+       if (!kfd_dbg_has_cwsr_workaround(q->device))
                return 0;
 
        if (enable && q->properties.is_user_cu_masked)
@@ -349,7 +348,7 @@ int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd)
 {
        uint32_t spi_dbg_cntl = pdd->spi_dbg_override | pdd->spi_dbg_launch_mode;
        uint32_t flags = pdd->process->dbg_flags;
-       bool sq_trap_en = !!spi_dbg_cntl;
+       bool sq_trap_en = !!spi_dbg_cntl || !kfd_dbg_has_cwsr_workaround(pdd->dev);
 
        if (!kfd_dbg_is_per_vmid_supported(pdd->dev))
                return 0;
index a289e59..662a13a 100644 (file)
@@ -100,6 +100,12 @@ static inline bool kfd_dbg_is_rlc_restore_supported(struct kfd_node *dev)
                 KFD_GC_VERSION(dev) == IP_VERSION(10, 1, 1));
 }
 
+static inline bool kfd_dbg_has_cwsr_workaround(struct kfd_node *dev)
+{
+       return KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
+              KFD_GC_VERSION(dev) <= IP_VERSION(11, 0, 3);
+}
+
 static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
 {
        if ((KFD_GC_VERSION(dev) == IP_VERSION(9, 0, 1)
index f515cb8..2df1538 100644 (file)
@@ -226,8 +226,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
        queue_input.paging = false;
        queue_input.tba_addr = qpd->tba_addr;
        queue_input.tma_addr = qpd->tma_addr;
-       queue_input.trap_en = KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
-                             KFD_GC_VERSION(q->device) > IP_VERSION(11, 0, 3);
+       queue_input.trap_en = !kfd_dbg_has_cwsr_workaround(q->device);
        queue_input.skip_process_ctx_clear = qpd->pqm->process->debug_trap_enabled;
 
        queue_type = convert_to_mes_queue_type(q->properties.type);
@@ -1806,8 +1805,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
         */
        q->properties.is_evicted = !!qpd->evicted;
        q->properties.is_dbg_wa = qpd->pqm->process->debug_trap_enabled &&
-                       KFD_GC_VERSION(q->device) >= IP_VERSION(11, 0, 0) &&
-                       KFD_GC_VERSION(q->device) <= IP_VERSION(11, 0, 3);
+                                 kfd_dbg_has_cwsr_workaround(q->device);
 
        if (qd)
                mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr,
index ff0a217..0fa739f 100644 (file)
@@ -424,12 +424,12 @@ static void dm_pflip_high_irq(void *interrupt_params)
 
        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
 
-       if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
-               DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
-                                                amdgpu_crtc->pflip_status,
-                                                AMDGPU_FLIP_SUBMITTED,
-                                                amdgpu_crtc->crtc_id,
-                                                amdgpu_crtc);
+       if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
+               DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
+                            amdgpu_crtc->pflip_status,
+                            AMDGPU_FLIP_SUBMITTED,
+                            amdgpu_crtc->crtc_id,
+                            amdgpu_crtc);
                spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
                return;
        }
@@ -883,7 +883,7 @@ static int dm_set_powergating_state(void *handle,
 }
 
 /* Prototypes of private functions */
-static int dm_early_init(voidhandle);
+static int dm_early_init(void *handle);
 
 /* Allocate memory for FBC compressed data  */
 static void amdgpu_dm_fbc_init(struct drm_connector *connector)
@@ -1282,7 +1282,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
        pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
        pa_config->system_aperture.end_addr = (uint64_t)logical_addr_high << 18;
 
-       pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24 ;
+       pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24;
        pa_config->system_aperture.agp_bot = (uint64_t)agp_bot << 24;
        pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
 
@@ -1347,6 +1347,15 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
        if (amdgpu_in_reset(adev))
                goto skip;
 
+       if (offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
+               offload_work->data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
+               dm_handle_mst_sideband_msg_ready_event(&aconnector->mst_mgr, DOWN_OR_UP_MSG_RDY_EVENT);
+               spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
+               offload_work->offload_wq->is_handling_mst_msg_rdy_event = false;
+               spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
+               goto skip;
+       }
+
        mutex_lock(&adev->dm.dc_lock);
        if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
                dc_link_dp_handle_automated_test(dc_link);
@@ -1365,8 +1374,7 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
                DP_TEST_RESPONSE,
                &test_response.raw,
                sizeof(test_response));
-       }
-       else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
+       } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
                        dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
                        dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                /* offload_work->data is from handle_hpd_rx_irq->
@@ -1554,7 +1562,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        mutex_init(&adev->dm.dc_lock);
        mutex_init(&adev->dm.audio_lock);
 
-       if(amdgpu_dm_irq_init(adev)) {
+       if (amdgpu_dm_irq_init(adev)) {
                DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
                goto error;
        }
@@ -1696,9 +1704,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
                adev->dm.dc->debug.disable_stutter = true;
 
-       if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) {
+       if (amdgpu_dc_debug_mask & DC_DISABLE_DSC)
                adev->dm.dc->debug.disable_dsc = true;
-       }
 
        if (amdgpu_dc_debug_mask & DC_DISABLE_CLOCK_GATING)
                adev->dm.dc->debug.disable_clock_gate = true;
@@ -1942,8 +1949,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
        mutex_destroy(&adev->dm.audio_lock);
        mutex_destroy(&adev->dm.dc_lock);
        mutex_destroy(&adev->dm.dpia_aux_lock);
-
-       return;
 }
 
 static int load_dmcu_fw(struct amdgpu_device *adev)
@@ -1952,7 +1957,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
        int r;
        const struct dmcu_firmware_header_v1_0 *hdr;
 
-       switch(adev->asic_type) {
+       switch (adev->asic_type) {
 #if defined(CONFIG_DRM_AMD_DC_SI)
        case CHIP_TAHITI:
        case CHIP_PITCAIRN:
@@ -2709,7 +2714,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
                struct dc_scaling_info scaling_infos[MAX_SURFACES];
                struct dc_flip_addrs flip_addrs[MAX_SURFACES];
                struct dc_stream_update stream_update;
-       } * bundle;
+       } *bundle;
        int k, m;
 
        bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
@@ -2739,8 +2744,6 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
 
 cleanup:
        kfree(bundle);
-
-       return;
 }
 
 static int dm_resume(void *handle)
@@ -2954,8 +2957,7 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
        .set_powergating_state = dm_set_powergating_state,
 };
 
-const struct amdgpu_ip_block_version dm_ip_block =
-{
+const struct amdgpu_ip_block_version dm_ip_block = {
        .type = AMD_IP_BLOCK_TYPE_DCE,
        .major = 1,
        .minor = 0,
@@ -3000,9 +3002,12 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
 
-       if (caps->ext_caps->bits.oled == 1 /*||
-           caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
-           caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
+       if (caps->ext_caps->bits.oled == 1
+           /*
+            * ||
+            * caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
+            * caps->ext_caps->bits.hdr_aux_backlight_control == 1
+            */)
                caps->aux_support = true;
 
        if (amdgpu_backlight == 0)
@@ -3236,86 +3241,6 @@ static void handle_hpd_irq(void *param)
 
 }
 
-static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
-{
-       u8 esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
-       u8 dret;
-       bool new_irq_handled = false;
-       int dpcd_addr;
-       int dpcd_bytes_to_read;
-
-       const int max_process_count = 30;
-       int process_count = 0;
-
-       const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
-
-       if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
-               dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
-               /* DPCD 0x200 - 0x201 for downstream IRQ */
-               dpcd_addr = DP_SINK_COUNT;
-       } else {
-               dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
-               /* DPCD 0x2002 - 0x2005 for downstream IRQ */
-               dpcd_addr = DP_SINK_COUNT_ESI;
-       }
-
-       dret = drm_dp_dpcd_read(
-               &aconnector->dm_dp_aux.aux,
-               dpcd_addr,
-               esi,
-               dpcd_bytes_to_read);
-
-       while (dret == dpcd_bytes_to_read &&
-               process_count < max_process_count) {
-               u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
-               u8 retry;
-               dret = 0;
-
-               process_count++;
-
-               DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
-               /* handle HPD short pulse irq */
-               if (aconnector->mst_mgr.mst_state)
-                       drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
-                                                       esi,
-                                                       ack,
-                                                       &new_irq_handled);
-
-               if (new_irq_handled) {
-                       /* ACK at DPCD to notify down stream */
-                       for (retry = 0; retry < 3; retry++) {
-                               ssize_t wret;
-
-                               wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
-                                                         dpcd_addr + 1,
-                                                         ack[1]);
-                               if (wret == 1)
-                                       break;
-                       }
-
-                       if (retry == 3) {
-                               DRM_ERROR("Failed to ack MST event.\n");
-                               return;
-                       }
-
-                       drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
-                       /* check if there is new irq to be handled */
-                       dret = drm_dp_dpcd_read(
-                               &aconnector->dm_dp_aux.aux,
-                               dpcd_addr,
-                               esi,
-                               dpcd_bytes_to_read);
-
-                       new_irq_handled = false;
-               } else {
-                       break;
-               }
-       }
-
-       if (process_count == max_process_count)
-               DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
-}
-
 static void schedule_hpd_rx_offload_work(struct hpd_rx_irq_offload_work_queue *offload_wq,
                                                        union hpd_irq_data hpd_irq_data)
 {
@@ -3377,7 +3302,23 @@ static void handle_hpd_rx_irq(void *param)
        if (dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
                        hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
-                       dm_handle_mst_sideband_msg(aconnector);
+                       bool skip = false;
+
+                       /*
+                        * DOWN_REP_MSG_RDY is also handled by polling method
+                        * mgr->cbs->poll_hpd_irq()
+                        */
+                       spin_lock(&offload_wq->offload_lock);
+                       skip = offload_wq->is_handling_mst_msg_rdy_event;
+
+                       if (!skip)
+                               offload_wq->is_handling_mst_msg_rdy_event = true;
+
+                       spin_unlock(&offload_wq->offload_lock);
+
+                       if (!skip)
+                               schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data);
+
                        goto out;
                }
 
@@ -3468,7 +3409,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
                aconnector = to_amdgpu_dm_connector(connector);
                dc_link = aconnector->dc_link;
 
-               if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
+               if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
                        int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
                        int_params.irq_source = dc_link->irq_source_hpd;
 
@@ -3477,7 +3418,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
                                        (void *) aconnector);
                }
 
-               if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+               if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
 
                        /* Also register for DP short pulse (hpd_rx). */
                        int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
@@ -3486,11 +3427,11 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
                        amdgpu_dm_irq_register_interrupt(adev, &int_params,
                                        handle_hpd_rx_irq,
                                        (void *) aconnector);
-
-                       if (adev->dm.hpd_rx_offload_wq)
-                               adev->dm.hpd_rx_offload_wq[dc_link->link_index].aconnector =
-                                       aconnector;
                }
+
+               if (adev->dm.hpd_rx_offload_wq)
+                       adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
+                               aconnector;
        }
 }
 
@@ -3503,7 +3444,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
        struct dc_interrupt_params int_params = {0};
        int r;
        int i;
-       unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+       unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
 
        int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
        int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
@@ -3517,11 +3458,12 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
         *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
         *    coming from DC hardware.
         *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
-        *    for acknowledging and handling. */
+        *    for acknowledging and handling.
+        */
 
        /* Use VBLANK interrupt */
        for (i = 0; i < adev->mode_info.num_crtc; i++) {
-               r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq);
+               r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq);
                if (r) {
                        DRM_ERROR("Failed to add crtc irq id!\n");
                        return r;
@@ -3529,7 +3471,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
 
                int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
                int_params.irq_source =
-                       dc_interrupt_to_irq_source(dc, i+1 , 0);
+                       dc_interrupt_to_irq_source(dc, i + 1, 0);
 
                c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
 
@@ -3585,7 +3527,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
        struct dc_interrupt_params int_params = {0};
        int r;
        int i;
-       unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+       unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
 
        if (adev->family >= AMDGPU_FAMILY_AI)
                client_id = SOC15_IH_CLIENTID_DCE;
@@ -3602,7 +3544,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
         *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
         *    coming from DC hardware.
         *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
-        *    for acknowledging and handling. */
+        *    for acknowledging and handling.
+        */
 
        /* Use VBLANK interrupt */
        for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) {
@@ -4049,7 +3992,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
 }
 
 static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
-                               unsigned *min, unsigned *max)
+                               unsigned int *min, unsigned int *max)
 {
        if (!caps)
                return 0;
@@ -4069,7 +4012,7 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
 static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
                                        uint32_t brightness)
 {
-       unsigned min, max;
+       unsigned int min, max;
 
        if (!get_brightness_range(caps, &min, &max))
                return brightness;
@@ -4082,7 +4025,7 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c
 static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
                                      uint32_t brightness)
 {
-       unsigned min, max;
+       unsigned int min, max;
 
        if (!get_brightness_range(caps, &min, &max))
                return brightness;
@@ -4562,7 +4505,6 @@ fail:
 static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
 {
        drm_atomic_private_obj_fini(&dm->atomic_obj);
-       return;
 }
 
 /******************************************************************************
@@ -5394,6 +5336,7 @@ static bool adjust_colour_depth_from_display_info(
 {
        enum dc_color_depth depth = timing_out->display_color_depth;
        int normalized_clk;
+
        do {
                normalized_clk = timing_out->pix_clk_100hz / 10;
                /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
@@ -5609,6 +5552,7 @@ create_fake_sink(struct amdgpu_dm_connector *aconnector)
 {
        struct dc_sink_init_data sink_init_data = { 0 };
        struct dc_sink *sink = NULL;
+
        sink_init_data.link = aconnector->dc_link;
        sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
 
@@ -5732,7 +5676,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
                return &aconnector->freesync_vid_base;
 
        /* Find the preferred mode */
-       list_for_each_entry (m, list_head, head) {
+       list_for_each_entry(m, list_head, head) {
                if (m->type & DRM_MODE_TYPE_PREFERRED) {
                        m_pref = m;
                        break;
@@ -5756,7 +5700,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
         * For some monitors, preferred mode is not the mode with highest
         * supported refresh rate.
         */
-       list_for_each_entry (m, list_head, head) {
+       list_for_each_entry(m, list_head, head) {
                current_refresh  = drm_mode_vrefresh(m);
 
                if (m->hdisplay == m_pref->hdisplay &&
@@ -6028,7 +5972,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                 * This may not be an error, the use case is when we have no
                 * usermode calls to reset and set mode upon hotplug. In this
                 * case, we call set mode ourselves to restore the previous mode
-                * and the modelist may not be filled in in time.
+                * and the modelist may not be filled in time.
                 */
                DRM_DEBUG_DRIVER("No preferred mode found\n");
        } else {
@@ -6051,9 +5995,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                drm_mode_set_crtcinfo(&mode, 0);
 
        /*
-       * If scaling is enabled and refresh rate didn't change
-       * we copy the vic and polarities of the old timings
-       */
+        * If scaling is enabled and refresh rate didn't change
+        * we copy the vic and polarities of the old timings
+        */
        if (!scale || mode_refresh != preferred_refresh)
                fill_stream_properties_from_drm_display_mode(
                        stream, &mode, &aconnector->base, con_state, NULL,
@@ -6817,6 +6761,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
 
        if (!state->duplicated) {
                int max_bpc = conn_state->max_requested_bpc;
+
                is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
                          aconnector->force_yuv420_output;
                color_depth = convert_color_depth_from_display_info(connector,
@@ -7135,7 +7080,7 @@ static bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
 {
        struct drm_display_mode *m;
 
-       list_for_each_entry (m, &aconnector->base.probed_modes, head) {
+       list_for_each_entry(m, &aconnector->base.probed_modes, head) {
                if (drm_mode_equal(m, mode))
                        return true;
        }
@@ -7295,6 +7240,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
        memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info));
        mutex_init(&aconnector->hpd_lock);
+       mutex_init(&aconnector->handle_mst_msg_ready);
 
        /*
         * configure support HPD hot plug connector_>polled default value is 0
@@ -7454,7 +7400,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
 
        link->priv = aconnector;
 
-       DRM_DEBUG_DRIVER("%s()\n", __func__);
 
        i2c = create_i2c(link->ddc, link->link_index, &res);
        if (!i2c) {
@@ -8125,7 +8070,15 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                 * Only allow immediate flips for fast updates that don't
                 * change memory domain, FB pitch, DCC state, rotation or
                 * mirroring.
+                *
+                * dm_crtc_helper_atomic_check() only accepts async flips with
+                * fast updates.
                 */
+               if (crtc->state->async_flip &&
+                   acrtc_state->update_type != UPDATE_TYPE_FAST)
+                       drm_warn_once(state->dev,
+                                     "[PLANE:%d:%s] async flip with non-fast update\n",
+                                     plane->base.id, plane->name);
                bundle->flip_addrs[planes_count].flip_immediate =
                        crtc->state->async_flip &&
                        acrtc_state->update_type == UPDATE_TYPE_FAST &&
@@ -8168,8 +8121,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                         * DRI3/Present extension with defined target_msc.
                         */
                        last_flip_vblank = amdgpu_get_vblank_counter_kms(pcrtc);
-               }
-               else {
+               } else {
                        /* For variable refresh rate mode only:
                         * Get vblank of last completed flip to avoid > 1 vrr
                         * flips per video frame by use of throttling, but allow
@@ -8502,8 +8454,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                dc_resource_state_copy_construct_current(dm->dc, dc_state);
        }
 
-       for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state,
-                                      new_crtc_state, i) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
+                                     new_crtc_state, i) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
@@ -8526,9 +8478,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
                drm_dbg_state(state->dev,
-                       "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
-                       "planes_changed:%d, mode_changed:%d,active_changed:%d,"
-                       "connectors_changed:%d\n",
+                       "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
                        acrtc->crtc_id,
                        new_crtc_state->enable,
                        new_crtc_state->active,
@@ -9104,8 +9054,8 @@ static int do_aquire_global_lock(struct drm_device *dev,
                                        &commit->flip_done, 10*HZ);
 
                if (ret == 0)
-                       DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done "
-                                 "timed out\n", crtc->base.id, crtc->name);
+                       DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done timed out\n",
+                                 crtc->base.id, crtc->name);
 
                drm_crtc_commit_put(commit);
        }
@@ -9190,7 +9140,8 @@ is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
        return false;
 }
 
-static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
+static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
+{
        u64 num, den, res;
        struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
 
@@ -9312,9 +9263,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                goto skip_modeset;
 
        drm_dbg_state(state->dev,
-               "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
-               "planes_changed:%d, mode_changed:%d,active_changed:%d,"
-               "connectors_changed:%d\n",
+               "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
                acrtc->crtc_id,
                new_crtc_state->enable,
                new_crtc_state->active,
@@ -9343,8 +9292,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                                                     old_crtc_state)) {
                        new_crtc_state->mode_changed = false;
                        DRM_DEBUG_DRIVER(
-                               "Mode change not required for front porch change, "
-                               "setting mode_changed to %d",
+                               "Mode change not required for front porch change, setting mode_changed to %d",
                                new_crtc_state->mode_changed);
 
                        set_freesync_fixed_config(dm_new_crtc_state);
@@ -9356,9 +9304,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                        struct drm_display_mode *high_mode;
 
                        high_mode = get_highest_refresh_rate_mode(aconnector, false);
-                       if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
+                       if (!drm_mode_equal(&new_crtc_state->mode, high_mode))
                                set_freesync_fixed_config(dm_new_crtc_state);
-                       }
                }
 
                ret = dm_atomic_get_state(state, &dm_state);
@@ -9526,6 +9473,7 @@ static bool should_reset_plane(struct drm_atomic_state *state,
         */
        for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
                struct amdgpu_framebuffer *old_afb, *new_afb;
+
                if (other->type == DRM_PLANE_TYPE_CURSOR)
                        continue;
 
@@ -9624,11 +9572,12 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
        }
 
        /* Core DRM takes care of checking FB modifiers, so we only need to
-        * check tiling flags when the FB doesn't have a modifier. */
+        * check tiling flags when the FB doesn't have a modifier.
+        */
        if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
                if (adev->family < AMDGPU_FAMILY_AI) {
                        linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
-                                AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
+                                AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
                                 AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
                } else {
                        linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
@@ -9850,12 +9799,12 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
        /* On DCE and DCN there is no dedicated hardware cursor plane. We get a
         * cursor per pipe but it's going to inherit the scaling and
         * positioning from the underlying pipe. Check the cursor plane's
-        * blending properties match the underlying planes'. */
+        * blending properties match the underlying planes'.
+        */
 
        new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
-       if (!new_cursor_state || !new_cursor_state->fb) {
+       if (!new_cursor_state || !new_cursor_state->fb)
                return 0;
-       }
 
        dm_get_oriented_plane_size(new_cursor_state, &cursor_src_w, &cursor_src_h);
        cursor_scale_w = new_cursor_state->crtc_w * 1000 / cursor_src_w;
@@ -9900,6 +9849,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
        struct drm_connector_state *conn_state, *old_conn_state;
        struct amdgpu_dm_connector *aconnector = NULL;
        int i;
+
        for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
                if (!conn_state->crtc)
                        conn_state = old_conn_state;
@@ -10334,7 +10284,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        }
 
        /* Store the overall update type for use later in atomic check. */
-       for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                struct dm_crtc_state *dm_new_crtc_state =
                        to_dm_crtc_state(new_crtc_state);
 
@@ -10356,7 +10306,7 @@ fail:
        else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
                DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n");
        else
-               DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
+               DRM_DEBUG_DRIVER("Atomic check failed with err: %d\n", ret);
 
        trace_amdgpu_dm_atomic_check_finish(state, ret);
 
index 4561f55..9fb5bb3 100644 (file)
@@ -195,6 +195,11 @@ struct hpd_rx_irq_offload_work_queue {
         */
        bool is_handling_link_loss;
        /**
+        * @is_handling_mst_msg_rdy_event: Used to prevent inserting mst message
+        * ready event when we're already handling mst message ready event
+        */
+       bool is_handling_mst_msg_rdy_event;
+       /**
         * @aconnector: The aconnector that this work queue is attached to
         */
        struct amdgpu_dm_connector *aconnector;
@@ -638,6 +643,8 @@ struct amdgpu_dm_connector {
        struct drm_dp_mst_port *mst_output_port;
        struct amdgpu_dm_connector *mst_root;
        struct drm_dp_aux *dsc_aux;
+       struct mutex handle_mst_msg_ready;
+
        /* TODO see if we can merge with ddc_bus or make a dm_connector */
        struct amdgpu_i2c_adapter *i2c;
 
index 440fc08..30d4c6f 100644 (file)
@@ -398,6 +398,18 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
+       /*
+        * Only allow async flips for fast updates that don't change the FB
+        * pitch, the DCC state, rotation, etc.
+        */
+       if (crtc_state->async_flip &&
+           dm_crtc_state->update_type != UPDATE_TYPE_FAST) {
+               drm_dbg_atomic(crtc->dev,
+                              "[CRTC:%d:%s] async flips are only supported for fast updates\n",
+                              crtc->base.id, crtc->name);
+               return -EINVAL;
+       }
+
        /* In some use cases, like reset, no stream is attached */
        if (!dm_crtc_state->stream)
                return 0;
index 46d0a8f..9bc86de 100644 (file)
@@ -619,8 +619,118 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        return connector;
 }
 
+void dm_handle_mst_sideband_msg_ready_event(
+       struct drm_dp_mst_topology_mgr *mgr,
+       enum mst_msg_ready_type msg_rdy_type)
+{
+       uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
+       uint8_t dret;
+       bool new_irq_handled = false;
+       int dpcd_addr;
+       uint8_t dpcd_bytes_to_read;
+       const uint8_t max_process_count = 30;
+       uint8_t process_count = 0;
+       u8 retry;
+       struct amdgpu_dm_connector *aconnector =
+                       container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
+
+
+       const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
+
+       if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
+               dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
+               /* DPCD 0x200 - 0x201 for downstream IRQ */
+               dpcd_addr = DP_SINK_COUNT;
+       } else {
+               dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
+               /* DPCD 0x2002 - 0x2005 for downstream IRQ */
+               dpcd_addr = DP_SINK_COUNT_ESI;
+       }
+
+       mutex_lock(&aconnector->handle_mst_msg_ready);
+
+       while (process_count < max_process_count) {
+               u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
+
+               process_count++;
+
+               dret = drm_dp_dpcd_read(
+                       &aconnector->dm_dp_aux.aux,
+                       dpcd_addr,
+                       esi,
+                       dpcd_bytes_to_read);
+
+               if (dret != dpcd_bytes_to_read) {
+                       DRM_DEBUG_KMS("DPCD read and acked number is not as expected!");
+                       break;
+               }
+
+               DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+
+               switch (msg_rdy_type) {
+               case DOWN_REP_MSG_RDY_EVENT:
+                       /* Only handle DOWN_REP_MSG_RDY case*/
+                       esi[1] &= DP_DOWN_REP_MSG_RDY;
+                       break;
+               case UP_REQ_MSG_RDY_EVENT:
+                       /* Only handle UP_REQ_MSG_RDY case*/
+                       esi[1] &= DP_UP_REQ_MSG_RDY;
+                       break;
+               default:
+                       /* Handle both cases*/
+                       esi[1] &= (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
+                       break;
+               }
+
+               if (!esi[1])
+                       break;
+
+               /* handle MST irq */
+               if (aconnector->mst_mgr.mst_state)
+                       drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
+                                                esi,
+                                                ack,
+                                                &new_irq_handled);
+
+               if (new_irq_handled) {
+                       /* ACK at DPCD to notify down stream */
+                       for (retry = 0; retry < 3; retry++) {
+                               ssize_t wret;
+
+                               wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
+                                                         dpcd_addr + 1,
+                                                         ack[1]);
+                               if (wret == 1)
+                                       break;
+                       }
+
+                       if (retry == 3) {
+                               DRM_ERROR("Failed to ack MST event.\n");
+                               break;
+                       }
+
+                       drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
+
+                       new_irq_handled = false;
+               } else {
+                       break;
+               }
+       }
+
+       mutex_unlock(&aconnector->handle_mst_msg_ready);
+
+       if (process_count == max_process_count)
+               DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
+}
+
+static void dm_handle_mst_down_rep_msg_ready(struct drm_dp_mst_topology_mgr *mgr)
+{
+       dm_handle_mst_sideband_msg_ready_event(mgr, DOWN_REP_MSG_RDY_EVENT);
+}
+
 static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
        .add_connector = dm_dp_add_mst_connector,
+       .poll_hpd_irq = dm_handle_mst_down_rep_msg_ready,
 };
 
 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
index 1e4ede1..37c820a 100644 (file)
 #define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B     1031
 #define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B  1000
 
+enum mst_msg_ready_type {
+       NONE_MSG_RDY_EVENT = 0,
+       DOWN_REP_MSG_RDY_EVENT = 1,
+       UP_REQ_MSG_RDY_EVENT = 2,
+       DOWN_OR_UP_MSG_RDY_EVENT = 3
+};
+
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;
 
@@ -61,6 +68,10 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
 void
 dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
 
+void dm_handle_mst_sideband_msg_ready_event(
+       struct drm_dp_mst_topology_mgr *mgr,
+       enum mst_msg_ready_type msg_rdy_type);
+
 struct dsc_mst_fairness_vars {
        int pbn;
        bool dsc_enabled;
index 7ccd969..3db4ef5 100644 (file)
@@ -87,6 +87,11 @@ static int dcn31_get_active_display_cnt_wa(
                                stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
                                stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
                        tmds_present = true;
+
+               /* Checking stream / link detection ensuring that PHY is active*/
+               if (dc_is_dp_signal(stream->signal) && !stream->dpms_off)
+                       display_count++;
+
        }
 
        for (i = 0; i < dc->link_count; i++) {
index 6c9ca43..20d4d08 100644 (file)
@@ -1792,10 +1792,13 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
                        hws->funcs.edp_backlight_control(edp_link_with_sink, false);
                }
                /*resume from S3, no vbios posting, no need to power down again*/
+               clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
+
                power_down_all_hw_blocks(dc);
                disable_vga_and_power_gate_all_controllers(dc);
                if (edp_link_with_sink && !keep_edp_vdd_on)
                        dc->hwss.edp_power_control(edp_link_with_sink, false);
+               clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
        }
        bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1);
 }
index a503090..9834b75 100644 (file)
@@ -3278,7 +3278,8 @@ void dcn10_wait_for_mpcc_disconnect(
                if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
                        struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
 
-                       if (pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
+                       if (pipe_ctx->stream_res.tg &&
+                               pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
                                res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
                        pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
                        hubp->funcs->set_blank(hubp, true);
index dfb8f62..5bf4d0a 100644 (file)
@@ -215,7 +215,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc,
        optc1->opp_count = 1;
 }
 
-static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
                struct dc_crtc_timing *timing)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -293,7 +293,7 @@ static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool e
                   OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode);
 }
 
-static void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc)
+void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
index fb06dc9..d3a056c 100644 (file)
@@ -351,6 +351,9 @@ void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable);
 
 void optc3_set_odm_bypass(struct timing_generator *optc,
                const struct dc_crtc_timing *dc_crtc_timing);
+void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+               struct dc_crtc_timing *timing);
+void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc);
 void optc3_tg_init(struct timing_generator *optc);
 void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
 #endif /* __DC_OPTC_DCN30_H__ */
index 7aa628c..9002cb1 100644 (file)
@@ -11,7 +11,8 @@
 # Makefile for dcn30.
 
 DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
-               dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o
+               dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o \
+               dcn301_optc.o
 
 AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c
new file mode 100644 (file)
index 0000000..b3cfcb8
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "reg_helper.h"
+#include "dcn301_optc.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
+
+#include "dml/dcn30/dcn30_fpu.h"
+#include "dc_trace.h"
+
+#define REG(reg)\
+       optc1->tg_regs->reg
+
+#define CTX \
+       optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+
+/**
+ * optc301_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
+ *
+ * @optc: timing_generator instance.
+ * @params: parameters used for Dynamic Refresh Rate.
+ */
+void optc301_set_drr(
+       struct timing_generator *optc,
+       const struct drr_params *params)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       if (params != NULL &&
+               params->vertical_total_max > 0 &&
+               params->vertical_total_min > 0) {
+
+               if (params->vertical_total_mid != 0) {
+
+                       REG_SET(OTG_V_TOTAL_MID, 0,
+                               OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
+
+                       REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
+                                       OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
+                                       OTG_VTOTAL_MID_FRAME_NUM,
+                                       (uint8_t)params->vertical_total_mid_frame_num);
+
+               }
+
+               optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
+
+               REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
+                               OTG_V_TOTAL_MIN_SEL, 1,
+                               OTG_V_TOTAL_MAX_SEL, 1,
+                               OTG_FORCE_LOCK_ON_EVENT, 0,
+                               OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0);
+               // Setup manual flow control for EOF via TRIG_A
+               optc->funcs->setup_manual_trigger(optc);
+
+       } else {
+               REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0,
+                               OTG_V_TOTAL_MIN_SEL, 0,
+                               OTG_V_TOTAL_MAX_SEL, 0,
+                               OTG_FORCE_LOCK_ON_EVENT, 0);
+
+               optc->funcs->set_vtotal_min_max(optc, 0, 0);
+       }
+}
+
+
+void optc301_setup_manual_trigger(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_SET_8(OTG_TRIGA_CNTL, 0,
+                       OTG_TRIGA_SOURCE_SELECT, 21,
+                       OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
+                       OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
+                       OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
+                       OTG_TRIGA_POLARITY_SELECT, 0,
+                       OTG_TRIGA_FREQUENCY_SELECT, 0,
+                       OTG_TRIGA_DELAY, 0,
+                       OTG_TRIGA_CLEAR, 1);
+}
+
+static struct timing_generator_funcs dcn30_tg_funcs = {
+               .validate_timing = optc1_validate_timing,
+               .program_timing = optc1_program_timing,
+               .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+               .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+               .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+               .program_global_sync = optc1_program_global_sync,
+               .enable_crtc = optc2_enable_crtc,
+               .disable_crtc = optc1_disable_crtc,
+               /* used by enable_timing_synchronization. Not need for FPGA */
+               .is_counter_moving = optc1_is_counter_moving,
+               .get_position = optc1_get_position,
+               .get_frame_count = optc1_get_vblank_counter,
+               .get_scanoutpos = optc1_get_crtc_scanoutpos,
+               .get_otg_active_size = optc1_get_otg_active_size,
+               .set_early_control = optc1_set_early_control,
+               /* used by enable_timing_synchronization. Not need for FPGA */
+               .wait_for_state = optc1_wait_for_state,
+               .set_blank_color = optc3_program_blank_color,
+               .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+               .triplebuffer_lock = optc3_triplebuffer_lock,
+               .triplebuffer_unlock = optc2_triplebuffer_unlock,
+               .enable_reset_trigger = optc1_enable_reset_trigger,
+               .enable_crtc_reset = optc1_enable_crtc_reset,
+               .disable_reset_trigger = optc1_disable_reset_trigger,
+               .lock = optc3_lock,
+               .unlock = optc1_unlock,
+               .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
+               .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+               .enable_optc_clock = optc1_enable_optc_clock,
+               .set_drr = optc301_set_drr,
+               .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+               .set_vtotal_min_max = optc3_set_vtotal_min_max,
+               .set_static_screen_control = optc1_set_static_screen_control,
+               .program_stereo = optc1_program_stereo,
+               .is_stereo_left_eye = optc1_is_stereo_left_eye,
+               .tg_init = optc3_tg_init,
+               .is_tg_enabled = optc1_is_tg_enabled,
+               .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
+               .clear_optc_underflow = optc1_clear_optc_underflow,
+               .setup_global_swap_lock = NULL,
+               .get_crc = optc1_get_crc,
+               .configure_crc = optc2_configure_crc,
+               .set_dsc_config = optc3_set_dsc_config,
+               .get_dsc_status = optc2_get_dsc_status,
+               .set_dwb_source = NULL,
+               .set_odm_bypass = optc3_set_odm_bypass,
+               .set_odm_combine = optc3_set_odm_combine,
+               .get_optc_source = optc2_get_optc_source,
+               .set_out_mux = optc3_set_out_mux,
+               .set_drr_trigger_window = optc3_set_drr_trigger_window,
+               .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+               .set_gsl = optc2_set_gsl,
+               .set_gsl_source_select = optc2_set_gsl_source_select,
+               .set_vtg_params = optc1_set_vtg_params,
+               .program_manual_trigger = optc2_program_manual_trigger,
+               .setup_manual_trigger = optc301_setup_manual_trigger,
+               .get_hw_timing = optc1_get_hw_timing,
+               .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
+};
+
+void dcn301_timing_generator_init(struct optc *optc1)
+{
+       optc1->base.funcs = &dcn30_tg_funcs;
+
+       optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+       optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+       optc1->min_h_blank = 32;
+       optc1->min_v_blank = 3;
+       optc1->min_v_blank_interlace = 5;
+       optc1->min_h_sync_width = 4;
+       optc1->min_v_sync_width = 1;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h
new file mode 100644 (file)
index 0000000..b495856
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_OPTC_DCN301_H__
+#define __DC_OPTC_DCN301_H__
+
+#include "dcn20/dcn20_optc.h"
+#include "dcn30/dcn30_optc.h"
+
+void dcn301_timing_generator_init(struct optc *optc1);
+void optc301_setup_manual_trigger(struct timing_generator *optc);
+void optc301_set_drr(struct timing_generator *optc, const struct drr_params *params);
+
+#endif /* __DC_OPTC_DCN301_H__ */
index 3485fbb..1bee9a4 100644 (file)
@@ -42,7 +42,7 @@
 #include "dcn30/dcn30_hubp.h"
 #include "irq/dcn30/irq_service_dcn30.h"
 #include "dcn30/dcn30_dpp.h"
-#include "dcn30/dcn30_optc.h"
+#include "dcn301/dcn301_optc.h"
 #include "dcn20/dcn20_hwseq.h"
 #include "dcn30/dcn30_hwseq.h"
 #include "dce110/dce110_hw_sequencer.h"
@@ -855,7 +855,7 @@ static struct timing_generator *dcn301_timing_generator_create(
        tgn10->tg_shift = &optc_shift;
        tgn10->tg_mask = &optc_mask;
 
-       dcn30_timing_generator_init(tgn10);
+       dcn301_timing_generator_init(tgn10);
 
        return &tgn10->base;
 }
index 45956ef..131b8b8 100644 (file)
@@ -65,7 +65,7 @@ static const struct dc_debug_options debug_defaults_drv = {
                .timing_trace = false,
                .clock_trace = true,
                .disable_pplib_clock_request = true,
-               .pipe_split_policy = MPC_SPLIT_DYNAMIC,
+               .pipe_split_policy = MPC_SPLIT_AVOID,
                .force_single_disp_pipe_split = false,
                .disable_dcc = DCC_ENABLE,
                .vsr_support = true,
index 65c1d75..01cc679 100644 (file)
@@ -84,7 +84,8 @@ static enum phyd32clk_clock_source get_phy_mux_symclk(
                struct dcn_dccg *dccg_dcn,
                enum phyd32clk_clock_source src)
 {
-       if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
+       if (dccg_dcn->base.ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
+                       dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
                if (src == PHYD32CLKC)
                        src = PHYD32CLKF;
                if (src == PHYD32CLKD)
index 11e28e0..61ceff6 100644 (file)
@@ -49,7 +49,10 @@ static void dccg32_trigger_dio_fifo_resync(
        uint32_t dispclk_rdivider_value = 0;
 
        REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
-       REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
+
+       /* Not valid for the WDIVIDER to be set to 0 */
+       if (dispclk_rdivider_value != 0)
+               REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
 }
 
 static void dccg32_get_pixel_rate_div(
index d9e049e..ed8ddb7 100644 (file)
@@ -295,7 +295,11 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
                pipe = &res_ctx->pipe_ctx[i];
                timing = &pipe->stream->timing;
 
-               pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+               if (pipe->stream->adjust.v_total_min != 0)
+                       pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+               else
+                       pipes[pipe_cnt].pipe.dest.vtotal = timing->v_total;
+
                pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive;
                pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, dcn3_14_ip.VBlankNomDefaultUS);
                pipes[pipe_cnt].pipe.dest.vblank_nom = max(pipes[pipe_cnt].pipe.dest.vblank_nom, timing->v_sync_width);
index 6841a4b..1cb4022 100644 (file)
@@ -1798,17 +1798,6 @@ static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
        return result;
 }
 
-static bool intel_core_rkl_chk(void)
-{
-#if IS_ENABLED(CONFIG_X86_64)
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       return (c->x86 == 6 && c->x86_model == INTEL_FAM6_ROCKETLAKE);
-#else
-       return false;
-#endif
-}
-
 static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 {
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -1835,7 +1824,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
        data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
        data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
        data->pcie_dpm_key_disabled =
-               intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
+               !amdgpu_device_pcie_dynamic_switching_supported() ||
+               !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
        /* need to set voltage control types before EVV patching */
        data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE;
        data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE;
index f6599c0..0cda3b2 100644 (file)
@@ -1927,12 +1927,16 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
                *size = 4;
                break;
        case AMDGPU_PP_SENSOR_GFX_MCLK:
-               ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
+               ret = sienna_cichlid_get_smu_metrics_data(smu,
+                                                         METRICS_CURR_UCLK,
+                                                         (uint32_t *)data);
                *(uint32_t *)data *= 100;
                *size = 4;
                break;
        case AMDGPU_PP_SENSOR_GFX_SCLK:
-               ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
+               ret = sienna_cichlid_get_smu_metrics_data(smu,
+                                                         METRICS_AVERAGE_GFXCLK,
+                                                         (uint32_t *)data);
                *(uint32_t *)data *= 100;
                *size = 4;
                break;
index b9bde5f..3d18861 100644 (file)
@@ -1734,7 +1734,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
        gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
        gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
 
-       gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+       gpu_metrics->current_gfxclk = gpu_metrics->average_gfxclk_frequency;
        gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
        gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
        gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
index 3ba0213..b1f0937 100644 (file)
@@ -949,7 +949,7 @@ static int smu_v13_0_7_read_sensor(struct smu_context *smu,
                break;
        case AMDGPU_PP_SENSOR_GFX_MCLK:
                ret = smu_v13_0_7_get_smu_metrics_data(smu,
-                                                      METRICS_AVERAGE_UCLK,
+                                                      METRICS_CURR_UCLK,
                                                       (uint32_t *)data);
                *(uint32_t *)data *= 100;
                *size = 4;
index 2c45456..c277b19 100644 (file)
@@ -140,6 +140,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
        if (!state->planes)
                goto fail;
 
+       /*
+        * Because drm_atomic_state can be committed asynchronously we need our
+        * own reference and cannot rely on the on implied by drm_file in the
+        * ioctl call.
+        */
+       drm_dev_get(dev);
        state->dev = dev;
 
        drm_dbg_atomic(dev, "Allocated atomic state %p\n", state);
@@ -299,7 +305,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
 void __drm_atomic_state_free(struct kref *ref)
 {
        struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
-       struct drm_mode_config *config = &state->dev->mode_config;
+       struct drm_device *dev = state->dev;
+       struct drm_mode_config *config = &dev->mode_config;
 
        drm_atomic_state_clear(state);
 
@@ -311,6 +318,8 @@ void __drm_atomic_state_free(struct kref *ref)
                drm_atomic_state_default_release(state);
                kfree(state);
        }
+
+       drm_dev_put(dev);
 }
 EXPORT_SYMBOL(__drm_atomic_state_free);
 
index 1b12a3c..871e4e2 100644 (file)
@@ -311,6 +311,9 @@ static bool drm_client_target_cloned(struct drm_device *dev,
        can_clone = true;
        dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
 
+       if (!dmt_mode)
+               goto fail;
+
        for (i = 0; i < connector_count; i++) {
                if (!enabled[i])
                        continue;
@@ -326,11 +329,13 @@ static bool drm_client_target_cloned(struct drm_device *dev,
                if (!modes[i])
                        can_clone = false;
        }
+       kfree(dmt_mode);
 
        if (can_clone) {
                DRM_DEBUG_KMS("can clone using 1024x768\n");
                return true;
        }
+fail:
        DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
        return false;
 }
@@ -862,6 +867,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
                                break;
                        }
 
+                       kfree(modeset->mode);
                        modeset->mode = drm_mode_duplicate(dev, mode);
                        drm_connector_get(connector);
                        modeset->connectors[modeset->num_connectors++] = connector;
index 789dce9..dcbda9b 100644 (file)
@@ -23,6 +23,11 @@ subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable)
 subdir-ccflags-y += $(call cc-disable-warning, frame-address)
 subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
 
+# Fine grained warnings disable
+CFLAGS_i915_pci.o = $(call cc-disable-warning, override-init)
+CFLAGS_display/intel_display_device.o = $(call cc-disable-warning, override-init)
+CFLAGS_display/intel_fbdev.o = $(call cc-disable-warning, override-init)
+
 subdir-ccflags-y += -I$(srctree)/$(src)
 
 # Please keep these build lists sorted!
index 3fd30e7..f0ee9bc 100644 (file)
@@ -16,9 +16,6 @@
 #include "intel_display_reg_defs.h"
 #include "intel_fbc.h"
 
-__diag_push();
-__diag_ignore_all("-Woverride-init", "Allow overriding inherited members");
-
 static const struct intel_display_device_info no_display = {};
 
 #define PIPE_A_OFFSET          0x70000
@@ -665,8 +662,6 @@ static const struct intel_display_device_info xe_lpdp_display = {
                BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
 };
 
-__diag_pop();
-
 #undef INTEL_VGA_DEVICE
 #undef INTEL_QUANTA_VGA_DEVICE
 #define INTEL_VGA_DEVICE(id, info) { id, info }
index 7c5fddb..fbfd8f9 100644 (file)
@@ -166,6 +166,8 @@ struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
                i915_vma_get(vma);
        }
 
+       dpt->obj->mm.dirty = true;
+
        atomic_dec(&i915->gpu_error.pending_fb_pin);
        intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 
@@ -261,7 +263,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
                dpt_obj = i915_gem_object_create_stolen(i915, size);
        if (IS_ERR(dpt_obj) && !HAS_LMEM(i915)) {
                drm_dbg_kms(&i915->drm, "Allocating dpt from smem\n");
-               dpt_obj = i915_gem_object_create_internal(i915, size);
+               dpt_obj = i915_gem_object_create_shmem(i915, size);
        }
        if (IS_ERR(dpt_obj))
                return ERR_CAST(dpt_obj);
index 1cc0ddc..80c3f88 100644 (file)
@@ -135,9 +135,6 @@ static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
        return i915_gem_fb_mmap(obj, vma);
 }
 
-__diag_push();
-__diag_ignore_all("-Woverride-init", "Allow overriding the default ops");
-
 static const struct fb_ops intelfb_ops = {
        .owner = THIS_MODULE,
        __FB_DEFAULT_DEFERRED_OPS_RDWR(intel_fbdev),
@@ -149,8 +146,6 @@ static const struct fb_ops intelfb_ops = {
        .fb_mmap = intel_fbdev_mmap,
 };
 
-__diag_pop();
-
 static int intelfb_alloc(struct drm_fb_helper *helper,
                         struct drm_fb_helper_surface_size *sizes)
 {
index df6c9a8..6b9f6cf 100644 (file)
@@ -1246,8 +1246,10 @@ static int igt_write_huge(struct drm_i915_private *i915,
         * times in succession a possibility by enlarging the permutation array.
         */
        order = i915_random_order(count * count, &prng);
-       if (!order)
-               return -ENOMEM;
+       if (!order) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        max_page_size = rounddown_pow_of_two(obj->mm.page_sizes.sg);
        max = div_u64(max - size, max_page_size);
index 3d7a5db..928975d 100644 (file)
@@ -38,9 +38,6 @@
 #include "i915_reg.h"
 #include "intel_pci_config.h"
 
-__diag_push();
-__diag_ignore_all("-Woverride-init", "Allow overriding inherited members");
-
 #define PLATFORM(x) .platform = (x)
 #define GEN(x) \
        .__runtime.graphics.ip.ver = (x), \
@@ -846,8 +843,6 @@ static const struct intel_device_info mtl_info = {
 
 #undef PLATFORM
 
-__diag_pop();
-
 /*
  * Make sure any device matches here are from most specific to most
  * general.  For example, since the Quanta match is based on the subsystem
index 7413c11..49c6f1f 100644 (file)
@@ -4431,6 +4431,7 @@ static const struct i915_range mtl_oam_b_counters[] = {
 static const struct i915_range xehp_oa_b_counters[] = {
        { .start = 0xdc48, .end = 0xdc48 },     /* OAA_ENABLE_REG */
        { .start = 0xdd00, .end = 0xdd48 },     /* OAG_LCE0_0 - OAA_LENABLE_REG */
+       {}
 };
 
 static const struct i915_range gen7_oa_mux_regs[] = {
index a99310b..bbb1bf3 100644 (file)
@@ -89,7 +89,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
                         * since we've already mapped it once in
                         * submit_reloc()
                         */
-                       if (WARN_ON(!ptr))
+                       if (WARN_ON(IS_ERR_OR_NULL(ptr)))
                                return;
 
                        for (i = 0; i < dwords; i++) {
index 790f55e..e788ed7 100644 (file)
@@ -206,7 +206,7 @@ static const struct a6xx_shader_block {
        SHADER(A6XX_SP_LB_3_DATA, 0x800),
        SHADER(A6XX_SP_LB_4_DATA, 0x800),
        SHADER(A6XX_SP_LB_5_DATA, 0x200),
-       SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x2000),
+       SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800),
        SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280),
        SHADER(A6XX_SP_UAV_DATA, 0x80),
        SHADER(A6XX_SP_INST_TAG, 0x80),
index cb94cfd..ce8d0b2 100644 (file)
@@ -369,8 +369,6 @@ static const struct adreno_info gpulist[] = {
                .hwcg = a640_hwcg,
        }, {
                .rev = ADRENO_REV(6, 9, 0, ANY_ID),
-               .revn = 690,
-               .name = "A690",
                .fw = {
                        [ADRENO_FW_SQE] = "a660_sqe.fw",
                        [ADRENO_FW_GMU] = "a690_gmu.bin",
index d8c9e8c..8450198 100644 (file)
@@ -149,7 +149,8 @@ bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2);
 
 static inline bool adreno_is_revn(const struct adreno_gpu *gpu, uint32_t revn)
 {
-       WARN_ON_ONCE(!gpu->revn);
+       /* revn can be zero, but if not is set at same time as info */
+       WARN_ON_ONCE(!gpu->info);
 
        return gpu->revn == revn;
 }
@@ -161,14 +162,16 @@ static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu)
 
 static inline bool adreno_is_a2xx(const struct adreno_gpu *gpu)
 {
-       WARN_ON_ONCE(!gpu->revn);
+       /* revn can be zero, but if not is set at same time as info */
+       WARN_ON_ONCE(!gpu->info);
 
        return (gpu->revn < 300);
 }
 
 static inline bool adreno_is_a20x(const struct adreno_gpu *gpu)
 {
-       WARN_ON_ONCE(!gpu->revn);
+       /* revn can be zero, but if not is set at same time as info */
+       WARN_ON_ONCE(!gpu->info);
 
        return (gpu->revn < 210);
 }
@@ -307,7 +310,8 @@ static inline int adreno_is_a680(const struct adreno_gpu *gpu)
 
 static inline int adreno_is_a690(const struct adreno_gpu *gpu)
 {
-       return adreno_is_revn(gpu, 690);
+       /* The order of args is important here to handle ANY_ID correctly */
+       return adreno_cmp_rev(ADRENO_REV(6, 9, 0, ANY_ID), gpu->rev);
 };
 
 /* check for a615, a616, a618, a619 or any derivatives */
index e379599..29bb8ee 100644 (file)
 #define        DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE      412500000
 
 /**
- * enum dpu_core_perf_data_bus_id - data bus identifier
- * @DPU_CORE_PERF_DATA_BUS_ID_MNOC: DPU/MNOC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_LLCC: MNOC/LLCC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_EBI: LLCC/EBI data bus
- */
-enum dpu_core_perf_data_bus_id {
-       DPU_CORE_PERF_DATA_BUS_ID_MNOC,
-       DPU_CORE_PERF_DATA_BUS_ID_LLCC,
-       DPU_CORE_PERF_DATA_BUS_ID_EBI,
-       DPU_CORE_PERF_DATA_BUS_ID_MAX,
-};
-
-/**
  * struct dpu_core_perf_params - definition of performance parameters
  * @max_per_pipe_ib: maximum instantaneous bandwidth request
  * @bw_ctl: arbitrated bandwidth request
index c278fb9..86182c7 100644 (file)
@@ -51,7 +51,7 @@
 
 static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
        CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
-       1, 2, 3, CTL_INVALID_BIT, CTL_INVALID_BIT};
+       1, 2, 3, 4, 5};
 
 static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,
                enum dpu_lm lm)
@@ -198,6 +198,12 @@ static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,
        case SSPP_DMA3:
                ctx->pending_flush_mask |= BIT(25);
                break;
+       case SSPP_DMA4:
+               ctx->pending_flush_mask |= BIT(13);
+               break;
+       case SSPP_DMA5:
+               ctx->pending_flush_mask |= BIT(14);
+               break;
        case SSPP_CURSOR0:
                ctx->pending_flush_mask |= BIT(22);
                break;
index 3ce45b0..31deda1 100644 (file)
@@ -1087,8 +1087,6 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = {
 
 const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs = {
        .has_phy_lane = true,
-       .regulator_data = dsi_phy_14nm_17mA_regulators,
-       .num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators),
        .ops = {
                .enable = dsi_14nm_phy_enable,
                .disable = dsi_14nm_phy_disable,
index 96599ec..1a5d4f1 100644 (file)
@@ -191,6 +191,12 @@ msm_fence_init(struct dma_fence *fence, struct msm_fence_context *fctx)
 
        f->fctx = fctx;
 
+       /*
+        * Until this point, the fence was just some pre-allocated memory,
+        * no-one should have taken a reference to it yet.
+        */
+       WARN_ON(kref_read(&fence->refcount));
+
        dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
                       fctx->context, ++fctx->last_fence);
 }
index 3f1aa4d..63c9641 100644 (file)
@@ -86,7 +86,19 @@ void __msm_gem_submit_destroy(struct kref *kref)
        }
 
        dma_fence_put(submit->user_fence);
-       dma_fence_put(submit->hw_fence);
+
+       /*
+        * If the submit is freed before msm_job_run(), then hw_fence is
+        * just some pre-allocated memory, not a reference counted fence.
+        * Once the job runs and the hw_fence is initialized, it will
+        * have a refcount of at least one, since the submit holds a ref
+        * to the hw_fence.
+        */
+       if (kref_read(&submit->hw_fence->refcount) == 0) {
+               kfree(submit->hw_fence);
+       } else {
+               dma_fence_put(submit->hw_fence);
+       }
 
        put_pid(submit->pid);
        msm_submitqueue_put(submit->queue);
@@ -889,7 +901,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
         * after the job is armed
         */
        if ((args->flags & MSM_SUBMIT_FENCE_SN_IN) &&
-                       idr_find(&queue->fence_idr, args->fence)) {
+                       (!args->fence || idr_find(&queue->fence_idr, args->fence))) {
                spin_unlock(&queue->idr_lock);
                idr_preload_end();
                ret = -EINVAL;
index 05648c9..798bd4f 100644 (file)
@@ -189,6 +189,7 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
 #define UBWC_2_0 0x20000000
 #define UBWC_3_0 0x30000000
 #define UBWC_4_0 0x40000000
+#define UBWC_4_3 0x40030000
 
 static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
 {
@@ -227,7 +228,10 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
                writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2);
                writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE);
        } else {
-               writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
+               if (data->ubwc_dec_version == UBWC_4_3)
+                       writel_relaxed(3, msm_mdss->mmio + UBWC_CTRL_2);
+               else
+                       writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
                writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
        }
 }
@@ -271,6 +275,7 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
                msm_mdss_setup_ubwc_dec_30(msm_mdss);
                break;
        case UBWC_4_0:
+       case UBWC_4_3:
                msm_mdss_setup_ubwc_dec_40(msm_mdss);
                break;
        default:
@@ -569,6 +574,16 @@ static const struct msm_mdss_data sm8250_data = {
        .macrotile_mode = 1,
 };
 
+static const struct msm_mdss_data sm8550_data = {
+       .ubwc_version = UBWC_4_0,
+       .ubwc_dec_version = UBWC_4_3,
+       .ubwc_swizzle = 6,
+       .ubwc_static = 1,
+       /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+       .highest_bank_bit = 3,
+       .macrotile_mode = 1,
+};
+
 static const struct of_device_id mdss_dt_match[] = {
        { .compatible = "qcom,mdss" },
        { .compatible = "qcom,msm8998-mdss" },
@@ -585,7 +600,7 @@ static const struct of_device_id mdss_dt_match[] = {
        { .compatible = "qcom,sm8250-mdss", .data = &sm8250_data },
        { .compatible = "qcom,sm8350-mdss", .data = &sm8250_data },
        { .compatible = "qcom,sm8450-mdss", .data = &sm8250_data },
-       { .compatible = "qcom,sm8550-mdss", .data = &sm8250_data },
+       { .compatible = "qcom,sm8550-mdss", .data = &sm8550_data },
        {}
 };
 MODULE_DEVICE_TABLE(of, mdss_dt_match);
index 38d3fad..1bec819 100644 (file)
@@ -1877,6 +1877,8 @@ nv50_pior_destroy(struct drm_encoder *encoder)
        nvif_outp_dtor(&nv_encoder->outp);
 
        drm_encoder_cleanup(encoder);
+
+       mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
        kfree(encoder);
 }
 
@@ -1921,6 +1923,8 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
        nv_encoder->i2c = ddc;
        nv_encoder->aux = aux;
 
+       mutex_init(&nv_encoder->dp.hpd_irq_lock);
+
        encoder = to_drm_encoder(nv_encoder);
        encoder->possible_crtcs = dcbe->heads;
        encoder->possible_clones = 0;
index 40a1065..ef441df 100644 (file)
@@ -16,7 +16,7 @@ struct nvkm_i2c_bus {
        const struct nvkm_i2c_bus_func *func;
        struct nvkm_i2c_pad *pad;
 #define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */                           (n)
-#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
+#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */  ((n) + 0x10)
 #define NVKM_I2C_BUS_PRI /* ccb primary comm. port */                        -1
 #define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */                      -2
        int id;
@@ -38,7 +38,7 @@ struct nvkm_i2c_aux {
        const struct nvkm_i2c_aux_func *func;
        struct nvkm_i2c_pad *pad;
 #define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */                           (n)
-#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
+#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */  ((n) + 0x10)
        int id;
 
        struct mutex mutex;
index dad942b..46b057f 100644 (file)
@@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
                return -ENOSYS;
 
        list_for_each_entry(outp, &conn->disp->outps, head) {
-               if (outp->info.connector == conn->index && outp->dp.aux) {
-                       if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_I2C_PLUG;
-                       if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
-                       if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ   ) bits |= NVKM_I2C_IRQ;
+               if (outp->info.connector == conn->index)
+                       break;
+       }
 
-                       return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
-                                              nvkm_uconn_uevent_aux);
-               }
+       if (&outp->head == &conn->disp->outps)
+               return -EINVAL;
+
+       if (outp->dp.aux && !outp->info.location) {
+               if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_I2C_PLUG;
+               if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
+               if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ   ) bits |= NVKM_I2C_IRQ;
+
+               return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
+                                      nvkm_uconn_uevent_aux);
        }
 
        if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_GPIO_HI;
        if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO;
-       if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ)
-               return -EINVAL;
+       if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) {
+               /* TODO: support DP IRQ on ANX9805 and remove this hack. */
+               if (!outp->info.location)
+                       return -EINVAL;
+       }
 
        return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits,
                               nvkm_uconn_uevent_gpio);
index 976539d..731b2f6 100644 (file)
@@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
 {
        struct nvkm_bios *bios = device->bios;
        struct nvkm_i2c *i2c;
+       struct nvkm_i2c_aux *aux;
        struct dcb_i2c_entry ccbE;
        struct dcb_output dcbE;
        u8 ver, hdr;
-       int ret, i;
+       int ret, i, ids;
 
        if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
                return -ENOMEM;
@@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
                }
        }
 
-       return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event);
+       ids = 0;
+       list_for_each_entry(aux, &i2c->aux, head)
+               ids = max(ids, aux->id + 1);
+       if (!ids)
+               return 0;
+
+       return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event);
 }
index b930036..256c2d4 100644 (file)
@@ -199,43 +199,6 @@ static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
        return __intel_idle(dev, drv, index);
 }
 
-static __always_inline int __intel_idle_hlt(struct cpuidle_device *dev,
-                                       struct cpuidle_driver *drv, int index)
-{
-       raw_safe_halt();
-       raw_local_irq_disable();
-       return index;
-}
-
-/**
- * intel_idle_hlt - Ask the processor to enter the given idle state using hlt.
- * @dev: cpuidle device of the target CPU.
- * @drv: cpuidle driver (assumed to point to intel_idle_driver).
- * @index: Target idle state index.
- *
- * Use the HLT instruction to notify the processor that the CPU represented by
- * @dev is idle and it can try to enter the idle state corresponding to @index.
- *
- * Must be called under local_irq_disable().
- */
-static __cpuidle int intel_idle_hlt(struct cpuidle_device *dev,
-                               struct cpuidle_driver *drv, int index)
-{
-       return __intel_idle_hlt(dev, drv, index);
-}
-
-static __cpuidle int intel_idle_hlt_irq_on(struct cpuidle_device *dev,
-                                   struct cpuidle_driver *drv, int index)
-{
-       int ret;
-
-       raw_local_irq_enable();
-       ret = __intel_idle_hlt(dev, drv, index);
-       raw_local_irq_disable();
-
-       return ret;
-}
-
 /**
  * intel_idle_s2idle - Ask the processor to enter the given idle state.
  * @dev: cpuidle device of the target CPU.
@@ -1279,25 +1242,6 @@ static struct cpuidle_state snr_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state vmguest_cstates[] __initdata = {
-       {
-               .name = "C1",
-               .desc = "HLT",
-               .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
-               .exit_latency = 5,
-               .target_residency = 10,
-               .enter = &intel_idle_hlt, },
-       {
-               .name = "C1L",
-               .desc = "Long HLT",
-               .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TLB_FLUSHED,
-               .exit_latency = 5,
-               .target_residency = 200,
-               .enter = &intel_idle_hlt, },
-       {
-               .enter = NULL }
-};
-
 static const struct idle_cpu idle_cpu_nehalem __initconst = {
        .state_table = nehalem_cstates,
        .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
@@ -1897,16 +1841,6 @@ static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
 
 static void state_update_enter_method(struct cpuidle_state *state, int cstate)
 {
-       if (state->enter == intel_idle_hlt) {
-               if (force_irq_on) {
-                       pr_info("forced intel_idle_irq for state %d\n", cstate);
-                       state->enter = intel_idle_hlt_irq_on;
-               }
-               return;
-       }
-       if (state->enter == intel_idle_hlt_irq_on)
-               return; /* no update scenarios */
-
        if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
                /*
                 * Combining with XSTATE with IBRS or IRQ_ENABLE flags
@@ -1940,21 +1874,6 @@ static void state_update_enter_method(struct cpuidle_state *state, int cstate)
        }
 }
 
-/*
- * For mwait based states, we want to verify the cpuid data to see if the state
- * is actually supported by this specific CPU.
- * For non-mwait based states, this check should be skipped.
- */
-static bool should_verify_mwait(struct cpuidle_state *state)
-{
-       if (state->enter == intel_idle_hlt)
-               return false;
-       if (state->enter == intel_idle_hlt_irq_on)
-               return false;
-
-       return true;
-}
-
 static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
 {
        int cstate;
@@ -2003,7 +1922,7 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
                }
 
                mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
-               if (should_verify_mwait(&cpuidle_state_table[cstate]) && !intel_idle_verify_cstate(mwait_hint))
+               if (!intel_idle_verify_cstate(mwait_hint))
                        continue;
 
                /* Structure copy. */
@@ -2137,93 +2056,6 @@ static void __init intel_idle_cpuidle_devices_uninit(void)
                cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
 }
 
-/*
- * Match up the latency and break even point of the bare metal (cpu based)
- * states with the deepest VM available state.
- *
- * We only want to do this for the deepest state, the ones that has
- * the TLB_FLUSHED flag set on the .
- *
- * All our short idle states are dominated by vmexit/vmenter latencies,
- * not the underlying hardware latencies so we keep our values for these.
- */
-static void __init matchup_vm_state_with_baremetal(void)
-{
-       int cstate;
-
-       for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
-               int matching_cstate;
-
-               if (intel_idle_max_cstate_reached(cstate))
-                       break;
-
-               if (!cpuidle_state_table[cstate].enter)
-                       break;
-
-               if (!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_TLB_FLUSHED))
-                       continue;
-
-               for (matching_cstate = 0; matching_cstate < CPUIDLE_STATE_MAX; ++matching_cstate) {
-                       if (!icpu->state_table[matching_cstate].enter)
-                               break;
-                       if (icpu->state_table[matching_cstate].exit_latency > cpuidle_state_table[cstate].exit_latency) {
-                               cpuidle_state_table[cstate].exit_latency = icpu->state_table[matching_cstate].exit_latency;
-                               cpuidle_state_table[cstate].target_residency = icpu->state_table[matching_cstate].target_residency;
-                       }
-               }
-
-       }
-}
-
-
-static int __init intel_idle_vminit(const struct x86_cpu_id *id)
-{
-       int retval;
-
-       cpuidle_state_table = vmguest_cstates;
-
-       icpu = (const struct idle_cpu *)id->driver_data;
-
-       pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
-                boot_cpu_data.x86_model);
-
-       intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
-       if (!intel_idle_cpuidle_devices)
-               return -ENOMEM;
-
-       /*
-        * We don't know exactly what the host will do when we go idle, but as a worst estimate
-        * we can assume that the exit latency of the deepest host state will be hit for our
-        * deep (long duration) guest idle state.
-        * The same logic applies to the break even point for the long duration guest idle state.
-        * So lets copy these two properties from the table we found for the host CPU type.
-        */
-       matchup_vm_state_with_baremetal();
-
-       intel_idle_cpuidle_driver_init(&intel_idle_driver);
-
-       retval = cpuidle_register_driver(&intel_idle_driver);
-       if (retval) {
-               struct cpuidle_driver *drv = cpuidle_get_driver();
-               printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
-                      drv ? drv->name : "none");
-               goto init_driver_fail;
-       }
-
-       retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
-                                  intel_idle_cpu_online, NULL);
-       if (retval < 0)
-               goto hp_setup_fail;
-
-       return 0;
-hp_setup_fail:
-       intel_idle_cpuidle_devices_uninit();
-       cpuidle_unregister_driver(&intel_idle_driver);
-init_driver_fail:
-       free_percpu(intel_idle_cpuidle_devices);
-       return retval;
-}
-
 static int __init intel_idle_init(void)
 {
        const struct x86_cpu_id *id;
@@ -2242,8 +2074,6 @@ static int __init intel_idle_init(void)
        id = x86_match_cpu(intel_idle_ids);
        if (id) {
                if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
-                       if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
-                               return intel_idle_vminit(id);
                        pr_debug("Please enable MWAIT in BIOS SETUP\n");
                        return -ENODEV;
                }
index 04b13cd..ba67587 100644 (file)
@@ -809,8 +809,11 @@ static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
 
        mutex_lock(&pulse8->lock);
        cmd = MSGCODE_PING;
-       pulse8_send_and_wait(pulse8, &cmd, 1,
-                            MSGCODE_COMMAND_ACCEPTED, 0);
+       if (pulse8_send_and_wait(pulse8, &cmd, 1,
+                                MSGCODE_COMMAND_ACCEPTED, 0)) {
+               dev_warn(pulse8->dev, "failed to ping EEPROM\n");
+               goto unlock;
+       }
 
        if (pulse8->vers < 2)
                goto unlock;
index e9b2d90..3f7e147 100644 (file)
@@ -813,8 +813,8 @@ static unsigned long tc358746_find_pll_settings(struct tc358746 *tc358746,
        u32 min_delta = 0xffffffff;
        u16 prediv_max = 17;
        u16 prediv_min = 1;
-       u16 m_best, mul;
-       u16 p_best, p;
+       u16 m_best = 0, mul;
+       u16 p_best = 1, p;
        u8 postdiv;
 
        if (fout > 1000 * HZ_PER_MHZ) {
index 8fd5b6e..7551ca4 100644 (file)
@@ -2459,16 +2459,10 @@ static int dvb_register(struct cx23885_tsport *port)
                        request_module("%s", info.type);
                        client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
                        if (!i2c_client_has_driver(client_tuner)) {
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        if (!try_module_get(client_tuner->dev.driver->owner)) {
                                i2c_unregister_device(client_tuner);
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        port->i2c_client_tuner = client_tuner;
@@ -2505,16 +2499,10 @@ static int dvb_register(struct cx23885_tsport *port)
                        request_module("%s", info.type);
                        client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
                        if (!i2c_client_has_driver(client_tuner)) {
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        if (!try_module_get(client_tuner->dev.driver->owner)) {
                                i2c_unregister_device(client_tuner);
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        port->i2c_client_tuner = client_tuner;
index 43d85a5..7863b7b 100644 (file)
@@ -826,7 +826,7 @@ static const struct dev_pm_ops vpu_core_pm_ops = {
 
 static struct vpu_core_resources imx8q_enc = {
        .type = VPU_CORE_TYPE_ENC,
-       .fwname = "vpu/vpu_fw_imx8_enc.bin",
+       .fwname = "amphion/vpu/vpu_fw_imx8_enc.bin",
        .stride = 16,
        .max_width = 1920,
        .max_height = 1920,
@@ -841,7 +841,7 @@ static struct vpu_core_resources imx8q_enc = {
 
 static struct vpu_core_resources imx8q_dec = {
        .type = VPU_CORE_TYPE_DEC,
-       .fwname = "vpu/vpu_fw_imx8_dec.bin",
+       .fwname = "amphion/vpu/vpu_fw_imx8_dec.bin",
        .stride = 256,
        .max_width = 8188,
        .max_height = 8188,
index bf759eb..b6d5b48 100644 (file)
@@ -46,11 +46,10 @@ static int vpu_mbox_request_channel(struct device *dev, struct vpu_mbox *mbox)
        cl->rx_callback = vpu_mbox_rx_callback;
 
        ch = mbox_request_channel_byname(cl, mbox->name);
-       if (IS_ERR(ch)) {
-               dev_err(dev, "Failed to request mbox chan %s, ret : %ld\n",
-                       mbox->name, PTR_ERR(ch));
-               return PTR_ERR(ch);
-       }
+       if (IS_ERR(ch))
+               return dev_err_probe(dev, PTR_ERR(ch),
+                                    "Failed to request mbox chan %s\n",
+                                    mbox->name);
 
        mbox->ch = ch;
        return 0;
index 4768156..40cb3cb 100644 (file)
@@ -28,7 +28,6 @@
 #include "mtk_jpeg_core.h"
 #include "mtk_jpeg_dec_parse.h"
 
-#if defined(CONFIG_OF)
 static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = {
        {
                .fourcc         = V4L2_PIX_FMT_JPEG,
@@ -102,7 +101,6 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
                .flags          = MTK_JPEG_FMT_FLAG_CAPTURE,
        },
 };
-#endif
 
 #define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats)
 #define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
@@ -1455,7 +1453,6 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = {
        SET_RUNTIME_PM_OPS(mtk_jpeg_pm_suspend, mtk_jpeg_pm_resume, NULL)
 };
 
-#if defined(CONFIG_OF)
 static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx)
 {
        struct mtk_jpegenc_comp_dev *comp_jpeg;
@@ -1951,14 +1948,13 @@ static const struct of_device_id mtk_jpeg_match[] = {
 };
 
 MODULE_DEVICE_TABLE(of, mtk_jpeg_match);
-#endif
 
 static struct platform_driver mtk_jpeg_driver = {
        .probe = mtk_jpeg_probe,
        .remove_new = mtk_jpeg_remove,
        .driver = {
                .name           = MTK_JPEG_NAME,
-               .of_match_table = of_match_ptr(mtk_jpeg_match),
+               .of_match_table = mtk_jpeg_match,
                .pm             = &mtk_jpeg_pm_ops,
        },
 };
index 869068f..baa7be5 100644 (file)
@@ -39,7 +39,6 @@ enum mtk_jpeg_color {
        MTK_JPEG_COLOR_400              = 0x00110000
 };
 
-#if defined(CONFIG_OF)
 static const struct of_device_id mtk_jpegdec_hw_ids[] = {
        {
                .compatible = "mediatek,mt8195-jpgdec-hw",
@@ -47,7 +46,6 @@ static const struct of_device_id mtk_jpegdec_hw_ids[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, mtk_jpegdec_hw_ids);
-#endif
 
 static inline int mtk_jpeg_verify_align(u32 val, int align, u32 reg)
 {
@@ -653,7 +651,7 @@ static struct platform_driver mtk_jpegdec_hw_driver = {
        .probe = mtk_jpegdec_hw_probe,
        .driver = {
                .name = "mtk-jpegdec-hw",
-               .of_match_table = of_match_ptr(mtk_jpegdec_hw_ids),
+               .of_match_table = mtk_jpegdec_hw_ids,
        },
 };
 
index 71e85b4..2440183 100644 (file)
@@ -46,7 +46,6 @@ static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
        {.quality_param = 97, .hardware_value = JPEG_ENC_QUALITY_Q97},
 };
 
-#if defined(CONFIG_OF)
 static const struct of_device_id mtk_jpegenc_drv_ids[] = {
        {
                .compatible = "mediatek,mt8195-jpgenc-hw",
@@ -54,7 +53,6 @@ static const struct of_device_id mtk_jpegenc_drv_ids[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, mtk_jpegenc_drv_ids);
-#endif
 
 void mtk_jpeg_enc_reset(void __iomem *base)
 {
@@ -377,7 +375,7 @@ static struct platform_driver mtk_jpegenc_hw_driver = {
        .probe = mtk_jpegenc_hw_probe,
        .driver = {
                .name = "mtk-jpegenc-hw",
-               .of_match_table = of_match_ptr(mtk_jpegenc_drv_ids),
+               .of_match_table = mtk_jpegenc_drv_ids,
        },
 };
 
index f555341..04e6dc6 100644 (file)
@@ -233,7 +233,8 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
                kfree(lat_buf->private_data);
        }
 
-       cancel_work_sync(&msg_queue->core_work);
+       if (msg_queue->wdma_addr.size)
+               cancel_work_sync(&msg_queue->core_work);
 }
 
 static void vdec_msg_queue_core_work(struct work_struct *work)
index ed15ea3..a2b4fb9 100644 (file)
@@ -58,7 +58,6 @@
 #define CAST_OFBSIZE_LO                        CAST_STATUS18
 #define CAST_OFBSIZE_HI                        CAST_STATUS19
 
-#define MXC_MAX_SLOTS  1 /* TODO use all 4 slots*/
 /* JPEG-Decoder Wrapper Slot Registers 0..3 */
 #define SLOT_BASE                      0x10000
 #define SLOT_STATUS                    0x0
index c0e49be..9512c0a 100644 (file)
@@ -745,87 +745,77 @@ static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
        v4l2_event_queue_fh(&ctx->fh, &ev);
 }
 
-static int mxc_get_free_slot(struct mxc_jpeg_slot_data slot_data[], int n)
+static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)
 {
-       int free_slot = 0;
-
-       while (slot_data[free_slot].used && free_slot < n)
-               free_slot++;
-
-       return free_slot; /* >=n when there are no more free slots */
+       if (!slot_data->used)
+               return slot_data->slot;
+       return -1;
 }
 
-static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg,
-                                    unsigned int slot)
+static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
 {
        struct mxc_jpeg_desc *desc;
        struct mxc_jpeg_desc *cfg_desc;
        void *cfg_stm;
 
-       if (jpeg->slot_data[slot].desc)
+       if (jpeg->slot_data.desc)
                goto skip_alloc; /* already allocated, reuse it */
 
        /* allocate descriptor for decoding/encoding phase */
        desc = dma_alloc_coherent(jpeg->dev,
                                  sizeof(struct mxc_jpeg_desc),
-                                 &jpeg->slot_data[slot].desc_handle,
+                                 &jpeg->slot_data.desc_handle,
                                  GFP_ATOMIC);
        if (!desc)
                goto err;
-       jpeg->slot_data[slot].desc = desc;
+       jpeg->slot_data.desc = desc;
 
        /* allocate descriptor for configuration phase (encoder only) */
        cfg_desc = dma_alloc_coherent(jpeg->dev,
                                      sizeof(struct mxc_jpeg_desc),
-                                     &jpeg->slot_data[slot].cfg_desc_handle,
+                                     &jpeg->slot_data.cfg_desc_handle,
                                      GFP_ATOMIC);
        if (!cfg_desc)
                goto err;
-       jpeg->slot_data[slot].cfg_desc = cfg_desc;
+       jpeg->slot_data.cfg_desc = cfg_desc;
 
        /* allocate configuration stream */
        cfg_stm = dma_alloc_coherent(jpeg->dev,
                                     MXC_JPEG_MAX_CFG_STREAM,
-                                    &jpeg->slot_data[slot].cfg_stream_handle,
+                                    &jpeg->slot_data.cfg_stream_handle,
                                     GFP_ATOMIC);
        if (!cfg_stm)
                goto err;
-       jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm;
+       jpeg->slot_data.cfg_stream_vaddr = cfg_stm;
 
 skip_alloc:
-       jpeg->slot_data[slot].used = true;
+       jpeg->slot_data.used = true;
 
        return true;
 err:
-       dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", slot);
+       dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot);
 
        return false;
 }
 
-static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg,
-                                   unsigned int slot)
+static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
 {
-       if (slot >= MXC_MAX_SLOTS) {
-               dev_err(jpeg->dev, "Invalid slot %d, nothing to free.", slot);
-               return;
-       }
-
        /* free descriptor for decoding/encoding phase */
        dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
-                         jpeg->slot_data[slot].desc,
-                         jpeg->slot_data[slot].desc_handle);
+                         jpeg->slot_data.desc,
+                         jpeg->slot_data.desc_handle);
 
        /* free descriptor for encoder configuration phase / decoder DHT */
        dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
-                         jpeg->slot_data[slot].cfg_desc,
-                         jpeg->slot_data[slot].cfg_desc_handle);
+                         jpeg->slot_data.cfg_desc,
+                         jpeg->slot_data.cfg_desc_handle);
 
        /* free configuration stream */
        dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
-                         jpeg->slot_data[slot].cfg_stream_vaddr,
-                         jpeg->slot_data[slot].cfg_stream_handle);
+                         jpeg->slot_data.cfg_stream_vaddr,
+                         jpeg->slot_data.cfg_stream_handle);
 
-       jpeg->slot_data[slot].used = false;
+       jpeg->slot_data.used = false;
 }
 
 static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx,
@@ -855,7 +845,7 @@ static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state
        v4l2_m2m_buf_done(dst_buf, state);
 
        mxc_jpeg_disable_irq(reg, ctx->slot);
-       ctx->mxc_jpeg->slot_data[ctx->slot].used = false;
+       jpeg->slot_data.used = false;
        if (reset)
                mxc_jpeg_sw_reset(reg);
 }
@@ -919,7 +909,7 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
                goto job_unlock;
        }
 
-       if (!jpeg->slot_data[slot].used)
+       if (!jpeg->slot_data.used)
                goto job_unlock;
 
        dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
@@ -1179,13 +1169,13 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
        struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
        void __iomem *reg = jpeg->base_reg;
        unsigned int slot = ctx->slot;
-       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
-       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
-       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
-       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
-       dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
-       unsigned int *cfg_size = &jpeg->slot_data[slot].cfg_stream_size;
-       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+       struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;
+       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;
+       dma_addr_t desc_handle = jpeg->slot_data.desc_handle;
+       dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;
+       dma_addr_t cfg_stream_handle = jpeg->slot_data.cfg_stream_handle;
+       unsigned int *cfg_size = &jpeg->slot_data.cfg_stream_size;
+       void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;
        struct mxc_jpeg_src_buf *jpeg_src_buf;
 
        jpeg_src_buf = vb2_to_mxc_buf(src_buf);
@@ -1245,18 +1235,18 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
        struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
        void __iomem *reg = jpeg->base_reg;
        unsigned int slot = ctx->slot;
-       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
-       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
-       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
-       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
-       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+       struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;
+       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;
+       dma_addr_t desc_handle = jpeg->slot_data.desc_handle;
+       dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;
+       void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;
        struct mxc_jpeg_q_data *q_data;
        enum mxc_jpeg_image_format img_fmt;
        int w, h;
 
        q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);
 
-       jpeg->slot_data[slot].cfg_stream_size =
+       jpeg->slot_data.cfg_stream_size =
                        mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
                                                  q_data->fmt->fourcc,
                                                  q_data->crop.width,
@@ -1265,7 +1255,7 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
        /* chain the config descriptor with the encoding descriptor */
        cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
 
-       cfg_desc->buf_base0 = jpeg->slot_data[slot].cfg_stream_handle;
+       cfg_desc->buf_base0 = jpeg->slot_data.cfg_stream_handle;
        cfg_desc->buf_base1 = 0;
        cfg_desc->line_pitch = 0;
        cfg_desc->stm_bufbase = 0; /* no output expected */
@@ -1408,7 +1398,7 @@ static void mxc_jpeg_device_run_timeout(struct work_struct *work)
        unsigned long flags;
 
        spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
-       if (ctx->slot < MXC_MAX_SLOTS && ctx->mxc_jpeg->slot_data[ctx->slot].used) {
+       if (ctx->mxc_jpeg->slot_data.used) {
                dev_warn(jpeg->dev, "%s timeout, cancel it\n",
                         ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? "decode" : "encode");
                mxc_jpeg_job_finish(ctx, VB2_BUF_STATE_ERROR, true);
@@ -1476,12 +1466,12 @@ static void mxc_jpeg_device_run(void *priv)
        mxc_jpeg_enable(reg);
        mxc_jpeg_set_l_endian(reg, 1);
 
-       ctx->slot = mxc_get_free_slot(jpeg->slot_data, MXC_MAX_SLOTS);
-       if (ctx->slot >= MXC_MAX_SLOTS) {
+       ctx->slot = mxc_get_free_slot(&jpeg->slot_data);
+       if (ctx->slot < 0) {
                dev_err(dev, "No more free slots\n");
                goto end;
        }
-       if (!mxc_jpeg_alloc_slot_data(jpeg, ctx->slot)) {
+       if (!mxc_jpeg_alloc_slot_data(jpeg)) {
                dev_err(dev, "Cannot allocate slot data\n");
                goto end;
        }
@@ -2101,7 +2091,7 @@ static int mxc_jpeg_open(struct file *file)
        }
        ctx->fh.ctrl_handler = &ctx->ctrl_handler;
        mxc_jpeg_set_default_params(ctx);
-       ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */
+       ctx->slot = -1; /* slot not allocated yet */
        INIT_DELAYED_WORK(&ctx->task_timer, mxc_jpeg_device_run_timeout);
 
        if (mxc_jpeg->mode == MXC_JPEG_DECODE)
@@ -2677,6 +2667,11 @@ static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
                dev_err(dev, "No power domains defined for jpeg node\n");
                return jpeg->num_domains;
        }
+       if (jpeg->num_domains == 1) {
+               /* genpd_dev_pm_attach() attach automatically if power domains count is 1 */
+               jpeg->num_domains = 0;
+               return 0;
+       }
 
        jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,
                                          sizeof(*jpeg->pd_dev), GFP_KERNEL);
@@ -2718,7 +2713,6 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
        int ret;
        int mode;
        const struct of_device_id *of_id;
-       unsigned int slot;
 
        of_id = of_match_node(mxc_jpeg_match, dev->of_node);
        if (!of_id)
@@ -2742,19 +2736,22 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
        if (IS_ERR(jpeg->base_reg))
                return PTR_ERR(jpeg->base_reg);
 
-       for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
-               dec_irq = platform_get_irq(pdev, slot);
-               if (dec_irq < 0) {
-                       ret = dec_irq;
-                       goto err_irq;
-               }
-               ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
-                                      0, pdev->name, jpeg);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
-                               dec_irq, ret);
-                       goto err_irq;
-               }
+       ret = of_property_read_u32_index(pdev->dev.of_node, "slot", 0, &jpeg->slot_data.slot);
+       if (ret)
+               jpeg->slot_data.slot = 0;
+       dev_info(&pdev->dev, "choose slot %d\n", jpeg->slot_data.slot);
+       dec_irq = platform_get_irq(pdev, 0);
+       if (dec_irq < 0) {
+               dev_err(&pdev->dev, "Failed to get irq %d\n", dec_irq);
+               ret = dec_irq;
+               goto err_irq;
+       }
+       ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
+                              0, pdev->name, jpeg);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
+                       dec_irq, ret);
+               goto err_irq;
        }
 
        jpeg->pdev = pdev;
@@ -2914,11 +2911,9 @@ static const struct dev_pm_ops   mxc_jpeg_pm_ops = {
 
 static void mxc_jpeg_remove(struct platform_device *pdev)
 {
-       unsigned int slot;
        struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
 
-       for (slot = 0; slot < MXC_MAX_SLOTS; slot++)
-               mxc_jpeg_free_slot_data(jpeg, slot);
+       mxc_jpeg_free_slot_data(jpeg);
 
        pm_runtime_disable(&pdev->dev);
        video_unregister_device(jpeg->dec_vdev);
index 87157db..d80e94c 100644 (file)
@@ -97,7 +97,7 @@ struct mxc_jpeg_ctx {
        struct mxc_jpeg_q_data          cap_q;
        struct v4l2_fh                  fh;
        enum mxc_jpeg_enc_state         enc_state;
-       unsigned int                    slot;
+       int                             slot;
        unsigned int                    source_change;
        bool                            header_parsed;
        struct v4l2_ctrl_handler        ctrl_handler;
@@ -106,6 +106,7 @@ struct mxc_jpeg_ctx {
 };
 
 struct mxc_jpeg_slot_data {
+       int slot;
        bool used;
        struct mxc_jpeg_desc *desc; // enc/dec descriptor
        struct mxc_jpeg_desc *cfg_desc; // configuration descriptor
@@ -128,7 +129,7 @@ struct mxc_jpeg_dev {
        struct v4l2_device              v4l2_dev;
        struct v4l2_m2m_dev             *m2m_dev;
        struct video_device             *dec_vdev;
-       struct mxc_jpeg_slot_data       slot_data[MXC_MAX_SLOTS];
+       struct mxc_jpeg_slot_data       slot_data;
        int                             num_domains;
        struct device                   **pd_dev;
        struct device_link              **pd_link;
index 6523ffb..77aee94 100644 (file)
@@ -370,26 +370,26 @@ extern int hantro_debug;
        pr_err("%s:%d: " fmt, __func__, __LINE__, ##args)
 
 /* Structure access helpers. */
-static inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh)
+static __always_inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh)
 {
        return container_of(fh, struct hantro_ctx, fh);
 }
 
 /* Register accessors. */
-static inline void vepu_write_relaxed(struct hantro_dev *vpu,
-                                     u32 val, u32 reg)
+static __always_inline void vepu_write_relaxed(struct hantro_dev *vpu,
+                                              u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel_relaxed(val, vpu->enc_base + reg);
 }
 
-static inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
+static __always_inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel(val, vpu->enc_base + reg);
 }
 
-static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
+static __always_inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
 {
        u32 val = readl(vpu->enc_base + reg);
 
@@ -397,27 +397,27 @@ static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
        return val;
 }
 
-static inline void vdpu_write_relaxed(struct hantro_dev *vpu,
-                                     u32 val, u32 reg)
+static __always_inline void vdpu_write_relaxed(struct hantro_dev *vpu,
+                                              u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel_relaxed(val, vpu->dec_base + reg);
 }
 
-static inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
+static __always_inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel(val, vpu->dec_base + reg);
 }
 
-static inline void hantro_write_addr(struct hantro_dev *vpu,
-                                    unsigned long offset,
-                                    dma_addr_t addr)
+static __always_inline void hantro_write_addr(struct hantro_dev *vpu,
+                                             unsigned long offset,
+                                             dma_addr_t addr)
 {
        vdpu_write(vpu, addr & 0xffffffff, offset);
 }
 
-static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
+static __always_inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
 {
        u32 val = readl(vpu->dec_base + reg);
 
@@ -425,9 +425,9 @@ static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
        return val;
 }
 
-static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
-                                const struct hantro_reg *reg,
-                                u32 val)
+static __always_inline u32 vdpu_read_mask(struct hantro_dev *vpu,
+                                         const struct hantro_reg *reg,
+                                         u32 val)
 {
        u32 v;
 
@@ -437,18 +437,18 @@ static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
        return v;
 }
 
-static inline void hantro_reg_write(struct hantro_dev *vpu,
-                                   const struct hantro_reg *reg,
-                                   u32 val)
+static __always_inline void hantro_reg_write(struct hantro_dev *vpu,
+                                            const struct hantro_reg *reg,
+                                            u32 val)
 {
-       vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
+       vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
 }
 
-static inline void hantro_reg_write_s(struct hantro_dev *vpu,
-                                     const struct hantro_reg *reg,
-                                     u32 val)
+static __always_inline void hantro_reg_write_relaxed(struct hantro_dev *vpu,
+                                                    const struct hantro_reg *reg,
+                                                    u32 val)
 {
-       vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
+       vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
 }
 
 void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id);
index c977d64..0224ff6 100644 (file)
                         val); \
 }
 
-#define HANTRO_PP_REG_WRITE_S(vpu, reg_name, val) \
+#define HANTRO_PP_REG_WRITE_RELAXED(vpu, reg_name, val) \
 { \
-       hantro_reg_write_s(vpu, \
-                          &hantro_g1_postproc_regs.reg_name, \
-                          val); \
+       hantro_reg_write_relaxed(vpu, \
+                                &hantro_g1_postproc_regs.reg_name, \
+                                val); \
 }
 
 #define VPU_PP_IN_YUYV                 0x0
@@ -72,7 +72,7 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
        dma_addr_t dst_dma;
 
        /* Turn on pipeline mode. Must be done first. */
-       HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x1);
+       HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x1);
 
        src_pp_fmt = VPU_PP_IN_NV12;
 
@@ -242,7 +242,7 @@ static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
 {
        struct hantro_dev *vpu = ctx->dev;
 
-       HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x0);
+       HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x0);
 }
 
 static void hantro_postproc_g2_disable(struct hantro_ctx *ctx)
index 7a0f253..484c9e3 100644 (file)
@@ -1508,6 +1508,11 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
 
        memcpy(bond_dev->broadcast, slave_dev->broadcast,
                slave_dev->addr_len);
+
+       if (slave_dev->flags & IFF_POINTOPOINT) {
+               bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+               bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+       }
 }
 
 /* On bonding slaves other than the currently active slave, suppress
index 68df6d4..eebf967 100644 (file)
@@ -227,6 +227,8 @@ static int
 __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
                          const u8 mode_req, bool nowait)
 {
+       const struct can_bittiming *bt = &priv->can.bittiming;
+       unsigned long timeout_us = MCP251XFD_POLL_TIMEOUT_US;
        u32 con = 0, con_reqop, osc = 0;
        u8 mode;
        int err;
@@ -246,12 +248,16 @@ __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
        if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait)
                return 0;
 
+       if (bt->bitrate)
+               timeout_us = max_t(unsigned long, timeout_us,
+                                  MCP251XFD_FRAME_LEN_MAX_BITS * USEC_PER_SEC /
+                                  bt->bitrate);
+
        err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con,
                                       !mcp251xfd_reg_invalid(con) &&
                                       FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK,
                                                 con) == mode_req,
-                                      MCP251XFD_POLL_SLEEP_US,
-                                      MCP251XFD_POLL_TIMEOUT_US);
+                                      MCP251XFD_POLL_SLEEP_US, timeout_us);
        if (err != -ETIMEDOUT && err != -EBADMSG)
                return err;
 
index 7024ff0..24510b3 100644 (file)
@@ -387,6 +387,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
 #define MCP251XFD_POLL_SLEEP_US (10)
 #define MCP251XFD_POLL_TIMEOUT_US (USEC_PER_MSEC)
+#define MCP251XFD_FRAME_LEN_MAX_BITS (736)
 
 /* Misc */
 #define MCP251XFD_NAPI_WEIGHT 32
index d476c28..bd9eb06 100644 (file)
@@ -303,12 +303,6 @@ struct gs_can {
        struct can_bittiming_const bt_const, data_bt_const;
        unsigned int channel;   /* channel number */
 
-       /* time counter for hardware timestamps */
-       struct cyclecounter cc;
-       struct timecounter tc;
-       spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
-       struct delayed_work timestamp;
-
        u32 feature;
        unsigned int hf_size_tx;
 
@@ -325,6 +319,13 @@ struct gs_usb {
        struct gs_can *canch[GS_MAX_INTF];
        struct usb_anchor rx_submitted;
        struct usb_device *udev;
+
+       /* time counter for hardware timestamps */
+       struct cyclecounter cc;
+       struct timecounter tc;
+       spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
+       struct delayed_work timestamp;
+
        unsigned int hf_size_rx;
        u8 active_channels;
 };
@@ -388,15 +389,15 @@ static int gs_cmd_reset(struct gs_can *dev)
                                    GFP_KERNEL);
 }
 
-static inline int gs_usb_get_timestamp(const struct gs_can *dev,
+static inline int gs_usb_get_timestamp(const struct gs_usb *parent,
                                       u32 *timestamp_p)
 {
        __le32 timestamp;
        int rc;
 
-       rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_TIMESTAMP,
+       rc = usb_control_msg_recv(parent->udev, 0, GS_USB_BREQ_TIMESTAMP,
                                  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                                 dev->channel, 0,
+                                 0, 0,
                                  &timestamp, sizeof(timestamp),
                                  USB_CTRL_GET_TIMEOUT,
                                  GFP_KERNEL);
@@ -410,20 +411,20 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
 
 static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
 {
-       struct gs_can *dev = container_of(cc, struct gs_can, cc);
+       struct gs_usb *parent = container_of(cc, struct gs_usb, cc);
        u32 timestamp = 0;
        int err;
 
-       lockdep_assert_held(&dev->tc_lock);
+       lockdep_assert_held(&parent->tc_lock);
 
        /* drop lock for synchronous USB transfer */
-       spin_unlock_bh(&dev->tc_lock);
-       err = gs_usb_get_timestamp(dev, &timestamp);
-       spin_lock_bh(&dev->tc_lock);
+       spin_unlock_bh(&parent->tc_lock);
+       err = gs_usb_get_timestamp(parent, &timestamp);
+       spin_lock_bh(&parent->tc_lock);
        if (err)
-               netdev_err(dev->netdev,
-                          "Error %d while reading timestamp. HW timestamps may be inaccurate.",
-                          err);
+               dev_err(&parent->udev->dev,
+                       "Error %d while reading timestamp. HW timestamps may be inaccurate.",
+                       err);
 
        return timestamp;
 }
@@ -431,14 +432,14 @@ static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev
 static void gs_usb_timestamp_work(struct work_struct *work)
 {
        struct delayed_work *delayed_work = to_delayed_work(work);
-       struct gs_can *dev;
+       struct gs_usb *parent;
 
-       dev = container_of(delayed_work, struct gs_can, timestamp);
-       spin_lock_bh(&dev->tc_lock);
-       timecounter_read(&dev->tc);
-       spin_unlock_bh(&dev->tc_lock);
+       parent = container_of(delayed_work, struct gs_usb, timestamp);
+       spin_lock_bh(&parent->tc_lock);
+       timecounter_read(&parent->tc);
+       spin_unlock_bh(&parent->tc_lock);
 
-       schedule_delayed_work(&dev->timestamp,
+       schedule_delayed_work(&parent->timestamp,
                              GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
 }
 
@@ -446,37 +447,38 @@ static void gs_usb_skb_set_timestamp(struct gs_can *dev,
                                     struct sk_buff *skb, u32 timestamp)
 {
        struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
+       struct gs_usb *parent = dev->parent;
        u64 ns;
 
-       spin_lock_bh(&dev->tc_lock);
-       ns = timecounter_cyc2time(&dev->tc, timestamp);
-       spin_unlock_bh(&dev->tc_lock);
+       spin_lock_bh(&parent->tc_lock);
+       ns = timecounter_cyc2time(&parent->tc, timestamp);
+       spin_unlock_bh(&parent->tc_lock);
 
        hwtstamps->hwtstamp = ns_to_ktime(ns);
 }
 
-static void gs_usb_timestamp_init(struct gs_can *dev)
+static void gs_usb_timestamp_init(struct gs_usb *parent)
 {
-       struct cyclecounter *cc = &dev->cc;
+       struct cyclecounter *cc = &parent->cc;
 
        cc->read = gs_usb_timestamp_read;
        cc->mask = CYCLECOUNTER_MASK(32);
        cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
        cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
 
-       spin_lock_init(&dev->tc_lock);
-       spin_lock_bh(&dev->tc_lock);
-       timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
-       spin_unlock_bh(&dev->tc_lock);
+       spin_lock_init(&parent->tc_lock);
+       spin_lock_bh(&parent->tc_lock);
+       timecounter_init(&parent->tc, &parent->cc, ktime_get_real_ns());
+       spin_unlock_bh(&parent->tc_lock);
 
-       INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
-       schedule_delayed_work(&dev->timestamp,
+       INIT_DELAYED_WORK(&parent->timestamp, gs_usb_timestamp_work);
+       schedule_delayed_work(&parent->timestamp,
                              GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
 }
 
-static void gs_usb_timestamp_stop(struct gs_can *dev)
+static void gs_usb_timestamp_stop(struct gs_usb *parent)
 {
-       cancel_delayed_work_sync(&dev->timestamp);
+       cancel_delayed_work_sync(&parent->timestamp);
 }
 
 static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
@@ -560,6 +562,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
        if (!netif_device_present(netdev))
                return;
 
+       if (!netif_running(netdev))
+               goto resubmit_urb;
+
        if (hf->echo_id == -1) { /* normal rx */
                if (hf->flags & GS_CAN_FLAG_FD) {
                        skb = alloc_canfd_skb(dev->netdev, &cfd);
@@ -833,6 +838,7 @@ static int gs_can_open(struct net_device *netdev)
                .mode = cpu_to_le32(GS_CAN_MODE_START),
        };
        struct gs_host_frame *hf;
+       struct urb *urb = NULL;
        u32 ctrlmode;
        u32 flags = 0;
        int rc, i;
@@ -855,14 +861,18 @@ static int gs_can_open(struct net_device *netdev)
        }
 
        if (!parent->active_channels) {
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_init(parent);
+
                for (i = 0; i < GS_MAX_RX_URBS; i++) {
-                       struct urb *urb;
                        u8 *buf;
 
                        /* alloc rx urb */
                        urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!urb)
-                               return -ENOMEM;
+                       if (!urb) {
+                               rc = -ENOMEM;
+                               goto out_usb_kill_anchored_urbs;
+                       }
 
                        /* alloc rx buffer */
                        buf = kmalloc(dev->parent->hf_size_rx,
@@ -870,8 +880,8 @@ static int gs_can_open(struct net_device *netdev)
                        if (!buf) {
                                netdev_err(netdev,
                                           "No memory left for USB buffer\n");
-                               usb_free_urb(urb);
-                               return -ENOMEM;
+                               rc = -ENOMEM;
+                               goto out_usb_free_urb;
                        }
 
                        /* fill, anchor, and submit rx urb */
@@ -894,9 +904,7 @@ static int gs_can_open(struct net_device *netdev)
                                netdev_err(netdev,
                                           "usb_submit failed (err=%d)\n", rc);
 
-                               usb_unanchor_urb(urb);
-                               usb_free_urb(urb);
-                               break;
+                               goto out_usb_unanchor_urb;
                        }
 
                        /* Drop reference,
@@ -926,13 +934,9 @@ static int gs_can_open(struct net_device *netdev)
                flags |= GS_CAN_MODE_FD;
 
        /* if hardware supports timestamps, enable it */
-       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
+       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
                flags |= GS_CAN_MODE_HW_TIMESTAMP;
 
-               /* start polling timestamp */
-               gs_usb_timestamp_init(dev);
-       }
-
        /* finally start device */
        dev->can.state = CAN_STATE_ERROR_ACTIVE;
        dm.flags = cpu_to_le32(flags);
@@ -942,10 +946,9 @@ static int gs_can_open(struct net_device *netdev)
                                  GFP_KERNEL);
        if (rc) {
                netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
-               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
-                       gs_usb_timestamp_stop(dev);
                dev->can.state = CAN_STATE_STOPPED;
-               return rc;
+
+               goto out_usb_kill_anchored_urbs;
        }
 
        parent->active_channels++;
@@ -953,6 +956,22 @@ static int gs_can_open(struct net_device *netdev)
                netif_start_queue(netdev);
 
        return 0;
+
+out_usb_unanchor_urb:
+       usb_unanchor_urb(urb);
+out_usb_free_urb:
+       usb_free_urb(urb);
+out_usb_kill_anchored_urbs:
+       if (!parent->active_channels) {
+               usb_kill_anchored_urbs(&dev->tx_submitted);
+
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_stop(parent);
+       }
+
+       close_candev(netdev);
+
+       return rc;
 }
 
 static int gs_usb_get_state(const struct net_device *netdev,
@@ -998,20 +1017,21 @@ static int gs_can_close(struct net_device *netdev)
 
        netif_stop_queue(netdev);
 
-       /* stop polling timestamp */
-       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
-               gs_usb_timestamp_stop(dev);
-
        /* Stop polling */
        parent->active_channels--;
        if (!parent->active_channels) {
                usb_kill_anchored_urbs(&parent->rx_submitted);
+
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_stop(parent);
        }
 
        /* Stop sending URBs */
        usb_kill_anchored_urbs(&dev->tx_submitted);
        atomic_set(&dev->active_tx_urbs, 0);
 
+       dev->can.state = CAN_STATE_STOPPED;
+
        /* reset the device */
        rc = gs_cmd_reset(dev);
        if (rc < 0)
index 84d5025..91aba47 100644 (file)
@@ -506,7 +506,13 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
                (data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
                        shifts[STATIC_MAC_FWD_PORTS];
        alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
-       data_hi >>= 1;
+
+       /* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and
+        * STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the
+        * static MAC table compared to doing write.
+        */
+       if (ksz_is_ksz87xx(dev))
+               data_hi >>= 1;
        alu->is_static = true;
        alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
        alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
index 813b91a..b18cd17 100644 (file)
@@ -331,13 +331,13 @@ static const u32 ksz8795_masks[] = {
        [STATIC_MAC_TABLE_VALID]        = BIT(21),
        [STATIC_MAC_TABLE_USE_FID]      = BIT(23),
        [STATIC_MAC_TABLE_FID]          = GENMASK(30, 24),
-       [STATIC_MAC_TABLE_OVERRIDE]     = BIT(26),
-       [STATIC_MAC_TABLE_FWD_PORTS]    = GENMASK(24, 20),
+       [STATIC_MAC_TABLE_OVERRIDE]     = BIT(22),
+       [STATIC_MAC_TABLE_FWD_PORTS]    = GENMASK(20, 16),
        [DYNAMIC_MAC_TABLE_ENTRIES_H]   = GENMASK(6, 0),
-       [DYNAMIC_MAC_TABLE_MAC_EMPTY]   = BIT(8),
+       [DYNAMIC_MAC_TABLE_MAC_EMPTY]   = BIT(7),
        [DYNAMIC_MAC_TABLE_NOT_READY]   = BIT(7),
        [DYNAMIC_MAC_TABLE_ENTRIES]     = GENMASK(31, 29),
-       [DYNAMIC_MAC_TABLE_FID]         = GENMASK(26, 20),
+       [DYNAMIC_MAC_TABLE_FID]         = GENMASK(22, 16),
        [DYNAMIC_MAC_TABLE_SRC_PORT]    = GENMASK(26, 24),
        [DYNAMIC_MAC_TABLE_TIMESTAMP]   = GENMASK(28, 27),
        [P_MII_TX_FLOW_CTRL]            = BIT(5),
index 28444e5..a4de588 100644 (file)
@@ -601,6 +601,13 @@ static inline void ksz_regmap_unlock(void *__mtx)
        mutex_unlock(mtx);
 }
 
+static inline bool ksz_is_ksz87xx(struct ksz_device *dev)
+{
+       return dev->chip_id == KSZ8795_CHIP_ID ||
+              dev->chip_id == KSZ8794_CHIP_ID ||
+              dev->chip_id == KSZ8765_CHIP_ID;
+}
+
 static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
 {
        return dev->chip_id == KSZ8830_CHIP_ID;
index 8b51756..c7d51a5 100644 (file)
@@ -109,6 +109,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
                        usleep_range(1000, 2000);
        }
 
+       err = mv88e6xxx_read(chip, addr, reg, &data);
+       if (err)
+               return err;
+
+       if ((data & mask) == val)
+               return 0;
+
        dev_err(chip->dev, "Timeout while waiting for switch\n");
        return -ETIMEDOUT;
 }
index b2bf78a..3b09370 100644 (file)
@@ -1002,6 +1002,8 @@ static const struct regmap_config ar9331_mdio_regmap_config = {
        .val_bits = 32,
        .reg_stride = 4,
        .max_register = AR9331_SW_REG_PAGE,
+       .use_single_read = true,
+       .use_single_write = true,
 
        .ranges = ar9331_regmap_range,
        .num_ranges = ARRAY_SIZE(ar9331_regmap_range),
@@ -1018,8 +1020,6 @@ static struct regmap_bus ar9331_sw_bus = {
        .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
        .read = ar9331_mdio_read,
        .write = ar9331_sw_bus_write,
-       .max_raw_read = 4,
-       .max_raw_write = 4,
 };
 
 static int ar9331_sw_probe(struct mdio_device *mdiodev)
index 09b8064..efe9380 100644 (file)
@@ -576,8 +576,11 @@ static struct regmap_config qca8k_regmap_config = {
        .rd_table = &qca8k_readable_table,
        .disable_locking = true, /* Locking is handled by qca8k read/write */
        .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
-       .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */
-       .max_raw_write = 32,
+       .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */
+       /* ATU regs suffer from a bug where some data are not correctly
+        * written. Disable bulk write to correctly write ATU entry.
+        */
+       .use_single_write = true,
 };
 
 static int
index 8c2dc0e..13b8452 100644 (file)
@@ -244,7 +244,7 @@ void qca8k_fdb_flush(struct qca8k_priv *priv)
 }
 
 static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
-                                      const u8 *mac, u16 vid)
+                                      const u8 *mac, u16 vid, u8 aging)
 {
        struct qca8k_fdb fdb = { 0 };
        int ret;
@@ -261,10 +261,12 @@ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
                goto exit;
 
        /* Rule exist. Delete first */
-       if (!fdb.aging) {
+       if (fdb.aging) {
                ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
                if (ret)
                        goto exit;
+       } else {
+               fdb.aging = aging;
        }
 
        /* Add port to fdb portmask */
@@ -291,6 +293,10 @@ static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
        if (ret < 0)
                goto exit;
 
+       ret = qca8k_fdb_read(priv, &fdb);
+       if (ret < 0)
+               goto exit;
+
        /* Rule doesn't exist. Why delete? */
        if (!fdb.aging) {
                ret = -EINVAL;
@@ -810,7 +816,11 @@ int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
        const u8 *addr = mdb->addr;
        u16 vid = mdb->vid;
 
-       return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
+       if (!vid)
+               vid = QCA8K_PORT_VID_DEF;
+
+       return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
+                                          QCA8K_ATU_STATUS_STATIC);
 }
 
 int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
@@ -821,6 +831,9 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
        const u8 *addr = mdb->addr;
        u16 vid = mdb->vid;
 
+       if (!vid)
+               vid = QCA8K_PORT_VID_DEF;
+
        return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
 }
 
index 4a28879..940c5d1 100644 (file)
@@ -2094,8 +2094,11 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter,
                        real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
                                        + ntohs(ip_hdr(skb)->tot_len));
 
-                       if (real_len < skb->len)
-                               pskb_trim(skb, real_len);
+                       if (real_len < skb->len) {
+                               err = pskb_trim(skb, real_len);
+                               if (err)
+                                       return err;
+                       }
 
                        hdr_len = skb_tcp_all_headers(skb);
                        if (unlikely(skb->len == hdr_len)) {
index 5db0f34..5935be1 100644 (file)
@@ -1641,8 +1641,11 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter,
                        real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
                                        + ntohs(ip_hdr(skb)->tot_len));
 
-                       if (real_len < skb->len)
-                               pskb_trim(skb, real_len);
+                       if (real_len < skb->len) {
+                               err = pskb_trim(skb, real_len);
+                               if (err)
+                                       return err;
+                       }
 
                        hdr_len = skb_tcp_all_headers(skb);
                        if (unlikely(skb->len == hdr_len)) {
index c8444bc..02aa6fd 100644 (file)
@@ -2113,8 +2113,11 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
 
                        real_len = (((unsigned char *)iph - skb->data) +
                                ntohs(iph->tot_len));
-                       if (real_len < skb->len)
-                               pskb_trim(skb, real_len);
+                       if (real_len < skb->len) {
+                               err = pskb_trim(skb, real_len);
+                               if (err)
+                                       return err;
+                       }
                        hdr_len = skb_tcp_all_headers(skb);
                        if (skb->len == hdr_len) {
                                iph->check = 0;
index 04ad0f2..7246e13 100644 (file)
@@ -512,11 +512,6 @@ bnad_debugfs_init(struct bnad *bnad)
        if (!bnad->port_debugfs_root) {
                bnad->port_debugfs_root =
                        debugfs_create_dir(name, bna_debugfs_root);
-               if (!bnad->port_debugfs_root) {
-                       netdev_warn(bnad->netdev,
-                                   "debugfs root dir creation failed\n");
-                       return;
-               }
 
                atomic_inc(&bna_debugfs_port_count);
 
index 18c2fc8..0616b5f 100644 (file)
@@ -1138,7 +1138,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
            (lancer_chip(adapter) || BE3_chip(adapter) ||
             skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
                ip = (struct iphdr *)ip_hdr(skb);
-               pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
+               if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len))))
+                       goto tx_drop;
        }
 
        /* If vlan tag is already inlined in the packet, skip HW VLAN
index ec9e4bd..66b5cbd 100644 (file)
@@ -1372,7 +1372,7 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
 }
 
 static void
-fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
+fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget)
 {
        struct  fec_enet_private *fep;
        struct xdp_frame *xdpf;
@@ -1416,6 +1416,14 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                        if (!skb)
                                goto tx_buf_done;
                } else {
+                       /* Tx processing cannot call any XDP (or page pool) APIs if
+                        * the "budget" is 0. Because NAPI is called with budget of
+                        * 0 (such as netpoll) indicates we may be in an IRQ context,
+                        * however, we can't use the page pool from IRQ context.
+                        */
+                       if (unlikely(!budget))
+                               break;
+
                        xdpf = txq->tx_buf[index].xdp;
                        if (bdp->cbd_bufaddr)
                                dma_unmap_single(&fep->pdev->dev,
@@ -1508,14 +1516,14 @@ tx_buf_done:
                writel(0, txq->bd.reg_desc_active);
 }
 
-static void fec_enet_tx(struct net_device *ndev)
+static void fec_enet_tx(struct net_device *ndev, int budget)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        int i;
 
        /* Make sure that AVB queues are processed first. */
        for (i = fep->num_tx_queues - 1; i >= 0; i--)
-               fec_enet_tx_queue(ndev, i);
+               fec_enet_tx_queue(ndev, i, budget);
 }
 
 static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
@@ -1858,7 +1866,7 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 
        do {
                done += fec_enet_rx(ndev, budget - done);
-               fec_enet_tx(ndev);
+               fec_enet_tx(ndev, budget);
        } while ((done < budget) && fec_enet_collect_events(fep));
 
        if (done < budget) {
@@ -3916,6 +3924,8 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
 
        __netif_tx_lock(nq, cpu);
 
+       /* Avoid tx timeout as XDP shares the queue with kernel stack */
+       txq_trans_cond_update(nq);
        for (i = 0; i < num_frames; i++) {
                if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) < 0)
                        break;
index b99d752..514a20b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/pkt_sched.h>
 #include <linux/types.h>
+#include <linux/bitmap.h>
 #include <net/pkt_cls.h>
 #include <net/pkt_sched.h>
 
@@ -101,6 +102,7 @@ enum HNAE3_DEV_CAP_BITS {
        HNAE3_DEV_SUPPORT_FEC_STATS_B,
        HNAE3_DEV_SUPPORT_LANE_NUM_B,
        HNAE3_DEV_SUPPORT_WOL_B,
+       HNAE3_DEV_SUPPORT_TM_FLUSH_B,
 };
 
 #define hnae3_ae_dev_fd_supported(ae_dev) \
@@ -172,6 +174,9 @@ enum HNAE3_DEV_CAP_BITS {
 #define hnae3_ae_dev_wol_supported(ae_dev) \
        test_bit(HNAE3_DEV_SUPPORT_WOL_B, (ae_dev)->caps)
 
+#define hnae3_ae_dev_tm_flush_supported(hdev) \
+       test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps)
+
 enum HNAE3_PF_CAP_BITS {
        HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
 };
@@ -407,7 +412,7 @@ struct hnae3_ae_dev {
        unsigned long hw_err_reset_req;
        struct hnae3_dev_specs dev_specs;
        u32 dev_version;
-       unsigned long caps[BITS_TO_LONGS(HNAE3_DEV_CAPS_MAX_NUM)];
+       DECLARE_BITMAP(caps, HNAE3_DEV_CAPS_MAX_NUM);
        void *priv;
 };
 
index b85c412..dcecb23 100644 (file)
@@ -156,6 +156,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
        {HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B},
        {HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
        {HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B},
+       {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B},
 };
 
 static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
@@ -172,6 +173,20 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
 };
 
 static void
+hclge_comm_capability_to_bitmap(unsigned long *bitmap, __le32 *caps)
+{
+       const unsigned int words = HCLGE_COMM_QUERY_CAP_LENGTH;
+       u32 val[HCLGE_COMM_QUERY_CAP_LENGTH];
+       unsigned int i;
+
+       for (i = 0; i < words; i++)
+               val[i] = __le32_to_cpu(caps[i]);
+
+       bitmap_from_arr32(bitmap, val,
+                         HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+}
+
+static void
 hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
                            struct hclge_comm_query_version_cmd *cmd)
 {
@@ -179,11 +194,12 @@ hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
                                is_pf ? hclge_pf_cmd_caps : hclge_vf_cmd_caps;
        u32 size = is_pf ? ARRAY_SIZE(hclge_pf_cmd_caps) :
                                ARRAY_SIZE(hclge_vf_cmd_caps);
-       u32 caps, i;
+       DECLARE_BITMAP(caps, HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+       u32 i;
 
-       caps = __le32_to_cpu(cmd->caps[0]);
+       hclge_comm_capability_to_bitmap(caps, cmd->caps);
        for (i = 0; i < size; i++)
-               if (hnae3_get_bit(caps, caps_map[i].imp_bit))
+               if (test_bit(caps_map[i].imp_bit, caps))
                        set_bit(caps_map[i].local_bit, ae_dev->caps);
 }
 
index 18f1b4b..2b7197c 100644 (file)
@@ -153,6 +153,7 @@ enum hclge_opcode_type {
        HCLGE_OPC_TM_INTERNAL_STS       = 0x0850,
        HCLGE_OPC_TM_INTERNAL_CNT       = 0x0851,
        HCLGE_OPC_TM_INTERNAL_STS_1     = 0x0852,
+       HCLGE_OPC_TM_FLUSH              = 0x0872,
 
        /* Packet buffer allocate commands */
        HCLGE_OPC_TX_BUFF_ALLOC         = 0x0901,
@@ -349,6 +350,7 @@ enum HCLGE_COMM_CAP_BITS {
        HCLGE_COMM_CAP_FEC_STATS_B = 25,
        HCLGE_COMM_CAP_LANE_NUM_B = 27,
        HCLGE_COMM_CAP_WOL_B = 28,
+       HCLGE_COMM_CAP_TM_FLUSH_B = 31,
 };
 
 enum HCLGE_COMM_API_CAP_BITS {
index 6546cfe..52546f6 100644 (file)
@@ -411,6 +411,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = {
        }, {
                .name = "support wake on lan",
                .cap_bit = HNAE3_DEV_SUPPORT_WOL_B,
+       }, {
+               .name = "support tm flush",
+               .cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B,
        }
 };
 
index c4aded6..fad5a5f 100644 (file)
@@ -52,7 +52,10 @@ static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,
 
        for (i = 0; i < HNAE3_MAX_TC; i++) {
                ets->prio_tc[i] = hdev->tm_info.prio_tc[i];
-               ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+               if (i < hdev->tm_info.num_tc)
+                       ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+               else
+                       ets->tc_tx_bw[i] = 0;
 
                if (hdev->tm_info.tc_info[i].tc_sch_mode ==
                    HCLGE_SCH_MODE_SP)
@@ -123,7 +126,8 @@ static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets,
 }
 
 static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
-                                      struct ieee_ets *ets, bool *changed)
+                                      struct ieee_ets *ets, bool *changed,
+                                      u8 tc_num)
 {
        bool has_ets_tc = false;
        u32 total_ets_bw = 0;
@@ -137,6 +141,13 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
                                *changed = true;
                        break;
                case IEEE_8021QAZ_TSA_ETS:
+                       if (i >= tc_num) {
+                               dev_err(&hdev->pdev->dev,
+                                       "tc%u is disabled, cannot set ets bw\n",
+                                       i);
+                               return -EINVAL;
+                       }
+
                        /* The hardware will switch to sp mode if bandwidth is
                         * 0, so limit ets bandwidth must be greater than 0.
                         */
@@ -176,7 +187,7 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
        if (ret)
                return ret;
 
-       ret = hclge_ets_sch_mode_validate(hdev, ets, changed);
+       ret = hclge_ets_sch_mode_validate(hdev, ets, changed, tc_num);
        if (ret)
                return ret;
 
@@ -216,6 +227,10 @@ static int hclge_notify_down_uinit(struct hclge_dev *hdev)
        if (ret)
                return ret;
 
+       ret = hclge_tm_flush_cfg(hdev, true);
+       if (ret)
+               return ret;
+
        return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
 }
 
@@ -227,6 +242,10 @@ static int hclge_notify_init_up(struct hclge_dev *hdev)
        if (ret)
                return ret;
 
+       ret = hclge_tm_flush_cfg(hdev, false);
+       if (ret)
+               return ret;
+
        return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
 }
 
@@ -313,6 +332,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
        struct net_device *netdev = h->kinfo.netdev;
        struct hclge_dev *hdev = vport->back;
        u8 i, j, pfc_map, *prio_tc;
+       int last_bad_ret = 0;
        int ret;
 
        if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
@@ -350,13 +370,28 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
        if (ret)
                return ret;
 
-       ret = hclge_buffer_alloc(hdev);
-       if (ret) {
-               hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+       ret = hclge_tm_flush_cfg(hdev, true);
+       if (ret)
                return ret;
-       }
 
-       return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+       /* No matter whether the following operations are performed
+        * successfully or not, disabling the tm flush and notify
+        * the network status to up are necessary.
+        * Do not return immediately.
+        */
+       ret = hclge_buffer_alloc(hdev);
+       if (ret)
+               last_bad_ret = ret;
+
+       ret = hclge_tm_flush_cfg(hdev, false);
+       if (ret)
+               last_bad_ret = ret;
+
+       ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+       if (ret)
+               last_bad_ret = ret;
+
+       return last_bad_ret;
 }
 
 static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app)
index 233c132..409db2e 100644 (file)
@@ -693,8 +693,7 @@ static int hclge_dbg_dump_tc(struct hclge_dev *hdev, char *buf, int len)
        for (i = 0; i < HNAE3_MAX_TC; i++) {
                sch_mode_str = ets_weight->tc_weight[i] ? "dwrr" : "sp";
                pos += scnprintf(buf + pos, len - pos, "%u     %4s    %3u\n",
-                                i, sch_mode_str,
-                                hdev->tm_info.pg_info[0].tc_dwrr[i]);
+                                i, sch_mode_str, ets_weight->tc_weight[i]);
        }
 
        return 0;
index 922c0da..de509e5 100644 (file)
@@ -785,6 +785,7 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
 static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
 {
 #define BW_PERCENT     100
+#define DEFAULT_BW_WEIGHT      1
 
        u8 i;
 
@@ -806,7 +807,7 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
                for (k = 0; k < hdev->tm_info.num_tc; k++)
                        hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT;
                for (; k < HNAE3_MAX_TC; k++)
-                       hdev->tm_info.pg_info[i].tc_dwrr[k] = 0;
+                       hdev->tm_info.pg_info[i].tc_dwrr[k] = DEFAULT_BW_WEIGHT;
        }
 }
 
@@ -1484,7 +1485,11 @@ int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
                return ret;
 
        /* Cfg schd mode for each level schd */
-       return hclge_tm_schd_mode_hw(hdev);
+       ret = hclge_tm_schd_mode_hw(hdev);
+       if (ret)
+               return ret;
+
+       return hclge_tm_flush_cfg(hdev, false);
 }
 
 static int hclge_pause_param_setup_hw(struct hclge_dev *hdev)
@@ -2113,3 +2118,28 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
 
        return 0;
 }
+
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable)
+{
+       struct hclge_desc desc;
+       int ret;
+
+       if (!hnae3_ae_dev_tm_flush_supported(hdev))
+               return 0;
+
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_FLUSH, false);
+
+       desc.data[0] = cpu_to_le32(enable ? HCLGE_TM_FLUSH_EN_MSK : 0);
+
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       if (ret) {
+               dev_err(&hdev->pdev->dev,
+                       "failed to config tm flush, ret = %d\n", ret);
+               return ret;
+       }
+
+       if (enable)
+               msleep(HCLGE_TM_FLUSH_TIME_MS);
+
+       return ret;
+}
index dd6f1fd..45dcfef 100644 (file)
@@ -33,6 +33,9 @@ enum hclge_opcode_type;
 #define HCLGE_DSCP_MAP_TC_BD_NUM       2
 #define HCLGE_DSCP_TC_SHIFT(n)         (((n) & 1) * 4)
 
+#define HCLGE_TM_FLUSH_TIME_MS 10
+#define HCLGE_TM_FLUSH_EN_MSK  BIT(0)
+
 struct hclge_pg_to_pri_link_cmd {
        u8 pg_id;
        u8 rsvd1[3];
@@ -272,4 +275,5 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
                             struct hclge_tm_shaper_para *para);
 int hclge_up_to_tc_map(struct hclge_dev *hdev);
 int hclge_dscp_to_tc_map(struct hclge_dev *hdev);
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable);
 #endif
index 9954493..62497f5 100644 (file)
@@ -1839,7 +1839,7 @@ void i40e_dbg_pf_exit(struct i40e_pf *pf)
 void i40e_dbg_init(void)
 {
        i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL);
-       if (!i40e_dbg_root)
+       if (IS_ERR(i40e_dbg_root))
                pr_info("init of debugfs failed\n");
 }
 
index f80f273..8cbdebc 100644 (file)
@@ -255,8 +255,10 @@ struct iavf_adapter {
        struct workqueue_struct *wq;
        struct work_struct reset_task;
        struct work_struct adminq_task;
+       struct work_struct finish_config;
        struct delayed_work client_task;
        wait_queue_head_t down_waitqueue;
+       wait_queue_head_t reset_waitqueue;
        wait_queue_head_t vc_waitqueue;
        struct iavf_q_vector *q_vectors;
        struct list_head vlan_filter_list;
@@ -518,8 +520,9 @@ int iavf_up(struct iavf_adapter *adapter);
 void iavf_down(struct iavf_adapter *adapter);
 int iavf_process_config(struct iavf_adapter *adapter);
 int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
-void iavf_schedule_reset(struct iavf_adapter *adapter);
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
 void iavf_schedule_request_stats(struct iavf_adapter *adapter);
+void iavf_schedule_finish_config(struct iavf_adapter *adapter);
 void iavf_reset(struct iavf_adapter *adapter);
 void iavf_set_ethtool_ops(struct net_device *netdev);
 void iavf_update_stats(struct iavf_adapter *adapter);
@@ -582,4 +585,5 @@ void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter);
 void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter);
 struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
                                        const u8 *macaddr);
+int iavf_wait_for_reset(struct iavf_adapter *adapter);
 #endif /* _IAVF_H_ */
index 6f171d1..2f47cfa 100644 (file)
@@ -484,6 +484,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 orig_flags, new_flags, changed_flags;
+       int ret = 0;
        u32 i;
 
        orig_flags = READ_ONCE(adapter->flags);
@@ -531,12 +532,14 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
        /* issue a reset to force legacy-rx change to take effect */
        if (changed_flags & IAVF_FLAG_LEGACY_RX) {
                if (netif_running(netdev)) {
-                       adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-                       queue_work(adapter->wq, &adapter->reset_task);
+                       iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+                       ret = iavf_wait_for_reset(adapter);
+                       if (ret)
+                               netdev_warn(netdev, "Changing private flags timeout or interrupted waiting for reset");
                }
        }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -627,6 +630,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 new_rx_count, new_tx_count;
+       int ret = 0;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
@@ -671,11 +675,13 @@ static int iavf_set_ringparam(struct net_device *netdev,
        }
 
        if (netif_running(netdev)) {
-               adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(adapter->wq, &adapter->reset_task);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+               ret = iavf_wait_for_reset(adapter);
+               if (ret)
+                       netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");
        }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -1830,7 +1836,7 @@ static int iavf_set_channels(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 num_req = ch->combined_count;
-       int i;
+       int ret = 0;
 
        if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
            adapter->num_tc) {
@@ -1852,22 +1858,13 @@ static int iavf_set_channels(struct net_device *netdev,
 
        adapter->num_req_queues = num_req;
        adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
-       iavf_schedule_reset(adapter);
+       iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 
-       /* wait for the reset is done */
-       for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) {
-               msleep(IAVF_RESET_WAIT_MS);
-               if (adapter->flags & IAVF_FLAG_RESET_PENDING)
-                       continue;
-               break;
-       }
-       if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {
-               adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
-               adapter->num_active_queues = num_req;
-               return -EOPNOTSUPP;
-       }
+       ret = iavf_wait_for_reset(adapter);
+       if (ret)
+               netdev_warn(netdev, "Changing channel count timeout or interrupted waiting for reset");
 
-       return 0;
+       return ret;
 }
 
 /**
index a483eb1..9610ca7 100644 (file)
@@ -167,6 +167,45 @@ static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev)
 }
 
 /**
+ * iavf_is_reset_in_progress - Check if a reset is in progress
+ * @adapter: board private structure
+ */
+static bool iavf_is_reset_in_progress(struct iavf_adapter *adapter)
+{
+       if (adapter->state == __IAVF_RESETTING ||
+           adapter->flags & (IAVF_FLAG_RESET_PENDING |
+                             IAVF_FLAG_RESET_NEEDED))
+               return true;
+
+       return false;
+}
+
+/**
+ * iavf_wait_for_reset - Wait for reset to finish.
+ * @adapter: board private structure
+ *
+ * Returns 0 if reset finished successfully, negative on timeout or interrupt.
+ */
+int iavf_wait_for_reset(struct iavf_adapter *adapter)
+{
+       int ret = wait_event_interruptible_timeout(adapter->reset_waitqueue,
+                                       !iavf_is_reset_in_progress(adapter),
+                                       msecs_to_jiffies(5000));
+
+       /* If ret < 0 then it means wait was interrupted.
+        * If ret == 0 then it means we got a timeout while waiting
+        * for reset to finish.
+        * If ret > 0 it means reset has finished.
+        */
+       if (ret > 0)
+               return 0;
+       else if (ret < 0)
+               return -EINTR;
+       else
+               return -EBUSY;
+}
+
+/**
  * iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
  * @hw:   pointer to the HW structure
  * @mem:  ptr to mem struct to fill out
@@ -262,12 +301,14 @@ static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
 /**
  * iavf_schedule_reset - Set the flags and schedule a reset event
  * @adapter: board private structure
+ * @flags: IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
  **/
-void iavf_schedule_reset(struct iavf_adapter *adapter)
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
 {
-       if (!(adapter->flags &
-             (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
-               adapter->flags |= IAVF_FLAG_RESET_NEEDED;
+       if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
+           !(adapter->flags &
+           (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
+               adapter->flags |= flags;
                queue_work(adapter->wq, &adapter->reset_task);
        }
 }
@@ -295,7 +336,7 @@ static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
        adapter->tx_timeout_count++;
-       iavf_schedule_reset(adapter);
+       iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 }
 
 /**
@@ -1651,10 +1692,10 @@ static int iavf_set_interrupt_capability(struct iavf_adapter *adapter)
                adapter->msix_entries[vector].entry = vector;
 
        err = iavf_acquire_msix_vectors(adapter, v_budget);
+       if (!err)
+               iavf_schedule_finish_config(adapter);
 
 out:
-       netif_set_real_num_rx_queues(adapter->netdev, pairs);
-       netif_set_real_num_tx_queues(adapter->netdev, pairs);
        return err;
 }
 
@@ -1828,19 +1869,16 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter)
 static void iavf_free_q_vectors(struct iavf_adapter *adapter)
 {
        int q_idx, num_q_vectors;
-       int napi_vectors;
 
        if (!adapter->q_vectors)
                return;
 
        num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-       napi_vectors = adapter->num_active_queues;
 
        for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
                struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
 
-               if (q_idx < napi_vectors)
-                       netif_napi_del(&q_vector->napi);
+               netif_napi_del(&q_vector->napi);
        }
        kfree(adapter->q_vectors);
        adapter->q_vectors = NULL;
@@ -1877,9 +1915,7 @@ static int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
                goto err_alloc_queues;
        }
 
-       rtnl_lock();
        err = iavf_set_interrupt_capability(adapter);
-       rtnl_unlock();
        if (err) {
                dev_err(&adapter->pdev->dev,
                        "Unable to setup interrupt capabilities\n");
@@ -1932,15 +1968,16 @@ static void iavf_free_rss(struct iavf_adapter *adapter)
 /**
  * iavf_reinit_interrupt_scheme - Reallocate queues and vectors
  * @adapter: board private structure
+ * @running: true if adapter->state == __IAVF_RUNNING
  *
  * Returns 0 on success, negative on failure
  **/
-static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
+static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter, bool running)
 {
        struct net_device *netdev = adapter->netdev;
        int err;
 
-       if (netif_running(netdev))
+       if (running)
                iavf_free_traffic_irqs(adapter);
        iavf_free_misc_irq(adapter);
        iavf_reset_interrupt_capability(adapter);
@@ -1965,6 +2002,78 @@ err:
 }
 
 /**
+ * iavf_finish_config - do all netdev work that needs RTNL
+ * @work: our work_struct
+ *
+ * Do work that needs both RTNL and crit_lock.
+ **/
+static void iavf_finish_config(struct work_struct *work)
+{
+       struct iavf_adapter *adapter;
+       int pairs, err;
+
+       adapter = container_of(work, struct iavf_adapter, finish_config);
+
+       /* Always take RTNL first to prevent circular lock dependency */
+       rtnl_lock();
+       mutex_lock(&adapter->crit_lock);
+
+       if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
+           adapter->netdev_registered &&
+           !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
+               netdev_update_features(adapter->netdev);
+               adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
+       }
+
+       switch (adapter->state) {
+       case __IAVF_DOWN:
+               if (!adapter->netdev_registered) {
+                       err = register_netdevice(adapter->netdev);
+                       if (err) {
+                               dev_err(&adapter->pdev->dev, "Unable to register netdev (%d)\n",
+                                       err);
+
+                               /* go back and try again.*/
+                               iavf_free_rss(adapter);
+                               iavf_free_misc_irq(adapter);
+                               iavf_reset_interrupt_capability(adapter);
+                               iavf_change_state(adapter,
+                                                 __IAVF_INIT_CONFIG_ADAPTER);
+                               goto out;
+                       }
+                       adapter->netdev_registered = true;
+               }
+
+               /* Set the real number of queues when reset occurs while
+                * state == __IAVF_DOWN
+                */
+               fallthrough;
+       case __IAVF_RUNNING:
+               pairs = adapter->num_active_queues;
+               netif_set_real_num_rx_queues(adapter->netdev, pairs);
+               netif_set_real_num_tx_queues(adapter->netdev, pairs);
+               break;
+
+       default:
+               break;
+       }
+
+out:
+       mutex_unlock(&adapter->crit_lock);
+       rtnl_unlock();
+}
+
+/**
+ * iavf_schedule_finish_config - Set the flags and schedule a reset event
+ * @adapter: board private structure
+ **/
+void iavf_schedule_finish_config(struct iavf_adapter *adapter)
+{
+       if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
+               queue_work(adapter->wq, &adapter->finish_config);
+}
+
+/**
  * iavf_process_aq_command - process aq_required flags
  * and sends aq command
  * @adapter: pointer to iavf adapter structure
@@ -2371,7 +2480,7 @@ int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter)
                        adapter->vsi_res->num_queue_pairs);
                adapter->flags |= IAVF_FLAG_REINIT_MSIX_NEEDED;
                adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
-               iavf_schedule_reset(adapter);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 
                return -EAGAIN;
        }
@@ -2601,22 +2710,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 
        netif_carrier_off(netdev);
        adapter->link_up = false;
-
-       /* set the semaphore to prevent any callbacks after device registration
-        * up to time when state of driver will be set to __IAVF_DOWN
-        */
-       rtnl_lock();
-       if (!adapter->netdev_registered) {
-               err = register_netdevice(netdev);
-               if (err) {
-                       rtnl_unlock();
-                       goto err_register;
-               }
-       }
-
-       adapter->netdev_registered = true;
-
        netif_tx_stop_all_queues(netdev);
+
        if (CLIENT_ALLOWED(adapter)) {
                err = iavf_lan_add_device(adapter);
                if (err)
@@ -2629,7 +2724,6 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 
        iavf_change_state(adapter, __IAVF_DOWN);
        set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
-       rtnl_unlock();
 
        iavf_misc_irq_enable(adapter);
        wake_up(&adapter->down_waitqueue);
@@ -2649,10 +2743,11 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
                /* request initial VLAN offload settings */
                iavf_set_vlan_offload_features(adapter, 0, netdev->features);
 
+       iavf_schedule_finish_config(adapter);
        return;
+
 err_mem:
        iavf_free_rss(adapter);
-err_register:
        iavf_free_misc_irq(adapter);
 err_sw_init:
        iavf_reset_interrupt_capability(adapter);
@@ -2679,26 +2774,9 @@ static void iavf_watchdog_task(struct work_struct *work)
                goto restart_watchdog;
        }
 
-       if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
-           adapter->netdev_registered &&
-           !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
-           rtnl_trylock()) {
-               netdev_update_features(adapter->netdev);
-               rtnl_unlock();
-               adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
-       }
-
        if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
                iavf_change_state(adapter, __IAVF_COMM_FAILED);
 
-       if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
-               adapter->aq_required = 0;
-               adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-               mutex_unlock(&adapter->crit_lock);
-               queue_work(adapter->wq, &adapter->reset_task);
-               return;
-       }
-
        switch (adapter->state) {
        case __IAVF_STARTUP:
                iavf_startup(adapter);
@@ -2826,11 +2904,10 @@ static void iavf_watchdog_task(struct work_struct *work)
        /* check for hw reset */
        reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
        if (!reg_val) {
-               adapter->flags |= IAVF_FLAG_RESET_PENDING;
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
                dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
-               queue_work(adapter->wq, &adapter->reset_task);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
                mutex_unlock(&adapter->crit_lock);
                queue_delayed_work(adapter->wq,
                                   &adapter->watchdog_task, HZ * 2);
@@ -2940,11 +3017,6 @@ static void iavf_reset_task(struct work_struct *work)
        int i = 0, err;
        bool running;
 
-       /* Detach interface to avoid subsequent NDO callbacks */
-       rtnl_lock();
-       netif_device_detach(netdev);
-       rtnl_unlock();
-
        /* When device is being removed it doesn't make sense to run the reset
         * task, just return in such a case.
         */
@@ -2952,7 +3024,7 @@ static void iavf_reset_task(struct work_struct *work)
                if (adapter->state != __IAVF_REMOVE)
                        queue_work(adapter->wq, &adapter->reset_task);
 
-               goto reset_finish;
+               return;
        }
 
        while (!mutex_trylock(&adapter->client_lock))
@@ -3010,11 +3082,6 @@ static void iavf_reset_task(struct work_struct *work)
                iavf_disable_vf(adapter);
                mutex_unlock(&adapter->client_lock);
                mutex_unlock(&adapter->crit_lock);
-               if (netif_running(netdev)) {
-                       rtnl_lock();
-                       dev_close(netdev);
-                       rtnl_unlock();
-               }
                return; /* Do not attempt to reinit. It's dead, Jim. */
        }
 
@@ -3056,7 +3123,7 @@ continue_reset:
 
        if ((adapter->flags & IAVF_FLAG_REINIT_MSIX_NEEDED) ||
            (adapter->flags & IAVF_FLAG_REINIT_ITR_NEEDED)) {
-               err = iavf_reinit_interrupt_scheme(adapter);
+               err = iavf_reinit_interrupt_scheme(adapter, running);
                if (err)
                        goto reset_err;
        }
@@ -3151,10 +3218,11 @@ continue_reset:
 
        adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
 
+       wake_up(&adapter->reset_waitqueue);
        mutex_unlock(&adapter->client_lock);
        mutex_unlock(&adapter->crit_lock);
 
-       goto reset_finish;
+       return;
 reset_err:
        if (running) {
                set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
@@ -3164,21 +3232,7 @@ reset_err:
 
        mutex_unlock(&adapter->client_lock);
        mutex_unlock(&adapter->crit_lock);
-
-       if (netif_running(netdev)) {
-               /* Close device to ensure that Tx queues will not be started
-                * during netif_device_attach() at the end of the reset task.
-                */
-               rtnl_lock();
-               dev_close(netdev);
-               rtnl_unlock();
-       }
-
        dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
-reset_finish:
-       rtnl_lock();
-       netif_device_attach(netdev);
-       rtnl_unlock();
 }
 
 /**
@@ -3196,9 +3250,6 @@ static void iavf_adminq_task(struct work_struct *work)
        u32 val, oldval;
        u16 pending;
 
-       if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
-               goto out;
-
        if (!mutex_trylock(&adapter->crit_lock)) {
                if (adapter->state == __IAVF_REMOVE)
                        return;
@@ -3207,10 +3258,13 @@ static void iavf_adminq_task(struct work_struct *work)
                goto out;
        }
 
+       if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+               goto unlock;
+
        event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
        event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
        if (!event.msg_buf)
-               goto out;
+               goto unlock;
 
        do {
                ret = iavf_clean_arq_element(hw, &event, &pending);
@@ -3225,11 +3279,8 @@ static void iavf_adminq_task(struct work_struct *work)
                if (pending != 0)
                        memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
        } while (pending);
-       mutex_unlock(&adapter->crit_lock);
 
-       if ((adapter->flags &
-            (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
-           adapter->state == __IAVF_RESETTING)
+       if (iavf_is_reset_in_progress(adapter))
                goto freedom;
 
        /* check for error indications */
@@ -3271,6 +3322,8 @@ static void iavf_adminq_task(struct work_struct *work)
 
 freedom:
        kfree(event.msg_buf);
+unlock:
+       mutex_unlock(&adapter->crit_lock);
 out:
        /* re-enable Admin queue interrupt cause */
        iavf_misc_irq_enable(adapter);
@@ -4315,6 +4368,7 @@ static int iavf_close(struct net_device *netdev)
 static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
+       int ret = 0;
 
        netdev_dbg(netdev, "changing MTU from %d to %d\n",
                   netdev->mtu, new_mtu);
@@ -4325,11 +4379,15 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
        }
 
        if (netif_running(netdev)) {
-               adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(adapter->wq, &adapter->reset_task);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+               ret = iavf_wait_for_reset(adapter);
+               if (ret < 0)
+                       netdev_warn(netdev, "MTU change interrupted waiting for reset");
+               else if (ret)
+                       netdev_warn(netdev, "MTU change timed out waiting for reset");
        }
 
-       return 0;
+       return ret;
 }
 
 #define NETIF_VLAN_OFFLOAD_FEATURES    (NETIF_F_HW_VLAN_CTAG_RX | \
@@ -4922,6 +4980,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        INIT_WORK(&adapter->reset_task, iavf_reset_task);
        INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
+       INIT_WORK(&adapter->finish_config, iavf_finish_config);
        INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
        INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
        queue_delayed_work(adapter->wq, &adapter->watchdog_task,
@@ -4930,6 +4989,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Setup the wait queue for indicating transition to down status */
        init_waitqueue_head(&adapter->down_waitqueue);
 
+       /* Setup the wait queue for indicating transition to running state */
+       init_waitqueue_head(&adapter->reset_waitqueue);
+
        /* Setup the wait queue for indicating virtchannel events */
        init_waitqueue_head(&adapter->vc_waitqueue);
 
@@ -5061,13 +5123,15 @@ static void iavf_remove(struct pci_dev *pdev)
                usleep_range(500, 1000);
        }
        cancel_delayed_work_sync(&adapter->watchdog_task);
+       cancel_work_sync(&adapter->finish_config);
 
+       rtnl_lock();
        if (adapter->netdev_registered) {
-               rtnl_lock();
                unregister_netdevice(netdev);
                adapter->netdev_registered = false;
-               rtnl_unlock();
        }
+       rtnl_unlock();
+
        if (CLIENT_ALLOWED(adapter)) {
                err = iavf_lan_del_device(adapter);
                if (err)
index 7c0578b..be3c007 100644 (file)
@@ -1961,9 +1961,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                case VIRTCHNL_EVENT_RESET_IMPENDING:
                        dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
                        if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
-                               adapter->flags |= IAVF_FLAG_RESET_PENDING;
                                dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
-                               queue_work(adapter->wq, &adapter->reset_task);
+                               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
                        }
                        break;
                default:
@@ -2237,6 +2236,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
 
                iavf_process_config(adapter);
                adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+               iavf_schedule_finish_config(adapter);
 
                iavf_set_queue_vlan_tag_loc(adapter);
 
@@ -2285,6 +2285,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
        case VIRTCHNL_OP_ENABLE_QUEUES:
                /* enable transmits */
                iavf_irq_enable(adapter, true);
+               wake_up(&adapter->reset_waitqueue);
                adapter->flags &= ~IAVF_FLAG_QUEUES_DISABLED;
                break;
        case VIRTCHNL_OP_DISABLE_QUEUES:
index 4a12316..b678bdf 100644 (file)
@@ -800,6 +800,8 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
 
        ice_for_each_q_vector(vsi, v_idx)
                ice_free_q_vector(vsi, v_idx);
+
+       vsi->num_q_vectors = 0;
 }
 
 /**
index 8d5cbbd..ad4d470 100644 (file)
@@ -2681,8 +2681,13 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
 
        ring->rx_max_pending = ICE_MAX_NUM_DESC;
        ring->tx_max_pending = ICE_MAX_NUM_DESC;
-       ring->rx_pending = vsi->rx_rings[0]->count;
-       ring->tx_pending = vsi->tx_rings[0]->count;
+       if (vsi->tx_rings && vsi->rx_rings) {
+               ring->rx_pending = vsi->rx_rings[0]->count;
+               ring->tx_pending = vsi->tx_rings[0]->count;
+       } else {
+               ring->rx_pending = 0;
+               ring->tx_pending = 0;
+       }
 
        /* Rx mini and jumbo rings are not supported */
        ring->rx_mini_max_pending = 0;
@@ -2716,6 +2721,10 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
                return -EINVAL;
        }
 
+       /* Return if there is no rings (device is reloading) */
+       if (!vsi->tx_rings || !vsi->rx_rings)
+               return -EBUSY;
+
        new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE);
        if (new_tx_cnt != ring->tx_pending)
                netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",
index ead6d50..8c6e13f 100644 (file)
@@ -1281,16 +1281,21 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
                                     ICE_FLOW_FLD_OFF_INVAL);
        }
 
-       /* add filter for outer headers */
        fltr_idx = ice_ethtool_flow_to_fltr(fsp->flow_type & ~FLOW_EXT);
+
+       assign_bit(fltr_idx, hw->fdir_perfect_fltr, perfect_filter);
+
+       /* add filter for outer headers */
        ret = ice_fdir_set_hw_fltr_rule(pf, seg, fltr_idx,
                                        ICE_FD_HW_SEG_NON_TUN);
-       if (ret == -EEXIST)
-               /* Rule already exists, free memory and continue */
-               devm_kfree(dev, seg);
-       else if (ret)
+       if (ret == -EEXIST) {
+               /* Rule already exists, free memory and count as success */
+               ret = 0;
+               goto err_exit;
+       } else if (ret) {
                /* could not write filter, free memory */
                goto err_exit;
+       }
 
        /* make tunneled filter HW entries if possible */
        memcpy(&tun_seg[1], seg, sizeof(*seg));
@@ -1305,18 +1310,13 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
                devm_kfree(dev, tun_seg);
        }
 
-       if (perfect_filter)
-               set_bit(fltr_idx, hw->fdir_perfect_fltr);
-       else
-               clear_bit(fltr_idx, hw->fdir_perfect_fltr);
-
        return ret;
 
 err_exit:
        devm_kfree(dev, tun_seg);
        devm_kfree(dev, seg);
 
-       return -EOPNOTSUPP;
+       return ret;
 }
 
 /**
@@ -1914,7 +1914,9 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
        input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
 
        /* input struct is added to the HW filter list */
-       ice_fdir_update_list_entry(pf, input, fsp->location);
+       ret = ice_fdir_update_list_entry(pf, input, fsp->location);
+       if (ret)
+               goto release_lock;
 
        ret = ice_fdir_write_all_fltr(pf, input, true);
        if (ret)
index 00e3afd..0054d7e 100644 (file)
@@ -2972,39 +2972,12 @@ int ice_vsi_release(struct ice_vsi *vsi)
                return -ENODEV;
        pf = vsi->back;
 
-       /* do not unregister while driver is in the reset recovery pending
-        * state. Since reset/rebuild happens through PF service task workqueue,
-        * it's not a good idea to unregister netdev that is associated to the
-        * PF that is running the work queue items currently. This is done to
-        * avoid check_flush_dependency() warning on this wq
-        */
-       if (vsi->netdev && !ice_is_reset_in_progress(pf->state) &&
-           (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state))) {
-               unregister_netdev(vsi->netdev);
-               clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
-       }
-
-       if (vsi->type == ICE_VSI_PF)
-               ice_devlink_destroy_pf_port(pf);
-
        if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
                ice_rss_clean(vsi);
 
        ice_vsi_close(vsi);
        ice_vsi_decfg(vsi);
 
-       if (vsi->netdev) {
-               if (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state)) {
-                       unregister_netdev(vsi->netdev);
-                       clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
-               }
-               if (test_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state)) {
-                       free_netdev(vsi->netdev);
-                       vsi->netdev = NULL;
-                       clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
-               }
-       }
-
        /* retain SW VSI data structure since it is needed to unregister and
         * free VSI netdev when PF is not in reset recovery pending state,\
         * for ex: during rmmod.
index 19a5e7f..f02d444 100644 (file)
@@ -4430,9 +4430,9 @@ static int ice_start_eth(struct ice_vsi *vsi)
        if (err)
                return err;
 
-       rtnl_lock();
        err = ice_vsi_open(vsi);
-       rtnl_unlock();
+       if (err)
+               ice_fltr_remove_all(vsi);
 
        return err;
 }
@@ -4895,6 +4895,7 @@ int ice_load(struct ice_pf *pf)
        params = ice_vsi_to_params(vsi);
        params.flags = ICE_VSI_FLAG_INIT;
 
+       rtnl_lock();
        err = ice_vsi_cfg(vsi, &params);
        if (err)
                goto err_vsi_cfg;
@@ -4902,6 +4903,7 @@ int ice_load(struct ice_pf *pf)
        err = ice_start_eth(ice_get_main_vsi(pf));
        if (err)
                goto err_start_eth;
+       rtnl_unlock();
 
        err = ice_init_rdma(pf);
        if (err)
@@ -4916,9 +4918,11 @@ int ice_load(struct ice_pf *pf)
 
 err_init_rdma:
        ice_vsi_close(ice_get_main_vsi(pf));
+       rtnl_lock();
 err_start_eth:
        ice_vsi_decfg(ice_get_main_vsi(pf));
 err_vsi_cfg:
+       rtnl_unlock();
        ice_deinit_dev(pf);
        return err;
 }
@@ -4931,8 +4935,10 @@ void ice_unload(struct ice_pf *pf)
 {
        ice_deinit_features(pf);
        ice_deinit_rdma(pf);
+       rtnl_lock();
        ice_stop_eth(ice_get_main_vsi(pf));
        ice_vsi_decfg(ice_get_main_vsi(pf));
+       rtnl_unlock();
        ice_deinit_dev(pf);
 }
 
index 9f93f0f..bdeb367 100644 (file)
@@ -316,6 +316,33 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter)
                        igc_clean_tx_ring(adapter->tx_ring[i]);
 }
 
+static void igc_disable_tx_ring_hw(struct igc_ring *ring)
+{
+       struct igc_hw *hw = &ring->q_vector->adapter->hw;
+       u8 idx = ring->reg_idx;
+       u32 txdctl;
+
+       txdctl = rd32(IGC_TXDCTL(idx));
+       txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
+       txdctl |= IGC_TXDCTL_SWFLUSH;
+       wr32(IGC_TXDCTL(idx), txdctl);
+}
+
+/**
+ * igc_disable_all_tx_rings_hw - Disable all transmit queue operation
+ * @adapter: board private structure
+ */
+static void igc_disable_all_tx_rings_hw(struct igc_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+               igc_disable_tx_ring_hw(tx_ring);
+       }
+}
+
 /**
  * igc_setup_tx_resources - allocate Tx resources (Descriptors)
  * @tx_ring: tx descriptor ring (for a specific queue) to setup
@@ -2828,9 +2855,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
        struct netdev_queue *nq = txring_txq(ring);
        union igc_adv_tx_desc *tx_desc = NULL;
        int cpu = smp_processor_id();
-       u16 ntu = ring->next_to_use;
        struct xdp_desc xdp_desc;
-       u16 budget;
+       u16 budget, ntu;
 
        if (!netif_carrier_ok(ring->netdev))
                return;
@@ -2840,6 +2866,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
        /* Avoid transmit queue timeout since we share it with the slow path */
        txq_trans_cond_update(nq);
 
+       ntu = ring->next_to_use;
        budget = igc_desc_unused(ring);
 
        while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
@@ -5058,6 +5085,7 @@ void igc_down(struct igc_adapter *adapter)
        /* clear VLAN promisc flag so VFTA will be updated if necessary */
        adapter->flags &= ~IGC_FLAG_VLAN_PROMISC;
 
+       igc_disable_all_tx_rings_hw(adapter);
        igc_clean_all_tx_rings(adapter);
        igc_clean_all_rx_rings(adapter);
 }
@@ -7290,18 +7318,6 @@ void igc_enable_rx_ring(struct igc_ring *ring)
                igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
 }
 
-static void igc_disable_tx_ring_hw(struct igc_ring *ring)
-{
-       struct igc_hw *hw = &ring->q_vector->adapter->hw;
-       u8 idx = ring->reg_idx;
-       u32 txdctl;
-
-       txdctl = rd32(IGC_TXDCTL(idx));
-       txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
-       txdctl |= IGC_TXDCTL_SWFLUSH;
-       wr32(IGC_TXDCTL(idx), txdctl);
-}
-
 void igc_disable_tx_ring(struct igc_ring *ring)
 {
        igc_disable_tx_ring_hw(ring);
index 1726297..8eb9839 100644 (file)
@@ -8479,7 +8479,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
                struct ixgbe_adapter *adapter = q_vector->adapter;
 
                if (unlikely(skb_tail_pointer(skb) < hdr.network +
-                            VXLAN_HEADROOM))
+                            vxlan_headroom(0)))
                        return;
 
                /* verify the port is recognized as VXLAN */
index 6fe67f3..7e20282 100644 (file)
@@ -218,13 +218,54 @@ void npc_config_secret_key(struct rvu *rvu, int blkaddr)
 
 void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
 {
+       struct npc_mcam_kex_hash *mh = rvu->kpu.mkex_hash;
        struct hw_cap *hwcap = &rvu->hw->cap;
+       u8 intf, ld, hdr_offset, byte_len;
        struct rvu_hwinfo *hw = rvu->hw;
-       u8 intf;
+       u64 cfg;
 
+       /* Check if hardware supports hash extraction */
        if (!hwcap->npc_hash_extract)
                return;
 
+       /* Check if IPv6 source/destination address
+        * should be hash enabled.
+        * Hashing reduces 128bit SIP/DIP fields to 32bit
+        * so that 224 bit X2 key can be used for IPv6 based filters as well,
+        * which in turn results in more number of MCAM entries available for
+        * use.
+        *
+        * Hashing of IPV6 SIP/DIP is enabled in below scenarios
+        * 1. If the silicon variant supports hashing feature
+        * 2. If the number of bytes of IP addr being extracted is 4 bytes ie
+        *    32bit. The assumption here is that if user wants 8bytes of LSB of
+        *    IP addr or full 16 bytes then his intention is not to use 32bit
+        *    hash.
+        */
+       for (intf = 0; intf < hw->npc_intfs; intf++) {
+               for (ld = 0; ld < NPC_MAX_LD; ld++) {
+                       cfg = rvu_read64(rvu, blkaddr,
+                                        NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf,
+                                                                      NPC_LID_LC,
+                                                                      NPC_LT_LC_IP6,
+                                                                      ld));
+                       hdr_offset = FIELD_GET(NPC_HDR_OFFSET, cfg);
+                       byte_len = FIELD_GET(NPC_BYTESM, cfg);
+                       /* Hashing of IPv6 source/destination address should be
+                        * enabled if,
+                        * hdr_offset == 8 (offset of source IPv6 address) or
+                        * hdr_offset == 24 (offset of destination IPv6)
+                        * address) and the number of byte to be
+                        * extracted is 4. As per hardware configuration
+                        * byte_len should be == actual byte_len - 1.
+                        * Hence byte_len is checked against 3 but nor 4.
+                        */
+                       if ((hdr_offset == 8 || hdr_offset == 24) && byte_len == 3)
+                               mh->lid_lt_ld_hash_en[intf][NPC_LID_LC][NPC_LT_LC_IP6][ld] = true;
+               }
+       }
+
+       /* Update hash configuration if the field is hash enabled */
        for (intf = 0; intf < hw->npc_intfs; intf++) {
                npc_program_mkex_hash_rx(rvu, blkaddr, intf);
                npc_program_mkex_hash_tx(rvu, blkaddr, intf);
index a1c3d98..57a0932 100644 (file)
@@ -70,8 +70,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
        [NIX_INTF_RX] = {
                [NPC_LID_LC] = {
                        [NPC_LT_LC_IP6] = {
-                               true,
-                               true,
+                               false,
+                               false,
                        },
                },
        },
@@ -79,8 +79,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
        [NIX_INTF_TX] = {
                [NPC_LID_LC] = {
                        [NPC_LT_LC_IP6] = {
-                               true,
-                               true,
+                               false,
+                               false,
                        },
                },
        },
index 6e2fb24..59b1382 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2022 Marvell.
  */
 
+#include <crypto/skcipher.h>
 #include <linux/rtnetlink.h>
 #include <linux/bitfield.h>
 #include "otx2_common.h"
 #define MCS_TCI_E                      0x08 /* encryption */
 #define MCS_TCI_C                      0x04 /* changed text */
 
+#define CN10K_MAX_HASH_LEN             16
+#define CN10K_MAX_SAK_LEN              32
+
+static int cn10k_ecb_aes_encrypt(struct otx2_nic *pfvf, u8 *sak,
+                                u16 sak_len, u8 *hash)
+{
+       u8 data[CN10K_MAX_HASH_LEN] = { 0 };
+       struct skcipher_request *req = NULL;
+       struct scatterlist sg_src, sg_dst;
+       struct crypto_skcipher *tfm;
+       DECLARE_CRYPTO_WAIT(wait);
+       int err;
+
+       tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
+       if (IS_ERR(tfm)) {
+               dev_err(pfvf->dev, "failed to allocate transform for ecb-aes\n");
+               return PTR_ERR(tfm);
+       }
+
+       req = skcipher_request_alloc(tfm, GFP_KERNEL);
+       if (!req) {
+               dev_err(pfvf->dev, "failed to allocate request for skcipher\n");
+               err = -ENOMEM;
+               goto free_tfm;
+       }
+
+       err = crypto_skcipher_setkey(tfm, sak, sak_len);
+       if (err) {
+               dev_err(pfvf->dev, "failed to set key for skcipher\n");
+               goto free_req;
+       }
+
+       /* build sg list */
+       sg_init_one(&sg_src, data, CN10K_MAX_HASH_LEN);
+       sg_init_one(&sg_dst, hash, CN10K_MAX_HASH_LEN);
+
+       skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
+       skcipher_request_set_crypt(req, &sg_src, &sg_dst,
+                                  CN10K_MAX_HASH_LEN, NULL);
+
+       err = crypto_skcipher_encrypt(req);
+       err = crypto_wait_req(err, &wait);
+
+free_req:
+       skcipher_request_free(req);
+free_tfm:
+       crypto_free_skcipher(tfm);
+       return err;
+}
+
 static struct cn10k_mcs_txsc *cn10k_mcs_get_txsc(struct cn10k_mcs_cfg *cfg,
                                                 struct macsec_secy *secy)
 {
@@ -330,19 +381,53 @@ fail:
        return ret;
 }
 
+static int cn10k_mcs_write_keys(struct otx2_nic *pfvf,
+                               struct macsec_secy *secy,
+                               struct mcs_sa_plcy_write_req *req,
+                               u8 *sak, u8 *salt, ssci_t ssci)
+{
+       u8 hash_rev[CN10K_MAX_HASH_LEN];
+       u8 sak_rev[CN10K_MAX_SAK_LEN];
+       u8 salt_rev[MACSEC_SALT_LEN];
+       u8 hash[CN10K_MAX_HASH_LEN];
+       u32 ssci_63_32;
+       int err, i;
+
+       err = cn10k_ecb_aes_encrypt(pfvf, sak, secy->key_len, hash);
+       if (err) {
+               dev_err(pfvf->dev, "Generating hash using ECB(AES) failed\n");
+               return err;
+       }
+
+       for (i = 0; i < secy->key_len; i++)
+               sak_rev[i] = sak[secy->key_len - 1 - i];
+
+       for (i = 0; i < CN10K_MAX_HASH_LEN; i++)
+               hash_rev[i] = hash[CN10K_MAX_HASH_LEN - 1 - i];
+
+       for (i = 0; i < MACSEC_SALT_LEN; i++)
+               salt_rev[i] = salt[MACSEC_SALT_LEN - 1 - i];
+
+       ssci_63_32 = (__force u32)cpu_to_be32((__force u32)ssci);
+
+       memcpy(&req->plcy[0][0], sak_rev, secy->key_len);
+       memcpy(&req->plcy[0][4], hash_rev, CN10K_MAX_HASH_LEN);
+       memcpy(&req->plcy[0][6], salt_rev, MACSEC_SALT_LEN);
+       req->plcy[0][7] |= (u64)ssci_63_32 << 32;
+
+       return 0;
+}
+
 static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
                                      struct macsec_secy *secy,
                                      struct cn10k_mcs_rxsc *rxsc,
                                      u8 assoc_num, bool sa_in_use)
 {
-       unsigned char *src = rxsc->sa_key[assoc_num];
        struct mcs_sa_plcy_write_req *plcy_req;
-       u8 *salt_p = rxsc->salt[assoc_num];
+       u8 *sak = rxsc->sa_key[assoc_num];
+       u8 *salt = rxsc->salt[assoc_num];
        struct mcs_rx_sc_sa_map *map_req;
        struct mbox *mbox = &pfvf->mbox;
-       u64 ssci_salt_95_64 = 0;
-       u8 reg, key_len;
-       u64 salt_63_0;
        int ret;
 
        mutex_lock(&mbox->lock);
@@ -360,20 +445,10 @@ static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
                goto fail;
        }
 
-       for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
-               memcpy((u8 *)&plcy_req->plcy[0][reg],
-                      (src + reg * 8), 8);
-               reg++;
-       }
-
-       if (secy->xpn) {
-               memcpy((u8 *)&salt_63_0, salt_p, 8);
-               memcpy((u8 *)&ssci_salt_95_64, salt_p + 8, 4);
-               ssci_salt_95_64 |= (__force u64)rxsc->ssci[assoc_num] << 32;
-
-               plcy_req->plcy[0][6] = salt_63_0;
-               plcy_req->plcy[0][7] = ssci_salt_95_64;
-       }
+       ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+                                  salt, rxsc->ssci[assoc_num]);
+       if (ret)
+               goto fail;
 
        plcy_req->sa_index[0] = rxsc->hw_sa_id[assoc_num];
        plcy_req->sa_cnt = 1;
@@ -586,13 +661,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
                                      struct cn10k_mcs_txsc *txsc,
                                      u8 assoc_num)
 {
-       unsigned char *src = txsc->sa_key[assoc_num];
        struct mcs_sa_plcy_write_req *plcy_req;
-       u8 *salt_p = txsc->salt[assoc_num];
+       u8 *sak = txsc->sa_key[assoc_num];
+       u8 *salt = txsc->salt[assoc_num];
        struct mbox *mbox = &pfvf->mbox;
-       u64 ssci_salt_95_64 = 0;
-       u8 reg, key_len;
-       u64 salt_63_0;
        int ret;
 
        mutex_lock(&mbox->lock);
@@ -603,19 +675,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
                goto fail;
        }
 
-       for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
-               memcpy((u8 *)&plcy_req->plcy[0][reg], (src + reg * 8), 8);
-               reg++;
-       }
-
-       if (secy->xpn) {
-               memcpy((u8 *)&salt_63_0, salt_p, 8);
-               memcpy((u8 *)&ssci_salt_95_64, salt_p + 8, 4);
-               ssci_salt_95_64 |= (__force u64)txsc->ssci[assoc_num] << 32;
-
-               plcy_req->plcy[0][6] = salt_63_0;
-               plcy_req->plcy[0][7] = ssci_salt_95_64;
-       }
+       ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+                                  salt, txsc->ssci[assoc_num]);
+       if (ret)
+               goto fail;
 
        plcy_req->plcy[0][8] = assoc_num;
        plcy_req->sa_index[0] = txsc->hw_sa_id[assoc_num];
index fe8ea4e..9551b42 100644 (file)
@@ -1454,8 +1454,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
        if (err)
                goto err_free_npa_lf;
 
-       /* Enable backpressure */
-       otx2_nix_config_bp(pf, true);
+       /* Enable backpressure for CGX mapped PF/VFs */
+       if (!is_otx2_lbkvf(pf->pdev))
+               otx2_nix_config_bp(pf, true);
 
        /* Init Auras and pools used by NIX RQ, for free buffer ptrs */
        err = otx2_rq_aura_pool_init(pf);
index 834c644..2d15342 100644 (file)
@@ -3846,23 +3846,6 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
        return 0;
 }
 
-static int __init mtk_init(struct net_device *dev)
-{
-       struct mtk_mac *mac = netdev_priv(dev);
-       struct mtk_eth *eth = mac->hw;
-       int ret;
-
-       ret = of_get_ethdev_address(mac->of_node, dev);
-       if (ret) {
-               /* If the mac address is invalid, use random mac address */
-               eth_hw_addr_random(dev);
-               dev_err(eth->dev, "generated random MAC address %pM\n",
-                       dev->dev_addr);
-       }
-
-       return 0;
-}
-
 static void mtk_uninit(struct net_device *dev)
 {
        struct mtk_mac *mac = netdev_priv(dev);
@@ -4278,7 +4261,6 @@ static const struct ethtool_ops mtk_ethtool_ops = {
 };
 
 static const struct net_device_ops mtk_netdev_ops = {
-       .ndo_init               = mtk_init,
        .ndo_uninit             = mtk_uninit,
        .ndo_open               = mtk_open,
        .ndo_stop               = mtk_stop,
@@ -4340,6 +4322,17 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
        mac->hw = eth;
        mac->of_node = np;
 
+       err = of_get_ethdev_address(mac->of_node, eth->netdev[id]);
+       if (err == -EPROBE_DEFER)
+               return err;
+
+       if (err) {
+               /* If the mac address is invalid, use random mac address */
+               eth_hw_addr_random(eth->netdev[id]);
+               dev_err(eth->dev, "generated random MAC address %pM\n",
+                       eth->netdev[id]->dev_addr);
+       }
+
        memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
        mac->hwlro_ip_cnt = 0;
 
index 316fe2e..1a97fec 100644 (file)
@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind)
 
                acct = mtk_foe_entry_get_mib(ppe, i, NULL);
 
-               type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
+               type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1);
                seq_printf(m, "%05x %s %7s", i,
                           mtk_foe_entry_state_str(state),
                           mtk_foe_pkt_type_str(type));
index 8e3894c..83a3ce0 100644 (file)
@@ -368,7 +368,8 @@ static bool ocelot_fdma_receive_skb(struct ocelot *ocelot, struct sk_buff *skb)
        if (unlikely(!ndev))
                return false;
 
-       pskb_trim(skb, skb->len - ETH_FCS_LEN);
+       if (pskb_trim(skb, skb->len - ETH_FCS_LEN))
+               return false;
 
        skb->dev = ndev;
        skb->protocol = eth_type_trans(skb, skb->dev);
index 0d80447..d5c688a 100644 (file)
@@ -1260,8 +1260,11 @@ static int emac_tso_csum(struct emac_adapter *adpt,
                if (skb->protocol == htons(ETH_P_IP)) {
                        u32 pkt_len = ((unsigned char *)ip_hdr(skb) - skb->data)
                                       + ntohs(ip_hdr(skb)->tot_len);
-                       if (skb->len > pkt_len)
-                               pskb_trim(skb, pkt_len);
+                       if (skb->len > pkt_len) {
+                               ret = pskb_trim(skb, pkt_len);
+                               if (unlikely(ret))
+                                       return ret;
+                       }
                }
 
                hdr_len = skb_tcp_all_headers(skb);
index 9445f04..5eb50b2 100644 (file)
@@ -623,6 +623,7 @@ struct rtl8169_private {
        int cfg9346_usage_count;
 
        unsigned supports_gmii:1;
+       unsigned aspm_manageable:1;
        dma_addr_t counters_phys_addr;
        struct rtl8169_counters *counters;
        struct rtl8169_tc_offsets tc_offset;
@@ -2746,7 +2747,15 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
        if (tp->mac_version < RTL_GIGA_MAC_VER_32)
                return;
 
-       if (enable) {
+       /* Don't enable ASPM in the chip if OS can't control ASPM */
+       if (enable && tp->aspm_manageable) {
+               /* On these chip versions ASPM can even harm
+                * bus communication of other PCI devices.
+                */
+               if (tp->mac_version == RTL_GIGA_MAC_VER_42 ||
+                   tp->mac_version == RTL_GIGA_MAC_VER_43)
+                       return;
+
                rtl_mod_config5(tp, 0, ASPM_en);
                rtl_mod_config2(tp, 0, ClkReqEn);
 
@@ -4514,10 +4523,6 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
        }
 
        if (napi_schedule_prep(&tp->napi)) {
-               rtl_unlock_config_regs(tp);
-               rtl_hw_aspm_clkreq_enable(tp, false);
-               rtl_lock_config_regs(tp);
-
                rtl_irq_disable(tp);
                __napi_schedule(&tp->napi);
        }
@@ -4577,14 +4582,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
 
        work_done = rtl_rx(dev, tp, budget);
 
-       if (work_done < budget && napi_complete_done(napi, work_done)) {
+       if (work_done < budget && napi_complete_done(napi, work_done))
                rtl_irq_enable(tp);
 
-               rtl_unlock_config_regs(tp);
-               rtl_hw_aspm_clkreq_enable(tp, true);
-               rtl_lock_config_regs(tp);
-       }
-
        return work_done;
 }
 
@@ -5158,6 +5158,16 @@ done:
        rtl_rar_set(tp, mac_addr);
 }
 
+/* register is set if system vendor successfully tested ASPM 1.2 */
+static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
+{
+       if (tp->mac_version >= RTL_GIGA_MAC_VER_61 &&
+           r8168_mac_ocp_read(tp, 0xc0b2) & 0xf)
+               return true;
+
+       return false;
+}
+
 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct rtl8169_private *tp;
@@ -5227,6 +5237,19 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                                     xid);
        tp->mac_version = chipset;
 
+       /* Disable ASPM L1 as that cause random device stop working
+        * problems as well as full system hangs for some PCIe devices users.
+        * Chips from RTL8168h partially have issues with L1.2, but seem
+        * to work fine with L1 and L1.1.
+        */
+       if (rtl_aspm_is_safe(tp))
+               rc = 0;
+       else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
+               rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
+       else
+               rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
+       tp->aspm_manageable = !rc;
+
        tp->dash_type = rtl_check_dash(tp);
 
        tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
index df41eac..03ceb6a 100644 (file)
@@ -240,13 +240,15 @@ void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
 void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
 {
        u32 value = readl(ioaddr + GMAC_CONFIG);
+       u32 old_val = value;
 
        if (enable)
                value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
        else
                value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
 
-       writel(value, ioaddr + GMAC_CONFIG);
+       if (value != old_val)
+               writel(value, ioaddr + GMAC_CONFIG);
 }
 
 void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
index 0c5e783..64bf22c 100644 (file)
@@ -106,23 +106,37 @@ struct cpsw_ale_dev_id {
 
 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 {
-       int idx;
+       int idx, idx2;
+       u32 hi_val = 0;
 
        idx    = start / 32;
+       idx2 = (start + bits - 1) / 32;
+       /* Check if bits to be fetched exceed a word */
+       if (idx != idx2) {
+               idx2 = 2 - idx2; /* flip */
+               hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
+       }
        start -= idx * 32;
        idx    = 2 - idx; /* flip */
-       return (ale_entry[idx] >> start) & BITMASK(bits);
+       return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
 }
 
 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
                                      u32 value)
 {
-       int idx;
+       int idx, idx2;
 
        value &= BITMASK(bits);
-       idx    = start / 32;
+       idx = start / 32;
+       idx2 = (start + bits - 1) / 32;
+       /* Check if bits to be set exceed a word */
+       if (idx != idx2) {
+               idx2 = 2 - idx2; /* flip */
+               ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
+               ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
+       }
        start -= idx * 32;
-       idx    = 2 - idx; /* flip */
+       idx = 2 - idx; /* flip */
        ale_entry[idx] &= ~(BITMASK(bits) << start);
        ale_entry[idx] |=  (value << start);
 }
index 39a9aee..6321178 100644 (file)
@@ -1511,7 +1511,6 @@ static void wx_configure_rx(struct wx *wx)
        psrtype = WX_RDB_PL_CFG_L4HDR |
                  WX_RDB_PL_CFG_L3HDR |
                  WX_RDB_PL_CFG_L2HDR |
-                 WX_RDB_PL_CFG_TUN_TUNHDR |
                  WX_RDB_PL_CFG_TUN_TUNHDR;
        wr32(wx, WX_RDB_PL_CFG(0), psrtype);
 
index f0529c3..7b637bb 100644 (file)
@@ -273,16 +273,15 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
        if (ret)
                return ret;
 
-       ret = ipa_filter_reset_table(ipa, true, false, modem);
-       if (ret)
+       ret = ipa_filter_reset_table(ipa, false, true, modem);
+       if (ret || !ipa_table_hash_support(ipa))
                return ret;
 
-       ret = ipa_filter_reset_table(ipa, false, true, modem);
+       ret = ipa_filter_reset_table(ipa, true, false, modem);
        if (ret)
                return ret;
-       ret = ipa_filter_reset_table(ipa, true, true, modem);
 
-       return ret;
+       return ipa_filter_reset_table(ipa, true, true, modem);
 }
 
 /* The AP routes and modem routes are each contiguous within the
@@ -291,12 +290,13 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
  * */
 static int ipa_route_reset(struct ipa *ipa, bool modem)
 {
+       bool hash_support = ipa_table_hash_support(ipa);
        u32 modem_route_count = ipa->modem_route_count;
        struct gsi_trans *trans;
        u16 first;
        u16 count;
 
-       trans = ipa_cmd_trans_alloc(ipa, 4);
+       trans = ipa_cmd_trans_alloc(ipa, hash_support ? 4 : 2);
        if (!trans) {
                dev_err(&ipa->pdev->dev,
                        "no transaction for %s route reset\n",
@@ -313,10 +313,12 @@ static int ipa_route_reset(struct ipa *ipa, bool modem)
        }
 
        ipa_table_reset_add(trans, false, false, false, first, count);
-       ipa_table_reset_add(trans, false, true, false, first, count);
-
        ipa_table_reset_add(trans, false, false, true, first, count);
-       ipa_table_reset_add(trans, false, true, true, first, count);
+
+       if (hash_support) {
+               ipa_table_reset_add(trans, false, true, false, first, count);
+               ipa_table_reset_add(trans, false, true, true, first, count);
+       }
 
        gsi_trans_commit_wait(trans);
 
index 4a53deb..ed90816 100644 (file)
@@ -1746,6 +1746,7 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
        [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
        [IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 },
        [IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT },
+       [IFLA_MACVLAN_BC_CUTOFF] = { .type = NLA_S32 },
 };
 
 int macvlan_link_register(struct rtnl_link_ops *ops)
index 55d9d7a..d4bb90d 100644 (file)
@@ -328,6 +328,13 @@ static int mv3310_power_up(struct phy_device *phydev)
        ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
                                 MV_V2_PORT_CTRL_PWRDOWN);
 
+       /* Sometimes, the power down bit doesn't clear immediately, and
+        * a read of this register causes the bit not to clear. Delay
+        * 100us to allow the PHY to come out of power down mode before
+        * the next access.
+        */
+       udelay(100);
+
        if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
            priv->firmware_ver < 0x00030000)
                return ret;
index 0c2014a..61921d4 100644 (file)
@@ -3451,23 +3451,30 @@ static int __init phy_init(void)
 {
        int rc;
 
+       ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
+
        rc = mdio_bus_init();
        if (rc)
-               return rc;
+               goto err_ethtool_phy_ops;
 
-       ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
        features_init();
 
        rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
        if (rc)
-               goto err_c45;
+               goto err_mdio_bus;
 
        rc = phy_driver_register(&genphy_driver, THIS_MODULE);
-       if (rc) {
-               phy_driver_unregister(&genphy_c45_driver);
+       if (rc)
+               goto err_c45;
+
+       return 0;
+
 err_c45:
-               mdio_bus_exit();
-       }
+       phy_driver_unregister(&genphy_c45_driver);
+err_mdio_bus:
+       mdio_bus_exit();
+err_ethtool_phy_ops:
+       ethtool_set_ethtool_phy_ops(NULL);
 
        return rc;
 }
index 555b0b1..d3dc225 100644 (file)
@@ -2135,6 +2135,15 @@ static void team_setup_by_port(struct net_device *dev,
        dev->mtu = port_dev->mtu;
        memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
        eth_hw_addr_inherit(dev, port_dev);
+
+       if (port_dev->flags & IFF_POINTOPOINT) {
+               dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+               dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+       } else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) ==
+                   (IFF_BROADCAST | IFF_MULTICAST)) {
+               dev->flags |= (IFF_BROADCAST | IFF_MULTICAST);
+               dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP);
+       }
 }
 
 static int team_dev_type_check_change(struct net_device *dev,
index 283ffdd..2d14b0d 100644 (file)
@@ -1775,6 +1775,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        } else if (!info->in || !info->out)
                status = usbnet_get_endpoints (dev, udev);
        else {
+               u8 ep_addrs[3] = {
+                       info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0
+               };
+
                dev->in = usb_rcvbulkpipe (xdev, info->in);
                dev->out = usb_sndbulkpipe (xdev, info->out);
                if (!(info->flags & FLAG_NO_SETINT))
@@ -1784,6 +1788,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
                else
                        status = 0;
 
+               if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs))
+                       status = -EINVAL;
        }
        if (status >= 0 && dev->status)
                status = init_status (dev, udev);
index 0db14f6..1270c8d 100644 (file)
@@ -4219,6 +4219,8 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->has_rss || vi->has_rss_hash_report)
                virtnet_init_default_rss(vi);
 
+       _virtnet_set_queues(vi, vi->curr_queue_pairs);
+
        /* serialize netdev register + virtio_device_ready() with ndo_open() */
        rtnl_lock();
 
@@ -4257,8 +4259,6 @@ static int virtnet_probe(struct virtio_device *vdev)
                goto free_unregister_netdev;
        }
 
-       virtnet_set_queues(vi, vi->curr_queue_pairs);
-
        /* Assume link up if device can't report link status,
           otherwise get link status from config. */
        netif_carrier_off(dev);
index bdb3a76..6043e63 100644 (file)
@@ -664,7 +664,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
        skb->protocol = htons(ETH_P_IPV6);
        skb->dev = dev;
 
-       rcu_read_lock_bh();
+       rcu_read_lock();
        nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
        neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
        if (unlikely(!neigh))
@@ -672,10 +672,10 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
        if (!IS_ERR(neigh)) {
                sock_confirm_neigh(skb, neigh);
                ret = neigh_output(neigh, skb, false);
-               rcu_read_unlock_bh();
+               rcu_read_unlock();
                return ret;
        }
-       rcu_read_unlock_bh();
+       rcu_read_unlock();
 
        IP6_INC_STATS(dev_net(dst->dev),
                      ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -889,7 +889,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
                }
        }
 
-       rcu_read_lock_bh();
+       rcu_read_lock();
 
        neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
        if (!IS_ERR(neigh)) {
@@ -898,11 +898,11 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
                sock_confirm_neigh(skb, neigh);
                /* if crossing protocols, can not use the cached header */
                ret = neigh_output(neigh, skb, is_v6gw);
-               rcu_read_unlock_bh();
+               rcu_read_unlock();
                return ret;
        }
 
-       rcu_read_unlock_bh();
+       rcu_read_unlock();
        vrf_tx_error(skb->dev, skb);
        return -EINVAL;
 }
index 7874454..c9a9373 100644 (file)
@@ -623,6 +623,32 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
        return 1;
 }
 
+static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
+{
+       struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+
+       /* Need to have Next Protocol set for interfaces in GPE mode. */
+       if (!gpe->np_applied)
+               return false;
+       /* "The initial version is 0. If a receiver does not support the
+        * version indicated it MUST drop the packet.
+        */
+       if (gpe->version != 0)
+               return false;
+       /* "When the O bit is set to 1, the packet is an OAM packet and OAM
+        * processing MUST occur." However, we don't implement OAM
+        * processing, thus drop the packet.
+        */
+       if (gpe->oam_flag)
+               return false;
+
+       *protocol = tun_p_to_eth_p(gpe->next_protocol);
+       if (!*protocol)
+               return false;
+
+       return true;
+}
+
 static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
                                          unsigned int off,
                                          struct vxlanhdr *vh, size_t hdrlen,
@@ -649,26 +675,24 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
        return vh;
 }
 
-static struct sk_buff *vxlan_gro_receive(struct sock *sk,
-                                        struct list_head *head,
-                                        struct sk_buff *skb)
+static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk,
+                                                 struct list_head *head,
+                                                 struct sk_buff *skb,
+                                                 struct gro_remcsum *grc)
 {
-       struct sk_buff *pp = NULL;
        struct sk_buff *p;
        struct vxlanhdr *vh, *vh2;
        unsigned int hlen, off_vx;
-       int flush = 1;
        struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
        __be32 flags;
-       struct gro_remcsum grc;
 
-       skb_gro_remcsum_init(&grc);
+       skb_gro_remcsum_init(grc);
 
        off_vx = skb_gro_offset(skb);
        hlen = off_vx + sizeof(*vh);
        vh = skb_gro_header(skb, hlen, off_vx);
        if (unlikely(!vh))
-               goto out;
+               return NULL;
 
        skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
 
@@ -676,12 +700,12 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
 
        if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
                vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
-                                      vh->vx_vni, &grc,
+                                      vh->vx_vni, grc,
                                       !!(vs->flags &
                                          VXLAN_F_REMCSUM_NOPARTIAL));
 
                if (!vh)
-                       goto out;
+                       return NULL;
        }
 
        skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
@@ -698,12 +722,48 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
                }
        }
 
-       pp = call_gro_receive(eth_gro_receive, head, skb);
-       flush = 0;
+       return vh;
+}
 
-out:
+static struct sk_buff *vxlan_gro_receive(struct sock *sk,
+                                        struct list_head *head,
+                                        struct sk_buff *skb)
+{
+       struct sk_buff *pp = NULL;
+       struct gro_remcsum grc;
+       int flush = 1;
+
+       if (vxlan_gro_prepare_receive(sk, head, skb, &grc)) {
+               pp = call_gro_receive(eth_gro_receive, head, skb);
+               flush = 0;
+       }
        skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
+       return pp;
+}
+
+static struct sk_buff *vxlan_gpe_gro_receive(struct sock *sk,
+                                            struct list_head *head,
+                                            struct sk_buff *skb)
+{
+       const struct packet_offload *ptype;
+       struct sk_buff *pp = NULL;
+       struct gro_remcsum grc;
+       struct vxlanhdr *vh;
+       __be16 protocol;
+       int flush = 1;
 
+       vh = vxlan_gro_prepare_receive(sk, head, skb, &grc);
+       if (vh) {
+               if (!vxlan_parse_gpe_proto(vh, &protocol))
+                       goto out;
+               ptype = gro_find_receive_by_type(protocol);
+               if (!ptype)
+                       goto out;
+               pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+               flush = 0;
+       }
+out:
+       skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
        return pp;
 }
 
@@ -715,6 +775,21 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
        return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
 }
 
+static int vxlan_gpe_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+       struct vxlanhdr *vh = (struct vxlanhdr *)(skb->data + nhoff);
+       const struct packet_offload *ptype;
+       int err = -ENOSYS;
+       __be16 protocol;
+
+       if (!vxlan_parse_gpe_proto(vh, &protocol))
+               return err;
+       ptype = gro_find_complete_by_type(protocol);
+       if (ptype)
+               err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
+       return err;
+}
+
 static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
                                         __u16 state, __be32 src_vni,
                                         __u16 ndm_flags)
@@ -1525,35 +1600,6 @@ out:
        unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
 }
 
-static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
-                               __be16 *protocol,
-                               struct sk_buff *skb, u32 vxflags)
-{
-       struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
-
-       /* Need to have Next Protocol set for interfaces in GPE mode. */
-       if (!gpe->np_applied)
-               return false;
-       /* "The initial version is 0. If a receiver does not support the
-        * version indicated it MUST drop the packet.
-        */
-       if (gpe->version != 0)
-               return false;
-       /* "When the O bit is set to 1, the packet is an OAM packet and OAM
-        * processing MUST occur." However, we don't implement OAM
-        * processing, thus drop the packet.
-        */
-       if (gpe->oam_flag)
-               return false;
-
-       *protocol = tun_p_to_eth_p(gpe->next_protocol);
-       if (!*protocol)
-               return false;
-
-       unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
-       return true;
-}
-
 static bool vxlan_set_mac(struct vxlan_dev *vxlan,
                          struct vxlan_sock *vs,
                          struct sk_buff *skb, __be32 vni)
@@ -1655,8 +1701,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
         * used by VXLAN extensions if explicitly requested.
         */
        if (vs->flags & VXLAN_F_GPE) {
-               if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
+               if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
                        goto drop;
+               unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
                raw_proto = true;
        }
 
@@ -2516,7 +2563,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                }
 
                ndst = &rt->dst;
-               err = skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM,
+               err = skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE),
                                            netif_is_any_bridge_port(dev));
                if (err < 0) {
                        goto tx_error;
@@ -2577,7 +2624,8 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                                goto out_unlock;
                }
 
-               err = skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM,
+               err = skb_tunnel_check_pmtu(skb, ndst,
+                                           vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6),
                                            netif_is_any_bridge_port(dev));
                if (err < 0) {
                        goto tx_error;
@@ -2989,14 +3037,12 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
        struct vxlan_rdst *dst = &vxlan->default_dst;
        struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
                                                         dst->remote_ifindex);
-       bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
 
        /* This check is different than dev->max_mtu, because it looks at
         * the lowerdev->mtu, rather than the static dev->max_mtu
         */
        if (lowerdev) {
-               int max_mtu = lowerdev->mtu -
-                             (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+               int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags);
                if (new_mtu > max_mtu)
                        return -EINVAL;
        }
@@ -3379,8 +3425,13 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
        tunnel_cfg.encap_rcv = vxlan_rcv;
        tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
        tunnel_cfg.encap_destroy = NULL;
-       tunnel_cfg.gro_receive = vxlan_gro_receive;
-       tunnel_cfg.gro_complete = vxlan_gro_complete;
+       if (vs->flags & VXLAN_F_GPE) {
+               tunnel_cfg.gro_receive = vxlan_gpe_gro_receive;
+               tunnel_cfg.gro_complete = vxlan_gpe_gro_complete;
+       } else {
+               tunnel_cfg.gro_receive = vxlan_gro_receive;
+               tunnel_cfg.gro_complete = vxlan_gro_complete;
+       }
 
        setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
 
@@ -3644,11 +3695,11 @@ static void vxlan_config_apply(struct net_device *dev,
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_rdst *dst = &vxlan->default_dst;
        unsigned short needed_headroom = ETH_HLEN;
-       bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6);
        int max_mtu = ETH_MAX_MTU;
+       u32 flags = conf->flags;
 
        if (!changelink) {
-               if (conf->flags & VXLAN_F_GPE)
+               if (flags & VXLAN_F_GPE)
                        vxlan_raw_setup(dev);
                else
                        vxlan_ether_setup(dev);
@@ -3673,8 +3724,7 @@ static void vxlan_config_apply(struct net_device *dev,
 
                dev->needed_tailroom = lowerdev->needed_tailroom;
 
-               max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
-                                          VXLAN_HEADROOM);
+               max_mtu = lowerdev->mtu - vxlan_headroom(flags);
                if (max_mtu < ETH_MIN_MTU)
                        max_mtu = ETH_MIN_MTU;
 
@@ -3685,10 +3735,9 @@ static void vxlan_config_apply(struct net_device *dev,
        if (dev->mtu > max_mtu)
                dev->mtu = max_mtu;
 
-       if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
-               needed_headroom += VXLAN6_HEADROOM;
-       else
-               needed_headroom += VXLAN_HEADROOM;
+       if (flags & VXLAN_F_COLLECT_METADATA)
+               flags |= VXLAN_F_IPV6;
+       needed_headroom += vxlan_headroom(flags);
        dev->needed_headroom = needed_headroom;
 
        memcpy(&vxlan->cfg, conf, sizeof(*conf));
index e40f10b..da9826a 100644 (file)
@@ -55,7 +55,7 @@ config OF_FLATTREE
 
 config OF_EARLY_FLATTREE
        bool
-       select DMA_DECLARE_COHERENT if HAS_DMA
+       select DMA_DECLARE_COHERENT if HAS_DMA && HAS_IOMEM
        select OF_FLATTREE
 
 config OF_PROMTREE
index 051e29b..0c3475e 100644 (file)
@@ -552,7 +552,7 @@ static int __init of_platform_default_populate_init(void)
                        if (!of_get_property(node, "linux,opened", NULL) ||
                            !of_get_property(node, "linux,boot-display", NULL))
                                continue;
-                       dev = of_platform_device_create(node, "of-display.0", NULL);
+                       dev = of_platform_device_create(node, "of-display", NULL);
                        of_node_put(node);
                        if (WARN_ON(!dev))
                                return -ENOMEM;
index 15dafe3..6ae6d50 100644 (file)
@@ -184,7 +184,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
                phy_set_drvdata(phy, &priv->ports[i]);
                i++;
 
-               if (i > INNO_PHY_PORT_NUM) {
+               if (i >= INNO_PHY_PORT_NUM) {
                        dev_warn(dev, "Support %d ports in maximum\n", i);
                        of_node_put(child);
                        break;
index 232fd3f..d7024a1 100644 (file)
@@ -169,7 +169,7 @@ static int mtk_dp_phy_probe(struct platform_device *pdev)
 
        regs = *(struct regmap **)dev->platform_data;
        if (!regs)
-               return dev_err_probe(dev, EINVAL,
+               return dev_err_probe(dev, -EINVAL,
                                     "No data passed, requires struct regmap**\n");
 
        dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
index 8aa7251..bbfe11d 100644 (file)
@@ -253,7 +253,7 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw,
        for (i = 0; i < ARRAY_SIZE(txpredivs); i++) {
                ns_hdmipll_ck = 5 * tmds_clk * txposdiv * txpredivs[i];
                if (ns_hdmipll_ck >= 5 * GIGA &&
-                   ns_hdmipll_ck <= 1 * GIGA)
+                   ns_hdmipll_ck <= 12 * GIGA)
                        break;
        }
        if (i == (ARRAY_SIZE(txpredivs) - 1) &&
index 6c237f3..d0319be 100644 (file)
@@ -110,11 +110,13 @@ struct phy_override_seq {
 /**
  * struct qcom_snps_hsphy - snps hs phy attributes
  *
+ * @dev: device structure
+ *
  * @phy: generic phy
  * @base: iomapped memory space for snps hs phy
  *
- * @cfg_ahb_clk: AHB2PHY interface clock
- * @ref_clk: phy reference clock
+ * @num_clks: number of clocks
+ * @clks: array of clocks
  * @phy_reset: phy reset control
  * @vregs: regulator supplies bulk data
  * @phy_initialized: if PHY has been initialized correctly
@@ -122,11 +124,13 @@ struct phy_override_seq {
  * @update_seq_cfg: tuning parameters for phy init
  */
 struct qcom_snps_hsphy {
+       struct device *dev;
+
        struct phy *phy;
        void __iomem *base;
 
-       struct clk *cfg_ahb_clk;
-       struct clk *ref_clk;
+       int num_clks;
+       struct clk_bulk_data *clks;
        struct reset_control *phy_reset;
        struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
 
@@ -135,6 +139,34 @@ struct qcom_snps_hsphy {
        struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
 };
 
+static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
+{
+       struct device *dev = hsphy->dev;
+
+       hsphy->num_clks = 2;
+       hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
+       if (!hsphy->clks)
+               return -ENOMEM;
+
+       /*
+        * TODO: Currently no device tree instantiation of the PHY is using the clock.
+        * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
+        */
+       hsphy->clks[0].id = "cfg_ahb";
+       hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
+       if (IS_ERR(hsphy->clks[0].clk))
+               return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
+                                    "failed to get cfg_ahb clk\n");
+
+       hsphy->clks[1].id = "ref";
+       hsphy->clks[1].clk = devm_clk_get(dev, "ref");
+       if (IS_ERR(hsphy->clks[1].clk))
+               return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
+                                    "failed to get ref clk\n");
+
+       return 0;
+}
+
 static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
                                                u32 mask, u32 val)
 {
@@ -165,22 +197,13 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
                                           0, USB2_AUTO_RESUME);
        }
 
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
        return 0;
 }
 
 static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
 {
-       int ret;
-
        dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
 
-       ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
-       if (ret) {
-               dev_err(&hsphy->phy->dev, "failed to enable cfg ahb clock\n");
-               return ret;
-       }
-
        return 0;
 }
 
@@ -191,8 +214,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
        if (!hsphy->phy_initialized)
                return 0;
 
-       qcom_snps_hsphy_suspend(hsphy);
-       return 0;
+       return qcom_snps_hsphy_suspend(hsphy);
 }
 
 static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
@@ -202,8 +224,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
        if (!hsphy->phy_initialized)
                return 0;
 
-       qcom_snps_hsphy_resume(hsphy);
-       return 0;
+       return qcom_snps_hsphy_resume(hsphy);
 }
 
 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
@@ -374,16 +395,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        if (ret)
                return ret;
 
-       ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
+       ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
        if (ret) {
-               dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+               dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
                goto poweroff_phy;
        }
 
        ret = reset_control_assert(hsphy->phy_reset);
        if (ret) {
                dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
+               goto disable_clks;
        }
 
        usleep_range(100, 150);
@@ -391,7 +412,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        ret = reset_control_deassert(hsphy->phy_reset);
        if (ret) {
                dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
+               goto disable_clks;
        }
 
        qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
@@ -448,8 +469,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
 
        return 0;
 
-disable_ahb_clk:
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
+disable_clks:
+       clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
 poweroff_phy:
        regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
 
@@ -461,7 +482,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
        struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
 
        reset_control_assert(hsphy->phy_reset);
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
+       clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
        regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
        hsphy->phy_initialized = false;
 
@@ -554,14 +575,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
        if (!hsphy)
                return -ENOMEM;
 
+       hsphy->dev = dev;
+
        hsphy->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(hsphy->base))
                return PTR_ERR(hsphy->base);
 
-       hsphy->ref_clk = devm_clk_get(dev, "ref");
-       if (IS_ERR(hsphy->ref_clk))
-               return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk),
-                                    "failed to get ref clk\n");
+       ret = qcom_snps_hsphy_clk_init(hsphy);
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to initialize clocks\n");
 
        hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
        if (IS_ERR(hsphy->phy_reset)) {
index 362e7c0..ad70246 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/dmi.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
-#include <linux/slab.h>
 
 #include "pmc.h"
 
@@ -135,12 +134,10 @@ static const struct dmi_system_id fwbug_list[] = {
  */
 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
 {
-       struct resource *res;
        void __iomem *addr;
        u8 val;
 
-       res = request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80");
-       if (!res)
+       if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
                return;
 
        addr = ioremap(s2idle_bug_mmio, 1);
@@ -152,8 +149,7 @@ static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
 
        iounmap(addr);
 cleanup_resource:
-       release_resource(res);
-       kfree(res);
+       release_mem_region(s2idle_bug_mmio, 1);
 }
 
 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
index 081e84e..3fc5e45 100644 (file)
@@ -106,6 +106,27 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
                                                                         data, sizeof(*data));
 }
 
+int apmf_os_power_slider_update(struct amd_pmf_dev *pdev, u8 event)
+{
+       struct os_power_slider args;
+       struct acpi_buffer params;
+       union acpi_object *info;
+       int err = 0;
+
+       args.size = sizeof(args);
+       args.slider_event = event;
+
+       params.length = sizeof(args);
+       params.pointer = (void *)&args;
+
+       info = apmf_if_call(pdev, APMF_FUNC_OS_POWER_SLIDER_UPDATE, &params);
+       if (!info)
+               err = -EIO;
+
+       kfree(info);
+       return err;
+}
+
 static void apmf_sbios_heartbeat_notify(struct work_struct *work)
 {
        struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, heart_beat.work);
@@ -289,7 +310,7 @@ int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
 
        ret = apmf_get_system_params(pmf_dev);
        if (ret) {
-               dev_err(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
+               dev_dbg(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
                goto out;
        }
 
index d873255..57bf1a9 100644 (file)
@@ -72,7 +72,11 @@ static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long
                        return NOTIFY_DONE;
        }
 
-       amd_pmf_set_sps_power_limits(pmf);
+       if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+               amd_pmf_set_sps_power_limits(pmf);
+
+       if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE))
+               amd_pmf_power_slider_update_event(pmf);
 
        return NOTIFY_OK;
 }
@@ -297,7 +301,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
        int ret;
 
        /* Enable Static Slider */
-       if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+       if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) ||
+           is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
                amd_pmf_init_sps(dev);
                dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
                power_supply_reg_notifier(&dev->pwr_src_notifier);
index 06c30cd..deba88e 100644 (file)
@@ -21,6 +21,7 @@
 #define APMF_FUNC_SBIOS_HEARTBEAT                      4
 #define APMF_FUNC_AUTO_MODE                                    5
 #define APMF_FUNC_SET_FAN_IDX                          7
+#define APMF_FUNC_OS_POWER_SLIDER_UPDATE               8
 #define APMF_FUNC_STATIC_SLIDER_GRANULAR       9
 #define APMF_FUNC_DYN_SLIDER_AC                                11
 #define APMF_FUNC_DYN_SLIDER_DC                                12
 #define GET_STT_LIMIT_APU      0x20
 #define GET_STT_LIMIT_HS2      0x21
 
+/* OS slider update notification */
+#define DC_BEST_PERF           0
+#define DC_BETTER_PERF         1
+#define DC_BATTERY_SAVER       3
+#define AC_BEST_PERF           4
+#define AC_BETTER_PERF         5
+#define AC_BETTER_BATTERY      6
+
 /* Fan Index for Auto Mode */
 #define FAN_INDEX_AUTO         0xFFFFFFFF
 
@@ -193,6 +202,11 @@ struct amd_pmf_static_slider_granular {
        struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX][POWER_MODE_MAX];
 };
 
+struct os_power_slider {
+       u16 size;
+       u8 slider_event;
+} __packed;
+
 struct fan_table_control {
        bool manual;
        unsigned long fan_id;
@@ -383,6 +397,7 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32
 int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
 int amd_pmf_get_power_source(void);
 int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
+int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
 
 /* SPS Layer */
 int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
@@ -393,6 +408,7 @@ void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
 int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
                                    struct apmf_static_slider_granular_output *output);
 bool is_pprof_balanced(struct amd_pmf_dev *pmf);
+int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
 
 
 int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
index 445ff05..ab69d51 100644 (file)
@@ -174,14 +174,77 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
        return mode;
 }
 
+int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
+{
+       u8 mode, flag = 0;
+       int src;
+
+       mode = amd_pmf_get_pprof_modes(dev);
+       if (mode < 0)
+               return mode;
+
+       src = amd_pmf_get_power_source();
+
+       if (src == POWER_SOURCE_AC) {
+               switch (mode) {
+               case POWER_MODE_PERFORMANCE:
+                       flag |= BIT(AC_BEST_PERF);
+                       break;
+               case POWER_MODE_BALANCED_POWER:
+                       flag |= BIT(AC_BETTER_PERF);
+                       break;
+               case POWER_MODE_POWER_SAVER:
+                       flag |= BIT(AC_BETTER_BATTERY);
+                       break;
+               default:
+                       dev_err(dev->dev, "unsupported platform profile\n");
+                       return -EOPNOTSUPP;
+               }
+
+       } else if (src == POWER_SOURCE_DC) {
+               switch (mode) {
+               case POWER_MODE_PERFORMANCE:
+                       flag |= BIT(DC_BEST_PERF);
+                       break;
+               case POWER_MODE_BALANCED_POWER:
+                       flag |= BIT(DC_BETTER_PERF);
+                       break;
+               case POWER_MODE_POWER_SAVER:
+                       flag |= BIT(DC_BATTERY_SAVER);
+                       break;
+               default:
+                       dev_err(dev->dev, "unsupported platform profile\n");
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       apmf_os_power_slider_update(dev, flag);
+
+       return 0;
+}
+
 static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
                               enum platform_profile_option profile)
 {
        struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+       int ret = 0;
 
        pmf->current_profile = profile;
 
-       return amd_pmf_set_sps_power_limits(pmf);
+       /* Notify EC about the slider position change */
+       if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
+               ret = amd_pmf_power_slider_update_event(pmf);
+               if (ret)
+                       return ret;
+       }
+
+       if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+               ret = amd_pmf_set_sps_power_limits(pmf);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
 }
 
 int amd_pmf_init_sps(struct amd_pmf_dev *dev)
@@ -189,10 +252,13 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
        int err;
 
        dev->current_profile = PLATFORM_PROFILE_BALANCED;
-       amd_pmf_load_defaults_sps(dev);
 
-       /* update SPS balanced power mode thermals */
-       amd_pmf_set_sps_power_limits(dev);
+       if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+               amd_pmf_load_defaults_sps(dev);
+
+               /* update SPS balanced power mode thermals */
+               amd_pmf_set_sps_power_limits(dev);
+       }
 
        dev->pprof.profile_get = amd_pmf_profile_get;
        dev->pprof.profile_set = amd_pmf_profile_set;
index 1038dfd..8bef66a 100644 (file)
@@ -738,13 +738,23 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       u32 cmd, mode, r, g,  b,  speed;
+       u32 cmd, mode, r, g, b, speed;
        int err;
 
        if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
                return -EINVAL;
 
-       cmd = !!cmd;
+       /* B3 is set and B4 is save to BIOS */
+       switch (cmd) {
+       case 0:
+               cmd = 0xb3;
+               break;
+       case 1:
+               cmd = 0xb4;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        /* These are the known usable modes across all TUF/ROG */
        if (mode >= 12 || mode == 9)
index 70e5c4c..0ef1c46 100644 (file)
@@ -85,6 +85,8 @@ static const struct key_entry huawei_wmi_keymap[] = {
        { KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } },
        { KE_IGNORE, 0x294, { KEY_KBDILLUMUP } },
        { KE_IGNORE, 0x295, { KEY_KBDILLUMUP } },
+       // Ignore Ambient Light Sensoring
+       { KE_KEY,    0x2c1, { KEY_RESERVED } },
        { KE_END,        0 }
 };
 
index 5632bd3..7457ca2 100644 (file)
@@ -150,6 +150,12 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite Dragonfly G2 Notebook PC"),
+               },
+       },
        { }
 };
 
@@ -620,7 +626,7 @@ static bool button_array_present(struct platform_device *device)
 static int intel_hid_probe(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
-       unsigned long long mode;
+       unsigned long long mode, dummy;
        struct intel_hid_priv *priv;
        acpi_status status;
        int err;
@@ -692,18 +698,15 @@ static int intel_hid_probe(struct platform_device *device)
        if (err)
                goto err_remove_notify;
 
-       if (priv->array) {
-               unsigned long long dummy;
+       intel_button_array_enable(&device->dev, true);
 
-               intel_button_array_enable(&device->dev, true);
-
-               /* Call button load method to enable HID power button */
-               if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
-                                              &dummy)) {
-                       dev_warn(&device->dev,
-                                "failed to enable HID power button\n");
-               }
-       }
+       /*
+        * Call button load method to enable HID power button
+        * Always do this since it activates events on some devices without
+        * a button array too.
+        */
+       if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
+               dev_warn(&device->dev, "failed to enable HID power button\n");
 
        device_init_wakeup(&device->dev, true);
        /*
index 6b18ec5..f4c6c36 100644 (file)
@@ -208,7 +208,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
                return -EINVAL;
 
        if (quirks->ec_read_only)
-               return -EOPNOTSUPP;
+               return 0;
 
        /* read current device state */
        result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
@@ -838,15 +838,15 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
 static void msi_init_rfkill(struct work_struct *ignored)
 {
        if (rfk_wlan) {
-               rfkill_set_sw_state(rfk_wlan, !wlan_s);
+               msi_rfkill_set_state(rfk_wlan, !wlan_s);
                rfkill_wlan_set(NULL, !wlan_s);
        }
        if (rfk_bluetooth) {
-               rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
+               msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s);
                rfkill_bluetooth_set(NULL, !bluetooth_s);
        }
        if (rfk_threeg) {
-               rfkill_set_sw_state(rfk_threeg, !threeg_s);
+               msi_rfkill_set_state(rfk_threeg, !threeg_s);
                rfkill_threeg_set(NULL, !threeg_s);
        }
 }
index f3dcbdd..2c2abf6 100644 (file)
@@ -21,6 +21,7 @@
 #define IRQ_RESOURCE_NONE      0
 #define IRQ_RESOURCE_GPIO      1
 #define IRQ_RESOURCE_APIC      2
+#define IRQ_RESOURCE_AUTO   3
 
 enum smi_bus_type {
        SMI_I2C,
@@ -52,6 +53,18 @@ static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
        int ret;
 
        switch (inst->flags & IRQ_RESOURCE_TYPE) {
+       case IRQ_RESOURCE_AUTO:
+               ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
+               if (ret > 0) {
+                       dev_dbg(&pdev->dev, "Using gpio irq\n");
+                       break;
+               }
+               ret = platform_get_irq(pdev, inst->irq_idx);
+               if (ret > 0) {
+                       dev_dbg(&pdev->dev, "Using platform irq\n");
+                       break;
+               }
+               break;
        case IRQ_RESOURCE_GPIO:
                ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
                break;
@@ -307,10 +320,10 @@ static const struct smi_node int3515_data = {
 
 static const struct smi_node cs35l41_hda = {
        .instances = {
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
                {}
        },
        .bus_type = SMI_AUTO_DETECT,
index 52d1ce8..7934688 100644 (file)
@@ -719,12 +719,12 @@ static ssize_t cert_to_password_store(struct kobject *kobj,
        /* Format: 'Password,Signature' */
        auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature);
        if (!auth_str) {
-               kfree(passwd);
+               kfree_sensitive(passwd);
                return -ENOMEM;
        }
        ret = tlmi_simple_call(LENOVO_CERT_TO_PASSWORD_GUID, auth_str);
        kfree(auth_str);
-       kfree(passwd);
+       kfree_sensitive(passwd);
 
        return ret ?: count;
 }
index a5b687e..f9301a9 100644 (file)
@@ -27,11 +27,12 @@ struct ts_dmi_data {
 /* NOTE: Please keep all entries sorted alphabetically */
 
 static const struct property_entry archos_101_cesium_educ_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1280),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1850),
-       PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1850),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-archos-101-cesium-educ.fw"),
        { }
 };
index c5dd77b..dfd5ec9 100644 (file)
@@ -778,6 +778,9 @@ static int da9063_check_xvp_constraints(struct regulator_config *config)
        const struct notification_limit *uv_l = &constr->under_voltage_limits;
        const struct notification_limit *ov_l = &constr->over_voltage_limits;
 
+       if (!config->init_data) /* No config in DT, pointers will be invalid */
+               return 0;
+
        /* make sure that only one severity is used to clarify if unchanged, enabled or disabled */
        if ((!!uv_l->prot + !!uv_l->err + !!uv_l->warn) > 1) {
                dev_err(config->dev, "%s: at most one voltage monitoring severity allowed!\n",
index 67fd2ec..e668ff5 100644 (file)
@@ -1101,23 +1101,36 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
                                      struct ica_xcRB *xcrb,
                                      struct ap_message *ap_msg)
 {
-       int rc;
        struct response_type *rtype = ap_msg->private;
        struct {
                struct type6_hdr hdr;
                struct CPRBX cprbx;
                /* ... more data blocks ... */
        } __packed * msg = ap_msg->msg;
-
-       /*
-        * Set the queue's reply buffer length minus 128 byte padding
-        * as reply limit for the card firmware.
-        */
-       msg->hdr.fromcardlen1 = min_t(unsigned int, msg->hdr.fromcardlen1,
-                                     zq->reply.bufsize - 128);
-       if (msg->hdr.fromcardlen2)
-               msg->hdr.fromcardlen2 =
-                       zq->reply.bufsize - msg->hdr.fromcardlen1 - 128;
+       unsigned int max_payload_size;
+       int rc, delta;
+
+       /* calculate maximum payload for this card and msg type */
+       max_payload_size = zq->reply.bufsize - sizeof(struct type86_fmt2_msg);
+
+       /* limit each of the two from fields to the maximum payload size */
+       msg->hdr.fromcardlen1 = min(msg->hdr.fromcardlen1, max_payload_size);
+       msg->hdr.fromcardlen2 = min(msg->hdr.fromcardlen2, max_payload_size);
+
+       /* calculate delta if the sum of both exceeds max payload size */
+       delta = msg->hdr.fromcardlen1 + msg->hdr.fromcardlen2
+               - max_payload_size;
+       if (delta > 0) {
+               /*
+                * Sum exceeds maximum payload size, prune fromcardlen1
+                * (always trust fromcardlen2)
+                */
+               if (delta > msg->hdr.fromcardlen1) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               msg->hdr.fromcardlen1 -= delta;
+       }
 
        init_completion(&rtype->work);
        rc = ap_queue_message(zq->queue, ap_msg);
index 89fa046..0d8afff 100644 (file)
@@ -1497,9 +1497,10 @@ sg_add_device(struct device *cl_dev)
        int error;
        unsigned long iflags;
 
-       error = blk_get_queue(scsidp->request_queue);
-       if (error)
-               return error;
+       if (!blk_get_queue(scsidp->request_queue)) {
+               pr_warn("%s: get scsi_device queue failed\n", __func__);
+               return -ENODEV;
+       }
 
        error = -ENOMEM;
        cdev = cdev_alloc();
index 08aeb7e..3a99f6d 100644 (file)
@@ -910,9 +910,9 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        amd_manager->acp_mmio = devm_ioremap(dev, res->start, resource_size(res));
-       if (IS_ERR(amd_manager->mmio)) {
+       if (!amd_manager->acp_mmio) {
                dev_err(dev, "mmio not found\n");
-               return PTR_ERR(amd_manager->mmio);
+               return -ENOMEM;
        }
        amd_manager->instance = pdata->instance;
        amd_manager->mmio = amd_manager->acp_mmio +
index dba920e..cf78839 100644 (file)
@@ -922,8 +922,8 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
                        "initializing enumeration and init completion for Slave %d\n",
                        slave->dev_num);
 
-               init_completion(&slave->enumeration_complete);
-               init_completion(&slave->initialization_complete);
+               reinit_completion(&slave->enumeration_complete);
+               reinit_completion(&slave->initialization_complete);
 
        } else if ((status == SDW_SLAVE_ATTACHED) &&
                   (slave->status == SDW_SLAVE_UNATTACHED)) {
@@ -931,7 +931,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
                        "signaling enumeration completion for Slave %d\n",
                        slave->dev_num);
 
-               complete(&slave->enumeration_complete);
+               complete_all(&slave->enumeration_complete);
        }
        slave->status = status;
        mutex_unlock(&bus->bus_lock);
@@ -1951,7 +1951,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
                                "signaling initialization completion for Slave %d\n",
                                slave->dev_num);
 
-                       complete(&slave->initialization_complete);
+                       complete_all(&slave->initialization_complete);
 
                        /*
                         * If the manager became pm_runtime active, the peripherals will be
index 7970fdb..c029e4d 100644 (file)
@@ -540,7 +540,7 @@ static int qcom_swrm_get_alert_slave_dev_num(struct qcom_swrm_ctrl *ctrl)
                status = (val >> (dev_num * SWRM_MCP_SLV_STATUS_SZ));
 
                if ((status & SWRM_MCP_SLV_STATUS_MASK) == SDW_SLAVE_ALERT) {
-                       ctrl->status[dev_num] = status;
+                       ctrl->status[dev_num] = status & SWRM_MCP_SLV_STATUS_MASK;
                        return dev_num;
                }
        }
index c9bff98..e9b168b 100644 (file)
@@ -13,6 +13,7 @@ config VIDEO_ATOMISP
        tristate "Intel Atom Image Signal Processor Driver"
        depends on VIDEO_DEV && INTEL_ATOMISP
        depends on PMIC_OPREGION
+       select V4L2_FWNODE
        select IOSF_MBI
        select VIDEOBUF2_VMALLOC
        select VIDEO_V4L2_SUBDEV_API
index d11cfd2..992a4fa 100644 (file)
@@ -156,7 +156,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t,
     return false;
 }
 
-static int sticon_set_def_font(int unit, struct console_font *op)
+static void sticon_set_def_font(int unit)
 {
        if (font_data[unit] != STI_DEF_FONT) {
                if (--FNTREFCOUNT(font_data[unit]) == 0) {
@@ -165,8 +165,6 @@ static int sticon_set_def_font(int unit, struct console_font *op)
                }
                font_data[unit] = STI_DEF_FONT;
        }
-
-       return 0;
 }
 
 static int sticon_set_font(struct vc_data *vc, struct console_font *op,
@@ -246,7 +244,7 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
                  vc->vc_video_erase_char, font_data[vc->vc_num]);
 
        /* delete old font in case it is a user font */
-       sticon_set_def_font(unit, NULL);
+       sticon_set_def_font(unit);
 
        FNTREFCOUNT(cooked_font)++;
        font_data[unit] = cooked_font;
@@ -264,7 +262,9 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
 
 static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
 {
-       return sticon_set_def_font(vc->vc_num, op);
+       sticon_set_def_font(vc->vc_num);
+
+       return 0;
 }
 
 static int sticon_font_set(struct vc_data *vc, struct console_font *font,
@@ -297,7 +297,7 @@ static void sticon_deinit(struct vc_data *c)
 
     /* free memory used by user font */
     for (i = 0; i < MAX_NR_CONSOLES; i++)
-       sticon_set_def_font(i, NULL);
+       sticon_set_def_font(i);
 }
 
 static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
index e25ba52..7ad047b 100644 (file)
@@ -65,16 +65,8 @@ static struct vgastate vgastate;
  *  Interface used by the world
  */
 
-static const char *vgacon_startup(void);
-static void vgacon_init(struct vc_data *c, int init);
-static void vgacon_deinit(struct vc_data *c);
-static void vgacon_cursor(struct vc_data *c, int mode);
-static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
-static void vgacon_scrolldelta(struct vc_data *c, int lines);
 static int vgacon_set_origin(struct vc_data *c);
-static void vgacon_save_screen(struct vc_data *c);
-static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
+
 static struct uni_pagedict *vgacon_uni_pagedir;
 static int vgacon_refcount;
 
@@ -142,12 +134,6 @@ static inline void vga_set_mem_top(struct vc_data *c)
        write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
 }
 
-static void vgacon_restore_screen(struct vc_data *c)
-{
-       if (c->vc_origin != c->vc_visible_origin)
-               vgacon_scrolldelta(c, 0);
-}
-
 static void vgacon_scrolldelta(struct vc_data *c, int lines)
 {
        vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
@@ -155,6 +141,12 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        vga_set_mem_top(c);
 }
 
+static void vgacon_restore_screen(struct vc_data *c)
+{
+       if (c->vc_origin != c->vc_visible_origin)
+               vgacon_scrolldelta(c, 0);
+}
+
 static const char *vgacon_startup(void)
 {
        const char *display_desc = NULL;
@@ -445,7 +437,7 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
        }
 }
 
-static void vgacon_set_cursor_size(int xpos, int from, int to)
+static void vgacon_set_cursor_size(int from, int to)
 {
        unsigned long flags;
        int curs, cure;
@@ -478,18 +470,22 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
 
 static void vgacon_cursor(struct vc_data *c, int mode)
 {
+       unsigned int c_height;
+
        if (c->vc_mode != KD_TEXT)
                return;
 
        vgacon_restore_screen(c);
 
+       c_height = c->vc_cell_height;
+
        switch (mode) {
        case CM_ERASE:
                write_vga(14, (c->vc_pos - vga_vram_base) / 2);
                if (vga_video_type >= VIDEO_TYPE_VGAC)
-                       vgacon_set_cursor_size(c->state.x, 31, 30);
+                       vgacon_set_cursor_size(31, 30);
                else
-                       vgacon_set_cursor_size(c->state.x, 31, 31);
+                       vgacon_set_cursor_size(31, 31);
                break;
 
        case CM_MOVE:
@@ -497,51 +493,38 @@ static void vgacon_cursor(struct vc_data *c, int mode)
                write_vga(14, (c->vc_pos - vga_vram_base) / 2);
                switch (CUR_SIZE(c->vc_cursor_type)) {
                case CUR_UNDERLINE:
-                       vgacon_set_cursor_size(c->state.x,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 2 : 3),
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height -
+                                              (c_height < 10 ? 2 : 3),
+                                              c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_TWO_THIRDS:
-                       vgacon_set_cursor_size(c->state.x,
-                                              c->vc_cell_height / 3,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height / 3, c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_LOWER_THIRD:
-                       vgacon_set_cursor_size(c->state.x,
-                                              (c->vc_cell_height * 2) / 3,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height * 2 / 3, c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_LOWER_HALF:
-                       vgacon_set_cursor_size(c->state.x,
-                                              c->vc_cell_height / 2,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height / 2, c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_NONE:
                        if (vga_video_type >= VIDEO_TYPE_VGAC)
-                               vgacon_set_cursor_size(c->state.x, 31, 30);
+                               vgacon_set_cursor_size(31, 30);
                        else
-                               vgacon_set_cursor_size(c->state.x, 31, 31);
+                               vgacon_set_cursor_size(31, 31);
                        break;
                default:
-                       vgacon_set_cursor_size(c->state.x, 1,
-                                              c->vc_cell_height);
+                       vgacon_set_cursor_size(1, c_height);
                        break;
                }
                break;
        }
 }
 
-static int vgacon_doresize(struct vc_data *c,
+static void vgacon_doresize(struct vc_data *c,
                unsigned int width, unsigned int height)
 {
        unsigned long flags;
@@ -600,7 +583,6 @@ static int vgacon_doresize(struct vc_data *c,
        }
 
        raw_spin_unlock_irqrestore(&vga_lock, flags);
-       return 0;
 }
 
 static int vgacon_switch(struct vc_data *c)
index 5c232eb..c137d6a 100644 (file)
@@ -1732,6 +1732,9 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 
        /* Now hook interrupt too */
        irq = platform_get_irq(dev, 0);
+       if (irq < 0)
+               return irq;
+
        ret = request_irq(irq, au1200fb_handle_irq,
                          IRQF_SHARED, "lcd", (void *)dev);
        if (ret) {
index 025d663..39f438d 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 832a82f..90fdc9d 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/fb.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 6335cd3..98c60f7 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 6884572..6427b85 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index c6c9d04..887fad4 100644 (file)
@@ -1612,8 +1612,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
-                        int line, int count, int offset)
+static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset)
 {
        unsigned short *d = (unsigned short *)
            (vc->vc_origin + vc->vc_size_row * line);
@@ -1827,7 +1826,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 
                case SCROLL_REDRAW:
                      redraw_up:
-                       fbcon_redraw(vc, p, t, b - t - count,
+                       fbcon_redraw(vc, t, b - t - count,
                                     count * vc->vc_cols);
                        fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
@@ -1913,7 +1912,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 
                case SCROLL_REDRAW:
                      redraw_down:
-                       fbcon_redraw(vc, p, b - 1, b - t - count,
+                       fbcon_redraw(vc, b - 1, b - t - count,
                                     -count * vc->vc_cols);
                        fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
index 94fe529..22158d9 100644 (file)
@@ -548,7 +548,9 @@ static int ep93xxfb_probe(struct platform_device *pdev)
        }
 
        ep93xxfb_set_par(info);
-       clk_prepare_enable(fbi->clk);
+       err = clk_prepare_enable(fbi->clk);
+       if (err)
+               goto failed_check;
 
        err = register_framebuffer(info);
        if (err)
index c6d3111..c473841 100644 (file)
@@ -16,7 +16,8 @@
 #include <linux/fb.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/upa.h>
index 9aa15be..d4a9a58 100644 (file)
@@ -12,8 +12,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index adf3669..77dedd2 100644 (file)
@@ -613,10 +613,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
        if (var->hsync_len < 1    || var->hsync_len > 64)
                printk(KERN_ERR "%s: invalid hsync_len %d\n",
                        info->fix.id, var->hsync_len);
-       if (var->left_margin > 255)
+       if (var->left_margin < 3  || var->left_margin > 255)
                printk(KERN_ERR "%s: invalid left_margin %d\n",
                        info->fix.id, var->left_margin);
-       if (var->right_margin > 255)
+       if (var->right_margin < 1 || var->right_margin > 255)
                printk(KERN_ERR "%s: invalid right_margin %d\n",
                        info->fix.id, var->right_margin);
        if (var->yres < 1 || var->yres > ymax_mask)
@@ -673,7 +673,8 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
 
        pr_debug("%s\n",__func__);
 
-       info->pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL);
+       info->pseudo_palette = devm_kmalloc_array(&pdev->dev, 16,
+                                                 sizeof(u32), GFP_KERNEL);
        if (!info->pseudo_palette)
                return -ENOMEM;
 
@@ -868,7 +869,6 @@ static int imxfb_probe(struct platform_device *pdev)
        struct imxfb_info *fbi;
        struct lcd_device *lcd;
        struct fb_info *info;
-       struct resource *res;
        struct imx_fb_videomode *m;
        const struct of_device_id *of_id;
        struct device_node *display_np;
@@ -885,10 +885,6 @@ static int imxfb_probe(struct platform_device *pdev)
        if (of_id)
                pdev->id_entry = of_id->data;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
-
        info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev);
        if (!info)
                return -ENOMEM;
@@ -907,7 +903,7 @@ static int imxfb_probe(struct platform_device *pdev)
        if (!display_np) {
                dev_err(&pdev->dev, "No display defined in devicetree\n");
                ret = -EINVAL;
-               goto failed_of_parse;
+               goto failed_init;
        }
 
        /*
@@ -921,13 +917,13 @@ static int imxfb_probe(struct platform_device *pdev)
        if (!fbi->mode) {
                ret = -ENOMEM;
                of_node_put(display_np);
-               goto failed_of_parse;
+               goto failed_init;
        }
 
        ret = imxfb_of_read_mode(&pdev->dev, display_np, fbi->mode);
        of_node_put(display_np);
        if (ret)
-               goto failed_of_parse;
+               goto failed_init;
 
        /* Calculate maximum bytes used per pixel. In most cases this should
         * be the same as m->bpp/8 */
@@ -940,7 +936,7 @@ static int imxfb_probe(struct platform_device *pdev)
        fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(fbi->clk_ipg)) {
                ret = PTR_ERR(fbi->clk_ipg);
-               goto failed_getclock;
+               goto failed_init;
        }
 
        /*
@@ -955,25 +951,25 @@ static int imxfb_probe(struct platform_device *pdev)
         */
        ret = clk_prepare_enable(fbi->clk_ipg);
        if (ret)
-               goto failed_getclock;
+               goto failed_init;
        clk_disable_unprepare(fbi->clk_ipg);
 
        fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(fbi->clk_ahb)) {
                ret = PTR_ERR(fbi->clk_ahb);
-               goto failed_getclock;
+               goto failed_init;
        }
 
        fbi->clk_per = devm_clk_get(&pdev->dev, "per");
        if (IS_ERR(fbi->clk_per)) {
                ret = PTR_ERR(fbi->clk_per);
-               goto failed_getclock;
+               goto failed_init;
        }
 
-       fbi->regs = devm_ioremap_resource(&pdev->dev, res);
+       fbi->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(fbi->regs)) {
                ret = PTR_ERR(fbi->regs);
-               goto failed_ioremap;
+               goto failed_init;
        }
 
        fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
@@ -982,7 +978,7 @@ static int imxfb_probe(struct platform_device *pdev)
        if (!info->screen_buffer) {
                dev_err(&pdev->dev, "Failed to allocate video RAM\n");
                ret = -ENOMEM;
-               goto failed_map;
+               goto failed_init;
        }
 
        info->fix.smem_start = fbi->map_dma;
@@ -1034,18 +1030,11 @@ static int imxfb_probe(struct platform_device *pdev)
 
 failed_lcd:
        unregister_framebuffer(info);
-
 failed_register:
        fb_dealloc_cmap(&info->cmap);
 failed_cmap:
        dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer,
                    fbi->map_dma);
-failed_map:
-failed_ioremap:
-failed_getclock:
-       release_mem_region(res->start, resource_size(res));
-failed_of_parse:
-       kfree(info->pseudo_palette);
 failed_init:
        framebuffer_release(info);
        return ret;
@@ -1062,11 +1051,10 @@ static void imxfb_remove(struct platform_device *pdev)
        fb_dealloc_cmap(&info->cmap);
        dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer,
                    fbi->map_dma);
-       kfree(info->pseudo_palette);
        framebuffer_release(info);
 }
 
-static int __maybe_unused imxfb_suspend(struct device *dev)
+static int imxfb_suspend(struct device *dev)
 {
        struct fb_info *info = dev_get_drvdata(dev);
        struct imxfb_info *fbi = info->par;
@@ -1076,7 +1064,7 @@ static int __maybe_unused imxfb_suspend(struct device *dev)
        return 0;
 }
 
-static int __maybe_unused imxfb_resume(struct device *dev)
+static int imxfb_resume(struct device *dev)
 {
        struct fb_info *info = dev_get_drvdata(dev);
        struct imxfb_info *fbi = info->par;
@@ -1086,13 +1074,13 @@ static int __maybe_unused imxfb_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
 
 static struct platform_driver imxfb_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .of_match_table = imxfb_of_dev_id,
-               .pm     = &imxfb_pm_ops,
+               .pm     = pm_sleep_ptr(&imxfb_pm_ops),
        },
        .probe          = imxfb_probe,
        .remove_new     = imxfb_remove,
index edfa0a0..79886a2 100644 (file)
@@ -83,11 +83,11 @@ volatile u32 i,count=0; \
 static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
                              u32 dwSubSysID, u32 dwRevID)
 {
-       u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
-       u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
-       u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
-       u32 adwSDRAMRsh[] = { 36, 39, 40 };
-       u32 adwChipSpeed[] = { 110, 120, 125 };
+       static const u8 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
+       static const u16 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
+       static const u16 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
+       static const u8 adwSDRAMRsh[] = { 36, 39, 40 };
+       static const u8 adwChipSpeed[] = { 110, 120, 125 };
        u32 dwMemTypeIdx;
        u32 dwChipSpeedIdx;
 
index 3ffc0a7..89ca482 100644 (file)
@@ -16,8 +16,9 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/fbio.h>
 
index 61aed7f..c35a747 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#if defined(CONFIG_OF)
-#include <linux/of_platform.h>
-#endif
+
 #include "mb862xxfb.h"
 #include "mb862xx_reg.h"
 #include "mb862xxfb_accel.h"
index b5c8fca..9dc347d 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#if defined(CONFIG_OF)
+#include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#endif
+#include <linux/platform_device.h>
+
 #include "mb862xxfb.h"
 #include "mb862xx_reg.h"
 
index ba94a0a..77fce12 100644 (file)
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/sched/signal.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
-#include <linux/of_device.h>
 
 #include <video/omapfb_dss.h>
 #include <video/mipi_display.h>
index 0876962..e2e747c 100644 (file)
@@ -15,7 +15,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index f8283fc..b27f43b 100644 (file)
@@ -30,9 +30,9 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/nvram.h>
+#include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
+#include <linux/platform_device.h>
 
 #include "macmodes.h"
 #include "platinumfb.h"
index 7f79db8..21e9fd8 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/fb.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <asm/fbio.h>
 
index 490bd9a..17d61e1 100644 (file)
@@ -8,7 +8,8 @@
 #include <linux/kernel.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 struct gfb_info {
        struct fb_info          *info;
index 2cab4b9..e64ec7d 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 
index 6ec358a..c4e01e8 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 
index fc3ac23..255eb57 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 2aa3a52..542badd 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/platform_device.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
+#include <linux/of.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 
index 48ae509..030ab44 100644 (file)
@@ -499,12 +499,16 @@ static void fragment_free_space(struct btrfs_block_group *block_group)
  * used yet since their free space will be released as soon as the transaction
  * commits.
  */
-u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end)
+int add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end,
+                      u64 *total_added_ret)
 {
        struct btrfs_fs_info *info = block_group->fs_info;
-       u64 extent_start, extent_end, size, total_added = 0;
+       u64 extent_start, extent_end, size;
        int ret;
 
+       if (total_added_ret)
+               *total_added_ret = 0;
+
        while (start < end) {
                ret = find_first_extent_bit(&info->excluded_extents, start,
                                            &extent_start, &extent_end,
@@ -517,10 +521,12 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end
                        start = extent_end + 1;
                } else if (extent_start > start && extent_start < end) {
                        size = extent_start - start;
-                       total_added += size;
                        ret = btrfs_add_free_space_async_trimmed(block_group,
                                                                 start, size);
-                       BUG_ON(ret); /* -ENOMEM or logic error */
+                       if (ret)
+                               return ret;
+                       if (total_added_ret)
+                               *total_added_ret += size;
                        start = extent_end + 1;
                } else {
                        break;
@@ -529,13 +535,15 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end
 
        if (start < end) {
                size = end - start;
-               total_added += size;
                ret = btrfs_add_free_space_async_trimmed(block_group, start,
                                                         size);
-               BUG_ON(ret); /* -ENOMEM or logic error */
+               if (ret)
+                       return ret;
+               if (total_added_ret)
+                       *total_added_ret += size;
        }
 
-       return total_added;
+       return 0;
 }
 
 /*
@@ -779,8 +787,13 @@ next:
 
                if (key.type == BTRFS_EXTENT_ITEM_KEY ||
                    key.type == BTRFS_METADATA_ITEM_KEY) {
-                       total_found += add_new_free_space(block_group, last,
-                                                         key.objectid);
+                       u64 space_added;
+
+                       ret = add_new_free_space(block_group, last, key.objectid,
+                                                &space_added);
+                       if (ret)
+                               goto out;
+                       total_found += space_added;
                        if (key.type == BTRFS_METADATA_ITEM_KEY)
                                last = key.objectid +
                                        fs_info->nodesize;
@@ -795,11 +808,10 @@ next:
                }
                path->slots[0]++;
        }
-       ret = 0;
-
-       total_found += add_new_free_space(block_group, last,
-                               block_group->start + block_group->length);
 
+       ret = add_new_free_space(block_group, last,
+                                block_group->start + block_group->length,
+                                NULL);
 out:
        btrfs_free_path(path);
        return ret;
@@ -1640,13 +1652,14 @@ void btrfs_mark_bg_unused(struct btrfs_block_group *bg)
 {
        struct btrfs_fs_info *fs_info = bg->fs_info;
 
-       trace_btrfs_add_unused_block_group(bg);
        spin_lock(&fs_info->unused_bgs_lock);
        if (list_empty(&bg->bg_list)) {
                btrfs_get_block_group(bg);
+               trace_btrfs_add_unused_block_group(bg);
                list_add_tail(&bg->bg_list, &fs_info->unused_bgs);
-       } else {
+       } else if (!test_bit(BLOCK_GROUP_FLAG_NEW, &bg->runtime_flags)) {
                /* Pull out the block group from the reclaim_bgs list. */
+               trace_btrfs_add_unused_block_group(bg);
                list_move_tail(&bg->bg_list, &fs_info->unused_bgs);
        }
        spin_unlock(&fs_info->unused_bgs_lock);
@@ -2087,6 +2100,7 @@ static int exclude_super_stripes(struct btrfs_block_group *cache)
 
                /* Shouldn't have super stripes in sequential zones */
                if (zoned && nr) {
+                       kfree(logical);
                        btrfs_err(fs_info,
                        "zoned: block group %llu must not contain super block",
                                  cache->start);
@@ -2292,9 +2306,11 @@ static int read_one_block_group(struct btrfs_fs_info *info,
                btrfs_free_excluded_extents(cache);
        } else if (cache->used == 0) {
                cache->cached = BTRFS_CACHE_FINISHED;
-               add_new_free_space(cache, cache->start,
-                                  cache->start + cache->length);
+               ret = add_new_free_space(cache, cache->start,
+                                        cache->start + cache->length, NULL);
                btrfs_free_excluded_extents(cache);
+               if (ret)
+                       goto error;
        }
 
        ret = btrfs_add_block_group_cache(info, cache);
@@ -2668,6 +2684,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
 next:
                btrfs_delayed_refs_rsv_release(fs_info, 1);
                list_del_init(&block_group->bg_list);
+               clear_bit(BLOCK_GROUP_FLAG_NEW, &block_group->runtime_flags);
        }
        btrfs_trans_release_chunk_metadata(trans);
 }
@@ -2707,6 +2724,13 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
        if (!cache)
                return ERR_PTR(-ENOMEM);
 
+       /*
+        * Mark it as new before adding it to the rbtree of block groups or any
+        * list, so that no other task finds it and calls btrfs_mark_bg_unused()
+        * before the new flag is set.
+        */
+       set_bit(BLOCK_GROUP_FLAG_NEW, &cache->runtime_flags);
+
        cache->length = size;
        set_free_space_tree_thresholds(cache);
        cache->flags = type;
@@ -2730,9 +2754,12 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
                return ERR_PTR(ret);
        }
 
-       add_new_free_space(cache, chunk_offset, chunk_offset + size);
-
+       ret = add_new_free_space(cache, chunk_offset, chunk_offset + size, NULL);
        btrfs_free_excluded_extents(cache);
+       if (ret) {
+               btrfs_put_block_group(cache);
+               return ERR_PTR(ret);
+       }
 
        /*
         * Ensure the corresponding space_info object is created and
index f204add..aba5dff 100644 (file)
@@ -70,6 +70,11 @@ enum btrfs_block_group_flags {
        BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE,
        /* Indicate that the block group is placed on a sequential zone */
        BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE,
+       /*
+        * Indicate that block group is in the list of new block groups of a
+        * transaction.
+        */
+       BLOCK_GROUP_FLAG_NEW,
 };
 
 enum btrfs_caching_type {
@@ -284,8 +289,8 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait);
 void btrfs_put_caching_control(struct btrfs_caching_control *ctl);
 struct btrfs_caching_control *btrfs_get_caching_control(
                struct btrfs_block_group *cache);
-u64 add_new_free_space(struct btrfs_block_group *block_group,
-                      u64 start, u64 end);
+int add_new_free_space(struct btrfs_block_group *block_group,
+                      u64 start, u64 end, u64 *total_added_ret);
 struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
                                struct btrfs_fs_info *fs_info,
                                const u64 chunk_offset);
index 6279d20..77684c5 100644 (file)
@@ -349,6 +349,11 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
        }
        read_unlock(&fs_info->global_root_lock);
 
+       if (btrfs_fs_compat_ro(fs_info, BLOCK_GROUP_TREE)) {
+               num_bytes += btrfs_root_used(&fs_info->block_group_root->root_item);
+               min_items++;
+       }
+
        /*
         * But we also want to reserve enough space so we can do the fallback
         * global reserve for an unlink, which is an additional
index 7513388..9b9914e 100644 (file)
@@ -3438,11 +3438,16 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
         * For devices supporting discard turn on discard=async automatically,
         * unless it's already set or disabled. This could be turned off by
         * nodiscard for the same mount.
+        *
+        * The zoned mode piggy backs on the discard functionality for
+        * resetting a zone. There is no reason to delay the zone reset as it is
+        * fast enough. So, do not enable async discard for zoned mode.
         */
        if (!(btrfs_test_opt(fs_info, DISCARD_SYNC) ||
              btrfs_test_opt(fs_info, DISCARD_ASYNC) ||
              btrfs_test_opt(fs_info, NODISCARD)) &&
-           fs_info->fs_devices->discardable) {
+           fs_info->fs_devices->discardable &&
+           !btrfs_is_zoned(fs_info)) {
                btrfs_set_and_info(fs_info, DISCARD_ASYNC,
                                   "auto enabling async discard");
        }
index 045ddce..f169378 100644 (file)
@@ -1515,9 +1515,13 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
                        if (prev_bit == 0 && bit == 1) {
                                extent_start = offset;
                        } else if (prev_bit == 1 && bit == 0) {
-                               total_found += add_new_free_space(block_group,
-                                                                 extent_start,
-                                                                 offset);
+                               u64 space_added;
+
+                               ret = add_new_free_space(block_group, extent_start,
+                                                        offset, &space_added);
+                               if (ret)
+                                       goto out;
+                               total_found += space_added;
                                if (total_found > CACHING_CTL_WAKE_UP) {
                                        total_found = 0;
                                        wake_up(&caching_ctl->wait);
@@ -1529,8 +1533,9 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
                }
        }
        if (prev_bit == 1) {
-               total_found += add_new_free_space(block_group, extent_start,
-                                                 end);
+               ret = add_new_free_space(block_group, extent_start, end, NULL);
+               if (ret)
+                       goto out;
                extent_count++;
        }
 
@@ -1569,6 +1574,8 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
        end = block_group->start + block_group->length;
 
        while (1) {
+               u64 space_added;
+
                ret = btrfs_next_item(root, path);
                if (ret < 0)
                        goto out;
@@ -1583,8 +1590,11 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
                ASSERT(key.type == BTRFS_FREE_SPACE_EXTENT_KEY);
                ASSERT(key.objectid < end && key.objectid + key.offset <= end);
 
-               total_found += add_new_free_space(block_group, key.objectid,
-                                                 key.objectid + key.offset);
+               ret = add_new_free_space(block_group, key.objectid,
+                                        key.objectid + key.offset, &space_added);
+               if (ret)
+                       goto out;
+               total_found += space_added;
                if (total_found > CACHING_CTL_WAKE_UP) {
                        total_found = 0;
                        wake_up(&caching_ctl->wait);
index dbbb672..49cef61 100644 (file)
@@ -3482,15 +3482,21 @@ zeroit:
 void btrfs_add_delayed_iput(struct btrfs_inode *inode)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
+       unsigned long flags;
 
        if (atomic_add_unless(&inode->vfs_inode.i_count, -1, 1))
                return;
 
        atomic_inc(&fs_info->nr_delayed_iputs);
-       spin_lock(&fs_info->delayed_iput_lock);
+       /*
+        * Need to be irq safe here because we can be called from either an irq
+        * context (see bio.c and btrfs_put_ordered_extent()) or a non-irq
+        * context.
+        */
+       spin_lock_irqsave(&fs_info->delayed_iput_lock, flags);
        ASSERT(list_empty(&inode->delayed_iput));
        list_add_tail(&inode->delayed_iput, &fs_info->delayed_iputs);
-       spin_unlock(&fs_info->delayed_iput_lock);
+       spin_unlock_irqrestore(&fs_info->delayed_iput_lock, flags);
        if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags))
                wake_up_process(fs_info->cleaner_kthread);
 }
@@ -3499,37 +3505,46 @@ static void run_delayed_iput_locked(struct btrfs_fs_info *fs_info,
                                    struct btrfs_inode *inode)
 {
        list_del_init(&inode->delayed_iput);
-       spin_unlock(&fs_info->delayed_iput_lock);
+       spin_unlock_irq(&fs_info->delayed_iput_lock);
        iput(&inode->vfs_inode);
        if (atomic_dec_and_test(&fs_info->nr_delayed_iputs))
                wake_up(&fs_info->delayed_iputs_wait);
-       spin_lock(&fs_info->delayed_iput_lock);
+       spin_lock_irq(&fs_info->delayed_iput_lock);
 }
 
 static void btrfs_run_delayed_iput(struct btrfs_fs_info *fs_info,
                                   struct btrfs_inode *inode)
 {
        if (!list_empty(&inode->delayed_iput)) {
-               spin_lock(&fs_info->delayed_iput_lock);
+               spin_lock_irq(&fs_info->delayed_iput_lock);
                if (!list_empty(&inode->delayed_iput))
                        run_delayed_iput_locked(fs_info, inode);
-               spin_unlock(&fs_info->delayed_iput_lock);
+               spin_unlock_irq(&fs_info->delayed_iput_lock);
        }
 }
 
 void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
 {
-
-       spin_lock(&fs_info->delayed_iput_lock);
+       /*
+        * btrfs_put_ordered_extent() can run in irq context (see bio.c), which
+        * calls btrfs_add_delayed_iput() and that needs to lock
+        * fs_info->delayed_iput_lock. So we need to disable irqs here to
+        * prevent a deadlock.
+        */
+       spin_lock_irq(&fs_info->delayed_iput_lock);
        while (!list_empty(&fs_info->delayed_iputs)) {
                struct btrfs_inode *inode;
 
                inode = list_first_entry(&fs_info->delayed_iputs,
                                struct btrfs_inode, delayed_iput);
                run_delayed_iput_locked(fs_info, inode);
-               cond_resched_lock(&fs_info->delayed_iput_lock);
+               if (need_resched()) {
+                       spin_unlock_irq(&fs_info->delayed_iput_lock);
+                       cond_resched();
+                       spin_lock_irq(&fs_info->delayed_iput_lock);
+               }
        }
-       spin_unlock(&fs_info->delayed_iput_lock);
+       spin_unlock_irq(&fs_info->delayed_iput_lock);
 }
 
 /*
@@ -3659,11 +3674,14 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                found_key.type = BTRFS_INODE_ITEM_KEY;
                found_key.offset = 0;
                inode = btrfs_iget(fs_info->sb, last_objectid, root);
-               ret = PTR_ERR_OR_ZERO(inode);
-               if (ret && ret != -ENOENT)
-                       goto out;
+               if (IS_ERR(inode)) {
+                       ret = PTR_ERR(inode);
+                       inode = NULL;
+                       if (ret != -ENOENT)
+                               goto out;
+               }
 
-               if (ret == -ENOENT && root == fs_info->tree_root) {
+               if (!inode && root == fs_info->tree_root) {
                        struct btrfs_root *dead_root;
                        int is_dead_root = 0;
 
@@ -3724,17 +3742,17 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                 * deleted but wasn't. The inode number may have been reused,
                 * but either way, we can delete the orphan item.
                 */
-               if (ret == -ENOENT || inode->i_nlink) {
-                       if (!ret) {
+               if (!inode || inode->i_nlink) {
+                       if (inode) {
                                ret = btrfs_drop_verity_items(BTRFS_I(inode));
                                iput(inode);
+                               inode = NULL;
                                if (ret)
                                        goto out;
                        }
                        trans = btrfs_start_transaction(root, 1);
                        if (IS_ERR(trans)) {
                                ret = PTR_ERR(trans);
-                               iput(inode);
                                goto out;
                        }
                        btrfs_debug(fs_info, "auto deleting %Lu",
@@ -3742,10 +3760,8 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                        ret = btrfs_del_orphan_item(trans, root,
                                                    found_key.objectid);
                        btrfs_end_transaction(trans);
-                       if (ret) {
-                               iput(inode);
+                       if (ret)
                                goto out;
-                       }
                        continue;
                }
 
@@ -4847,9 +4863,6 @@ again:
                ret = -ENOMEM;
                goto out;
        }
-       ret = set_page_extent_mapped(page);
-       if (ret < 0)
-               goto out_unlock;
 
        if (!PageUptodate(page)) {
                ret = btrfs_read_folio(NULL, page_folio(page));
@@ -4864,6 +4877,17 @@ again:
                        goto out_unlock;
                }
        }
+
+       /*
+        * We unlock the page after the io is completed and then re-lock it
+        * above.  release_folio() could have come in between that and cleared
+        * PagePrivate(), but left the page in the mapping.  Set the page mapped
+        * here to make sure it's properly set for the subpage stuff.
+        */
+       ret = set_page_extent_mapped(page);
+       if (ret < 0)
+               goto out_unlock;
+
        wait_on_page_writeback(page);
 
        lock_extent(io_tree, block_start, block_end, &cached_state);
@@ -7849,8 +7873,11 @@ static void btrfs_dio_submit_io(const struct iomap_iter *iter, struct bio *bio,
 
                ret = btrfs_extract_ordered_extent(bbio, dio_data->ordered);
                if (ret) {
-                       bbio->bio.bi_status = errno_to_blk_status(ret);
-                       btrfs_dio_end_io(bbio);
+                       btrfs_finish_ordered_extent(dio_data->ordered, NULL,
+                                                   file_offset, dip->bytes,
+                                                   !ret);
+                       bio->bi_status = errno_to_blk_status(ret);
+                       iomap_dio_bio_end_io(bio);
                        return;
                }
        }
index da1f84a..2637d6b 100644 (file)
@@ -4445,4 +4445,5 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
                ulist_free(entry->old_roots);
                kfree(entry);
        }
+       *root = RB_ROOT;
 }
index f37b925..0249ea5 100644 (file)
@@ -71,7 +71,7 @@ static void rmw_rbio_work_locked(struct work_struct *work);
 static void index_rbio_pages(struct btrfs_raid_bio *rbio);
 static int alloc_rbio_pages(struct btrfs_raid_bio *rbio);
 
-static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check);
+static int finish_parity_scrub(struct btrfs_raid_bio *rbio);
 static void scrub_rbio_work_locked(struct work_struct *work);
 
 static void free_raid_bio_pointers(struct btrfs_raid_bio *rbio)
@@ -2404,7 +2404,7 @@ static int alloc_rbio_essential_pages(struct btrfs_raid_bio *rbio)
        return 0;
 }
 
-static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check)
+static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 {
        struct btrfs_io_context *bioc = rbio->bioc;
        const u32 sectorsize = bioc->fs_info->sectorsize;
@@ -2445,9 +2445,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check)
         */
        clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
 
-       if (!need_check)
-               goto writeback;
-
        p_sector.page = alloc_page(GFP_NOFS);
        if (!p_sector.page)
                return -ENOMEM;
@@ -2516,7 +2513,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check)
                q_sector.page = NULL;
        }
 
-writeback:
        /*
         * time to start writing.  Make bios for everything from the
         * higher layers (the bio_list in our rbio) and our p/q.  Ignore
@@ -2699,7 +2695,6 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
 
 static void scrub_rbio(struct btrfs_raid_bio *rbio)
 {
-       bool need_check = false;
        int sector_nr;
        int ret;
 
@@ -2722,7 +2717,7 @@ static void scrub_rbio(struct btrfs_raid_bio *rbio)
         * We have every sector properly prepared. Can finish the scrub
         * and writeback the good content.
         */
-       ret = finish_parity_scrub(rbio, need_check);
+       ret = finish_parity_scrub(rbio);
        wait_event(rbio->io_wait, atomic_read(&rbio->stripes_pending) == 0);
        for (sector_nr = 0; sector_nr < rbio->stripe_nsectors; sector_nr++) {
                int found_errors;
index cf30635..91b6c2f 100644 (file)
@@ -826,8 +826,13 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
 
        trans = start_transaction(root, 0, TRANS_ATTACH,
                                  BTRFS_RESERVE_NO_FLUSH, true);
-       if (trans == ERR_PTR(-ENOENT))
-               btrfs_wait_for_commit(root->fs_info, 0);
+       if (trans == ERR_PTR(-ENOENT)) {
+               int ret;
+
+               ret = btrfs_wait_for_commit(root->fs_info, 0);
+               if (ret)
+                       return ERR_PTR(ret);
+       }
 
        return trans;
 }
@@ -931,6 +936,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
        }
 
        wait_for_commit(cur_trans, TRANS_STATE_COMPLETED);
+       ret = cur_trans->aborted;
        btrfs_put_transaction(cur_trans);
 out:
        return ret;
index 73f9ea7..2ecb76c 100644 (file)
@@ -4078,14 +4078,6 @@ static int alloc_profile_is_valid(u64 flags, int extended)
        return has_single_bit_set(flags);
 }
 
-static inline int balance_need_close(struct btrfs_fs_info *fs_info)
-{
-       /* cancel requested || normal exit path */
-       return atomic_read(&fs_info->balance_cancel_req) ||
-               (atomic_read(&fs_info->balance_pause_req) == 0 &&
-                atomic_read(&fs_info->balance_cancel_req) == 0);
-}
-
 /*
  * Validate target profile against allowed profiles and return true if it's OK.
  * Otherwise print the error message and return false.
@@ -4275,6 +4267,7 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
        u64 num_devices;
        unsigned seq;
        bool reducing_redundancy;
+       bool paused = false;
        int i;
 
        if (btrfs_fs_closing(fs_info) ||
@@ -4405,6 +4398,7 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
        if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req)) {
                btrfs_info(fs_info, "balance: paused");
                btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED);
+               paused = true;
        }
        /*
         * Balance can be canceled by:
@@ -4433,8 +4427,8 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
                btrfs_update_ioctl_balance_args(fs_info, bargs);
        }
 
-       if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
-           balance_need_close(fs_info)) {
+       /* We didn't pause, we can clean everything up. */
+       if (!paused) {
                reset_balance_state(fs_info);
                btrfs_exclop_finish(fs_info);
        }
@@ -6404,7 +6398,8 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
            (op == BTRFS_MAP_READ || !dev_replace_is_ongoing ||
             !dev_replace->tgtdev)) {
                set_io_stripe(smap, map, stripe_index, stripe_offset, stripe_nr);
-               *mirror_num_ret = mirror_num;
+               if (mirror_num_ret)
+                       *mirror_num_ret = mirror_num;
                *bioc_ret = NULL;
                ret = 0;
                goto out;
index 85b8b33..72b90bc 100644 (file)
@@ -805,6 +805,9 @@ int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
                return -EINVAL;
        }
 
+       btrfs_clear_and_info(info, DISCARD_ASYNC,
+                       "zoned: async discard ignored and disabled for zoned mode");
+
        return 0;
 }
 
index a2475b8..21b903f 100644 (file)
@@ -1006,14 +1006,11 @@ static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context
         * fls() instead since we need to know the actual length while modifying
         * goal length.
         */
-       order = fls(ac->ac_g_ex.fe_len);
+       order = fls(ac->ac_g_ex.fe_len) - 1;
        min_order = order - sbi->s_mb_best_avail_max_trim_order;
        if (min_order < 0)
                min_order = 0;
 
-       if (1 << min_order < ac->ac_o_ex.fe_len)
-               min_order = fls(ac->ac_o_ex.fe_len) + 1;
-
        if (sbi->s_stripe > 0) {
                /*
                 * We are assuming that stripe size is always a multiple of
@@ -1021,9 +1018,16 @@ static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context
                 */
                num_stripe_clusters = EXT4_NUM_B2C(sbi, sbi->s_stripe);
                if (1 << min_order < num_stripe_clusters)
-                       min_order = fls(num_stripe_clusters);
+                       /*
+                        * We consider 1 order less because later we round
+                        * up the goal len to num_stripe_clusters
+                        */
+                       min_order = fls(num_stripe_clusters) - 1;
        }
 
+       if (1 << min_order < ac->ac_o_ex.fe_len)
+               min_order = fls(ac->ac_o_ex.fe_len);
+
        for (i = order; i >= min_order; i--) {
                int frag_order;
                /*
@@ -4761,8 +4765,8 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
        int order, i;
        struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
        struct ext4_locality_group *lg;
-       struct ext4_prealloc_space *tmp_pa, *cpa = NULL;
-       ext4_lblk_t tmp_pa_start, tmp_pa_end;
+       struct ext4_prealloc_space *tmp_pa = NULL, *cpa = NULL;
+       loff_t tmp_pa_end;
        struct rb_node *iter;
        ext4_fsblk_t goal_block;
 
@@ -4770,47 +4774,151 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
        if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
                return false;
 
-       /* first, try per-file preallocation */
+       /*
+        * first, try per-file preallocation by searching the inode pa rbtree.
+        *
+        * Here, we can't do a direct traversal of the tree because
+        * ext4_mb_discard_group_preallocation() can paralelly mark the pa
+        * deleted and that can cause direct traversal to skip some entries.
+        */
        read_lock(&ei->i_prealloc_lock);
+
+       if (RB_EMPTY_ROOT(&ei->i_prealloc_node)) {
+               goto try_group_pa;
+       }
+
+       /*
+        * Step 1: Find a pa with logical start immediately adjacent to the
+        * original logical start. This could be on the left or right.
+        *
+        * (tmp_pa->pa_lstart never changes so we can skip locking for it).
+        */
        for (iter = ei->i_prealloc_node.rb_node; iter;
             iter = ext4_mb_pa_rb_next_iter(ac->ac_o_ex.fe_logical,
-                                           tmp_pa_start, iter)) {
+                                           tmp_pa->pa_lstart, iter)) {
                tmp_pa = rb_entry(iter, struct ext4_prealloc_space,
                                  pa_node.inode_node);
+       }
 
-               /* all fields in this condition don't change,
-                * so we can skip locking for them */
-               tmp_pa_start = tmp_pa->pa_lstart;
-               tmp_pa_end = tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
-
-               /* original request start doesn't lie in this PA */
-               if (ac->ac_o_ex.fe_logical < tmp_pa_start ||
-                   ac->ac_o_ex.fe_logical >= tmp_pa_end)
-                       continue;
+       /*
+        * Step 2: The adjacent pa might be to the right of logical start, find
+        * the left adjacent pa. After this step we'd have a valid tmp_pa whose
+        * logical start is towards the left of original request's logical start
+        */
+       if (tmp_pa->pa_lstart > ac->ac_o_ex.fe_logical) {
+               struct rb_node *tmp;
+               tmp = rb_prev(&tmp_pa->pa_node.inode_node);
 
-               /* non-extent files can't have physical blocks past 2^32 */
-               if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
-                   (tmp_pa->pa_pstart + EXT4_C2B(sbi, tmp_pa->pa_len) >
-                    EXT4_MAX_BLOCK_FILE_PHYS)) {
+               if (tmp) {
+                       tmp_pa = rb_entry(tmp, struct ext4_prealloc_space,
+                                           pa_node.inode_node);
+               } else {
                        /*
-                        * Since PAs don't overlap, we won't find any
-                        * other PA to satisfy this.
+                        * If there is no adjacent pa to the left then finding
+                        * an overlapping pa is not possible hence stop searching
+                        * inode pa tree
                         */
-                       break;
+                       goto try_group_pa;
                }
+       }
+
+       BUG_ON(!(tmp_pa && tmp_pa->pa_lstart <= ac->ac_o_ex.fe_logical));
 
-               /* found preallocated blocks, use them */
+       /*
+        * Step 3: If the left adjacent pa is deleted, keep moving left to find
+        * the first non deleted adjacent pa. After this step we should have a
+        * valid tmp_pa which is guaranteed to be non deleted.
+        */
+       for (iter = &tmp_pa->pa_node.inode_node;; iter = rb_prev(iter)) {
+               if (!iter) {
+                       /*
+                        * no non deleted left adjacent pa, so stop searching
+                        * inode pa tree
+                        */
+                       goto try_group_pa;
+               }
+               tmp_pa = rb_entry(iter, struct ext4_prealloc_space,
+                                 pa_node.inode_node);
                spin_lock(&tmp_pa->pa_lock);
-               if (tmp_pa->pa_deleted == 0 && tmp_pa->pa_free &&
-                   likely(ext4_mb_pa_goal_check(ac, tmp_pa))) {
-                       atomic_inc(&tmp_pa->pa_count);
-                       ext4_mb_use_inode_pa(ac, tmp_pa);
+               if (tmp_pa->pa_deleted == 0) {
+                       /*
+                        * We will keep holding the pa_lock from
+                        * this point on because we don't want group discard
+                        * to delete this pa underneath us. Since group
+                        * discard is anyways an ENOSPC operation it
+                        * should be okay for it to wait a few more cycles.
+                        */
+                       break;
+               } else {
                        spin_unlock(&tmp_pa->pa_lock);
-                       read_unlock(&ei->i_prealloc_lock);
-                       return true;
                }
+       }
+
+       BUG_ON(!(tmp_pa && tmp_pa->pa_lstart <= ac->ac_o_ex.fe_logical));
+       BUG_ON(tmp_pa->pa_deleted == 1);
+
+       /*
+        * Step 4: We now have the non deleted left adjacent pa. Only this
+        * pa can possibly satisfy the request hence check if it overlaps
+        * original logical start and stop searching if it doesn't.
+        */
+       tmp_pa_end = (loff_t)tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
+
+       if (ac->ac_o_ex.fe_logical >= tmp_pa_end) {
                spin_unlock(&tmp_pa->pa_lock);
+               goto try_group_pa;
+       }
+
+       /* non-extent files can't have physical blocks past 2^32 */
+       if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
+           (tmp_pa->pa_pstart + EXT4_C2B(sbi, tmp_pa->pa_len) >
+            EXT4_MAX_BLOCK_FILE_PHYS)) {
+               /*
+                * Since PAs don't overlap, we won't find any other PA to
+                * satisfy this.
+                */
+               spin_unlock(&tmp_pa->pa_lock);
+               goto try_group_pa;
+       }
+
+       if (tmp_pa->pa_free && likely(ext4_mb_pa_goal_check(ac, tmp_pa))) {
+               atomic_inc(&tmp_pa->pa_count);
+               ext4_mb_use_inode_pa(ac, tmp_pa);
+               spin_unlock(&tmp_pa->pa_lock);
+               read_unlock(&ei->i_prealloc_lock);
+               return true;
+       } else {
+               /*
+                * We found a valid overlapping pa but couldn't use it because
+                * it had no free blocks. This should ideally never happen
+                * because:
+                *
+                * 1. When a new inode pa is added to rbtree it must have
+                *    pa_free > 0 since otherwise we won't actually need
+                *    preallocation.
+                *
+                * 2. An inode pa that is in the rbtree can only have it's
+                *    pa_free become zero when another thread calls:
+                *      ext4_mb_new_blocks
+                *       ext4_mb_use_preallocated
+                *        ext4_mb_use_inode_pa
+                *
+                * 3. Further, after the above calls make pa_free == 0, we will
+                *    immediately remove it from the rbtree in:
+                *      ext4_mb_new_blocks
+                *       ext4_mb_release_context
+                *        ext4_mb_put_pa
+                *
+                * 4. Since the pa_free becoming 0 and pa_free getting removed
+                * from tree both happen in ext4_mb_new_blocks, which is always
+                * called with i_data_sem held for data allocations, we can be
+                * sure that another process will never see a pa in rbtree with
+                * pa_free == 0.
+                */
+               WARN_ON_ONCE(tmp_pa->pa_free == 0);
        }
+       spin_unlock(&tmp_pa->pa_lock);
+try_group_pa:
        read_unlock(&ei->i_prealloc_lock);
 
        /* can we use group allocation? */
index 321e3a8..05151d6 100644 (file)
@@ -1782,6 +1782,20 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
                memmove(here, (void *)here + size,
                        (void *)last - (void *)here + sizeof(__u32));
                memset(last, 0, size);
+
+               /*
+                * Update i_inline_off - moved ibody region might contain
+                * system.data attribute.  Handling a failure here won't
+                * cause other complications for setting an xattr.
+                */
+               if (!is_block && ext4_has_inline_data(inode)) {
+                       ret = ext4_find_inline_data_nolock(inode);
+                       if (ret) {
+                               ext4_warning_inode(inode,
+                                       "unable to update i_inline_off");
+                               goto out;
+                       }
+               }
        } else if (s->not_found) {
                /* Insert new name. */
                size_t size = EXT4_XATTR_LEN(name_len);
index 7893ea1..35c62b5 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -1042,10 +1042,8 @@ unsigned long __fdget_pos(unsigned int fd)
        struct file *file = (struct file *)(v & ~3);
 
        if (file && (file->f_mode & FMODE_ATOMIC_POS)) {
-               if (file_count(file) > 1) {
-                       v |= FDPUT_POS_UNLOCK;
-                       mutex_lock(&file->f_pos_lock);
-               }
+               v |= FDPUT_POS_UNLOCK;
+               mutex_lock(&file->f_pos_lock);
        }
        return v;
 }
index 35bc174..f67bef9 100644 (file)
@@ -258,7 +258,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                        spin_unlock(&fi->lock);
                }
                kfree(forget);
-               if (ret == -ENOMEM)
+               if (ret == -ENOMEM || ret == -EINTR)
                        goto out;
                if (ret || fuse_invalid_attr(&outarg.attr) ||
                    fuse_stale_inode(inode, outarg.generation, &outarg.attr))
@@ -395,8 +395,6 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
                goto out_put_forget;
 
        err = -EIO;
-       if (!outarg->nodeid)
-               goto out_put_forget;
        if (fuse_invalid_attr(&outarg->attr))
                goto out_put_forget;
 
index d66070a..f19d748 100644 (file)
@@ -1134,7 +1134,10 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                process_init_limits(fc, arg);
 
                if (arg->minor >= 6) {
-                       u64 flags = arg->flags | (u64) arg->flags2 << 32;
+                       u64 flags = arg->flags;
+
+                       if (flags & FUSE_INIT_EXT)
+                               flags |= (u64) arg->flags2 << 32;
 
                        ra_pages = arg->max_readahead / PAGE_SIZE;
                        if (flags & FUSE_ASYNC_READ)
@@ -1254,7 +1257,8 @@ void fuse_send_init(struct fuse_mount *fm)
                FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
                FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
                FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
-               FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP;
+               FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
+               FUSE_HAS_EXPIRE_ONLY;
 #ifdef CONFIG_FUSE_DAX
        if (fm->fc->dax)
                flags |= FUSE_MAP_ALIGNMENT;
index 8e01bfd..726640f 100644 (file)
@@ -9,14 +9,23 @@
 #include <linux/compat.h>
 #include <linux/fileattr.h>
 
-static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args)
+static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
+                              struct fuse_ioctl_out *outarg)
 {
-       ssize_t ret = fuse_simple_request(fm, args);
+       ssize_t ret;
+
+       args->out_args[0].size = sizeof(*outarg);
+       args->out_args[0].value = outarg;
+
+       ret = fuse_simple_request(fm, args);
 
        /* Translate ENOSYS, which shouldn't be returned from fs */
        if (ret == -ENOSYS)
                ret = -ENOTTY;
 
+       if (ret >= 0 && outarg->result == -ENOSYS)
+               outarg->result = -ENOTTY;
+
        return ret;
 }
 
@@ -264,13 +273,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
        }
 
        ap.args.out_numargs = 2;
-       ap.args.out_args[0].size = sizeof(outarg);
-       ap.args.out_args[0].value = &outarg;
        ap.args.out_args[1].size = out_size;
        ap.args.out_pages = true;
        ap.args.out_argvar = true;
 
-       transferred = fuse_send_ioctl(fm, &ap.args);
+       transferred = fuse_send_ioctl(fm, &ap.args, &outarg);
        err = transferred;
        if (transferred < 0)
                goto out;
@@ -399,12 +406,10 @@ static int fuse_priv_ioctl(struct inode *inode, struct fuse_file *ff,
        args.in_args[1].size = inarg.in_size;
        args.in_args[1].value = ptr;
        args.out_numargs = 2;
-       args.out_args[0].size = sizeof(outarg);
-       args.out_args[0].value = &outarg;
        args.out_args[1].size = inarg.out_size;
        args.out_args[1].value = ptr;
 
-       err = fuse_send_ioctl(fm, &args);
+       err = fuse_send_ioctl(fm, &args, &outarg);
        if (!err) {
                if (outarg.result < 0)
                        err = outarg.result;
index adb92cd..aa8967c 100644 (file)
@@ -872,10 +872,10 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *i,
        while ((ret = iomap_iter(&iter, ops)) > 0)
                iter.processed = iomap_write_iter(&iter, i);
 
-       if (unlikely(ret < 0))
+       if (unlikely(iter.pos == iocb->ki_pos))
                return ret;
        ret = iter.pos - iocb->ki_pos;
-       iocb->ki_pos += ret;
+       iocb->ki_pos = iter.pos;
        return ret;
 }
 EXPORT_SYMBOL_GPL(iomap_file_buffered_write);
index 51bd38d..9ec9101 100644 (file)
@@ -27,7 +27,7 @@
  *
  * Called with j_list_lock held.
  */
-static inline void __buffer_unlink_first(struct journal_head *jh)
+static inline void __buffer_unlink(struct journal_head *jh)
 {
        transaction_t *transaction = jh->b_cp_transaction;
 
@@ -41,45 +41,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh)
 }
 
 /*
- * Unlink a buffer from a transaction checkpoint(io) list.
- *
- * Called with j_list_lock held.
- */
-static inline void __buffer_unlink(struct journal_head *jh)
-{
-       transaction_t *transaction = jh->b_cp_transaction;
-
-       __buffer_unlink_first(jh);
-       if (transaction->t_checkpoint_io_list == jh) {
-               transaction->t_checkpoint_io_list = jh->b_cpnext;
-               if (transaction->t_checkpoint_io_list == jh)
-                       transaction->t_checkpoint_io_list = NULL;
-       }
-}
-
-/*
- * Move a buffer from the checkpoint list to the checkpoint io list
- *
- * Called with j_list_lock held
- */
-static inline void __buffer_relink_io(struct journal_head *jh)
-{
-       transaction_t *transaction = jh->b_cp_transaction;
-
-       __buffer_unlink_first(jh);
-
-       if (!transaction->t_checkpoint_io_list) {
-               jh->b_cpnext = jh->b_cpprev = jh;
-       } else {
-               jh->b_cpnext = transaction->t_checkpoint_io_list;
-               jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
-               jh->b_cpprev->b_cpnext = jh;
-               jh->b_cpnext->b_cpprev = jh;
-       }
-       transaction->t_checkpoint_io_list = jh;
-}
-
-/*
  * Check a checkpoint buffer could be release or not.
  *
  * Requires j_list_lock
@@ -183,6 +144,7 @@ __flush_batch(journal_t *journal, int *batch_count)
                struct buffer_head *bh = journal->j_chkpt_bhs[i];
                BUFFER_TRACE(bh, "brelse");
                __brelse(bh);
+               journal->j_chkpt_bhs[i] = NULL;
        }
        *batch_count = 0;
 }
@@ -242,15 +204,6 @@ restart:
                jh = transaction->t_checkpoint_list;
                bh = jh2bh(jh);
 
-               if (buffer_locked(bh)) {
-                       get_bh(bh);
-                       spin_unlock(&journal->j_list_lock);
-                       wait_on_buffer(bh);
-                       /* the journal_head may have gone by now */
-                       BUFFER_TRACE(bh, "brelse");
-                       __brelse(bh);
-                       goto retry;
-               }
                if (jh->b_transaction != NULL) {
                        transaction_t *t = jh->b_transaction;
                        tid_t tid = t->t_tid;
@@ -285,30 +238,50 @@ restart:
                        spin_lock(&journal->j_list_lock);
                        goto restart;
                }
-               if (!buffer_dirty(bh)) {
+               if (!trylock_buffer(bh)) {
+                       /*
+                        * The buffer is locked, it may be writing back, or
+                        * flushing out in the last couple of cycles, or
+                        * re-adding into a new transaction, need to check
+                        * it again until it's unlocked.
+                        */
+                       get_bh(bh);
+                       spin_unlock(&journal->j_list_lock);
+                       wait_on_buffer(bh);
+                       /* the journal_head may have gone by now */
+                       BUFFER_TRACE(bh, "brelse");
+                       __brelse(bh);
+                       goto retry;
+               } else if (!buffer_dirty(bh)) {
+                       unlock_buffer(bh);
                        BUFFER_TRACE(bh, "remove from checkpoint");
-                       if (__jbd2_journal_remove_checkpoint(jh))
-                               /* The transaction was released; we're done */
+                       /*
+                        * If the transaction was released or the checkpoint
+                        * list was empty, we're done.
+                        */
+                       if (__jbd2_journal_remove_checkpoint(jh) ||
+                           !transaction->t_checkpoint_list)
                                goto out;
-                       continue;
+               } else {
+                       unlock_buffer(bh);
+                       /*
+                        * We are about to write the buffer, it could be
+                        * raced by some other transaction shrink or buffer
+                        * re-log logic once we release the j_list_lock,
+                        * leave it on the checkpoint list and check status
+                        * again to make sure it's clean.
+                        */
+                       BUFFER_TRACE(bh, "queue");
+                       get_bh(bh);
+                       J_ASSERT_BH(bh, !buffer_jwrite(bh));
+                       journal->j_chkpt_bhs[batch_count++] = bh;
+                       transaction->t_chp_stats.cs_written++;
+                       transaction->t_checkpoint_list = jh->b_cpnext;
                }
-               /*
-                * Important: we are about to write the buffer, and
-                * possibly block, while still holding the journal
-                * lock.  We cannot afford to let the transaction
-                * logic start messing around with this buffer before
-                * we write it to disk, as that would break
-                * recoverability.
-                */
-               BUFFER_TRACE(bh, "queue");
-               get_bh(bh);
-               J_ASSERT_BH(bh, !buffer_jwrite(bh));
-               journal->j_chkpt_bhs[batch_count++] = bh;
-               __buffer_relink_io(jh);
-               transaction->t_chp_stats.cs_written++;
+
                if ((batch_count == JBD2_NR_BATCH) ||
-                   need_resched() ||
-                   spin_needbreak(&journal->j_list_lock))
+                   need_resched() || spin_needbreak(&journal->j_list_lock) ||
+                   jh2bh(transaction->t_checkpoint_list) == journal->j_chkpt_bhs[0])
                        goto unlock_and_flush;
        }
 
@@ -322,38 +295,6 @@ restart:
                        goto restart;
        }
 
-       /*
-        * Now we issued all of the transaction's buffers, let's deal
-        * with the buffers that are out for I/O.
-        */
-restart2:
-       /* Did somebody clean up the transaction in the meanwhile? */
-       if (journal->j_checkpoint_transactions != transaction ||
-           transaction->t_tid != this_tid)
-               goto out;
-
-       while (transaction->t_checkpoint_io_list) {
-               jh = transaction->t_checkpoint_io_list;
-               bh = jh2bh(jh);
-               if (buffer_locked(bh)) {
-                       get_bh(bh);
-                       spin_unlock(&journal->j_list_lock);
-                       wait_on_buffer(bh);
-                       /* the journal_head may have gone by now */
-                       BUFFER_TRACE(bh, "brelse");
-                       __brelse(bh);
-                       spin_lock(&journal->j_list_lock);
-                       goto restart2;
-               }
-
-               /*
-                * Now in whatever state the buffer currently is, we
-                * know that it has been written out and so we can
-                * drop it from the list
-                */
-               if (__jbd2_journal_remove_checkpoint(jh))
-                       break;
-       }
 out:
        spin_unlock(&journal->j_list_lock);
        result = jbd2_cleanup_journal_tail(journal);
@@ -409,49 +350,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
 /* Checkpoint list management */
 
 /*
- * journal_clean_one_cp_list
- *
- * Find all the written-back checkpoint buffers in the given list and
- * release them. If 'destroy' is set, clean all buffers unconditionally.
- *
- * Called with j_list_lock held.
- * Returns 1 if we freed the transaction, 0 otherwise.
- */
-static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy)
-{
-       struct journal_head *last_jh;
-       struct journal_head *next_jh = jh;
-
-       if (!jh)
-               return 0;
-
-       last_jh = jh->b_cpprev;
-       do {
-               jh = next_jh;
-               next_jh = jh->b_cpnext;
-
-               if (!destroy && __cp_buffer_busy(jh))
-                       return 0;
-
-               if (__jbd2_journal_remove_checkpoint(jh))
-                       return 1;
-               /*
-                * This function only frees up some memory
-                * if possible so we dont have an obligation
-                * to finish processing. Bail out if preemption
-                * requested:
-                */
-               if (need_resched())
-                       return 0;
-       } while (jh != last_jh);
-
-       return 0;
-}
-
-/*
  * journal_shrink_one_cp_list
  *
- * Find 'nr_to_scan' written-back checkpoint buffers in the given list
+ * Find all the written-back checkpoint buffers in the given list
  * and try to release them. If the whole transaction is released, set
  * the 'released' parameter. Return the number of released checkpointed
  * buffers.
@@ -459,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy)
  * Called with j_list_lock held.
  */
 static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
-                                               unsigned long *nr_to_scan,
-                                               bool *released)
+                                               bool destroy, bool *released)
 {
        struct journal_head *last_jh;
        struct journal_head *next_jh = jh;
        unsigned long nr_freed = 0;
        int ret;
 
-       if (!jh || *nr_to_scan == 0)
+       *released = false;
+       if (!jh)
                return 0;
 
        last_jh = jh->b_cpprev;
@@ -475,12 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
                jh = next_jh;
                next_jh = jh->b_cpnext;
 
-               (*nr_to_scan)--;
-               if (__cp_buffer_busy(jh))
-                       continue;
+               if (destroy) {
+                       ret = __jbd2_journal_remove_checkpoint(jh);
+               } else {
+                       ret = jbd2_journal_try_remove_checkpoint(jh);
+                       if (ret < 0)
+                               continue;
+               }
 
                nr_freed++;
-               ret = __jbd2_journal_remove_checkpoint(jh);
                if (ret) {
                        *released = true;
                        break;
@@ -488,7 +392,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
 
                if (need_resched())
                        break;
-       } while (jh != last_jh && *nr_to_scan);
+       } while (jh != last_jh);
 
        return nr_freed;
 }
@@ -506,11 +410,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal,
                                                  unsigned long *nr_to_scan)
 {
        transaction_t *transaction, *last_transaction, *next_transaction;
-       bool released;
+       bool __maybe_unused released;
        tid_t first_tid = 0, last_tid = 0, next_tid = 0;
        tid_t tid = 0;
        unsigned long nr_freed = 0;
-       unsigned long nr_scanned = *nr_to_scan;
+       unsigned long freed;
 
 again:
        spin_lock(&journal->j_list_lock);
@@ -539,19 +443,11 @@ again:
                transaction = next_transaction;
                next_transaction = transaction->t_cpnext;
                tid = transaction->t_tid;
-               released = false;
-
-               nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list,
-                                                      nr_to_scan, &released);
-               if (*nr_to_scan == 0)
-                       break;
-               if (need_resched() || spin_needbreak(&journal->j_list_lock))
-                       break;
-               if (released)
-                       continue;
 
-               nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list,
-                                                      nr_to_scan, &released);
+               freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list,
+                                                  false, &released);
+               nr_freed += freed;
+               (*nr_to_scan) -= min(*nr_to_scan, freed);
                if (*nr_to_scan == 0)
                        break;
                if (need_resched() || spin_needbreak(&journal->j_list_lock))
@@ -572,9 +468,8 @@ again:
        if (*nr_to_scan && next_tid)
                goto again;
 out:
-       nr_scanned -= *nr_to_scan;
        trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid,
-                                         nr_freed, nr_scanned, next_tid);
+                                         nr_freed, next_tid);
 
        return nr_freed;
 }
@@ -590,7 +485,7 @@ out:
 void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
 {
        transaction_t *transaction, *last_transaction, *next_transaction;
-       int ret;
+       bool released;
 
        transaction = journal->j_checkpoint_transactions;
        if (!transaction)
@@ -601,8 +496,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
        do {
                transaction = next_transaction;
                next_transaction = transaction->t_cpnext;
-               ret = journal_clean_one_cp_list(transaction->t_checkpoint_list,
-                                               destroy);
+               journal_shrink_one_cp_list(transaction->t_checkpoint_list,
+                                          destroy, &released);
                /*
                 * This function only frees up some memory if possible so we
                 * dont have an obligation to finish processing. Bail out if
@@ -610,23 +505,12 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
                 */
                if (need_resched())
                        return;
-               if (ret)
-                       continue;
-               /*
-                * It is essential that we are as careful as in the case of
-                * t_checkpoint_list with removing the buffer from the list as
-                * we can possibly see not yet submitted buffers on io_list
-                */
-               ret = journal_clean_one_cp_list(transaction->
-                               t_checkpoint_io_list, destroy);
-               if (need_resched())
-                       return;
                /*
                 * Stop scanning if we couldn't free the transaction. This
                 * avoids pointless scanning of transactions which still
                 * weren't checkpointed.
                 */
-               if (!ret)
+               if (!released)
                        return;
        } while (transaction != last_transaction);
 }
@@ -705,7 +589,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
        jbd2_journal_put_journal_head(jh);
 
        /* Is this transaction empty? */
-       if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list)
+       if (transaction->t_checkpoint_list)
                return 0;
 
        /*
@@ -737,6 +621,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
 }
 
 /*
+ * Check the checkpoint buffer and try to remove it from the checkpoint
+ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if
+ * it frees the transaction, 0 otherwise.
+ *
+ * This function is called with j_list_lock held.
+ */
+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh)
+{
+       struct buffer_head *bh = jh2bh(jh);
+
+       if (!trylock_buffer(bh))
+               return -EBUSY;
+       if (buffer_dirty(bh)) {
+               unlock_buffer(bh);
+               return -EBUSY;
+       }
+       unlock_buffer(bh);
+
+       /*
+        * Buffer is clean and the IO has finished (we held the buffer
+        * lock) so the checkpoint is done. We can safely remove the
+        * buffer from this transaction.
+        */
+       JBUFFER_TRACE(jh, "remove from checkpoint list");
+       return __jbd2_journal_remove_checkpoint(jh);
+}
+
+/*
  * journal_insert_checkpoint: put a committed buffer onto a checkpoint
  * list so that we know when it is safe to clean the transaction out of
  * the log.
@@ -797,7 +709,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
        J_ASSERT(transaction->t_forget == NULL);
        J_ASSERT(transaction->t_shadow_list == NULL);
        J_ASSERT(transaction->t_checkpoint_list == NULL);
-       J_ASSERT(transaction->t_checkpoint_io_list == NULL);
        J_ASSERT(atomic_read(&transaction->t_updates) == 0);
        J_ASSERT(journal->j_committing_transaction != transaction);
        J_ASSERT(journal->j_running_transaction != transaction);
index b33155d..1073259 100644 (file)
@@ -1141,8 +1141,7 @@ restart_loop:
        spin_lock(&journal->j_list_lock);
        commit_transaction->t_state = T_FINISHED;
        /* Check if the transaction can be dropped now that we are finished */
-       if (commit_transaction->t_checkpoint_list == NULL &&
-           commit_transaction->t_checkpoint_io_list == NULL) {
+       if (commit_transaction->t_checkpoint_list == NULL) {
                __jbd2_journal_drop_transaction(journal, commit_transaction);
                jbd2_journal_free_transaction(commit_transaction);
        }
index 1861124..4d1fda1 100644 (file)
@@ -1784,8 +1784,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh)
                 * Otherwise, if the buffer has been written to disk,
                 * it is safe to remove the checkpoint and drop it.
                 */
-               if (!buffer_dirty(bh)) {
-                       __jbd2_journal_remove_checkpoint(jh);
+               if (jbd2_journal_try_remove_checkpoint(jh) >= 0) {
                        spin_unlock(&journal->j_list_lock);
                        goto drop;
                }
@@ -2100,35 +2099,6 @@ void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
        __brelse(bh);
 }
 
-/*
- * Called from jbd2_journal_try_to_free_buffers().
- *
- * Called under jh->b_state_lock
- */
-static void
-__journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
-{
-       struct journal_head *jh;
-
-       jh = bh2jh(bh);
-
-       if (buffer_locked(bh) || buffer_dirty(bh))
-               goto out;
-
-       if (jh->b_next_transaction != NULL || jh->b_transaction != NULL)
-               goto out;
-
-       spin_lock(&journal->j_list_lock);
-       if (jh->b_cp_transaction != NULL) {
-               /* written-back checkpointed metadata buffer */
-               JBUFFER_TRACE(jh, "remove from checkpoint list");
-               __jbd2_journal_remove_checkpoint(jh);
-       }
-       spin_unlock(&journal->j_list_lock);
-out:
-       return;
-}
-
 /**
  * jbd2_journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
@@ -2186,7 +2156,13 @@ bool jbd2_journal_try_to_free_buffers(journal_t *journal, struct folio *folio)
                        continue;
 
                spin_lock(&jh->b_state_lock);
-               __journal_try_to_free_buffer(journal, bh);
+               if (!jh->b_transaction && !jh->b_next_transaction) {
+                       spin_lock(&journal->j_list_lock);
+                       /* Remove written-back checkpointed metadata buffer */
+                       if (jh->b_cp_transaction != NULL)
+                               jbd2_journal_try_remove_checkpoint(jh);
+                       spin_unlock(&journal->j_list_lock);
+               }
                spin_unlock(&jh->b_state_lock);
                jbd2_journal_put_journal_head(jh);
                if (buffer_jbd(bh))
index 6e61fa3..3aefbad 100644 (file)
@@ -6341,8 +6341,6 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
                CLOSE_STATEID(stateid))
                return status;
-       if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid))
-               return status;
        spin_lock(&cl->cl_lock);
        s = find_stateid_locked(cl, stateid);
        if (!s)
index 5b069f1..cc89774 100644 (file)
@@ -1460,7 +1460,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
                ovl_trusted_xattr_handlers;
        sb->s_fs_info = ofs;
        sb->s_flags |= SB_POSIXACL;
-       sb->s_iflags |= SB_I_SKIP_SYNC;
+       sb->s_iflags |= SB_I_SKIP_SYNC | SB_I_IMA_UNVERIFIABLE_SIGNATURE;
 
        err = -ENOMEM;
        root_dentry = ovl_get_root(sb, ctx->upper.dentry, oe);
index d7274ee..15c8cc4 100644 (file)
@@ -159,6 +159,6 @@ extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
 /* when changing internal version - update following two lines at same time */
-#define SMB3_PRODUCT_BUILD 43
-#define CIFS_VERSION   "2.43"
+#define SMB3_PRODUCT_BUILD 44
+#define CIFS_VERSION   "2.44"
 #endif                         /* _CIFSFS_H */
index fff092b..e1904b8 100644 (file)
@@ -433,16 +433,21 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                         * Dump encryption keys. This is an old ioctl that only
                         * handles AES-128-{CCM,GCM}.
                         */
-                       if (pSMBFile == NULL)
-                               break;
                        if (!capable(CAP_SYS_ADMIN)) {
                                rc = -EACCES;
                                break;
                        }
 
-                       tcon = tlink_tcon(pSMBFile->tlink);
+                       cifs_sb = CIFS_SB(inode->i_sb);
+                       tlink = cifs_sb_tlink(cifs_sb);
+                       if (IS_ERR(tlink)) {
+                               rc = PTR_ERR(tlink);
+                               break;
+                       }
+                       tcon = tlink_tcon(tlink);
                        if (!smb3_encryption_required(tcon)) {
                                rc = -EOPNOTSUPP;
+                               cifs_put_tlink(tlink);
                                break;
                        }
                        pkey_inf.cipher_type =
@@ -459,6 +464,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                rc = -EFAULT;
                        else
                                rc = 0;
+                       cifs_put_tlink(tlink);
                        break;
                case CIFS_DUMP_FULL_KEY:
                        /*
@@ -470,8 +476,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                rc = -EACCES;
                                break;
                        }
-                       tcon = tlink_tcon(pSMBFile->tlink);
+                       cifs_sb = CIFS_SB(inode->i_sb);
+                       tlink = cifs_sb_tlink(cifs_sb);
+                       tcon = tlink_tcon(tlink);
                        rc = cifs_dump_full_key(tcon, (void __user *)arg);
+                       cifs_put_tlink(tlink);
                        break;
                case CIFS_IOC_NOTIFY:
                        if (!S_ISDIR(inode->i_mode)) {
index fb8b2d5..b7521e4 100644 (file)
@@ -352,7 +352,8 @@ enum KSMBD_TREE_CONN_STATUS {
 #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_UPDATE                        BIT(14)
+#define KSMBD_SHARE_FLAG_CROSSMNT              BIT(15)
 
 /*
  * Tree connect request flags.
index ced7a9e..9df121b 100644 (file)
@@ -286,6 +286,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
 static int queue_ksmbd_work(struct ksmbd_conn *conn)
 {
        struct ksmbd_work *work;
+       int err;
 
        work = ksmbd_alloc_work_struct();
        if (!work) {
@@ -297,7 +298,11 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
        work->request_buf = conn->request_buf;
        conn->request_buf = NULL;
 
-       ksmbd_init_smb_server(work);
+       err = ksmbd_init_smb_server(work);
+       if (err) {
+               ksmbd_free_work_struct(work);
+               return 0;
+       }
 
        ksmbd_conn_enqueue_request(work);
        atomic_inc(&conn->r_count);
index cf88221..9849d74 100644 (file)
@@ -87,9 +87,9 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
  */
 int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
 {
-       struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+       struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
        unsigned int cmd = le16_to_cpu(req_hdr->Command);
-       int tree_id;
+       unsigned int tree_id;
 
        if (cmd == SMB2_TREE_CONNECT_HE ||
            cmd ==  SMB2_CANCEL_HE ||
@@ -114,7 +114,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
                        pr_err("The first operation in the compound does not have tcon\n");
                        return -EINVAL;
                }
-               if (work->tcon->id != tree_id) {
+               if (tree_id != UINT_MAX && work->tcon->id != tree_id) {
                        pr_err("tree id(%u) is different with id(%u) in first operation\n",
                                        tree_id, work->tcon->id);
                        return -EINVAL;
@@ -559,9 +559,9 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
  */
 int smb2_check_user_session(struct ksmbd_work *work)
 {
-       struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+       struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
        struct ksmbd_conn *conn = work->conn;
-       unsigned int cmd = conn->ops->get_cmd_val(work);
+       unsigned int cmd = le16_to_cpu(req_hdr->Command);
        unsigned long long sess_id;
 
        /*
@@ -587,7 +587,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
                        pr_err("The first operation in the compound does not have sess\n");
                        return -EINVAL;
                }
-               if (work->sess->id != sess_id) {
+               if (sess_id != ULLONG_MAX && work->sess->id != sess_id) {
                        pr_err("session id(%llu) is different with the first operation(%lld)\n",
                                        sess_id, work->sess->id);
                        return -EINVAL;
@@ -2467,8 +2467,9 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
        }
 }
 
-static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
-                     int open_flags, umode_t posix_mode, bool is_dir)
+static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
+                     struct path *path, char *name, int open_flags,
+                     umode_t posix_mode, bool is_dir)
 {
        struct ksmbd_tree_connect *tcon = work->tcon;
        struct ksmbd_share_config *share = tcon->share_conf;
@@ -2495,7 +2496,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
                        return rc;
        }
 
-       rc = ksmbd_vfs_kern_path_locked(work, name, 0, path, 0);
+       rc = ksmbd_vfs_kern_path_locked(work, name, 0, parent_path, path, 0);
        if (rc) {
                pr_err("cannot get linux path (%s), err = %d\n",
                       name, rc);
@@ -2565,7 +2566,7 @@ int smb2_open(struct ksmbd_work *work)
        struct ksmbd_tree_connect *tcon = work->tcon;
        struct smb2_create_req *req;
        struct smb2_create_rsp *rsp;
-       struct path path;
+       struct path path, parent_path;
        struct ksmbd_share_config *share = tcon->share_conf;
        struct ksmbd_file *fp = NULL;
        struct file *filp = NULL;
@@ -2786,7 +2787,8 @@ int smb2_open(struct ksmbd_work *work)
                goto err_out1;
        }
 
-       rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
+       rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
+                                       &parent_path, &path, 1);
        if (!rc) {
                file_present = true;
 
@@ -2906,7 +2908,8 @@ int smb2_open(struct ksmbd_work *work)
 
        /*create file if not present */
        if (!file_present) {
-               rc = smb2_creat(work, &path, name, open_flags, posix_mode,
+               rc = smb2_creat(work, &parent_path, &path, name, open_flags,
+                               posix_mode,
                                req->CreateOptions & FILE_DIRECTORY_FILE_LE);
                if (rc) {
                        if (rc == -ENOENT) {
@@ -3321,8 +3324,9 @@ int smb2_open(struct ksmbd_work *work)
 
 err_out:
        if (file_present || created) {
-               inode_unlock(d_inode(path.dentry->d_parent));
-               dput(path.dentry);
+               inode_unlock(d_inode(parent_path.dentry));
+               path_put(&path);
+               path_put(&parent_path);
        }
        ksmbd_revert_fsids(work);
 err_out1:
@@ -5545,7 +5549,7 @@ static int smb2_create_link(struct ksmbd_work *work,
                            struct nls_table *local_nls)
 {
        char *link_name = NULL, *target_name = NULL, *pathname = NULL;
-       struct path path;
+       struct path path, parent_path;
        bool file_present = false;
        int rc;
 
@@ -5575,7 +5579,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 
        ksmbd_debug(SMB, "target name is %s\n", target_name);
        rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
-                                       &path, 0);
+                                       &parent_path, &path, 0);
        if (rc) {
                if (rc != -ENOENT)
                        goto out;
@@ -5605,8 +5609,9 @@ static int smb2_create_link(struct ksmbd_work *work,
                rc = -EINVAL;
 out:
        if (file_present) {
-               inode_unlock(d_inode(path.dentry->d_parent));
+               inode_unlock(d_inode(parent_path.dentry));
                path_put(&path);
+               path_put(&parent_path);
        }
        if (!IS_ERR(link_name))
                kfree(link_name);
@@ -6209,6 +6214,11 @@ int smb2_read(struct ksmbd_work *work)
        unsigned int max_read_size = conn->vals->max_read_size;
 
        WORK_BUFFERS(work, req, rsp);
+       if (work->next_smb2_rcv_hdr_off) {
+               work->send_no_response = 1;
+               err = -EOPNOTSUPP;
+               goto out;
+       }
 
        if (test_share_config_flag(work->tcon->share_conf,
                                   KSMBD_SHARE_FLAG_PIPE)) {
@@ -8609,7 +8619,8 @@ int smb3_decrypt_req(struct ksmbd_work *work)
        struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
        int rc = 0;
 
-       if (buf_data_size < sizeof(struct smb2_hdr)) {
+       if (pdu_length < sizeof(struct smb2_transform_hdr) ||
+           buf_data_size < sizeof(struct smb2_hdr)) {
                pr_err("Transform message is too small (%u)\n",
                       pdu_length);
                return -ECONNABORTED;
index ef20f63..c2b75d8 100644 (file)
@@ -388,26 +388,29 @@ static struct smb_version_cmds smb1_server_cmds[1] = {
        [SMB_COM_NEGOTIATE_EX]  = { .proc = smb1_negotiate, },
 };
 
-static void init_smb1_server(struct ksmbd_conn *conn)
+static int init_smb1_server(struct ksmbd_conn *conn)
 {
        conn->ops = &smb1_server_ops;
        conn->cmds = smb1_server_cmds;
        conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+       return 0;
 }
 
-void ksmbd_init_smb_server(struct ksmbd_work *work)
+int ksmbd_init_smb_server(struct ksmbd_work *work)
 {
        struct ksmbd_conn *conn = work->conn;
        __le32 proto;
 
-       if (conn->need_neg == false)
-               return;
-
        proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+       if (conn->need_neg == false) {
+               if (proto == SMB1_PROTO_NUMBER)
+                       return -EINVAL;
+               return 0;
+       }
+
        if (proto == SMB1_PROTO_NUMBER)
-               init_smb1_server(conn);
-       else
-               init_smb3_11_server(conn);
+               return init_smb1_server(conn);
+       return init_smb3_11_server(conn);
 }
 
 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
index aeca0f4..f109251 100644 (file)
@@ -427,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
 
 int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
 
-void ksmbd_init_smb_server(struct ksmbd_work *work);
+int ksmbd_init_smb_server(struct ksmbd_work *work);
 
 struct ksmbd_kstat;
 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
index e359144..3d5d652 100644 (file)
@@ -63,13 +63,13 @@ int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
 
 static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
                                        char *pathname, unsigned int flags,
+                                       struct path *parent_path,
                                        struct path *path)
 {
        struct qstr last;
        struct filename *filename;
        struct path *root_share_path = &share_conf->vfs_path;
        int err, type;
-       struct path parent_path;
        struct dentry *d;
 
        if (pathname[0] == '\0') {
@@ -84,7 +84,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
                return PTR_ERR(filename);
 
        err = vfs_path_parent_lookup(filename, flags,
-                                    &parent_path, &last, &type,
+                                    parent_path, &last, &type,
                                     root_share_path);
        if (err) {
                putname(filename);
@@ -92,13 +92,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        }
 
        if (unlikely(type != LAST_NORM)) {
-               path_put(&parent_path);
+               path_put(parent_path);
                putname(filename);
                return -ENOENT;
        }
 
-       inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
-       d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
+       inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
+       d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
        if (IS_ERR(d))
                goto err_out;
 
@@ -108,15 +108,22 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        }
 
        path->dentry = d;
-       path->mnt = share_conf->vfs_path.mnt;
-       path_put(&parent_path);
-       putname(filename);
+       path->mnt = mntget(parent_path->mnt);
 
+       if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_CROSSMNT)) {
+               err = follow_down(path, 0);
+               if (err < 0) {
+                       path_put(path);
+                       goto err_out;
+               }
+       }
+
+       putname(filename);
        return 0;
 
 err_out:
-       inode_unlock(parent_path.dentry->d_inode);
-       path_put(&parent_path);
+       inode_unlock(d_inode(parent_path->dentry));
+       path_put(parent_path);
        putname(filename);
        return -ENOENT;
 }
@@ -412,7 +419,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
 {
        char *stream_buf = NULL, *wbuf;
        struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);
-       size_t size, v_len;
+       size_t size;
+       ssize_t v_len;
        int err = 0;
 
        ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
@@ -429,9 +437,9 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
                                       fp->stream.name,
                                       fp->stream.size,
                                       &stream_buf);
-       if ((int)v_len < 0) {
+       if (v_len < 0) {
                pr_err("not found stream in xattr : %zd\n", v_len);
-               err = (int)v_len;
+               err = v_len;
                goto out;
        }
 
@@ -1194,14 +1202,14 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
  * Return:     0 on success, otherwise error
  */
 int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
-                              unsigned int flags, struct path *path,
-                              bool caseless)
+                              unsigned int flags, struct path *parent_path,
+                              struct path *path, bool caseless)
 {
        struct ksmbd_share_config *share_conf = work->tcon->share_conf;
        int err;
-       struct path parent_path;
 
-       err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, path);
+       err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, parent_path,
+                                          path);
        if (!err)
                return 0;
 
@@ -1216,10 +1224,10 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
                path_len = strlen(filepath);
                remain_len = path_len;
 
-               parent_path = share_conf->vfs_path;
-               path_get(&parent_path);
+               *parent_path = share_conf->vfs_path;
+               path_get(parent_path);
 
-               while (d_can_lookup(parent_path.dentry)) {
+               while (d_can_lookup(parent_path->dentry)) {
                        char *filename = filepath + path_len - remain_len;
                        char *next = strchrnul(filename, '/');
                        size_t filename_len = next - filename;
@@ -1228,7 +1236,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
                        if (filename_len == 0)
                                break;
 
-                       err = ksmbd_vfs_lookup_in_dir(&parent_path, filename,
+                       err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
                                                      filename_len,
                                                      work->conn->um);
                        if (err)
@@ -1245,8 +1253,8 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
                                goto out2;
                        else if (is_last)
                                goto out1;
-                       path_put(&parent_path);
-                       parent_path = *path;
+                       path_put(parent_path);
+                       *parent_path = *path;
 
                        next[0] = '/';
                        remain_len -= filename_len + 1;
@@ -1254,16 +1262,17 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
 
                err = -EINVAL;
 out2:
-               path_put(&parent_path);
+               path_put(parent_path);
 out1:
                kfree(filepath);
        }
 
        if (!err) {
-               err = ksmbd_vfs_lock_parent(parent_path.dentry, path->dentry);
-               if (err)
-                       dput(path->dentry);
-               path_put(&parent_path);
+               err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
+               if (err) {
+                       path_put(path);
+                       path_put(parent_path);
+               }
        }
        return err;
 }
index 8003931..72f9fb4 100644 (file)
@@ -115,8 +115,8 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
 int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
                           const struct path *path, char *attr_name);
 int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
-                              unsigned int flags, struct path *path,
-                              bool caseless);
+                              unsigned int flags, struct path *parent_path,
+                              struct path *path, bool caseless);
 struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
                                          const char *name,
                                          unsigned int flags,
index 004eb1c..3e2a31e 100644 (file)
@@ -876,6 +876,8 @@ ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
                        msg.msg_flags |= MSG_MORE;
                if (remain && pipe_occupancy(pipe->head, tail) > 0)
                        msg.msg_flags |= MSG_MORE;
+               if (out->f_flags & O_NONBLOCK)
+                       msg.msg_flags |= MSG_DONTWAIT;
 
                iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, bvec, bc,
                              len - remain);
index 25e2841..f9015f8 100644 (file)
@@ -591,7 +591,7 @@ struct xfs_attr_shortform {
                uint8_t valuelen;       /* actual length of value (no NULL) */
                uint8_t flags;  /* flags bits (see xfs_attr_leaf.h) */
                uint8_t nameval[];      /* name & value bytes concatenated */
-       } list[1];                      /* variable sized array */
+       } list[];                       /* variable sized array */
 };
 
 typedef struct xfs_attr_leaf_map {     /* RLE map of free bytes */
@@ -620,19 +620,29 @@ typedef struct xfs_attr_leaf_entry {      /* sorted on key, not name */
 typedef struct xfs_attr_leaf_name_local {
        __be16  valuelen;               /* number of bytes in value */
        __u8    namelen;                /* length of name bytes */
-       __u8    nameval[1];             /* name/value bytes */
+       /*
+        * In Linux 6.5 this flex array was converted from nameval[1] to
+        * nameval[].  Be very careful here about extra padding at the end;
+        * see xfs_attr_leaf_entsize_local() for details.
+        */
+       __u8    nameval[];              /* name/value bytes */
 } xfs_attr_leaf_name_local_t;
 
 typedef struct xfs_attr_leaf_name_remote {
        __be32  valueblk;               /* block number of value bytes */
        __be32  valuelen;               /* number of bytes in value */
        __u8    namelen;                /* length of name bytes */
-       __u8    name[1];                /* name bytes */
+       /*
+        * In Linux 6.5 this flex array was converted from name[1] to name[].
+        * Be very careful here about extra padding at the end; see
+        * xfs_attr_leaf_entsize_remote() for details.
+        */
+       __u8    name[];                 /* name bytes */
 } xfs_attr_leaf_name_remote_t;
 
 typedef struct xfs_attr_leafblock {
        xfs_attr_leaf_hdr_t     hdr;    /* constant-structure header block */
-       xfs_attr_leaf_entry_t   entries[1];     /* sorted on key, not name */
+       xfs_attr_leaf_entry_t   entries[];      /* sorted on key, not name */
        /*
         * The rest of the block contains the following structures after the
         * leaf entries, growing from the bottom up. The variables are never
@@ -664,7 +674,7 @@ struct xfs_attr3_leaf_hdr {
 
 struct xfs_attr3_leafblock {
        struct xfs_attr3_leaf_hdr       hdr;
-       struct xfs_attr_leaf_entry      entries[1];
+       struct xfs_attr_leaf_entry      entries[];
 
        /*
         * The rest of the block contains the following structures after the
@@ -747,14 +757,61 @@ xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
  */
 static inline int xfs_attr_leaf_entsize_remote(int nlen)
 {
-       return round_up(sizeof(struct xfs_attr_leaf_name_remote) - 1 +
-                       nlen, XFS_ATTR_LEAF_NAME_ALIGN);
+       /*
+        * Prior to Linux 6.5, struct xfs_attr_leaf_name_remote ended with
+        * name[1], which was used as a flexarray.  The layout of this struct
+        * is 9 bytes of fixed-length fields followed by a __u8 flex array at
+        * offset 9.
+        *
+        * On most architectures, struct xfs_attr_leaf_name_remote had two
+        * bytes of implicit padding at the end of the struct to make the
+        * struct length 12.  After converting name[1] to name[], there are
+        * three implicit padding bytes and the struct size remains 12.
+        * However, there are compiler configurations that do not add implicit
+        * padding at all (m68k) and have been broken for years.
+        *
+        * This entsize computation historically added (the xattr name length)
+        * to (the padded struct length - 1) and rounded that sum up to the
+        * nearest multiple of 4 (NAME_ALIGN).  IOWs, round_up(11 + nlen, 4).
+        * This is encoded in the ondisk format, so we cannot change this.
+        *
+        * Compute the entsize from offsetof of the flexarray and manually
+        * adding bytes for the implicit padding.
+        */
+       const size_t remotesize =
+                       offsetof(struct xfs_attr_leaf_name_remote, name) + 2;
+
+       return round_up(remotesize + nlen, XFS_ATTR_LEAF_NAME_ALIGN);
 }
 
 static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
 {
-       return round_up(sizeof(struct xfs_attr_leaf_name_local) - 1 +
-                       nlen + vlen, XFS_ATTR_LEAF_NAME_ALIGN);
+       /*
+        * Prior to Linux 6.5, struct xfs_attr_leaf_name_local ended with
+        * nameval[1], which was used as a flexarray.  The layout of this
+        * struct is 3 bytes of fixed-length fields followed by a __u8 flex
+        * array at offset 3.
+        *
+        * struct xfs_attr_leaf_name_local had zero bytes of implicit padding
+        * at the end of the struct to make the struct length 4.  On most
+        * architectures, after converting nameval[1] to nameval[], there is
+        * one implicit padding byte and the struct size remains 4.  However,
+        * there are compiler configurations that do not add implicit padding
+        * at all (m68k) and would break.
+        *
+        * This entsize computation historically added (the xattr name and
+        * value length) to (the padded struct length - 1) and rounded that sum
+        * up to the nearest multiple of 4 (NAME_ALIGN).  IOWs, the formula is
+        * round_up(3 + nlen + vlen, 4).  This is encoded in the ondisk format,
+        * so we cannot change this.
+        *
+        * Compute the entsize from offsetof of the flexarray and manually
+        * adding bytes for the implicit padding.
+        */
+       const size_t localsize =
+                       offsetof(struct xfs_attr_leaf_name_local, nameval);
+
+       return round_up(localsize + nlen + vlen, XFS_ATTR_LEAF_NAME_ALIGN);
 }
 
 static inline int xfs_attr_leaf_entsize_local_max(int bsize)
index 9c60ebb..2cbf9ea 100644 (file)
@@ -592,12 +592,12 @@ typedef struct xfs_attrlist_cursor {
 struct xfs_attrlist {
        __s32   al_count;       /* number of entries in attrlist */
        __s32   al_more;        /* T/F: more attrs (do call again) */
-       __s32   al_offset[1];   /* byte offsets of attrs [var-sized] */
+       __s32   al_offset[];    /* byte offsets of attrs [var-sized] */
 };
 
 struct xfs_attrlist_ent {      /* data from attr_list() */
        __u32   a_valuelen;     /* number bytes in value of attr */
-       char    a_name[1];      /* attr name (NULL terminated) */
+       char    a_name[];       /* attr name (NULL terminated) */
 };
 
 typedef struct xfs_fsop_attrlist_handlereq {
index 9737b5a..c4cc99b 100644 (file)
@@ -56,7 +56,7 @@ xfs_check_ondisk_structs(void)
 
        /* dir/attr trees */
        XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr,        80);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock,       88);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock,       80);
        XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_rmt_hdr,         56);
        XFS_CHECK_STRUCT_SIZE(struct xfs_da3_blkinfo,           56);
        XFS_CHECK_STRUCT_SIZE(struct xfs_da3_intnode,           64);
@@ -88,7 +88,8 @@ xfs_check_ondisk_structs(void)
        XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4);
        XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen,  8);
        XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name,     9);
-       XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t,             40);
+       XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t,             32);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_attr_shortform,        4);
        XFS_CHECK_OFFSET(struct xfs_attr_shortform, hdr.totsize, 0);
        XFS_CHECK_OFFSET(struct xfs_attr_shortform, hdr.count,   2);
        XFS_CHECK_OFFSET(struct xfs_attr_shortform, list[0].namelen,    4);
index 4863b0f..375737f 100644 (file)
@@ -368,11 +368,6 @@ static inline void drm_fb_helper_deferred_io(struct fb_info *info,
 {
 }
 
-static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
-{
-       return -ENODEV;
-}
-
 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
                                             bool suspend)
 {
index 402b545..5b27f94 100644 (file)
@@ -431,7 +431,7 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
 
 int vgic_v4_load(struct kvm_vcpu *vcpu);
 void vgic_v4_commit(struct kvm_vcpu *vcpu);
-int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db);
+int vgic_v4_put(struct kvm_vcpu *vcpu);
 
 /* CPU HP callbacks */
 void kvm_vgic_cpu_up(void);
index b96e004..495ca19 100644 (file)
@@ -397,8 +397,6 @@ struct blk_mq_hw_ctx {
         */
        struct blk_mq_tags      *sched_tags;
 
-       /** @queued: Number of queued requests. */
-       unsigned long           queued;
        /** @run: Number of dispatched requests. */
        unsigned long           run;
 
index d860499..44c298a 100644 (file)
@@ -614,12 +614,6 @@ struct transaction_s
        struct journal_head     *t_checkpoint_list;
 
        /*
-        * Doubly-linked circular list of all buffers submitted for IO while
-        * checkpointing. [j_list_lock]
-        */
-       struct journal_head     *t_checkpoint_io_list;
-
-       /*
         * Doubly-linked circular list of metadata buffers being
         * shadowed by log IO.  The IO buffers on the iobuf list and
         * the shadow buffers on this list match each other one for
@@ -1449,6 +1443,7 @@ extern void jbd2_journal_commit_transaction(journal_t *);
 void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy);
 unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan);
 int __jbd2_journal_remove_checkpoint(struct journal_head *);
+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh);
 void jbd2_journal_destroy_checkpoint(journal_t *journal);
 void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
index b4c08ac..91a37c9 100644 (file)
@@ -513,7 +513,7 @@ static inline void fastopen_queue_tune(struct sock *sk, int backlog)
        struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
        int somaxconn = READ_ONCE(sock_net(sk)->core.sysctl_somaxconn);
 
-       queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn);
+       WRITE_ONCE(queue->fastopenq.max_qlen, min_t(unsigned int, backlog, somaxconn));
 }
 
 static inline void tcp_move_syn(struct tcp_sock *tp,
index 9654567..e01d52c 100644 (file)
@@ -593,9 +593,7 @@ struct hci_dev {
        const char              *fw_info;
        struct dentry           *debugfs;
 
-#ifdef CONFIG_DEV_COREDUMP
        struct hci_devcoredump  dump;
-#endif
 
        struct device           dev;
 
@@ -822,6 +820,7 @@ struct hci_conn_params {
 
        struct hci_conn *conn;
        bool explicit_connect;
+       /* Accessed without hdev->lock: */
        hci_conn_flags_t flags;
        u8  privacy_mode;
 };
@@ -1573,7 +1572,11 @@ struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
                                            bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_clear_disabled(struct hci_dev *hdev);
+void hci_conn_params_free(struct hci_conn_params *param);
 
+void hci_pend_le_list_del_init(struct hci_conn_params *param);
+void hci_pend_le_list_add(struct hci_conn_params *param,
+                         struct list_head *list);
 struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
                                                  bdaddr_t *addr,
                                                  u8 addr_type);
index b57bec6..30ac427 100644 (file)
@@ -277,7 +277,7 @@ struct bond_vlan_tag {
        unsigned short  vlan_id;
 };
 
-/**
+/*
  * Returns NULL if the net_device does not belong to any of the bond's slaves
  *
  * Caller must hold bond lock for read
index e000579..f79ce13 100644 (file)
@@ -170,7 +170,8 @@ wpan_phy_cca_cmp(const struct wpan_phy_cca *a, const struct wpan_phy_cca *b)
 }
 
 /**
- * @WPAN_PHY_FLAG_TRANSMIT_POWER: Indicates that transceiver will support
+ * enum wpan_phy_flags - WPAN PHY state flags
+ * @WPAN_PHY_FLAG_TXPOWER: Indicates that transceiver will support
  *     transmit power setting.
  * @WPAN_PHY_FLAG_CCA_ED_LEVEL: Indicates that transceiver will support cca ed
  *     level setting.
index 5fed2f1..aa80f74 100644 (file)
@@ -145,8 +145,8 @@ struct codel_vars {
  * @maxpacket: largest packet we've seen so far
  * @drop_count:        temp count of dropped packets in dequeue()
  * @drop_len:  bytes of dropped packets in dequeue()
- * ecn_mark:   number of packets we ECN marked instead of dropping
- * ce_mark:    number of packets CE marked because sojourn time was above ce_threshold
+ * @ecn_mark:  number of packets we ECN marked instead of dropping
+ * @ce_mark:   number of packets CE marked because sojourn time was above ce_threshold
  */
 struct codel_stats {
        u32             maxpacket;
index 9a3c51a..0cdb4b1 100644 (file)
@@ -221,7 +221,7 @@ struct devlink_dpipe_field {
 /**
  * struct devlink_dpipe_header - dpipe header object
  * @name: header name
- * @id: index, global/local detrmined by global bit
+ * @id: index, global/local determined by global bit
  * @fields: fields
  * @fields_count: number of fields
  * @global: indicates if header is shared like most protocol header
@@ -241,7 +241,7 @@ struct devlink_dpipe_header {
  * @header_index: header index (packets can have several headers of same
  *               type like in case of tunnels)
  * @header: header
- * @fieled_id: field index
+ * @field_id: field index
  */
 struct devlink_dpipe_match {
        enum devlink_dpipe_match_type type;
@@ -256,7 +256,7 @@ struct devlink_dpipe_match {
  * @header_index: header index (packets can have several headers of same
  *               type like in case of tunnels)
  * @header: header
- * @fieled_id: field index
+ * @field_id: field index
  */
 struct devlink_dpipe_action {
        enum devlink_dpipe_action_type type;
@@ -292,7 +292,7 @@ struct devlink_dpipe_value {
  * struct devlink_dpipe_entry - table entry object
  * @index: index of the entry in the table
  * @match_values: match values
- * @matche_values_count: count of matches tuples
+ * @match_values_count: count of matches tuples
  * @action_values: actions values
  * @action_values_count: count of actions values
  * @counter: value of counter
@@ -342,7 +342,9 @@ struct devlink_dpipe_table_ops;
  */
 struct devlink_dpipe_table {
        void *priv;
+       /* private: */
        struct list_head list;
+       /* public: */
        const char *name;
        bool counters_enabled;
        bool counter_control_extern;
@@ -355,13 +357,13 @@ struct devlink_dpipe_table {
 
 /**
  * struct devlink_dpipe_table_ops - dpipe_table ops
- * @actions_dump - dumps all tables actions
- * @matches_dump - dumps all tables matches
- * @entries_dump - dumps all active entries in the table
- * @counters_set_update - when changing the counter status hardware sync
+ * @actions_dump: dumps all tables actions
+ * @matches_dump: dumps all tables matches
+ * @entries_dump: dumps all active entries in the table
+ * @counters_set_update when changing the counter status hardware sync
  *                       maybe needed to allocate/free counter related
  *                       resources
- * @size_get - get size
+ * @size_get: get size
  */
 struct devlink_dpipe_table_ops {
        int (*actions_dump)(void *priv, struct sk_buff *skb);
@@ -374,8 +376,8 @@ struct devlink_dpipe_table_ops {
 
 /**
  * struct devlink_dpipe_headers - dpipe headers
- * @headers - header array can be shared (global bit) or driver specific
- * @headers_count - count of headers
+ * @headers: header array can be shared (global bit) or driver specific
+ * @headers_count: count of headers
  */
 struct devlink_dpipe_headers {
        struct devlink_dpipe_header **headers;
@@ -387,7 +389,7 @@ struct devlink_dpipe_headers {
  * @size_min: minimum size which can be set
  * @size_max: maximum size which can be set
  * @size_granularity: size granularity
- * @size_unit: resource's basic unit
+ * @unit: resource's basic unit
  */
 struct devlink_resource_size_params {
        u64 size_min;
@@ -457,6 +459,7 @@ struct devlink_flash_notify {
 
 /**
  * struct devlink_param - devlink configuration parameter data
+ * @id: devlink parameter id number
  * @name: name of the parameter
  * @generic: indicates if the parameter is generic or driver specific
  * @type: parameter type
@@ -632,6 +635,7 @@ enum devlink_param_generic_id {
  * struct devlink_flash_update_params - Flash Update parameters
  * @fw: pointer to the firmware data to update from
  * @component: the flash component to update
+ * @overwrite_mask: which types of flash update are supported (may be %0)
  *
  * With the exception of fw, drivers must opt-in to parameters by
  * setting the appropriate bit in the supported_flash_update_params field in
index 325ad89..1539606 100644 (file)
@@ -29,7 +29,7 @@ struct fqdir {
 };
 
 /**
- * fragment queue flags
+ * enum: fragment queue flags
  *
  * @INET_FRAG_FIRST_IN: first fragment has arrived
  * @INET_FRAG_LAST_IN: final fragment has arrived
index 7332296..2acc4c8 100644 (file)
@@ -752,12 +752,8 @@ static inline u32 ipv6_addr_hash(const struct in6_addr *a)
 /* more secured version of ipv6_addr_hash() */
 static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 initval)
 {
-       u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1];
-
-       return jhash_3words(v,
-                           (__force u32)a->s6_addr32[2],
-                           (__force u32)a->s6_addr32[3],
-                           initval);
+       return jhash2((__force const u32 *)a->s6_addr32,
+                     ARRAY_SIZE(a->s6_addr32), initval);
 }
 
 static inline bool ipv6_addr_loopback(const struct in6_addr *a)
index 2c1ea34..374411b 100644 (file)
@@ -111,7 +111,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit);
 void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit);
 int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, u16 *how_many_unacked);
 struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
-                                   struct llc_addr *laddr);
+                                   struct llc_addr *laddr, const struct net *net);
 void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk);
 void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
 
index 49aa79c..7e73f8e 100644 (file)
@@ -269,7 +269,7 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 /**
  *     llc_pdu_decode_da - extracts dest address of input frame
  *     @skb: input skb that destination address must be extracted from it
- *     @sa: pointer to destination address (6 byte array).
+ *     @da: pointer to destination address (6 byte array).
  *
  *     This function extracts destination address(MAC) of input frame.
  */
@@ -321,7 +321,7 @@ static inline void llc_pdu_init_as_ui_cmd(struct sk_buff *skb)
 
 /**
  *     llc_pdu_init_as_test_cmd - sets PDU as TEST
- *     @skb - Address of the skb to build
+ *     @skb: Address of the skb to build
  *
  *     Sets a PDU as TEST
  */
@@ -369,6 +369,8 @@ struct llc_xid_info {
 /**
  *     llc_pdu_init_as_xid_cmd - sets bytes 3, 4 & 5 of LLC header as XID
  *     @skb: input skb that header must be set into it.
+ *     @svcs_supported: The class of the LLC (I or II)
+ *     @rx_window: The size of the receive window of the LLC
  *
  *     This function sets third,fourth,fifth and sixth bytes of LLC header as
  *     a XID PDU.
index 350b1ad..16a7510 100644 (file)
 
 /**
  * struct nsh_md1_ctx - Keeps track of NSH context data
- * @nshc<1-4>: NSH Contexts.
+ * @context: NSH Contexts.
  */
 struct nsh_md1_ctx {
        __be32 context[4];
index 3fe2361..01cbc66 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * struct pie_params - contains pie parameters
  * @target:            target delay in pschedtime
- * @tudpate:           interval at which drop probability is calculated
+ * @tupdate:           interval at which drop probability is calculated
  * @limit:             total number of packets that can be in the queue
  * @alpha:             parameter to control drop probability
  * @beta:              parameter to control drop probability
index 040f07b..b228376 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2017 Redpine Signals Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
index 226bce6..0ca972e 100644 (file)
@@ -1509,25 +1509,38 @@ void tcp_leave_memory_pressure(struct sock *sk);
 static inline int keepalive_intvl_when(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
+       int val;
 
-       return tp->keepalive_intvl ? :
-               READ_ONCE(net->ipv4.sysctl_tcp_keepalive_intvl);
+       /* Paired with WRITE_ONCE() in tcp_sock_set_keepintvl()
+        * and do_tcp_setsockopt().
+        */
+       val = READ_ONCE(tp->keepalive_intvl);
+
+       return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_intvl);
 }
 
 static inline int keepalive_time_when(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
+       int val;
 
-       return tp->keepalive_time ? :
-               READ_ONCE(net->ipv4.sysctl_tcp_keepalive_time);
+       /* Paired with WRITE_ONCE() in tcp_sock_set_keepidle_locked() */
+       val = READ_ONCE(tp->keepalive_time);
+
+       return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_time);
 }
 
 static inline int keepalive_probes(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
+       int val;
 
-       return tp->keepalive_probes ? :
-               READ_ONCE(net->ipv4.sysctl_tcp_keepalive_probes);
+       /* Paired with WRITE_ONCE() in tcp_sock_set_keepcnt()
+        * and do_tcp_setsockopt().
+        */
+       val = READ_ONCE(tp->keepalive_probes);
+
+       return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_probes);
 }
 
 static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp)
@@ -2048,7 +2061,11 @@ void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr);
 static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
-       return tp->notsent_lowat ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat);
+       u32 val;
+
+       val = READ_ONCE(tp->notsent_lowat);
+
+       return val ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat);
 }
 
 bool tcp_stream_memory_free(const struct sock *sk, int wake);
index 0be91ca..1648240 100644 (file)
@@ -386,10 +386,15 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
        return features;
 }
 
-/* IP header + UDP + VXLAN + Ethernet header */
-#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
-/* IPv6 header + UDP + VXLAN + Ethernet header */
-#define VXLAN6_HEADROOM (40 + 8 + 8 + 14)
+static inline int vxlan_headroom(u32 flags)
+{
+       /* VXLAN:     IP4/6 header + UDP + VXLAN + Ethernet header */
+       /* VXLAN-GPE: IP4/6 header + UDP + VXLAN */
+       return (flags & VXLAN_F_IPV6 ? sizeof(struct ipv6hdr) :
+                                      sizeof(struct iphdr)) +
+              sizeof(struct udphdr) + sizeof(struct vxlanhdr) +
+              (flags & VXLAN_F_GPE ? 0 : ETH_HLEN);
+}
 
 static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
 {
index 8f5ee38..5646ae1 100644 (file)
@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit,
 TRACE_EVENT(jbd2_shrink_checkpoint_list,
 
        TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid,
-                unsigned long nr_freed, unsigned long nr_scanned,
-                tid_t next_tid),
+                unsigned long nr_freed, tid_t next_tid),
 
-       TP_ARGS(journal, first_tid, tid, last_tid, nr_freed,
-               nr_scanned, next_tid),
+       TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid),
 
        TP_STRUCT__entry(
                __field(dev_t, dev)
@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list,
                __field(tid_t, tid)
                __field(tid_t, last_tid)
                __field(unsigned long, nr_freed)
-               __field(unsigned long, nr_scanned)
                __field(tid_t, next_tid)
        ),
 
@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list,
                __entry->tid            = tid;
                __entry->last_tid       = last_tid;
                __entry->nr_freed       = nr_freed;
-               __entry->nr_scanned     = nr_scanned;
                __entry->next_tid       = next_tid;
        ),
 
        TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu "
-                 "scanned %lu next transaction %u",
+                 "next transaction %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->first_tid, __entry->tid, __entry->last_tid,
-                 __entry->nr_freed, __entry->nr_scanned, __entry->next_tid)
+                 __entry->nr_freed, __entry->next_tid)
 );
 
 #endif /* _TRACE_JBD2_H */
index 1b9d0df..b3fcab1 100644 (file)
  *  - add extension header
  *  - add FUSE_EXT_GROUPS
  *  - add FUSE_CREATE_SUPP_GROUP
+ *  - add FUSE_HAS_EXPIRE_ONLY
  */
 
 #ifndef _LINUX_FUSE_H
@@ -369,6 +370,7 @@ struct fuse_file_lock {
  * FUSE_HAS_INODE_DAX:  use per inode DAX
  * FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
  *                     symlink and mknod (single group that matches parent)
+ * FUSE_HAS_EXPIRE_ONLY: kernel supports expiry-only entry invalidation
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -406,6 +408,7 @@ struct fuse_file_lock {
 #define FUSE_SECURITY_CTX      (1ULL << 32)
 #define FUSE_HAS_INODE_DAX     (1ULL << 33)
 #define FUSE_CREATE_SUPP_GROUP (1ULL << 34)
+#define FUSE_HAS_EXPIRE_ONLY   (1ULL << 35)
 
 /**
  * CUSE INIT request/reply flags
index 9efc423..4d0ad22 100644 (file)
@@ -18,7 +18,11 @@ struct sockaddr_ll {
        unsigned short  sll_hatype;
        unsigned char   sll_pkttype;
        unsigned char   sll_halen;
-       unsigned char   sll_addr[8];
+       union {
+               unsigned char   sll_addr[8];
+               /* Actual length is in sll_halen. */
+               __DECLARE_FLEX_ARRAY(unsigned char, sll_addr_flex);
+       };
 };
 
 /* Packet types */
index 7505de2..89a6115 100644 (file)
@@ -1948,6 +1948,14 @@ fail:
                ret = io_issue_sqe(req, issue_flags);
                if (ret != -EAGAIN)
                        break;
+
+               /*
+                * If REQ_F_NOWAIT is set, then don't wait or retry with
+                * poll. -EAGAIN is final for that case.
+                */
+               if (req->flags & REQ_F_NOWAIT)
+                       break;
+
                /*
                 * We can get EAGAIN for iopolled IO even though we're
                 * forcing a sync submission from here, since we can't
@@ -3429,8 +3437,6 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
                        unsigned long addr, unsigned long len,
                        unsigned long pgoff, unsigned long flags)
 {
-       const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
-       struct vm_unmapped_area_info info;
        void *ptr;
 
        /*
@@ -3445,32 +3451,26 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
        if (IS_ERR(ptr))
                return -ENOMEM;
 
-       info.flags = VM_UNMAPPED_AREA_TOPDOWN;
-       info.length = len;
-       info.low_limit = max(PAGE_SIZE, mmap_min_addr);
-       info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
+       /*
+        * Some architectures have strong cache aliasing requirements.
+        * For such architectures we need a coherent mapping which aliases
+        * kernel memory *and* userspace memory. To achieve that:
+        * - use a NULL file pointer to reference physical memory, and
+        * - use the kernel virtual address of the shared io_uring context
+        *   (instead of the userspace-provided address, which has to be 0UL
+        *   anyway).
+        * For architectures without such aliasing requirements, the
+        * architecture will return any suitable mapping because addr is 0.
+        */
+       filp = NULL;
+       flags |= MAP_SHARED;
+       pgoff = 0;      /* has been translated to ptr above */
 #ifdef SHM_COLOUR
-       info.align_mask = PAGE_MASK & (SHM_COLOUR - 1UL);
+       addr = (uintptr_t) ptr;
 #else
-       info.align_mask = PAGE_MASK & (SHMLBA - 1UL);
+       addr = 0UL;
 #endif
-       info.align_offset = (unsigned long) ptr;
-
-       /*
-        * A failed mmap() very likely causes application failure,
-        * so fall back to the bottom-up function here. This scenario
-        * can happen with large stack limits and large mmap()
-        * allocations.
-        */
-       addr = vm_unmapped_area(&info);
-       if (offset_in_page(addr)) {
-               info.flags = 0;
-               info.low_limit = TASK_UNMAPPED_BASE;
-               info.high_limit = mmap_end;
-               addr = vm_unmapped_area(&info);
-       }
-
-       return addr;
+       return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
 }
 
 #else /* !CONFIG_MMU */
@@ -3870,7 +3870,7 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
                ctx->syscall_iopoll = 1;
 
        ctx->compat = in_compat_syscall();
-       if (!capable(CAP_IPC_LOCK))
+       if (!ns_capable_noaudit(&init_user_ns, CAP_IPC_LOCK))
                ctx->user = get_uid(current_user());
 
        /*
index 930b555..02a021c 100644 (file)
@@ -5573,16 +5573,17 @@ static int update_stack_depth(struct bpf_verifier_env *env,
  * Since recursion is prevented by check_cfg() this algorithm
  * only needs a local stack of MAX_CALL_FRAMES to remember callsites
  */
-static int check_max_stack_depth(struct bpf_verifier_env *env)
+static int check_max_stack_depth_subprog(struct bpf_verifier_env *env, int idx)
 {
-       int depth = 0, frame = 0, idx = 0, i = 0, subprog_end;
        struct bpf_subprog_info *subprog = env->subprog_info;
        struct bpf_insn *insn = env->prog->insnsi;
+       int depth = 0, frame = 0, i, subprog_end;
        bool tail_call_reachable = false;
        int ret_insn[MAX_CALL_FRAMES];
        int ret_prog[MAX_CALL_FRAMES];
        int j;
 
+       i = subprog[idx].start;
 process_func:
        /* protect against potential stack overflow that might happen when
         * bpf2bpf calls get combined with tailcalls. Limit the caller's stack
@@ -5621,7 +5622,7 @@ process_func:
 continue_func:
        subprog_end = subprog[idx + 1].start;
        for (; i < subprog_end; i++) {
-               int next_insn;
+               int next_insn, sidx;
 
                if (!bpf_pseudo_call(insn + i) && !bpf_pseudo_func(insn + i))
                        continue;
@@ -5631,14 +5632,14 @@ continue_func:
 
                /* find the callee */
                next_insn = i + insn[i].imm + 1;
-               idx = find_subprog(env, next_insn);
-               if (idx < 0) {
+               sidx = find_subprog(env, next_insn);
+               if (sidx < 0) {
                        WARN_ONCE(1, "verifier bug. No program starts at insn %d\n",
                                  next_insn);
                        return -EFAULT;
                }
-               if (subprog[idx].is_async_cb) {
-                       if (subprog[idx].has_tail_call) {
+               if (subprog[sidx].is_async_cb) {
+                       if (subprog[sidx].has_tail_call) {
                                verbose(env, "verifier bug. subprog has tail_call and async cb\n");
                                return -EFAULT;
                        }
@@ -5647,6 +5648,7 @@ continue_func:
                                continue;
                }
                i = next_insn;
+               idx = sidx;
 
                if (subprog[idx].has_tail_call)
                        tail_call_reachable = true;
@@ -5682,6 +5684,22 @@ continue_func:
        goto continue_func;
 }
 
+static int check_max_stack_depth(struct bpf_verifier_env *env)
+{
+       struct bpf_subprog_info *si = env->subprog_info;
+       int ret;
+
+       for (int i = 0; i < env->subprog_cnt; i++) {
+               if (!i || si[i].is_async_cb) {
+                       ret = check_max_stack_depth_subprog(env, i);
+                       if (ret < 0)
+                               return ret;
+               }
+               continue;
+       }
+       return 0;
+}
+
 #ifndef CONFIG_BPF_JIT_ALWAYS_ON
 static int get_callee_stack_depth(struct bpf_verifier_env *env,
                                  const struct bpf_insn *insn, int idx)
index b5370fe..128e9bb 100644 (file)
@@ -562,6 +562,10 @@ bool unhandled_signal(struct task_struct *tsk, int sig)
        if (handler != SIG_IGN && handler != SIG_DFL)
                return false;
 
+       /* If dying, we handle all new signals by ignoring them */
+       if (fatal_signal_pending(tsk))
+               return false;
+
        /* if ptraced, let the tracer determine */
        return !tsk->ptrace;
 }
index 05f8389..2410e39 100644 (file)
@@ -2535,11 +2535,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
                        else
                                return -EINVAL;
                        break;
-       case PR_GET_AUXV:
-               if (arg4 || arg5)
-                       return -EINVAL;
-               error = prctl_get_auxv((void __user *)arg2, arg3);
-               break;
                default:
                        return -EINVAL;
                }
@@ -2694,6 +2689,11 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
        case PR_SET_VMA:
                error = prctl_set_vma(arg2, arg3, arg4, arg5);
                break;
+       case PR_GET_AUXV:
+               if (arg4 || arg5)
+                       return -EINVAL;
+               error = prctl_get_auxv((void __user *)arg2, arg3);
+               break;
 #ifdef CONFIG_KSM
        case PR_SET_MEMORY_MERGE:
                if (arg3 || arg4 || arg5)
index 14d8001..de061dd 100644 (file)
@@ -536,6 +536,7 @@ struct trace_buffer {
        unsigned                        flags;
        int                             cpus;
        atomic_t                        record_disabled;
+       atomic_t                        resizing;
        cpumask_var_t                   cpumask;
 
        struct lock_class_key           *reader_lock_key;
@@ -2167,7 +2168,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
 
        /* prevent another thread from changing buffer sizes */
        mutex_lock(&buffer->mutex);
-
+       atomic_inc(&buffer->resizing);
 
        if (cpu_id == RING_BUFFER_ALL_CPUS) {
                /*
@@ -2322,6 +2323,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
                atomic_dec(&buffer->record_disabled);
        }
 
+       atomic_dec(&buffer->resizing);
        mutex_unlock(&buffer->mutex);
        return 0;
 
@@ -2342,6 +2344,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
                }
        }
  out_err_unlock:
+       atomic_dec(&buffer->resizing);
        mutex_unlock(&buffer->mutex);
        return err;
 }
@@ -5541,6 +5544,15 @@ int ring_buffer_swap_cpu(struct trace_buffer *buffer_a,
        if (local_read(&cpu_buffer_b->committing))
                goto out_dec;
 
+       /*
+        * When resize is in progress, we cannot swap it because
+        * it will mess the state of the cpu buffer.
+        */
+       if (atomic_read(&buffer_a->resizing))
+               goto out_dec;
+       if (atomic_read(&buffer_b->resizing))
+               goto out_dec;
+
        buffer_a->buffers[cpu] = cpu_buffer_b;
        buffer_b->buffers[cpu] = cpu_buffer_a;
 
index be847d4..b887007 100644 (file)
@@ -1928,9 +1928,10 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
                 * place on this CPU. We fail to record, but we reset
                 * the max trace buffer (no one writes directly to it)
                 * and flag that it failed.
+                * Another reason is resize is in progress.
                 */
                trace_array_printk_buf(tr->max_buffer.buffer, _THIS_IP_,
-                       "Failed to swap buffers due to commit in progress\n");
+                       "Failed to swap buffers due to commit or resize in progress\n");
        }
 
        WARN_ON_ONCE(ret && ret != -EAGAIN && ret != -EBUSY);
index c8c6138..d06938a 100644 (file)
@@ -6668,7 +6668,8 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
                goto out_unreg;
 
        if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
-               if (save_hist_vars(hist_data))
+               ret = save_hist_vars(hist_data);
+               if (ret)
                        goto out_unreg;
        }
 
index 2c765ee..99c37ee 100644 (file)
@@ -272,10 +272,6 @@ extern u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i);
 extern u64 tracing_map_read_var(struct tracing_map_elt *elt, unsigned int i);
 extern u64 tracing_map_read_var_once(struct tracing_map_elt *elt, unsigned int i);
 
-extern void tracing_map_set_field_descr(struct tracing_map *map,
-                                       unsigned int i,
-                                       unsigned int key_offset,
-                                       tracing_map_cmp_fn_t cmp_fn);
 extern int
 tracing_map_sort_entries(struct tracing_map *map,
                         struct tracing_map_sort_key *sort_keys,
index bfffbb7..4dd73cf 100644 (file)
@@ -3692,7 +3692,8 @@ static inline int mas_root_expand(struct ma_state *mas, void *entry)
        mas->offset = slot;
        pivots[slot] = mas->last;
        if (mas->last != ULONG_MAX)
-               slot++;
+               pivots[++slot] = ULONG_MAX;
+
        mas->depth = 1;
        mas_set_height(mas);
        ma_set_meta(node, maple_leaf_64, 0, slot);
index eff4e42..d0a5081 100644 (file)
@@ -550,7 +550,7 @@ EXPORT_SYMBOL_GPL(sbitmap_queue_min_shallow_depth);
 
 static void __sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr)
 {
-       int i, wake_index;
+       int i, wake_index, woken;
 
        if (!atomic_read(&sbq->ws_active))
                return;
@@ -567,13 +567,12 @@ static void __sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr)
                 */
                wake_index = sbq_index_inc(wake_index);
 
-               /*
-                * It is sufficient to wake up at least one waiter to
-                * guarantee forward progress.
-                */
-               if (waitqueue_active(&ws->wait) &&
-                   wake_up_nr(&ws->wait, nr))
-                       break;
+               if (waitqueue_active(&ws->wait)) {
+                       woken = wake_up_nr(&ws->wait, nr);
+                       if (woken == nr)
+                               break;
+                       nr -= woken;
+               }
        }
 
        if (wake_index != atomic_read(&sbq->wake_index))
index 9939be3..8d4c92c 100644 (file)
@@ -1898,13 +1898,16 @@ static noinline void __init next_prev_test(struct maple_tree *mt)
                                                   725};
        static const unsigned long level2_32[] = { 1747, 2000, 1750, 1755,
                                                   1760, 1765};
+       unsigned long last_index;
 
        if (MAPLE_32BIT) {
                nr_entries = 500;
                level2 = level2_32;
+               last_index = 0x138e;
        } else {
                nr_entries = 200;
                level2 = level2_64;
+               last_index = 0x7d6;
        }
 
        for (i = 0; i <= nr_entries; i++)
@@ -2011,7 +2014,7 @@ static noinline void __init next_prev_test(struct maple_tree *mt)
 
        val = mas_next(&mas, ULONG_MAX);
        MT_BUG_ON(mt, val != NULL);
-       MT_BUG_ON(mt, mas.index != 0x7d6);
+       MT_BUG_ON(mt, mas.index != last_index);
        MT_BUG_ON(mt, mas.last != ULONG_MAX);
 
        val = mas_prev(&mas, 0);
index 01f39e8..603b2f4 100644 (file)
@@ -5393,27 +5393,28 @@ retry:
        if (!vma_is_anonymous(vma) && !vma_is_tcp(vma))
                goto inval;
 
-       /* find_mergeable_anon_vma uses adjacent vmas which are not locked */
-       if (!vma->anon_vma && !vma_is_tcp(vma))
-               goto inval;
-
        if (!vma_start_read(vma))
                goto inval;
 
        /*
+        * find_mergeable_anon_vma uses adjacent vmas which are not locked.
+        * This check must happen after vma_start_read(); otherwise, a
+        * concurrent mremap() with MREMAP_DONTUNMAP could dissociate the VMA
+        * from its anon_vma.
+        */
+       if (unlikely(!vma->anon_vma && !vma_is_tcp(vma)))
+               goto inval_end_read;
+
+       /*
         * Due to the possibility of userfault handler dropping mmap_lock, avoid
         * it for now and fall back to page fault handling under mmap_lock.
         */
-       if (userfaultfd_armed(vma)) {
-               vma_end_read(vma);
-               goto inval;
-       }
+       if (userfaultfd_armed(vma))
+               goto inval_end_read;
 
        /* Check since vm_start/vm_end might change before we lock the VMA */
-       if (unlikely(address < vma->vm_start || address >= vma->vm_end)) {
-               vma_end_read(vma);
-               goto inval;
-       }
+       if (unlikely(address < vma->vm_start || address >= vma->vm_end))
+               goto inval_end_read;
 
        /* Check if the VMA got isolated after we found it */
        if (vma->detached) {
@@ -5425,6 +5426,9 @@ retry:
 
        rcu_read_unlock();
        return vma;
+
+inval_end_read:
+       vma_end_read(vma);
 inval:
        rcu_read_unlock();
        count_vm_vma_lock_event(VMA_LOCK_ABORT);
index edc2519..c53f8be 100644 (file)
@@ -384,8 +384,10 @@ void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
        VMA_ITERATOR(vmi, mm, 0);
 
        mmap_write_lock(mm);
-       for_each_vma(vmi, vma)
+       for_each_vma(vmi, vma) {
+               vma_start_write(vma);
                mpol_rebind_policy(vma->vm_policy, new);
+       }
        mmap_write_unlock(mm);
 }
 
@@ -768,6 +770,8 @@ static int vma_replace_policy(struct vm_area_struct *vma,
        struct mempolicy *old;
        struct mempolicy *new;
 
+       vma_assert_write_locked(vma);
+
        pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
                 vma->vm_start, vma->vm_end, vma->vm_pgoff,
                 vma->vm_ops, vma->vm_file,
@@ -1313,6 +1317,14 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (err)
                goto mpol_out;
 
+       /*
+        * Lock the VMAs before scanning for pages to migrate, to ensure we don't
+        * miss a concurrently inserted page.
+        */
+       vma_iter_init(&vmi, mm, start);
+       for_each_vma_range(vmi, vma, end)
+               vma_start_write(vma);
+
        ret = queue_pages_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
 
@@ -1538,6 +1550,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le
                        break;
                }
 
+               vma_start_write(vma);
                new->home_node = home_node;
                err = mbind_range(&vmi, vma, &prev, start, end, new);
                mpol_put(new);
index d7db945..0a0c996 100644 (file)
@@ -477,7 +477,6 @@ static int apply_vma_lock_flags(unsigned long start, size_t len,
 {
        unsigned long nstart, end, tmp;
        struct vm_area_struct *vma, *prev;
-       int error;
        VMA_ITERATOR(vmi, current->mm, start);
 
        VM_BUG_ON(offset_in_page(start));
@@ -498,6 +497,7 @@ static int apply_vma_lock_flags(unsigned long start, size_t len,
        nstart = start;
        tmp = vma->vm_start;
        for_each_vma_range(vmi, vma, end) {
+               int error;
                vm_flags_t newflags;
 
                if (vma->vm_start != tmp)
@@ -511,14 +511,15 @@ static int apply_vma_lock_flags(unsigned long start, size_t len,
                        tmp = end;
                error = mlock_fixup(&vmi, vma, &prev, nstart, tmp, newflags);
                if (error)
-                       break;
+                       return error;
+               tmp = vma_iter_end(&vmi);
                nstart = tmp;
        }
 
-       if (vma_iter_end(&vmi) < end)
+       if (tmp < end)
                return -ENOMEM;
 
-       return error;
+       return 0;
 }
 
 /*
index 056f951..7622256 100644 (file)
@@ -118,7 +118,7 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
         */
        params->explicit_connect = false;
 
-       list_del_init(&params->action);
+       hci_pend_le_list_del_init(params);
 
        switch (params->auto_connect) {
        case HCI_AUTO_CONN_EXPLICIT:
@@ -127,10 +127,10 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
                return;
        case HCI_AUTO_CONN_DIRECT:
        case HCI_AUTO_CONN_ALWAYS:
-               list_add(&params->action, &hdev->pend_le_conns);
+               hci_pend_le_list_add(params, &hdev->pend_le_conns);
                break;
        case HCI_AUTO_CONN_REPORT:
-               list_add(&params->action, &hdev->pend_le_reports);
+               hci_pend_le_list_add(params, &hdev->pend_le_reports);
                break;
        default:
                break;
@@ -1426,8 +1426,8 @@ static int hci_explicit_conn_params_set(struct hci_dev *hdev,
        if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
            params->auto_connect == HCI_AUTO_CONN_REPORT ||
            params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
-               list_del_init(&params->action);
-               list_add(&params->action, &hdev->pend_le_conns);
+               hci_pend_le_list_del_init(params);
+               hci_pend_le_list_add(params, &hdev->pend_le_conns);
        }
 
        params->explicit_connect = true;
@@ -1684,7 +1684,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
        if (!link) {
                hci_conn_drop(acl);
                hci_conn_drop(sco);
-               return NULL;
+               return ERR_PTR(-ENOLINK);
        }
 
        sco->setting = setting;
@@ -2254,7 +2254,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
        if (!link) {
                hci_conn_drop(le);
                hci_conn_drop(cis);
-               return NULL;
+               return ERR_PTR(-ENOLINK);
        }
 
        /* If LE is already connected and CIS handle is already set proceed to
index 48917c6..1ec8398 100644 (file)
@@ -1972,6 +1972,7 @@ static int hci_remove_adv_monitor(struct hci_dev *hdev,
                                  struct adv_monitor *monitor)
 {
        int status = 0;
+       int handle;
 
        switch (hci_get_adv_monitor_offload_ext(hdev)) {
        case HCI_ADV_MONITOR_EXT_NONE: /* also goes here when powered off */
@@ -1980,9 +1981,10 @@ static int hci_remove_adv_monitor(struct hci_dev *hdev,
                goto free_monitor;
 
        case HCI_ADV_MONITOR_EXT_MSFT:
+               handle = monitor->handle;
                status = msft_remove_monitor(hdev, monitor);
                bt_dev_dbg(hdev, "%s remove monitor %d msft status %d",
-                          hdev->name, monitor->handle, status);
+                          hdev->name, handle, status);
                break;
        }
 
@@ -2249,22 +2251,46 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
        return NULL;
 }
 
-/* This function requires the caller holds hdev->lock */
+/* This function requires the caller holds hdev->lock or rcu_read_lock */
 struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
                                                  bdaddr_t *addr, u8 addr_type)
 {
        struct hci_conn_params *param;
 
-       list_for_each_entry(param, list, action) {
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(param, list, action) {
                if (bacmp(&param->addr, addr) == 0 &&
-                   param->addr_type == addr_type)
+                   param->addr_type == addr_type) {
+                       rcu_read_unlock();
                        return param;
+               }
        }
 
+       rcu_read_unlock();
+
        return NULL;
 }
 
 /* This function requires the caller holds hdev->lock */
+void hci_pend_le_list_del_init(struct hci_conn_params *param)
+{
+       if (list_empty(&param->action))
+               return;
+
+       list_del_rcu(&param->action);
+       synchronize_rcu();
+       INIT_LIST_HEAD(&param->action);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_list_add(struct hci_conn_params *param,
+                         struct list_head *list)
+{
+       list_add_rcu(&param->action, list);
+}
+
+/* This function requires the caller holds hdev->lock */
 struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
                                            bdaddr_t *addr, u8 addr_type)
 {
@@ -2297,14 +2323,15 @@ struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
        return params;
 }
 
-static void hci_conn_params_free(struct hci_conn_params *params)
+void hci_conn_params_free(struct hci_conn_params *params)
 {
+       hci_pend_le_list_del_init(params);
+
        if (params->conn) {
                hci_conn_drop(params->conn);
                hci_conn_put(params->conn);
        }
 
-       list_del(&params->action);
        list_del(&params->list);
        kfree(params);
 }
@@ -2342,8 +2369,7 @@ void hci_conn_params_clear_disabled(struct hci_dev *hdev)
                        continue;
                }
 
-               list_del(&params->list);
-               kfree(params);
+               hci_conn_params_free(params);
        }
 
        BT_DBG("All LE disabled connection parameters were removed");
index 95816a9..31ca320 100644 (file)
@@ -1564,7 +1564,7 @@ static u8 hci_cc_le_set_privacy_mode(struct hci_dev *hdev, void *data,
 
        params = hci_conn_params_lookup(hdev, &cp->bdaddr, cp->bdaddr_type);
        if (params)
-               params->privacy_mode = cp->mode;
+               WRITE_ONCE(params->privacy_mode, cp->mode);
 
        hci_dev_unlock(hdev);
 
@@ -2784,6 +2784,9 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
                        hci_enable_advertising(hdev);
                }
 
+               /* Inform sockets conn is gone before we delete it */
+               hci_disconn_cfm(conn, HCI_ERROR_UNSPECIFIED);
+
                goto done;
        }
 
@@ -2804,8 +2807,8 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
 
                case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
-                       list_del_init(&params->action);
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_del_init(params);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                        break;
 
                default:
@@ -3423,8 +3426,8 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
 
                case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
-                       list_del_init(&params->action);
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_del_init(params);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                        hci_update_passive_scan(hdev);
                        break;
 
@@ -5962,7 +5965,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
        params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
                                           conn->dst_type);
        if (params) {
-               list_del_init(&params->action);
+               hci_pend_le_list_del_init(params);
                if (params->conn) {
                        hci_conn_drop(params->conn);
                        hci_conn_put(params->conn);
index 8561616..4d1e32b 100644 (file)
@@ -2160,15 +2160,23 @@ static int hci_le_del_accept_list_sync(struct hci_dev *hdev,
        return 0;
 }
 
+struct conn_params {
+       bdaddr_t addr;
+       u8 addr_type;
+       hci_conn_flags_t flags;
+       u8 privacy_mode;
+};
+
 /* Adds connection to resolve list if needed.
  * Setting params to NULL programs local hdev->irk
  */
 static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
-                                       struct hci_conn_params *params)
+                                       struct conn_params *params)
 {
        struct hci_cp_le_add_to_resolv_list cp;
        struct smp_irk *irk;
        struct bdaddr_list_with_irk *entry;
+       struct hci_conn_params *p;
 
        if (!use_ll_privacy(hdev))
                return 0;
@@ -2203,6 +2211,16 @@ static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
        /* Default privacy mode is always Network */
        params->privacy_mode = HCI_NETWORK_PRIVACY;
 
+       rcu_read_lock();
+       p = hci_pend_le_action_lookup(&hdev->pend_le_conns,
+                                     &params->addr, params->addr_type);
+       if (!p)
+               p = hci_pend_le_action_lookup(&hdev->pend_le_reports,
+                                             &params->addr, params->addr_type);
+       if (p)
+               WRITE_ONCE(p->privacy_mode, HCI_NETWORK_PRIVACY);
+       rcu_read_unlock();
+
 done:
        if (hci_dev_test_flag(hdev, HCI_PRIVACY))
                memcpy(cp.local_irk, hdev->irk, 16);
@@ -2215,7 +2233,7 @@ done:
 
 /* Set Device Privacy Mode. */
 static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
-                                       struct hci_conn_params *params)
+                                       struct conn_params *params)
 {
        struct hci_cp_le_set_privacy_mode cp;
        struct smp_irk *irk;
@@ -2240,6 +2258,8 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
        bacpy(&cp.bdaddr, &irk->bdaddr);
        cp.mode = HCI_DEVICE_PRIVACY;
 
+       /* Note: params->privacy_mode is not updated since it is a copy */
+
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_PRIVACY_MODE,
                                     sizeof(cp), &cp, HCI_CMD_TIMEOUT);
 }
@@ -2249,7 +2269,7 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
  * properly set the privacy mode.
  */
 static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
-                                      struct hci_conn_params *params,
+                                      struct conn_params *params,
                                       u8 *num_entries)
 {
        struct hci_cp_le_add_to_accept_list cp;
@@ -2447,6 +2467,52 @@ struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
        return __hci_cmd_sync_sk(hdev, opcode, 0, NULL, 0, HCI_CMD_TIMEOUT, sk);
 }
 
+static struct conn_params *conn_params_copy(struct list_head *list, size_t *n)
+{
+       struct hci_conn_params *params;
+       struct conn_params *p;
+       size_t i;
+
+       rcu_read_lock();
+
+       i = 0;
+       list_for_each_entry_rcu(params, list, action)
+               ++i;
+       *n = i;
+
+       rcu_read_unlock();
+
+       p = kvcalloc(*n, sizeof(struct conn_params), GFP_KERNEL);
+       if (!p)
+               return NULL;
+
+       rcu_read_lock();
+
+       i = 0;
+       list_for_each_entry_rcu(params, list, action) {
+               /* Racing adds are handled in next scan update */
+               if (i >= *n)
+                       break;
+
+               /* No hdev->lock, but: addr, addr_type are immutable.
+                * privacy_mode is only written by us or in
+                * hci_cc_le_set_privacy_mode that we wait for.
+                * We should be idempotent so MGMT updating flags
+                * while we are processing is OK.
+                */
+               bacpy(&p[i].addr, &params->addr);
+               p[i].addr_type = params->addr_type;
+               p[i].flags = READ_ONCE(params->flags);
+               p[i].privacy_mode = READ_ONCE(params->privacy_mode);
+               ++i;
+       }
+
+       rcu_read_unlock();
+
+       *n = i;
+       return p;
+}
+
 /* Device must not be scanning when updating the accept list.
  *
  * Update is done using the following sequence:
@@ -2466,11 +2532,12 @@ struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
  */
 static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
 {
-       struct hci_conn_params *params;
+       struct conn_params *params;
        struct bdaddr_list *b, *t;
        u8 num_entries = 0;
        bool pend_conn, pend_report;
        u8 filter_policy;
+       size_t i, n;
        int err;
 
        /* Pause advertising if resolving list can be used as controllers
@@ -2504,6 +2571,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
                if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type))
                        continue;
 
+               /* Pointers not dereferenced, no locks needed */
                pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns,
                                                      &b->bdaddr,
                                                      b->bdaddr_type);
@@ -2532,23 +2600,50 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
         * available accept list entries in the controller, then
         * just abort and return filer policy value to not use the
         * accept list.
+        *
+        * The list and params may be mutated while we wait for events,
+        * so make a copy and iterate it.
         */
-       list_for_each_entry(params, &hdev->pend_le_conns, action) {
-               err = hci_le_add_accept_list_sync(hdev, params, &num_entries);
-               if (err)
+
+       params = conn_params_copy(&hdev->pend_le_conns, &n);
+       if (!params) {
+               err = -ENOMEM;
+               goto done;
+       }
+
+       for (i = 0; i < n; ++i) {
+               err = hci_le_add_accept_list_sync(hdev, &params[i],
+                                                 &num_entries);
+               if (err) {
+                       kvfree(params);
                        goto done;
+               }
        }
 
+       kvfree(params);
+
        /* After adding all new pending connections, walk through
         * the list of pending reports and also add these to the
         * accept list if there is still space. Abort if space runs out.
         */
-       list_for_each_entry(params, &hdev->pend_le_reports, action) {
-               err = hci_le_add_accept_list_sync(hdev, params, &num_entries);
-               if (err)
+
+       params = conn_params_copy(&hdev->pend_le_reports, &n);
+       if (!params) {
+               err = -ENOMEM;
+               goto done;
+       }
+
+       for (i = 0; i < n; ++i) {
+               err = hci_le_add_accept_list_sync(hdev, &params[i],
+                                                 &num_entries);
+               if (err) {
+                       kvfree(params);
                        goto done;
+               }
        }
 
+       kvfree(params);
+
        /* Use the allowlist unless the following conditions are all true:
         * - We are not currently suspending
         * - There are 1 or more ADV monitors registered and it's not offloaded
@@ -4837,12 +4932,12 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
        struct hci_conn_params *p;
 
        list_for_each_entry(p, &hdev->le_conn_params, list) {
+               hci_pend_le_list_del_init(p);
                if (p->conn) {
                        hci_conn_drop(p->conn);
                        hci_conn_put(p->conn);
                        p->conn = NULL;
                }
-               list_del_init(&p->action);
        }
 
        BT_DBG("All LE pending actions cleared");
index 0e6cc57..505d622 100644 (file)
@@ -123,8 +123,11 @@ static struct iso_conn *iso_conn_add(struct hci_conn *hcon)
 {
        struct iso_conn *conn = hcon->iso_data;
 
-       if (conn)
+       if (conn) {
+               if (!conn->hcon)
+                       conn->hcon = hcon;
                return conn;
+       }
 
        conn = kzalloc(sizeof(*conn), GFP_KERNEL);
        if (!conn)
@@ -300,14 +303,13 @@ static int iso_connect_bis(struct sock *sk)
                goto unlock;
        }
 
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
+       lock_sock(sk);
 
        err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               return err;
-
-       lock_sock(sk);
+       if (err) {
+               release_sock(sk);
+               goto unlock;
+       }
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
@@ -321,7 +323,6 @@ static int iso_connect_bis(struct sock *sk)
        }
 
        release_sock(sk);
-       return err;
 
 unlock:
        hci_dev_unlock(hdev);
@@ -389,14 +390,13 @@ static int iso_connect_cis(struct sock *sk)
                goto unlock;
        }
 
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
+       lock_sock(sk);
 
        err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               return err;
-
-       lock_sock(sk);
+       if (err) {
+               release_sock(sk);
+               goto unlock;
+       }
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
@@ -413,7 +413,6 @@ static int iso_connect_cis(struct sock *sk)
        }
 
        release_sock(sk);
-       return err;
 
 unlock:
        hci_dev_unlock(hdev);
@@ -1072,8 +1071,8 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
                            size_t len)
 {
        struct sock *sk = sock->sk;
-       struct iso_conn *conn = iso_pi(sk)->conn;
        struct sk_buff *skb, **frag;
+       size_t mtu;
        int err;
 
        BT_DBG("sock %p, sk %p", sock, sk);
@@ -1085,11 +1084,18 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
        if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
 
-       if (sk->sk_state != BT_CONNECTED)
+       lock_sock(sk);
+
+       if (sk->sk_state != BT_CONNECTED) {
+               release_sock(sk);
                return -ENOTCONN;
+       }
+
+       mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu;
+
+       release_sock(sk);
 
-       skb = bt_skb_sendmsg(sk, msg, len, conn->hcon->hdev->iso_mtu,
-                            HCI_ISO_DATA_HDR_SIZE, 0);
+       skb = bt_skb_sendmsg(sk, msg, len, mtu, HCI_ISO_DATA_HDR_SIZE, 0);
        if (IS_ERR(skb))
                return PTR_ERR(skb);
 
@@ -1102,8 +1108,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
        while (len) {
                struct sk_buff *tmp;
 
-               tmp = bt_skb_sendmsg(sk, msg, len, conn->hcon->hdev->iso_mtu,
-                                    0, 0);
+               tmp = bt_skb_sendmsg(sk, msg, len, mtu, 0, 0);
                if (IS_ERR(tmp)) {
                        kfree_skb(skb);
                        return PTR_ERR(tmp);
@@ -1158,15 +1163,19 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
        BT_DBG("sk %p", sk);
 
        if (test_and_clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+               lock_sock(sk);
                switch (sk->sk_state) {
                case BT_CONNECT2:
-                       lock_sock(sk);
                        iso_conn_defer_accept(pi->conn->hcon);
                        sk->sk_state = BT_CONFIG;
                        release_sock(sk);
                        return 0;
                case BT_CONNECT:
+                       release_sock(sk);
                        return iso_connect_cis(sk);
+               default:
+                       release_sock(sk);
+                       break;
                }
        }
 
index f7b2d09..d449803 100644 (file)
@@ -1297,15 +1297,15 @@ static void restart_le_actions(struct hci_dev *hdev)
                /* Needed for AUTO_OFF case where might not "really"
                 * have been powered off.
                 */
-               list_del_init(&p->action);
+               hci_pend_le_list_del_init(p);
 
                switch (p->auto_connect) {
                case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
-                       list_add(&p->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(p, &hdev->pend_le_conns);
                        break;
                case HCI_AUTO_CONN_REPORT:
-                       list_add(&p->action, &hdev->pend_le_reports);
+                       hci_pend_le_list_add(p, &hdev->pend_le_reports);
                        break;
                default:
                        break;
@@ -5169,7 +5169,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
-       params->flags = current_flags;
+       WRITE_ONCE(params->flags, current_flags);
        status = MGMT_STATUS_SUCCESS;
 
        /* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
@@ -7285,7 +7285,7 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err)
 
        bt_dev_dbg(hdev, "err %d", err);
 
-       memcpy(&rp.addr, &cp->addr.bdaddr, sizeof(rp.addr));
+       memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
 
        status = mgmt_status(err);
        if (status == MGMT_STATUS_SUCCESS) {
@@ -7580,7 +7580,7 @@ static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
        if (params->auto_connect == auto_connect)
                return 0;
 
-       list_del_init(&params->action);
+       hci_pend_le_list_del_init(params);
 
        switch (auto_connect) {
        case HCI_AUTO_CONN_DISABLED:
@@ -7589,18 +7589,18 @@ static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
                 * connect to device, keep connecting.
                 */
                if (params->explicit_connect)
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                break;
        case HCI_AUTO_CONN_REPORT:
                if (params->explicit_connect)
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                else
-                       list_add(&params->action, &hdev->pend_le_reports);
+                       hci_pend_le_list_add(params, &hdev->pend_le_reports);
                break;
        case HCI_AUTO_CONN_DIRECT:
        case HCI_AUTO_CONN_ALWAYS:
                if (!is_connected(hdev, addr, addr_type))
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                break;
        }
 
@@ -7823,9 +7823,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        goto unlock;
                }
 
-               list_del(&params->action);
-               list_del(&params->list);
-               kfree(params);
+               hci_conn_params_free(params);
 
                device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
        } else {
@@ -7856,9 +7854,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                                p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
                                continue;
                        }
-                       list_del(&p->action);
-                       list_del(&p->list);
-                       kfree(p);
+                       hci_conn_params_free(p);
                }
 
                bt_dev_dbg(hdev, "All LE connection parameters were removed");
index cd1a27a..7762604 100644 (file)
@@ -126,8 +126,11 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
        struct hci_dev *hdev = hcon->hdev;
        struct sco_conn *conn = hcon->sco_data;
 
-       if (conn)
+       if (conn) {
+               if (!conn->hcon)
+                       conn->hcon = hcon;
                return conn;
+       }
 
        conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
        if (!conn)
@@ -268,21 +271,21 @@ static int sco_connect(struct sock *sk)
                goto unlock;
        }
 
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
-
        conn = sco_conn_add(hcon);
        if (!conn) {
                hci_conn_drop(hcon);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto unlock;
        }
 
-       err = sco_chan_add(conn, sk, NULL);
-       if (err)
-               return err;
-
        lock_sock(sk);
 
+       err = sco_chan_add(conn, sk, NULL);
+       if (err) {
+               release_sock(sk);
+               goto unlock;
+       }
+
        /* Update source addr of the socket */
        bacpy(&sco_pi(sk)->src, &hcon->src);
 
@@ -296,8 +299,6 @@ static int sco_connect(struct sock *sk)
 
        release_sock(sk);
 
-       return err;
-
 unlock:
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);
index 9ba3568..9168114 100644 (file)
@@ -1526,6 +1526,12 @@ static int bcm_release(struct socket *sock)
 
        lock_sock(sk);
 
+#if IS_ENABLED(CONFIG_PROC_FS)
+       /* remove procfs entry */
+       if (net->can.bcmproc_dir && bo->bcm_proc_read)
+               remove_proc_entry(bo->procname, net->can.bcmproc_dir);
+#endif /* CONFIG_PROC_FS */
+
        list_for_each_entry_safe(op, next, &bo->tx_ops, list)
                bcm_remove_op(op);
 
@@ -1561,12 +1567,6 @@ static int bcm_release(struct socket *sock)
        list_for_each_entry_safe(op, next, &bo->rx_ops, list)
                bcm_remove_op(op);
 
-#if IS_ENABLED(CONFIG_PROC_FS)
-       /* remove procfs entry */
-       if (net->can.bcmproc_dir && bo->bcm_proc_read)
-               remove_proc_entry(bo->procname, net->can.bcmproc_dir);
-#endif /* CONFIG_PROC_FS */
-
        /* remove device reference */
        if (bo->bound) {
                bo->bound   = 0;
index 15c79b0..ba6b52b 100644 (file)
@@ -84,6 +84,7 @@ struct raw_sock {
        struct sock sk;
        int bound;
        int ifindex;
+       struct net_device *dev;
        struct list_head notifier;
        int loopback;
        int recv_own_msgs;
@@ -277,7 +278,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
        if (!net_eq(dev_net(dev), sock_net(sk)))
                return;
 
-       if (ro->ifindex != dev->ifindex)
+       if (ro->dev != dev)
                return;
 
        switch (msg) {
@@ -292,6 +293,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
 
                ro->ifindex = 0;
                ro->bound = 0;
+               ro->dev = NULL;
                ro->count = 0;
                release_sock(sk);
 
@@ -337,6 +339,7 @@ static int raw_init(struct sock *sk)
 
        ro->bound            = 0;
        ro->ifindex          = 0;
+       ro->dev              = NULL;
 
        /* set default filter to single entry dfilter */
        ro->dfilter.can_id   = 0;
@@ -383,21 +386,15 @@ static int raw_release(struct socket *sock)
        list_del(&ro->notifier);
        spin_unlock(&raw_notifier_lock);
 
+       rtnl_lock();
        lock_sock(sk);
 
        /* remove current filters & unregister */
        if (ro->bound) {
-               if (ro->ifindex) {
-                       struct net_device *dev;
-
-                       dev = dev_get_by_index(sock_net(sk), ro->ifindex);
-                       if (dev) {
-                               raw_disable_allfilters(dev_net(dev), dev, sk);
-                               dev_put(dev);
-                       }
-               } else {
+               if (ro->dev)
+                       raw_disable_allfilters(dev_net(ro->dev), ro->dev, sk);
+               else
                        raw_disable_allfilters(sock_net(sk), NULL, sk);
-               }
        }
 
        if (ro->count > 1)
@@ -405,6 +402,7 @@ static int raw_release(struct socket *sock)
 
        ro->ifindex = 0;
        ro->bound = 0;
+       ro->dev = NULL;
        ro->count = 0;
        free_percpu(ro->uniq);
 
@@ -412,6 +410,8 @@ static int raw_release(struct socket *sock)
        sock->sk = NULL;
 
        release_sock(sk);
+       rtnl_unlock();
+
        sock_put(sk);
 
        return 0;
@@ -422,6 +422,7 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
        struct sock *sk = sock->sk;
        struct raw_sock *ro = raw_sk(sk);
+       struct net_device *dev = NULL;
        int ifindex;
        int err = 0;
        int notify_enetdown = 0;
@@ -431,14 +432,13 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        if (addr->can_family != AF_CAN)
                return -EINVAL;
 
+       rtnl_lock();
        lock_sock(sk);
 
        if (ro->bound && addr->can_ifindex == ro->ifindex)
                goto out;
 
        if (addr->can_ifindex) {
-               struct net_device *dev;
-
                dev = dev_get_by_index(sock_net(sk), addr->can_ifindex);
                if (!dev) {
                        err = -ENODEV;
@@ -467,26 +467,20 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        if (!err) {
                if (ro->bound) {
                        /* unregister old filters */
-                       if (ro->ifindex) {
-                               struct net_device *dev;
-
-                               dev = dev_get_by_index(sock_net(sk),
-                                                      ro->ifindex);
-                               if (dev) {
-                                       raw_disable_allfilters(dev_net(dev),
-                                                              dev, sk);
-                                       dev_put(dev);
-                               }
-                       } else {
+                       if (ro->dev)
+                               raw_disable_allfilters(dev_net(ro->dev),
+                                                      ro->dev, sk);
+                       else
                                raw_disable_allfilters(sock_net(sk), NULL, sk);
-                       }
                }
                ro->ifindex = ifindex;
                ro->bound = 1;
+               ro->dev = dev;
        }
 
  out:
        release_sock(sk);
+       rtnl_unlock();
 
        if (notify_enetdown) {
                sk->sk_err = ENETDOWN;
@@ -553,9 +547,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                rtnl_lock();
                lock_sock(sk);
 
-               if (ro->bound && ro->ifindex) {
-                       dev = dev_get_by_index(sock_net(sk), ro->ifindex);
-                       if (!dev) {
+               dev = ro->dev;
+               if (ro->bound && dev) {
+                       if (dev->reg_state != NETREG_REGISTERED) {
                                if (count > 1)
                                        kfree(filter);
                                err = -ENODEV;
@@ -596,7 +590,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                ro->count  = count;
 
  out_fil:
-               dev_put(dev);
                release_sock(sk);
                rtnl_unlock();
 
@@ -614,9 +607,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                rtnl_lock();
                lock_sock(sk);
 
-               if (ro->bound && ro->ifindex) {
-                       dev = dev_get_by_index(sock_net(sk), ro->ifindex);
-                       if (!dev) {
+               dev = ro->dev;
+               if (ro->bound && dev) {
+                       if (dev->reg_state != NETREG_REGISTERED) {
                                err = -ENODEV;
                                goto out_err;
                        }
@@ -640,7 +633,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                ro->err_mask = err_mask;
 
  out_err:
-               dev_put(dev);
                release_sock(sk);
                rtnl_unlock();
 
index ba06ed4..2be2d49 100644 (file)
@@ -1132,7 +1132,7 @@ static int esp_init_authenc(struct xfrm_state *x,
        err = crypto_aead_setkey(aead, key, keylen);
 
 free_key:
-       kfree(key);
+       kfree_sensitive(key);
 
 error:
        return err;
index 0cc19cf..aeebe88 100644 (file)
@@ -1019,7 +1019,7 @@ static void reqsk_timer_handler(struct timer_list *t)
 
        icsk = inet_csk(sk_listener);
        net = sock_net(sk_listener);
-       max_syn_ack_retries = icsk->icsk_syn_retries ? :
+       max_syn_ack_retries = READ_ONCE(icsk->icsk_syn_retries) ? :
                READ_ONCE(net->ipv4.sysctl_tcp_synack_retries);
        /* Normally all the openreqs are young and become mature
         * (i.e. converted to established socket) for first timeout.
index e7391bf..0819d60 100644 (file)
@@ -650,20 +650,8 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        spin_lock(lock);
        if (osk) {
                WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
-               ret = sk_hashed(osk);
-               if (ret) {
-                       /* Before deleting the node, we insert a new one to make
-                        * sure that the look-up-sk process would not miss either
-                        * of them and that at least one node would exist in ehash
-                        * table all the time. Otherwise there's a tiny chance
-                        * that lookup process could find nothing in ehash table.
-                        */
-                       __sk_nulls_add_node_tail_rcu(sk, list);
-                       sk_nulls_del_node_init_rcu(osk);
-               }
-               goto unlock;
-       }
-       if (found_dup_sk) {
+               ret = sk_nulls_del_node_init_rcu(osk);
+       } else if (found_dup_sk) {
                *found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
                if (*found_dup_sk)
                        ret = false;
@@ -672,7 +660,6 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        if (ret)
                __sk_nulls_add_node_rcu(sk, list);
 
-unlock:
        spin_unlock(lock);
 
        return ret;
index 4005241..2c1b245 100644 (file)
@@ -88,10 +88,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
 }
 EXPORT_SYMBOL_GPL(inet_twsk_put);
 
-static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw,
-                                       struct hlist_nulls_head *list)
+static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
+                                  struct hlist_nulls_head *list)
 {
-       hlist_nulls_add_tail_rcu(&tw->tw_node, list);
+       hlist_nulls_add_head_rcu(&tw->tw_node, list);
 }
 
 static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
@@ -144,7 +144,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 
        spin_lock(lock);
 
-       inet_twsk_add_node_tail_rcu(tw, &ehead->chain);
+       inet_twsk_add_node_rcu(tw, &ehead->chain);
 
        /* Step 3: Remove SK from hash chain */
        if (__sk_nulls_del_node_init_rcu(sk))
index 81a1cce..22a26d1 100644 (file)
@@ -548,7 +548,8 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                goto err_free_skb;
 
        if (skb->len > dev->mtu + dev->hard_header_len) {
-               pskb_trim(skb, dev->mtu + dev->hard_header_len);
+               if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+                       goto err_free_skb;
                truncate = true;
        }
 
@@ -689,7 +690,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
                goto free_skb;
 
        if (skb->len > dev->mtu + dev->hard_header_len) {
-               pskb_trim(skb, dev->mtu + dev->hard_header_len);
+               if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+                       goto free_skb;
                truncate = true;
        }
 
index e03e087..8ed52e1 100644 (file)
@@ -3291,7 +3291,7 @@ int tcp_sock_set_syncnt(struct sock *sk, int val)
                return -EINVAL;
 
        lock_sock(sk);
-       inet_csk(sk)->icsk_syn_retries = val;
+       WRITE_ONCE(inet_csk(sk)->icsk_syn_retries, val);
        release_sock(sk);
        return 0;
 }
@@ -3300,7 +3300,7 @@ EXPORT_SYMBOL(tcp_sock_set_syncnt);
 void tcp_sock_set_user_timeout(struct sock *sk, u32 val)
 {
        lock_sock(sk);
-       inet_csk(sk)->icsk_user_timeout = val;
+       WRITE_ONCE(inet_csk(sk)->icsk_user_timeout, val);
        release_sock(sk);
 }
 EXPORT_SYMBOL(tcp_sock_set_user_timeout);
@@ -3312,7 +3312,8 @@ int tcp_sock_set_keepidle_locked(struct sock *sk, int val)
        if (val < 1 || val > MAX_TCP_KEEPIDLE)
                return -EINVAL;
 
-       tp->keepalive_time = val * HZ;
+       /* Paired with WRITE_ONCE() in keepalive_time_when() */
+       WRITE_ONCE(tp->keepalive_time, val * HZ);
        if (sock_flag(sk, SOCK_KEEPOPEN) &&
            !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
                u32 elapsed = keepalive_time_elapsed(tp);
@@ -3344,7 +3345,7 @@ int tcp_sock_set_keepintvl(struct sock *sk, int val)
                return -EINVAL;
 
        lock_sock(sk);
-       tcp_sk(sk)->keepalive_intvl = val * HZ;
+       WRITE_ONCE(tcp_sk(sk)->keepalive_intvl, val * HZ);
        release_sock(sk);
        return 0;
 }
@@ -3356,7 +3357,8 @@ int tcp_sock_set_keepcnt(struct sock *sk, int val)
                return -EINVAL;
 
        lock_sock(sk);
-       tcp_sk(sk)->keepalive_probes = val;
+       /* Paired with READ_ONCE() in keepalive_probes() */
+       WRITE_ONCE(tcp_sk(sk)->keepalive_probes, val);
        release_sock(sk);
        return 0;
 }
@@ -3558,19 +3560,19 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                if (val < 1 || val > MAX_TCP_KEEPINTVL)
                        err = -EINVAL;
                else
-                       tp->keepalive_intvl = val * HZ;
+                       WRITE_ONCE(tp->keepalive_intvl, val * HZ);
                break;
        case TCP_KEEPCNT:
                if (val < 1 || val > MAX_TCP_KEEPCNT)
                        err = -EINVAL;
                else
-                       tp->keepalive_probes = val;
+                       WRITE_ONCE(tp->keepalive_probes, val);
                break;
        case TCP_SYNCNT:
                if (val < 1 || val > MAX_TCP_SYNCNT)
                        err = -EINVAL;
                else
-                       icsk->icsk_syn_retries = val;
+                       WRITE_ONCE(icsk->icsk_syn_retries, val);
                break;
 
        case TCP_SAVE_SYN:
@@ -3583,18 +3585,18 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
 
        case TCP_LINGER2:
                if (val < 0)
-                       tp->linger2 = -1;
+                       WRITE_ONCE(tp->linger2, -1);
                else if (val > TCP_FIN_TIMEOUT_MAX / HZ)
-                       tp->linger2 = TCP_FIN_TIMEOUT_MAX;
+                       WRITE_ONCE(tp->linger2, TCP_FIN_TIMEOUT_MAX);
                else
-                       tp->linger2 = val * HZ;
+                       WRITE_ONCE(tp->linger2, val * HZ);
                break;
 
        case TCP_DEFER_ACCEPT:
                /* Translate value in seconds to number of retransmits */
-               icsk->icsk_accept_queue.rskq_defer_accept =
-                       secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
-                                       TCP_RTO_MAX / HZ);
+               WRITE_ONCE(icsk->icsk_accept_queue.rskq_defer_accept,
+                          secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
+                                          TCP_RTO_MAX / HZ));
                break;
 
        case TCP_WINDOW_CLAMP:
@@ -3618,7 +3620,7 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                if (val < 0)
                        err = -EINVAL;
                else
-                       icsk->icsk_user_timeout = val;
+                       WRITE_ONCE(icsk->icsk_user_timeout, val);
                break;
 
        case TCP_FASTOPEN:
@@ -3656,13 +3658,13 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                if (!tp->repair)
                        err = -EPERM;
                else
-                       tp->tsoffset = val - tcp_time_stamp_raw();
+                       WRITE_ONCE(tp->tsoffset, val - tcp_time_stamp_raw());
                break;
        case TCP_REPAIR_WINDOW:
                err = tcp_repair_set_window(tp, optval, optlen);
                break;
        case TCP_NOTSENT_LOWAT:
-               tp->notsent_lowat = val;
+               WRITE_ONCE(tp->notsent_lowat, val);
                sk->sk_write_space(sk);
                break;
        case TCP_INQ:
@@ -3674,7 +3676,7 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
        case TCP_TX_DELAY:
                if (val)
                        tcp_enable_tx_delay();
-               tp->tcp_tx_delay = val;
+               WRITE_ONCE(tp->tcp_tx_delay, val);
                break;
        default:
                err = -ENOPROTOOPT;
@@ -3991,17 +3993,18 @@ int do_tcp_getsockopt(struct sock *sk, int level,
                val = keepalive_probes(tp);
                break;
        case TCP_SYNCNT:
-               val = icsk->icsk_syn_retries ? :
+               val = READ_ONCE(icsk->icsk_syn_retries) ? :
                        READ_ONCE(net->ipv4.sysctl_tcp_syn_retries);
                break;
        case TCP_LINGER2:
-               val = tp->linger2;
+               val = READ_ONCE(tp->linger2);
                if (val >= 0)
                        val = (val ? : READ_ONCE(net->ipv4.sysctl_tcp_fin_timeout)) / HZ;
                break;
        case TCP_DEFER_ACCEPT:
-               val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept,
-                                     TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ);
+               val = READ_ONCE(icsk->icsk_accept_queue.rskq_defer_accept);
+               val = retrans_to_secs(val, TCP_TIMEOUT_INIT / HZ,
+                                     TCP_RTO_MAX / HZ);
                break;
        case TCP_WINDOW_CLAMP:
                val = tp->window_clamp;
@@ -4138,11 +4141,11 @@ int do_tcp_getsockopt(struct sock *sk, int level,
                break;
 
        case TCP_USER_TIMEOUT:
-               val = icsk->icsk_user_timeout;
+               val = READ_ONCE(icsk->icsk_user_timeout);
                break;
 
        case TCP_FASTOPEN:
-               val = icsk->icsk_accept_queue.fastopenq.max_qlen;
+               val = READ_ONCE(icsk->icsk_accept_queue.fastopenq.max_qlen);
                break;
 
        case TCP_FASTOPEN_CONNECT:
@@ -4154,14 +4157,14 @@ int do_tcp_getsockopt(struct sock *sk, int level,
                break;
 
        case TCP_TX_DELAY:
-               val = tp->tcp_tx_delay;
+               val = READ_ONCE(tp->tcp_tx_delay);
                break;
 
        case TCP_TIMESTAMP:
-               val = tcp_time_stamp_raw() + tp->tsoffset;
+               val = tcp_time_stamp_raw() + READ_ONCE(tp->tsoffset);
                break;
        case TCP_NOTSENT_LOWAT:
-               val = tp->notsent_lowat;
+               val = READ_ONCE(tp->notsent_lowat);
                break;
        case TCP_INQ:
                val = tp->recvmsg_inq;
index 45cc7f1..85e4953 100644 (file)
@@ -296,6 +296,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
 static bool tcp_fastopen_queue_check(struct sock *sk)
 {
        struct fastopen_queue *fastopenq;
+       int max_qlen;
 
        /* Make sure the listener has enabled fastopen, and we don't
         * exceed the max # of pending TFO requests allowed before trying
@@ -308,10 +309,11 @@ static bool tcp_fastopen_queue_check(struct sock *sk)
         * temporarily vs a server not supporting Fast Open at all.
         */
        fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
-       if (fastopenq->max_qlen == 0)
+       max_qlen = READ_ONCE(fastopenq->max_qlen);
+       if (max_qlen == 0)
                return false;
 
-       if (fastopenq->qlen >= fastopenq->max_qlen) {
+       if (fastopenq->qlen >= max_qlen) {
                struct request_sock *req1;
                spin_lock(&fastopenq->lock);
                req1 = fastopenq->rskq_rst_head;
index fd365de..0696420 100644 (file)
@@ -307,8 +307,9 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                  inet->inet_daddr,
                                                  inet->inet_sport,
                                                  usin->sin_port));
-               tp->tsoffset = secure_tcp_ts_off(net, inet->inet_saddr,
-                                                inet->inet_daddr);
+               WRITE_ONCE(tp->tsoffset,
+                          secure_tcp_ts_off(net, inet->inet_saddr,
+                                            inet->inet_daddr));
        }
 
        inet->inet_id = get_random_u16();
@@ -988,11 +989,12 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_rsk(req)->rcv_nxt,
                        req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
                        tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
-                       req->ts_recent,
+                       READ_ONCE(req->ts_recent),
                        0,
                        tcp_md5_do_lookup(sk, l3index, addr, AF_INET),
                        inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
-                       ip_hdr(skb)->tos, tcp_rsk(req)->txhash);
+                       ip_hdr(skb)->tos,
+                       READ_ONCE(tcp_rsk(req)->txhash));
 }
 
 /*
index 04fc328..c8f2aa0 100644 (file)
@@ -528,7 +528,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
        newicsk->icsk_ack.lrcvtime = tcp_jiffies32;
 
        newtp->lsndtime = tcp_jiffies32;
-       newsk->sk_txhash = treq->txhash;
+       newsk->sk_txhash = READ_ONCE(treq->txhash);
        newtp->total_retrans = req->num_retrans;
 
        tcp_init_xmit_timers(newsk);
@@ -555,7 +555,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
        newtp->max_window = newtp->snd_wnd;
 
        if (newtp->rx_opt.tstamp_ok) {
-               newtp->rx_opt.ts_recent = req->ts_recent;
+               newtp->rx_opt.ts_recent = READ_ONCE(req->ts_recent);
                newtp->rx_opt.ts_recent_stamp = ktime_get_seconds();
                newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
        } else {
@@ -619,7 +619,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0, NULL);
 
                if (tmp_opt.saw_tstamp) {
-                       tmp_opt.ts_recent = req->ts_recent;
+                       tmp_opt.ts_recent = READ_ONCE(req->ts_recent);
                        if (tmp_opt.rcv_tsecr)
                                tmp_opt.rcv_tsecr -= tcp_rsk(req)->ts_off;
                        /* We do not store true stamp, but it is not required,
@@ -758,8 +758,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 
        /* In sequence, PAWS is OK. */
 
+       /* TODO: We probably should defer ts_recent change once
+        * we take ownership of @req.
+        */
        if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt))
-               req->ts_recent = tmp_opt.rcv_tsval;
+               WRITE_ONCE(req->ts_recent, tmp_opt.rcv_tsval);
 
        if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) {
                /* Truncate SYN, it is out of window starting
index 2cb39b6..51d8638 100644 (file)
@@ -878,7 +878,7 @@ static unsigned int tcp_synack_options(const struct sock *sk,
        if (likely(ireq->tstamp_ok)) {
                opts->options |= OPTION_TS;
                opts->tsval = tcp_skb_timestamp(skb) + tcp_rsk(req)->ts_off;
-               opts->tsecr = req->ts_recent;
+               opts->tsecr = READ_ONCE(req->ts_recent);
                remaining -= TCPOLEN_TSTAMP_ALIGNED;
        }
        if (likely(ireq->sack_ok)) {
@@ -3660,7 +3660,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
        rcu_read_lock();
        md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req));
 #endif
-       skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4);
+       skb_set_hash(skb, READ_ONCE(tcp_rsk(req)->txhash), PKT_HASH_TYPE_L4);
        /* bpf program will be interested in the tcp_flags */
        TCP_SKB_CB(skb)->tcp_flags = TCPHDR_SYN | TCPHDR_ACK;
        tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5,
@@ -4210,7 +4210,7 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req)
 
        /* Paired with WRITE_ONCE() in sock_setsockopt() */
        if (READ_ONCE(sk->sk_txrehash) == SOCK_TXREHASH_ENABLED)
-               tcp_rsk(req)->txhash = net_tx_rndhash();
+               WRITE_ONCE(tcp_rsk(req)->txhash, net_tx_rndhash());
        res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL,
                                  NULL);
        if (!res) {
index 75aa4de..f402946 100644 (file)
@@ -274,13 +274,20 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
        __sum16 check;
        __be16 newlen;
 
-       if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
-               return __udp_gso_segment_list(gso_skb, features, is_ipv6);
-
        mss = skb_shinfo(gso_skb)->gso_size;
        if (gso_skb->len <= sizeof(*uh) + mss)
                return ERR_PTR(-EINVAL);
 
+       if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) {
+               /* Packet is from an untrusted source, reset gso_segs. */
+               skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh),
+                                                            mss);
+               return NULL;
+       }
+
+       if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
+               return __udp_gso_segment_list(gso_skb, features, is_ipv6);
+
        skb_pull(gso_skb, sizeof(*uh));
 
        /* clear destructor to avoid skb_segment assigning it to tail */
@@ -388,8 +395,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
        if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                goto out;
 
-       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
-           !skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
                return __udp_gso_segment(skb, features, false);
 
        mss = skb_shinfo(skb)->gso_size;
index e5213e5..94cec20 100644 (file)
@@ -2561,12 +2561,18 @@ static void manage_tempaddrs(struct inet6_dev *idev,
                        ipv6_ifa_notify(0, ift);
        }
 
-       if ((create || list_empty(&idev->tempaddr_list)) &&
-           idev->cnf.use_tempaddr > 0) {
+       /* Also create a temporary address if it's enabled but no temporary
+        * address currently exists.
+        * However, we get called with valid_lft == 0, prefered_lft == 0, create == false
+        * as part of cleanup (ie. deleting the mngtmpaddr).
+        * We don't want that to result in creating a new temporary ip address.
+        */
+       if (list_empty(&idev->tempaddr_list) && (valid_lft || prefered_lft))
+               create = true;
+
+       if (create && idev->cnf.use_tempaddr > 0) {
                /* When a new public address is created as described
                 * in [ADDRCONF], also create a new temporary address.
-                * Also create a temporary address if it's enabled but
-                * no temporary address currently exists.
                 */
                read_unlock_bh(&idev->lock);
                ipv6_create_tempaddr(ifp, false);
index da80974..070d87a 100644 (file)
@@ -955,7 +955,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                goto tx_err;
 
        if (skb->len > dev->mtu + dev->hard_header_len) {
-               pskb_trim(skb, dev->mtu + dev->hard_header_len);
+               if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+                       goto tx_err;
                truncate = true;
        }
 
index 40dd92a..4714eb6 100644 (file)
@@ -1126,10 +1126,10 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_rsk(req)->rcv_nxt,
                        req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
                        tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
-                       req->ts_recent, sk->sk_bound_dev_if,
+                       READ_ONCE(req->ts_recent), sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index),
                        ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority,
-                       tcp_rsk(req)->txhash);
+                       READ_ONCE(tcp_rsk(req)->txhash));
 }
 
 
index ad3b872..09fa7a4 100644 (file)
@@ -43,8 +43,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                        goto out;
 
-               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
-                   !skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
                        return __udp_gso_segment(skb, features, true);
 
                mss = skb_shinfo(skb)->gso_size;
index 57c35c9..9b06c38 100644 (file)
@@ -402,7 +402,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
                laddr.lsap = addr->sllc_sap;
                rc = -EADDRINUSE; /* mac + sap clash. */
-               ask = llc_lookup_established(sap, &daddr, &laddr);
+               ask = llc_lookup_established(sap, &daddr, &laddr, &init_net);
                if (ask) {
                        sock_put(ask);
                        goto out_put;
index 912aa9b..d037009 100644 (file)
@@ -453,11 +453,13 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
 static inline bool llc_estab_match(const struct llc_sap *sap,
                                   const struct llc_addr *daddr,
                                   const struct llc_addr *laddr,
-                                  const struct sock *sk)
+                                  const struct sock *sk,
+                                  const struct net *net)
 {
        struct llc_sock *llc = llc_sk(sk);
 
-       return llc->laddr.lsap == laddr->lsap &&
+       return net_eq(sock_net(sk), net) &&
+               llc->laddr.lsap == laddr->lsap &&
                llc->daddr.lsap == daddr->lsap &&
                ether_addr_equal(llc->laddr.mac, laddr->mac) &&
                ether_addr_equal(llc->daddr.mac, daddr->mac);
@@ -468,6 +470,7 @@ static inline bool llc_estab_match(const struct llc_sap *sap,
  *     @sap: SAP
  *     @daddr: address of remote LLC (MAC + SAP)
  *     @laddr: address of local LLC (MAC + SAP)
+ *     @net: netns to look up a socket in
  *
  *     Search connection list of the SAP and finds connection using the remote
  *     mac, remote sap, local mac, and local sap. Returns pointer for
@@ -476,7 +479,8 @@ static inline bool llc_estab_match(const struct llc_sap *sap,
  */
 static struct sock *__llc_lookup_established(struct llc_sap *sap,
                                             struct llc_addr *daddr,
-                                            struct llc_addr *laddr)
+                                            struct llc_addr *laddr,
+                                            const struct net *net)
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
@@ -486,12 +490,12 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap,
        rcu_read_lock();
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
-               if (llc_estab_match(sap, daddr, laddr, rc)) {
+               if (llc_estab_match(sap, daddr, laddr, rc, net)) {
                        /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
-                                    !llc_estab_match(sap, daddr, laddr, rc))) {
+                                    !llc_estab_match(sap, daddr, laddr, rc, net))) {
                                sock_put(rc);
                                continue;
                        }
@@ -513,29 +517,33 @@ found:
 
 struct sock *llc_lookup_established(struct llc_sap *sap,
                                    struct llc_addr *daddr,
-                                   struct llc_addr *laddr)
+                                   struct llc_addr *laddr,
+                                   const struct net *net)
 {
        struct sock *sk;
 
        local_bh_disable();
-       sk = __llc_lookup_established(sap, daddr, laddr);
+       sk = __llc_lookup_established(sap, daddr, laddr, net);
        local_bh_enable();
        return sk;
 }
 
 static inline bool llc_listener_match(const struct llc_sap *sap,
                                      const struct llc_addr *laddr,
-                                     const struct sock *sk)
+                                     const struct sock *sk,
+                                     const struct net *net)
 {
        struct llc_sock *llc = llc_sk(sk);
 
-       return sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN &&
+       return net_eq(sock_net(sk), net) &&
+               sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN &&
                llc->laddr.lsap == laddr->lsap &&
                ether_addr_equal(llc->laddr.mac, laddr->mac);
 }
 
 static struct sock *__llc_lookup_listener(struct llc_sap *sap,
-                                         struct llc_addr *laddr)
+                                         struct llc_addr *laddr,
+                                         const struct net *net)
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
@@ -545,12 +553,12 @@ static struct sock *__llc_lookup_listener(struct llc_sap *sap,
        rcu_read_lock();
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
-               if (llc_listener_match(sap, laddr, rc)) {
+               if (llc_listener_match(sap, laddr, rc, net)) {
                        /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
-                                    !llc_listener_match(sap, laddr, rc))) {
+                                    !llc_listener_match(sap, laddr, rc, net))) {
                                sock_put(rc);
                                continue;
                        }
@@ -574,6 +582,7 @@ found:
  *     llc_lookup_listener - Finds listener for local MAC + SAP
  *     @sap: SAP
  *     @laddr: address of local LLC (MAC + SAP)
+ *     @net: netns to look up a socket in
  *
  *     Search connection list of the SAP and finds connection listening on
  *     local mac, and local sap. Returns pointer for parent socket found,
@@ -581,24 +590,26 @@ found:
  *     Caller has to make sure local_bh is disabled.
  */
 static struct sock *llc_lookup_listener(struct llc_sap *sap,
-                                       struct llc_addr *laddr)
+                                       struct llc_addr *laddr,
+                                       const struct net *net)
 {
+       struct sock *rc = __llc_lookup_listener(sap, laddr, net);
        static struct llc_addr null_addr;
-       struct sock *rc = __llc_lookup_listener(sap, laddr);
 
        if (!rc)
-               rc = __llc_lookup_listener(sap, &null_addr);
+               rc = __llc_lookup_listener(sap, &null_addr, net);
 
        return rc;
 }
 
 static struct sock *__llc_lookup(struct llc_sap *sap,
                                 struct llc_addr *daddr,
-                                struct llc_addr *laddr)
+                                struct llc_addr *laddr,
+                                const struct net *net)
 {
-       struct sock *sk = __llc_lookup_established(sap, daddr, laddr);
+       struct sock *sk = __llc_lookup_established(sap, daddr, laddr, net);
 
-       return sk ? : llc_lookup_listener(sap, laddr);
+       return sk ? : llc_lookup_listener(sap, laddr, net);
 }
 
 /**
@@ -776,7 +787,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
        llc_pdu_decode_da(skb, daddr.mac);
        llc_pdu_decode_dsap(skb, &daddr.lsap);
 
-       sk = __llc_lookup(sap, &saddr, &daddr);
+       sk = __llc_lookup(sap, &saddr, &daddr, dev_net(skb->dev));
        if (!sk)
                goto drop;
 
index dde9bf0..58a5f41 100644 (file)
@@ -92,7 +92,7 @@ int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac, u8 dsap)
        daddr.lsap = dsap;
        memcpy(daddr.mac, dmac, sizeof(daddr.mac));
        memcpy(laddr.mac, lmac, sizeof(laddr.mac));
-       existing = llc_lookup_established(llc->sap, &daddr, &laddr);
+       existing = llc_lookup_established(llc->sap, &daddr, &laddr, sock_net(sk));
        if (existing) {
                if (existing->sk_state == TCP_ESTABLISHED) {
                        sk = existing;
index c309b72..7cac441 100644 (file)
@@ -163,9 +163,6 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
        void (*sta_handler)(struct sk_buff *skb);
        void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
 
-       if (!net_eq(dev_net(dev), &init_net))
-               goto drop;
-
        /*
         * When the interface is in promisc. mode, drop all the crap that it
         * receives, do not try to analyse it.
index 6805ce4..116c0e4 100644 (file)
@@ -294,25 +294,29 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
 
 static inline bool llc_dgram_match(const struct llc_sap *sap,
                                   const struct llc_addr *laddr,
-                                  const struct sock *sk)
+                                  const struct sock *sk,
+                                  const struct net *net)
 {
      struct llc_sock *llc = llc_sk(sk);
 
      return sk->sk_type == SOCK_DGRAM &&
-         llc->laddr.lsap == laddr->lsap &&
-         ether_addr_equal(llc->laddr.mac, laddr->mac);
+            net_eq(sock_net(sk), net) &&
+            llc->laddr.lsap == laddr->lsap &&
+            ether_addr_equal(llc->laddr.mac, laddr->mac);
 }
 
 /**
  *     llc_lookup_dgram - Finds dgram socket for the local sap/mac
  *     @sap: SAP
  *     @laddr: address of local LLC (MAC + SAP)
+ *     @net: netns to look up a socket in
  *
  *     Search socket list of the SAP and finds connection using the local
  *     mac, and local sap. Returns pointer for socket found, %NULL otherwise.
  */
 static struct sock *llc_lookup_dgram(struct llc_sap *sap,
-                                    const struct llc_addr *laddr)
+                                    const struct llc_addr *laddr,
+                                    const struct net *net)
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
@@ -322,12 +326,12 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
        rcu_read_lock_bh();
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
-               if (llc_dgram_match(sap, laddr, rc)) {
+               if (llc_dgram_match(sap, laddr, rc, net)) {
                        /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
-                                    !llc_dgram_match(sap, laddr, rc))) {
+                                    !llc_dgram_match(sap, laddr, rc, net))) {
                                sock_put(rc);
                                continue;
                        }
@@ -429,7 +433,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
                llc_sap_mcast(sap, &laddr, skb);
                kfree_skb(skb);
        } else {
-               struct sock *sk = llc_lookup_dgram(sap, &laddr);
+               struct sock *sk = llc_lookup_dgram(sap, &laddr, dev_net(skb->dev));
                if (sk) {
                        llc_sap_rcv(sap, skb, sk);
                        sock_put(sk);
index 3613489..3317d1c 100644 (file)
@@ -3723,10 +3723,9 @@ static int mptcp_listen(struct socket *sock, int backlog)
        if (!err) {
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
                mptcp_copy_inaddrs(sk, ssock->sk);
+               mptcp_event_pm_listener(ssock->sk, MPTCP_EVENT_LISTENER_CREATED);
        }
 
-       mptcp_event_pm_listener(ssock->sk, MPTCP_EVENT_LISTENER_CREATED);
-
 unlock:
        release_sock(sk);
        return err;
index 237f739..d3c6ecd 100644 (file)
@@ -3685,8 +3685,6 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
                        if (err < 0)
                                return err;
                }
-
-               cond_resched();
        }
 
        return 0;
@@ -3710,6 +3708,8 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
                err = nft_chain_validate(&ctx, chain);
                if (err < 0)
                        return err;
+
+               cond_resched();
        }
 
        return 0;
@@ -3811,8 +3811,6 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                        NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
                        return PTR_ERR(chain);
                }
-               if (nft_chain_is_bound(chain))
-                       return -EOPNOTSUPP;
 
        } else if (nla[NFTA_RULE_CHAIN_ID]) {
                chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID],
@@ -3825,6 +3823,9 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                return -EINVAL;
        }
 
+       if (nft_chain_is_bound(chain))
+               return -EOPNOTSUPP;
+
        if (nla[NFTA_RULE_HANDLE]) {
                handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE]));
                rule = __nft_rule_lookup(chain, handle);
@@ -4087,6 +4088,8 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
                list_for_each_entry(chain, &table->chains, list) {
                        if (!nft_is_active_next(net, chain))
                                continue;
+                       if (nft_chain_is_bound(chain))
+                               continue;
 
                        ctx.chain = chain;
                        err = nft_delrule_by_chain(&ctx);
@@ -10517,6 +10520,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
 
        if (!tb[NFTA_VERDICT_CODE])
                return -EINVAL;
+
+       /* zero padding hole for memcmp */
+       memset(data, 0, sizeof(*data));
        data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
 
        switch (data->verdict.code) {
@@ -10799,6 +10805,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
        ctx.family = table->family;
        ctx.table = table;
        list_for_each_entry(chain, &table->chains, list) {
+               if (nft_chain_is_bound(chain))
+                       continue;
+
                ctx.chain = chain;
                list_for_each_entry_safe(rule, nr, &chain->rules, list) {
                        list_del(&rule->list);
index 407d719..fccb3cf 100644 (file)
@@ -125,15 +125,27 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
        return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
 }
 
+static void nft_immediate_chain_deactivate(const struct nft_ctx *ctx,
+                                          struct nft_chain *chain,
+                                          enum nft_trans_phase phase)
+{
+       struct nft_ctx chain_ctx;
+       struct nft_rule *rule;
+
+       chain_ctx = *ctx;
+       chain_ctx.chain = chain;
+
+       list_for_each_entry(rule, &chain->rules, list)
+               nft_rule_expr_deactivate(&chain_ctx, rule, phase);
+}
+
 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
                                     const struct nft_expr *expr,
                                     enum nft_trans_phase phase)
 {
        const struct nft_immediate_expr *priv = nft_expr_priv(expr);
        const struct nft_data *data = &priv->data;
-       struct nft_ctx chain_ctx;
        struct nft_chain *chain;
-       struct nft_rule *rule;
 
        if (priv->dreg == NFT_REG_VERDICT) {
                switch (data->verdict.code) {
@@ -143,20 +155,17 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
                        if (!nft_chain_binding(chain))
                                break;
 
-                       chain_ctx = *ctx;
-                       chain_ctx.chain = chain;
-
-                       list_for_each_entry(rule, &chain->rules, list)
-                               nft_rule_expr_deactivate(&chain_ctx, rule, phase);
-
                        switch (phase) {
                        case NFT_TRANS_PREPARE_ERROR:
                                nf_tables_unbind_chain(ctx, chain);
-                               fallthrough;
+                               nft_deactivate_next(ctx->net, chain);
+                               break;
                        case NFT_TRANS_PREPARE:
+                               nft_immediate_chain_deactivate(ctx, chain, phase);
                                nft_deactivate_next(ctx->net, chain);
                                break;
                        default:
+                               nft_immediate_chain_deactivate(ctx, chain, phase);
                                nft_chain_del(chain);
                                chain->bound = false;
                                nft_use_dec(&chain->table->use);
index db526cb..49915a2 100644 (file)
@@ -1929,7 +1929,11 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
                int i, start, rules_fx;
 
                match_start = data;
-               match_end = (const u8 *)nft_set_ext_key_end(&e->ext)->data;
+
+               if (nft_set_ext_exists(&e->ext, NFT_SET_EXT_KEY_END))
+                       match_end = (const u8 *)nft_set_ext_key_end(&e->ext)->data;
+               else
+                       match_end = data;
 
                start = first_rule;
                rules_fx = rules_f0;
index 5c05c9b..8d73fff 100644 (file)
@@ -217,29 +217,37 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set,
 
 static int nft_rbtree_gc_elem(const struct nft_set *__set,
                              struct nft_rbtree *priv,
-                             struct nft_rbtree_elem *rbe)
+                             struct nft_rbtree_elem *rbe,
+                             u8 genmask)
 {
        struct nft_set *set = (struct nft_set *)__set;
        struct rb_node *prev = rb_prev(&rbe->node);
-       struct nft_rbtree_elem *rbe_prev = NULL;
+       struct nft_rbtree_elem *rbe_prev;
        struct nft_set_gc_batch *gcb;
 
        gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
        if (!gcb)
                return -ENOMEM;
 
-       /* search for expired end interval coming before this element. */
+       /* search for end interval coming before this element.
+        * end intervals don't carry a timeout extension, they
+        * are coupled with the interval start element.
+        */
        while (prev) {
                rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
-               if (nft_rbtree_interval_end(rbe_prev))
+               if (nft_rbtree_interval_end(rbe_prev) &&
+                   nft_set_elem_active(&rbe_prev->ext, genmask))
                        break;
 
                prev = rb_prev(prev);
        }
 
-       if (rbe_prev) {
+       if (prev) {
+               rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
+
                rb_erase(&rbe_prev->node, &priv->root);
                atomic_dec(&set->nelems);
+               nft_set_gc_batch_add(gcb, rbe_prev);
        }
 
        rb_erase(&rbe->node, &priv->root);
@@ -321,7 +329,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
 
                /* perform garbage collection to avoid bogus overlap reports. */
                if (nft_set_elem_expired(&rbe->ext)) {
-                       err = nft_rbtree_gc_elem(set, priv, rbe);
+                       err = nft_rbtree_gc_elem(set, priv, rbe, genmask);
                        if (err < 0)
                                return err;
 
index 85ff90a..8e3ddec 100644 (file)
@@ -3601,7 +3601,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
        if (dev) {
                sll->sll_hatype = dev->type;
                sll->sll_halen = dev->addr_len;
-               memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len);
+               memcpy(sll->sll_addr_flex, dev->dev_addr, dev->addr_len);
        } else {
                sll->sll_hatype = 0;    /* Bad: we have no ARPHRD_UNSPEC */
                sll->sll_halen = 0;
index 466c26d..382c7a7 100644 (file)
@@ -406,56 +406,6 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
        return 0;
 }
 
-static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
-                            struct cls_bpf_prog *prog, unsigned long base,
-                            struct nlattr **tb, struct nlattr *est, u32 flags,
-                            struct netlink_ext_ack *extack)
-{
-       bool is_bpf, is_ebpf, have_exts = false;
-       u32 gen_flags = 0;
-       int ret;
-
-       is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
-       is_ebpf = tb[TCA_BPF_FD];
-       if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
-               return -EINVAL;
-
-       ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, flags,
-                               extack);
-       if (ret < 0)
-               return ret;
-
-       if (tb[TCA_BPF_FLAGS]) {
-               u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
-
-               if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT)
-                       return -EINVAL;
-
-               have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
-       }
-       if (tb[TCA_BPF_FLAGS_GEN]) {
-               gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
-               if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
-                   !tc_flags_valid(gen_flags))
-                       return -EINVAL;
-       }
-
-       prog->exts_integrated = have_exts;
-       prog->gen_flags = gen_flags;
-
-       ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
-                      cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
-       if (ret < 0)
-               return ret;
-
-       if (tb[TCA_BPF_CLASSID]) {
-               prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
-               tcf_bind_filter(tp, &prog->res, base);
-       }
-
-       return 0;
-}
-
 static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
                          struct tcf_proto *tp, unsigned long base,
                          u32 handle, struct nlattr **tca,
@@ -463,9 +413,12 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
                          struct netlink_ext_ack *extack)
 {
        struct cls_bpf_head *head = rtnl_dereference(tp->root);
+       bool is_bpf, is_ebpf, have_exts = false;
        struct cls_bpf_prog *oldprog = *arg;
        struct nlattr *tb[TCA_BPF_MAX + 1];
+       bool bound_to_filter = false;
        struct cls_bpf_prog *prog;
+       u32 gen_flags = 0;
        int ret;
 
        if (tca[TCA_OPTIONS] == NULL)
@@ -504,11 +457,51 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
                goto errout;
        prog->handle = handle;
 
-       ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], flags,
-                               extack);
+       is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
+       is_ebpf = tb[TCA_BPF_FD];
+       if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) {
+               ret = -EINVAL;
+               goto errout_idr;
+       }
+
+       ret = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &prog->exts,
+                               flags, extack);
+       if (ret < 0)
+               goto errout_idr;
+
+       if (tb[TCA_BPF_FLAGS]) {
+               u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
+
+               if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) {
+                       ret = -EINVAL;
+                       goto errout_idr;
+               }
+
+               have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
+       }
+       if (tb[TCA_BPF_FLAGS_GEN]) {
+               gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
+               if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
+                   !tc_flags_valid(gen_flags)) {
+                       ret = -EINVAL;
+                       goto errout_idr;
+               }
+       }
+
+       prog->exts_integrated = have_exts;
+       prog->gen_flags = gen_flags;
+
+       ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
+               cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
        if (ret < 0)
                goto errout_idr;
 
+       if (tb[TCA_BPF_CLASSID]) {
+               prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
+               tcf_bind_filter(tp, &prog->res, base);
+               bound_to_filter = true;
+       }
+
        ret = cls_bpf_offload(tp, prog, oldprog, extack);
        if (ret)
                goto errout_parms;
@@ -530,6 +523,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
        return 0;
 
 errout_parms:
+       if (bound_to_filter)
+               tcf_unbind_filter(tp, &prog->res);
        cls_bpf_free_parms(prog);
 errout_idr:
        if (!oldprog)
index f2b0bc4..8da9d03 100644 (file)
@@ -2173,53 +2173,6 @@ static bool fl_needs_tc_skb_ext(const struct fl_flow_key *mask)
        return mask->meta.l2_miss;
 }
 
-static int fl_set_parms(struct net *net, struct tcf_proto *tp,
-                       struct cls_fl_filter *f, struct fl_flow_mask *mask,
-                       unsigned long base, struct nlattr **tb,
-                       struct nlattr *est,
-                       struct fl_flow_tmplt *tmplt,
-                       u32 flags, u32 fl_flags,
-                       struct netlink_ext_ack *extack)
-{
-       int err;
-
-       err = tcf_exts_validate_ex(net, tp, tb, est, &f->exts, flags,
-                                  fl_flags, extack);
-       if (err < 0)
-               return err;
-
-       if (tb[TCA_FLOWER_CLASSID]) {
-               f->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
-               if (flags & TCA_ACT_FLAGS_NO_RTNL)
-                       rtnl_lock();
-               tcf_bind_filter(tp, &f->res, base);
-               if (flags & TCA_ACT_FLAGS_NO_RTNL)
-                       rtnl_unlock();
-       }
-
-       err = fl_set_key(net, tb, &f->key, &mask->key, extack);
-       if (err)
-               return err;
-
-       fl_mask_update_range(mask);
-       fl_set_masked_key(&f->mkey, &f->key, mask);
-
-       if (!fl_mask_fits_tmplt(tmplt, mask)) {
-               NL_SET_ERR_MSG_MOD(extack, "Mask does not fit the template");
-               return -EINVAL;
-       }
-
-       /* Enable tc skb extension if filter matches on data extracted from
-        * this extension.
-        */
-       if (fl_needs_tc_skb_ext(&mask->key)) {
-               f->needs_tc_skb_ext = 1;
-               tc_skb_ext_tc_enable();
-       }
-
-       return 0;
-}
-
 static int fl_ht_insert_unique(struct cls_fl_filter *fnew,
                               struct cls_fl_filter *fold,
                               bool *in_ht)
@@ -2251,6 +2204,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        struct cls_fl_head *head = fl_head_dereference(tp);
        bool rtnl_held = !(flags & TCA_ACT_FLAGS_NO_RTNL);
        struct cls_fl_filter *fold = *arg;
+       bool bound_to_filter = false;
        struct cls_fl_filter *fnew;
        struct fl_flow_mask *mask;
        struct nlattr **tb;
@@ -2335,15 +2289,46 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        if (err < 0)
                goto errout_idr;
 
-       err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE],
-                          tp->chain->tmplt_priv, flags, fnew->flags,
-                          extack);
-       if (err)
+       err = tcf_exts_validate_ex(net, tp, tb, tca[TCA_RATE],
+                                  &fnew->exts, flags, fnew->flags,
+                                  extack);
+       if (err < 0)
                goto errout_idr;
 
+       if (tb[TCA_FLOWER_CLASSID]) {
+               fnew->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_lock();
+               tcf_bind_filter(tp, &fnew->res, base);
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_unlock();
+               bound_to_filter = true;
+       }
+
+       err = fl_set_key(net, tb, &fnew->key, &mask->key, extack);
+       if (err)
+               goto unbind_filter;
+
+       fl_mask_update_range(mask);
+       fl_set_masked_key(&fnew->mkey, &fnew->key, mask);
+
+       if (!fl_mask_fits_tmplt(tp->chain->tmplt_priv, mask)) {
+               NL_SET_ERR_MSG_MOD(extack, "Mask does not fit the template");
+               err = -EINVAL;
+               goto unbind_filter;
+       }
+
+       /* Enable tc skb extension if filter matches on data extracted from
+        * this extension.
+        */
+       if (fl_needs_tc_skb_ext(&mask->key)) {
+               fnew->needs_tc_skb_ext = 1;
+               tc_skb_ext_tc_enable();
+       }
+
        err = fl_check_assign_mask(head, fnew, fold, mask);
        if (err)
-               goto errout_idr;
+               goto unbind_filter;
 
        err = fl_ht_insert_unique(fnew, fold, &in_ht);
        if (err)
@@ -2434,6 +2419,16 @@ errout_hw:
                                       fnew->mask->filter_ht_params);
 errout_mask:
        fl_mask_put(head, fnew->mask);
+
+unbind_filter:
+       if (bound_to_filter) {
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_lock();
+               tcf_unbind_filter(tp, &fnew->res);
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_unlock();
+       }
+
 errout_idr:
        if (!fold)
                idr_remove(&head->handle_idr, fnew->handle);
index fa3bbd1..c4ed11d 100644 (file)
@@ -159,26 +159,6 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
        [TCA_MATCHALL_FLAGS]            = { .type = NLA_U32 },
 };
 
-static int mall_set_parms(struct net *net, struct tcf_proto *tp,
-                         struct cls_mall_head *head,
-                         unsigned long base, struct nlattr **tb,
-                         struct nlattr *est, u32 flags, u32 fl_flags,
-                         struct netlink_ext_ack *extack)
-{
-       int err;
-
-       err = tcf_exts_validate_ex(net, tp, tb, est, &head->exts, flags,
-                                  fl_flags, extack);
-       if (err < 0)
-               return err;
-
-       if (tb[TCA_MATCHALL_CLASSID]) {
-               head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
-               tcf_bind_filter(tp, &head->res, base);
-       }
-       return 0;
-}
-
 static int mall_change(struct net *net, struct sk_buff *in_skb,
                       struct tcf_proto *tp, unsigned long base,
                       u32 handle, struct nlattr **tca,
@@ -187,6 +167,7 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
        struct nlattr *tb[TCA_MATCHALL_MAX + 1];
+       bool bound_to_filter = false;
        struct cls_mall_head *new;
        u32 userflags = 0;
        int err;
@@ -226,11 +207,17 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
                goto err_alloc_percpu;
        }
 
-       err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE],
-                            flags, new->flags, extack);
-       if (err)
+       err = tcf_exts_validate_ex(net, tp, tb, tca[TCA_RATE],
+                                  &new->exts, flags, new->flags, extack);
+       if (err < 0)
                goto err_set_parms;
 
+       if (tb[TCA_MATCHALL_CLASSID]) {
+               new->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
+               tcf_bind_filter(tp, &new->res, base);
+               bound_to_filter = true;
+       }
+
        if (!tc_skip_hw(new->flags)) {
                err = mall_replace_hw_filter(tp, new, (unsigned long)new,
                                             extack);
@@ -246,6 +233,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
        return 0;
 
 err_replace_hw_filter:
+       if (bound_to_filter)
+               tcf_unbind_filter(tp, &new->res);
 err_set_parms:
        free_percpu(new->pf);
 err_alloc_percpu:
index d15d50d..5abf31e 100644 (file)
@@ -712,8 +712,23 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
        [TCA_U32_FLAGS]         = { .type = NLA_U32 },
 };
 
+static void u32_unbind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
+                             struct nlattr **tb)
+{
+       if (tb[TCA_U32_CLASSID])
+               tcf_unbind_filter(tp, &n->res);
+}
+
+static void u32_bind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
+                           unsigned long base, struct nlattr **tb)
+{
+       if (tb[TCA_U32_CLASSID]) {
+               n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
+               tcf_bind_filter(tp, &n->res, base);
+       }
+}
+
 static int u32_set_parms(struct net *net, struct tcf_proto *tp,
-                        unsigned long base,
                         struct tc_u_knode *n, struct nlattr **tb,
                         struct nlattr *est, u32 flags, u32 fl_flags,
                         struct netlink_ext_ack *extack)
@@ -760,10 +775,6 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
                if (ht_old)
                        ht_old->refcnt--;
        }
-       if (tb[TCA_U32_CLASSID]) {
-               n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
-               tcf_bind_filter(tp, &n->res, base);
-       }
 
        if (ifindex >= 0)
                n->ifindex = ifindex;
@@ -903,17 +914,27 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                if (!new)
                        return -ENOMEM;
 
-               err = u32_set_parms(net, tp, base, new, tb,
-                                   tca[TCA_RATE], flags, new->flags,
-                                   extack);
+               err = u32_set_parms(net, tp, new, tb, tca[TCA_RATE],
+                                   flags, new->flags, extack);
 
                if (err) {
                        __u32_destroy_key(new);
                        return err;
                }
 
+               u32_bind_filter(tp, new, base, tb);
+
                err = u32_replace_hw_knode(tp, new, flags, extack);
                if (err) {
+                       u32_unbind_filter(tp, new, tb);
+
+                       if (tb[TCA_U32_LINK]) {
+                               struct tc_u_hnode *ht_old;
+
+                               ht_old = rtnl_dereference(n->ht_down);
+                               if (ht_old)
+                                       ht_old->refcnt++;
+                       }
                        __u32_destroy_key(new);
                        return err;
                }
@@ -1074,15 +1095,18 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
        }
 #endif
 
-       err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE],
+       err = u32_set_parms(net, tp, n, tb, tca[TCA_RATE],
                            flags, n->flags, extack);
+
+       u32_bind_filter(tp, n, base, tb);
+
        if (err == 0) {
                struct tc_u_knode __rcu **ins;
                struct tc_u_knode *pins;
 
                err = u32_replace_hw_knode(tp, n, flags, extack);
                if (err)
-                       goto errhw;
+                       goto errunbind;
 
                if (!tc_in_hw(n->flags))
                        n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
@@ -1100,7 +1124,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                return 0;
        }
 
-errhw:
+errunbind:
+       u32_unbind_filter(tp, n, tb);
+
 #ifdef CONFIG_CLS_U32_MARK
        free_percpu(n->pcpu_success);
 #endif
index ab69ff7..793009f 100644 (file)
@@ -290,6 +290,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,
                                                    "Attribute type expected to be TCA_MQPRIO_MIN_RATE64");
                                return -EINVAL;
                        }
+
+                       if (nla_len(attr) != sizeof(u64)) {
+                               NL_SET_ERR_MSG_ATTR(extack, attr,
+                                                   "Attribute TCA_MQPRIO_MIN_RATE64 expected to have 8 bytes length");
+                               return -EINVAL;
+                       }
+
                        if (i >= qopt->num_tc)
                                break;
                        priv->min_rate[i] = nla_get_u64(attr);
@@ -312,6 +319,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,
                                                    "Attribute type expected to be TCA_MQPRIO_MAX_RATE64");
                                return -EINVAL;
                        }
+
+                       if (nla_len(attr) != sizeof(u64)) {
+                               NL_SET_ERR_MSG_ATTR(extack, attr,
+                                                   "Attribute TCA_MQPRIO_MAX_RATE64 expected to have 8 bytes length");
+                               return -EINVAL;
+                       }
+
                        if (i >= qopt->num_tc)
                                break;
                        priv->max_rate[i] = nla_get_u64(attr);
index 577fa5a..302fd74 100644 (file)
@@ -1960,7 +1960,8 @@ rcv:
 
        skb_reset_network_header(*skb);
        skb_pull(*skb, tipc_ehdr_size(ehdr));
-       pskb_trim(*skb, (*skb)->len - aead->authsize);
+       if (pskb_trim(*skb, (*skb)->len - aead->authsize))
+               goto free_skb;
 
        /* Validate TIPCv2 message */
        if (unlikely(!tipc_msg_validate(skb))) {
index 5e000fd..a9c5b65 100644 (file)
@@ -583,7 +583,7 @@ update:
                                 n->capabilities, &n->bc_entry.inputq1,
                                 &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
                pr_warn("Broadcast rcv link creation failed, no memory\n");
-               kfree(n);
+               tipc_node_put(n);
                n = NULL;
                goto exit;
        }
index 123b35d..7858521 100644 (file)
@@ -289,17 +289,29 @@ static int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
        return 0;
 }
 
-static void unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
+static int unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
 {
+       struct sockaddr_storage *addr = (struct sockaddr_storage *)sunaddr;
+       short offset = offsetof(struct sockaddr_storage, __data);
+
+       BUILD_BUG_ON(offset != offsetof(struct sockaddr_un, sun_path));
+
        /* This may look like an off by one error but it is a bit more
         * subtle.  108 is the longest valid AF_UNIX path for a binding.
         * sun_path[108] doesn't as such exist.  However in kernel space
         * we are guaranteed that it is a valid memory location in our
         * kernel address buffer because syscall functions always pass
         * a pointer of struct sockaddr_storage which has a bigger buffer
-        * than 108.
+        * than 108.  Also, we must terminate sun_path for strlen() in
+        * getname_kernel().
+        */
+       addr->__data[addr_len - offset] = 0;
+
+       /* Don't pass sunaddr->sun_path to strlen().  Otherwise, 108 will
+        * cause panic if CONFIG_FORTIFY_SOURCE=y.  Let __fortify_strlen()
+        * know the actual buffer.
         */
-       ((char *)sunaddr)[addr_len] = 0;
+       return strlen(addr->__data) + offset + 1;
 }
 
 static void __unix_remove_socket(struct sock *sk)
@@ -1208,10 +1220,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
        struct path parent;
        int err;
 
-       unix_mkname_bsd(sunaddr, addr_len);
-       addr_len = strlen(sunaddr->sun_path) +
-               offsetof(struct sockaddr_un, sun_path) + 1;
-
+       addr_len = unix_mkname_bsd(sunaddr, addr_len);
        addr = unix_create_addr(sunaddr, addr_len);
        if (!addr)
                return -ENOMEM;
index 6413342..82e3fb1 100644 (file)
@@ -264,6 +264,9 @@ $(obj)/%.lst: $(src)/%.c FORCE
 
 rust_allowed_features := new_uninit
 
+# `--out-dir` is required to avoid temporaries being created by `rustc` in the
+# current working directory, which may be not accessible in the out-of-tree
+# modules case.
 rust_common_cmd = \
        RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \
        -Zallow-features=$(rust_allowed_features) \
@@ -272,7 +275,7 @@ rust_common_cmd = \
        --extern alloc --extern kernel \
        --crate-type rlib -L $(objtree)/rust/ \
        --crate-name $(basename $(notdir $@)) \
-       --emit=dep-info=$(depfile)
+       --out-dir $(dir $@) --emit=dep-info=$(depfile)
 
 # `--emit=obj`, `--emit=asm` and `--emit=llvm-ir` imply a single codegen unit
 # will be used. We explicitly request `-Ccodegen-units=1` in any case, and
index 7aea900..8f7f842 100644 (file)
@@ -86,7 +86,11 @@ hostc_flags    = -Wp,-MMD,$(depfile) \
 hostcxx_flags  = -Wp,-MMD,$(depfile) \
                  $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
                  $(HOSTCXXFLAGS_$(target-stem).o)
-hostrust_flags = --emit=dep-info=$(depfile) \
+
+# `--out-dir` is required to avoid temporaries being created by `rustc` in the
+# current working directory, which may be not accessible in the out-of-tree
+# modules case.
+hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
                  $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
                  $(HOSTRUSTFLAGS_$(target-stem))
 
index 15ba565..a84cc57 100755 (executable)
@@ -19,7 +19,7 @@ _DEFAULT_OUTPUT = 'compile_commands.json'
 _DEFAULT_LOG_LEVEL = 'WARNING'
 
 _FILENAME_PATTERN = r'^\..*\.cmd$'
-_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.c) *(;|$)'
+_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.[cS]) *(;|$)'
 _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
 # The tools/ directory adopts a different build system, and produces .cmd
 # files in a different format. Do not support it.
index 17adabf..9709aca 100644 (file)
@@ -636,7 +636,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *intro_text =
-           "Welcome to gkc, the GTK+ graphical configuration tool\n"
+           "Welcome to gconfig, the GTK+ graphical configuration tool.\n"
            "For each option, a blank box indicates the feature is disabled, a\n"
            "check indicates it is enabled, and a dot indicates that it is to\n"
            "be compiled as a module.  Clicking on the box will cycle through the three states.\n"
@@ -647,10 +647,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
            "Although there is no cross reference yet to help you figure out\n"
            "what other options must be enabled to support the option you\n"
            "are interested in, you can still view the help of a grayed-out\n"
-           "option.\n"
-           "\n"
-           "Toggling Show Debug Info under the Options menu will show \n"
-           "the dependencies, which you can then match by examining other options.";
+           "option.";
 
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -667,7 +664,7 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *about_text =
-           "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+           "gconfig is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
              "Based on the source code from Roman Zippel.\n";
 
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
@@ -685,7 +682,7 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *license_text =
-           "gkc is released under the terms of the GNU GPL v2.\n"
+           "gconfig is released under the terms of the GNU GPL v2.\n"
              "For more information, please see the source code or\n"
              "visit http://www.fsf.org/licenses/licenses.html\n";
 
index 07a0ef2..a7673ad 100644 (file)
@@ -401,17 +401,21 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
        set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
 
        if (dest_keyring) {
-               ret = __key_link_lock(dest_keyring, &ctx->index_key);
+               ret = __key_link_lock(dest_keyring, &key->index_key);
                if (ret < 0)
                        goto link_lock_failed;
-               ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit);
-               if (ret < 0)
-                       goto link_prealloc_failed;
        }
 
-       /* attach the key to the destination keyring under lock, but we do need
+       /*
+        * Attach the key to the destination keyring under lock, but we do need
         * to do another check just in case someone beat us to it whilst we
-        * waited for locks */
+        * waited for locks.
+        *
+        * The caller might specify a comparison function which looks for keys
+        * that do not exactly match but are still equivalent from the caller's
+        * perspective. The __key_link_begin() operation must be done only after
+        * an actual key is determined.
+        */
        mutex_lock(&key_construction_mutex);
 
        rcu_read_lock();
@@ -420,12 +424,16 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
        if (!IS_ERR(key_ref))
                goto key_already_present;
 
-       if (dest_keyring)
+       if (dest_keyring) {
+               ret = __key_link_begin(dest_keyring, &key->index_key, &edit);
+               if (ret < 0)
+                       goto link_alloc_failed;
                __key_link(dest_keyring, key, &edit);
+       }
 
        mutex_unlock(&key_construction_mutex);
        if (dest_keyring)
-               __key_link_end(dest_keyring, &ctx->index_key, edit);
+               __key_link_end(dest_keyring, &key->index_key, edit);
        mutex_unlock(&user->cons_lock);
        *_key = key;
        kleave(" = 0 [%d]", key_serial(key));
@@ -438,10 +446,13 @@ key_already_present:
        mutex_unlock(&key_construction_mutex);
        key = key_ref_to_ptr(key_ref);
        if (dest_keyring) {
+               ret = __key_link_begin(dest_keyring, &key->index_key, &edit);
+               if (ret < 0)
+                       goto link_alloc_failed_unlocked;
                ret = __key_link_check_live_key(dest_keyring, key);
                if (ret == 0)
                        __key_link(dest_keyring, key, &edit);
-               __key_link_end(dest_keyring, &ctx->index_key, edit);
+               __key_link_end(dest_keyring, &key->index_key, edit);
                if (ret < 0)
                        goto link_check_failed;
        }
@@ -456,8 +467,10 @@ link_check_failed:
        kleave(" = %d [linkcheck]", ret);
        return ret;
 
-link_prealloc_failed:
-       __key_link_end(dest_keyring, &ctx->index_key, edit);
+link_alloc_failed:
+       mutex_unlock(&key_construction_mutex);
+link_alloc_failed_unlocked:
+       __key_link_end(dest_keyring, &key->index_key, edit);
 link_lock_failed:
        mutex_unlock(&user->cons_lock);
        key_put(key);
index 2b2c8eb..bc700f8 100644 (file)
@@ -186,7 +186,7 @@ int tpm2_key_priv(void *context, size_t hdrlen,
 }
 
 /**
- * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
+ * tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
  *
  * @buf: an allocated tpm_buf instance
  * @session_handle: session handle
index 9b80f82..f3f14ff 100644 (file)
@@ -149,6 +149,7 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
        write_lock_irq(&client->ports_lock);
        list_for_each_entry(p, &client->ports_list_head, list) {
                if (p->addr.port == port) {
+                       kfree(new_port);
                        num = -EBUSY;
                        goto unlock;
                }
index fe21c80..f26a181 100644 (file)
@@ -298,8 +298,7 @@ static void update_group_attrs(struct seq_ump_client *client)
        }
 
        list_for_each_entry(fb, &client->ump->block_list, list) {
-               if (fb->info.first_group < 0 ||
-                   fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
+               if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
                        break;
                group = &client->groups[fb->info.first_group];
                for (i = 0; i < fb->info.num_groups; i++, group++) {
index 2ae912a..291e7fe 100644 (file)
@@ -110,8 +110,6 @@ struct pcmtst_buf_iter {
        struct timer_list timer_instance;
 };
 
-static struct pcmtst *pcmtst;
-
 static struct snd_pcm_hardware snd_pcmtst_hw = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED |
                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -552,6 +550,7 @@ _err_free_chip:
 static int pcmtst_probe(struct platform_device *pdev)
 {
        struct snd_card *card;
+       struct pcmtst *pcmtst;
        int err;
 
        err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
@@ -573,13 +572,16 @@ static int pcmtst_probe(struct platform_device *pdev)
        if (err < 0)
                return err;
 
+       platform_set_drvdata(pdev, pcmtst);
+
        return 0;
 }
 
-static int pdev_remove(struct platform_device *dev)
+static void pdev_remove(struct platform_device *pdev)
 {
+       struct pcmtst *pcmtst = platform_get_drvdata(pdev);
+
        snd_pcmtst_free(pcmtst);
-       return 0;
 }
 
 static struct platform_device pcmtst_pdev = {
@@ -589,7 +591,7 @@ static struct platform_device pcmtst_pdev = {
 
 static struct platform_driver pcmtst_pdrv = {
        .probe =        pcmtst_probe,
-       .remove =       pdev_remove,
+       .remove_new =   pdev_remove,
        .driver =       {
                .name = "pcmtest",
        },
index e2f8b60..44fccfb 100644 (file)
@@ -122,6 +122,7 @@ struct alc_spec {
        unsigned int ultra_low_power:1;
        unsigned int has_hs_key:1;
        unsigned int no_internal_mic_pin:1;
+       unsigned int en_3kpull_low:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -3622,6 +3623,7 @@ static void alc256_shutup(struct hda_codec *codec)
        if (!hp_pin)
                hp_pin = 0x21;
 
+       alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
        hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 
        if (hp_pin_sense)
@@ -3638,8 +3640,7 @@ static void alc256_shutup(struct hda_codec *codec)
        /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
         * when booting with headset plugged. So skip setting it for the codec alc257
         */
-       if (codec->core.vendor_id != 0x10ec0236 &&
-           codec->core.vendor_id != 0x10ec0257)
+       if (spec->en_3kpull_low)
                alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
 
        if (!spec->no_shutup_pins)
@@ -4623,6 +4624,21 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
        }
 }
 
+static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec,
+                                         const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->mute_led_polarity = 0;
+               spec->mute_led_coef.idx = 0x07;
+               spec->mute_led_coef.mask = 1;
+               spec->mute_led_coef.on = 1;
+               spec->mute_led_coef.off = 0;
+               snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
+       }
+}
+
 /* turn on/off mic-mute LED per capture hook by coef bit */
 static int coef_micmute_led_set(struct led_classdev *led_cdev,
                                enum led_brightness brightness)
@@ -7143,6 +7159,7 @@ enum {
        ALC285_FIXUP_HP_GPIO_LED,
        ALC285_FIXUP_HP_MUTE_LED,
        ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
+       ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
        ALC236_FIXUP_HP_GPIO_LED,
        ALC236_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
@@ -7213,6 +7230,7 @@ enum {
        ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
        ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
        ALC236_FIXUP_DELL_DUAL_CODECS,
+       ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
 };
 
 /* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -8632,6 +8650,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc285_fixup_hp_spectre_x360_mute_led,
        },
+       [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = {
+           .type = HDA_FIXUP_FUNC,
+           .v.func = alc236_fixup_hp_mute_led_coefbit2,
+       },
        [ALC236_FIXUP_HP_GPIO_LED] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc236_fixup_hp_gpio_led,
@@ -9145,8 +9167,6 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC287_FIXUP_CS35L41_I2C_2] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cs35l41_fixup_i2c_two,
-               .chained = true,
-               .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
        },
        [ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED] = {
                .type = HDA_FIXUP_FUNC,
@@ -9283,6 +9303,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
        },
+       [ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cs35l41_fixup_i2c_two,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -9393,6 +9419,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0c1c, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
        SND_PCI_QUIRK(0x1028, 0x0c1d, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
        SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc5, "Dell Oasis MLK 14 RPL-P", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -9507,6 +9541,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
        SND_PCI_QUIRK(0x103c, 0x8812, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+       SND_PCI_QUIRK(0x103c, 0x881d, "HP 250 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
@@ -9516,6 +9551,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+       SND_PCI_QUIRK(0x103c, 0x887a, "HP Laptop 15s-eq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
@@ -9636,6 +9672,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2),
@@ -9727,6 +9764,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51b1, "Clevo NS50AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -9810,14 +9848,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
-       SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
        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),
@@ -10682,6 +10720,8 @@ static int patch_alc269(struct hda_codec *codec)
                spec->shutup = alc256_shutup;
                spec->init_hook = alc256_init;
                spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
+               if (codec->bus->pci->vendor == PCI_VENDOR_ID_AMD)
+                       spec->en_3kpull_low = true;
                break;
        case 0x10ec0257:
                spec->codec_variant = ALC269_TYPE_ALC257;
index 5f2119f..12a176a 100644 (file)
@@ -173,7 +173,7 @@ int snd_amd_acp_find_config(struct pci_dev *pci);
 
 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
 {
-       u64 byte_count, low = 0, high = 0;
+       u64 byte_count = 0, low = 0, high = 0;
 
        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
                switch (dai_id) {
@@ -191,7 +191,7 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
                        break;
                default:
                        dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
-                       return -EINVAL;
+                       goto POINTER_RETURN_BYTES;
                }
        } else {
                switch (dai_id) {
@@ -213,12 +213,13 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
                        break;
                default:
                        dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
-                       return -EINVAL;
+                       goto POINTER_RETURN_BYTES;
                }
        }
        /* Get 64 bit value from two 32 bit registers */
        byte_count = (high << 32) | low;
 
+POINTER_RETURN_BYTES:
        return byte_count;
 }
 
index e96e6dc..8b853b8 100644 (file)
 #define ACP63_SDW0_DMA_MAX_STREAMS     6
 #define ACP63_SDW1_DMA_MAX_STREAMS     2
 #define ACP_P1_AUDIO_TX_THRESHOLD      6
+
+/*
+ * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping
+ * in ACP_EXTENAL_INTR_CNTL register.
+ * Stream id           IRQ Bit
+ * 0 (SDW0_AUDIO0_TX)  28
+ * 1 (SDW0_AUDIO1_TX)  26
+ * 2 (SDW0_AUDIO2_TX)  24
+ * 3 (SDW0_AUDIO0_RX)  27
+ * 4 (SDW0_AUDIO1_RX)  25
+ * 5 (SDW0_AUDIO2_RX)  23
+ */
 #define SDW0_DMA_TX_IRQ_MASK(i)        (ACP_AUDIO0_TX_THRESHOLD - (2 * (i)))
-#define SDW0_DMA_RX_IRQ_MASK(i)        (ACP_AUDIO0_RX_THRESHOLD - (2 * (i)))
+#define SDW0_DMA_RX_IRQ_MASK(i)        (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3)))
+
+/*
+ * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping
+ * in ACP_EXTENAL_INTR_CNTL1 register.
+ * Stream id           IRQ Bit
+ * 0 (SDW1_AUDIO1_TX)  6
+ * 1 (SDW1_AUDIO1_RX)  5
+ */
 #define SDW1_DMA_IRQ_MASK(i)   (ACP_P1_AUDIO_TX_THRESHOLD - (i))
 
 #define ACP_DELAY_US           5
index 5b46dc8..4af3c36 100644 (file)
@@ -257,7 +257,7 @@ static int sdw_amd_scan_controller(struct device *dev)
                                             &sdw_manager_bitmap, 1);
 
        if (ret) {
-               dev_err(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
+               dev_dbg(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
                return -EINVAL;
        }
        count = hweight32(sdw_manager_bitmap);
@@ -641,7 +641,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
        ret = get_acp63_device_config(val, pci, adata);
        /* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */
        if (ret) {
-               dev_err(&pci->dev, "get acp device config failed:%d\n", ret);
+               dev_dbg(&pci->dev, "get acp device config failed:%d\n", ret);
                goto skip_pdev_creation;
        }
        ret = create_acp63_platform_devs(pci, adata, addr);
index ade130a..324c80f 100644 (file)
@@ -30,7 +30,7 @@ static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STRE
         ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH},
        {ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE,
         ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE,
-        ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
+        ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH},
        {ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE,
         ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE,
         ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
@@ -39,6 +39,11 @@ static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STRE
         ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH}
 };
 
+/*
+ * SDW1 instance supports one TX stream and one RX stream.
+ * For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register
+ * set as per hardware register documentation
+ */
 static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STREAMS] =  {
        {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE,
         ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR,
@@ -59,6 +64,12 @@ static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = {
        ACP_SW0_AUDIO2_RX_EN,
 };
 
+/*
+ * SDW1 instance supports one TX stream and one RX stream.
+ * For TX/RX streams DMA enable register programming for SDW1 instance,
+ * it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers
+ * as per hardware register documentation.
+ */
 static u32 sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = {
        ACP_SW1_AUDIO1_TX_EN,
        ACP_SW1_AUDIO1_RX_EN,
@@ -307,12 +318,13 @@ static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __io
                pos_high_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_high_reg;
                break;
        default:
-               return -EINVAL;
+               goto POINTER_RETURN_BYTES;
        }
        if (pos_low_reg) {
                byte_count.bcount.high = readl(acp_base + pos_high_reg);
                byte_count.bcount.low = readl(acp_base + pos_low_reg);
        }
+POINTER_RETURN_BYTES:
        return byte_count.bytescount;
 }
 
index 49930ba..69a88dc 100644 (file)
@@ -163,11 +163,14 @@ struct atmel_i2s_gck_param {
 
 #define I2S_MCK_12M288         12288000UL
 #define I2S_MCK_11M2896                11289600UL
+#define I2S_MCK_6M144          6144000UL
 
 /* mck = (32 * (imckfs+1) / (imckdiv+1)) * fs */
 static const struct atmel_i2s_gck_param gck_params[] = {
+       /* mck = 6.144Mhz */
+       {  8000, I2S_MCK_6M144,  1, 47},        /* mck =  768 fs */
+
        /* mck = 12.288MHz */
-       {  8000, I2S_MCK_12M288, 0, 47},        /* mck = 1536 fs */
        { 16000, I2S_MCK_12M288, 1, 47},        /* mck =  768 fs */
        { 24000, I2S_MCK_12M288, 3, 63},        /* mck =  512 fs */
        { 32000, I2S_MCK_12M288, 3, 47},        /* mck =  384 fs */
index 2a62dbd..c2de4ee 100644 (file)
@@ -715,6 +715,7 @@ config SND_SOC_CS35L41_I2C
 
 config SND_SOC_CS35L45
        tristate
+       select REGMAP_IRQ
 
 config SND_SOC_CS35L45_SPI
        tristate "Cirrus Logic CS35L45 CODEC (SPI)"
@@ -1942,6 +1943,7 @@ config SND_SOC_WCD934X
        tristate "WCD9340/WCD9341 Codec"
        depends on COMMON_CLK
        depends on SLIMBUS
+       select REGMAP_IRQ
        select REGMAP_SLIMBUS
        select SND_SOC_WCD_MBHC
        depends on MFD_WCD934X || COMPILE_TEST
index b2106ff..e7db7bc 100644 (file)
@@ -19,6 +19,12 @@ static struct i2c_device_id cs42l51_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id);
 
+const struct of_device_id cs42l51_of_match[] = {
+       { .compatible = "cirrus,cs42l51", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, cs42l51_of_match);
+
 static int cs42l51_i2c_probe(struct i2c_client *i2c)
 {
        struct regmap_config config;
index a67cd3e..a7079ae 100644 (file)
@@ -823,13 +823,6 @@ int __maybe_unused cs42l51_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(cs42l51_resume);
 
-const struct of_device_id cs42l51_of_match[] = {
-       { .compatible = "cirrus,cs42l51", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, cs42l51_of_match);
-EXPORT_SYMBOL_GPL(cs42l51_of_match);
-
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
 MODULE_LICENSE("GPL");
index a79343e..125703e 100644 (file)
@@ -16,7 +16,6 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap);
 void cs42l51_remove(struct device *dev);
 int __maybe_unused cs42l51_suspend(struct device *dev);
 int __maybe_unused cs42l51_resume(struct device *dev);
-extern const struct of_device_id cs42l51_of_match[];
 
 #define CS42L51_CHIP_ID                        0x1B
 #define CS42L51_CHIP_REV_A             0x00
index c65256b..581b334 100644 (file)
@@ -361,11 +361,15 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
        struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
        u8 events[DA7219_AAD_IRQ_REG_MAX];
        u8 statusa;
-       int i, report = 0, mask = 0;
+       int i, ret, report = 0, mask = 0;
 
        /* Read current IRQ events */
-       regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
-                        events, DA7219_AAD_IRQ_REG_MAX);
+       ret = regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
+                              events, DA7219_AAD_IRQ_REG_MAX);
+       if (ret) {
+               dev_warn_ratelimited(component->dev, "Failed to read IRQ events: %d\n", ret);
+               return IRQ_NONE;
+       }
 
        if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B])
                return IRQ_NONE;
@@ -944,6 +948,8 @@ void da7219_aad_suspend(struct snd_soc_component *component)
                        }
                }
        }
+
+       synchronize_irq(da7219_aad->irq);
 }
 
 void da7219_aad_resume(struct snd_soc_component *component)
index 34cf607..65e497b 100644 (file)
@@ -153,7 +153,7 @@ static const char * const es8316_dmic_txt[] = {
                "dmic data at high level",
                "dmic data at low level",
 };
-static const unsigned int es8316_dmic_values[] = { 0, 1, 2 };
+static const unsigned int es8316_dmic_values[] = { 0, 2, 3 };
 static const struct soc_enum es8316_dmic_src_enum =
        SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
                              ARRAY_SIZE(es8316_dmic_txt),
index 96d7588..ca6beb2 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <sound/tlv.h>
 #include "nau8821.h"
 
+#define NAU8821_JD_ACTIVE_HIGH                 BIT(0)
+
+static int nau8821_quirk;
+static int quirk_override = -1;
+module_param_named(quirk, quirk_override, uint, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
+
 #define NAU_FREF_MAX 13500000
 #define NAU_FVCO_MAX 100000000
 #define NAU_FVCO_MIN 90000000
@@ -1792,6 +1800,33 @@ static int nau8821_setup_irq(struct nau8821 *nau8821)
        return 0;
 }
 
+/* Please keep this list alphabetically sorted */
+static const struct dmi_system_id nau8821_quirk_table[] = {
+       {
+               /* Positivo CW14Q01P-V2 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+                       DMI_MATCH(DMI_BOARD_NAME, "CW14Q01P-V2"),
+               },
+               .driver_data = (void *)(NAU8821_JD_ACTIVE_HIGH),
+       },
+       {}
+};
+
+static void nau8821_check_quirks(void)
+{
+       const struct dmi_system_id *dmi_id;
+
+       if (quirk_override != -1) {
+               nau8821_quirk = quirk_override;
+               return;
+       }
+
+       dmi_id = dmi_first_match(nau8821_quirk_table);
+       if (dmi_id)
+               nau8821_quirk = (unsigned long)dmi_id->driver_data;
+}
+
 static int nau8821_i2c_probe(struct i2c_client *i2c)
 {
        struct device *dev = &i2c->dev;
@@ -1812,6 +1847,12 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)
 
        nau8821->dev = dev;
        nau8821->irq = i2c->irq;
+
+       nau8821_check_quirks();
+
+       if (nau8821_quirk & NAU8821_JD_ACTIVE_HIGH)
+               nau8821->jkdet_polarity = 0;
+
        nau8821_print_device_properties(nau8821);
 
        nau8821_reset_chip(nau8821->regmap);
index 0ed4fa2..eceed82 100644 (file)
@@ -53,7 +53,6 @@ static const struct reg_sequence init_list[] = {
        {RT5640_PR_BASE + 0x3d, 0x3600},
        {RT5640_PR_BASE + 0x12, 0x0aa8},
        {RT5640_PR_BASE + 0x14, 0x0aaa},
-       {RT5640_PR_BASE + 0x20, 0x6110},
        {RT5640_PR_BASE + 0x21, 0xe0e0},
        {RT5640_PR_BASE + 0x23, 0x1804},
 };
@@ -2567,9 +2566,10 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
        if (jack_data && jack_data->use_platform_clock)
                rt5640->use_platform_clock = jack_data->use_platform_clock;
 
-       ret = request_irq(rt5640->irq, rt5640_irq,
-                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                         "rt5640", rt5640);
+       ret = devm_request_threaded_irq(component->dev, rt5640->irq,
+                                       NULL, rt5640_irq,
+                                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                       "rt5640", rt5640);
        if (ret) {
                dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
                rt5640_disable_jack_detect(component);
@@ -2622,8 +2622,9 @@ static void rt5640_enable_hda_jack_detect(
 
        rt5640->jack = jack;
 
-       ret = request_irq(rt5640->irq, rt5640_irq,
-                         IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
+       ret = devm_request_threaded_irq(component->dev, rt5640->irq,
+                                       NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                       "rt5640", rt5640);
        if (ret) {
                dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
                rt5640->irq = -ENXIO;
index acc7fb1..a506d94 100644 (file)
@@ -3950,7 +3950,11 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
         * read and power On.
         */
        msleep(TIME_TO_POWER_MS);
-       regmap_read(regmap, RT5645_VENDOR_ID2, &val);
+       ret = regmap_read(regmap, RT5645_VENDOR_ID2, &val);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read: 0x%02X\n, ret = %d", RT5645_VENDOR_ID2, ret);
+               goto err_enable;
+       }
 
        switch (val) {
        case RT5645_DEVICE_ID:
index 67404f4..4968a8c 100644 (file)
@@ -750,8 +750,15 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
        if (!rt5682->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt5682->disable_irq == true) {
+                       mutex_lock(&rt5682->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
+                       rt5682->disable_irq = false;
+                       mutex_unlock(&rt5682->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
index 119e1f9..23f23f7 100644 (file)
@@ -438,8 +438,16 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
        if (!rt711->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt711->disable_irq == true) {
+                       mutex_lock(&rt711->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt711->disable_irq = false;
+                       mutex_unlock(&rt711->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT711_PROBE_TIMEOUT));
index 87dafcb..33dced3 100644 (file)
@@ -538,8 +538,15 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
        if (!rt711->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt711->disable_irq == true) {
+                       mutex_lock(&rt711->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
+                       rt711->disable_irq = false;
+                       mutex_unlock(&rt711->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT711_PROBE_TIMEOUT));
index ad06267..6bc5039 100644 (file)
@@ -438,8 +438,16 @@ static int __maybe_unused rt712_sdca_dev_resume(struct device *dev)
        if (!rt712->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt712->disable_irq == true) {
+                       mutex_lock(&rt712->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt712->disable_irq = false;
+                       mutex_unlock(&rt712->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT712_PROBE_TIMEOUT));
index cc57e4e..e9103ff 100644 (file)
@@ -463,8 +463,16 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev)
        if (!rt722->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt722->disable_irq == true) {
+                       mutex_lock(&rt722->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt722->disable_irq = false;
+                       mutex_unlock(&rt722->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT722_PROBE_TIMEOUT));
index 1911750..5da1934 100644 (file)
@@ -1454,7 +1454,7 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
                return ERR_PTR(-EINVAL);
        }
 
-       mbhc = devm_kzalloc(dev, sizeof(*mbhc), GFP_KERNEL);
+       mbhc = kzalloc(sizeof(*mbhc), GFP_KERNEL);
        if (!mbhc)
                return ERR_PTR(-ENOMEM);
 
@@ -1474,61 +1474,76 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
 
        INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_sw_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_sw_intr, NULL,
                                        wcd_mbhc_mech_plug_detect_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "mbhc sw intr", mbhc);
        if (ret)
-               goto err;
+               goto err_free_mbhc;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_press_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_press_intr, NULL,
                                        wcd_mbhc_btn_press_handler,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Button Press detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_sw_intr;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_release_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_release_intr, NULL,
                                        wcd_mbhc_btn_release_handler,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Button Release detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_btn_press_intr;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_ins_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_ins_intr, NULL,
                                        wcd_mbhc_adc_hs_ins_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Elect Insert", mbhc);
        if (ret)
-               goto err;
+               goto err_free_btn_release_intr;
 
        disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_rem_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_rem_intr, NULL,
                                        wcd_mbhc_adc_hs_rem_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Elect Remove", mbhc);
        if (ret)
-               goto err;
+               goto err_free_hs_ins_intr;
 
        disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_left_ocp, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->hph_left_ocp, NULL,
                                        wcd_mbhc_hphl_ocp_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "HPH_L OCP detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_hs_rem_intr;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_right_ocp, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->hph_right_ocp, NULL,
                                        wcd_mbhc_hphr_ocp_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "HPH_R OCP detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_hph_left_ocp;
 
        return mbhc;
-err:
+
+err_free_hph_left_ocp:
+       free_irq(mbhc->intr_ids->hph_left_ocp, mbhc);
+err_free_hs_rem_intr:
+       free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
+err_free_hs_ins_intr:
+       free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
+err_free_btn_release_intr:
+       free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc);
+err_free_btn_press_intr:
+       free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc);
+err_free_sw_intr:
+       free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc);
+err_free_mbhc:
+       kfree(mbhc);
+
        dev_err(dev, "Failed to request mbhc interrupts %d\n", ret);
 
        return ERR_PTR(ret);
@@ -1537,9 +1552,19 @@ EXPORT_SYMBOL(wcd_mbhc_init);
 
 void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
 {
+       free_irq(mbhc->intr_ids->hph_right_ocp, mbhc);
+       free_irq(mbhc->intr_ids->hph_left_ocp, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc);
+
        mutex_lock(&mbhc->lock);
        wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
        mutex_unlock(&mbhc->lock);
+
+       kfree(mbhc);
 }
 EXPORT_SYMBOL(wcd_mbhc_deinit);
 
index c0d1fa3..1b6e376 100644 (file)
@@ -2642,7 +2642,7 @@ static int wcd934x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon
        return rc;
 }
 
-static inline void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x,
+static void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x,
                                                s16 *d1_a, u16 noff,
                                                int32_t *zdet)
 {
@@ -2683,7 +2683,7 @@ static inline void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x,
        else if (x1 < minCode_param[noff])
                *zdet = WCD934X_ZDET_FLOATING_IMPEDANCE;
 
-       dev_info(wcd934x->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+       dev_dbg(wcd934x->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%di (milliohm)\n",
                __func__, d1, c1, x1, *zdet);
 ramp_down:
        i = 0;
@@ -2740,8 +2740,8 @@ z_right:
        *zr = zdet;
 }
 
-static inline void wcd934x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
-                                             int32_t *z_val, int flag_l_r)
+static void wcd934x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+                                       int32_t *z_val, int flag_l_r)
 {
        s16 q1;
        int q1_cal;
@@ -3044,6 +3044,17 @@ static int wcd934x_mbhc_init(struct snd_soc_component *component)
 
        return 0;
 }
+
+static void wcd934x_mbhc_deinit(struct snd_soc_component *component)
+{
+       struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(component);
+
+       if (!wcd->mbhc)
+               return;
+
+       wcd_mbhc_deinit(wcd->mbhc);
+}
+
 static int wcd934x_comp_probe(struct snd_soc_component *component)
 {
        struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
@@ -3077,6 +3088,7 @@ static void wcd934x_comp_remove(struct snd_soc_component *comp)
 {
        struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
 
+       wcd934x_mbhc_deinit(comp);
        wcd_clsh_ctrl_free(wcd->clsh_ctrl);
 }
 
index e7d6a02..a3c6806 100644 (file)
@@ -210,7 +210,7 @@ struct wcd938x_priv {
 };
 
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
-static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(line_gain, 600, -3000);
+static const DECLARE_TLV_DB_SCALE(line_gain, -3000, 150, -3000);
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000);
 
 struct wcd938x_mbhc_zdet_param {
@@ -2124,10 +2124,11 @@ static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon
        return wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
 }
 
-static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
+static void wcd938x_mbhc_get_result_params(struct snd_soc_component *component,
                                                s16 *d1_a, u16 noff,
                                                int32_t *zdet)
 {
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
        int i;
        int val, val1;
        s16 c1;
@@ -2154,8 +2155,8 @@ static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
                usleep_range(5000, 5050);
 
        if (!c1 || !x1) {
-               pr_err("%s: Impedance detect ramp error, c1=%d, x1=0x%x\n",
-                       __func__, c1, x1);
+               dev_err(component->dev, "Impedance detect ramp error, c1=%d, x1=0x%x\n",
+                       c1, x1);
                goto ramp_down;
        }
        d1 = d1_a[c1];
@@ -2165,7 +2166,7 @@ static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
        else if (x1 < minCode_param[noff])
                *zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;
 
-       pr_err("%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+       dev_dbg(component->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d (milliohm)\n",
                __func__, d1, c1, x1, *zdet);
 ramp_down:
        i = 0;
@@ -2210,7 +2211,7 @@ static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,
                           WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);
        dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n",
                __func__, zdet_param->noff);
-       wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+       wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);
        regmap_update_bits(wcd938x->regmap,
                           WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);
 
@@ -2224,15 +2225,15 @@ z_right:
                           WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);
        dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n",
                __func__, zdet_param->noff);
-       wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+       wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);
        regmap_update_bits(wcd938x->regmap,
                           WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);
 
        *zr = zdet;
 }
 
-static inline void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
-                                             int32_t *z_val, int flag_l_r)
+static void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+                                       int32_t *z_val, int flag_l_r)
 {
        s16 q1;
        int q1_cal;
@@ -2625,6 +2626,8 @@ static int wcd938x_mbhc_init(struct snd_soc_component *component)
                                                     WCD938X_IRQ_HPHR_OCP_INT);
 
        wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true);
+       if (IS_ERR(wcd938x->wcd_mbhc))
+               return PTR_ERR(wcd938x->wcd_mbhc);
 
        snd_soc_add_component_controls(component, impedance_detect_controls,
                                       ARRAY_SIZE(impedance_detect_controls));
@@ -2633,6 +2636,14 @@ static int wcd938x_mbhc_init(struct snd_soc_component *component)
 
        return 0;
 }
+
+static void wcd938x_mbhc_deinit(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       wcd_mbhc_deinit(wcd938x->wcd_mbhc);
+}
+
 /* END MBHC */
 
 static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
@@ -2652,8 +2663,8 @@ static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
                       wcd938x_get_swr_port, wcd938x_set_swr_port),
        SOC_SINGLE_EXT("DSD_R Switch", WCD938X_DSD_R, 0, 1, 0,
                       wcd938x_get_swr_port, wcd938x_set_swr_port),
-       SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 0, line_gain),
-       SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 0, line_gain),
+       SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 1, line_gain),
+       SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 1, line_gain),
        WCD938X_EAR_PA_GAIN_TLV("EAR_PA Volume", WCD938X_ANA_EAR_COMPANDER_CTL,
                                2, 0x10, 0, ear_pa_gain),
        SOC_SINGLE_EXT("ADC1 Switch", WCD938X_ADC1, 1, 1, 0,
@@ -3080,16 +3091,33 @@ static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev)
 static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
 {
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev;
        struct device *dev = component->dev;
+       unsigned long time_left;
        int ret, i;
 
+       time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
+                                               msecs_to_jiffies(2000));
+       if (!time_left) {
+               dev_err(dev, "soundwire device init timeout\n");
+               return -ETIMEDOUT;
+       }
+
        snd_soc_component_init_regmap(component, wcd938x->regmap);
 
+       ret = pm_runtime_resume_and_get(dev);
+       if (ret < 0)
+               return ret;
+
        wcd938x->variant = snd_soc_component_read_field(component,
                                                 WCD938X_DIGITAL_EFUSE_REG_0,
                                                 WCD938X_ID_MASK);
 
        wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X);
+       if (IS_ERR(wcd938x->clsh_info)) {
+               pm_runtime_put(dev);
+               return PTR_ERR(wcd938x->clsh_info);
+       }
 
        wcd938x_io_init(wcd938x);
        /* Set all interrupts as edge triggered */
@@ -3098,6 +3126,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
                             (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0);
        }
 
+       pm_runtime_put(dev);
+
        wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
                                                       WCD938X_IRQ_HPHR_PDM_WD_INT);
        wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
@@ -3109,20 +3139,26 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
        ret = request_threaded_irq(wcd938x->hphr_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
                                   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                   "HPHR PDM WD INT", wcd938x);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to request HPHR WD interrupt (%d)\n", ret);
+               goto err_free_clsh_ctrl;
+       }
 
        ret = request_threaded_irq(wcd938x->hphl_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
                                   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                   "HPHL PDM WD INT", wcd938x);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to request HPHL WD interrupt (%d)\n", ret);
+               goto err_free_hphr_pdm_wd_int;
+       }
 
        ret = request_threaded_irq(wcd938x->aux_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
                                   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                   "AUX PDM WD INT", wcd938x);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to request Aux WD interrupt (%d)\n", ret);
+               goto err_free_hphl_pdm_wd_int;
+       }
 
        /* Disable watchdog interrupt for HPH and AUX */
        disable_irq_nosync(wcd938x->hphr_pdm_wd_int);
@@ -3137,7 +3173,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
                        dev_err(component->dev,
                                "%s: Failed to add snd ctrls for variant: %d\n",
                                __func__, wcd938x->variant);
-                       goto err;
+                       goto err_free_aux_pdm_wd_int;
                }
                break;
        case WCD9385:
@@ -3147,7 +3183,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
                        dev_err(component->dev,
                                "%s: Failed to add snd ctrls for variant: %d\n",
                                __func__, wcd938x->variant);
-                       goto err;
+                       goto err_free_aux_pdm_wd_int;
                }
                break;
        default:
@@ -3155,12 +3191,38 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
        }
 
        ret = wcd938x_mbhc_init(component);
-       if (ret)
+       if (ret) {
                dev_err(component->dev,  "mbhc initialization failed\n");
-err:
+               goto err_free_aux_pdm_wd_int;
+       }
+
+       return 0;
+
+err_free_aux_pdm_wd_int:
+       free_irq(wcd938x->aux_pdm_wd_int, wcd938x);
+err_free_hphl_pdm_wd_int:
+       free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);
+err_free_hphr_pdm_wd_int:
+       free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);
+err_free_clsh_ctrl:
+       wcd_clsh_ctrl_free(wcd938x->clsh_info);
+
        return ret;
 }
 
+static void wcd938x_soc_codec_remove(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       wcd938x_mbhc_deinit(component);
+
+       free_irq(wcd938x->aux_pdm_wd_int, wcd938x);
+       free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);
+       free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);
+
+       wcd_clsh_ctrl_free(wcd938x->clsh_info);
+}
+
 static int wcd938x_codec_set_jack(struct snd_soc_component *comp,
                                  struct snd_soc_jack *jack, void *data)
 {
@@ -3177,6 +3239,7 @@ static int wcd938x_codec_set_jack(struct snd_soc_component *comp,
 static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
        .name = "wcd938x_codec",
        .probe = wcd938x_soc_codec_probe,
+       .remove = wcd938x_soc_codec_remove,
        .controls = wcd938x_snd_controls,
        .num_controls = ARRAY_SIZE(wcd938x_snd_controls),
        .dapm_widgets = wcd938x_dapm_widgets,
index 068e610..f2baee7 100644 (file)
@@ -2308,6 +2308,9 @@ static int wm8904_i2c_probe(struct i2c_client *i2c)
        regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0,
                            WM8904_POBCTRL, 0);
 
+       /* Fill the cache for the ADC test register */
+       regmap_read(wm8904->regmap, WM8904_ADC_TEST_0, &val);
+
        /* Can leave the device powered off until we need it */
        regcache_cache_only(wm8904->regmap, true);
        regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
index 5e09f63..f7676d3 100644 (file)
@@ -507,12 +507,6 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
                                   savediv / 2 - 1);
        }
 
-       if (sai->soc_data->max_register >= FSL_SAI_MCTL) {
-               /* SAI is in master mode at this point, so enable MCLK */
-               regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
-                                  FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
-       }
-
        return 0;
 }
 
@@ -719,7 +713,7 @@ static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
        u32 xcsr, count = 100;
 
        regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
-                          FSL_SAI_CSR_TERE, 0);
+                          FSL_SAI_CSR_TERE | FSL_SAI_CSR_BCE, 0);
 
        /* TERE will remain set till the end of current frame */
        do {
index 8254c35..550df87 100644 (file)
@@ -91,6 +91,7 @@
 /* SAI Transmit/Receive Control Register */
 #define FSL_SAI_CSR_TERE       BIT(31)
 #define FSL_SAI_CSR_SE         BIT(30)
+#define FSL_SAI_CSR_BCE                BIT(28)
 #define FSL_SAI_CSR_FR         BIT(25)
 #define FSL_SAI_CSR_SR         BIT(24)
 #define FSL_SAI_CSR_xF_SHIFT   16
index 015c370..3fd26f2 100644 (file)
@@ -751,6 +751,8 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0);
                regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0);
+               regmap_write(regmap, REG_SPDIF_STL, 0x0);
+               regmap_write(regmap, REG_SPDIF_STR, 0x0);
                break;
        default:
                return -EINVAL;
index 31e0bad..dbff55a 100644 (file)
@@ -476,7 +476,7 @@ static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,
 
 static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
        {"HDMI Playback", NULL, "HDMI_RX"},
-       {"Display Port Playback", NULL, "DISPLAY_PORT_RX"},
+       {"DISPLAY_PORT_RX_0 Playback", NULL, "DISPLAY_PORT_RX"},
        {"Slimbus Playback", NULL, "SLIMBUS_0_RX"},
        {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"},
        {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"},
index 5eb0b86..c90db6d 100644 (file)
@@ -840,6 +840,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
        .pointer        = q6apm_dai_pointer,
        .trigger        = q6apm_dai_trigger,
        .compress_ops   = &q6apm_dai_compress_ops,
+       .use_dai_pcm_id = true,
 };
 
 static int q6apm_dai_probe(struct platform_device *pdev)
index 7bfac94..5d44d07 100644 (file)
@@ -511,6 +511,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
 
        switch (hdr->opcode) {
        case DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2:
+               if (!graph->ar_graph)
+                       break;
                client_event = APM_CLIENT_EVENT_DATA_WRITE_DONE;
                mutex_lock(&graph->lock);
                token = hdr->token & APM_WRITE_TOKEN_MASK;
@@ -544,6 +546,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
                wake_up(&graph->cmd_wait);
                break;
        case DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2:
+               if (!graph->ar_graph)
+                       break;
                client_event = APM_CLIENT_EVENT_DATA_READ_DONE;
                mutex_lock(&graph->lock);
                rd_done = data->payload;
@@ -649,8 +653,9 @@ int q6apm_graph_close(struct q6apm_graph *graph)
 {
        struct audioreach_graph *ar_graph = graph->ar_graph;
 
-       gpr_free_port(graph->port);
+       graph->ar_graph = NULL;
        kref_put(&ar_graph->refcount, q6apm_put_audioreach_graph);
+       gpr_free_port(graph->port);
        kfree(graph);
 
        return 0;
index cccc59b..130b22a 100644 (file)
@@ -1277,8 +1277,8 @@ int audioreach_tplg_init(struct snd_soc_component *component)
 
        ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw);
        if (ret < 0) {
-               dev_err(dev, "tplg component load failed%d\n", ret);
-               ret = -EINVAL;
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "tplg component load failed: %d\n", ret);
        }
 
        release_firmware(fw);
index 11bc525..1a0bde2 100644 (file)
@@ -1988,8 +1988,10 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
        /* probe all components used by DAI links on this card */
        ret = soc_probe_link_components(card);
        if (ret < 0) {
-               dev_err(card->dev,
-                       "ASoC: failed to instantiate card %d\n", ret);
+               if (ret != -EPROBE_DEFER) {
+                       dev_err(card->dev,
+                               "ASoC: failed to instantiate card %d\n", ret);
+               }
                goto probe_end;
        }
 
index 8add361..ad08d4f 100644 (file)
@@ -1732,7 +1732,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
 
        ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1);
        if (ret < 0) {
-               dev_err(tplg->dev, "ASoC: adding FE link failed\n");
+               if (ret != -EPROBE_DEFER)
+                       dev_err(tplg->dev, "ASoC: adding FE link failed\n");
                goto err;
        }
 
@@ -2492,8 +2493,11 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg)
                        /* load the header object */
                        ret = soc_tplg_load_header(tplg, hdr);
                        if (ret < 0) {
-                               dev_err(tplg->dev,
-                                       "ASoC: topology: could not load header: %d\n", ret);
+                               if (ret != -EPROBE_DEFER) {
+                                       dev_err(tplg->dev,
+                                               "ASoC: topology: could not load header: %d\n",
+                                               ret);
+                               }
                                return ret;
                        }
 
index 2ae76bc..afb5054 100644 (file)
@@ -217,6 +217,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
                              unsigned int image_length)
 {
        struct snd_sof_dev *sdev = adata->dev;
+       const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
        unsigned int tx_count, fw_qualifier, val;
        int ret;
 
@@ -251,9 +252,12 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
                return ret;
        }
 
-       ret = psp_send_cmd(adata, MBOX_ACP_SHA_DMA_COMMAND);
-       if (ret)
-               return ret;
+       /* psp_send_cmd only required for renoir platform (rev - 3) */
+       if (desc->rev == 3) {
+               ret = psp_send_cmd(adata, MBOX_ACP_SHA_DMA_COMMAND);
+               if (ret)
+                       return ret;
+       }
 
        ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER,
                                            fw_qualifier, fw_qualifier & DSP_FW_RUN_ENABLE,
index 1d3bca2..35da85a 100644 (file)
@@ -186,7 +186,6 @@ static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user
        struct snd_sof_dfsentry *dfse = file->private_data;
        struct sof_ipc_trace_filter_elem *elems = NULL;
        struct snd_sof_dev *sdev = dfse->sdev;
-       loff_t pos = 0;
        int num_elems;
        char *string;
        int ret;
@@ -201,11 +200,11 @@ static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user
        if (!string)
                return -ENOMEM;
 
-       /* assert null termination */
-       string[count] = 0;
-       ret = simple_write_to_buffer(string, count, &pos, from, count);
-       if (ret < 0)
+       if (copy_from_user(string, from, count)) {
+               ret = -EFAULT;
                goto error;
+       }
+       string[count] = '\0';
 
        ret = trace_filter_parse(sdev, string, &num_elems, &elems);
        if (ret < 0)
index bd0b10c..7d003f0 100644 (file)
@@ -2,7 +2,7 @@
 //
 // tegra210_adx.c - Tegra210 ADX driver
 //
-// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+// Copyright (c) 2021-2023 NVIDIA CORPORATION.  All rights reserved.
 
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -175,10 +175,20 @@ static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
        mc = (struct soc_mixer_control *)kcontrol->private_value;
        enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
 
+       /*
+        * TODO: Simplify this logic to just return from bytes_map[]
+        *
+        * Presently below is required since bytes_map[] is
+        * tightly packed and cannot store the control value of 256.
+        * Byte mask state is used to know if 256 needs to be returned.
+        * Note that for control value of 256, the put() call stores 0
+        * in the bytes_map[] and disables the corresponding bit in
+        * byte_mask[].
+        */
        if (enabled)
                ucontrol->value.integer.value[0] = bytes_map[mc->reg];
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.integer.value[0] = 256;
 
        return 0;
 }
@@ -192,19 +202,19 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
        int value = ucontrol->value.integer.value[0];
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int mask_val = adx->byte_mask[mc->reg / 32];
 
-       if (value == bytes_map[mc->reg])
+       if (value >= 0 && value <= 255)
+               mask_val |= (1 << (mc->reg % 32));
+       else
+               mask_val &= ~(1 << (mc->reg % 32));
+
+       if (mask_val == adx->byte_mask[mc->reg / 32])
                return 0;
 
-       if (value >= 0 && value <= 255) {
-               /* update byte map and enable slot */
-               bytes_map[mc->reg] = value;
-               adx->byte_mask[mc->reg / 32] |= (1 << (mc->reg % 32));
-       } else {
-               /* reset byte map and disable slot */
-               bytes_map[mc->reg] = 0;
-               adx->byte_mask[mc->reg / 32] &= ~(1 << (mc->reg % 32));
-       }
+       /* Update byte map and slot */
+       bytes_map[mc->reg] = value % 256;
+       adx->byte_mask[mc->reg / 32] = mask_val;
 
        return 1;
 }
index 782a141..1798769 100644 (file)
@@ -2,7 +2,7 @@
 //
 // tegra210_amx.c - Tegra210 AMX driver
 //
-// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+// Copyright (c) 2021-2023 NVIDIA CORPORATION.  All rights reserved.
 
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -203,10 +203,20 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
        else
                enabled = amx->byte_mask[0] & (1 << reg);
 
+       /*
+        * TODO: Simplify this logic to just return from bytes_map[]
+        *
+        * Presently below is required since bytes_map[] is
+        * tightly packed and cannot store the control value of 256.
+        * Byte mask state is used to know if 256 needs to be returned.
+        * Note that for control value of 256, the put() call stores 0
+        * in the bytes_map[] and disables the corresponding bit in
+        * byte_mask[].
+        */
        if (enabled)
                ucontrol->value.integer.value[0] = bytes_map[reg];
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.integer.value[0] = 256;
 
        return 0;
 }
@@ -221,25 +231,19 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
        unsigned char *bytes_map = (unsigned char *)&amx->map;
        int reg = mc->reg;
        int value = ucontrol->value.integer.value[0];
+       unsigned int mask_val = amx->byte_mask[reg / 32];
 
-       if (value == bytes_map[reg])
+       if (value >= 0 && value <= 255)
+               mask_val |= (1 << (reg % 32));
+       else
+               mask_val &= ~(1 << (reg % 32));
+
+       if (mask_val == amx->byte_mask[reg / 32])
                return 0;
 
-       if (value >= 0 && value <= 255) {
-               /* Update byte map and enable slot */
-               bytes_map[reg] = value;
-               if (reg > 31)
-                       amx->byte_mask[1] |= (1 << (reg - 32));
-               else
-                       amx->byte_mask[0] |= (1 << reg);
-       } else {
-               /* Reset byte map and disable slot */
-               bytes_map[reg] = 0;
-               if (reg > 31)
-                       amx->byte_mask[1] &= ~(1 << (reg - 32));
-               else
-                       amx->byte_mask[0] &= ~(1 << reg);
-       }
+       /* Update byte map and slot */
+       bytes_map[reg] = value % 256;
+       amx->byte_mask[reg / 32] = mask_val;
 
        return 1;
 }
index f4bd1e8..23260aa 100644 (file)
@@ -374,6 +374,15 @@ static const struct usbmix_name_map corsair_virtuoso_map[] = {
        { 0 }
 };
 
+/* Microsoft USB Link headset */
+/* a guess work: raw playback volume values are from 2 to 129 */
+static const struct usbmix_dB_map ms_usb_link_dB = { -3225, 0, true };
+static const struct usbmix_name_map ms_usb_link_map[] = {
+       { 9, NULL, .dB = &ms_usb_link_dB },
+       { 10, NULL }, /* Headset Capture volume; seems non-working, disabled */
+       { 0 }   /* terminator */
+};
+
 /* ASUS ROG Zenith II with Realtek ALC1220-VB */
 static const struct usbmix_name_map asus_zenith_ii_map[] = {
        { 19, NULL, 12 }, /* FU, Input Gain Pad - broken response, disabled */
@@ -668,6 +677,11 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x1395, 0x0025),
                .map = sennheiser_pc8_map,
        },
+       {
+               /* Microsoft USB Link headset */
+               .id = USB_ID(0x045e, 0x083c),
+               .map = ms_usb_link_map,
+       },
        { 0 } /* terminator */
 };
 
index 30bcb80..598659d 100644 (file)
@@ -1876,8 +1876,10 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 
        /* XMOS based USB DACs */
        switch (chip->usb_id) {
-       case USB_ID(0x1511, 0x0037): /* AURALiC VEGA */
-       case USB_ID(0x21ed, 0xd75a): /* Accuphase DAC-60 option card */
+       case USB_ID(0x139f, 0x5504): /* Nagra DAC */
+       case USB_ID(0x20b1, 0x3089): /* Mola-Mola DAC */
+       case USB_ID(0x2522, 0x0007): /* LH Labs Geek Out 1V5 */
+       case USB_ID(0x2522, 0x0009): /* LH Labs Geek Pulse X Inifinity 2V0 */
        case USB_ID(0x2522, 0x0012): /* LH Labs VI DAC Infinity */
        case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */
                if (fp->altsetting == 2)
@@ -1887,14 +1889,18 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
        case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
        case USB_ID(0x16d0, 0x06b2): /* NuPrime DAC-10 */
-       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
+       case USB_ID(0x16d0, 0x06b4): /* NuPrime Audio HD-AVP/AVA */
        case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */
+       case USB_ID(0x16d0, 0x09d8): /* NuPrime IDA-8 */
        case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */
+       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x1db5, 0x0003): /* Bryston BDA3 */
+       case USB_ID(0x20a0, 0x4143): /* WaveIO USB Audio 2.0 */
        case USB_ID(0x22e1, 0xca01): /* HDTA Serenade DSD */
        case USB_ID(0x249c, 0x9326): /* M2Tech Young MkIII */
        case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
        case USB_ID(0x2622, 0x0041): /* Audiolab M-DAC+ */
+       case USB_ID(0x278b, 0x5100): /* Rotel RC-1590 */
        case USB_ID(0x27f7, 0x3002): /* W4S DAC-2v2SE */
        case USB_ID(0x29a2, 0x0086): /* Mutec MC3+ USB */
        case USB_ID(0x6b42, 0x0042): /* MSB Technology */
@@ -1904,9 +1910,6 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 
        /* Amanero Combo384 USB based DACs with native DSD support */
        case USB_ID(0x16d0, 0x071a):  /* Amanero - Combo384 */
-       case USB_ID(0x2ab6, 0x0004):  /* T+A DAC8DSD-V2.0, MP1000E-V2.0, MP2000R-V2.0, MP2500R-V2.0, MP3100HV-V2.0 */
-       case USB_ID(0x2ab6, 0x0005):  /* T+A USB HD Audio 1 */
-       case USB_ID(0x2ab6, 0x0006):  /* T+A USB HD Audio 2 */
                if (fp->altsetting == 2) {
                        switch (le16_to_cpu(chip->dev->descriptor.bcdDevice)) {
                        case 0x199:
@@ -2013,6 +2016,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x045e, 0x083c, /* MS USB Link headset */
+                  QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
        DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
                   QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
        DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
@@ -2048,6 +2054,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_IFACE_DELAY),
        DEVICE_FLG(0x0644, 0x805f, /* TEAC Model 12 */
                   QUIRK_FLAG_FORCE_IFACE_RESET),
+       DEVICE_FLG(0x0644, 0x806b, /* TEAC UD-701 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
        DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
@@ -2086,6 +2095,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
        DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */
                   QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x300b, /* Marantz SA-KI RUBY / SA-12 */
+                  QUIRK_FLAG_DSD_RAW),
        DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */
                   QUIRK_FLAG_IGNORE_CLOCK_SOURCE),
        DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */
@@ -2130,6 +2141,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x21b4, 0x0230, /* Ayre QB-9 Twenty */
+                  QUIRK_FLAG_DSD_RAW),
+       DEVICE_FLG(0x21b4, 0x0232, /* Ayre QX-5 Twenty */
+                  QUIRK_FLAG_DSD_RAW),
        DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
                   QUIRK_FLAG_SET_IFACE_FIRST),
        DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
@@ -2172,12 +2187,18 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_VALIDATE_RATES),
        VENDOR_FLG(0x1235, /* Focusrite Novation */
                   QUIRK_FLAG_VALIDATE_RATES),
+       VENDOR_FLG(0x1511, /* AURALiC */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x152a, /* Thesycon devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x18d1, /* iBasso devices */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x1de7, /* Phoenix Audio */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
        VENDOR_FLG(0x20b1, /* XMOS based devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x21ed, /* Accuphase Laboratory */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x22d9, /* Oppo */
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x23ba, /* Playback Design */
@@ -2193,10 +2214,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x2ab6, /* T+A devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x2d87, /* Cayin device */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x3336, /* HEM devices */
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x3353, /* Khadas devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x35f4, /* MSB Technology */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x3842, /* EVGA */
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0xc502, /* HiBy devices */
index 683ca3a..5f6f848 100644 (file)
 #define APPLE_CPU_PART_M1_FIRESTORM_MAX        0x029
 #define APPLE_CPU_PART_M2_BLIZZARD     0x032
 #define APPLE_CPU_PART_M2_AVALANCHE    0x033
+#define APPLE_CPU_PART_M2_BLIZZARD_PRO 0x034
+#define APPLE_CPU_PART_M2_AVALANCHE_PRO        0x035
+#define APPLE_CPU_PART_M2_BLIZZARD_MAX 0x038
+#define APPLE_CPU_PART_M2_AVALANCHE_MAX        0x039
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
 #define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
 #define MIDR_APPLE_M2_BLIZZARD MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD)
 #define MIDR_APPLE_M2_AVALANCHE MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE)
+#define MIDR_APPLE_M2_BLIZZARD_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO)
+#define MIDR_APPLE_M2_AVALANCHE_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO)
+#define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX)
+#define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX)
 #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
index 0f0aa9b..2cd6dbb 100644 (file)
@@ -208,7 +208,7 @@ $(OUTPUT)test-libtraceevent.bin:
        $(BUILD) -ltraceevent
 
 $(OUTPUT)test-libtracefs.bin:
-       $(BUILD) -ltracefs
+        $(BUILD) $(shell $(PKG_CONFIG) --cflags libtraceevent 2>/dev/null) -ltracefs
 
 $(OUTPUT)test-libcrypto.bin:
        $(BUILD) -lcrypto
index dd7d8e1..fd6c1cb 100644 (file)
@@ -817,8 +817,11 @@ __SYSCALL(__NR_futex_waitv, sys_futex_waitv)
 #define __NR_set_mempolicy_home_node 450
 __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
 
+#define __NR_cachestat 451
+__SYSCALL(__NR_cachestat, sys_cachestat)
+
 #undef __NR_syscalls
-#define __NR_syscalls 451
+#define __NR_syscalls 452
 
 /*
  * 32 bit systems traditionally used different
index dba7c5a..7000e59 100644 (file)
@@ -280,7 +280,16 @@ enum drm_i915_pmu_engine_sample {
 #define I915_PMU_ENGINE_SEMA(class, instance) \
        __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
 
-#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))
+/*
+ * Top 4 bits of every non-engine counter are GT id.
+ */
+#define __I915_PMU_GT_SHIFT (60)
+
+#define ___I915_PMU_OTHER(gt, x) \
+       (((__u64)__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x)) | \
+       ((__u64)(gt) << __I915_PMU_GT_SHIFT))
+
+#define __I915_PMU_OTHER(x) ___I915_PMU_OTHER(0, x)
 
 #define I915_PMU_ACTUAL_FREQUENCY      __I915_PMU_OTHER(0)
 #define I915_PMU_REQUESTED_FREQUENCY   __I915_PMU_OTHER(1)
@@ -290,6 +299,12 @@ enum drm_i915_pmu_engine_sample {
 
 #define I915_PMU_LAST /* Deprecated - do not use */ I915_PMU_RC6_RESIDENCY
 
+#define __I915_PMU_ACTUAL_FREQUENCY(gt)                ___I915_PMU_OTHER(gt, 0)
+#define __I915_PMU_REQUESTED_FREQUENCY(gt)     ___I915_PMU_OTHER(gt, 1)
+#define __I915_PMU_INTERRUPTS(gt)              ___I915_PMU_OTHER(gt, 2)
+#define __I915_PMU_RC6_RESIDENCY(gt)           ___I915_PMU_OTHER(gt, 3)
+#define __I915_PMU_SOFTWARE_GT_AWAKE_TIME(gt)  ___I915_PMU_OTHER(gt, 4)
+
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
 #define I915_NR_TEX_REGIONS 255        /* table size 2k - maximum due to use
@@ -659,7 +674,8 @@ typedef struct drm_i915_irq_wait {
  * If the IOCTL is successful, the returned parameter will be set to one of the
  * following values:
  *  * 0 if HuC firmware load is not complete,
- *  * 1 if HuC firmware is authenticated and running.
+ *  * 1 if HuC firmware is loaded and fully authenticated,
+ *  * 2 if HuC firmware is loaded and authenticated for clear media only
  */
 #define I915_PARAM_HUC_STATUS           42
 
@@ -771,6 +787,25 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_OA_TIMESTAMP_FREQUENCY 57
 
+/*
+ * Query the status of PXP support in i915.
+ *
+ * The query can fail in the following scenarios with the listed error codes:
+ *     -ENODEV = PXP support is not available on the GPU device or in the
+ *               kernel due to missing component drivers or kernel configs.
+ *
+ * If the IOCTL is successful, the returned parameter will be set to one of
+ * the following values:
+ *     1 = PXP feature is supported and is ready for use.
+ *     2 = PXP feature is supported but should be ready soon (pending
+ *         initialization of non-i915 system dependencies).
+ *
+ * NOTE: When param is supported (positive return values), user space should
+ *       still refer to the GEM PXP context-creation UAPI header specs to be
+ *       aware of possible failure due to system state machine at the time.
+ */
+#define I915_PARAM_PXP_STATUS           58
+
 /* Must be kept compact -- no holes and well documented */
 
 /**
@@ -2096,6 +2131,21 @@ struct drm_i915_gem_context_param {
  *
  * -ENODEV: feature not available
  * -EPERM: trying to mark a recoverable or not bannable context as protected
+ * -ENXIO: A dependency such as a component driver or firmware is not yet
+ *         loaded so user space may need to attempt again. Depending on the
+ *         device, this error may be reported if protected context creation is
+ *         attempted very early after kernel start because the internal timeout
+ *         waiting for such dependencies is not guaranteed to be larger than
+ *         required (numbers differ depending on system and kernel config):
+ *            - ADL/RPL: dependencies may take up to 3 seconds from kernel start
+ *                       while context creation internal timeout is 250 milisecs
+ *            - MTL: dependencies may take up to 8 seconds from kernel start
+ *                   while context creation internal timeout is 250 milisecs
+ *         NOTE: such dependencies happen once, so a subsequent call to create a
+ *         protected context after a prior successful call will not experience
+ *         such timeouts and will not return -ENXIO (unless the driver is reloaded,
+ *         or, depending on the device, resumes from a suspended state).
+ * -EIO: The firmware did not succeed in creating the protected context.
  */
 #define I915_CONTEXT_PARAM_PROTECTED_CONTENT    0xd
 /* Must be kept compact -- no holes and well documented */
@@ -3630,9 +3680,13 @@ struct drm_i915_gem_create_ext {
         *
         * For I915_GEM_CREATE_EXT_PROTECTED_CONTENT usage see
         * struct drm_i915_gem_create_ext_protected_content.
+        *
+        * For I915_GEM_CREATE_EXT_SET_PAT usage see
+        * struct drm_i915_gem_create_ext_set_pat.
         */
 #define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0
 #define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1
+#define I915_GEM_CREATE_EXT_SET_PAT 2
        __u64 extensions;
 };
 
@@ -3747,6 +3801,43 @@ struct drm_i915_gem_create_ext_protected_content {
        __u32 flags;
 };
 
+/**
+ * struct drm_i915_gem_create_ext_set_pat - The
+ * I915_GEM_CREATE_EXT_SET_PAT extension.
+ *
+ * If this extension is provided, the specified caching policy (PAT index) is
+ * applied to the buffer object.
+ *
+ * Below is an example on how to create an object with specific caching policy:
+ *
+ * .. code-block:: C
+ *
+ *      struct drm_i915_gem_create_ext_set_pat set_pat_ext = {
+ *              .base = { .name = I915_GEM_CREATE_EXT_SET_PAT },
+ *              .pat_index = 0,
+ *      };
+ *      struct drm_i915_gem_create_ext create_ext = {
+ *              .size = PAGE_SIZE,
+ *              .extensions = (uintptr_t)&set_pat_ext,
+ *      };
+ *
+ *      int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
+ *      if (err) ...
+ */
+struct drm_i915_gem_create_ext_set_pat {
+       /** @base: Extension link. See struct i915_user_extension. */
+       struct i915_user_extension base;
+       /**
+        * @pat_index: PAT index to be set
+        * PAT index is a bit field in Page Table Entry to control caching
+        * behaviors for GPU accesses. The definition of PAT index is
+        * platform dependent and can be found in hardware specifications,
+        */
+       __u32 pat_index;
+       /** @rsvd: reserved for future use */
+       __u32 rsvd;
+};
+
 /* ID of the protected content session managed by i915 when PXP is active */
 #define I915_PROTECTED_CONTENT_DEFAULT_SESSION 0xf
 
index e8c07da..6c80f96 100644 (file)
 
 #define AT_RECURSIVE           0x8000  /* Apply to the entire subtree */
 
+/* Flags for name_to_handle_at(2). We reuse AT_ flag space to save bits... */
+#define AT_HANDLE_FID          AT_REMOVEDIR    /* file handle is needed to
+                                       compare object identity and may not
+                                       be usable to open_by_handle_at(2) */
+
 #endif /* _UAPI_LINUX_FCNTL_H */
index 737318b..f089ab2 100644 (file)
@@ -1190,6 +1190,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP 225
 #define KVM_CAP_PMU_EVENT_MASKED_EVENTS 226
 #define KVM_CAP_COUNTER_OFFSET 227
+#define KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE 228
+#define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1442,6 +1444,8 @@ enum kvm_device_type {
 #define KVM_DEV_TYPE_XIVE              KVM_DEV_TYPE_XIVE
        KVM_DEV_TYPE_ARM_PV_TIME,
 #define KVM_DEV_TYPE_ARM_PV_TIME       KVM_DEV_TYPE_ARM_PV_TIME
+       KVM_DEV_TYPE_RISCV_AIA,
+#define KVM_DEV_TYPE_RISCV_AIA         KVM_DEV_TYPE_RISCV_AIA
        KVM_DEV_TYPE_MAX,
 };
 
@@ -1613,7 +1617,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_GET_DEBUGREGS         _IOR(KVMIO,  0xa1, struct kvm_debugregs)
 #define KVM_SET_DEBUGREGS         _IOW(KVMIO,  0xa2, struct kvm_debugregs)
 /*
- * vcpu version available with KVM_ENABLE_CAP
+ * vcpu version available with KVM_CAP_ENABLE_CAP
  * vm version available with KVM_CAP_ENABLE_CAP_VM
  */
 #define KVM_ENABLE_CAP            _IOW(KVMIO,  0xa3, struct kvm_enable_cap)
index f55bc68..a246e11 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <asm/mman.h>
 #include <asm-generic/hugetlb_encode.h>
+#include <linux/types.h>
 
 #define MREMAP_MAYMOVE         1
 #define MREMAP_FIXED           2
 #define MAP_HUGE_2GB   HUGETLB_FLAG_ENCODE_2GB
 #define MAP_HUGE_16GB  HUGETLB_FLAG_ENCODE_16GB
 
+struct cachestat_range {
+       __u64 off;
+       __u64 len;
+};
+
+struct cachestat {
+       __u64 nr_cache;
+       __u64 nr_dirty;
+       __u64 nr_writeback;
+       __u64 nr_evicted;
+       __u64 nr_recently_evicted;
+};
+
 #endif /* _UAPI_LINUX_MMAN_H */
index 4d93967..8eb0d7b 100644 (file)
@@ -74,7 +74,8 @@
 #define MOVE_MOUNT_T_AUTOMOUNTS                0x00000020 /* Follow automounts on to path */
 #define MOVE_MOUNT_T_EMPTY_PATH                0x00000040 /* Empty to path permitted */
 #define MOVE_MOUNT_SET_GROUP           0x00000100 /* Set sharing group instead */
-#define MOVE_MOUNT__MASK               0x00000177
+#define MOVE_MOUNT_BENEATH             0x00000200 /* Mount beneath top mount */
+#define MOVE_MOUNT__MASK               0x00000377
 
 /*
  * fsopen() flags.
index f23d9a1..3c36aea 100644 (file)
@@ -294,4 +294,15 @@ struct prctl_mm_map {
 
 #define PR_SET_MEMORY_MERGE            67
 #define PR_GET_MEMORY_MERGE            68
+
+#define PR_RISCV_V_SET_CONTROL         69
+#define PR_RISCV_V_GET_CONTROL         70
+# define PR_RISCV_V_VSTATE_CTRL_DEFAULT                0
+# define PR_RISCV_V_VSTATE_CTRL_OFF            1
+# define PR_RISCV_V_VSTATE_CTRL_ON             2
+# define PR_RISCV_V_VSTATE_CTRL_INHERIT                (1 << 4)
+# define PR_RISCV_V_VSTATE_CTRL_CUR_MASK       0x3
+# define PR_RISCV_V_VSTATE_CTRL_NEXT_MASK      0xc
+# define PR_RISCV_V_VSTATE_CTRL_MASK           0x1f
+
 #endif /* _LINUX_PRCTL_H */
index 92e1b70..f5c48b6 100644 (file)
 #define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
 /* Specify an eventfd file descriptor to signal on log write. */
 #define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
+/* By default, a device gets one vhost_worker that its virtqueues share. This
+ * command allows the owner of the device to create an additional vhost_worker
+ * for the device. It can later be bound to 1 or more of its virtqueues using
+ * the VHOST_ATTACH_VRING_WORKER command.
+ *
+ * This must be called after VHOST_SET_OWNER and the caller must be the owner
+ * of the device. The new thread will inherit caller's cgroups and namespaces,
+ * and will share the caller's memory space. The new thread will also be
+ * counted against the caller's RLIMIT_NPROC value.
+ *
+ * The worker's ID used in other commands will be returned in
+ * vhost_worker_state.
+ */
+#define VHOST_NEW_WORKER _IOR(VHOST_VIRTIO, 0x8, struct vhost_worker_state)
+/* Free a worker created with VHOST_NEW_WORKER if it's not attached to any
+ * virtqueue. If userspace is not able to call this for workers its created,
+ * the kernel will free all the device's workers when the device is closed.
+ */
+#define VHOST_FREE_WORKER _IOW(VHOST_VIRTIO, 0x9, struct vhost_worker_state)
 
 /* Ring setup. */
 /* Set number of descriptors in ring. This parameter can not
 #define VHOST_VRING_BIG_ENDIAN 1
 #define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state)
 #define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
+/* Attach a vhost_worker created with VHOST_NEW_WORKER to one of the device's
+ * virtqueues.
+ *
+ * This will replace the virtqueue's existing worker. If the replaced worker
+ * is no longer attached to any virtqueues, it can be freed with
+ * VHOST_FREE_WORKER.
+ */
+#define VHOST_ATTACH_VRING_WORKER _IOW(VHOST_VIRTIO, 0x15,             \
+                                      struct vhost_vring_worker)
+/* Return the vring worker's ID */
+#define VHOST_GET_VRING_WORKER _IOWR(VHOST_VIRTIO, 0x16,               \
+                                    struct vhost_vring_worker)
 
 /* The following ioctls use eventfd file descriptors to signal and poll
  * for events. */
index 0aa955a..f9939da 100644 (file)
@@ -274,6 +274,7 @@ typedef int __bitwise snd_pcm_subformat_t;
 #define SNDRV_PCM_INFO_DOUBLE          0x00000004      /* Double buffering needed for PCM start/stop */
 #define SNDRV_PCM_INFO_BATCH           0x00000010      /* double buffering */
 #define SNDRV_PCM_INFO_SYNC_APPLPTR    0x00000020      /* need the explicit sync of appl_ptr update */
+#define SNDRV_PCM_INFO_PERFECT_DRAIN   0x00000040      /* silencing at the end of stream is not required */
 #define SNDRV_PCM_INFO_INTERLEAVED     0x00000100      /* channels are interleaved */
 #define SNDRV_PCM_INFO_NONINTERLEAVED  0x00000200      /* channels are not interleaved */
 #define SNDRV_PCM_INFO_COMPLEX         0x00000400      /* complex frame organization (mmap only) */
@@ -383,6 +384,9 @@ typedef int snd_pcm_hw_param_t;
 #define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
 #define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER      (1<<1)  /* export buffer */
 #define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP   (1<<2)  /* disable period wakeups */
+#define SNDRV_PCM_HW_PARAMS_NO_DRAIN_SILENCE   (1<<3)  /* suppress drain with the filling
+                                                        * of the silence samples
+                                                        */
 
 struct snd_interval {
        unsigned int min, max;
@@ -708,7 +712,7 @@ enum {
  *  Raw MIDI section - /dev/snd/midi??
  */
 
-#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 2)
+#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 4)
 
 enum {
        SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
@@ -719,6 +723,7 @@ enum {
 #define SNDRV_RAWMIDI_INFO_OUTPUT              0x00000001
 #define SNDRV_RAWMIDI_INFO_INPUT               0x00000002
 #define SNDRV_RAWMIDI_INFO_DUPLEX              0x00000004
+#define SNDRV_RAWMIDI_INFO_UMP                 0x00000008
 
 struct snd_rawmidi_info {
        unsigned int device;            /* RO/WR (control): device number */
@@ -779,6 +784,72 @@ struct snd_rawmidi_status {
 };
 #endif
 
+/* UMP EP info flags */
+#define SNDRV_UMP_EP_INFO_STATIC_BLOCKS                0x01
+
+/* UMP EP Protocol / JRTS capability bits */
+#define SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK      0x0300
+#define SNDRV_UMP_EP_INFO_PROTO_MIDI1          0x0100 /* MIDI 1.0 */
+#define SNDRV_UMP_EP_INFO_PROTO_MIDI2          0x0200 /* MIDI 2.0 */
+#define SNDRV_UMP_EP_INFO_PROTO_JRTS_MASK      0x0003
+#define SNDRV_UMP_EP_INFO_PROTO_JRTS_TX                0x0001 /* JRTS Transmit */
+#define SNDRV_UMP_EP_INFO_PROTO_JRTS_RX                0x0002 /* JRTS Receive */
+
+/* UMP Endpoint information */
+struct snd_ump_endpoint_info {
+       int card;                       /* card number */
+       int device;                     /* device number */
+       unsigned int flags;             /* additional info */
+       unsigned int protocol_caps;     /* protocol capabilities */
+       unsigned int protocol;          /* current protocol */
+       unsigned int num_blocks;        /* # of function blocks */
+       unsigned short version;         /* UMP major/minor version */
+       unsigned short family_id;       /* MIDI device family ID */
+       unsigned short model_id;        /* MIDI family model ID */
+       unsigned int manufacturer_id;   /* MIDI manufacturer ID */
+       unsigned char sw_revision[4];   /* software revision */
+       unsigned short padding;
+       unsigned char name[128];        /* endpoint name string */
+       unsigned char product_id[128];  /* unique product id string */
+       unsigned char reserved[32];
+} __packed;
+
+/* UMP direction */
+#define SNDRV_UMP_DIR_INPUT            0x01
+#define SNDRV_UMP_DIR_OUTPUT           0x02
+#define SNDRV_UMP_DIR_BIDIRECTION      0x03
+
+/* UMP block info flags */
+#define SNDRV_UMP_BLOCK_IS_MIDI1       (1U << 0) /* MIDI 1.0 port w/o restrict */
+#define SNDRV_UMP_BLOCK_IS_LOWSPEED    (1U << 1) /* 31.25Kbps B/W MIDI1 port */
+
+/* UMP block user-interface hint */
+#define SNDRV_UMP_BLOCK_UI_HINT_UNKNOWN                0x00
+#define SNDRV_UMP_BLOCK_UI_HINT_RECEIVER       0x01
+#define SNDRV_UMP_BLOCK_UI_HINT_SENDER         0x02
+#define SNDRV_UMP_BLOCK_UI_HINT_BOTH           0x03
+
+/* UMP groups and blocks */
+#define SNDRV_UMP_MAX_GROUPS           16
+#define SNDRV_UMP_MAX_BLOCKS           32
+
+/* UMP Block information */
+struct snd_ump_block_info {
+       int card;                       /* card number */
+       int device;                     /* device number */
+       unsigned char block_id;         /* block ID (R/W) */
+       unsigned char direction;        /* UMP direction */
+       unsigned char active;           /* Activeness */
+       unsigned char first_group;      /* first group ID */
+       unsigned char num_groups;       /* number of groups */
+       unsigned char midi_ci_version;  /* MIDI-CI support version */
+       unsigned char sysex8_streams;   /* max number of sysex8 streams */
+       unsigned char ui_hint;          /* user interface hint */
+       unsigned int flags;             /* various info flags */
+       unsigned char name[128];        /* block name string */
+       unsigned char reserved[32];
+} __packed;
+
 #define SNDRV_RAWMIDI_IOCTL_PVERSION   _IOR('W', 0x00, int)
 #define SNDRV_RAWMIDI_IOCTL_INFO       _IOR('W', 0x01, struct snd_rawmidi_info)
 #define SNDRV_RAWMIDI_IOCTL_USER_PVERSION _IOW('W', 0x02, int)
@@ -786,6 +857,9 @@ struct snd_rawmidi_status {
 #define SNDRV_RAWMIDI_IOCTL_STATUS     _IOWR('W', 0x20, struct snd_rawmidi_status)
 #define SNDRV_RAWMIDI_IOCTL_DROP       _IOW('W', 0x30, int)
 #define SNDRV_RAWMIDI_IOCTL_DRAIN      _IOW('W', 0x31, int)
+/* Additional ioctls for UMP rawmidi devices */
+#define SNDRV_UMP_IOCTL_ENDPOINT_INFO  _IOR('W', 0x40, struct snd_ump_endpoint_info)
+#define SNDRV_UMP_IOCTL_BLOCK_INFO     _IOR('W', 0x41, struct snd_ump_block_info)
 
 /*
  *  Timer section - /dev/snd/timer
@@ -961,7 +1035,7 @@ struct snd_timer_tread {
  *                                                                          *
  ****************************************************************************/
 
-#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 8)
+#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 9)
 
 struct snd_ctl_card_info {
        int card;                       /* card number */
@@ -1122,6 +1196,9 @@ struct snd_ctl_tlv {
 #define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
 #define SNDRV_CTL_IOCTL_RAWMIDI_INFO   _IOWR('U', 0x41, struct snd_rawmidi_info)
 #define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE        _IOWR('U', 0x43, int)
+#define SNDRV_CTL_IOCTL_UMP_ENDPOINT_INFO _IOWR('U', 0x44, struct snd_ump_endpoint_info)
+#define SNDRV_CTL_IOCTL_UMP_BLOCK_INFO _IOWR('U', 0x45, struct snd_ump_block_info)
 #define SNDRV_CTL_IOCTL_POWER          _IOWR('U', 0xd0, int)
 #define SNDRV_CTL_IOCTL_POWER_STATE    _IOR('U', 0xd1, int)
 
index 67a8d6b..adfbae2 100644 (file)
@@ -68,8 +68,13 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
        while (ci < cmds->cnt && ei < excludes->cnt) {
                cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name);
                if (cmp < 0) {
-                       zfree(&cmds->names[cj]);
-                       cmds->names[cj++] = cmds->names[ci++];
+                       if (ci == cj) {
+                               ci++;
+                               cj++;
+                       } else {
+                               zfree(&cmds->names[cj]);
+                               cmds->names[cj++] = cmds->names[ci++];
+                       }
                } else if (cmp == 0) {
                        ci++;
                        ei++;
@@ -77,10 +82,11 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
                        ei++;
                }
        }
-
-       while (ci < cmds->cnt) {
-               zfree(&cmds->names[cj]);
-               cmds->names[cj++] = cmds->names[ci++];
+       if (ci != cj) {
+               while (ci < cmds->cnt) {
+                       zfree(&cmds->names[cj]);
+                       cmds->names[cj++] = cmds->names[ci++];
+               }
        }
        for (ci = cj; ci < cmds->cnt; ci++)
                zfree(&cmds->names[ci]);
index 1b3a36f..3ca28d4 100644 (file)
@@ -417,11 +417,10 @@ class YnlFamily(SpecFamily):
         pad = b'\x00' * ((4 - len(attr_payload) % 4) % 4)
         return struct.pack('HH', len(attr_payload) + 4, nl_type) + attr_payload + pad
 
-    def _decode_enum(self, rsp, attr_spec):
-        raw = rsp[attr_spec['name']]
+    def _decode_enum(self, raw, attr_spec):
         enum = self.consts[attr_spec['enum']]
-        i = attr_spec.get('value-start', 0)
         if 'enum-as-flags' in attr_spec and attr_spec['enum-as-flags']:
+            i = 0
             value = set()
             while raw:
                 if raw & 1:
@@ -429,8 +428,8 @@ class YnlFamily(SpecFamily):
                 raw >>= 1
                 i += 1
         else:
-            value = enum.entries_by_val[raw - i].name
-        rsp[attr_spec['name']] = value
+            value = enum.entries_by_val[raw].name
+        return value
 
     def _decode_binary(self, attr, attr_spec):
         if attr_spec.struct_name:
@@ -438,7 +437,7 @@ class YnlFamily(SpecFamily):
             decoded = attr.as_struct(members)
             for m in members:
                 if m.enum:
-                    self._decode_enum(decoded, m)
+                    decoded[m.name] = self._decode_enum(decoded[m.name], m)
         elif attr_spec.sub_type:
             decoded = attr.as_c_array(attr_spec.sub_type)
         else:
@@ -466,6 +465,9 @@ class YnlFamily(SpecFamily):
             else:
                 raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
 
+            if 'enum' in attr_spec:
+                decoded = self._decode_enum(decoded, attr_spec)
+
             if not attr_spec.is_multi:
                 rsp[attr_spec['name']] = decoded
             elif attr_spec.name in rsp:
@@ -473,8 +475,6 @@ class YnlFamily(SpecFamily):
             else:
                 rsp[attr_spec.name] = [decoded]
 
-            if 'enum' in attr_spec:
-                self._decode_enum(rsp, attr_spec)
         return rsp
 
     def _decode_extack_path(self, attrs, attr_set, offset, target):
index 0609c19..c5db0de 100644 (file)
@@ -155,9 +155,9 @@ FEATURE_CHECK_LDFLAGS-libcrypto = -lcrypto
 ifdef CSINCLUDES
   LIBOPENCSD_CFLAGS := -I$(CSINCLUDES)
 endif
-OPENCSDLIBS := -lopencsd_c_api
+OPENCSDLIBS := -lopencsd_c_api -lopencsd
 ifeq ($(findstring -static,${LDFLAGS}),-static)
-  OPENCSDLIBS += -lopencsd -lstdc++
+  OPENCSDLIBS += -lstdc++
 endif
 ifdef CSLIBS
   LIBOPENCSD_LDFLAGS := -L$(CSLIBS)
index 3f1886a..cfda251 100644 (file)
 448    n64     process_mrelease                sys_process_mrelease
 449    n64     futex_waitv                     sys_futex_waitv
 450    common  set_mempolicy_home_node         sys_set_mempolicy_home_node
+451    n64     cachestat                       sys_cachestat
index a0be127..8c0b08b 100644 (file)
 448    common  process_mrelease                sys_process_mrelease
 449    common  futex_waitv                     sys_futex_waitv
 450    nospu   set_mempolicy_home_node         sys_set_mempolicy_home_node
+451    common  cachestat                       sys_cachestat
index b68f475..a6935af 100644 (file)
 448  common    process_mrelease        sys_process_mrelease            sys_process_mrelease
 449  common    futex_waitv             sys_futex_waitv                 sys_futex_waitv
 450  common    set_mempolicy_home_node sys_set_mempolicy_home_node     sys_set_mempolicy_home_node
+451  common    cachestat               sys_cachestat                   sys_cachestat
index c84d126..227538b 100644 (file)
 448    common  process_mrelease        sys_process_mrelease
 449    common  futex_waitv             sys_futex_waitv
 450    common  set_mempolicy_home_node sys_set_mempolicy_home_node
+451    common  cachestat               sys_cachestat
 
 #
 # Due to a historical design error, certain syscalls are numbered differently
index bf5083c..4d28177 100644 (file)
   },
   {
     "MetricName": "nps1_die_to_dram",
-    "BriefDescription": "Approximate: Combined DRAM B/bytes of all channels on a NPS1 node (die) (may need --metric-no-group)",
+    "BriefDescription": "Approximate: Combined DRAM B/bytes of all channels on a NPS1 node (die)",
     "MetricExpr": "dram_channel_data_controller_0 + dram_channel_data_controller_1 + dram_channel_data_controller_2 + dram_channel_data_controller_3 + dram_channel_data_controller_4 + dram_channel_data_controller_5 + dram_channel_data_controller_6 + dram_channel_data_controller_7",
+    "MetricConstraint": "NO_GROUP_EVENTS",
     "MetricGroup": "data_fabric",
     "PerPkg": "1",
     "ScaleUnit": "6.1e-5MiB"
index a71694a..60e1945 100644 (file)
   },
   {
     "MetricName": "nps1_die_to_dram",
-    "BriefDescription": "Approximate: Combined DRAM B/bytes of all channels on a NPS1 node (die) (may need --metric-no-group)",
+    "BriefDescription": "Approximate: Combined DRAM B/bytes of all channels on a NPS1 node (die)",
     "MetricExpr": "dram_channel_data_controller_0 + dram_channel_data_controller_1 + dram_channel_data_controller_2 + dram_channel_data_controller_3 + dram_channel_data_controller_4 + dram_channel_data_controller_5 + dram_channel_data_controller_6 + dram_channel_data_controller_7",
+    "MetricConstraint": "NO_GROUP_EVENTS",
     "MetricGroup": "data_fabric",
     "PerPkg": "1",
     "ScaleUnit": "6.1e-5MiB"
index 988cf68..3e9e178 100644 (file)
   },
   {
     "MetricName": "nps1_die_to_dram",
-    "BriefDescription": "Approximate: Combined DRAM B/bytes of all channels on a NPS1 node (die) (may need --metric-no-group)",
+    "BriefDescription": "Approximate: Combined DRAM B/bytes of all channels on a NPS1 node (die)",
     "MetricExpr": "dram_channel_data_controller_0 + dram_channel_data_controller_1 + dram_channel_data_controller_2 + dram_channel_data_controller_3 + dram_channel_data_controller_4 + dram_channel_data_controller_5 + dram_channel_data_controller_6 + dram_channel_data_controller_7",
     "MetricGroup": "data_fabric",
     "PerPkg": "1",
+    "MetricConstraint": "NO_GROUP_EVENTS",
     "ScaleUnit": "6.1e-5MiB"
   }
 ]
diff --git a/tools/perf/tests/shell/test_uprobe_from_different_cu.sh b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh
new file mode 100755 (executable)
index 0000000..00d2e0e
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/bash
+# test perf probe of function from different CU
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX)
+
+cleanup()
+{
+       trap - EXIT TERM INT
+       if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then
+               echo "--- Cleaning up ---"
+               perf probe -x ${temp_dir}/testfile -d foo
+               rm -f "${temp_dir}/"*
+               rmdir "${temp_dir}"
+       fi
+}
+
+trap_cleanup()
+{
+        cleanup
+        exit 1
+}
+
+trap trap_cleanup EXIT TERM INT
+
+cat > ${temp_dir}/testfile-foo.h << EOF
+struct t
+{
+  int *p;
+  int c;
+};
+
+extern int foo (int i, struct t *t);
+EOF
+
+cat > ${temp_dir}/testfile-foo.c << EOF
+#include "testfile-foo.h"
+
+int
+foo (int i, struct t *t)
+{
+  int j, res = 0;
+  for (j = 0; j < i && j < t->c; j++)
+    res += t->p[j];
+
+  return res;
+}
+EOF
+
+cat > ${temp_dir}/testfile-main.c << EOF
+#include "testfile-foo.h"
+
+static struct t g;
+
+int
+main (int argc, char **argv)
+{
+  int i;
+  int j[argc];
+  g.c = argc;
+  g.p = j;
+  for (i = 0; i < argc; i++)
+    j[i] = (int) argv[i][0];
+  return foo (3, &g);
+}
+EOF
+
+gcc -g -Og -flto -c ${temp_dir}/testfile-foo.c -o ${temp_dir}/testfile-foo.o
+gcc -g -Og -c ${temp_dir}/testfile-main.c -o ${temp_dir}/testfile-main.o
+gcc -g -Og -o ${temp_dir}/testfile ${temp_dir}/testfile-foo.o ${temp_dir}/testfile-main.o
+
+perf probe -x ${temp_dir}/testfile --funcs foo
+perf probe -x ${temp_dir}/testfile foo
+
+cleanup
index 25f075f..968dddd 100644 (file)
@@ -58,9 +58,9 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
 
        signal(SIGCHLD, sig_handler);
 
-       evlist = evlist__new_default();
+       evlist = evlist__new_dummy();
        if (evlist == NULL) {
-               pr_debug("evlist__new_default\n");
+               pr_debug("evlist__new_dummy\n");
                return -1;
        }
 
index 3bef212..39b74d8 100644 (file)
@@ -177,6 +177,7 @@ static inline size_t msg_data_left(struct msghdr *msg)
 #define        SCM_RIGHTS      0x01            /* rw: access rights (array of int) */
 #define SCM_CREDENTIALS 0x02           /* rw: struct ucred             */
 #define SCM_SECURITY   0x03            /* rw: security label           */
+#define SCM_PIDFD      0x04            /* ro: pidfd (int)              */
 
 struct ucred {
        __u32   pid;
@@ -326,6 +327,7 @@ struct ucred {
                                          */
 
 #define MSG_ZEROCOPY   0x4000000       /* Use user data in kernel path */
+#define MSG_SPLICE_PAGES 0x8000000     /* Splice the pages from the iterator in sendmsg() */
 #define MSG_FASTOPEN   0x20000000      /* Send data in TCP SYN */
 #define MSG_CMSG_CLOEXEC 0x40000000    /* Set close_on_exec for file
                                           descriptor received through
@@ -336,6 +338,9 @@ struct ucred {
 #define MSG_CMSG_COMPAT        0               /* We never have 32 bit fixups */
 #endif
 
+/* Flags to be cleared on entry by sendmsg and sendmmsg syscalls */
+#define MSG_INTERNAL_SENDMSG_FLAGS \
+       (MSG_SPLICE_PAGES | MSG_SENDPAGE_NOPOLICY | MSG_SENDPAGE_DECRYPTED)
 
 /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
 #define SOL_IP         0
index 32e552f..ce5e632 100755 (executable)
@@ -10,7 +10,7 @@ fi
 linux_mount=${linux_header_dir}/mount.h
 
 printf "static const char *move_mount_flags[] = {\n"
-regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MOVE_MOUNT_([^_]+_[[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MOVE_MOUNT_([^_]+[[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
 grep -E $regex ${linux_mount} | \
        sed -r "s/$regex/\2 \1/g"       | \
        xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
index aa99340..ed3ff96 100644 (file)
@@ -8,6 +8,12 @@
 #ifndef MSG_WAITFORONE
 #define MSG_WAITFORONE            0x10000
 #endif
+#ifndef MSG_BATCH
+#define MSG_BATCH                 0x40000
+#endif
+#ifndef MSG_ZEROCOPY
+#define MSG_ZEROCOPY            0x4000000
+#endif
 #ifndef MSG_SPLICE_PAGES
 #define MSG_SPLICE_PAGES       0x8000000
 #endif
@@ -50,6 +56,8 @@ static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
        P_MSG_FLAG(NOSIGNAL);
        P_MSG_FLAG(MORE);
        P_MSG_FLAG(WAITFORONE);
+       P_MSG_FLAG(BATCH);
+       P_MSG_FLAG(ZEROCOPY);
        P_MSG_FLAG(SPLICE_PAGES);
        P_MSG_FLAG(FASTOPEN);
        P_MSG_FLAG(CMSG_CLOEXEC);
index 45e018c..2941d88 100644 (file)
@@ -478,8 +478,10 @@ static const char *die_get_file_name(Dwarf_Die *dw_die, int idx)
 {
        Dwarf_Die cu_die;
        Dwarf_Files *files;
+       Dwarf_Attribute attr_mem;
 
-       if (idx < 0 || !dwarf_diecu(dw_die, &cu_die, NULL, NULL) ||
+       if (idx < 0 || !dwarf_attr_integrate(dw_die, DW_AT_decl_file, &attr_mem) ||
+           !dwarf_cu_die(attr_mem.cu, &cu_die, NULL, NULL, NULL, NULL, NULL, NULL) ||
            dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
                return NULL;
 
index 5dcfbf3..acde097 100644 (file)
@@ -1216,6 +1216,14 @@ static int config_term_pmu(struct perf_event_attr *attr,
        if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) {
                const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type);
 
+               if (!pmu) {
+                       char *err_str;
+
+                       if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0)
+                               parse_events_error__handle(err, term->err_term,
+                                                          err_str, /*help=*/NULL);
+                       return -EINVAL;
+               }
                if (perf_pmu__supports_legacy_cache(pmu)) {
                        attr->type = PERF_TYPE_HW_CACHE;
                        return parse_events__decode_legacy_cache(term->config, pmu->type,
index 0e78d8e..fb6ab9c 100644 (file)
@@ -999,10 +999,6 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
 #define SZ_64G (SZ_32G * 2)
 #endif
 
-#ifndef SZ_512G
-#define SZ_512G (SZ_64G * 8)
-#endif
-
 static __init int cxl_rch_init(void)
 {
        int rc, i;
index 03539d8..75ea208 100644 (file)
@@ -206,9 +206,9 @@ static noinline void __init check_new_node(struct maple_tree *mt)
                                e = i - 1;
                } else {
                        if (i >= 4)
-                               e = i - 4;
-                       else if (i == 3)
-                               e = i - 2;
+                               e = i - 3;
+                       else if (i >= 1)
+                               e = i - 1;
                        else
                                e = 0;
                }
index 71931b2..357adc7 100644 (file)
@@ -47,10 +47,8 @@ static int read_patterns(void)
 
                sprintf(pf, "/sys/kernel/debug/pcmtest/fill_pattern%d", i);
                fp = fopen(pf, "r");
-               if (!fp) {
-                       fclose(fpl);
+               if (!fp)
                        return -1;
-               }
                fread(patterns[i].buf, 1, patterns[i].len, fp);
                fclose(fp);
        }
index 9460cbe..ace8b67 100644 (file)
@@ -42,7 +42,7 @@ run_tests: all
        done
 
 # Avoid any output on non arm64 on emit_tests
-emit_tests: all
+emit_tests:
        @for DIR in $(ARM64_SUBTARGETS); do                             \
                BUILD_TARGET=$(OUTPUT)/$$DIR;                   \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;         \
index 477ba95..3517c0e 100644 (file)
@@ -22,9 +22,16 @@ static int timer_cb(void *map, int *key, struct bpf_timer *timer)
        return buf[69];
 }
 
+__attribute__((noinline))
+static int bad_timer_cb(void *map, int *key, struct bpf_timer *timer)
+{
+       volatile char buf[300] = {};
+       return buf[255] + timer_cb(NULL, NULL, NULL);
+}
+
 SEC("tc")
-__failure __msg("combined stack size of 2 calls")
-int prog(struct __sk_buff *ctx)
+__failure __msg("combined stack size of 2 calls is 576. Too large")
+int pseudo_call_check(struct __sk_buff *ctx)
 {
        struct hmap_elem *elem;
        volatile char buf[256] = {};
@@ -37,4 +44,18 @@ int prog(struct __sk_buff *ctx)
        return bpf_timer_set_callback(&elem->timer, timer_cb) + buf[0];
 }
 
+SEC("tc")
+__failure __msg("combined stack size of 2 calls is 608. Too large")
+int async_call_root_check(struct __sk_buff *ctx)
+{
+       struct hmap_elem *elem;
+       volatile char buf[256] = {};
+
+       elem = bpf_map_lookup_elem(&hmap, &(int){0});
+       if (!elem)
+               return 0;
+
+       return bpf_timer_set_callback(&elem->timer, bad_timer_cb) + buf[0];
+}
+
 char _license[] SEC("license") = "GPL";
index 4c88238..e949a43 100644 (file)
@@ -150,8 +150,8 @@ TEST(check_huge_pages)
                MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
                -1, 0);
        if (addr == MAP_FAILED) {
-               if (errno == ENOMEM)
-                       SKIP(return, "No huge pages available.");
+               if (errno == ENOMEM || errno == EINVAL)
+                       SKIP(return, "No huge pages available or CONFIG_HUGETLB_PAGE disabled.");
                else
                        TH_LOG("mmap error: %s", strerror(errno));
        }
old mode 100644 (file)
new mode 100755 (executable)
index 6d71d97..301abb9 100644 (file)
@@ -321,8 +321,8 @@ close_uffd:
 munmap:
        munmap(dst, pagesize);
        free(src);
-#endif /* __NR_userfaultfd */
 }
+#endif /* __NR_userfaultfd */
 
 int main(void)
 {
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index e6c9d54..3c2096a 100755 (executable)
@@ -162,9 +162,7 @@ check_tools()
        elif ! iptables -V &> /dev/null; then
                echo "SKIP: Could not run all tests without iptables tool"
                exit $ksft_skip
-       fi
-
-       if ! ip6tables -V &> /dev/null; then
+       elif ! ip6tables -V &> /dev/null; then
                echo "SKIP: Could not run all tests without ip6tables tool"
                exit $ksft_skip
        fi
index 9dd629c..f4b3d5c 100644 (file)
@@ -43,7 +43,7 @@ run_tests: all
        done
 
 # Avoid any output on non riscv on emit_tests
-emit_tests: all
+emit_tests:
        @for DIR in $(RISCV_SUBTARGETS); do                             \
                BUILD_TARGET=$(OUTPUT)/$$DIR;                   \
                $(MAKE) OUTPUT=$$BUILD_TARGET -C $$DIR $@;              \
index 6e73b09..7170619 100644 (file)
@@ -5,6 +5,8 @@ CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_MARK=y
 CONFIG_NF_CONNTRACK_ZONES=y
 CONFIG_NF_CONNTRACK_LABELS=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_FLOW_TABLE=m
 CONFIG_NF_NAT=m
 CONFIG_NETFILTER_XT_TARGET_LOG=m
 
diff --git a/tools/testing/selftests/tc-testing/settings b/tools/testing/selftests/tc-testing/settings
new file mode 100644 (file)
index 0000000..e220626
--- /dev/null
@@ -0,0 +1 @@
+timeout=900
index 5beceee..6eba203 100644 (file)
@@ -129,8 +129,7 @@ int main(int argc, char **argv)
        printf("%lld.%i(est)", eppm/1000, abs((int)(eppm%1000)));
 
        /* Avg the two actual freq samples adjtimex gave us */
-       ppm = (tx1.freq + tx2.freq) * 1000 / 2;
-       ppm = (long long)tx1.freq * 1000;
+       ppm = (long long)(tx1.freq + tx2.freq) * 1000 / 2;
        ppm = shift_right(ppm, 16);
        printf(" %lld.%i(act)", ppm/1000, abs((int)(ppm%1000)));