Merge tag 'mtd/fixes-for-6.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Jun 2023 21:35:17 +0000 (17:35 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Jun 2023 21:35:17 +0000 (17:35 -0400)
Pull mtd fixes from Miquel Raynal:
 "MTD core:
   - MAINTAINERS: Add Michal as reviewer instead of Naga
   - mtdchar: Mark bits of ioctl handler noinline

  NAND controller drivers:
   - marvell:
       - Don't set the NAND frequency select
       - Ensure timing values are written
   - ingenic: Fix empty stub helper definitions

  SPI-NOR core:
   - Fix divide by zero for spi-nor-generic flashes

  SPI-NOR manufacturer driver:
   - spansion: make sure local struct does not contain garbage"

* tag 'mtd/fixes-for-6.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: marvell: don't set the NAND frequency select
  mtd: rawnand: marvell: ensure timing values are written
  mtdchar: mark bits of ioctl handler noinline
  MAINTAINERS: Add myself as reviewer instead of Naga
  mtd: spi-nor: Fix divide by zero for spi-nor-generic flashes
  mtd: rawnand: ingenic: fix empty stub helper definitions
  mtd: spi-nor: spansion: make sure local struct does not contain garbage

576 files changed:
Documentation/admin-guide/cifs/changes.rst
Documentation/admin-guide/cifs/usage.rst
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
Documentation/devicetree/bindings/usb/cdns,usb3.yaml
Documentation/filesystems/index.rst
Documentation/filesystems/smb/cifsroot.rst [moved from Documentation/filesystems/cifs/cifsroot.rst with 97% similarity]
Documentation/filesystems/smb/index.rst [moved from Documentation/filesystems/cifs/index.rst with 100% similarity]
Documentation/filesystems/smb/ksmbd.rst [moved from Documentation/filesystems/cifs/ksmbd.rst with 100% similarity]
Documentation/netlink/specs/ethtool.yaml
Documentation/netlink/specs/handshake.yaml
Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst
Documentation/networking/tls-handshake.rst
Documentation/process/maintainer-netdev.rst
Documentation/trace/histogram.rst
Documentation/userspace-api/ioctl/ioctl-number.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/imx6qdl-mba6.dtsi
arch/arm/boot/dts/imx6ull-dhcor-som.dtsi
arch/arm/boot/dts/vexpress-v2p-ca5s.dts
arch/arm64/boot/dts/arm/foundation-v8.dtsi
arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi
arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi
arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi
arch/m68k/kernel/signal.c
arch/mips/Kconfig
arch/mips/alchemy/common/dbdma.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/setup.c
arch/parisc/Kconfig
arch/parisc/Kconfig.debug
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/spinlock.h
arch/parisc/include/asm/spinlock_types.h
arch/parisc/kernel/alternative.c
arch/parisc/kernel/cache.c
arch/parisc/kernel/pci-dma.c
arch/parisc/kernel/process.c
arch/parisc/kernel/traps.c
arch/powerpc/Kconfig
arch/x86/crypto/aria-aesni-avx-asm_64.S
arch/x86/events/intel/core.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/include/asm/fpu/sched.h
arch/x86/kernel/cpu/topology.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/fpu/context.h
arch/x86/kernel/fpu/core.c
arch/x86/lib/copy_user_64.S
arch/x86/mm/init.c
arch/x86/pci/xen.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/lib/Makefile
arch/xtensa/lib/bswapdi2.S [new file with mode: 0644]
arch/xtensa/lib/bswapsi2.S [new file with mode: 0644]
block/blk-core.c
block/blk-map.c
block/blk-mq-tag.c
block/blk-wbt.c
drivers/accel/qaic/qaic_control.c
drivers/accel/qaic/qaic_data.c
drivers/accel/qaic/qaic_drv.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/android/binder_alloc.h
drivers/android/binder_alloc_selftest.c
drivers/ata/libata-scsi.c
drivers/base/regmap/Kconfig
drivers/base/regmap/regcache-maple.c
drivers/base/regmap/regmap-sdw.c
drivers/base/regmap/regmap.c
drivers/block/xen-blkfront.c
drivers/bluetooth/btnxpuart.c
drivers/char/agp/parisc-agp.c
drivers/char/tpm/tpm_tis.c
drivers/cpufreq/amd-pstate.c
drivers/cxl/core/mbox.c
drivers/cxl/core/pci.c
drivers/cxl/core/port.c
drivers/cxl/cxl.h
drivers/cxl/cxlmem.h
drivers/cxl/cxlpci.h
drivers/cxl/mem.c
drivers/cxl/pci.c
drivers/cxl/port.c
drivers/dma/at_hdmac.c
drivers/dma/at_xdmac.c
drivers/dma/idxd/cdev.c
drivers/dma/pl330.c
drivers/dma/ti/k3-udma.c
drivers/firmware/arm_ffa/bus.c
drivers/firmware/arm_ffa/driver.c
drivers/firmware/arm_scmi/raw_mode.c
drivers/gpio/Kconfig
drivers/gpio/gpio-f7188x.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/drm_managed.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/pl111/pl111_display.c
drivers/gpu/drm/pl111/pl111_drm.h
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/pl111/pl111_versatile.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/hid/hid-google-hammer.c
drivers/hid/hid-ids.h
drivers/hid/hid-logitech-hidpp.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/coresight/coresight-tmc-etr.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/bnxt_re/qplib_sp.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
drivers/infiniband/hw/hns/hns_roce_mr.c
drivers/infiniband/hw/irdma/verbs.c
drivers/infiniband/sw/rxe/rxe_comp.c
drivers/infiniband/sw/rxe/rxe_net.c
drivers/infiniband/sw/rxe/rxe_qp.c
drivers/infiniband/sw/rxe/rxe_recv.c
drivers/infiniband/sw/rxe/rxe_req.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/irqchip/irq-gic-common.c
drivers/irqchip/irq-gic-common.h
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-mbigen.c
drivers/irqchip/irq-meson-gpio.c
drivers/irqchip/irq-mips-gic.c
drivers/mailbox/mailbox-test.c
drivers/mmc/core/block.c
drivers/mmc/host/sdhci-cadence.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/ethernet/3com/3c589_cs.c
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.h
drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
drivers/net/ethernet/mellanox/mlx5/core/en_common.c
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h
drivers/net/ethernet/mellanox/mlx5/core/mr.c
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microsoft/mana/mana_en.c
drivers/net/ethernet/microsoft/mana/mana_ethtool.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/rswitch.c
drivers/net/ethernet/sfc/efx_devlink.c
drivers/net/ethernet/sfc/tc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
drivers/net/ipa/ipa_endpoint.c
drivers/net/phy/mscc/mscc.h
drivers/net/phy/mscc/mscc_main.c
drivers/net/phy/mxl-gpy.c
drivers/net/team/team.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/nfc/nfcsim.c
drivers/nvme/host/pci.c
drivers/pci/quirks.c
drivers/phy/amlogic/phy-meson-g12a-mipi-dphy-analog.c
drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c
drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
drivers/platform/mellanox/mlxbf-pmc.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/intel/ifs/load.c
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
drivers/power/supply/ab8500_btemp.c
drivers/power/supply/ab8500_fg.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq24190_charger.c
drivers/power/supply/bq25890_charger.c
drivers/power/supply/bq27xxx_battery.c
drivers/power/supply/bq27xxx_battery_i2c.c
drivers/power/supply/mt6360_charger.c
drivers/power/supply/power_supply_core.c
drivers/power/supply/power_supply_leds.c
drivers/power/supply/power_supply_sysfs.c
drivers/power/supply/rt9467-charger.c
drivers/power/supply/sbs-charger.c
drivers/power/supply/sc27xx_fuel_gauge.c
drivers/regulator/core.c
drivers/regulator/mt6359-regulator.c
drivers/regulator/pca9450-regulator.c
drivers/spi/spi-cadence.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-geni-qcom.c
drivers/tee/optee/smc_abi.c
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/vhost.c
drivers/xen/pvcalls-back.c
fs/Kconfig
fs/Makefile
fs/btrfs/bio.c
fs/btrfs/block-group.c
fs/btrfs/disk-io.c
fs/btrfs/file-item.c
fs/btrfs/scrub.c
fs/btrfs/tree-log.c
fs/coredump.c
fs/erofs/Kconfig
fs/erofs/Makefile
fs/erofs/internal.h
fs/erofs/xattr.c
fs/erofs/zdata.c
fs/ext4/ext4.h
fs/ext4/fsync.c
fs/ext4/inode.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/nfs/dir.c
fs/nfs/nfs4proc.c
fs/smb/Kconfig [new file with mode: 0644]
fs/smb/Makefile [new file with mode: 0644]
fs/smb/client/Kconfig [moved from fs/cifs/Kconfig with 100% similarity]
fs/smb/client/Makefile [moved from fs/cifs/Makefile with 100% similarity]
fs/smb/client/asn1.c [moved from fs/cifs/asn1.c with 100% similarity]
fs/smb/client/cached_dir.c [moved from fs/cifs/cached_dir.c with 100% similarity]
fs/smb/client/cached_dir.h [moved from fs/cifs/cached_dir.h with 100% similarity]
fs/smb/client/cifs_debug.c [moved from fs/cifs/cifs_debug.c with 99% similarity]
fs/smb/client/cifs_debug.h [moved from fs/cifs/cifs_debug.h with 100% similarity]
fs/smb/client/cifs_dfs_ref.c [moved from fs/cifs/cifs_dfs_ref.c with 100% similarity]
fs/smb/client/cifs_fs_sb.h [moved from fs/cifs/cifs_fs_sb.h with 100% similarity]
fs/smb/client/cifs_ioctl.h [moved from fs/cifs/cifs_ioctl.h with 100% similarity]
fs/smb/client/cifs_spnego.c [moved from fs/cifs/cifs_spnego.c with 100% similarity]
fs/smb/client/cifs_spnego.h [moved from fs/cifs/cifs_spnego.h with 100% similarity]
fs/smb/client/cifs_spnego_negtokeninit.asn1 [moved from fs/cifs/cifs_spnego_negtokeninit.asn1 with 100% similarity]
fs/smb/client/cifs_swn.c [moved from fs/cifs/cifs_swn.c with 100% similarity]
fs/smb/client/cifs_swn.h [moved from fs/cifs/cifs_swn.h with 100% similarity]
fs/smb/client/cifs_unicode.c [moved from fs/cifs/cifs_unicode.c with 100% similarity]
fs/smb/client/cifs_unicode.h [moved from fs/cifs/cifs_unicode.h with 100% similarity]
fs/smb/client/cifs_uniupr.h [moved from fs/cifs/cifs_uniupr.h with 100% similarity]
fs/smb/client/cifsacl.c [moved from fs/cifs/cifsacl.c with 100% similarity]
fs/smb/client/cifsacl.h [moved from fs/cifs/cifsacl.h with 100% similarity]
fs/smb/client/cifsencrypt.c [moved from fs/cifs/cifsencrypt.c with 99% similarity]
fs/smb/client/cifsfs.c [moved from fs/cifs/cifsfs.c with 100% similarity]
fs/smb/client/cifsfs.h [moved from fs/cifs/cifsfs.h with 100% similarity]
fs/smb/client/cifsglob.h [moved from fs/cifs/cifsglob.h with 99% similarity]
fs/smb/client/cifspdu.h [moved from fs/cifs/cifspdu.h with 99% similarity]
fs/smb/client/cifsproto.h [moved from fs/cifs/cifsproto.h with 100% similarity]
fs/smb/client/cifsroot.c [moved from fs/cifs/cifsroot.c with 100% similarity]
fs/smb/client/cifssmb.c [moved from fs/cifs/cifssmb.c with 100% similarity]
fs/smb/client/connect.c [moved from fs/cifs/connect.c with 100% similarity]
fs/smb/client/dfs.c [moved from fs/cifs/dfs.c with 99% similarity]
fs/smb/client/dfs.h [moved from fs/cifs/dfs.h with 100% similarity]
fs/smb/client/dfs_cache.c [moved from fs/cifs/dfs_cache.c with 100% similarity]
fs/smb/client/dfs_cache.h [moved from fs/cifs/dfs_cache.h with 100% similarity]
fs/smb/client/dir.c [moved from fs/cifs/dir.c with 100% similarity]
fs/smb/client/dns_resolve.c [moved from fs/cifs/dns_resolve.c with 100% similarity]
fs/smb/client/dns_resolve.h [moved from fs/cifs/dns_resolve.h with 100% similarity]
fs/smb/client/export.c [moved from fs/cifs/export.c with 100% similarity]
fs/smb/client/file.c [moved from fs/cifs/file.c with 99% similarity]
fs/smb/client/fs_context.c [moved from fs/cifs/fs_context.c with 99% similarity]
fs/smb/client/fs_context.h [moved from fs/cifs/fs_context.h with 100% similarity]
fs/smb/client/fscache.c [moved from fs/cifs/fscache.c with 100% similarity]
fs/smb/client/fscache.h [moved from fs/cifs/fscache.h with 100% similarity]
fs/smb/client/inode.c [moved from fs/cifs/inode.c with 100% similarity]
fs/smb/client/ioctl.c [moved from fs/cifs/ioctl.c with 98% similarity]
fs/smb/client/link.c [moved from fs/cifs/link.c with 100% similarity]
fs/smb/client/misc.c [moved from fs/cifs/misc.c with 100% similarity]
fs/smb/client/netlink.c [moved from fs/cifs/netlink.c with 100% similarity]
fs/smb/client/netlink.h [moved from fs/cifs/netlink.h with 100% similarity]
fs/smb/client/netmisc.c [moved from fs/cifs/netmisc.c with 100% similarity]
fs/smb/client/nterr.c [moved from fs/cifs/nterr.c with 100% similarity]
fs/smb/client/nterr.h [moved from fs/cifs/nterr.h with 100% similarity]
fs/smb/client/ntlmssp.h [moved from fs/cifs/ntlmssp.h with 100% similarity]
fs/smb/client/readdir.c [moved from fs/cifs/readdir.c with 100% similarity]
fs/smb/client/rfc1002pdu.h [moved from fs/cifs/rfc1002pdu.h with 100% similarity]
fs/smb/client/sess.c [moved from fs/cifs/sess.c with 100% similarity]
fs/smb/client/smb1ops.c [moved from fs/cifs/smb1ops.c with 100% similarity]
fs/smb/client/smb2file.c [moved from fs/cifs/smb2file.c with 100% similarity]
fs/smb/client/smb2glob.h [moved from fs/cifs/smb2glob.h with 100% similarity]
fs/smb/client/smb2inode.c [moved from fs/cifs/smb2inode.c with 100% similarity]
fs/smb/client/smb2maperror.c [moved from fs/cifs/smb2maperror.c with 100% similarity]
fs/smb/client/smb2misc.c [moved from fs/cifs/smb2misc.c with 100% similarity]
fs/smb/client/smb2ops.c [moved from fs/cifs/smb2ops.c with 99% similarity]
fs/smb/client/smb2pdu.c [moved from fs/cifs/smb2pdu.c with 99% similarity]
fs/smb/client/smb2pdu.h [moved from fs/cifs/smb2pdu.h with 100% similarity]
fs/smb/client/smb2proto.h [moved from fs/cifs/smb2proto.h with 100% similarity]
fs/smb/client/smb2status.h [moved from fs/cifs/smb2status.h with 100% similarity]
fs/smb/client/smb2transport.c [moved from fs/cifs/smb2transport.c with 100% similarity]
fs/smb/client/smbdirect.c [moved from fs/cifs/smbdirect.c with 100% similarity]
fs/smb/client/smbdirect.h [moved from fs/cifs/smbdirect.h with 100% similarity]
fs/smb/client/smbencrypt.c [moved from fs/cifs/smbencrypt.c with 98% similarity]
fs/smb/client/smberr.h [moved from fs/cifs/smberr.h with 100% similarity]
fs/smb/client/trace.c [moved from fs/cifs/trace.c with 100% similarity]
fs/smb/client/trace.h [moved from fs/cifs/trace.h with 100% similarity]
fs/smb/client/transport.c [moved from fs/cifs/transport.c with 100% similarity]
fs/smb/client/unc.c [moved from fs/cifs/unc.c with 100% similarity]
fs/smb/client/winucase.c [moved from fs/cifs/winucase.c with 100% similarity]
fs/smb/client/xattr.c [moved from fs/cifs/xattr.c with 100% similarity]
fs/smb/common/Makefile [moved from fs/smbfs_common/Makefile with 59% similarity]
fs/smb/common/arc4.h [moved from fs/smbfs_common/arc4.h with 100% similarity]
fs/smb/common/cifs_arc4.c [moved from fs/smbfs_common/cifs_arc4.c with 100% similarity]
fs/smb/common/cifs_md4.c [moved from fs/smbfs_common/cifs_md4.c with 100% similarity]
fs/smb/common/md4.h [moved from fs/smbfs_common/md4.h with 100% similarity]
fs/smb/common/smb2pdu.h [moved from fs/smbfs_common/smb2pdu.h with 100% similarity]
fs/smb/common/smbfsctl.h [moved from fs/smbfs_common/smbfsctl.h with 100% similarity]
fs/smb/server/Kconfig [moved from fs/ksmbd/Kconfig with 100% similarity]
fs/smb/server/Makefile [moved from fs/ksmbd/Makefile with 100% similarity]
fs/smb/server/asn1.c [moved from fs/ksmbd/asn1.c with 100% similarity]
fs/smb/server/asn1.h [moved from fs/ksmbd/asn1.h with 100% similarity]
fs/smb/server/auth.c [moved from fs/ksmbd/auth.c with 99% similarity]
fs/smb/server/auth.h [moved from fs/ksmbd/auth.h with 100% similarity]
fs/smb/server/connection.c [moved from fs/ksmbd/connection.c with 100% similarity]
fs/smb/server/connection.h [moved from fs/ksmbd/connection.h with 100% similarity]
fs/smb/server/crypto_ctx.c [moved from fs/ksmbd/crypto_ctx.c with 100% similarity]
fs/smb/server/crypto_ctx.h [moved from fs/ksmbd/crypto_ctx.h with 100% similarity]
fs/smb/server/glob.h [moved from fs/ksmbd/glob.h with 100% similarity]
fs/smb/server/ksmbd_netlink.h [moved from fs/ksmbd/ksmbd_netlink.h with 100% similarity]
fs/smb/server/ksmbd_spnego_negtokeninit.asn1 [moved from fs/ksmbd/ksmbd_spnego_negtokeninit.asn1 with 100% similarity]
fs/smb/server/ksmbd_spnego_negtokentarg.asn1 [moved from fs/ksmbd/ksmbd_spnego_negtokentarg.asn1 with 100% similarity]
fs/smb/server/ksmbd_work.c [moved from fs/ksmbd/ksmbd_work.c with 100% similarity]
fs/smb/server/ksmbd_work.h [moved from fs/ksmbd/ksmbd_work.h with 100% similarity]
fs/smb/server/mgmt/ksmbd_ida.c [moved from fs/ksmbd/mgmt/ksmbd_ida.c with 100% similarity]
fs/smb/server/mgmt/ksmbd_ida.h [moved from fs/ksmbd/mgmt/ksmbd_ida.h with 100% similarity]
fs/smb/server/mgmt/share_config.c [moved from fs/ksmbd/mgmt/share_config.c with 100% similarity]
fs/smb/server/mgmt/share_config.h [moved from fs/ksmbd/mgmt/share_config.h with 100% similarity]
fs/smb/server/mgmt/tree_connect.c [moved from fs/ksmbd/mgmt/tree_connect.c with 100% similarity]
fs/smb/server/mgmt/tree_connect.h [moved from fs/ksmbd/mgmt/tree_connect.h with 100% similarity]
fs/smb/server/mgmt/user_config.c [moved from fs/ksmbd/mgmt/user_config.c with 100% similarity]
fs/smb/server/mgmt/user_config.h [moved from fs/ksmbd/mgmt/user_config.h with 100% similarity]
fs/smb/server/mgmt/user_session.c [moved from fs/ksmbd/mgmt/user_session.c with 100% similarity]
fs/smb/server/mgmt/user_session.h [moved from fs/ksmbd/mgmt/user_session.h with 100% similarity]
fs/smb/server/misc.c [moved from fs/ksmbd/misc.c with 100% similarity]
fs/smb/server/misc.h [moved from fs/ksmbd/misc.h with 100% similarity]
fs/smb/server/ndr.c [moved from fs/ksmbd/ndr.c with 100% similarity]
fs/smb/server/ndr.h [moved from fs/ksmbd/ndr.h with 100% similarity]
fs/smb/server/nterr.h [moved from fs/ksmbd/nterr.h with 100% similarity]
fs/smb/server/ntlmssp.h [moved from fs/ksmbd/ntlmssp.h with 100% similarity]
fs/smb/server/oplock.c [moved from fs/ksmbd/oplock.c with 98% similarity]
fs/smb/server/oplock.h [moved from fs/ksmbd/oplock.h with 100% similarity]
fs/smb/server/server.c [moved from fs/ksmbd/server.c with 100% similarity]
fs/smb/server/server.h [moved from fs/ksmbd/server.h with 100% similarity]
fs/smb/server/smb2misc.c [moved from fs/ksmbd/smb2misc.c with 100% similarity]
fs/smb/server/smb2ops.c [moved from fs/ksmbd/smb2ops.c with 100% similarity]
fs/smb/server/smb2pdu.c [moved from fs/ksmbd/smb2pdu.c with 99% similarity]
fs/smb/server/smb2pdu.h [moved from fs/ksmbd/smb2pdu.h with 100% similarity]
fs/smb/server/smb_common.c [moved from fs/ksmbd/smb_common.c with 100% similarity]
fs/smb/server/smb_common.h [moved from fs/ksmbd/smb_common.h with 99% similarity]
fs/smb/server/smbacl.c [moved from fs/ksmbd/smbacl.c with 100% similarity]
fs/smb/server/smbacl.h [moved from fs/ksmbd/smbacl.h with 100% similarity]
fs/smb/server/smbfsctl.h [moved from fs/ksmbd/smbfsctl.h with 98% similarity]
fs/smb/server/smbstatus.h [moved from fs/ksmbd/smbstatus.h with 99% similarity]
fs/smb/server/transport_ipc.c [moved from fs/ksmbd/transport_ipc.c with 100% similarity]
fs/smb/server/transport_ipc.h [moved from fs/ksmbd/transport_ipc.h with 100% similarity]
fs/smb/server/transport_rdma.c [moved from fs/ksmbd/transport_rdma.c with 100% similarity]
fs/smb/server/transport_rdma.h [moved from fs/ksmbd/transport_rdma.h with 100% similarity]
fs/smb/server/transport_tcp.c [moved from fs/ksmbd/transport_tcp.c with 100% similarity]
fs/smb/server/transport_tcp.h [moved from fs/ksmbd/transport_tcp.h with 100% similarity]
fs/smb/server/unicode.c [moved from fs/ksmbd/unicode.c with 100% similarity]
fs/smb/server/unicode.h [moved from fs/ksmbd/unicode.h with 100% similarity]
fs/smb/server/uniupr.h [moved from fs/ksmbd/uniupr.h with 100% similarity]
fs/smb/server/vfs.c [moved from fs/ksmbd/vfs.c with 99% similarity]
fs/smb/server/vfs.h [moved from fs/ksmbd/vfs.h with 100% similarity]
fs/smb/server/vfs_cache.c [moved from fs/ksmbd/vfs_cache.c with 100% similarity]
fs/smb/server/vfs_cache.h [moved from fs/ksmbd/vfs_cache.h with 100% similarity]
fs/smb/server/xattr.h [moved from fs/ksmbd/xattr.h with 100% similarity]
fs/xattr.c
include/asm-generic/vmlinux.lds.h
include/drm/drm_managed.h
include/linux/arm_ffa.h
include/linux/firewire.h
include/linux/fs.h
include/linux/if_team.h
include/linux/lockdep.h
include/linux/lockdep_types.h
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/msi.h
include/linux/power/bq27xxx_battery.h
include/linux/sched/task.h
include/linux/sched/vhost_task.h
include/linux/skbuff.h
include/linux/skmsg.h
include/linux/trace_events.h
include/linux/user_events.h
include/net/bluetooth/hci_core.h
include/net/bonding.h
include/net/handshake.h
include/net/ip.h
include/net/mana/mana.h
include/net/page_pool.h
include/net/sock.h
include/net/tcp.h
include/net/tls.h
include/sound/soc-acpi.h
include/sound/soc-dpcm.h
include/uapi/linux/handshake.h
include/uapi/linux/in.h
include/uapi/sound/skl-tplg-interface.h
io_uring/sqpoll.c
kernel/bpf/hashtab.c
kernel/bpf/offload.c
kernel/bpf/verifier.c
kernel/exit.c
kernel/fork.c
kernel/irq/msi.c
kernel/locking/lockdep.c
kernel/module/main.c
kernel/module/stats.c
kernel/signal.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_user.c
kernel/trace/trace_osnoise.c
kernel/trace/trace_selftest.c
kernel/vhost_task.c
lib/debugobjects.c
net/bluetooth/hci_conn.c
net/core/page_pool.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_map.c
net/handshake/handshake-test.c
net/handshake/handshake.h
net/handshake/netlink.c
net/handshake/request.c
net/handshake/tlshd.c
net/ipv4/af_inet.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_sockglue.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_input.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/udplite.c
net/ipv6/exthdrs_core.c
net/ipv6/raw.c
net/ipv6/udplite.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netlink/af_netlink.c
net/netrom/nr_subr.c
net/packet/af_packet.c
net/packet/diag.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/local_event.c
net/sched/cls_flower.c
net/sched/sch_api.c
net/sched/sch_ingress.c
net/sctp/transport.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_llc.c
net/sunrpc/sched.c
net/tls/tls.h
net/tls/tls_device.c
net/tls/tls_strp.c
net/tls/tls_sw.c
net/unix/af_unix.c
net/vmw_vsock/virtio_transport_common.c
samples/bpf/hbm.c
sound/hda/hdac_device.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/cs35l41-lib.c
sound/soc/codecs/lpass-tx-macro.c
sound/soc/codecs/rt5682-i2c.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/rt5682.h
sound/soc/dwc/dwc-i2s.c
sound/soc/intel/avs/apl.c
sound/soc/intel/avs/avs.h
sound/soc/intel/avs/board_selection.c
sound/soc/intel/avs/control.c
sound/soc/intel/avs/dsp.c
sound/soc/intel/avs/messages.h
sound/soc/intel/avs/path.h
sound/soc/intel/avs/pcm.c
sound/soc/intel/avs/probes.c
sound/soc/soc-pcm.c
tools/gpio/lsgpio.c
tools/include/linux/coresight-pmu.h
tools/include/uapi/linux/in.h
tools/net/ynl/lib/ynl.py
tools/perf/Makefile.config
tools/perf/Makefile.perf
tools/perf/arch/arm/util/pmu.c
tools/perf/builtin-ftrace.c
tools/perf/util/Build
tools/perf/util/bpf_skel/sample_filter.bpf.c
tools/perf/util/cs-etm.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/symbol-elf.c
tools/testing/cxl/Kbuild
tools/testing/cxl/test/mem.c
tools/testing/cxl/test/mock.c
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_sockmap_kern.h
tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack-legacy.tc [new file with mode: 0644]
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack.tc
tools/testing/selftests/gpio/gpio-sim.sh
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/mptcp/Makefile
tools/testing/selftests/net/mptcp/diag.sh
tools/testing/selftests/net/mptcp/mptcp_connect.sh
tools/testing/selftests/net/mptcp/mptcp_join.sh
tools/testing/selftests/net/mptcp/mptcp_lib.sh [new file with mode: 0644]
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh
tools/testing/selftests/net/mptcp/pm_netlink.sh
tools/testing/selftests/net/mptcp/simult_flows.sh
tools/testing/selftests/net/mptcp/userspace_pm.sh

index 3147bba..8c42c4d 100644 (file)
@@ -5,5 +5,5 @@ Changes
 See https://wiki.samba.org/index.php/LinuxCIFSKernel for summary
 information about fixes/improvements to CIFS/SMB2/SMB3 support (changes
 to cifs.ko module) by kernel version (and cifs internal module version).
-This may be easier to read than parsing the output of "git log fs/cifs"
-by release.
+This may be easier to read than parsing the output of
+"git log fs/smb/client" by release.
index 2e151cd..5f936b4 100644 (file)
@@ -45,7 +45,7 @@ Installation instructions
 
 If you have built the CIFS vfs as module (successfully) simply
 type ``make modules_install`` (or if you prefer, manually copy the file to
-the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.ko).
+the modules directory e.g. /lib/modules/6.3.0-060300-generic/kernel/fs/smb/client/cifs.ko).
 
 If you have built the CIFS vfs into the kernel itself, follow the instructions
 for your distribution on how to install a new kernel (usually you
@@ -66,15 +66,15 @@ If cifs is built as a module, then the size and number of network buffers
 and maximum number of simultaneous requests to one server can be configured.
 Changing these from their defaults is not recommended. By executing modinfo::
 
-       modinfo kernel/fs/cifs/cifs.ko
+       modinfo <path to cifs.ko>
 
-on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
+on kernel/fs/smb/client/cifs.ko the list of configuration changes that can be made
 at module initialization time (by running insmod cifs.ko) can be seen.
 
 Recommendations
 ===============
 
-To improve security the SMB2.1 dialect or later (usually will get SMB3) is now
+To improve security the SMB2.1 dialect or later (usually will get SMB3.1.1) is now
 the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0"
 on mount (or vers=2.0 for Windows Vista).  Note that the CIFS (vers=1.0) is
 much older and less secure than the default dialect SMB3 which includes
index 9211726..39e64c7 100644 (file)
@@ -166,6 +166,12 @@ properties:
   resets:
     maxItems: 1
 
+  mediatek,broken-save-restore-fw:
+    type: boolean
+    description:
+      Asserts that the firmware on this device has issues saving and restoring
+      GICR registers when the GIC redistributors are powered off.
+
 dependencies:
   mbi-ranges: [ msi-controller ]
   msi-controller: [ mbi-ranges ]
index f59125b..0b4e21b 100644 (file)
@@ -8,7 +8,7 @@ Required properties:
        "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
        "ti,tas2505" TAS2505, TAS2521
  - reg: I2C slave address
- - supply-*: Required supply regulators are:
+ - *-supply: Required supply regulators are:
     "iov" - digital IO power supply
     "ldoin" - LDO power supply
     "dv" - Digital core power supply
index cae46c4..69a93a0 100644 (file)
@@ -64,7 +64,7 @@ properties:
     description:
       size of memory intended as internal memory for endpoints
       buffers expressed in KB
-    $ref: /schemas/types.yaml#/definitions/uint32
+    $ref: /schemas/types.yaml#/definitions/uint16
 
   cdns,phyrst-a-enable:
     description: Enable resetting of PHY if Rx fail is detected
index fbb2b5a..eb252fc 100644 (file)
@@ -72,7 +72,6 @@ Documentation for filesystem implementations.
    befs
    bfs
    btrfs
-   cifs/index
    ceph
    coda
    configfs
@@ -111,6 +110,7 @@ Documentation for filesystem implementations.
    ramfs-rootfs-initramfs
    relay
    romfs
+   smb/index
    spufs/index
    squashfs
    sysfs
similarity index 97%
rename from Documentation/filesystems/cifs/cifsroot.rst
rename to Documentation/filesystems/smb/cifsroot.rst
index 4930bb4..bf2d9db 100644 (file)
@@ -59,7 +59,7 @@ the root file system via SMB protocol.
 Enables the kernel to mount the root file system via SMB that are
 located in the <server-ip> and <share> specified in this option.
 
-The default mount options are set in fs/cifs/cifsroot.c.
+The default mount options are set in fs/smb/client/cifsroot.c.
 
 server-ip
        IPv4 address of the server.
index 129f413..3abc576 100644 (file)
@@ -61,22 +61,6 @@ attribute-sets:
         nested-attributes: bitset-bits
 
   -
-    name: u64-array
-    attributes:
-      -
-        name: u64
-        type: nest
-        multi-attr: true
-        nested-attributes: u64
-  -
-    name: s32-array
-    attributes:
-      -
-        name: s32
-        type: nest
-        multi-attr: true
-        nested-attributes: s32
-  -
     name: string
     attributes:
       -
@@ -705,16 +689,16 @@ attribute-sets:
         type: u8
       -
         name: corrected
-        type: nest
-        nested-attributes: u64-array
+        type: binary
+        sub-type: u64
       -
         name: uncorr
-        type: nest
-        nested-attributes: u64-array
+        type: binary
+        sub-type: u64
       -
         name: corr-bits
-        type: nest
-        nested-attributes: u64-array
+        type: binary
+        sub-type: u64
   -
     name: fec
     attributes:
@@ -827,8 +811,8 @@ attribute-sets:
         type: u32
       -
         name: index
-        type: nest
-        nested-attributes: s32-array
+        type: binary
+        sub-type: s32
   -
     name: module
     attributes:
index 614f1a5..6d89e30 100644 (file)
@@ -68,6 +68,9 @@ attribute-sets:
         type: nest
         nested-attributes: x509
         multi-attr: true
+      -
+        name: peername
+        type: string
   -
     name: done
     attributes:
@@ -105,6 +108,7 @@ operations:
             - auth-mode
             - peer-identity
             - certificate
+            - peername
     -
       name: done
       doc: Handler reports handshake completion
index 3a7a714..3354ca3 100644 (file)
@@ -40,6 +40,7 @@ flow_steering_mode: Device flow steering mode
 ---------------------------------------------
 The flow steering mode parameter controls the flow steering mode of the driver.
 Two modes are supported:
+
 1. 'dmfs' - Device managed flow steering.
 2. 'smfs' - Software/Driver managed flow steering.
 
@@ -99,6 +100,7 @@ between representors and stacked devices.
 By default metadata is enabled on the supported devices in E-switch.
 Metadata is applicable only for E-switch in switchdev mode and
 users may disable it when NONE of the below use cases will be in use:
+
 1. HCA is in Dual/multi-port RoCE mode.
 2. VF/SF representor bonding (Usually used for Live migration)
 3. Stacked devices
@@ -180,7 +182,8 @@ User commands examples:
 
     $ devlink health diagnose pci/0000:82:00.0 reporter tx
 
-NOTE: This command has valid output only when interface is up, otherwise the command has empty output.
+.. note::
+   This command has valid output only when interface is up, otherwise the command has empty output.
 
 - Show number of tx errors indicated, number of recover flows ended successfully,
   is autorecover enabled and graceful period from last recover::
@@ -232,8 +235,9 @@ User commands examples:
 
     $ devlink health dump show pci/0000:82:00.0 reporter fw
 
-NOTE: This command can run only on the PF which has fw tracer ownership,
-running it on other PF or any VF will return "Operation not permitted".
+.. note::
+   This command can run only on the PF which has fw tracer ownership,
+   running it on other PF or any VF will return "Operation not permitted".
 
 fw fatal reporter
 -----------------
@@ -256,7 +260,8 @@ User commands examples:
 
     $ devlink health dump show pci/0000:82:00.1 reporter fw_fatal
 
-NOTE: This command can run only on PF.
+.. note::
+   This command can run only on PF.
 
 vnic reporter
 -------------
@@ -265,28 +270,37 @@ It is responsible for querying the vnic diagnostic counters from fw and displayi
 them in realtime.
 
 Description of the vnic counters:
-total_q_under_processor_handle: number of queues in an error state due to
-an async error or errored command.
-send_queue_priority_update_flow: number of QP/SQ priority/SL update
-events.
-cq_overrun: number of times CQ entered an error state due to an
-overflow.
-async_eq_overrun: number of times an EQ mapped to async events was
-overrun.
-comp_eq_overrun: number of times an EQ mapped to completion events was
-overrun.
-quota_exceeded_command: number of commands issued and failed due to quota
-exceeded.
-invalid_command: number of commands issued and failed dues to any reason
-other than quota exceeded.
-nic_receive_steering_discard: number of packets that completed RX flow
-steering but were discarded due to a mismatch in flow table.
+
+- total_q_under_processor_handle
+        number of queues in an error state due to
+        an async error or errored command.
+- send_queue_priority_update_flow
+        number of QP/SQ priority/SL update events.
+- cq_overrun
+        number of times CQ entered an error state due to an overflow.
+- async_eq_overrun
+        number of times an EQ mapped to async events was overrun.
+        comp_eq_overrun number of times an EQ mapped to completion events was
+        overrun.
+- quota_exceeded_command
+        number of commands issued and failed due to quota exceeded.
+- invalid_command
+        number of commands issued and failed dues to any reason other than quota
+        exceeded.
+- nic_receive_steering_discard
+        number of packets that completed RX flow
+        steering but were discarded due to a mismatch in flow table.
 
 User commands examples:
-- Diagnose PF/VF vnic counters
+
+- Diagnose PF/VF vnic counters::
+
         $ devlink health diagnose pci/0000:82:00.1 reporter vnic
+
 - Diagnose representor vnic counters (performed by supplying devlink port of the
-  representor, which can be obtained via devlink port command)
+  representor, which can be obtained via devlink port command)::
+
         $ devlink health diagnose pci/0000:82:00.1/65537 reporter vnic
 
-NOTE: This command can run over all interfaces such as PF/VF and representor ports.
+.. note::
+   This command can run over all interfaces such as PF/VF and representor ports.
index a2817a8..6f5ea16 100644 (file)
@@ -53,6 +53,7 @@ fills in a structure that contains the parameters of the request:
         struct socket   *ta_sock;
         tls_done_func_t ta_done;
         void            *ta_data;
+        const char      *ta_peername;
         unsigned int    ta_timeout_ms;
         key_serial_t    ta_keyring;
         key_serial_t    ta_my_cert;
@@ -71,6 +72,10 @@ instantiated a struct file in sock->file.
 has completed. Further explanation of this function is in the "Handshake
 Completion" sesction below.
 
+The consumer can provide a NUL-terminated hostname in the @ta_peername
+field that is sent as part of ClientHello. If no peername is provided,
+the DNS hostname associated with the server's IP address is used instead.
+
 The consumer can fill in the @ta_timeout_ms field to force the servicing
 handshake agent to exit after a number of milliseconds. This enables the
 socket to be fully closed once both the kernel and the handshake agent
index f73ac9e..83614ce 100644 (file)
@@ -127,13 +127,32 @@ the value of ``Message-ID`` to the URL above.
 Updating patch status
 ~~~~~~~~~~~~~~~~~~~~~
 
-It may be tempting to help the maintainers and update the state of your
-own patches when you post a new version or spot a bug. Please **do not**
-do that.
-Interfering with the patch status on patchwork will only cause confusion. Leave
-it to the maintainer to figure out what is the most recent and current
-version that should be applied. If there is any doubt, the maintainer
-will reply and ask what should be done.
+Contributors and reviewers do not have the permissions to update patch
+state directly in patchwork. Patchwork doesn't expose much information
+about the history of the state of patches, therefore having multiple
+people update the state leads to confusion.
+
+Instead of delegating patchwork permissions netdev uses a simple mail
+bot which looks for special commands/lines within the emails sent to
+the mailing list. For example to mark a series as Changes Requested
+one needs to send the following line anywhere in the email thread::
+
+  pw-bot: changes-requested
+
+As a result the bot will set the entire series to Changes Requested.
+This may be useful when author discovers a bug in their own series
+and wants to prevent it from getting applied.
+
+The use of the bot is entirely optional, if in doubt ignore its existence
+completely. Maintainers will classify and update the state of the patches
+themselves. No email should ever be sent to the list with the main purpose
+of communicating with the bot, the bot commands should be seen as metadata.
+
+The use of the bot is restricted to authors of the patches (the ``From:``
+header on patch submission and command must match!), maintainers themselves
+and a handful of senior reviewers. Bot records its activity here:
+
+  https://patchwork.hopto.org/pw-bot.html
 
 Review timelines
 ~~~~~~~~~~~~~~~~
index 479c9ea..3c9b263 100644 (file)
@@ -35,7 +35,7 @@ Documentation written by Tom Zanussi
   in place of an explicit value field - this is simply a count of
   event hits.  If 'values' isn't specified, an implicit 'hitcount'
   value will be automatically created and used as the only value.
-  Keys can be any field, or the special string 'stacktrace', which
+  Keys can be any field, or the special string 'common_stacktrace', which
   will use the event's kernel stacktrace as the key.  The keywords
   'keys' or 'key' can be used to specify keys, and the keywords
   'values', 'vals', or 'val' can be used to specify values.  Compound
@@ -54,7 +54,7 @@ Documentation written by Tom Zanussi
   'compatible' if the fields named in the trigger share the same
   number and type of fields and those fields also have the same names.
   Note that any two events always share the compatible 'hitcount' and
-  'stacktrace' fields and can therefore be combined using those
+  'common_stacktrace' fields and can therefore be combined using those
   fields, however pointless that may be.
 
   'hist' triggers add a 'hist' file to each event's subdirectory.
@@ -547,9 +547,9 @@ Extended error information
   the hist trigger display symbolic call_sites, we can have the hist
   trigger additionally display the complete set of kernel stack traces
   that led to each call_site.  To do that, we simply use the special
-  value 'stacktrace' for the key parameter::
+  value 'common_stacktrace' for the key parameter::
 
-    # echo 'hist:keys=stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \
+    # echo 'hist:keys=common_stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \
            /sys/kernel/tracing/events/kmem/kmalloc/trigger
 
   The above trigger will use the kernel stack trace in effect when an
@@ -561,9 +561,9 @@ Extended error information
   every callpath to a kmalloc for a kernel compile)::
 
     # cat /sys/kernel/tracing/events/kmem/kmalloc/hist
-    # trigger info: hist:keys=stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active]
+    # trigger info: hist:keys=common_stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active]
 
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc_track_caller+0x10b/0x1a0
          kmemdup+0x20/0x50
          hidraw_report_event+0x8a/0x120 [hid]
@@ -581,7 +581,7 @@ Extended error information
          cpu_startup_entry+0x315/0x3e0
          rest_init+0x7c/0x80
     } hitcount:          3  bytes_req:         21  bytes_alloc:         24
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc_track_caller+0x10b/0x1a0
          kmemdup+0x20/0x50
          hidraw_report_event+0x8a/0x120 [hid]
@@ -596,7 +596,7 @@ Extended error information
          do_IRQ+0x5a/0xf0
          ret_from_intr+0x0/0x30
     } hitcount:          3  bytes_req:         21  bytes_alloc:         24
-    { stacktrace:
+    { common_stacktrace:
          kmem_cache_alloc_trace+0xeb/0x150
          aa_alloc_task_context+0x27/0x40
          apparmor_cred_prepare+0x1f/0x50
@@ -608,7 +608,7 @@ Extended error information
     .
     .
     .
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc+0x11b/0x1b0
          i915_gem_execbuffer2+0x6c/0x2c0 [i915]
          drm_ioctl+0x349/0x670 [drm]
@@ -616,7 +616,7 @@ Extended error information
          SyS_ioctl+0x81/0xa0
          system_call_fastpath+0x12/0x6a
     } hitcount:      17726  bytes_req:   13944120  bytes_alloc:   19593808
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc+0x11b/0x1b0
          load_elf_phdrs+0x76/0xa0
          load_elf_binary+0x102/0x1650
@@ -625,7 +625,7 @@ Extended error information
          SyS_execve+0x3a/0x50
          return_from_execve+0x0/0x23
     } hitcount:      33348  bytes_req:   17152128  bytes_alloc:   20226048
-    { stacktrace:
+    { common_stacktrace:
          kmem_cache_alloc_trace+0xeb/0x150
          apparmor_file_alloc_security+0x27/0x40
          security_file_alloc+0x16/0x20
@@ -636,7 +636,7 @@ Extended error information
          SyS_open+0x1e/0x20
          system_call_fastpath+0x12/0x6a
     } hitcount:    4766422  bytes_req:    9532844  bytes_alloc:   38131376
-    { stacktrace:
+    { common_stacktrace:
          __kmalloc+0x11b/0x1b0
          seq_buf_alloc+0x1b/0x50
          seq_read+0x2cc/0x370
@@ -1026,7 +1026,7 @@ Extended error information
   First we set up an initially paused stacktrace trigger on the
   netif_receive_skb event::
 
-    # echo 'hist:key=stacktrace:vals=len:pause' > \
+    # echo 'hist:key=common_stacktrace:vals=len:pause' > \
            /sys/kernel/tracing/events/net/netif_receive_skb/trigger
 
   Next, we set up an 'enable_hist' trigger on the sched_process_exec
@@ -1060,9 +1060,9 @@ Extended error information
     $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz
 
     # cat /sys/kernel/tracing/events/net/netif_receive_skb/hist
-    # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused]
+    # trigger info: hist:keys=common_stacktrace:vals=len:sort=hitcount:size=2048 [paused]
 
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          netif_receive_skb_internal+0x23/0x90
@@ -1079,7 +1079,7 @@ Extended error information
          kthread+0xd2/0xf0
          ret_from_fork+0x42/0x70
     } hitcount:         85  len:      28884
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          netif_receive_skb_internal+0x23/0x90
@@ -1097,7 +1097,7 @@ Extended error information
          irq_thread+0x11f/0x150
          kthread+0xd2/0xf0
     } hitcount:         98  len:     664329
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          process_backlog+0xa8/0x150
@@ -1115,7 +1115,7 @@ Extended error information
          inet_sendmsg+0x64/0xa0
          sock_sendmsg+0x3d/0x50
     } hitcount:        115  len:      13030
-    { stacktrace:
+    { common_stacktrace:
          __netif_receive_skb_core+0x46d/0x990
          __netif_receive_skb+0x18/0x60
          netif_receive_skb_internal+0x23/0x90
@@ -1142,14 +1142,14 @@ Extended error information
   into the histogram.  In order to avoid having to set everything up
   again, we can just clear the histogram first::
 
-    # echo 'hist:key=stacktrace:vals=len:clear' >> \
+    # echo 'hist:key=common_stacktrace:vals=len:clear' >> \
            /sys/kernel/tracing/events/net/netif_receive_skb/trigger
 
   Just to verify that it is in fact cleared, here's what we now see in
   the hist file::
 
     # cat /sys/kernel/tracing/events/net/netif_receive_skb/hist
-    # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused]
+    # trigger info: hist:keys=common_stacktrace:vals=len:sort=hitcount:size=2048 [paused]
 
     Totals:
         Hits: 0
@@ -1485,12 +1485,12 @@ Extended error information
 
   And here's an example that shows how to combine histogram data from
   any two events even if they don't share any 'compatible' fields
-  other than 'hitcount' and 'stacktrace'.  These commands create a
+  other than 'hitcount' and 'common_stacktrace'.  These commands create a
   couple of triggers named 'bar' using those fields::
 
-    # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \
+    # echo 'hist:name=bar:key=common_stacktrace:val=hitcount' > \
            /sys/kernel/tracing/events/sched/sched_process_fork/trigger
-    # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \
+    # echo 'hist:name=bar:key=common_stacktrace:val=hitcount' > \
           /sys/kernel/tracing/events/net/netif_rx/trigger
 
   And displaying the output of either shows some interesting if
@@ -1501,16 +1501,16 @@ Extended error information
 
     # event histogram
     #
-    # trigger info: hist:name=bar:keys=stacktrace:vals=hitcount:sort=hitcount:size=2048 [active]
+    # trigger info: hist:name=bar:keys=common_stacktrace:vals=hitcount:sort=hitcount:size=2048 [active]
     #
 
-    { stacktrace:
+    { common_stacktrace:
              kernel_clone+0x18e/0x330
              kernel_thread+0x29/0x30
              kthreadd+0x154/0x1b0
              ret_from_fork+0x3f/0x70
     } hitcount:          1
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx_ni+0x20/0x70
              dev_loopback_xmit+0xaa/0xd0
@@ -1528,7 +1528,7 @@ Extended error information
              call_cpuidle+0x3b/0x60
              cpu_startup_entry+0x22d/0x310
     } hitcount:          1
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx_ni+0x20/0x70
              dev_loopback_xmit+0xaa/0xd0
@@ -1543,7 +1543,7 @@ Extended error information
              SyS_sendto+0xe/0x10
              entry_SYSCALL_64_fastpath+0x12/0x6a
     } hitcount:          2
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx+0x1c/0x60
              loopback_xmit+0x6c/0xb0
@@ -1561,7 +1561,7 @@ Extended error information
              sock_sendmsg+0x38/0x50
              ___sys_sendmsg+0x14e/0x270
     } hitcount:         76
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx+0x1c/0x60
              loopback_xmit+0x6c/0xb0
@@ -1579,7 +1579,7 @@ Extended error information
              sock_sendmsg+0x38/0x50
              ___sys_sendmsg+0x269/0x270
     } hitcount:         77
-    { stacktrace:
+    { common_stacktrace:
              netif_rx_internal+0xb2/0xd0
              netif_rx+0x1c/0x60
              loopback_xmit+0x6c/0xb0
@@ -1597,7 +1597,7 @@ Extended error information
              sock_sendmsg+0x38/0x50
              SYSC_sendto+0xef/0x170
     } hitcount:         88
-    { stacktrace:
+    { common_stacktrace:
              kernel_clone+0x18e/0x330
              SyS_clone+0x19/0x20
              entry_SYSCALL_64_fastpath+0x12/0x6a
@@ -1949,7 +1949,7 @@ uninterruptible state::
 
   # cd /sys/kernel/tracing
   # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
-  # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace  if prev_state == 2' >> events/sched/sched_switch/trigger
+  # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=common_stacktrace  if prev_state == 2' >> events/sched/sched_switch/trigger
   # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
   # echo 1 > events/synthetic/block_lat/enable
   # cat trace
index 176e8fc..4f7b23f 100644 (file)
@@ -363,7 +363,7 @@ Code  Seq#    Include File                                           Comments
 0xCC  00-0F  drivers/misc/ibmvmc.h                                   pseries VMC driver
 0xCD  01     linux/reiserfs_fs.h
 0xCE  01-02  uapi/linux/cxl_mem.h                                    Compute Express Link Memory Devices
-0xCF  02     fs/cifs/ioctl.c
+0xCF  02     fs/smb/client/cifs_ioctl.h
 0xDB  00-0F  drivers/char/mwave/mwavepub.h
 0xDD  00-3F                                                          ZFCP device driver see drivers/s390/scsi/
                                                                      <mailto:aherrman@de.ibm.com>
index 2a6606a..8fdb066 100644 (file)
@@ -956,7 +956,8 @@ F:  Documentation/networking/device_drivers/ethernet/amazon/ena.rst
 F:     drivers/net/ethernet/amazon/
 
 AMAZON RDMA EFA DRIVER
-M:     Gal Pressman <galpress@amazon.com>
+M:     Michael Margolin <mrgolin@amazon.com>
+R:     Gal Pressman <gal.pressman@linux.dev>
 R:     Yossi Leybovich <sleybo@amazon.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
@@ -2429,6 +2430,15 @@ X:       drivers/net/wireless/atmel/
 N:     at91
 N:     atmel
 
+ARM/MICROCHIP (ARM64) SoC support
+M:     Conor Dooley <conor@kernel.org>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
+M:     Claudiu Beznea <claudiu.beznea@microchip.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Supported
+T:     git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git
+F:     arch/arm64/boot/dts/microchip/
+
 ARM/Microchip Sparx5 SoC support
 M:     Lars Povlsen <lars.povlsen@microchip.com>
 M:     Steen Hegelund <Steen.Hegelund@microchip.com>
@@ -2436,8 +2446,7 @@ M:        Daniel Machon <daniel.machon@microchip.com>
 M:     UNGLinuxDriver@microchip.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
-T:     git git://github.com/microchip-ung/linux-upstream.git
-F:     arch/arm64/boot/dts/microchip/
+F:     arch/arm64/boot/dts/microchip/sparx*
 F:     drivers/net/ethernet/microchip/vcap/
 F:     drivers/pinctrl/pinctrl-microchip-sgpio.c
 N:     sparx5
@@ -3536,7 +3545,7 @@ F:        Documentation/filesystems/befs.rst
 F:     fs/befs/
 
 BFQ I/O SCHEDULER
-M:     Paolo Valente <paolo.valente@linaro.org>
+M:     Paolo Valente <paolo.valente@unimore.it>
 M:     Jens Axboe <axboe@kernel.dk>
 L:     linux-block@vger.kernel.org
 S:     Maintained
@@ -5130,7 +5139,7 @@ X:        drivers/clk/clkdev.c
 
 COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
 M:     Steve French <sfrench@samba.org>
-R:     Paulo Alcantara <pc@cjr.nz> (DFS, global name space)
+R:     Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
 R:     Ronnie Sahlberg <lsahlber@redhat.com> (directory leases, sparse files)
 R:     Shyam Prasad N <sprasad@microsoft.com> (multichannel)
 R:     Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
@@ -5140,8 +5149,8 @@ S:        Supported
 W:     https://wiki.samba.org/index.php/LinuxCIFS
 T:     git git://git.samba.org/sfrench/cifs-2.6.git
 F:     Documentation/admin-guide/cifs/
-F:     fs/cifs/
-F:     fs/smbfs_common/
+F:     fs/smb/client/
+F:     fs/smb/common/
 F:     include/uapi/linux/cifs
 
 COMPACTPCI HOTPLUG CORE
@@ -8153,6 +8162,7 @@ F:        include/linux/spi/spi-fsl-dspi.h
 
 FREESCALE ENETC ETHERNET DRIVERS
 M:     Claudiu Manoil <claudiu.manoil@nxp.com>
+M:     Vladimir Oltean <vladimir.oltean@nxp.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/freescale/enetc/
@@ -9334,7 +9344,7 @@ F:        include/linux/hisi_acc_qm.h
 
 HISILICON ROCE DRIVER
 M:     Haoyue Xu <xuhaoyue1@hisilicon.com>
-M:     Wenpeng Liang <liangwenpeng@huawei.com>
+M:     Junxian Huang <huangjunxian6@hisilicon.com>
 L:     linux-rdma@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt
@@ -11300,9 +11310,9 @@ R:      Tom Talpey <tom@talpey.com>
 L:     linux-cifs@vger.kernel.org
 S:     Maintained
 T:     git git://git.samba.org/ksmbd.git
-F:     Documentation/filesystems/cifs/ksmbd.rst
-F:     fs/ksmbd/
-F:     fs/smbfs_common/
+F:     Documentation/filesystems/smb/ksmbd.rst
+F:     fs/smb/common/
+F:     fs/smb/server/
 
 KERNEL UNIT TESTING FRAMEWORK (KUnit)
 M:     Brendan Higgins <brendanhiggins@google.com>
@@ -14926,6 +14936,7 @@ F:      drivers/ntb/hw/intel/
 
 NTFS FILESYSTEM
 M:     Anton Altaparmakov <anton@tuxera.com>
+R:     Namjae Jeon <linkinjeon@kernel.org>
 L:     linux-ntfs-dev@lists.sourceforge.net
 S:     Supported
 W:     http://www.tuxera.com/
@@ -18703,7 +18714,6 @@ F:      include/dt-bindings/clock/samsung,*.h
 F:     include/linux/clk/samsung.h
 
 SAMSUNG SPI DRIVERS
-M:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
 M:     Andi Shyti <andi.shyti@kernel.org>
 L:     linux-spi@vger.kernel.org
 L:     linux-samsung-soc@vger.kernel.org
index 3cd9bc2..836643e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 78555a6..7b7e6c2 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_pcie>;
        reset-gpio = <&gpio6 7 GPIO_ACTIVE_LOW>;
+       vpcie-supply = <&reg_pcie>;
        status = "okay";
 };
 
index 5882c75..32a6022 100644 (file)
@@ -8,6 +8,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/regulator/dlg,da9063-regulator.h>
 #include "imx6ull.dtsi"
 
 / {
 
                regulators {
                        vdd_soc_in_1v4: buck1 {
+                               regulator-allowed-modes = <DA9063_BUCK_MODE_SLEEP>; /* PFM */
                                regulator-always-on;
                                regulator-boot-on;
+                               regulator-initial-mode = <DA9063_BUCK_MODE_SLEEP>;
                                regulator-max-microvolt = <1400000>;
                                regulator-min-microvolt = <1400000>;
                                regulator-name = "vdd_soc_in_1v4";
                        };
 
                        vcc_3v3: buck2 {
+                               regulator-allowed-modes = <DA9063_BUCK_MODE_SYNC>; /* PWM */
                                regulator-always-on;
                                regulator-boot-on;
+                               regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
                                regulator-max-microvolt = <3300000>;
                                regulator-min-microvolt = <3300000>;
                                regulator-name = "vcc_3v3";
                         * the voltage is set to 1.5V.
                         */
                        vcc_ddr_1v35: buck3 {
+                               regulator-allowed-modes = <DA9063_BUCK_MODE_SYNC>; /* PWM */
                                regulator-always-on;
                                regulator-boot-on;
+                               regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
                                regulator-max-microvolt = <1500000>;
                                regulator-min-microvolt = <1500000>;
                                regulator-name = "vcc_ddr_1v35";
index 3b88209..ff1f9a1 100644 (file)
                reg = <0x2c0f0000 0x1000>;
                interrupts = <0 84 4>;
                cache-level = <2>;
+               cache-unified;
        };
 
        pmu {
index 0295780..7b41537 100644 (file)
@@ -59,6 +59,7 @@
                L2_0: l2-cache0 {
                        compatible = "cache";
                        cache-level = <2>;
+                       cache-unified;
                };
        };
 
index ef68f5a..afdf954 100644 (file)
@@ -72,6 +72,7 @@
                L2_0: l2-cache0 {
                        compatible = "cache";
                        cache-level = <2>;
+                       cache-unified;
                };
        };
 
index 796cd7d..7bdeb96 100644 (file)
@@ -58,6 +58,7 @@
                L2_0: l2-cache0 {
                        compatible = "cache";
                        cache-level = <2>;
+                       cache-unified;
                };
        };
 
index 2209c1a..e62a435 100644 (file)
@@ -171,6 +171,7 @@ conn_subsys: bus@5b000000 {
                        interrupt-names = "host", "peripheral", "otg", "wakeup";
                        phys = <&usb3_phy>;
                        phy-names = "cdns3,usb3-phy";
+                       cdns,on-chip-buff-size = /bits/ 16 <18>;
                        status = "disabled";
                };
        };
index 67072e6..cbd9d12 100644 (file)
                #address-cells = <1>;
                #size-cells = <0>;
 
-               ethphy: ethernet-phy@4 {
+               ethphy: ethernet-phy@4 { /* AR8033 or ADIN1300 */
                        compatible = "ethernet-phy-ieee802.3-c22";
                        reg = <4>;
                        reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
                        reset-assert-us = <10000>;
+                       /*
+                        * Deassert delay:
+                        * ADIN1300 requires 5ms.
+                        * AR8033   requires 1ms.
+                        */
+                       reset-deassert-us = <20000>;
                };
        };
 };
index bd84db5..8be8f09 100644 (file)
                                         <&clk IMX8MN_CLK_DISP_APB_ROOT>,
                                         <&clk IMX8MN_CLK_DISP_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
-                               assigned-clocks = <&clk IMX8MN_CLK_DISP_PIXEL_ROOT>,
-                                                 <&clk IMX8MN_CLK_DISP_AXI>,
-                                                 <&clk IMX8MN_CLK_DISP_APB>;
-                               assigned-clock-parents = <&clk IMX8MN_CLK_DISP_PIXEL>,
-                                                        <&clk IMX8MN_SYS_PLL2_1000M>,
-                                                        <&clk IMX8MN_SYS_PLL1_800M>;
-                               assigned-clock-rates = <594000000>, <500000000>, <200000000>;
                                interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
                                power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_LCDIF>;
                                status = "disabled";
                                clocks = <&clk IMX8MN_CLK_DSI_CORE>,
                                         <&clk IMX8MN_CLK_DSI_PHY_REF>;
                                clock-names = "bus_clk", "sclk_mipi";
-                               assigned-clocks = <&clk IMX8MN_CLK_DSI_CORE>,
-                                                 <&clk IMX8MN_CLK_DSI_PHY_REF>;
-                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>,
-                                                        <&clk IMX8MN_CLK_24M>;
-                               assigned-clock-rates = <266000000>, <24000000>;
-                               samsung,pll-clock-frequency = <24000000>;
                                interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
                                power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_MIPI_DSI>;
                                status = "disabled";
                                              "lcdif-axi", "lcdif-apb", "lcdif-pix",
                                              "dsi-pclk", "dsi-ref",
                                              "csi-aclk", "csi-pclk";
+                               assigned-clocks = <&clk IMX8MN_CLK_DSI_CORE>,
+                                                 <&clk IMX8MN_CLK_DSI_PHY_REF>,
+                                                 <&clk IMX8MN_CLK_DISP_PIXEL>,
+                                                 <&clk IMX8MN_CLK_DISP_AXI>,
+                                                 <&clk IMX8MN_CLK_DISP_APB>;
+                               assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>,
+                                                        <&clk IMX8MN_CLK_24M>,
+                                                        <&clk IMX8MN_VIDEO_PLL1_OUT>,
+                                                        <&clk IMX8MN_SYS_PLL2_1000M>,
+                                                        <&clk IMX8MN_SYS_PLL1_800M>;
+                               assigned-clock-rates = <266000000>,
+                                                      <24000000>,
+                                                      <594000000>,
+                                                      <500000000>,
+                                                      <200000000>;
                                #power-domain-cells = <1>;
                        };
 
index f813919..428c604 100644 (file)
                                         <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
                                         <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
-                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT>,
-                                                 <&clk IMX8MP_CLK_MEDIA_AXI>,
-                                                 <&clk IMX8MP_CLK_MEDIA_APB>;
-                               assigned-clock-parents = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>,
-                                                        <&clk IMX8MP_SYS_PLL2_1000M>,
-                                                        <&clk IMX8MP_SYS_PLL1_800M>;
-                               assigned-clock-rates = <594000000>, <500000000>, <200000000>;
                                interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
                                power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_1>;
                                status = "disabled";
                                         <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
                                         <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
-                               assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
-                                                 <&clk IMX8MP_VIDEO_PLL1>;
-                               assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>,
-                                                        <&clk IMX8MP_VIDEO_PLL1_REF_SEL>;
-                               assigned-clock-rates = <0>, <1039500000>;
                                power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_2>;
                                status = "disabled";
 
                                              "disp1", "disp2", "isp", "phy";
 
                                assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>,
-                                                 <&clk IMX8MP_CLK_MEDIA_APB>;
+                                                 <&clk IMX8MP_CLK_MEDIA_APB>,
+                                                 <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>,
+                                                 <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
+                                                 <&clk IMX8MP_VIDEO_PLL1>;
                                assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>,
-                                                        <&clk IMX8MP_SYS_PLL1_800M>;
-                               assigned-clock-rates = <500000000>, <200000000>;
-
+                                                        <&clk IMX8MP_SYS_PLL1_800M>,
+                                                        <&clk IMX8MP_VIDEO_PLL1_OUT>,
+                                                        <&clk IMX8MP_VIDEO_PLL1_OUT>;
+                               assigned-clock-rates = <500000000>, <200000000>,
+                                                      <0>, <0>, <1039500000>;
                                #power-domain-cells = <1>;
 
                                lvds_bridge: bridge@5c {
index 7264d78..9af769a 100644 (file)
        };
 };
 
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ext_io0>, <&pinctrl_hog0>, <&pinctrl_hog1>,
+                   <&pinctrl_lpspi2_cs2>;
+};
+
 /* Colibri SPI */
 &lpspi2 {
        status = "okay";
index 5f30c88..f895306 100644 (file)
@@ -48,8 +48,7 @@
                           <IMX8QXP_SAI0_TXFS_LSIO_GPIO0_IO28           0x20>,          /* SODIMM 101 */
                           <IMX8QXP_SAI0_RXD_LSIO_GPIO0_IO27            0x20>,          /* SODIMM  97 */
                           <IMX8QXP_ENET0_RGMII_RXC_LSIO_GPIO5_IO03     0x06000020>,    /* SODIMM  85 */
-                          <IMX8QXP_SAI0_TXC_LSIO_GPIO0_IO26            0x20>,          /* SODIMM  79 */
-                          <IMX8QXP_QSPI0A_DATA1_LSIO_GPIO3_IO10        0x06700041>;    /* SODIMM  45 */
+                          <IMX8QXP_SAI0_TXC_LSIO_GPIO0_IO26            0x20>;          /* SODIMM  79 */
        };
 
        pinctrl_uart1_forceoff: uart1forceoffgrp {
index 7cad791..49d105e 100644 (file)
 /* TODO VPU Encoder/Decoder */
 
 &iomuxc {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ext_io0>, <&pinctrl_hog0>, <&pinctrl_hog1>,
-                   <&pinctrl_hog2>, <&pinctrl_lpspi2_cs2>;
-
        /* On-module touch pen-down interrupt */
        pinctrl_ad7879_int: ad7879intgrp {
                fsl,pins = <IMX8QXP_MIPI_CSI0_I2C0_SCL_LSIO_GPIO3_IO05  0x21>;
        };
 
        pinctrl_hog1: hog1grp {
-               fsl,pins = <IMX8QXP_CSI_MCLK_LSIO_GPIO3_IO01                    0x20>,          /* SODIMM  75 */
-                          <IMX8QXP_QSPI0A_SCLK_LSIO_GPIO3_IO16                 0x20>;          /* SODIMM  93 */
+               fsl,pins = <IMX8QXP_QSPI0A_SCLK_LSIO_GPIO3_IO16                 0x20>;          /* SODIMM  93 */
        };
 
        pinctrl_hog2: hog2grp {
                fsl,pins = <IMX8QXP_SCU_BOOT_MODE3_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0x20>;
        };
 };
+
+/* Delete peripherals which are not present on SOC, but are defined in imx8-ss-*.dtsi */
+
+/delete-node/ &adc1;
+/delete-node/ &adc1_lpcg;
+/delete-node/ &dsp;
+/delete-node/ &dsp_lpcg;
index b9f6908..ba468b5 100644 (file)
@@ -858,11 +858,17 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
 }
 
 static inline void __user *
-get_sigframe(struct ksignal *ksig, size_t frame_size)
+get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size)
 {
        unsigned long usp = sigsp(rdusp(), ksig);
+       unsigned long gap = 0;
 
-       return (void __user *)((usp - frame_size) & -8UL);
+       if (CPU_IS_020_OR_030 && tregs->format == 0xb) {
+               /* USP is unreliable so use worst-case value */
+               gap = 256;
+       }
+
+       return (void __user *)((usp - gap - frame_size) & -8UL);
 }
 
 static int setup_frame(struct ksignal *ksig, sigset_t *set,
@@ -880,7 +886,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
        }
 
-       frame = get_sigframe(ksig, sizeof(*frame) + fsize);
+       frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize);
 
        if (fsize)
                err |= copy_to_user (frame + 1, regs + 1, fsize);
@@ -952,7 +958,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
        }
 
-       frame = get_sigframe(ksig, sizeof(*frame));
+       frame = get_sigframe(ksig, tregs, sizeof(*frame));
 
        if (fsize)
                err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
index c2f5498..675a866 100644 (file)
@@ -79,6 +79,7 @@ config MIPS
        select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_NMI
+       select HAVE_PATA_PLATFORM
        select HAVE_PERF_EVENTS
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
index 5ab0430..6a3c890 100644 (file)
@@ -30,6 +30,7 @@
  *
  */
 
+#include <linux/dma-map-ops.h> /* for dma_default_coherent */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -623,17 +624,18 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
                dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
 
        /*
-        * There is an errata on the Au1200/Au1550 parts that could result
-        * in "stale" data being DMA'ed. It has to do with the snoop logic on
-        * the cache eviction buffer.  DMA_NONCOHERENT is on by default for
-        * these parts. If it is fixed in the future, these dma_cache_inv will
-        * just be nothing more than empty macros. See io.h.
+        * There is an erratum on certain Au1200/Au1550 revisions that could
+        * result in "stale" data being DMA'ed. It has to do with the snoop
+        * logic on the cache eviction buffer.  dma_default_coherent is set
+        * to false on these parts.
         */
-       dma_cache_wback_inv((unsigned long)buf, nbytes);
+       if (!dma_default_coherent)
+               dma_cache_wback_inv(KSEG0ADDR(buf), nbytes);
        dp->dscr_cmd0 |= DSCR_CMD0_V;   /* Let it rip */
        wmb(); /* drain writebuffer */
        dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
        ctp->chan_ptr->ddma_dbell = 0;
+       wmb(); /* force doorbell write out to dma engine */
 
        /* Get next descriptor pointer. */
        ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
@@ -685,17 +687,18 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
                          dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1);
 #endif
        /*
-        * There is an errata on the Au1200/Au1550 parts that could result in
-        * "stale" data being DMA'ed. It has to do with the snoop logic on the
-        * cache eviction buffer.  DMA_NONCOHERENT is on by default for these
-        * parts. If it is fixed in the future, these dma_cache_inv will just
-        * be nothing more than empty macros. See io.h.
+        * There is an erratum on certain Au1200/Au1550 revisions that could
+        * result in "stale" data being DMA'ed. It has to do with the snoop
+        * logic on the cache eviction buffer.  dma_default_coherent is set
+        * to false on these parts.
         */
-       dma_cache_inv((unsigned long)buf, nbytes);
+       if (!dma_default_coherent)
+               dma_cache_inv(KSEG0ADDR(buf), nbytes);
        dp->dscr_cmd0 |= DSCR_CMD0_V;   /* Let it rip */
        wmb(); /* drain writebuffer */
        dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
        ctp->chan_ptr->ddma_dbell = 0;
+       wmb(); /* force doorbell write out to dma engine */
 
        /* Get next descriptor pointer. */
        ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
index 6d15a39..e79adcb 100644 (file)
@@ -1502,6 +1502,10 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
                        break;
                }
                break;
+       case PRID_IMP_NETLOGIC_AU13XX:
+               c->cputype = CPU_ALCHEMY;
+               __cpu_name[cpu] = "Au1300";
+               break;
        }
 }
 
@@ -1863,6 +1867,7 @@ void cpu_probe(void)
                cpu_probe_mips(c, cpu);
                break;
        case PRID_COMP_ALCHEMY:
+       case PRID_COMP_NETLOGIC:
                cpu_probe_alchemy(c, cpu);
                break;
        case PRID_COMP_SIBYTE:
index febdc55..c0e6513 100644 (file)
@@ -158,10 +158,6 @@ static unsigned long __init init_initrd(void)
                pr_err("initrd start must be page aligned\n");
                goto disable;
        }
-       if (initrd_start < PAGE_OFFSET) {
-               pr_err("initrd start < PAGE_OFFSET\n");
-               goto disable;
-       }
 
        /*
         * Sanitize initrd addresses. For example firmware
@@ -174,6 +170,11 @@ static unsigned long __init init_initrd(void)
        initrd_end = (unsigned long)__va(end);
        initrd_start = (unsigned long)__va(__pa(initrd_start));
 
+       if (initrd_start < PAGE_OFFSET) {
+               pr_err("initrd start < PAGE_OFFSET\n");
+               goto disable;
+       }
+
        ROOT_DEV = Root_RAM0;
        return PFN_UP(end);
 disable:
index 466a255..967bde6 100644 (file)
@@ -130,6 +130,10 @@ config PM
 config STACKTRACE_SUPPORT
        def_bool y
 
+config LOCKDEP_SUPPORT
+       bool
+       default y
+
 config ISA_DMA_API
        bool
 
index f66554c..3a059cb 100644 (file)
@@ -1 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
+#
+config LIGHTWEIGHT_SPINLOCK_CHECK
+       bool "Enable lightweight spinlock checks"
+       depends on SMP && !DEBUG_SPINLOCK
+       default y
+       help
+         Add checks with low performance impact to the spinlock functions
+         to catch memory overwrites at runtime. For more advanced
+         spinlock debugging you should choose the DEBUG_SPINLOCK option
+         which will detect unitialized spinlocks too.
+         If unsure say Y here.
index 0bdee67..c8b6928 100644 (file)
@@ -48,6 +48,10 @@ void flush_dcache_page(struct page *page);
 
 #define flush_dcache_mmap_lock(mapping)                xa_lock_irq(&mapping->i_pages)
 #define flush_dcache_mmap_unlock(mapping)      xa_unlock_irq(&mapping->i_pages)
+#define flush_dcache_mmap_lock_irqsave(mapping, flags)         \
+               xa_lock_irqsave(&mapping->i_pages, flags)
+#define flush_dcache_mmap_unlock_irqrestore(mapping, flags)    \
+               xa_unlock_irqrestore(&mapping->i_pages, flags)
 
 #define flush_icache_page(vma,page)    do {            \
        flush_kernel_dcache_page_addr(page_address(page)); \
index a6e5d66..edfcb98 100644 (file)
@@ -7,10 +7,26 @@
 #include <asm/processor.h>
 #include <asm/spinlock_types.h>
 
+#define SPINLOCK_BREAK_INSN    0x0000c006      /* break 6,6 */
+
+static inline void arch_spin_val_check(int lock_val)
+{
+       if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK))
+               asm volatile(   "andcm,= %0,%1,%%r0\n"
+                               ".word %2\n"
+               : : "r" (lock_val), "r" (__ARCH_SPIN_LOCK_UNLOCKED_VAL),
+                       "i" (SPINLOCK_BREAK_INSN));
+}
+
 static inline int arch_spin_is_locked(arch_spinlock_t *x)
 {
-       volatile unsigned int *a = __ldcw_align(x);
-       return READ_ONCE(*a) == 0;
+       volatile unsigned int *a;
+       int lock_val;
+
+       a = __ldcw_align(x);
+       lock_val = READ_ONCE(*a);
+       arch_spin_val_check(lock_val);
+       return (lock_val == 0);
 }
 
 static inline void arch_spin_lock(arch_spinlock_t *x)
@@ -18,9 +34,18 @@ static inline void arch_spin_lock(arch_spinlock_t *x)
        volatile unsigned int *a;
 
        a = __ldcw_align(x);
-       while (__ldcw(a) == 0)
+       do {
+               int lock_val_old;
+
+               lock_val_old = __ldcw(a);
+               arch_spin_val_check(lock_val_old);
+               if (lock_val_old)
+                       return; /* got lock */
+
+               /* wait until we should try to get lock again */
                while (*a == 0)
                        continue;
+       } while (1);
 }
 
 static inline void arch_spin_unlock(arch_spinlock_t *x)
@@ -29,15 +54,19 @@ static inline void arch_spin_unlock(arch_spinlock_t *x)
 
        a = __ldcw_align(x);
        /* Release with ordered store. */
-       __asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory");
+       __asm__ __volatile__("stw,ma %0,0(%1)"
+               : : "r"(__ARCH_SPIN_LOCK_UNLOCKED_VAL), "r"(a) : "memory");
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *x)
 {
        volatile unsigned int *a;
+       int lock_val;
 
        a = __ldcw_align(x);
-       return __ldcw(a) != 0;
+       lock_val = __ldcw(a);
+       arch_spin_val_check(lock_val);
+       return lock_val != 0;
 }
 
 /*
index ca39ee3..d659340 100644 (file)
@@ -2,13 +2,17 @@
 #ifndef __ASM_SPINLOCK_TYPES_H
 #define __ASM_SPINLOCK_TYPES_H
 
+#define __ARCH_SPIN_LOCK_UNLOCKED_VAL  0x1a46
+
 typedef struct {
 #ifdef CONFIG_PA20
        volatile unsigned int slock;
-# define __ARCH_SPIN_LOCK_UNLOCKED { 1 }
+# define __ARCH_SPIN_LOCK_UNLOCKED { __ARCH_SPIN_LOCK_UNLOCKED_VAL }
 #else
        volatile unsigned int lock[4];
-# define __ARCH_SPIN_LOCK_UNLOCKED     { { 1, 1, 1, 1 } }
+# define __ARCH_SPIN_LOCK_UNLOCKED     \
+       { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \
+           __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } }
 #endif
 } arch_spinlock_t;
 
index 66f5672..25c4d6c 100644 (file)
@@ -25,7 +25,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
 {
        struct alt_instr *entry;
        int index = 0, applied = 0;
-       int num_cpus = num_online_cpus();
+       int num_cpus = num_present_cpus();
        u16 cond_check;
 
        cond_check = ALT_COND_ALWAYS |
index 1d3b8bc..ca4a302 100644 (file)
@@ -399,6 +399,7 @@ void flush_dcache_page(struct page *page)
        unsigned long offset;
        unsigned long addr, old_addr = 0;
        unsigned long count = 0;
+       unsigned long flags;
        pgoff_t pgoff;
 
        if (mapping && !mapping_mapped(mapping)) {
@@ -420,7 +421,7 @@ void flush_dcache_page(struct page *page)
         * to flush one address here for them all to become coherent
         * on machines that support equivalent aliasing
         */
-       flush_dcache_mmap_lock(mapping);
+       flush_dcache_mmap_lock_irqsave(mapping, flags);
        vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
                offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
                addr = mpnt->vm_start + offset;
@@ -460,7 +461,7 @@ void flush_dcache_page(struct page *page)
                }
                WARN_ON(++count == 4096);
        }
-       flush_dcache_mmap_unlock(mapping);
+       flush_dcache_mmap_unlock_irqrestore(mapping, flags);
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
index ba87f79..71ed539 100644 (file)
@@ -446,11 +446,27 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr,
 void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
                enum dma_data_direction dir)
 {
+       /*
+        * fdc: The data cache line is written back to memory, if and only if
+        * it is dirty, and then invalidated from the data cache.
+        */
        flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
 }
 
 void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
                enum dma_data_direction dir)
 {
-       flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
+       unsigned long addr = (unsigned long) phys_to_virt(paddr);
+
+       switch (dir) {
+       case DMA_TO_DEVICE:
+       case DMA_BIDIRECTIONAL:
+               flush_kernel_dcache_range(addr, size);
+               return;
+       case DMA_FROM_DEVICE:
+               purge_kernel_dcache_range_asm(addr, addr + size);
+               return;
+       default:
+               BUG();
+       }
 }
index 97c6f87..24411ab 100644 (file)
@@ -122,13 +122,18 @@ void machine_power_off(void)
        /* It seems we have no way to power the system off via
         * software. The user has to press the button himself. */
 
-       printk(KERN_EMERG "System shut down completed.\n"
-              "Please power this system off now.");
+       printk("Power off or press RETURN to reboot.\n");
 
        /* prevent soft lockup/stalled CPU messages for endless loop. */
        rcu_sysrq_start();
        lockup_detector_soft_poweroff();
-       for (;;);
+       while (1) {
+               /* reboot if user presses RETURN key */
+               if (pdc_iodc_getc() == 13) {
+                       printk("Rebooting...\n");
+                       machine_restart(NULL);
+               }
+       }
 }
 
 void (*pm_power_off)(void);
index f9696fb..304eebd 100644 (file)
 #include <linux/kgdb.h>
 #include <linux/kprobes.h>
 
+#if defined(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)
+#include <asm/spinlock.h>
+#endif
+
 #include "../math-emu/math-emu.h"      /* for handle_fpe() */
 
 static void parisc_show_stack(struct task_struct *task,
@@ -291,24 +295,30 @@ static void handle_break(struct pt_regs *regs)
        }
 
 #ifdef CONFIG_KPROBES
-       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN)) {
+       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN && !user_mode(regs))) {
                parisc_kprobe_break_handler(regs);
                return;
        }
-       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN2)) {
+       if (unlikely(iir == PARISC_KPROBES_BREAK_INSN2 && !user_mode(regs))) {
                parisc_kprobe_ss_handler(regs);
                return;
        }
 #endif
 
 #ifdef CONFIG_KGDB
-       if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
-               iir == PARISC_KGDB_BREAK_INSN)) {
+       if (unlikely((iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
+               iir == PARISC_KGDB_BREAK_INSN)) && !user_mode(regs)) {
                kgdb_handle_exception(9, SIGTRAP, 0, regs);
                return;
        }
 #endif
 
+#ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK
+        if ((iir == SPINLOCK_BREAK_INSN) && !user_mode(regs)) {
+               die_if_kernel("Spinlock was trashed", regs, 1);
+       }
+#endif
+
        if (unlikely(iir != GDB_BREAK_INSN))
                parisc_printk_ratelimited(0, regs,
                        KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
index 539d1f0..bff5820 100644 (file)
@@ -906,11 +906,17 @@ config DATA_SHIFT
 
 config ARCH_FORCE_MAX_ORDER
        int "Order of maximal physically contiguous allocations"
+       range 7 8 if PPC64 && PPC_64K_PAGES
        default "8" if PPC64 && PPC_64K_PAGES
+       range 12 12 if PPC64 && !PPC_64K_PAGES
        default "12" if PPC64 && !PPC_64K_PAGES
+       range 8 10 if PPC32 && PPC_16K_PAGES
        default "8" if PPC32 && PPC_16K_PAGES
+       range 6 10 if PPC32 && PPC_64K_PAGES
        default "6" if PPC32 && PPC_64K_PAGES
+       range 4 10 if PPC32 && PPC_256K_PAGES
        default "4" if PPC32 && PPC_256K_PAGES
+       range 10 10
        default "10"
        help
          The kernel page allocator limits the size of maximal physically
index 7c1abc5..9556dac 100644 (file)
        .octa 0x3F893781E95FE1576CDA64D2BA0CB204
 
 #ifdef CONFIG_AS_GFNI
-.section       .rodata.cst8, "aM", @progbits, 8
-.align 8
 /* AES affine: */
 #define tf_aff_const BV8(1, 1, 0, 0, 0, 1, 1, 0)
 .Ltf_aff_bitmatrix:
index 070cc4e..89b9c1c 100644 (file)
@@ -4074,7 +4074,7 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
        if (x86_pmu.intel_cap.pebs_baseline) {
                arr[(*nr)++] = (struct perf_guest_switch_msr){
                        .msr = MSR_PEBS_DATA_CFG,
-                       .host = cpuc->pebs_data_cfg,
+                       .host = cpuc->active_pebs_data_cfg,
                        .guest = kvm_pmu->pebs_data_cfg,
                };
        }
index fa9b209..d49e90d 100644 (file)
@@ -6150,6 +6150,7 @@ static struct intel_uncore_type spr_uncore_mdf = {
 };
 
 #define UNCORE_SPR_NUM_UNCORE_TYPES            12
+#define UNCORE_SPR_CHA                         0
 #define UNCORE_SPR_IIO                         1
 #define UNCORE_SPR_IMC                         6
 #define UNCORE_SPR_UPI                         8
@@ -6460,12 +6461,22 @@ static int uncore_type_max_boxes(struct intel_uncore_type **types,
        return max + 1;
 }
 
+#define SPR_MSR_UNC_CBO_CONFIG         0x2FFE
+
 void spr_uncore_cpu_init(void)
 {
+       struct intel_uncore_type *type;
+       u64 num_cbo;
+
        uncore_msr_uncores = uncore_get_uncores(UNCORE_ACCESS_MSR,
                                                UNCORE_SPR_MSR_EXTRA_UNCORES,
                                                spr_msr_uncores);
 
+       type = uncore_find_type_by_id(uncore_msr_uncores, UNCORE_SPR_CHA);
+       if (type) {
+               rdmsrl(SPR_MSR_UNC_CBO_CONFIG, num_cbo);
+               type->num_boxes = num_cbo;
+       }
        spr_uncore_iio_free_running.num_boxes = uncore_type_max_boxes(uncore_msr_uncores, UNCORE_SPR_IIO);
 }
 
index c2d6cd7..78fcde7 100644 (file)
@@ -39,7 +39,7 @@ extern void fpu_flush_thread(void);
 static inline void switch_fpu_prepare(struct fpu *old_fpu, int cpu)
 {
        if (cpu_feature_enabled(X86_FEATURE_FPU) &&
-           !(current->flags & (PF_KTHREAD | PF_IO_WORKER))) {
+           !(current->flags & (PF_KTHREAD | PF_USER_WORKER))) {
                save_fpregs_to_fpstate(old_fpu);
                /*
                 * The save operation preserved register state, so the
index 5e868b6..0270925 100644 (file)
@@ -79,7 +79,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
         * initial apic id, which also represents 32-bit extended x2apic id.
         */
        c->initial_apicid = edx;
-       smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
 #endif
        return 0;
 }
@@ -109,7 +109,8 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
         */
        cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
        c->initial_apicid = edx;
-       core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
+       smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
        core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
        die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
        pkg_mask_width = die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
index 0bf6779..f18ca44 100644 (file)
@@ -195,7 +195,6 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
        printk("%sCall Trace:\n", log_lvl);
 
        unwind_start(&state, task, regs, stack);
-       stack = stack ? : get_stack_pointer(task, regs);
        regs = unwind_get_entry_regs(&state, &partial);
 
        /*
@@ -214,9 +213,13 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
         * - hardirq stack
         * - entry stack
         */
-       for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
+       for (stack = stack ?: get_stack_pointer(task, regs);
+            stack;
+            stack = stack_info.next_sp) {
                const char *stack_name;
 
+               stack = PTR_ALIGN(stack, sizeof(long));
+
                if (get_stack_info(stack, task, &stack_info, &visit_mask)) {
                        /*
                         * We weren't on a valid stack.  It's possible that
index 9fcfa5c..af5cbdd 100644 (file)
@@ -57,7 +57,7 @@ static inline void fpregs_restore_userregs(void)
        struct fpu *fpu = &current->thread.fpu;
        int cpu = smp_processor_id();
 
-       if (WARN_ON_ONCE(current->flags & (PF_KTHREAD | PF_IO_WORKER)))
+       if (WARN_ON_ONCE(current->flags & (PF_KTHREAD | PF_USER_WORKER)))
                return;
 
        if (!fpregs_state_valid(fpu, cpu)) {
index caf3348..1015af1 100644 (file)
@@ -426,7 +426,7 @@ void kernel_fpu_begin_mask(unsigned int kfpu_mask)
 
        this_cpu_write(in_kernel_fpu, true);
 
-       if (!(current->flags & (PF_KTHREAD | PF_IO_WORKER)) &&
+       if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER)) &&
            !test_thread_flag(TIF_NEED_FPU_LOAD)) {
                set_thread_flag(TIF_NEED_FPU_LOAD);
                save_fpregs_to_fpstate(&current->thread.fpu);
index 4fc5c2d..01c5de4 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/cpufeatures.h>
+#include <asm/alternative.h>
 #include <asm/asm.h>
 #include <asm/export.h>
 
@@ -29,7 +31,7 @@
  */
 SYM_FUNC_START(rep_movs_alternative)
        cmpq $64,%rcx
-       jae .Lunrolled
+       jae .Llarge
 
        cmp $8,%ecx
        jae .Lword
@@ -65,6 +67,12 @@ SYM_FUNC_START(rep_movs_alternative)
        _ASM_EXTABLE_UA( 2b, .Lcopy_user_tail)
        _ASM_EXTABLE_UA( 3b, .Lcopy_user_tail)
 
+.Llarge:
+0:     ALTERNATIVE "jmp .Lunrolled", "rep movsb", X86_FEATURE_ERMS
+1:     RET
+
+        _ASM_EXTABLE_UA( 0b, 1b)
+
        .p2align 4
 .Lunrolled:
 10:    movq (%rsi),%r8
index 3cdac0f..8192452 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/sched/task.h>
 
 #include <asm/set_memory.h>
+#include <asm/cpu_device_id.h>
 #include <asm/e820/api.h>
 #include <asm/init.h>
 #include <asm/page.h>
@@ -261,6 +262,24 @@ static void __init probe_page_size_mask(void)
        }
 }
 
+#define INTEL_MATCH(_model) { .vendor  = X86_VENDOR_INTEL,     \
+                             .family  = 6,                     \
+                             .model = _model,                  \
+                           }
+/*
+ * INVLPG may not properly flush Global entries
+ * on these CPUs when PCIDs are enabled.
+ */
+static const struct x86_cpu_id invlpg_miss_ids[] = {
+       INTEL_MATCH(INTEL_FAM6_ALDERLAKE   ),
+       INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ),
+       INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ),
+       INTEL_MATCH(INTEL_FAM6_RAPTORLAKE  ),
+       INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P),
+       INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S),
+       {}
+};
+
 static void setup_pcid(void)
 {
        if (!IS_ENABLED(CONFIG_X86_64))
@@ -269,6 +288,12 @@ static void setup_pcid(void)
        if (!boot_cpu_has(X86_FEATURE_PCID))
                return;
 
+       if (x86_match_cpu(invlpg_miss_ids)) {
+               pr_info("Incomplete global flushes, disabling PCID");
+               setup_clear_cpu_cap(X86_FEATURE_PCID);
+               return;
+       }
+
        if (boot_cpu_has(X86_FEATURE_PGE)) {
                /*
                 * This can't be cr4_set_bits_and_update_boot() -- the
index 8babce7..014c508 100644 (file)
@@ -198,7 +198,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                i++;
        }
        kfree(v);
-       return 0;
+       return msi_device_populate_sysfs(&dev->dev);
 
 error:
        if (ret == -ENOSYS)
@@ -254,7 +254,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                dev_dbg(&dev->dev,
                        "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
        }
-       return 0;
+       return msi_device_populate_sysfs(&dev->dev);
 
 error:
        dev_err(&dev->dev, "Failed to create MSI%s! ret=%d!\n",
@@ -346,7 +346,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                if (ret < 0)
                        goto out;
        }
-       ret = 0;
+       ret = msi_device_populate_sysfs(&dev->dev);
 out:
        return ret;
 }
@@ -394,6 +394,8 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
                        xen_destroy_irq(msidesc->irq + i);
                msidesc->irq = 0;
        }
+
+       msi_device_destroy_sysfs(&dev->dev);
 }
 
 static void xen_pv_teardown_msi_irqs(struct pci_dev *dev)
index 876d5df..5c01d7e 100644 (file)
@@ -343,7 +343,19 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        struct rt_sigframe *frame;
        int err = 0, sig = ksig->sig;
        unsigned long sp, ra, tp, ps;
+       unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
+       unsigned long handler_fdpic_GOT = 0;
        unsigned int base;
+       bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
+               (current->personality & FDPIC_FUNCPTRS);
+
+       if (fdpic) {
+               unsigned long __user *fdpic_func_desc =
+                       (unsigned long __user *)handler;
+               if (__get_user(handler, &fdpic_func_desc[0]) ||
+                   __get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
+                       return -EFAULT;
+       }
 
        sp = regs->areg[1];
 
@@ -373,20 +385,26 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
        if (ksig->ka.sa.sa_flags & SA_RESTORER) {
-               ra = (unsigned long)ksig->ka.sa.sa_restorer;
+               if (fdpic) {
+                       unsigned long __user *fdpic_func_desc =
+                               (unsigned long __user *)ksig->ka.sa.sa_restorer;
+
+                       err |= __get_user(ra, fdpic_func_desc);
+               } else {
+                       ra = (unsigned long)ksig->ka.sa.sa_restorer;
+               }
        } else {
 
                /* Create sys_rt_sigreturn syscall in stack frame */
 
                err |= gen_return_code(frame->retcode);
-
-               if (err) {
-                       return -EFAULT;
-               }
                ra = (unsigned long) frame->retcode;
        }
 
-       /* 
+       if (err)
+               return -EFAULT;
+
+       /*
         * Create signal handler execution context.
         * Return context not modified until this point.
         */
@@ -394,8 +412,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        /* Set up registers for signal handler; preserve the threadptr */
        tp = regs->threadptr;
        ps = regs->ps;
-       start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
-                    (unsigned long) frame);
+       start_thread(regs, handler, (unsigned long)frame);
 
        /* Set up a stack frame for a call4 if userspace uses windowed ABI */
        if (ps & PS_WOE_MASK) {
@@ -413,6 +430,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
        regs->areg[base + 4] = (unsigned long) &frame->uc;
        regs->threadptr = tp;
        regs->ps = ps;
+       if (fdpic)
+               regs->areg[base + 11] = handler_fdpic_GOT;
 
        pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n",
                 current->comm, current->pid, sig, frame, regs->pc);
index 2a31b1a..17a7ef8 100644 (file)
@@ -56,6 +56,8 @@ EXPORT_SYMBOL(empty_zero_page);
  */
 extern long long __ashrdi3(long long, int);
 extern long long __ashldi3(long long, int);
+extern long long __bswapdi2(long long);
+extern int __bswapsi2(int);
 extern long long __lshrdi3(long long, int);
 extern int __divsi3(int, int);
 extern int __modsi3(int, int);
@@ -66,6 +68,8 @@ extern unsigned long long __umulsidi3(unsigned int, unsigned int);
 
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__bswapdi2);
+EXPORT_SYMBOL(__bswapsi2);
 EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__divsi3);
 EXPORT_SYMBOL(__modsi3);
index 7ecef05..c9c2614 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 lib-y  += memcopy.o memset.o checksum.o \
-          ashldi3.o ashrdi3.o lshrdi3.o \
+          ashldi3.o ashrdi3.o bswapdi2.o bswapsi2.o lshrdi3.o \
           divsi3.o udivsi3.o modsi3.o umodsi3.o mulsi3.o umulsidi3.o \
           usercopy.o strncpy_user.o strnlen_user.o
 lib-$(CONFIG_PCI) += pci-auto.o
diff --git a/arch/xtensa/lib/bswapdi2.S b/arch/xtensa/lib/bswapdi2.S
new file mode 100644 (file)
index 0000000..d8e52e0
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/core.h>
+
+ENTRY(__bswapdi2)
+
+       abi_entry_default
+       ssai    8
+       srli    a4, a2, 16
+       src     a4, a4, a2
+       src     a4, a4, a4
+       src     a4, a2, a4
+       srli    a2, a3, 16
+       src     a2, a2, a3
+       src     a2, a2, a2
+       src     a2, a3, a2
+       mov     a3, a4
+       abi_ret_default
+
+ENDPROC(__bswapdi2)
diff --git a/arch/xtensa/lib/bswapsi2.S b/arch/xtensa/lib/bswapsi2.S
new file mode 100644 (file)
index 0000000..9c1de13
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/core.h>
+
+ENTRY(__bswapsi2)
+
+       abi_entry_default
+       ssai    8
+       srli    a3, a2, 16
+       src     a3, a3, a2
+       src     a3, a3, a3
+       src     a2, a2, a3
+       abi_ret_default
+
+ENDPROC(__bswapsi2)
index 00c7433..1da77e7 100644 (file)
@@ -520,7 +520,7 @@ static inline int bio_check_eod(struct bio *bio)
        sector_t maxsector = bdev_nr_sectors(bio->bi_bdev);
        unsigned int nr_sectors = bio_sectors(bio);
 
-       if (nr_sectors && maxsector &&
+       if (nr_sectors &&
            (nr_sectors > maxsector ||
             bio->bi_iter.bi_sector > maxsector - nr_sectors)) {
                pr_info_ratelimited("%s: attempt to access beyond end of device\n"
index 04c55f1..46eed2e 100644 (file)
@@ -248,7 +248,7 @@ static struct bio *blk_rq_map_bio_alloc(struct request *rq,
 {
        struct bio *bio;
 
-       if (rq->cmd_flags & REQ_ALLOC_CACHE) {
+       if (rq->cmd_flags & REQ_ALLOC_CACHE && (nr_vecs <= BIO_INLINE_VECS)) {
                bio = bio_alloc_bioset(NULL, nr_vecs, rq->cmd_flags, gfp_mask,
                                        &fs_bio_set);
                if (!bio)
index d6af9d4..dfd81ca 100644 (file)
@@ -39,16 +39,20 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
 {
        unsigned int users;
 
+       /*
+        * calling test_bit() prior to test_and_set_bit() is intentional,
+        * it avoids dirtying the cacheline if the queue is already active.
+        */
        if (blk_mq_is_shared_tags(hctx->flags)) {
                struct request_queue *q = hctx->queue;
 
-               if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
+               if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) ||
+                   test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
                        return;
-               set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags);
        } else {
-               if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
+               if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) ||
+                   test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
                        return;
-               set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state);
        }
 
        users = atomic_inc_return(&hctx->tags->active_queues);
index e49a486..9ec2a2f 100644 (file)
@@ -730,14 +730,16 @@ void wbt_enable_default(struct gendisk *disk)
 {
        struct request_queue *q = disk->queue;
        struct rq_qos *rqos;
-       bool disable_flag = q->elevator &&
-                   test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags);
+       bool enable = IS_ENABLED(CONFIG_BLK_WBT_MQ);
+
+       if (q->elevator &&
+           test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags))
+               enable = false;
 
        /* Throttling already enabled? */
        rqos = wbt_rq_qos(q);
        if (rqos) {
-               if (!disable_flag &&
-                   RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
+               if (enable && RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
                        RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
                return;
        }
@@ -746,7 +748,7 @@ void wbt_enable_default(struct gendisk *disk)
        if (!blk_queue_registered(q))
                return;
 
-       if (queue_is_mq(q) && !disable_flag)
+       if (queue_is_mq(q) && enable)
                wbt_init(disk);
 }
 EXPORT_SYMBOL_GPL(wbt_enable_default);
index 9f216eb..5c57f7b 100644 (file)
@@ -997,14 +997,34 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
        struct xfer_queue_elem elem;
        struct wire_msg *out_buf;
        struct wrapper_msg *w;
+       long ret = -EAGAIN;
+       int xfer_count = 0;
        int retry_count;
-       long ret;
 
        if (qdev->in_reset) {
                mutex_unlock(&qdev->cntl_mutex);
                return ERR_PTR(-ENODEV);
        }
 
+       /* Attempt to avoid a partial commit of a message */
+       list_for_each_entry(w, &wrappers->list, list)
+               xfer_count++;
+
+       for (retry_count = 0; retry_count < QAIC_MHI_RETRY_MAX; retry_count++) {
+               if (xfer_count <= mhi_get_free_desc_count(qdev->cntl_ch, DMA_TO_DEVICE)) {
+                       ret = 0;
+                       break;
+               }
+               msleep_interruptible(QAIC_MHI_RETRY_WAIT_MS);
+               if (signal_pending(current))
+                       break;
+       }
+
+       if (ret) {
+               mutex_unlock(&qdev->cntl_mutex);
+               return ERR_PTR(ret);
+       }
+
        elem.seq_num = seq_num;
        elem.buf = NULL;
        init_completion(&elem.xfer_done);
@@ -1038,16 +1058,9 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
        list_for_each_entry(w, &wrappers->list, list) {
                kref_get(&w->ref_count);
                retry_count = 0;
-retry:
                ret = mhi_queue_buf(qdev->cntl_ch, DMA_TO_DEVICE, &w->msg, w->len,
                                    list_is_last(&w->list, &wrappers->list) ? MHI_EOT : MHI_CHAIN);
                if (ret) {
-                       if (ret == -EAGAIN && retry_count++ < QAIC_MHI_RETRY_MAX) {
-                               msleep_interruptible(QAIC_MHI_RETRY_WAIT_MS);
-                               if (!signal_pending(current))
-                                       goto retry;
-                       }
-
                        qdev->cntl_lost_buf = true;
                        kref_put(&w->ref_count, free_wrapper);
                        mutex_unlock(&qdev->cntl_mutex);
@@ -1249,7 +1262,7 @@ dma_cont_failed:
 
 int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       struct qaic_manage_msg *user_msg;
+       struct qaic_manage_msg *user_msg = data;
        struct qaic_device *qdev;
        struct manage_msg *msg;
        struct qaic_user *usr;
@@ -1258,6 +1271,9 @@ int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_
        int usr_rcu_id;
        int ret;
 
+       if (user_msg->len > QAIC_MANAGE_MAX_MSG_LENGTH)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
 
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
@@ -1275,13 +1291,6 @@ int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_
                return -ENODEV;
        }
 
-       user_msg = data;
-
-       if (user_msg->len > QAIC_MANAGE_MAX_MSG_LENGTH) {
-               ret = -EINVAL;
-               goto out;
-       }
-
        msg = kzalloc(QAIC_MANAGE_MAX_MSG_LENGTH + sizeof(*msg), GFP_KERNEL);
        if (!msg) {
                ret = -ENOMEM;
index c0a574c..e42c1f9 100644 (file)
@@ -591,7 +591,7 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc
        struct qaic_bo *bo = to_qaic_bo(obj);
        unsigned long offset = 0;
        struct scatterlist *sg;
-       int ret;
+       int ret = 0;
 
        if (obj->import_attach)
                return -EINVAL;
@@ -663,6 +663,10 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
        if (args->pad)
                return -EINVAL;
 
+       size = PAGE_ALIGN(args->size);
+       if (size == 0)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
        if (!usr->qddev) {
@@ -677,12 +681,6 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi
                goto unlock_dev_srcu;
        }
 
-       size = PAGE_ALIGN(args->size);
-       if (size == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        bo = qaic_alloc_init_bo();
        if (IS_ERR(bo)) {
                ret = PTR_ERR(bo);
@@ -926,8 +924,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 {
        struct qaic_attach_slice_entry *slice_ent;
        struct qaic_attach_slice *args = data;
+       int rcu_id, usr_rcu_id, qdev_rcu_id;
        struct dma_bridge_chan  *dbc;
-       int usr_rcu_id, qdev_rcu_id;
        struct drm_gem_object *obj;
        struct qaic_device *qdev;
        unsigned long arg_size;
@@ -936,6 +934,22 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
        struct qaic_bo *bo;
        int ret;
 
+       if (args->hdr.count == 0)
+               return -EINVAL;
+
+       arg_size = args->hdr.count * sizeof(*slice_ent);
+       if (arg_size / args->hdr.count != sizeof(*slice_ent))
+               return -EINVAL;
+
+       if (args->hdr.size == 0)
+               return -EINVAL;
+
+       if (!(args->hdr.dir == DMA_TO_DEVICE || args->hdr.dir == DMA_FROM_DEVICE))
+               return -EINVAL;
+
+       if (args->data == 0)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
        if (!usr->qddev) {
@@ -950,43 +964,11 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
                goto unlock_dev_srcu;
        }
 
-       if (args->hdr.count == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       arg_size = args->hdr.count * sizeof(*slice_ent);
-       if (arg_size / args->hdr.count != sizeof(*slice_ent)) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        if (args->hdr.dbc_id >= qdev->num_dbc) {
                ret = -EINVAL;
                goto unlock_dev_srcu;
        }
 
-       if (args->hdr.size == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       if (!(args->hdr.dir == DMA_TO_DEVICE  || args->hdr.dir == DMA_FROM_DEVICE)) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       dbc = &qdev->dbc[args->hdr.dbc_id];
-       if (dbc->usr != usr) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
-       if (args->data == 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        user_data = u64_to_user_ptr(args->data);
 
        slice_ent = kzalloc(arg_size, GFP_KERNEL);
@@ -1013,9 +995,21 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 
        bo = to_qaic_bo(obj);
 
+       if (bo->sliced) {
+               ret = -EINVAL;
+               goto put_bo;
+       }
+
+       dbc = &qdev->dbc[args->hdr.dbc_id];
+       rcu_id = srcu_read_lock(&dbc->ch_lock);
+       if (dbc->usr != usr) {
+               ret = -EINVAL;
+               goto unlock_ch_srcu;
+       }
+
        ret = qaic_prepare_bo(qdev, bo, &args->hdr);
        if (ret)
-               goto put_bo;
+               goto unlock_ch_srcu;
 
        ret = qaic_attach_slicing_bo(qdev, bo, &args->hdr, slice_ent);
        if (ret)
@@ -1025,6 +1019,7 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
                dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, args->hdr.dir);
 
        bo->dbc = dbc;
+       srcu_read_unlock(&dbc->ch_lock, rcu_id);
        drm_gem_object_put(obj);
        srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id);
        srcu_read_unlock(&usr->qddev_lock, usr_rcu_id);
@@ -1033,6 +1028,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi
 
 unprepare_bo:
        qaic_unprepare_bo(qdev, bo);
+unlock_ch_srcu:
+       srcu_read_unlock(&dbc->ch_lock, rcu_id);
 put_bo:
        drm_gem_object_put(obj);
 free_slice_ent:
@@ -1316,7 +1313,6 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr
        received_ts = ktime_get_ns();
 
        size = is_partial ? sizeof(*pexec) : sizeof(*exec);
-
        n = (unsigned long)size * args->hdr.count;
        if (args->hdr.count == 0 || n / args->hdr.count != size)
                return -EINVAL;
@@ -1665,6 +1661,9 @@ int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file
        int rcu_id;
        int ret;
 
+       if (args->pad != 0)
+               return -EINVAL;
+
        usr = file_priv->driver_priv;
        usr_rcu_id = srcu_read_lock(&usr->qddev_lock);
        if (!usr->qddev) {
@@ -1679,11 +1678,6 @@ int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file
                goto unlock_dev_srcu;
        }
 
-       if (args->pad != 0) {
-               ret = -EINVAL;
-               goto unlock_dev_srcu;
-       }
-
        if (args->dbc_id >= qdev->num_dbc) {
                ret = -EINVAL;
                goto unlock_dev_srcu;
@@ -1855,6 +1849,11 @@ void wakeup_dbc(struct qaic_device *qdev, u32 dbc_id)
        dbc->usr = NULL;
        empty_xfer_list(qdev, dbc);
        synchronize_srcu(&dbc->ch_lock);
+       /*
+        * Threads holding channel lock, may add more elements in the xfer_list.
+        * Flush out these elements from xfer_list.
+        */
+       empty_xfer_list(qdev, dbc);
 }
 
 void release_dbc(struct qaic_device *qdev, u32 dbc_id)
index ff80eb5..2d0828d 100644 (file)
@@ -262,8 +262,8 @@ static void qaic_destroy_drm_device(struct qaic_device *qdev, s32 partition_id)
 
 static int qaic_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
 {
+       u16 major = -1, minor = -1;
        struct qaic_device *qdev;
-       u16 major, minor;
        int ret;
 
        /*
index fb56bfc..8fb7672 100644 (file)
@@ -1934,24 +1934,23 @@ static void binder_deferred_fd_close(int fd)
 static void binder_transaction_buffer_release(struct binder_proc *proc,
                                              struct binder_thread *thread,
                                              struct binder_buffer *buffer,
-                                             binder_size_t failed_at,
+                                             binder_size_t off_end_offset,
                                              bool is_failure)
 {
        int debug_id = buffer->debug_id;
-       binder_size_t off_start_offset, buffer_offset, off_end_offset;
+       binder_size_t off_start_offset, buffer_offset;
 
        binder_debug(BINDER_DEBUG_TRANSACTION,
                     "%d buffer release %d, size %zd-%zd, failed at %llx\n",
                     proc->pid, buffer->debug_id,
                     buffer->data_size, buffer->offsets_size,
-                    (unsigned long long)failed_at);
+                    (unsigned long long)off_end_offset);
 
        if (buffer->target_node)
                binder_dec_node(buffer->target_node, 1, 0);
 
        off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
-       off_end_offset = is_failure && failed_at ? failed_at :
-                               off_start_offset + buffer->offsets_size;
+
        for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
             buffer_offset += sizeof(binder_size_t)) {
                struct binder_object_header *hdr;
@@ -2111,6 +2110,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
        }
 }
 
+/* Clean up all the objects in the buffer */
+static inline void binder_release_entire_buffer(struct binder_proc *proc,
+                                               struct binder_thread *thread,
+                                               struct binder_buffer *buffer,
+                                               bool is_failure)
+{
+       binder_size_t off_end_offset;
+
+       off_end_offset = ALIGN(buffer->data_size, sizeof(void *));
+       off_end_offset += buffer->offsets_size;
+
+       binder_transaction_buffer_release(proc, thread, buffer,
+                                         off_end_offset, is_failure);
+}
+
 static int binder_translate_binder(struct flat_binder_object *fp,
                                   struct binder_transaction *t,
                                   struct binder_thread *thread)
@@ -2806,7 +2820,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
                t_outdated->buffer = NULL;
                buffer->transaction = NULL;
                trace_binder_transaction_update_buffer_release(buffer);
-               binder_transaction_buffer_release(proc, NULL, buffer, 0, 0);
+               binder_release_entire_buffer(proc, NULL, buffer, false);
                binder_alloc_free_buf(&proc->alloc, buffer);
                kfree(t_outdated);
                binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -3775,7 +3789,7 @@ binder_free_buf(struct binder_proc *proc,
                binder_node_inner_unlock(buf_node);
        }
        trace_binder_transaction_buffer_release(buffer);
-       binder_transaction_buffer_release(proc, thread, buffer, 0, is_failure);
+       binder_release_entire_buffer(proc, thread, buffer, is_failure);
        binder_alloc_free_buf(&proc->alloc, buffer);
 }
 
index 55a3c3c..662a2a2 100644 (file)
@@ -212,8 +212,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
                mm = alloc->mm;
 
        if (mm) {
-               mmap_read_lock(mm);
-               vma = vma_lookup(mm, alloc->vma_addr);
+               mmap_write_lock(mm);
+               vma = alloc->vma;
        }
 
        if (!vma && need_mm) {
@@ -270,7 +270,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
                trace_binder_alloc_page_end(alloc, index);
        }
        if (mm) {
-               mmap_read_unlock(mm);
+               mmap_write_unlock(mm);
                mmput(mm);
        }
        return 0;
@@ -303,21 +303,24 @@ err_page_ptr_cleared:
        }
 err_no_vma:
        if (mm) {
-               mmap_read_unlock(mm);
+               mmap_write_unlock(mm);
                mmput(mm);
        }
        return vma ? -ENOMEM : -ESRCH;
 }
 
+static inline void binder_alloc_set_vma(struct binder_alloc *alloc,
+               struct vm_area_struct *vma)
+{
+       /* pairs with smp_load_acquire in binder_alloc_get_vma() */
+       smp_store_release(&alloc->vma, vma);
+}
+
 static inline struct vm_area_struct *binder_alloc_get_vma(
                struct binder_alloc *alloc)
 {
-       struct vm_area_struct *vma = NULL;
-
-       if (alloc->vma_addr)
-               vma = vma_lookup(alloc->mm, alloc->vma_addr);
-
-       return vma;
+       /* pairs with smp_store_release in binder_alloc_set_vma() */
+       return smp_load_acquire(&alloc->vma);
 }
 
 static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
@@ -380,15 +383,13 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
        size_t size, data_offsets_size;
        int ret;
 
-       mmap_read_lock(alloc->mm);
+       /* Check binder_alloc is fully initialized */
        if (!binder_alloc_get_vma(alloc)) {
-               mmap_read_unlock(alloc->mm);
                binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
                                   "%d: binder_alloc_buf, no vma\n",
                                   alloc->pid);
                return ERR_PTR(-ESRCH);
        }
-       mmap_read_unlock(alloc->mm);
 
        data_offsets_size = ALIGN(data_size, sizeof(void *)) +
                ALIGN(offsets_size, sizeof(void *));
@@ -778,7 +779,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
        buffer->free = 1;
        binder_insert_free_buffer(alloc, buffer);
        alloc->free_async_space = alloc->buffer_size / 2;
-       alloc->vma_addr = vma->vm_start;
+
+       /* Signal binder_alloc is fully initialized */
+       binder_alloc_set_vma(alloc, vma);
 
        return 0;
 
@@ -808,8 +811,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
 
        buffers = 0;
        mutex_lock(&alloc->mutex);
-       BUG_ON(alloc->vma_addr &&
-              vma_lookup(alloc->mm, alloc->vma_addr));
+       BUG_ON(alloc->vma);
 
        while ((n = rb_first(&alloc->allocated_buffers))) {
                buffer = rb_entry(n, struct binder_buffer, rb_node);
@@ -916,25 +918,17 @@ void binder_alloc_print_pages(struct seq_file *m,
         * Make sure the binder_alloc is fully initialized, otherwise we might
         * read inconsistent state.
         */
-
-       mmap_read_lock(alloc->mm);
-       if (binder_alloc_get_vma(alloc) == NULL) {
-               mmap_read_unlock(alloc->mm);
-               goto uninitialized;
-       }
-
-       mmap_read_unlock(alloc->mm);
-       for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
-               page = &alloc->pages[i];
-               if (!page->page_ptr)
-                       free++;
-               else if (list_empty(&page->lru))
-                       active++;
-               else
-                       lru++;
+       if (binder_alloc_get_vma(alloc) != NULL) {
+               for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
+                       page = &alloc->pages[i];
+                       if (!page->page_ptr)
+                               free++;
+                       else if (list_empty(&page->lru))
+                               active++;
+                       else
+                               lru++;
+               }
        }
-
-uninitialized:
        mutex_unlock(&alloc->mutex);
        seq_printf(m, "  pages: %d:%d:%d\n", active, lru, free);
        seq_printf(m, "  pages high watermark: %zu\n", alloc->pages_high);
@@ -969,7 +963,7 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc)
  */
 void binder_alloc_vma_close(struct binder_alloc *alloc)
 {
-       alloc->vma_addr = 0;
+       binder_alloc_set_vma(alloc, NULL);
 }
 
 /**
index 0f811ac..138d1d5 100644 (file)
@@ -75,7 +75,7 @@ struct binder_lru_page {
 /**
  * struct binder_alloc - per-binder proc state for binder allocator
  * @mutex:              protects binder_alloc fields
- * @vma_addr:           vm_area_struct->vm_start passed to mmap_handler
+ * @vma:                vm_area_struct passed to mmap_handler
  *                      (invariant after mmap)
  * @mm:                 copy of task->mm (invariant after open)
  * @buffer:             base of per-proc address space mapped via mmap
@@ -99,7 +99,7 @@ struct binder_lru_page {
  */
 struct binder_alloc {
        struct mutex mutex;
-       unsigned long vma_addr;
+       struct vm_area_struct *vma;
        struct mm_struct *mm;
        void __user *buffer;
        struct list_head buffers;
index 43a8810..c2b323b 100644 (file)
@@ -287,7 +287,7 @@ void binder_selftest_alloc(struct binder_alloc *alloc)
        if (!binder_selftest_run)
                return;
        mutex_lock(&binder_selftest_lock);
-       if (!binder_selftest_run || !alloc->vma_addr)
+       if (!binder_selftest_run || !alloc->vma)
                goto done;
        pr_info("STARTED\n");
        binder_selftest_alloc_offset(alloc, end_offset, 0);
index 7bb12de..8ce9028 100644 (file)
@@ -2694,18 +2694,36 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
        return 0;
 }
 
-static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
+static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno)
 {
-       if (!sata_pmp_attached(ap)) {
-               if (likely(devno >= 0 &&
-                          devno < ata_link_max_devices(&ap->link)))
+       /*
+        * For the non-PMP case, ata_link_max_devices() returns 1 (SATA case),
+        * or 2 (IDE master + slave case). However, the former case includes
+        * libsas hosted devices which are numbered per scsi host, leading
+        * to devno potentially being larger than 0 but with each struct
+        * ata_device having its own struct ata_port and struct ata_link.
+        * To accommodate these, ignore devno and always use device number 0.
+        */
+       if (likely(!sata_pmp_attached(ap))) {
+               int link_max_devices = ata_link_max_devices(&ap->link);
+
+               if (link_max_devices == 1)
+                       return &ap->link.device[0];
+
+               if (devno < link_max_devices)
                        return &ap->link.device[devno];
-       } else {
-               if (likely(devno >= 0 &&
-                          devno < ap->nr_pmp_links))
-                       return &ap->pmp_link[devno].device[0];
+
+               return NULL;
        }
 
+       /*
+        * For PMP-attached devices, the device number corresponds to C
+        * (channel) of SCSI [H:C:I:L], indicating the port pmp link
+        * for the device.
+        */
+       if (devno < ap->nr_pmp_links)
+               return &ap->pmp_link[devno].device[0];
+
        return NULL;
 }
 
index 33a8366..0db2021 100644 (file)
@@ -4,16 +4,23 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
+       bool "Register Map support" if KUNIT_ALL_TESTS
        default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI)
        select IRQ_DOMAIN if REGMAP_IRQ
        select MDIO_BUS if REGMAP_MDIO
-       bool
+       help
+         Enable support for the Register Map (regmap) access API.
+
+         Usually, this option is automatically selected when needed.
+         However, you may want to enable it manually for running the regmap
+         KUnit tests.
+
+         If unsure, say N.
 
 config REGMAP_KUNIT
        tristate "KUnit tests for regmap"
-       depends on KUNIT
+       depends on KUNIT && REGMAP
        default KUNIT_ALL_TESTS
-       select REGMAP
        select REGMAP_RAM
 
 config REGMAP_AC97
index 9b1b559..c2e3a0f 100644 (file)
@@ -203,15 +203,18 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min,
 
        mas_for_each(&mas, entry, max) {
                for (r = max(mas.index, lmin); r <= min(mas.last, lmax); r++) {
+                       mas_pause(&mas);
+                       rcu_read_unlock();
                        ret = regcache_sync_val(map, r, entry[r - mas.index]);
                        if (ret != 0)
                                goto out;
+                       rcu_read_lock();
                }
        }
 
-out:
        rcu_read_unlock();
 
+out:
        map->cache_bypass = false;
 
        return ret;
index 09899ae..159c0b7 100644 (file)
@@ -59,6 +59,10 @@ static int regmap_sdw_config_check(const struct regmap_config *config)
        if (config->pad_bits != 0)
                return -ENOTSUPP;
 
+       /* Only bulk writes are supported not multi-register writes */
+       if (config->can_multi_write)
+               return -ENOTSUPP;
+
        return 0;
 }
 
index db7851f..fa2d3fb 100644 (file)
@@ -2082,6 +2082,8 @@ 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)
@@ -2089,8 +2091,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 > map->max_raw_write)
-               chunk_regs = map->max_raw_write / val_bytes;
+       else if (map->max_raw_write && val_len > max_data)
+               chunk_regs = max_data / val_bytes;
 
        chunk_count = val_count / chunk_regs;
        chunk_bytes = chunk_regs * val_bytes;
index 23ed258..c1890c8 100644 (file)
@@ -780,7 +780,8 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri
                ring_req->u.rw.handle = info->handle;
                ring_req->operation = rq_data_dir(req) ?
                        BLKIF_OP_WRITE : BLKIF_OP_READ;
-               if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) {
+               if (req_op(req) == REQ_OP_FLUSH ||
+                   (req_op(req) == REQ_OP_WRITE && (req->cmd_flags & REQ_FUA))) {
                        /*
                         * Ideally we can do an unordered flush-to-disk.
                         * In case the backend onlysupports barriers, use that.
index 3a34d7c..52ef446 100644 (file)
@@ -1319,17 +1319,17 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
        hci_free_dev(hdev);
 }
 
-static struct btnxpuart_data w8987_data = {
+static struct btnxpuart_data w8987_data __maybe_unused = {
        .helper_fw_name = NULL,
        .fw_name = FIRMWARE_W8987,
 };
 
-static struct btnxpuart_data w8997_data = {
+static struct btnxpuart_data w8997_data __maybe_unused = {
        .helper_fw_name = FIRMWARE_HELPER,
        .fw_name = FIRMWARE_W8997,
 };
 
-static const struct of_device_id nxpuart_of_match_table[] = {
+static const struct of_device_id nxpuart_of_match_table[] __maybe_unused = {
        { .compatible = "nxp,88w8987-bt", .data = &w8987_data },
        { .compatible = "nxp,88w8997-bt", .data = &w8997_data },
        { }
index d68d05d..514f9f2 100644 (file)
@@ -90,6 +90,9 @@ parisc_agp_tlbflush(struct agp_memory *mem)
 {
        struct _parisc_agp_info *info = &parisc_agp_info;
 
+       /* force fdc ops to be visible to IOMMU */
+       asm_io_sync();
+
        writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM);
        readq(info->ioc_regs+IOC_PCOM); /* flush */
 }
@@ -158,6 +161,7 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
                        info->gatt[j] =
                                parisc_agp_mask_memory(agp_bridge,
                                        paddr, type);
+                       asm_io_fdc(&info->gatt[j]);
                }
        }
 
@@ -191,7 +195,16 @@ static unsigned long
 parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
                       int type)
 {
-       return SBA_PDIR_VALID_BIT | addr;
+       unsigned ci;                    /* coherent index */
+       dma_addr_t pa;
+
+       pa = addr & IOVP_MASK;
+       asm("lci 0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pa)));
+
+       pa |= (ci >> PAGE_SHIFT) & 0xff;/* move CI (8 bits) into lowest byte */
+       pa |= SBA_PDIR_VALID_BIT;       /* set "valid" bit */
+
+       return cpu_to_le64(pa);
 }
 
 static void
index 709b4e1..7db3593 100644 (file)
@@ -138,6 +138,13 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"),
                },
        },
+       {
+               .callback = tpm_tis_disable_irq,
+               .ident = "UPX-TGL",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+               },
+       },
        {}
 };
 
index 5a3d4aa..ddd346a 100644 (file)
@@ -444,9 +444,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
        return 0;
 }
 
-static int amd_pstate_target(struct cpufreq_policy *policy,
-                            unsigned int target_freq,
-                            unsigned int relation)
+static int amd_pstate_update_freq(struct cpufreq_policy *policy,
+                                 unsigned int target_freq, bool fast_switch)
 {
        struct cpufreq_freqs freqs;
        struct amd_cpudata *cpudata = policy->driver_data;
@@ -465,26 +464,51 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
        des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf,
                                     cpudata->max_freq);
 
-       cpufreq_freq_transition_begin(policy, &freqs);
+       WARN_ON(fast_switch && !policy->fast_switch_enabled);
+       /*
+        * If fast_switch is desired, then there aren't any registered
+        * transition notifiers. See comment for
+        * cpufreq_enable_fast_switch().
+        */
+       if (!fast_switch)
+               cpufreq_freq_transition_begin(policy, &freqs);
+
        amd_pstate_update(cpudata, min_perf, des_perf,
-                         max_perf, false, policy->governor->flags);
-       cpufreq_freq_transition_end(policy, &freqs, false);
+                       max_perf, fast_switch, policy->governor->flags);
+
+       if (!fast_switch)
+               cpufreq_freq_transition_end(policy, &freqs, false);
 
        return 0;
 }
 
+static int amd_pstate_target(struct cpufreq_policy *policy,
+                            unsigned int target_freq,
+                            unsigned int relation)
+{
+       return amd_pstate_update_freq(policy, target_freq, false);
+}
+
+static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
+                                 unsigned int target_freq)
+{
+       return amd_pstate_update_freq(policy, target_freq, true);
+}
+
 static void amd_pstate_adjust_perf(unsigned int cpu,
                                   unsigned long _min_perf,
                                   unsigned long target_perf,
                                   unsigned long capacity)
 {
        unsigned long max_perf, min_perf, des_perf,
-                     cap_perf, lowest_nonlinear_perf;
+                     cap_perf, lowest_nonlinear_perf, max_freq;
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
        struct amd_cpudata *cpudata = policy->driver_data;
+       unsigned int target_freq;
 
        cap_perf = READ_ONCE(cpudata->highest_perf);
        lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
+       max_freq = READ_ONCE(cpudata->max_freq);
 
        des_perf = cap_perf;
        if (target_perf < capacity)
@@ -501,6 +525,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
        if (max_perf < min_perf)
                max_perf = min_perf;
 
+       des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
+       target_freq = div_u64(des_perf * max_freq, max_perf);
+       policy->cur = target_freq;
+
        amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true,
                        policy->governor->flags);
        cpufreq_cpu_put(policy);
@@ -715,6 +743,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
 
        freq_qos_remove_request(&cpudata->req[1]);
        freq_qos_remove_request(&cpudata->req[0]);
+       policy->fast_switch_possible = false;
        kfree(cpudata);
 
        return 0;
@@ -1079,7 +1108,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
        policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
        if (boot_cpu_has(X86_FEATURE_CPPC)) {
-               policy->fast_switch_possible = true;
                ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
                if (ret)
                        return ret;
@@ -1102,7 +1130,6 @@ free_cpudata1:
 static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
 {
        pr_debug("CPU %d exiting\n", policy->cpu);
-       policy->fast_switch_possible = false;
        return 0;
 }
 
@@ -1309,6 +1336,7 @@ static struct cpufreq_driver amd_pstate_driver = {
        .flags          = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
        .verify         = amd_pstate_verify,
        .target         = amd_pstate_target,
+       .fast_switch    = amd_pstate_fast_switch,
        .init           = amd_pstate_cpu_init,
        .exit           = amd_pstate_cpu_exit,
        .suspend        = amd_pstate_cpu_suspend,
index 23b9ff9..bea9cf3 100644 (file)
@@ -1028,7 +1028,7 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
  * cxl_dev_state_identify() - Send the IDENTIFY command to the device.
  * @cxlds: The device data for the operation
  *
- * Return: 0 if identify was executed successfully.
+ * Return: 0 if identify was executed successfully or media not ready.
  *
  * This will dispatch the identify command to the device and on success populate
  * structures to be exported to sysfs.
@@ -1041,6 +1041,9 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
        u32 val;
        int rc;
 
+       if (!cxlds->media_ready)
+               return 0;
+
        mbox_cmd = (struct cxl_mbox_cmd) {
                .opcode = CXL_MBOX_OP_IDENTIFY,
                .size_out = sizeof(id),
@@ -1102,6 +1105,13 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds)
        struct device *dev = cxlds->dev;
        int rc;
 
+       if (!cxlds->media_ready) {
+               cxlds->dpa_res = DEFINE_RES_MEM(0, 0);
+               cxlds->ram_res = DEFINE_RES_MEM(0, 0);
+               cxlds->pmem_res = DEFINE_RES_MEM(0, 0);
+               return 0;
+       }
+
        cxlds->dpa_res =
                (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes);
 
index f332fe7..67f4ab6 100644 (file)
@@ -101,23 +101,57 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port)
 }
 EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, CXL);
 
-/*
- * Wait up to @media_ready_timeout for the device to report memory
- * active.
- */
-int cxl_await_media_ready(struct cxl_dev_state *cxlds)
+static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id)
+{
+       struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+       int d = cxlds->cxl_dvsec;
+       bool valid = false;
+       int rc, i;
+       u32 temp;
+
+       if (id > CXL_DVSEC_RANGE_MAX)
+               return -EINVAL;
+
+       /* Check MEM INFO VALID bit first, give up after 1s */
+       i = 1;
+       do {
+               rc = pci_read_config_dword(pdev,
+                                          d + CXL_DVSEC_RANGE_SIZE_LOW(id),
+                                          &temp);
+               if (rc)
+                       return rc;
+
+               valid = FIELD_GET(CXL_DVSEC_MEM_INFO_VALID, temp);
+               if (valid)
+                       break;
+               msleep(1000);
+       } while (i--);
+
+       if (!valid) {
+               dev_err(&pdev->dev,
+                       "Timeout awaiting memory range %d valid after 1s.\n",
+                       id);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int cxl_dvsec_mem_range_active(struct cxl_dev_state *cxlds, int id)
 {
        struct pci_dev *pdev = to_pci_dev(cxlds->dev);
        int d = cxlds->cxl_dvsec;
        bool active = false;
-       u64 md_status;
        int rc, i;
+       u32 temp;
 
-       for (i = media_ready_timeout; i; i--) {
-               u32 temp;
+       if (id > CXL_DVSEC_RANGE_MAX)
+               return -EINVAL;
 
+       /* Check MEM ACTIVE bit, up to 60s timeout by default */
+       for (i = media_ready_timeout; i; i--) {
                rc = pci_read_config_dword(
-                       pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp);
+                       pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(id), &temp);
                if (rc)
                        return rc;
 
@@ -134,6 +168,39 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds)
                return -ETIMEDOUT;
        }
 
+       return 0;
+}
+
+/*
+ * Wait up to @media_ready_timeout for the device to report memory
+ * active.
+ */
+int cxl_await_media_ready(struct cxl_dev_state *cxlds)
+{
+       struct pci_dev *pdev = to_pci_dev(cxlds->dev);
+       int d = cxlds->cxl_dvsec;
+       int rc, i, hdm_count;
+       u64 md_status;
+       u16 cap;
+
+       rc = pci_read_config_word(pdev,
+                                 d + CXL_DVSEC_CAP_OFFSET, &cap);
+       if (rc)
+               return rc;
+
+       hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap);
+       for (i = 0; i < hdm_count; i++) {
+               rc = cxl_dvsec_mem_range_valid(cxlds, i);
+               if (rc)
+                       return rc;
+       }
+
+       for (i = 0; i < hdm_count; i++) {
+               rc = cxl_dvsec_mem_range_active(cxlds, i);
+               if (rc)
+                       return rc;
+       }
+
        md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET);
        if (!CXLMDEV_READY(md_status))
                return -EIO;
@@ -241,17 +308,36 @@ static void disable_hdm(void *_cxlhdm)
               hdm + CXL_HDM_DECODER_CTRL_OFFSET);
 }
 
-static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm)
+int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm)
 {
-       void __iomem *hdm = cxlhdm->regs.hdm_decoder;
+       void __iomem *hdm;
        u32 global_ctrl;
 
+       /*
+        * If the hdm capability was not mapped there is nothing to enable and
+        * the caller is responsible for what happens next.  For example,
+        * emulate a passthrough decoder.
+        */
+       if (IS_ERR(cxlhdm))
+               return 0;
+
+       hdm = cxlhdm->regs.hdm_decoder;
        global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
+
+       /*
+        * If the HDM decoder capability was enabled on entry, skip
+        * registering disable_hdm() since this decode capability may be
+        * owned by platform firmware.
+        */
+       if (global_ctrl & CXL_HDM_DECODER_ENABLE)
+               return 0;
+
        writel(global_ctrl | CXL_HDM_DECODER_ENABLE,
               hdm + CXL_HDM_DECODER_CTRL_OFFSET);
 
-       return devm_add_action_or_reset(host, disable_hdm, cxlhdm);
+       return devm_add_action_or_reset(&port->dev, disable_hdm, cxlhdm);
 }
+EXPORT_SYMBOL_NS_GPL(devm_cxl_enable_hdm, CXL);
 
 int cxl_dvsec_rr_decode(struct device *dev, int d,
                        struct cxl_endpoint_dvsec_info *info)
@@ -425,7 +511,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
        if (info->mem_enabled)
                return 0;
 
-       rc = devm_cxl_enable_hdm(&port->dev, cxlhdm);
+       rc = devm_cxl_enable_hdm(port, cxlhdm);
        if (rc)
                return rc;
 
index da20684..e7c284c 100644 (file)
@@ -750,11 +750,10 @@ struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
 
        parent_port = parent_dport ? parent_dport->port : NULL;
        if (IS_ERR(port)) {
-               dev_dbg(uport, "Failed to add %s%s%s%s: %ld\n",
-                       dev_name(&port->dev),
-                       parent_port ? " to " : "",
+               dev_dbg(uport, "Failed to add%s%s%s: %ld\n",
+                       parent_port ? " port to " : "",
                        parent_port ? dev_name(&parent_port->dev) : "",
-                       parent_port ? "" : " (root port)",
+                       parent_port ? "" : " root port",
                        PTR_ERR(port));
        } else {
                dev_dbg(uport, "%s added%s%s%s\n",
index 044a92d..f93a285 100644 (file)
@@ -710,6 +710,7 @@ struct cxl_endpoint_dvsec_info {
 struct cxl_hdm;
 struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
                                   struct cxl_endpoint_dvsec_info *info);
+int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm);
 int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
                                struct cxl_endpoint_dvsec_info *info);
 int devm_cxl_add_passthrough_decoder(struct cxl_port *port);
index db12b63..a2845a7 100644 (file)
@@ -266,6 +266,7 @@ struct cxl_poison_state {
  * @regs: Parsed register blocks
  * @cxl_dvsec: Offset to the PCIe device DVSEC
  * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH)
+ * @media_ready: Indicate whether the device media is usable
  * @payload_size: Size of space for payload
  *                (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register)
  * @lsa_size: Size of Label Storage Area
@@ -303,6 +304,7 @@ struct cxl_dev_state {
        int cxl_dvsec;
 
        bool rcd;
+       bool media_ready;
        size_t payload_size;
        size_t lsa_size;
        struct mutex mbox_mutex; /* Protects device mailbox and firmware */
index 0465ef9..7c02e55 100644 (file)
@@ -31,6 +31,8 @@
 #define   CXL_DVSEC_RANGE_BASE_LOW(i)  (0x24 + (i * 0x10))
 #define     CXL_DVSEC_MEM_BASE_LOW_MASK        GENMASK(31, 28)
 
+#define CXL_DVSEC_RANGE_MAX            2
+
 /* CXL 2.0 8.1.4: Non-CXL Function Map DVSEC */
 #define CXL_DVSEC_FUNCTION_MAP                                 2
 
index 10caf18..519edd0 100644 (file)
@@ -124,6 +124,9 @@ static int cxl_mem_probe(struct device *dev)
        struct dentry *dentry;
        int rc;
 
+       if (!cxlds->media_ready)
+               return -EBUSY;
+
        /*
         * Someone is trying to reattach this device after it lost its port
         * connection (an endpoint port previously registered by this memdev was
index f7a5b8e..0872f22 100644 (file)
@@ -708,6 +708,12 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                dev_dbg(&pdev->dev, "Failed to map RAS capability.\n");
 
+       rc = cxl_await_media_ready(cxlds);
+       if (rc == 0)
+               cxlds->media_ready = true;
+       else
+               dev_warn(&pdev->dev, "Media not active (%d)\n", rc);
+
        rc = cxl_pci_setup_mailbox(cxlds);
        if (rc)
                return rc;
index eb57324..c23b616 100644 (file)
@@ -60,13 +60,17 @@ static int discover_region(struct device *dev, void *root)
 static int cxl_switch_port_probe(struct cxl_port *port)
 {
        struct cxl_hdm *cxlhdm;
-       int rc;
+       int rc, nr_dports;
 
-       rc = devm_cxl_port_enumerate_dports(port);
-       if (rc < 0)
-               return rc;
+       nr_dports = devm_cxl_port_enumerate_dports(port);
+       if (nr_dports < 0)
+               return nr_dports;
 
        cxlhdm = devm_cxl_setup_hdm(port, NULL);
+       rc = devm_cxl_enable_hdm(port, cxlhdm);
+       if (rc)
+               return rc;
+
        if (!IS_ERR(cxlhdm))
                return devm_cxl_enumerate_decoders(cxlhdm, NULL);
 
@@ -75,7 +79,7 @@ static int cxl_switch_port_probe(struct cxl_port *port)
                return PTR_ERR(cxlhdm);
        }
 
-       if (rc == 1) {
+       if (nr_dports == 1) {
                dev_dbg(&port->dev, "Fallback to passthrough decoder\n");
                return devm_cxl_add_passthrough_decoder(port);
        }
@@ -113,12 +117,6 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
        if (rc)
                return rc;
 
-       rc = cxl_await_media_ready(cxlds);
-       if (rc) {
-               dev_err(&port->dev, "Media not active (%d)\n", rc);
-               return rc;
-       }
-
        rc = devm_cxl_enumerate_decoders(cxlhdm, &info);
        if (rc)
                return rc;
index 8858470..ee3a219 100644 (file)
 #define ATC_DST_PIP            BIT(12)         /* Destination Picture-in-Picture enabled */
 #define ATC_SRC_DSCR_DIS       BIT(16)         /* Src Descriptor fetch disable */
 #define ATC_DST_DSCR_DIS       BIT(20)         /* Dst Descriptor fetch disable */
-#define ATC_FC                 GENMASK(22, 21) /* Choose Flow Controller */
+#define ATC_FC                 GENMASK(23, 21) /* Choose Flow Controller */
 #define ATC_FC_MEM2MEM         0x0             /* Mem-to-Mem (DMA) */
 #define ATC_FC_MEM2PER         0x1             /* Mem-to-Periph (DMA) */
 #define ATC_FC_PER2MEM         0x2             /* Periph-to-Mem (DMA) */
 #define ATC_AUTO               BIT(31)         /* Auto multiple buffer tx enable */
 
 /* Bitfields in CFG */
-#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4)    /* Extract most significant bits of a handshaking identifier */
-
 #define ATC_SRC_PER            GENMASK(3, 0)   /* Channel src rq associated with periph handshaking ifc h */
 #define ATC_DST_PER            GENMASK(7, 4)   /* Channel dst rq associated with periph handshaking ifc h */
 #define ATC_SRC_REP            BIT(8)          /* Source Replay Mod */
 #define ATC_DPIP_HOLE          GENMASK(15, 0)
 #define ATC_DPIP_BOUNDARY      GENMASK(25, 16)
 
-#define ATC_SRC_PER_ID(id)     (FIELD_PREP(ATC_SRC_PER_MSB, (id)) |    \
-                                FIELD_PREP(ATC_SRC_PER, (id)))
-#define ATC_DST_PER_ID(id)     (FIELD_PREP(ATC_DST_PER_MSB, (id)) |    \
-                                FIELD_PREP(ATC_DST_PER, (id)))
+#define ATC_PER_MSB            GENMASK(5, 4)   /* Extract MSBs of a handshaking identifier */
+#define ATC_SRC_PER_ID(id)                                            \
+       ({ typeof(id) _id = (id);                                      \
+          FIELD_PREP(ATC_SRC_PER_MSB, FIELD_GET(ATC_PER_MSB, _id)) |  \
+          FIELD_PREP(ATC_SRC_PER, _id); })
+#define ATC_DST_PER_ID(id)                                            \
+       ({ typeof(id) _id = (id);                                      \
+          FIELD_PREP(ATC_DST_PER_MSB, FIELD_GET(ATC_PER_MSB, _id)) |  \
+          FIELD_PREP(ATC_DST_PER, _id); })
 
 
 
index 7da6d9b..c3b3716 100644 (file)
@@ -1102,6 +1102,8 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
                                                        NULL,
                                                        src_addr, dst_addr,
                                                        xt, xt->sgl);
+               if (!first)
+                       return NULL;
 
                /* Length of the block is (BLEN+1) microblocks. */
                for (i = 0; i < xt->numf - 1; i++)
@@ -1132,8 +1134,9 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
                                                               src_addr, dst_addr,
                                                               xt, chunk);
                        if (!desc) {
-                               list_splice_tail_init(&first->descs_list,
-                                                     &atchan->free_descs_list);
+                               if (first)
+                                       list_splice_tail_init(&first->descs_list,
+                                                             &atchan->free_descs_list);
                                return NULL;
                        }
 
index ecbf67c..d32deb9 100644 (file)
@@ -277,7 +277,6 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
                if (wq_dedicated(wq)) {
                        rc = idxd_wq_set_pasid(wq, pasid);
                        if (rc < 0) {
-                               iommu_sva_unbind_device(sva);
                                dev_err(dev, "wq set pasid failed: %d\n", rc);
                                goto failed_set_pasid;
                        }
index 0d9257f..b4731fe 100644 (file)
@@ -1050,7 +1050,7 @@ static bool _trigger(struct pl330_thread *thrd)
        return true;
 }
 
-static bool _start(struct pl330_thread *thrd)
+static bool pl330_start_thread(struct pl330_thread *thrd)
 {
        switch (_state(thrd)) {
        case PL330_STATE_FAULT_COMPLETING:
@@ -1702,7 +1702,7 @@ static int pl330_update(struct pl330_dmac *pl330)
                        thrd->req_running = -1;
 
                        /* Get going again ASAP */
-                       _start(thrd);
+                       pl330_start_thread(thrd);
 
                        /* For now, just make a list of callbacks to be done */
                        list_add_tail(&descdone->rqd, &pl330->req_done);
@@ -2089,7 +2089,7 @@ static void pl330_tasklet(struct tasklet_struct *t)
        } else {
                /* Make sure the PL330 Channel thread is active */
                spin_lock(&pch->thread->dmac->lock);
-               _start(pch->thread);
+               pl330_start_thread(pch->thread);
                spin_unlock(&pch->thread->dmac->lock);
        }
 
@@ -2107,7 +2107,7 @@ static void pl330_tasklet(struct tasklet_struct *t)
                        if (power_down) {
                                pch->active = true;
                                spin_lock(&pch->thread->dmac->lock);
-                               _start(pch->thread);
+                               pl330_start_thread(pch->thread);
                                spin_unlock(&pch->thread->dmac->lock);
                                power_down = false;
                        }
index fc3a2a0..b8329a2 100644 (file)
@@ -5527,7 +5527,7 @@ static int udma_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int udma_pm_suspend(struct device *dev)
+static int __maybe_unused udma_pm_suspend(struct device *dev)
 {
        struct udma_dev *ud = dev_get_drvdata(dev);
        struct dma_device *dma_dev = &ud->ddev;
@@ -5549,7 +5549,7 @@ static int udma_pm_suspend(struct device *dev)
        return 0;
 }
 
-static int udma_pm_resume(struct device *dev)
+static int __maybe_unused udma_pm_resume(struct device *dev)
 {
        struct udma_dev *ud = dev_get_drvdata(dev);
        struct dma_device *dma_dev = &ud->ddev;
index f29d77e..2b8bfcd 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "common.h"
 
+static DEFINE_IDA(ffa_bus_id);
+
 static int ffa_device_match(struct device *dev, struct device_driver *drv)
 {
        const struct ffa_device_id *id_table;
@@ -53,7 +55,8 @@ static void ffa_device_remove(struct device *dev)
 {
        struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
 
-       ffa_drv->remove(to_ffa_dev(dev));
+       if (ffa_drv->remove)
+               ffa_drv->remove(to_ffa_dev(dev));
 }
 
 static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
@@ -130,6 +133,7 @@ static void ffa_release_device(struct device *dev)
 {
        struct ffa_device *ffa_dev = to_ffa_dev(dev);
 
+       ida_free(&ffa_bus_id, ffa_dev->id);
        kfree(ffa_dev);
 }
 
@@ -170,18 +174,24 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
 struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
                                       const struct ffa_ops *ops)
 {
-       int ret;
+       int id, ret;
        struct device *dev;
        struct ffa_device *ffa_dev;
 
+       id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL);
+       if (id < 0)
+               return NULL;
+
        ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
-       if (!ffa_dev)
+       if (!ffa_dev) {
+               ida_free(&ffa_bus_id, id);
                return NULL;
+       }
 
        dev = &ffa_dev->dev;
        dev->bus = &ffa_bus_type;
        dev->release = ffa_release_device;
-       dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
+       dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
 
        ffa_dev->vm_id = vm_id;
        ffa_dev->ops = ops;
@@ -217,4 +227,5 @@ void arm_ffa_bus_exit(void)
 {
        ffa_devices_unregister();
        bus_unregister(&ffa_bus_type);
+       ida_destroy(&ffa_bus_id);
 }
index fa85c64..e234091 100644 (file)
@@ -193,7 +193,8 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
        int idx, count, flags = 0, sz, buf_sz;
        ffa_value_t partition_info;
 
-       if (!buffer || !num_partitions) /* Just get the count for now */
+       if (drv_info->version > FFA_VERSION_1_0 &&
+           (!buffer || !num_partitions)) /* Just get the count for now */
                flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY;
 
        mutex_lock(&drv_info->rx_lock);
@@ -420,12 +421,17 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
                ep_mem_access->receiver = args->attrs[idx].receiver;
                ep_mem_access->attrs = args->attrs[idx].attrs;
                ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs);
+               ep_mem_access->flag = 0;
+               ep_mem_access->reserved = 0;
        }
+       mem_region->reserved_0 = 0;
+       mem_region->reserved_1 = 0;
        mem_region->ep_count = args->nattrs;
 
        composite = buffer + COMPOSITE_OFFSET(args->nattrs);
        composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
        composite->addr_range_cnt = num_entries;
+       composite->reserved = 0;
 
        length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries);
        frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0);
@@ -460,6 +466,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
 
                constituents->address = sg_phys(args->sg);
                constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
+               constituents->reserved = 0;
                constituents++;
                frag_len += sizeof(struct ffa_mem_region_addr_range);
        } while ((args->sg = sg_next(args->sg)));
index d40df09..6971dcf 100644 (file)
@@ -1066,7 +1066,7 @@ static int scmi_xfer_raw_worker_init(struct scmi_raw_mode_info *raw)
 
        raw->wait_wq = alloc_workqueue("scmi-raw-wait-wq-%d",
                                       WQ_UNBOUND | WQ_FREEZABLE |
-                                      WQ_HIGHPRI, WQ_SYSFS, raw->id);
+                                      WQ_HIGHPRI | WQ_SYSFS, 0, raw->id);
        if (!raw->wait_wq)
                return -ENOMEM;
 
index 5521f06..f45c6a3 100644 (file)
@@ -897,7 +897,7 @@ config GPIO_F7188X
        help
          This option enables support for GPIOs found on Fintek Super-I/O
          chips F71869, F71869A, F71882FG, F71889F and F81866.
-         As well as Nuvoton Super-I/O chip NCT6116D.
+         As well as Nuvoton Super-I/O chip NCT6126D.
 
          To compile this driver as a module, choose M here: the module will
          be called f7188x-gpio.
index 9effa77..f54ca5a 100644 (file)
@@ -48,7 +48,7 @@
 /*
  * Nuvoton devices.
  */
-#define SIO_NCT6116D_ID                0xD283  /* NCT6116D chipset ID */
+#define SIO_NCT6126D_ID                0xD283  /* NCT6126D chipset ID */
 
 #define SIO_LD_GPIO_NUVOTON    0x07    /* GPIO logical device */
 
@@ -62,7 +62,7 @@ enum chips {
        f81866,
        f81804,
        f81865,
-       nct6116d,
+       nct6126d,
 };
 
 static const char * const f7188x_names[] = {
@@ -74,7 +74,7 @@ static const char * const f7188x_names[] = {
        "f81866",
        "f81804",
        "f81865",
-       "nct6116d",
+       "nct6126d",
 };
 
 struct f7188x_sio {
@@ -187,8 +187,8 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
 /* Output mode register (0:open drain 1:push-pull). */
 #define f7188x_gpio_out_mode(base) ((base) + 3)
 
-#define f7188x_gpio_dir_invert(type)   ((type) == nct6116d)
-#define f7188x_gpio_data_single(type)  ((type) == nct6116d)
+#define f7188x_gpio_dir_invert(type)   ((type) == nct6126d)
+#define f7188x_gpio_data_single(type)  ((type) == nct6126d)
 
 static struct f7188x_gpio_bank f71869_gpio_bank[] = {
        F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
@@ -274,7 +274,7 @@ static struct f7188x_gpio_bank f81865_gpio_bank[] = {
        F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"),
 };
 
-static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
+static struct f7188x_gpio_bank nct6126d_gpio_bank[] = {
        F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"),
        F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"),
        F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"),
@@ -282,7 +282,7 @@ static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
        F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"),
        F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"),
        F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"),
-       F7188X_GPIO_BANK(70, 1, 0xFC, DRVNAME "-7"),
+       F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"),
 };
 
 static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
@@ -490,9 +490,9 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
                data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
                data->bank = f81865_gpio_bank;
                break;
-       case nct6116d:
-               data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank);
-               data->bank = nct6116d_gpio_bank;
+       case nct6126d:
+               data->nr_bank = ARRAY_SIZE(nct6126d_gpio_bank);
+               data->bank = nct6126d_gpio_bank;
                break;
        default:
                return -ENODEV;
@@ -559,9 +559,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
        case SIO_F81865_ID:
                sio->type = f81865;
                break;
-       case SIO_NCT6116D_ID:
+       case SIO_NCT6126D_ID:
                sio->device = SIO_LD_GPIO_NUVOTON;
-               sio->type = nct6116d;
+               sio->type = nct6126d;
                break;
        default:
                pr_info("Unsupported Fintek device 0x%04x\n", devid);
@@ -569,7 +569,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
        }
 
        /* double check manufacturer where possible */
-       if (sio->type != nct6116d) {
+       if (sio->type != nct6126d) {
                manid = superio_inw(addr, SIO_FINTEK_MANID);
                if (manid != SIO_FINTEK_ID) {
                        pr_debug("Not a Fintek device at 0x%08x\n", addr);
@@ -581,7 +581,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
        err = 0;
 
        pr_info("Found %s at %#x\n", f7188x_names[sio->type], (unsigned int)addr);
-       if (sio->type != nct6116d)
+       if (sio->type != nct6126d)
                pr_info("   revision %d\n", superio_inb(addr, SIO_FINTEK_DEVREV));
 
 err:
index e6a7049..b32063a 100644 (file)
@@ -369,7 +369,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
                priv->offset = i;
                priv->desc = gpiochip_get_desc(gc, i);
 
-               debugfs_create_file(name, 0200, chip->dbg_dir, priv,
+               debugfs_create_file(name, 0600, chip->dbg_dir, priv,
                                    &gpio_mockup_debugfs_ops);
        }
 }
index 04fb05d..a7220e0 100644 (file)
@@ -209,6 +209,8 @@ static int gpiochip_find_base(int ngpio)
                        break;
                /* nope, check the space right after the chip */
                base = gdev->base + gdev->ngpio;
+               if (base < GPIO_DYNAMIC_BASE)
+                       base = GPIO_DYNAMIC_BASE;
        }
 
        if (gpio_is_valid(base)) {
index 1ec0765..ab44c13 100644 (file)
@@ -6892,8 +6892,10 @@ static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev)
                return r;
 
        r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
-       if (unlikely(r != 0))
+       if (unlikely(r != 0)) {
+               amdgpu_bo_unreserve(ring->mqd_obj);
                return r;
+       }
 
        gfx_v10_0_kiq_init_queue(ring);
        amdgpu_bo_kunmap(ring->mqd_obj);
index 9818743..ce22f7b 100644 (file)
@@ -3617,8 +3617,10 @@ static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev)
                return r;
 
        r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
-       if (unlikely(r != 0))
+       if (unlikely(r != 0)) {
+               amdgpu_bo_unreserve(ring->mqd_obj);
                return r;
+       }
 
        gfx_v9_0_kiq_init_queue(ring);
        amdgpu_bo_kunmap(ring->mqd_obj);
index e1b7fca..5f10883 100644 (file)
@@ -57,7 +57,13 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
        if (err)
                return err;
 
-       return psp_init_ta_microcode(psp, ucode_prefix);
+       err = psp_init_ta_microcode(psp, ucode_prefix);
+       if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 1, 0)) &&
+               (adev->pdev->revision == 0xa1) &&
+               (psp->securedisplay_context.context.bin_desc.fw_version >= 0x27000008)) {
+               adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
+       }
+       return err;
 }
 
 static int psp_v10_0_ring_create(struct psp_context *psp,
index 8b4b186..d5cec03 100644 (file)
@@ -2479,20 +2479,25 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
                if (acrtc && state->stream_status[i].plane_count != 0) {
                        irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst;
                        rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
-                       DRM_DEBUG_VBL("crtc %d - vupdate irq %sabling: r=%d\n",
-                                     acrtc->crtc_id, enable ? "en" : "dis", rc);
                        if (rc)
                                DRM_WARN("Failed to %s pflip interrupts\n",
                                         enable ? "enable" : "disable");
 
                        if (enable) {
-                               rc = amdgpu_dm_crtc_enable_vblank(&acrtc->base);
-                               if (rc)
-                                       DRM_WARN("Failed to enable vblank interrupts\n");
-                       } else {
-                               amdgpu_dm_crtc_disable_vblank(&acrtc->base);
-                       }
+                               if (amdgpu_dm_crtc_vrr_active(to_dm_crtc_state(acrtc->base.state)))
+                                       rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true);
+                       } else
+                               rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false);
 
+                       if (rc)
+                               DRM_WARN("Failed to %sable vupdate interrupt\n", enable ? "en" : "dis");
+
+                       irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
+                       /* During gpu-reset we disable and then enable vblank irq, so
+                        * don't use amdgpu_irq_get/put() to avoid refcount change.
+                        */
+                       if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
+                               DRM_WARN("Failed to %sable vblank interrupt\n", enable ? "en" : "dis");
                }
        }
 
@@ -2852,7 +2857,7 @@ static int dm_resume(void *handle)
                 * this is the case when traversing through already created
                 * MST connectors, should be skipped
                 */
-               if (aconnector->dc_link->type == dc_connection_mst_branch)
+               if (aconnector && aconnector->mst_root)
                        continue;
 
                mutex_lock(&aconnector->hpd_lock);
@@ -6737,7 +6742,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
        int clock, bpp = 0;
        bool is_y420 = false;
 
-       if (!aconnector->mst_output_port || !aconnector->dc_sink)
+       if (!aconnector->mst_output_port)
                return 0;
 
        mst_port = aconnector->mst_output_port;
index e3762e8..440fc08 100644 (file)
@@ -146,7 +146,6 @@ static void vblank_control_worker(struct work_struct *work)
 
 static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
 {
-       enum dc_irq_source irq_source;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
        struct amdgpu_device *adev = drm_to_adev(crtc->dev);
        struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
@@ -169,18 +168,9 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
        if (rc)
                return rc;
 
-       if (amdgpu_in_reset(adev)) {
-               irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
-               /* During gpu-reset we disable and then enable vblank irq, so
-                * don't use amdgpu_irq_get/put() to avoid refcount change.
-                */
-               if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
-                       rc = -EBUSY;
-       } else {
-               rc = (enable)
-                       ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id)
-                       : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id);
-       }
+       rc = (enable)
+               ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id)
+               : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id);
 
        if (rc)
                return rc;
index 58c2246..f4f4045 100644 (file)
@@ -871,13 +871,11 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
        }
        if (ret == -ENOENT) {
                size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf);
-               if (size > 0) {
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size);
-                       size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size);
-               }
+               size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size);
+               size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size);
        }
 
        if (size == 0)
index 98a33f8..bba6216 100644 (file)
@@ -125,6 +125,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
        MSG_MAP(ArmD3,                          PPSMC_MSG_ArmD3,                       0),
        MSG_MAP(AllowGpo,                       PPSMC_MSG_SetGpoAllow,           0),
        MSG_MAP(GetPptLimit,                    PPSMC_MSG_GetPptLimit,                 0),
+       MSG_MAP(NotifyPowerSource,              PPSMC_MSG_NotifyPowerSource,           0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
index 4cf214d..c21c3f6 100644 (file)
@@ -264,28 +264,10 @@ void drmm_kfree(struct drm_device *dev, void *data)
 }
 EXPORT_SYMBOL(drmm_kfree);
 
-static void drmm_mutex_release(struct drm_device *dev, void *res)
+void __drmm_mutex_release(struct drm_device *dev, void *res)
 {
        struct mutex *lock = res;
 
        mutex_destroy(lock);
 }
-
-/**
- * drmm_mutex_init - &drm_device-managed mutex_init()
- * @dev: DRM device
- * @lock: lock to be initialized
- *
- * Returns:
- * 0 on success, or a negative errno code otherwise.
- *
- * This is a &drm_device-managed version of mutex_init(). The initialized
- * lock is automatically destroyed on the final drm_dev_put().
- */
-int drmm_mutex_init(struct drm_device *dev, struct mutex *lock)
-{
-       mutex_init(lock);
-
-       return drmm_add_action_or_reset(dev, drmm_mutex_release, lock);
-}
-EXPORT_SYMBOL(drmm_mutex_init);
+EXPORT_SYMBOL(__drmm_mutex_release);
index b1a38e6..0cb646c 100644 (file)
@@ -179,7 +179,7 @@ static const struct dmi_system_id orientation_data[] = {
        }, {    /* AYA NEO AIR */
                .matches = {
                  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
-                 DMI_MATCH(DMI_BOARD_NAME, "AIR"),
+                 DMI_MATCH(DMI_PRODUCT_NAME, "AIR"),
                },
                .driver_data = (void *)&lcd1080x1920_leftside_up,
        }, {    /* AYA NEO NEXT */
index 3c29792..0aae9a1 100644 (file)
@@ -1851,9 +1851,17 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
 
        intel_disable_shared_dpll(old_crtc_state);
 
-       intel_encoders_post_pll_disable(state, crtc);
+       if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) {
+               struct intel_crtc *slave_crtc;
+
+               intel_encoders_post_pll_disable(state, crtc);
 
-       intel_dmc_disable_pipe(i915, crtc->pipe);
+               intel_dmc_disable_pipe(i915, crtc->pipe);
+
+               for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
+                                                intel_crtc_bigjoiner_slave_pipes(old_crtc_state))
+                       intel_dmc_disable_pipe(i915, slave_crtc->pipe);
+       }
 }
 
 static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
index 0f2dd26..af3ce5a 100644 (file)
@@ -642,6 +642,11 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_
        if (funcs->pixpllc_atomic_update)
                funcs->pixpllc_atomic_update(crtc, old_state);
 
+       if (crtc_state->gamma_lut)
+               mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
+       else
+               mgag200_crtc_set_gamma_linear(mdev, format);
+
        mgag200_enable_display(mdev);
 
        if (funcs->enable_vidrst)
index 6afdf26..b9fe926 100644 (file)
@@ -53,7 +53,7 @@ pl111_mode_valid(struct drm_simple_display_pipe *pipe,
 {
        struct drm_device *drm = pipe->crtc.dev;
        struct pl111_drm_dev_private *priv = drm->dev_private;
-       u32 cpp = priv->variant->fb_bpp / 8;
+       u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8);
        u64 bw;
 
        /*
index 2a46b5b..d1fe756 100644 (file)
@@ -114,7 +114,7 @@ struct drm_minor;
  *     extensions to the control register
  * @formats: array of supported pixel formats on this variant
  * @nformats: the length of the array of supported pixel formats
- * @fb_bpp: desired bits per pixel on the default framebuffer
+ * @fb_depth: desired depth per pixel on the default framebuffer
  */
 struct pl111_variant_data {
        const char *name;
@@ -126,7 +126,7 @@ struct pl111_variant_data {
        bool st_bitmux_control;
        const u32 *formats;
        unsigned int nformats;
-       unsigned int fb_bpp;
+       unsigned int fb_depth;
 };
 
 struct pl111_drm_dev_private {
index 4b2a9e9..43049c8 100644 (file)
@@ -308,7 +308,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
        if (ret < 0)
                goto dev_put;
 
-       drm_fbdev_dma_setup(drm, priv->variant->fb_bpp);
+       drm_fbdev_dma_setup(drm, priv->variant->fb_depth);
 
        return 0;
 
@@ -351,7 +351,7 @@ static const struct pl111_variant_data pl110_variant = {
        .is_pl110 = true,
        .formats = pl110_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /* RealView, Versatile Express etc use this modern variant */
@@ -376,7 +376,7 @@ static const struct pl111_variant_data pl111_variant = {
        .name = "PL111",
        .formats = pl111_pixel_formats,
        .nformats = ARRAY_SIZE(pl111_pixel_formats),
-       .fb_bpp = 32,
+       .fb_depth = 32,
 };
 
 static const u32 pl110_nomadik_pixel_formats[] = {
@@ -405,7 +405,7 @@ static const struct pl111_variant_data pl110_nomadik_variant = {
        .is_lcdc = true,
        .st_bitmux_control = true,
        .broken_vblank = true,
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 static const struct amba_id pl111_id_table[] = {
index 1b436b7..00c3ebd 100644 (file)
@@ -316,7 +316,7 @@ static const struct pl111_variant_data pl110_integrator = {
        .broken_vblank = true,
        .formats = pl110_integrator_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /*
@@ -330,7 +330,7 @@ static const struct pl111_variant_data pl110_impd1 = {
        .broken_vblank = true,
        .formats = pl110_integrator_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 15,
 };
 
 /*
@@ -343,7 +343,7 @@ static const struct pl111_variant_data pl110_versatile = {
        .external_bgr = true,
        .formats = pl110_versatile_pixel_formats,
        .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /*
@@ -355,7 +355,7 @@ static const struct pl111_variant_data pl111_realview = {
        .name = "PL111 RealView",
        .formats = pl111_realview_pixel_formats,
        .nformats = ARRAY_SIZE(pl111_realview_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
 };
 
 /*
@@ -367,7 +367,7 @@ static const struct pl111_variant_data pl111_vexpress = {
        .name = "PL111 Versatile Express",
        .formats = pl111_realview_pixel_formats,
        .nformats = ARRAY_SIZE(pl111_realview_pixel_formats),
-       .fb_bpp = 16,
+       .fb_depth = 16,
        .broken_clockdivider = true,
 };
 
index 3377fbc..c4dda90 100644 (file)
@@ -99,6 +99,16 @@ static void radeon_hotplug_work_func(struct work_struct *work)
 
 static void radeon_dp_work_func(struct work_struct *work)
 {
+       struct radeon_device *rdev = container_of(work, struct radeon_device,
+                                                 dp_work);
+       struct drm_device *dev = rdev->ddev;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *connector;
+
+       mutex_lock(&mode_config->mutex);
+       list_for_each_entry(connector, &mode_config->connector_list, head)
+               radeon_connector_hotplug(connector);
+       mutex_unlock(&mode_config->mutex);
 }
 
 /**
index 8c18363..aea5a90 100644 (file)
@@ -1141,9 +1141,6 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched)
        for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
                struct drm_sched_rq *rq = &sched->sched_rq[i];
 
-               if (!rq)
-                       continue;
-
                spin_lock(&rq->lock);
                list_for_each_entry(s_entity, &rq->entities, list)
                        /*
index 7ae5f27..c6bdb9c 100644 (file)
@@ -587,6 +587,8 @@ static const struct hid_device_id hammer_devices[] = {
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_JEWEL) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) },
index d79e946..5d29aba 100644 (file)
 #define USB_DEVICE_ID_GOOGLE_MOONBALL  0x5044
 #define USB_DEVICE_ID_GOOGLE_DON       0x5050
 #define USB_DEVICE_ID_GOOGLE_EEL       0x5057
+#define USB_DEVICE_ID_GOOGLE_JEWEL     0x5061
 
 #define USB_VENDOR_ID_GOTOP            0x08f2
 #define USB_DEVICE_ID_SUPER_Q2         0x007f
index 0fcfd85..2246044 100644 (file)
@@ -314,6 +314,7 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
                        dbg_hid("%s:timeout waiting for response\n", __func__);
                        memset(response, 0, sizeof(struct hidpp_report));
                        ret = -ETIMEDOUT;
+                       goto exit;
                }
 
                if (response->report_id == REPORT_ID_HIDPP_SHORT &&
index 8214896..76e5353 100644 (file)
@@ -2224,7 +2224,9 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
                } else if (strstr(product_name, "Wacom") ||
                           strstr(product_name, "wacom") ||
                           strstr(product_name, "WACOM")) {
-                       strscpy(name, product_name, sizeof(name));
+                       if (strscpy(name, product_name, sizeof(name)) < 0) {
+                               hid_warn(wacom->hdev, "String overflow while assembling device name");
+                       }
                } else {
                        snprintf(name, sizeof(name), "Wacom %s", product_name);
                }
@@ -2242,7 +2244,9 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
                if (name[strlen(name)-1] == ' ')
                        name[strlen(name)-1] = '\0';
        } else {
-               strscpy(name, features->name, sizeof(name));
+               if (strscpy(name, features->name, sizeof(name)) < 0) {
+                       hid_warn(wacom->hdev, "String overflow while assembling device name");
+               }
        }
 
        snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s",
@@ -2410,8 +2414,13 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
                goto fail_quirks;
        }
 
-       if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
+       if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
                error = hid_hw_open(hdev);
+               if (error) {
+                       hid_err(hdev, "hw open failed\n");
+                       goto fail_quirks;
+               }
+       }
 
        wacom_set_shared_values(wacom_wac);
        devres_close_group(&hdev->dev, wacom);
@@ -2500,8 +2509,10 @@ static void wacom_wireless_work(struct work_struct *work)
                                goto fail;
                }
 
-               strscpy(wacom_wac->name, wacom_wac1->name,
-                       sizeof(wacom_wac->name));
+               if (strscpy(wacom_wac->name, wacom_wac1->name,
+                       sizeof(wacom_wac->name)) < 0) {
+                       hid_warn(wacom->hdev, "String overflow while assembling device name");
+               }
        }
 
        return;
index dc0f7d9..2ccf838 100644 (file)
@@ -831,7 +831,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
        /* Enter report */
        if ((data[1] & 0xfc) == 0xc0) {
                /* serial number of the tool */
-               wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+               wacom->serial[idx] = ((__u64)(data[3] & 0x0f) << 28) +
                        (data[4] << 20) + (data[5] << 12) +
                        (data[6] << 4) + (data[7] >> 4);
 
index 711f451..89e8ed2 100644 (file)
@@ -402,6 +402,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
                trace_id = coresight_trace_id_get_cpu_id(cpu);
                if (!IS_VALID_CS_TRACE_ID(trace_id)) {
                        cpumask_clear_cpu(cpu, mask);
+                       coresight_release_path(path);
                        continue;
                }
 
index 918d461..eaa296c 100644 (file)
@@ -942,7 +942,7 @@ tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset)
 
        len = tmc_etr_buf_get_data(etr_buf, offset,
                                   CORESIGHT_BARRIER_PKT_SIZE, &bufp);
-       if (WARN_ON(len < CORESIGHT_BARRIER_PKT_SIZE))
+       if (WARN_ON(len < 0 || len < CORESIGHT_BARRIER_PKT_SIZE))
                return -EINVAL;
        coresight_insert_barrier_packet(bufp);
        return offset + CORESIGHT_BARRIER_PKT_SIZE;
index e86afec..b1c3641 100644 (file)
@@ -3341,9 +3341,7 @@ static int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *gsi_qp,
        udwr.remote_qkey = gsi_sqp->qplib_qp.qkey;
 
        /* post data received  in the send queue */
-       rc = bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
-
-       return 0;
+       return bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
 }
 
 static void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc,
index b9e2f89..e34eccd 100644 (file)
@@ -1336,6 +1336,10 @@ static void bnxt_re_setup_cc(struct bnxt_re_dev *rdev, bool enable)
 {
        struct bnxt_qplib_cc_param cc_param = {};
 
+       /* Do not enable congestion control on VFs */
+       if (rdev->is_virtfn)
+               return;
+
        /* Currently enabling only for GenP5 adapters */
        if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx))
                return;
index f139d4c..8974f62 100644 (file)
@@ -2056,6 +2056,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
        u32 pg_sz_lvl;
        int rc;
 
+       if (!cq->dpi) {
+               dev_err(&rcfw->pdev->dev,
+                       "FP: CREATE_CQ failed due to NULL DPI\n");
+               return -EINVAL;
+       }
+
        hwq_attr.res = res;
        hwq_attr.depth = cq->max_wqe;
        hwq_attr.stride = sizeof(struct cq_base);
@@ -2069,11 +2075,6 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
                                 CMDQ_BASE_OPCODE_CREATE_CQ,
                                 sizeof(req));
 
-       if (!cq->dpi) {
-               dev_err(&rcfw->pdev->dev,
-                       "FP: CREATE_CQ failed due to NULL DPI\n");
-               return -EINVAL;
-       }
        req.dpi = cpu_to_le32(cq->dpi->dpi);
        req.cq_handle = cpu_to_le64(cq->cq_handle);
        req.cq_size = cpu_to_le32(cq->hwq.max_elements);
index 126d4f2..81b0c5e 100644 (file)
@@ -215,17 +215,9 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
                        return -EINVAL;
                hwq_attr->sginfo->npages = npages;
        } else {
-               unsigned long sginfo_num_pages = ib_umem_num_dma_blocks(
-                       hwq_attr->sginfo->umem, hwq_attr->sginfo->pgsize);
-
+               npages = ib_umem_num_dma_blocks(hwq_attr->sginfo->umem,
+                                               hwq_attr->sginfo->pgsize);
                hwq->is_user = true;
-               npages = sginfo_num_pages;
-               npages = (npages * PAGE_SIZE) /
-                         BIT_ULL(hwq_attr->sginfo->pgshft);
-               if ((sginfo_num_pages * PAGE_SIZE) %
-                    BIT_ULL(hwq_attr->sginfo->pgshft))
-                       if (!npages)
-                               npages++;
        }
 
        if (npages == MAX_PBL_LVL_0_PGS && !hwq_attr->sginfo->nopte) {
index 1714a1e..b967a17 100644 (file)
@@ -617,16 +617,15 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
                /* Free the hwq if it already exist, must be a rereg */
                if (mr->hwq.max_elements)
                        bnxt_qplib_free_hwq(res, &mr->hwq);
-               /* Use system PAGE_SIZE */
                hwq_attr.res = res;
                hwq_attr.depth = pages;
-               hwq_attr.stride = buf_pg_size;
+               hwq_attr.stride = sizeof(dma_addr_t);
                hwq_attr.type = HWQ_TYPE_MR;
                hwq_attr.sginfo = &sginfo;
                hwq_attr.sginfo->umem = umem;
                hwq_attr.sginfo->npages = pages;
-               hwq_attr.sginfo->pgsize = PAGE_SIZE;
-               hwq_attr.sginfo->pgshft = PAGE_SHIFT;
+               hwq_attr.sginfo->pgsize = buf_pg_size;
+               hwq_attr.sginfo->pgshft = ilog2(buf_pg_size);
                rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr);
                if (rc) {
                        dev_err(&res->pdev->dev,
index 8eca6c1..2a195c4 100644 (file)
@@ -1403,7 +1403,7 @@ static int pbl_continuous_initialize(struct efa_dev *dev,
  */
 static int pbl_indirect_initialize(struct efa_dev *dev, struct pbl_context *pbl)
 {
-       u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, PAGE_SIZE);
+       u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, EFA_CHUNK_PAYLOAD_SIZE);
        struct scatterlist *sgl;
        int sg_dma_cnt, err;
 
index 84f1167..d4c6b9b 100644 (file)
@@ -4583,11 +4583,9 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
        mtu = ib_mtu_enum_to_int(ib_mtu);
        if (WARN_ON(mtu <= 0))
                return -EINVAL;
-#define MAX_LP_MSG_LEN 16384
-       /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 16KB */
-       lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu);
-       if (WARN_ON(lp_pktn_ini >= 0xF))
-               return -EINVAL;
+#define MIN_LP_MSG_LEN 1024
+       /* mtu * (2 ^ lp_pktn_ini) should be in the range of 1024 to mtu */
+       lp_pktn_ini = ilog2(max(mtu, MIN_LP_MSG_LEN) / mtu);
 
        if (attr_mask & IB_QP_PATH_MTU) {
                hr_reg_write(context, QPC_MTU, ib_mtu);
@@ -5012,7 +5010,6 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp,
 static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout)
 {
 #define QP_ACK_TIMEOUT_MAX_HIP08 20
-#define QP_ACK_TIMEOUT_OFFSET 10
 #define QP_ACK_TIMEOUT_MAX 31
 
        if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) {
@@ -5021,7 +5018,7 @@ static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout)
                                   "local ACK timeout shall be 0 to 20.\n");
                        return false;
                }
-               *timeout += QP_ACK_TIMEOUT_OFFSET;
+               *timeout += HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08;
        } else if (hr_dev->pci_dev->revision > PCI_REVISION_ID_HIP08) {
                if (*timeout > QP_ACK_TIMEOUT_MAX) {
                        ibdev_warn(&hr_dev->ib_dev,
@@ -5307,6 +5304,18 @@ out:
        return ret;
 }
 
+static u8 get_qp_timeout_attr(struct hns_roce_dev *hr_dev,
+                             struct hns_roce_v2_qp_context *context)
+{
+       u8 timeout;
+
+       timeout = (u8)hr_reg_read(context, QPC_AT);
+       if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08)
+               timeout -= HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08;
+
+       return timeout;
+}
+
 static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
                                int qp_attr_mask,
                                struct ib_qp_init_attr *qp_init_attr)
@@ -5384,7 +5393,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
        qp_attr->max_dest_rd_atomic = 1 << hr_reg_read(&context, QPC_RR_MAX);
 
        qp_attr->min_rnr_timer = (u8)hr_reg_read(&context, QPC_MIN_RNR_TIME);
-       qp_attr->timeout = (u8)hr_reg_read(&context, QPC_AT);
+       qp_attr->timeout = get_qp_timeout_attr(hr_dev, &context);
        qp_attr->retry_cnt = hr_reg_read(&context, QPC_RETRY_NUM_INIT);
        qp_attr->rnr_retry = hr_reg_read(&context, QPC_RNR_NUM_INIT);
 
index 1b44d24..7033eae 100644 (file)
@@ -44,6 +44,8 @@
 #define HNS_ROCE_V2_MAX_XRCD_NUM               0x1000000
 #define HNS_ROCE_V2_RSV_XRCD_NUM               0
 
+#define HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08    10
+
 #define HNS_ROCE_V3_SCCC_SZ                    64
 #define HNS_ROCE_V3_GMV_ENTRY_SZ               32
 
index 37a5cf6..1437649 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/vmalloc.h>
 #include <rdma/ib_umem.h>
+#include <linux/math.h>
 #include "hns_roce_device.h"
 #include "hns_roce_cmd.h"
 #include "hns_roce_hem.h"
@@ -909,6 +910,44 @@ static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev,
        return page_cnt;
 }
 
+static u64 cal_pages_per_l1ba(unsigned int ba_per_bt, unsigned int hopnum)
+{
+       return int_pow(ba_per_bt, hopnum - 1);
+}
+
+static unsigned int cal_best_bt_pg_sz(struct hns_roce_dev *hr_dev,
+                                     struct hns_roce_mtr *mtr,
+                                     unsigned int pg_shift)
+{
+       unsigned long cap = hr_dev->caps.page_size_cap;
+       struct hns_roce_buf_region *re;
+       unsigned int pgs_per_l1ba;
+       unsigned int ba_per_bt;
+       unsigned int ba_num;
+       int i;
+
+       for_each_set_bit_from(pg_shift, &cap, sizeof(cap) * BITS_PER_BYTE) {
+               if (!(BIT(pg_shift) & cap))
+                       continue;
+
+               ba_per_bt = BIT(pg_shift) / BA_BYTE_LEN;
+               ba_num = 0;
+               for (i = 0; i < mtr->hem_cfg.region_count; i++) {
+                       re = &mtr->hem_cfg.region[i];
+                       if (re->hopnum == 0)
+                               continue;
+
+                       pgs_per_l1ba = cal_pages_per_l1ba(ba_per_bt, re->hopnum);
+                       ba_num += DIV_ROUND_UP(re->count, pgs_per_l1ba);
+               }
+
+               if (ba_num <= ba_per_bt)
+                       return pg_shift;
+       }
+
+       return 0;
+}
+
 static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
                         unsigned int ba_page_shift)
 {
@@ -917,6 +956,10 @@ static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
 
        hns_roce_hem_list_init(&mtr->hem_list);
        if (!cfg->is_direct) {
+               ba_page_shift = cal_best_bt_pg_sz(hr_dev, mtr, ba_page_shift);
+               if (!ba_page_shift)
+                       return -ERANGE;
+
                ret = hns_roce_hem_list_request(hr_dev, &mtr->hem_list,
                                                cfg->region, cfg->region_count,
                                                ba_page_shift);
index ab5cdf7..eaa12c1 100644 (file)
@@ -522,11 +522,6 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
        if (!iwqp->user_mode)
                cancel_delayed_work_sync(&iwqp->dwork_flush);
 
-       irdma_qp_rem_ref(&iwqp->ibqp);
-       wait_for_completion(&iwqp->free_qp);
-       irdma_free_lsmm_rsrc(iwqp);
-       irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
-
        if (!iwqp->user_mode) {
                if (iwqp->iwscq) {
                        irdma_clean_cqes(iwqp, iwqp->iwscq);
@@ -534,6 +529,12 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
                                irdma_clean_cqes(iwqp, iwqp->iwrcq);
                }
        }
+
+       irdma_qp_rem_ref(&iwqp->ibqp);
+       wait_for_completion(&iwqp->free_qp);
+       irdma_free_lsmm_rsrc(iwqp);
+       irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp);
+
        irdma_remove_push_mmap_entries(iwqp);
        irdma_free_qp_rsrc(iwqp);
 
@@ -3291,6 +3292,7 @@ static int irdma_post_send(struct ib_qp *ibqp,
                        break;
                case IB_WR_LOCAL_INV:
                        info.op_type = IRDMA_OP_TYPE_INV_STAG;
+                       info.local_fence = info.read_fence;
                        info.op.inv_local_stag.target_stag = ib_wr->ex.invalidate_rkey;
                        err = irdma_uk_stag_local_invalidate(ukqp, &info, true);
                        break;
index db18ace..f46c5a5 100644 (file)
@@ -115,15 +115,16 @@ static enum ib_wc_opcode wr_to_wc_opcode(enum ib_wr_opcode opcode)
 void retransmit_timer(struct timer_list *t)
 {
        struct rxe_qp *qp = from_timer(qp, t, retrans_timer);
+       unsigned long flags;
 
        rxe_dbg_qp(qp, "retransmit timer fired\n");
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp->valid) {
                qp->comp.timeout = 1;
                rxe_sched_task(&qp->comp.task);
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
@@ -481,11 +482,13 @@ static void do_complete(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
 
 static void comp_check_sq_drain_done(struct rxe_qp *qp)
 {
-       spin_lock_bh(&qp->state_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely(qp_state(qp) == IB_QPS_SQD)) {
                if (qp->attr.sq_draining && qp->comp.psn == qp->req.psn) {
                        qp->attr.sq_draining = 0;
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
 
                        if (qp->ibqp.event_handler) {
                                struct ib_event ev;
@@ -499,7 +502,7 @@ static void comp_check_sq_drain_done(struct rxe_qp *qp)
                        return;
                }
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static inline enum comp_state complete_ack(struct rxe_qp *qp,
@@ -625,13 +628,15 @@ static void free_pkt(struct rxe_pkt_info *pkt)
  */
 static void reset_retry_timer(struct rxe_qp *qp)
 {
+       unsigned long flags;
+
        if (qp_type(qp) == IB_QPT_RC && qp->qp_timeout_jiffies) {
-               spin_lock_bh(&qp->state_lock);
+               spin_lock_irqsave(&qp->state_lock, flags);
                if (qp_state(qp) >= IB_QPS_RTS &&
                    psn_compare(qp->req.psn, qp->comp.psn) > 0)
                        mod_timer(&qp->retrans_timer,
                                  jiffies + qp->qp_timeout_jiffies);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
        }
 }
 
@@ -643,18 +648,19 @@ int rxe_completer(struct rxe_qp *qp)
        struct rxe_pkt_info *pkt = NULL;
        enum comp_state state;
        int ret;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (!qp->valid || qp_state(qp) == IB_QPS_ERR ||
                          qp_state(qp) == IB_QPS_RESET) {
                bool notify = qp->valid && (qp_state(qp) == IB_QPS_ERR);
 
                drain_resp_pkts(qp);
                flush_send_queue(qp, notify);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (qp->comp.timeout) {
                qp->comp.timeout_retry = 1;
index 2bc7361..a38fab1 100644 (file)
@@ -412,15 +412,16 @@ int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
        int err;
        int is_request = pkt->mask & RXE_REQ_MASK;
        struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if ((is_request && (qp_state(qp) < IB_QPS_RTS)) ||
            (!is_request && (qp_state(qp) < IB_QPS_RTR))) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                rxe_dbg_qp(qp, "Packet dropped. QP is not in ready state\n");
                goto drop;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        rxe_icrc_generate(skb, pkt);
 
index c5451a4..61a2eb7 100644 (file)
@@ -300,6 +300,7 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
        struct rxe_cq *rcq = to_rcq(init->recv_cq);
        struct rxe_cq *scq = to_rcq(init->send_cq);
        struct rxe_srq *srq = init->srq ? to_rsrq(init->srq) : NULL;
+       unsigned long flags;
 
        rxe_get(pd);
        rxe_get(rcq);
@@ -325,10 +326,10 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
        if (err)
                goto err2;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->attr.qp_state = IB_QPS_RESET;
        qp->valid = 1;
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return 0;
 
@@ -492,24 +493,28 @@ static void rxe_qp_reset(struct rxe_qp *qp)
 /* move the qp to the error state */
 void rxe_qp_error(struct rxe_qp *qp)
 {
-       spin_lock_bh(&qp->state_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->attr.qp_state = IB_QPS_ERR;
 
        /* drain work and packet queues */
        rxe_sched_task(&qp->resp.task);
        rxe_sched_task(&qp->comp.task);
        rxe_sched_task(&qp->req.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static void rxe_qp_sqd(struct rxe_qp *qp, struct ib_qp_attr *attr,
                       int mask)
 {
-       spin_lock_bh(&qp->state_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->attr.sq_draining = 1;
        rxe_sched_task(&qp->comp.task);
        rxe_sched_task(&qp->req.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 /* caller should hold qp->state_lock */
@@ -555,14 +560,16 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,
                qp->attr.cur_qp_state = attr->qp_state;
 
        if (mask & IB_QP_STATE) {
-               spin_lock_bh(&qp->state_lock);
+               unsigned long flags;
+
+               spin_lock_irqsave(&qp->state_lock, flags);
                err = __qp_chk_state(qp, attr, mask);
                if (!err) {
                        qp->attr.qp_state = attr->qp_state;
                        rxe_dbg_qp(qp, "state -> %s\n",
                                        qps2str[attr->qp_state]);
                }
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
 
                if (err)
                        return err;
@@ -688,6 +695,8 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,
 /* called by the query qp verb */
 int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
 {
+       unsigned long flags;
+
        *attr = qp->attr;
 
        attr->rq_psn                            = qp->resp.psn;
@@ -708,12 +717,13 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
        /* Applications that get this state typically spin on it.
         * Yield the processor
         */
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp->attr.sq_draining) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                cond_resched();
+       } else {
+               spin_unlock_irqrestore(&qp->state_lock, flags);
        }
-       spin_unlock_bh(&qp->state_lock);
 
        return 0;
 }
@@ -736,10 +746,11 @@ int rxe_qp_chk_destroy(struct rxe_qp *qp)
 static void rxe_qp_do_cleanup(struct work_struct *work)
 {
        struct rxe_qp *qp = container_of(work, typeof(*qp), cleanup_work.work);
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        qp->valid = 0;
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
        qp->qp_timeout_jiffies = 0;
 
        if (qp_type(qp) == IB_QPT_RC) {
index 2f953cc..5861e42 100644 (file)
@@ -14,6 +14,7 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
                            struct rxe_qp *qp)
 {
        unsigned int pkt_type;
+       unsigned long flags;
 
        if (unlikely(!qp->valid))
                return -EINVAL;
@@ -38,19 +39,19 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
                return -EINVAL;
        }
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (pkt->mask & RXE_REQ_MASK) {
                if (unlikely(qp_state(qp) < IB_QPS_RTR)) {
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
                        return -EINVAL;
                }
        } else {
                if (unlikely(qp_state(qp) < IB_QPS_RTS)) {
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
                        return -EINVAL;
                }
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return 0;
 }
index 65134a9..5fe7cba 100644 (file)
@@ -99,17 +99,18 @@ static void req_retry(struct rxe_qp *qp)
 void rnr_nak_timer(struct timer_list *t)
 {
        struct rxe_qp *qp = from_timer(qp, t, rnr_nak_timer);
+       unsigned long flags;
 
        rxe_dbg_qp(qp, "nak timer fired\n");
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp->valid) {
                /* request a send queue retry */
                qp->req.need_retry = 1;
                qp->req.wait_for_rnr_timer = 0;
                rxe_sched_task(&qp->req.task);
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static void req_check_sq_drain_done(struct rxe_qp *qp)
@@ -118,8 +119,9 @@ static void req_check_sq_drain_done(struct rxe_qp *qp)
        unsigned int index;
        unsigned int cons;
        struct rxe_send_wqe *wqe;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp_state(qp) == IB_QPS_SQD) {
                q = qp->sq.queue;
                index = qp->req.wqe_index;
@@ -140,7 +142,7 @@ static void req_check_sq_drain_done(struct rxe_qp *qp)
                                break;
 
                        qp->attr.sq_draining = 0;
-                       spin_unlock_bh(&qp->state_lock);
+                       spin_unlock_irqrestore(&qp->state_lock, flags);
 
                        if (qp->ibqp.event_handler) {
                                struct ib_event ev;
@@ -154,7 +156,7 @@ static void req_check_sq_drain_done(struct rxe_qp *qp)
                        return;
                } while (0);
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 }
 
 static struct rxe_send_wqe *__req_next_wqe(struct rxe_qp *qp)
@@ -173,6 +175,7 @@ static struct rxe_send_wqe *__req_next_wqe(struct rxe_qp *qp)
 static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
 {
        struct rxe_send_wqe *wqe;
+       unsigned long flags;
 
        req_check_sq_drain_done(qp);
 
@@ -180,13 +183,13 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
        if (wqe == NULL)
                return NULL;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely((qp_state(qp) == IB_QPS_SQD) &&
                     (wqe->state != wqe_state_processing))) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                return NULL;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
        return wqe;
@@ -676,16 +679,17 @@ int rxe_requester(struct rxe_qp *qp)
        struct rxe_queue *q = qp->sq.queue;
        struct rxe_ah *ah;
        struct rxe_av *av;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely(!qp->valid)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
 
        if (unlikely(qp_state(qp) == IB_QPS_ERR)) {
                wqe = __req_next_wqe(qp);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                if (wqe)
                        goto err;
                else
@@ -700,10 +704,10 @@ int rxe_requester(struct rxe_qp *qp)
                qp->req.wait_psn = 0;
                qp->req.need_retry = 0;
                qp->req.wait_for_rnr_timer = 0;
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        /* we come here if the retransmit timer has fired
         * or if the rnr timer has fired. If the retransmit
index 68f6cd1..1da044f 100644 (file)
@@ -1047,6 +1047,7 @@ static enum resp_states do_complete(struct rxe_qp *qp,
        struct ib_uverbs_wc *uwc = &cqe.uibwc;
        struct rxe_recv_wqe *wqe = qp->resp.wqe;
        struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+       unsigned long flags;
 
        if (!wqe)
                goto finish;
@@ -1137,12 +1138,12 @@ static enum resp_states do_complete(struct rxe_qp *qp,
                return RESPST_ERR_CQ_OVERFLOW;
 
 finish:
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (unlikely(qp_state(qp) == IB_QPS_ERR)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                return RESPST_CHK_RESOURCE;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (unlikely(!pkt))
                return RESPST_DONE;
@@ -1468,18 +1469,19 @@ int rxe_responder(struct rxe_qp *qp)
        enum resp_states state;
        struct rxe_pkt_info *pkt = NULL;
        int ret;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (!qp->valid || qp_state(qp) == IB_QPS_ERR ||
                          qp_state(qp) == IB_QPS_RESET) {
                bool notify = qp->valid && (qp_state(qp) == IB_QPS_ERR);
 
                drain_req_pkts(qp);
                flush_recv_queue(qp, notify);
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                goto exit;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED;
 
index dea605b..4d8f6b8 100644 (file)
@@ -904,10 +904,10 @@ static int rxe_post_send_kernel(struct rxe_qp *qp,
        if (!err)
                rxe_sched_task(&qp->req.task);
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp_state(qp) == IB_QPS_ERR)
                rxe_sched_task(&qp->comp.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return err;
 }
@@ -917,22 +917,23 @@ static int rxe_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
 {
        struct rxe_qp *qp = to_rqp(ibqp);
        int err;
+       unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        /* caller has already called destroy_qp */
        if (WARN_ON_ONCE(!qp->valid)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                rxe_err_qp(qp, "qp has been destroyed");
                return -EINVAL;
        }
 
        if (unlikely(qp_state(qp) < IB_QPS_RTS)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                *bad_wr = wr;
                rxe_err_qp(qp, "qp not ready to send");
                return -EINVAL;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (qp->is_user) {
                /* Utilize process context to do protocol processing */
@@ -1008,22 +1009,22 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
        struct rxe_rq *rq = &qp->rq;
        unsigned long flags;
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        /* caller has already called destroy_qp */
        if (WARN_ON_ONCE(!qp->valid)) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                rxe_err_qp(qp, "qp has been destroyed");
                return -EINVAL;
        }
 
        /* see C10-97.2.1 */
        if (unlikely((qp_state(qp) < IB_QPS_INIT))) {
-               spin_unlock_bh(&qp->state_lock);
+               spin_unlock_irqrestore(&qp->state_lock, flags);
                *bad_wr = wr;
                rxe_dbg_qp(qp, "qp not ready to post recv");
                return -EINVAL;
        }
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        if (unlikely(qp->srq)) {
                *bad_wr = wr;
@@ -1044,10 +1045,10 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
 
        spin_unlock_irqrestore(&rq->producer_lock, flags);
 
-       spin_lock_bh(&qp->state_lock);
+       spin_lock_irqsave(&qp->state_lock, flags);
        if (qp_state(qp) == IB_QPS_ERR)
                rxe_sched_task(&qp->resp.task);
-       spin_unlock_bh(&qp->state_lock);
+       spin_unlock_irqrestore(&qp->state_lock, flags);
 
        return err;
 }
index a610821..de47b51 100644 (file)
@@ -16,7 +16,11 @@ void gic_enable_of_quirks(const struct device_node *np,
                          const struct gic_quirk *quirks, void *data)
 {
        for (; quirks->desc; quirks++) {
-               if (!of_device_is_compatible(np, quirks->compatible))
+               if (quirks->compatible &&
+                   !of_device_is_compatible(np, quirks->compatible))
+                       continue;
+               if (quirks->property &&
+                   !of_property_read_bool(np, quirks->property))
                        continue;
                if (quirks->init(data))
                        pr_info("GIC: enabling workaround for %s\n",
@@ -28,7 +32,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
                void *data)
 {
        for (; quirks->desc; quirks++) {
-               if (quirks->compatible)
+               if (quirks->compatible || quirks->property)
                        continue;
                if (quirks->iidr != (quirks->mask & iidr))
                        continue;
index 27e3d4e..3db4592 100644 (file)
@@ -13,6 +13,7 @@
 struct gic_quirk {
        const char *desc;
        const char *compatible;
+       const char *property;
        bool (*init)(void *data);
        u32 iidr;
        u32 mask;
index 6fcee22..a605aa7 100644 (file)
@@ -39,6 +39,7 @@
 
 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996    (1ULL << 0)
 #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539  (1ULL << 1)
+#define FLAGS_WORKAROUND_MTK_GICR_SAVE         (1ULL << 2)
 
 #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
 
@@ -1720,6 +1721,15 @@ static bool gic_enable_quirk_msm8996(void *data)
        return true;
 }
 
+static bool gic_enable_quirk_mtk_gicr(void *data)
+{
+       struct gic_chip_data *d = data;
+
+       d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE;
+
+       return true;
+}
+
 static bool gic_enable_quirk_cavium_38539(void *data)
 {
        struct gic_chip_data *d = data;
@@ -1793,6 +1803,11 @@ static const struct gic_quirk gic_quirks[] = {
                .init   = gic_enable_quirk_msm8996,
        },
        {
+               .desc   = "GICv3: Mediatek Chromebook GICR save problem",
+               .property = "mediatek,broken-save-restore-fw",
+               .init   = gic_enable_quirk_mtk_gicr,
+       },
+       {
                .desc   = "GICv3: HIP06 erratum 161010803",
                .iidr   = 0x0204043b,
                .mask   = 0xffffffff,
@@ -1834,6 +1849,11 @@ static void gic_enable_nmi_support(void)
        if (!gic_prio_masking_enabled())
                return;
 
+       if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) {
+               pr_warn("Skipping NMI enable due to firmware issues\n");
+               return;
+       }
+
        ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
        if (!ppi_nmi_refs)
                return;
index eada5e0..5101a3f 100644 (file)
@@ -240,26 +240,27 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
        struct irq_domain *domain;
        struct device_node *np;
        u32 num_pins;
+       int ret = 0;
+
+       parent = bus_get_dev_root(&platform_bus_type);
+       if (!parent)
+               return -ENODEV;
 
        for_each_child_of_node(pdev->dev.of_node, np) {
                if (!of_property_read_bool(np, "interrupt-controller"))
                        continue;
 
-               parent = bus_get_dev_root(&platform_bus_type);
-               if (parent) {
-                       child = of_platform_device_create(np, NULL, parent);
-                       put_device(parent);
-                       if (!child) {
-                               of_node_put(np);
-                               return -ENOMEM;
-                       }
+               child = of_platform_device_create(np, NULL, parent);
+               if (!child) {
+                       ret = -ENOMEM;
+                       break;
                }
 
                if (of_property_read_u32(child->dev.of_node, "num-pins",
                                         &num_pins) < 0) {
                        dev_err(&pdev->dev, "No num-pins property\n");
-                       of_node_put(np);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       break;
                }
 
                domain = platform_msi_create_device_domain(&child->dev, num_pins,
@@ -267,12 +268,16 @@ static int mbigen_of_create_domain(struct platform_device *pdev,
                                                           &mbigen_domain_ops,
                                                           mgn_chip);
                if (!domain) {
-                       of_node_put(np);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       break;
                }
        }
 
-       return 0;
+       put_device(parent);
+       if (ret)
+               of_node_put(np);
+
+       return ret;
 }
 
 #ifdef CONFIG_ACPI
index 2aaa9aa..7da18ef 100644 (file)
@@ -150,7 +150,7 @@ static const struct meson_gpio_irq_params s4_params = {
        INIT_MESON_S4_COMMON_DATA(82)
 };
 
-static const struct of_device_id meson_irq_gpio_matches[] = {
+static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
        { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
        { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
        { .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
index 046c355..6d5ecc1 100644 (file)
@@ -50,7 +50,7 @@ void __iomem *mips_gic_base;
 
 static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks);
 
-static DEFINE_SPINLOCK(gic_lock);
+static DEFINE_RAW_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
 static int gic_shared_intrs;
 static unsigned int gic_cpu_pin;
@@ -210,7 +210,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 
        irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        switch (type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_FALLING:
                pol = GIC_POL_FALLING_EDGE;
@@ -250,7 +250,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
        else
                irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
                                                 handle_level_irq, NULL);
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
 }
@@ -268,7 +268,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                return -EINVAL;
 
        /* Assumption : cpumask refers to a single CPU */
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
 
        /* Re-route this IRQ */
        write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
@@ -279,7 +279,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
 
        irq_data_update_effective_affinity(d, cpumask_of(cpu));
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return IRQ_SET_MASK_OK;
 }
@@ -357,12 +357,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
        cd = irq_data_get_irq_chip_data(d);
        cd->mask = false;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        for_each_online_cpu(cpu) {
                write_gic_vl_other(mips_cm_vp_id(cpu));
                write_gic_vo_rmask(BIT(intr));
        }
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
@@ -375,12 +375,12 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
        cd = irq_data_get_irq_chip_data(d);
        cd->mask = true;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        for_each_online_cpu(cpu) {
                write_gic_vl_other(mips_cm_vp_id(cpu));
                write_gic_vo_smask(BIT(intr));
        }
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static void gic_all_vpes_irq_cpu_online(void)
@@ -393,19 +393,21 @@ static void gic_all_vpes_irq_cpu_online(void)
        unsigned long flags;
        int i;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
 
        for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
                unsigned int intr = local_intrs[i];
                struct gic_all_vpes_chip_data *cd;
 
+               if (!gic_local_irq_is_routable(intr))
+                       continue;
                cd = &gic_all_vpes_chip_data[intr];
                write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
                if (cd->mask)
                        write_gic_vl_smask(BIT(intr));
        }
 
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static struct irq_chip gic_all_vpes_local_irq_controller = {
@@ -435,11 +437,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
        data = irq_get_irq_data(virq);
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
        write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
        irq_data_update_effective_affinity(data, cpumask_of(cpu));
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
 }
@@ -531,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
        if (!gic_local_irq_is_routable(intr))
                return -EPERM;
 
-       spin_lock_irqsave(&gic_lock, flags);
+       raw_spin_lock_irqsave(&gic_lock, flags);
        for_each_online_cpu(cpu) {
                write_gic_vl_other(mips_cm_vp_id(cpu));
                write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
        }
-       spin_unlock_irqrestore(&gic_lock, flags);
+       raw_spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
 }
index c4a705c..fc6a12a 100644 (file)
@@ -98,6 +98,7 @@ static ssize_t mbox_test_message_write(struct file *filp,
                                       size_t count, loff_t *ppos)
 {
        struct mbox_test_device *tdev = filp->private_data;
+       char *message;
        void *data;
        int ret;
 
@@ -113,12 +114,13 @@ static ssize_t mbox_test_message_write(struct file *filp,
                return -EINVAL;
        }
 
-       mutex_lock(&tdev->mutex);
-
-       tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
-       if (!tdev->message)
+       message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
+       if (!message)
                return -ENOMEM;
 
+       mutex_lock(&tdev->mutex);
+
+       tdev->message = message;
        ret = copy_from_user(tdev->message, userbuf, count);
        if (ret) {
                ret = -EFAULT;
index 00c33ed..d920c41 100644 (file)
@@ -264,6 +264,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
                goto out_put;
        }
        req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        blk_execute_rq(req, false);
        ret = req_to_mmc_queue_req(req)->drv_op_result;
        blk_mq_free_request(req);
@@ -651,6 +652,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
        idatas[0] = idata;
        req_to_mmc_queue_req(req)->drv_op =
                rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        req_to_mmc_queue_req(req)->drv_op_data = idatas;
        req_to_mmc_queue_req(req)->ioc_count = 1;
        blk_execute_rq(req, false);
@@ -722,6 +724,7 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
        }
        req_to_mmc_queue_req(req)->drv_op =
                rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        req_to_mmc_queue_req(req)->drv_op_data = idata;
        req_to_mmc_queue_req(req)->ioc_count = n;
        blk_execute_rq(req, false);
@@ -2806,6 +2809,7 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
        if (IS_ERR(req))
                return PTR_ERR(req);
        req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        blk_execute_rq(req, false);
        ret = req_to_mmc_queue_req(req)->drv_op_result;
        if (ret >= 0) {
@@ -2844,6 +2848,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
                goto out_free;
        }
        req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
+       req_to_mmc_queue_req(req)->drv_op_result = -EIO;
        req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
        blk_execute_rq(req, false);
        err = req_to_mmc_queue_req(req)->drv_op_result;
index b24aa27..d2f6250 100644 (file)
@@ -540,9 +540,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
 
        if (host->mmc->caps & MMC_CAP_HW_RESET) {
                priv->rst_hw = devm_reset_control_get_optional_exclusive(dev, NULL);
-               if (IS_ERR(priv->rst_hw))
-                       return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw),
-                                            "reset controller error\n");
+               if (IS_ERR(priv->rst_hw)) {
+                       ret = dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw),
+                                           "reset controller error\n");
+                       goto free;
+               }
                if (priv->rst_hw)
                        host->mmc_host_ops.card_hw_reset = sdhci_cdns_mmc_hw_reset;
        }
index d7c0c0b..eebf946 100644 (file)
@@ -1634,6 +1634,10 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
        if (ret)
                return ret;
 
+       /* HS400/HS400ES require 8 bit bus */
+       if (!(host->mmc->caps & MMC_CAP_8_BIT_DATA))
+               host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES);
+
        if (mmc_gpio_get_cd(host->mmc) >= 0)
                host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 
@@ -1724,10 +1728,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                host->mmc_host_ops.init_card = usdhc_init_card;
        }
 
-       err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
-       if (err)
-               goto disable_ahb_clk;
-
        if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
                sdhci_esdhc_ops.platform_execute_tuning =
                                        esdhc_executing_tuning;
@@ -1735,15 +1735,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
        if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
                host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
 
-       if (host->mmc->caps & MMC_CAP_8_BIT_DATA &&
-           imx_data->socdata->flags & ESDHC_FLAG_HS400)
+       if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
                host->mmc->caps2 |= MMC_CAP2_HS400;
 
        if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
                host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;
 
-       if (host->mmc->caps & MMC_CAP_8_BIT_DATA &&
-           imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
+       if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
                host->mmc->caps2 |= MMC_CAP2_HS400_ES;
                host->mmc_host_ops.hs400_enhanced_strobe =
                                        esdhc_hs400_enhanced_strobe;
@@ -1765,6 +1763,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                        goto disable_ahb_clk;
        }
 
+       err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
+       if (err)
+               goto disable_ahb_clk;
+
        sdhci_esdhc_imx_hwinit(host);
 
        err = sdhci_add_host(host);
index 3fed888..edbaa14 100644 (file)
@@ -3947,7 +3947,11 @@ static int bond_slave_netdev_event(unsigned long event,
                unblock_netpoll_tx();
                break;
        case NETDEV_FEAT_CHANGE:
-               bond_compute_features(bond);
+               if (!bond->notifier_ctx) {
+                       bond->notifier_ctx = true;
+                       bond_compute_features(bond);
+                       bond->notifier_ctx = false;
+               }
                break;
        case NETDEV_RESEND_IGMP:
                /* Propagate to master device */
@@ -6342,6 +6346,8 @@ static int bond_init(struct net_device *bond_dev)
        if (!bond->wq)
                return -ENOMEM;
 
+       bond->notifier_ctx = false;
+
        spin_lock_init(&bond->stats_lock);
        netdev_lockdep_set_classes(bond_dev);
 
index 64a2f2f..08a46ff 100644 (file)
@@ -7170,7 +7170,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
                goto out;
        }
        if (chip->reset)
-               usleep_range(1000, 2000);
+               usleep_range(10000, 20000);
 
        /* Detect if the device is configured in single chip addressing mode,
         * otherwise continue with address specific smi init/detection.
index 82f94b1..5267e9d 100644 (file)
@@ -195,6 +195,7 @@ static int tc589_probe(struct pcmcia_device *link)
 {
        struct el3_private *lp;
        struct net_device *dev;
+       int ret;
 
        dev_dbg(&link->dev, "3c589_attach()\n");
 
@@ -218,7 +219,15 @@ static int tc589_probe(struct pcmcia_device *link)
 
        dev->ethtool_ops = &netdev_ethtool_ops;
 
-       return tc589_config(link);
+       ret = tc589_config(link);
+       if (ret)
+               goto err_free_netdev;
+
+       return 0;
+
+err_free_netdev:
+       free_netdev(dev);
+       return ret;
 }
 
 static void tc589_detach(struct pcmcia_device *link)
index 33a9574..32d2c6f 100644 (file)
@@ -1329,7 +1329,7 @@ static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
        return pdata->phy_if.phy_impl.an_outcome(pdata);
 }
 
-static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
+static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 {
        struct ethtool_link_ksettings *lks = &pdata->phy.lks;
        enum xgbe_mode mode;
@@ -1367,8 +1367,13 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 
        pdata->phy.duplex = DUPLEX_FULL;
 
-       if (xgbe_set_mode(pdata, mode) && pdata->an_again)
+       if (!xgbe_set_mode(pdata, mode))
+               return false;
+
+       if (pdata->an_again)
                xgbe_phy_reconfig_aneg(pdata);
+
+       return true;
 }
 
 static void xgbe_phy_status(struct xgbe_prv_data *pdata)
@@ -1398,7 +1403,8 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
                        return;
                }
 
-               xgbe_phy_status_result(pdata);
+               if (xgbe_phy_status_result(pdata))
+                       return;
 
                if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
                        clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
index 577d948..38e5b5a 100644 (file)
@@ -3834,6 +3834,11 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
        index = fec_enet_get_bd_index(last_bdp, &txq->bd);
        txq->tx_skbuff[index] = NULL;
 
+       /* Make sure the updates to rest of the descriptor are performed before
+        * transferring ownership.
+        */
+       dma_wmb();
+
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
         * it's the last BD of the frame, and to put the CRC on the end.
         */
@@ -3843,8 +3848,14 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
 
+       /* Make sure the update to bdp are performed before txq->bd.cur. */
+       dma_wmb();
+
        txq->bd.cur = bdp;
 
+       /* Trigger transmission start */
+       writel(0, txq->bd.reg_desc_active);
+
        return 0;
 }
 
@@ -3873,12 +3884,6 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
                sent_frames++;
        }
 
-       /* Make sure the update to bdp and tx_skbuff are performed. */
-       wmb();
-
-       /* Trigger transmission start */
-       writel(0, txq->bd.reg_desc_active);
-
        __netif_tx_unlock(nq);
 
        return sent_frames;
index 059bd91..52d0a12 100644 (file)
@@ -1152,11 +1152,11 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
        unsigned int total_rx_bytes = 0, total_rx_pkts = 0;
        unsigned int offset = rx_ring->rx_offset;
        struct xdp_buff *xdp = &rx_ring->xdp;
+       u32 cached_ntc = rx_ring->first_desc;
        struct ice_tx_ring *xdp_ring = NULL;
        struct bpf_prog *xdp_prog = NULL;
        u32 ntc = rx_ring->next_to_clean;
        u32 cnt = rx_ring->count;
-       u32 cached_ntc = ntc;
        u32 xdp_xmit = 0;
        u32 cached_ntu;
        bool failure;
index 7045fed..7af223b 100644 (file)
@@ -652,9 +652,7 @@ static void otx2_sqe_add_ext(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
                                htons(ext->lso_sb - skb_network_offset(skb));
                } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
                        ext->lso_format = pfvf->hw.lso_tsov6_idx;
-
-                       ipv6_hdr(skb)->payload_len =
-                               htons(ext->lso_sb - skb_network_offset(skb));
+                       ipv6_hdr(skb)->payload_len = htons(tcp_hdrlen(skb));
                } else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
                        __be16 l3_proto = vlan_get_protocol(skb);
                        struct udphdr *udph = udp_hdr(skb);
index a75fd07..834c644 100644 (file)
@@ -3269,18 +3269,14 @@ static int mtk_open(struct net_device *dev)
                        eth->dsa_meta[i] = md_dst;
                }
        } else {
-               /* Hardware special tag parsing needs to be disabled if at least
-                * one MAC does not use DSA.
+               /* Hardware DSA untagging and VLAN RX offloading need to be
+                * disabled if at least one MAC does not use DSA.
                 */
                u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
 
                val &= ~MTK_CDMP_STAG_EN;
                mtk_w32(eth, val, MTK_CDMP_IG_CTRL);
 
-               val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
-               val &= ~MTK_CDMQ_STAG_EN;
-               mtk_w32(eth, val, MTK_CDMQ_IG_CTRL);
-
                mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
        }
 
index d53de39..d532883 100644 (file)
@@ -1920,9 +1920,10 @@ static void mlx5_cmd_err_trace(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod
 static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status,
                           u32 syndrome, int err)
 {
+       const char *namep = mlx5_command_str(opcode);
        struct mlx5_cmd_stats *stats;
 
-       if (!err)
+       if (!err || !(strcmp(namep, "unknown command opcode")))
                return;
 
        stats = &dev->cmd.stats[opcode];
index f404978..7c0f2ad 100644 (file)
@@ -490,7 +490,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer,
                                (u64)timestamp_low;
                break;
        default:
-               if (tracer_event->event_id >= tracer->str_db.first_string_trace ||
+               if (tracer_event->event_id >= tracer->str_db.first_string_trace &&
                    tracer_event->event_id <= tracer->str_db.first_string_trace +
                                              tracer->str_db.num_string_trace) {
                        tracer_event->type = TRACER_EVENT_TYPE_STRING;
index b8987a4..8e999f2 100644 (file)
@@ -327,6 +327,7 @@ struct mlx5e_params {
        unsigned int sw_mtu;
        int hard_mtu;
        bool ptp_rx;
+       __be32 terminate_lkey_be;
 };
 
 static inline u8 mlx5e_get_dcb_num_tc(struct mlx5e_params *params)
index 7ac1ad9..7e8e96c 100644 (file)
@@ -51,7 +51,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
        if (err)
                goto out;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]);
                port_buffer->buffer[i].lossy =
                        MLX5_GET(bufferx_reg, buffer, lossy);
@@ -73,14 +73,24 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
                          port_buffer->buffer[i].lossy);
        }
 
-       port_buffer->headroom_size = total_used;
+       port_buffer->internal_buffers_size = 0;
+       for (i = MLX5E_MAX_NETWORK_BUFFER; i < MLX5E_TOTAL_BUFFERS; i++) {
+               buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]);
+               port_buffer->internal_buffers_size +=
+                       MLX5_GET(bufferx_reg, buffer, size) * port_buff_cell_sz;
+       }
+
        port_buffer->port_buffer_size =
                MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz;
-       port_buffer->spare_buffer_size =
-               port_buffer->port_buffer_size - total_used;
-
-       mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n",
-                 port_buffer->port_buffer_size,
+       port_buffer->headroom_size = total_used;
+       port_buffer->spare_buffer_size = port_buffer->port_buffer_size -
+                                        port_buffer->internal_buffers_size -
+                                        port_buffer->headroom_size;
+
+       mlx5e_dbg(HW, priv,
+                 "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n",
+                 port_buffer->port_buffer_size, port_buffer->headroom_size,
+                 port_buffer->internal_buffers_size,
                  port_buffer->spare_buffer_size);
 out:
        kfree(out);
@@ -206,11 +216,11 @@ static int port_update_pool_cfg(struct mlx5_core_dev *mdev,
        if (!MLX5_CAP_GEN(mdev, sbcam_reg))
                return 0;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
                lossless_buff_count += ((port_buffer->buffer[i].size) &&
                                       (!(port_buffer->buffer[i].lossy)));
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                p = select_sbcm_params(&port_buffer->buffer[i], lossless_buff_count);
                err = mlx5e_port_set_sbcm(mdev, 0, i,
                                          MLX5_INGRESS_DIR,
@@ -293,7 +303,7 @@ static int port_set_buffer(struct mlx5e_priv *priv,
        if (err)
                goto out;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
                u64 size = port_buffer->buffer[i].size;
                u64 xoff = port_buffer->buffer[i].xoff;
@@ -351,7 +361,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
 {
        int i;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                if (port_buffer->buffer[i].lossy) {
                        port_buffer->buffer[i].xoff = 0;
                        port_buffer->buffer[i].xon  = 0;
@@ -408,7 +418,7 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev,
        int err;
        int i;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                prio_count = 0;
                lossy_count = 0;
 
@@ -432,11 +442,11 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev,
        }
 
        if (changed) {
-               err = port_update_pool_cfg(mdev, port_buffer);
+               err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
 
-               err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz);
+               err = port_update_pool_cfg(mdev, port_buffer);
                if (err)
                        return err;
 
@@ -515,7 +525,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 
        if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
                update_prio2buffer = true;
-               for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+               for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
                        mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n",
                                  __func__, i, prio2buffer[i]);
 
@@ -530,7 +540,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
        }
 
        if (change & MLX5E_PORT_BUFFER_SIZE) {
-               for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+               for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                        mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
                        if (!port_buffer.buffer[i].lossy && !buffer_size[i]) {
                                mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n",
@@ -544,7 +554,9 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 
                mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used);
 
-               if (total_used > port_buffer.port_buffer_size)
+               if (total_used > port_buffer.headroom_size &&
+                   (total_used - port_buffer.headroom_size) >
+                           port_buffer.spare_buffer_size)
                        return -EINVAL;
 
                update_buffer = true;
index a6ef118..f4a19ff 100644 (file)
@@ -35,7 +35,8 @@
 #include "en.h"
 #include "port.h"
 
-#define MLX5E_MAX_BUFFER 8
+#define MLX5E_MAX_NETWORK_BUFFER 8
+#define MLX5E_TOTAL_BUFFERS 10
 #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */
 
 #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \
@@ -60,8 +61,9 @@ struct mlx5e_bufferx_reg {
 struct mlx5e_port_buffer {
        u32                       port_buffer_size;
        u32                       spare_buffer_size;
-       u32                       headroom_size;
-       struct mlx5e_bufferx_reg  buffer[MLX5E_MAX_BUFFER];
+       u32                       headroom_size;          /* Buffers 0-7 */
+       u32                       internal_buffers_size;  /* Buffers 8-9 */
+       struct mlx5e_bufferx_reg  buffer[MLX5E_MAX_NETWORK_BUFFER];
 };
 
 int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
index eb5abd0..3cbebfb 100644 (file)
@@ -175,6 +175,8 @@ static bool mlx5e_ptp_poll_ts_cq(struct mlx5e_cq *cq, int budget)
        /* ensure cq space is freed before enabling more cqes */
        wmb();
 
+       mlx5e_txqsq_wake(&ptpsq->txqsq);
+
        return work_done == budget;
 }
 
index fc923a9..0380a04 100644 (file)
@@ -84,7 +84,7 @@ mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state,
 
 int
 mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
-                       struct flow_action *flow_action,
+                       struct flow_action *flow_action, int from, int to,
                        struct mlx5_flow_attr *attr,
                        enum mlx5_flow_namespace_type ns_type)
 {
@@ -96,6 +96,11 @@ mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
        priv = parse_state->flow->priv;
 
        flow_action_for_each(i, act, flow_action) {
+               if (i < from)
+                       continue;
+               else if (i > to)
+                       break;
+
                tc_act = mlx5e_tc_act_get(act->id, ns_type);
                if (!tc_act || !tc_act->post_parse)
                        continue;
index 0e6e187..d6c12d0 100644 (file)
@@ -112,7 +112,7 @@ mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state,
 
 int
 mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state,
-                       struct flow_action *flow_action,
+                       struct flow_action *flow_action, int from, int to,
                        struct mlx5_flow_attr *attr,
                        enum mlx5_flow_namespace_type ns_type);
 
index 20c2d2e..f0c3464 100644 (file)
@@ -492,6 +492,19 @@ void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e)
        mlx5e_encap_dealloc(priv, e);
 }
 
+static void mlx5e_encap_put_locked(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e)
+{
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+       lockdep_assert_held(&esw->offloads.encap_tbl_lock);
+
+       if (!refcount_dec_and_test(&e->refcnt))
+               return;
+       list_del(&e->route_list);
+       hash_del_rcu(&e->encap_hlist);
+       mlx5e_encap_dealloc(priv, e);
+}
+
 static void mlx5e_decap_put(struct mlx5e_priv *priv, struct mlx5e_decap_entry *d)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -816,6 +829,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
        uintptr_t hash_key;
        int err = 0;
 
+       lockdep_assert_held(&esw->offloads.encap_tbl_lock);
+
        parse_attr = attr->parse_attr;
        tun_info = parse_attr->tun_info[out_index];
        mpls_info = &parse_attr->mpls_info[out_index];
@@ -829,7 +844,6 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
 
        hash_key = hash_encap_info(&key);
 
-       mutex_lock(&esw->offloads.encap_tbl_lock);
        e = mlx5e_encap_get(priv, &key, hash_key);
 
        /* must verify if encap is valid or not */
@@ -840,15 +854,6 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
                        goto out_err;
                }
 
-               mutex_unlock(&esw->offloads.encap_tbl_lock);
-               wait_for_completion(&e->res_ready);
-
-               /* Protect against concurrent neigh update. */
-               mutex_lock(&esw->offloads.encap_tbl_lock);
-               if (e->compl_result < 0) {
-                       err = -EREMOTEIO;
-                       goto out_err;
-               }
                goto attach_flow;
        }
 
@@ -877,15 +882,12 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv,
        INIT_LIST_HEAD(&e->flows);
        hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
        tbl_time_before = mlx5e_route_tbl_get_last_update(priv);
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
 
        if (family == AF_INET)
                err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e);
        else if (family == AF_INET6)
                err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e);
 
-       /* Protect against concurrent neigh update. */
-       mutex_lock(&esw->offloads.encap_tbl_lock);
        complete_all(&e->res_ready);
        if (err) {
                e->compl_result = err;
@@ -920,18 +922,15 @@ attach_flow:
        } else {
                flow_flag_set(flow, SLOW);
        }
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
 
        return err;
 
 out_err:
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
        if (e)
-               mlx5e_encap_put(priv, e);
+               mlx5e_encap_put_locked(priv, e);
        return err;
 
 out_err_init:
-       mutex_unlock(&esw->offloads.encap_tbl_lock);
        kfree(tun_info);
        kfree(e);
        return err;
@@ -1016,6 +1015,93 @@ out_err:
        return err;
 }
 
+int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
+                                struct mlx5e_tc_flow *flow,
+                                struct mlx5_flow_attr *attr,
+                                struct netlink_ext_ack *extack,
+                                bool *vf_tun)
+{
+       struct mlx5e_tc_flow_parse_attr *parse_attr;
+       struct mlx5_esw_flow_attr *esw_attr;
+       struct net_device *encap_dev = NULL;
+       struct mlx5e_rep_priv *rpriv;
+       struct mlx5e_priv *out_priv;
+       struct mlx5_eswitch *esw;
+       int out_index;
+       int err = 0;
+
+       if (!mlx5e_is_eswitch_flow(flow))
+               return 0;
+
+       parse_attr = attr->parse_attr;
+       esw_attr = attr->esw_attr;
+       *vf_tun = false;
+
+       esw = priv->mdev->priv.eswitch;
+       mutex_lock(&esw->offloads.encap_tbl_lock);
+       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
+               struct net_device *out_dev;
+               int mirred_ifindex;
+
+               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
+                       continue;
+
+               mirred_ifindex = parse_attr->mirred_ifindex[out_index];
+               out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex);
+               if (!out_dev) {
+                       NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found");
+                       err = -ENODEV;
+                       goto out;
+               }
+               err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index,
+                                        extack, &encap_dev);
+               dev_put(out_dev);
+               if (err)
+                       goto out;
+
+               if (esw_attr->dests[out_index].flags &
+                   MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE &&
+                   !esw_attr->dest_int_port)
+                       *vf_tun = true;
+
+               out_priv = netdev_priv(encap_dev);
+               rpriv = out_priv->ppriv;
+               esw_attr->dests[out_index].rep = rpriv->rep;
+               esw_attr->dests[out_index].mdev = out_priv->mdev;
+       }
+
+       if (*vf_tun && esw_attr->out_count > 1) {
+               NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported");
+               err = -EOPNOTSUPP;
+               goto out;
+       }
+
+out:
+       mutex_unlock(&esw->offloads.encap_tbl_lock);
+       return err;
+}
+
+void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv,
+                                   struct mlx5e_tc_flow *flow,
+                                   struct mlx5_flow_attr *attr)
+{
+       struct mlx5_esw_flow_attr *esw_attr;
+       int out_index;
+
+       if (!mlx5e_is_eswitch_flow(flow))
+               return;
+
+       esw_attr = attr->esw_attr;
+
+       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
+               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
+                       continue;
+
+               mlx5e_detach_encap(flow->priv, flow, attr, out_index);
+               kfree(attr->parse_attr->tun_info[out_index]);
+       }
+}
+
 static int cmp_route_info(struct mlx5e_route_key *a,
                          struct mlx5e_route_key *b)
 {
@@ -1369,11 +1455,13 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv,
        struct mlx5e_tc_flow *flow;
 
        list_for_each_entry(flow, encap_flows, tmp_list) {
-               struct mlx5_flow_attr *attr = flow->attr;
                struct mlx5_esw_flow_attr *esw_attr;
+               struct mlx5_flow_attr *attr;
 
                if (!mlx5e_is_offloaded_flow(flow))
                        continue;
+
+               attr = mlx5e_tc_get_encap_attr(flow);
                esw_attr = attr->esw_attr;
 
                if (flow_flag_test(flow, SLOW))
index 8ad273d..5d7d676 100644 (file)
@@ -30,6 +30,15 @@ int mlx5e_attach_decap_route(struct mlx5e_priv *priv,
 void mlx5e_detach_decap_route(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow);
 
+int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
+                                struct mlx5e_tc_flow *flow,
+                                struct mlx5_flow_attr *attr,
+                                struct netlink_ext_ack *extack,
+                                bool *vf_tun);
+void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv,
+                                   struct mlx5e_tc_flow *flow,
+                                   struct mlx5_flow_attr *attr);
+
 struct ip_tunnel_info *mlx5e_dup_tun_info(const struct ip_tunnel_info *tun_info);
 
 int mlx5e_tc_set_attr_rx_tun(struct mlx5e_tc_flow *flow,
index 47381e9..879d698 100644 (file)
@@ -193,6 +193,8 @@ static inline u16 mlx5e_txqsq_get_next_pi(struct mlx5e_txqsq *sq, u16 size)
        return pi;
 }
 
+void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq);
+
 static inline u16 mlx5e_shampo_get_cqe_header_index(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
 {
        return be16_to_cpu(cqe->shampo.header_entry_index) & (rq->mpwqe.shampo->hd_per_wq - 1);
index 1f90594..41c396e 100644 (file)
@@ -150,10 +150,8 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
 
        inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
        in = kvzalloc(inlen, GFP_KERNEL);
-       if (!in) {
-               err = -ENOMEM;
-               goto out;
-       }
+       if (!in)
+               return -ENOMEM;
 
        if (enable_uc_lb)
                lb_flags = MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST;
@@ -171,14 +169,13 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb,
                tirn = tir->tirn;
                err = mlx5_core_modify_tir(mdev, tirn, in);
                if (err)
-                       goto out;
+                       break;
        }
+       mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock);
 
-out:
        kvfree(in);
        if (err)
                netdev_err(priv->netdev, "refresh tir(0x%x) failed, %d\n", tirn, err);
-       mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock);
 
        return err;
 }
index 89de92d..ebee52a 100644 (file)
@@ -926,9 +926,10 @@ static int mlx5e_dcbnl_getbuffer(struct net_device *dev,
        if (err)
                return err;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++)
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
                dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size;
-       dcb_buffer->total_size = port_buffer.port_buffer_size;
+       dcb_buffer->total_size = port_buffer.port_buffer_size -
+                                port_buffer.internal_buffers_size;
 
        return 0;
 }
@@ -970,7 +971,7 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
        if (err)
                return err;
 
-       for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
+       for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
                if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) {
                        changed |= MLX5E_PORT_BUFFER_SIZE;
                        buffer_size = dcb_buffer->buffer_size;
index 2944691..a7c526e 100644 (file)
@@ -727,26 +727,6 @@ static void mlx5e_rq_free_shampo(struct mlx5e_rq *rq)
        mlx5e_rq_shampo_hd_free(rq);
 }
 
-static __be32 mlx5e_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev)
-{
-       u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {};
-       u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {};
-       int res;
-
-       if (!MLX5_CAP_GEN(dev, terminate_scatter_list_mkey))
-               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
-
-       MLX5_SET(query_special_contexts_in, in, opcode,
-                MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
-       res = mlx5_cmd_exec_inout(dev, query_special_contexts, in, out);
-       if (res)
-               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
-
-       res = MLX5_GET(query_special_contexts_out, out,
-                      terminate_scatter_list_mkey);
-       return cpu_to_be32(res);
-}
-
 static int mlx5e_alloc_rq(struct mlx5e_params *params,
                          struct mlx5e_xsk_param *xsk,
                          struct mlx5e_rq_param *rqp,
@@ -908,7 +888,7 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params,
                        /* check if num_frags is not a pow of two */
                        if (rq->wqe.info.num_frags < (1 << rq->wqe.info.log_num_frags)) {
                                wqe->data[f].byte_count = 0;
-                               wqe->data[f].lkey = mlx5e_get_terminate_scatter_list_mkey(mdev);
+                               wqe->data[f].lkey = params->terminate_lkey_be;
                                wqe->data[f].addr = 0;
                        }
                }
@@ -5007,6 +4987,8 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
        /* RQ */
        mlx5e_build_rq_params(mdev, params);
 
+       params->terminate_lkey_be = mlx5_core_get_terminate_scatter_list_mkey(mdev);
+
        params->packet_merge.timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT);
 
        /* CQ moderation params */
@@ -5279,12 +5261,16 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
 
        mlx5e_timestamp_init(priv);
 
+       priv->dfs_root = debugfs_create_dir("nic",
+                                           mlx5_debugfs_get_dev_root(mdev));
+
        fs = mlx5e_fs_init(priv->profile, mdev,
                           !test_bit(MLX5E_STATE_DESTROYING, &priv->state),
                           priv->dfs_root);
        if (!fs) {
                err = -ENOMEM;
                mlx5_core_err(mdev, "FS initialization failed, %d\n", err);
+               debugfs_remove_recursive(priv->dfs_root);
                return err;
        }
        priv->fs = fs;
@@ -5305,6 +5291,7 @@ static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
        mlx5e_health_destroy_reporters(priv);
        mlx5e_ktls_cleanup(priv);
        mlx5e_fs_cleanup(priv->fs);
+       debugfs_remove_recursive(priv->dfs_root);
        priv->fs = NULL;
 }
 
@@ -5851,8 +5838,8 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv)
 }
 
 static int
-mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mdev,
-                           const struct mlx5e_profile *new_profile, void *new_ppriv)
+mlx5e_netdev_init_profile(struct net_device *netdev, struct mlx5_core_dev *mdev,
+                         const struct mlx5e_profile *new_profile, void *new_ppriv)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        int err;
@@ -5868,6 +5855,25 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde
        err = new_profile->init(priv->mdev, priv->netdev);
        if (err)
                goto priv_cleanup;
+
+       return 0;
+
+priv_cleanup:
+       mlx5e_priv_cleanup(priv);
+       return err;
+}
+
+static int
+mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mdev,
+                           const struct mlx5e_profile *new_profile, void *new_ppriv)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+       int err;
+
+       err = mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv);
+       if (err)
+               return err;
+
        err = mlx5e_attach_netdev(priv);
        if (err)
                goto profile_cleanup;
@@ -5875,7 +5881,6 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde
 
 profile_cleanup:
        new_profile->cleanup(priv);
-priv_cleanup:
        mlx5e_priv_cleanup(priv);
        return err;
 }
@@ -5894,6 +5899,12 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
        priv->profile->cleanup(priv);
        mlx5e_priv_cleanup(priv);
 
+       if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+               mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv);
+               set_bit(MLX5E_STATE_DESTROYING, &priv->state);
+               return -EIO;
+       }
+
        err = mlx5e_netdev_attach_profile(netdev, mdev, new_profile, new_ppriv);
        if (err) { /* roll back to original profile */
                netdev_warn(netdev, "%s: new profile init failed, %d\n", __func__, err);
@@ -5955,8 +5966,11 @@ static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state)
        struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
 
-       if (!netif_device_present(netdev))
+       if (!netif_device_present(netdev)) {
+               if (test_bit(MLX5E_STATE_DESTROYING, &priv->state))
+                       mlx5e_destroy_mdev_resources(mdev);
                return -ENODEV;
+       }
 
        mlx5e_detach_netdev(priv);
        mlx5e_destroy_mdev_resources(mdev);
@@ -6002,9 +6016,6 @@ static int mlx5e_probe(struct auxiliary_device *adev,
        priv->profile = profile;
        priv->ppriv = NULL;
 
-       priv->dfs_root = debugfs_create_dir("nic",
-                                           mlx5_debugfs_get_dev_root(priv->mdev));
-
        err = profile->init(mdev, netdev);
        if (err) {
                mlx5_core_err(mdev, "mlx5e_nic_profile init failed, %d\n", err);
@@ -6033,7 +6044,6 @@ err_resume:
 err_profile_cleanup:
        profile->cleanup(priv);
 err_destroy_netdev:
-       debugfs_remove_recursive(priv->dfs_root);
        mlx5e_destroy_netdev(priv);
 err_devlink_port_unregister:
        mlx5e_devlink_port_unregister(mlx5e_dev);
@@ -6053,7 +6063,6 @@ static void mlx5e_remove(struct auxiliary_device *adev)
        unregister_netdev(priv->netdev);
        mlx5e_suspend(adev, state);
        priv->profile->cleanup(priv);
-       debugfs_remove_recursive(priv->dfs_root);
        mlx5e_destroy_netdev(priv);
        mlx5e_devlink_port_unregister(mlx5e_dev);
        mlx5e_destroy_devlink(mlx5e_dev);
index 1fc386e..3e7041b 100644 (file)
@@ -30,6 +30,7 @@
  * SOFTWARE.
  */
 
+#include <linux/debugfs.h>
 #include <linux/mlx5/fs.h>
 #include <net/switchdev.h>
 #include <net/pkt_cls.h>
@@ -812,11 +813,15 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev,
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
+       priv->dfs_root = debugfs_create_dir("nic",
+                                           mlx5_debugfs_get_dev_root(mdev));
+
        priv->fs = mlx5e_fs_init(priv->profile, mdev,
                                 !test_bit(MLX5E_STATE_DESTROYING, &priv->state),
                                 priv->dfs_root);
        if (!priv->fs) {
                netdev_err(priv->netdev, "FS allocation failed\n");
+               debugfs_remove_recursive(priv->dfs_root);
                return -ENOMEM;
        }
 
@@ -829,6 +834,7 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev,
 static void mlx5e_cleanup_rep(struct mlx5e_priv *priv)
 {
        mlx5e_fs_cleanup(priv->fs);
+       debugfs_remove_recursive(priv->dfs_root);
        priv->fs = NULL;
 }
 
index 728b82c..8a5a870 100644 (file)
@@ -1665,11 +1665,9 @@ bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_
 int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev, u16 *vport)
 {
        struct mlx5e_priv *out_priv, *route_priv;
-       struct mlx5_devcom *devcom = NULL;
        struct mlx5_core_dev *route_mdev;
        struct mlx5_eswitch *esw;
        u16 vhca_id;
-       int err;
 
        out_priv = netdev_priv(out_dev);
        esw = out_priv->mdev->priv.eswitch;
@@ -1678,6 +1676,9 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
 
        vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id);
        if (mlx5_lag_is_active(out_priv->mdev)) {
+               struct mlx5_devcom *devcom;
+               int err;
+
                /* In lag case we may get devices from different eswitch instances.
                 * If we failed to get vport num, it means, mostly, that we on the wrong
                 * eswitch.
@@ -1686,101 +1687,16 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
                if (err != -ENOENT)
                        return err;
 
+               rcu_read_lock();
                devcom = out_priv->mdev->priv.devcom;
-               esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
-               if (!esw)
-                       return -ENODEV;
-       }
-
-       err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
-       if (devcom)
-               mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
-       return err;
-}
-
-static int
-set_encap_dests(struct mlx5e_priv *priv,
-               struct mlx5e_tc_flow *flow,
-               struct mlx5_flow_attr *attr,
-               struct netlink_ext_ack *extack,
-               bool *vf_tun)
-{
-       struct mlx5e_tc_flow_parse_attr *parse_attr;
-       struct mlx5_esw_flow_attr *esw_attr;
-       struct net_device *encap_dev = NULL;
-       struct mlx5e_rep_priv *rpriv;
-       struct mlx5e_priv *out_priv;
-       int out_index;
-       int err = 0;
-
-       if (!mlx5e_is_eswitch_flow(flow))
-               return 0;
-
-       parse_attr = attr->parse_attr;
-       esw_attr = attr->esw_attr;
-       *vf_tun = false;
-
-       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
-               struct net_device *out_dev;
-               int mirred_ifindex;
-
-               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
-                       continue;
-
-               mirred_ifindex = parse_attr->mirred_ifindex[out_index];
-               out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex);
-               if (!out_dev) {
-                       NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found");
-                       err = -ENODEV;
-                       goto out;
-               }
-               err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index,
-                                        extack, &encap_dev);
-               dev_put(out_dev);
-               if (err)
-                       goto out;
+               esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+               err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV;
+               rcu_read_unlock();
 
-               if (esw_attr->dests[out_index].flags &
-                   MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE &&
-                   !esw_attr->dest_int_port)
-                       *vf_tun = true;
-
-               out_priv = netdev_priv(encap_dev);
-               rpriv = out_priv->ppriv;
-               esw_attr->dests[out_index].rep = rpriv->rep;
-               esw_attr->dests[out_index].mdev = out_priv->mdev;
-       }
-
-       if (*vf_tun && esw_attr->out_count > 1) {
-               NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported");
-               err = -EOPNOTSUPP;
-               goto out;
+               return err;
        }
 
-out:
-       return err;
-}
-
-static void
-clean_encap_dests(struct mlx5e_priv *priv,
-                 struct mlx5e_tc_flow *flow,
-                 struct mlx5_flow_attr *attr)
-{
-       struct mlx5_esw_flow_attr *esw_attr;
-       int out_index;
-
-       if (!mlx5e_is_eswitch_flow(flow))
-               return;
-
-       esw_attr = attr->esw_attr;
-
-       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
-               if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
-                       continue;
-
-               mlx5e_detach_encap(priv, flow, attr, out_index);
-               kfree(attr->parse_attr->tun_info[out_index]);
-       }
+       return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
 }
 
 static int
@@ -1819,7 +1735,7 @@ post_process_attr(struct mlx5e_tc_flow *flow,
        if (err)
                goto err_out;
 
-       err = set_encap_dests(flow->priv, flow, attr, extack, &vf_tun);
+       err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
        if (err)
                goto err_out;
 
@@ -3943,8 +3859,8 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
        struct mlx5_flow_attr *prev_attr;
        struct flow_action_entry *act;
        struct mlx5e_tc_act *tc_act;
+       int err, i, i_split = 0;
        bool is_missable;
-       int err, i;
 
        ns_type = mlx5e_get_flow_namespace(flow);
        list_add(&attr->list, &flow->attrs);
@@ -3985,7 +3901,8 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
                    i < flow_action->num_entries - 1)) {
                        is_missable = tc_act->is_missable ? tc_act->is_missable(act) : false;
 
-                       err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type);
+                       err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr,
+                                                     ns_type);
                        if (err)
                                goto out_free_post_acts;
 
@@ -3995,6 +3912,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
                                goto out_free_post_acts;
                        }
 
+                       i_split = i + 1;
                        list_add(&attr->list, &flow->attrs);
                }
 
@@ -4009,7 +3927,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
                }
        }
 
-       err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type);
+       err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr, ns_type);
        if (err)
                goto out_free_post_acts;
 
@@ -4323,7 +4241,7 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a
        if (attr->post_act_handle)
                mlx5e_tc_post_act_del(get_post_action(flow->priv), attr->post_act_handle);
 
-       clean_encap_dests(flow->priv, flow, attr);
+       mlx5e_tc_tun_encap_dests_unset(flow->priv, flow, attr);
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
                mlx5_fc_destroy(counter_dev, attr->counter);
@@ -5301,6 +5219,8 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv)
                goto err_action_counter;
        }
 
+       mlx5_esw_offloads_devcom_init(esw);
+
        return 0;
 
 err_action_counter:
@@ -5329,7 +5249,7 @@ void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv)
        priv = netdev_priv(rpriv->netdev);
        esw = priv->mdev->priv.eswitch;
 
-       mlx5e_tc_clean_fdb_peer_flows(esw);
+       mlx5_esw_offloads_devcom_cleanup(esw);
 
        mlx5e_tc_tun_cleanup(uplink_priv->encap);
 
@@ -5643,22 +5563,43 @@ bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb)
                                   0, NULL);
 }
 
+static struct mapping_ctx *
+mlx5e_get_priv_obj_mapping(struct mlx5e_priv *priv)
+{
+       struct mlx5e_tc_table *tc;
+       struct mlx5_eswitch *esw;
+       struct mapping_ctx *ctx;
+
+       if (is_mdev_switchdev_mode(priv->mdev)) {
+               esw = priv->mdev->priv.eswitch;
+               ctx = esw->offloads.reg_c0_obj_pool;
+       } else {
+               tc = mlx5e_fs_get_tc(priv->fs);
+               ctx = tc->mapping;
+       }
+
+       return ctx;
+}
+
 int mlx5e_tc_action_miss_mapping_get(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr,
                                     u64 act_miss_cookie, u32 *act_miss_mapping)
 {
-       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_mapped_obj mapped_obj = {};
+       struct mlx5_eswitch *esw;
        struct mapping_ctx *ctx;
        int err;
 
-       ctx = esw->offloads.reg_c0_obj_pool;
-
+       ctx = mlx5e_get_priv_obj_mapping(priv);
        mapped_obj.type = MLX5_MAPPED_OBJ_ACT_MISS;
        mapped_obj.act_miss_cookie = act_miss_cookie;
        err = mapping_add(ctx, &mapped_obj, act_miss_mapping);
        if (err)
                return err;
 
+       if (!is_mdev_switchdev_mode(priv->mdev))
+               return 0;
+
+       esw = priv->mdev->priv.eswitch;
        attr->act_id_restore_rule = esw_add_restore_rule(esw, *act_miss_mapping);
        if (IS_ERR(attr->act_id_restore_rule))
                goto err_rule;
@@ -5673,10 +5614,9 @@ err_rule:
 void mlx5e_tc_action_miss_mapping_put(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr,
                                      u32 act_miss_mapping)
 {
-       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
-       struct mapping_ctx *ctx;
+       struct mapping_ctx *ctx = mlx5e_get_priv_obj_mapping(priv);
 
-       ctx = esw->offloads.reg_c0_obj_pool;
-       mlx5_del_flow_rules(attr->act_id_restore_rule);
+       if (is_mdev_switchdev_mode(priv->mdev))
+               mlx5_del_flow_rules(attr->act_id_restore_rule);
        mapping_remove(ctx, act_miss_mapping);
 }
index df5e780..c7eb6b2 100644 (file)
@@ -762,6 +762,17 @@ static void mlx5e_tx_wi_consume_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_t
        }
 }
 
+void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq)
+{
+       if (netif_tx_queue_stopped(sq->txq) &&
+           mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) &&
+           mlx5e_ptpsq_fifo_has_room(sq) &&
+           !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) {
+               netif_tx_wake_queue(sq->txq);
+               sq->stats->wake++;
+       }
+}
+
 bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
 {
        struct mlx5e_sq_stats *stats;
@@ -861,13 +872,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
 
        netdev_tx_completed_queue(sq->txq, npkts, nbytes);
 
-       if (netif_tx_queue_stopped(sq->txq) &&
-           mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) &&
-           mlx5e_ptpsq_fifo_has_room(sq) &&
-           !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) {
-               netif_tx_wake_queue(sq->txq);
-               stats->wake++;
-       }
+       mlx5e_txqsq_wake(sq);
 
        return (i == MLX5E_TX_CQ_POLL_BUDGET);
 }
index a50bfda..fbb2d96 100644 (file)
@@ -161,20 +161,22 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
                }
        }
 
+       /* budget=0 means we may be in IRQ context, do as little as possible */
+       if (unlikely(!budget))
+               goto out;
+
        busy |= mlx5e_poll_xdpsq_cq(&c->xdpsq.cq);
 
        if (c->xdp)
                busy |= mlx5e_poll_xdpsq_cq(&c->rq_xdpsq.cq);
 
-       if (likely(budget)) { /* budget=0 means: don't poll rx rings */
-               if (xsk_open)
-                       work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget);
+       if (xsk_open)
+               work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget);
 
-               if (likely(budget - work_done))
-                       work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done);
+       if (likely(budget - work_done))
+               work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done);
 
-               busy |= work_done == budget;
-       }
+       busy |= work_done == budget;
 
        mlx5e_poll_ico_cq(&c->icosq.cq);
        if (mlx5e_poll_ico_cq(&c->async_icosq.cq))
index 1c35d72..3db4866 100644 (file)
@@ -824,7 +824,7 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev)
        ncomp_eqs = table->num_comp_eqs;
        cpus = kcalloc(ncomp_eqs, sizeof(*cpus), GFP_KERNEL);
        if (!cpus)
-               ret = -ENOMEM;
+               return -ENOMEM;
 
        i = 0;
        rcu_read_lock();
@@ -1104,7 +1104,7 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
        struct mlx5_eq_table *table = dev->priv.eq_table;
 
        mutex_lock(&table->lock); /* sync with create/destroy_async_eq */
-       mlx5_irq_table_destroy(dev);
+       mlx5_irq_table_free_irqs(dev);
        mutex_unlock(&table->lock);
 }
 
index 1a042c9..add6cfa 100644 (file)
@@ -342,6 +342,7 @@ struct mlx5_eswitch {
                u32             large_group_num;
        }  params;
        struct blocking_notifier_head n_head;
+       bool paired[MLX5_MAX_PORTS];
 };
 
 void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -369,6 +370,8 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs);
 void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf);
 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw);
 void mlx5_eswitch_disable(struct mlx5_eswitch *esw);
+void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw);
+void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw);
 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
                               u16 vport, const u8 *mac);
 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
@@ -767,6 +770,8 @@ static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {}
 static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; }
 static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) {}
 static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {}
+static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) {}
+static inline void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) {}
 static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
 static inline
 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; }
index 69215ff..8d19c20 100644 (file)
@@ -2742,6 +2742,9 @@ static int mlx5_esw_offloads_devcom_event(int event,
                    mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
                        break;
 
+               if (esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+                       break;
+
                err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
                if (err)
                        goto err_out;
@@ -2753,14 +2756,18 @@ static int mlx5_esw_offloads_devcom_event(int event,
                if (err)
                        goto err_pair;
 
+               esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true;
+               peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true;
                mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
                break;
 
        case ESW_OFFLOADS_DEVCOM_UNPAIR:
-               if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
+               if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)])
                        break;
 
                mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
+               esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false;
+               peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false;
                mlx5_esw_offloads_unpair(peer_esw);
                mlx5_esw_offloads_unpair(esw);
                mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
@@ -2779,7 +2786,7 @@ err_out:
        return err;
 }
 
-static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
+void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw)
 {
        struct mlx5_devcom *devcom = esw->dev->priv.devcom;
 
@@ -2802,7 +2809,7 @@ static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
                               ESW_OFFLOADS_DEVCOM_PAIR, esw);
 }
 
-static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
+void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
 {
        struct mlx5_devcom *devcom = esw->dev->priv.devcom;
 
@@ -3250,8 +3257,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
        if (err)
                goto err_vports;
 
-       esw_offloads_devcom_init(esw);
-
        return 0;
 
 err_vports:
@@ -3292,7 +3297,6 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
 
 void esw_offloads_disable(struct mlx5_eswitch *esw)
 {
-       esw_offloads_devcom_cleanup(esw);
        mlx5_eswitch_disable_pf_vf_vports(esw);
        esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
        esw_set_passing_vport_metadata(esw, false);
index adefde3..b7d779d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/mlx5/vport.h>
 #include "lib/devcom.h"
+#include "mlx5_core.h"
 
 static LIST_HEAD(devcom_list);
 
@@ -13,7 +14,7 @@ static LIST_HEAD(devcom_list);
 
 struct mlx5_devcom_component {
        struct {
-               void *data;
+               void __rcu *data;
        } device[MLX5_DEVCOM_PORTS_SUPPORTED];
 
        mlx5_devcom_event_handler_t handler;
@@ -77,6 +78,7 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
        if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
                return NULL;
 
+       mlx5_dev_list_lock();
        sguid0 = mlx5_query_nic_system_image_guid(dev);
        list_for_each_entry(iter, &devcom_list, list) {
                struct mlx5_core_dev *tmp_dev = NULL;
@@ -102,8 +104,10 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
 
        if (!priv) {
                priv = mlx5_devcom_list_alloc();
-               if (!priv)
-                       return ERR_PTR(-ENOMEM);
+               if (!priv) {
+                       devcom = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
 
                idx = 0;
                new_priv = true;
@@ -112,13 +116,16 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
        priv->devs[idx] = dev;
        devcom = mlx5_devcom_alloc(priv, idx);
        if (!devcom) {
-               kfree(priv);
-               return ERR_PTR(-ENOMEM);
+               if (new_priv)
+                       kfree(priv);
+               devcom = ERR_PTR(-ENOMEM);
+               goto out;
        }
 
        if (new_priv)
                list_add(&priv->list, &devcom_list);
-
+out:
+       mlx5_dev_list_unlock();
        return devcom;
 }
 
@@ -131,6 +138,7 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
        if (IS_ERR_OR_NULL(devcom))
                return;
 
+       mlx5_dev_list_lock();
        priv = devcom->priv;
        priv->devs[devcom->idx] = NULL;
 
@@ -141,10 +149,12 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
                        break;
 
        if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
-               return;
+               goto out;
 
        list_del(&priv->list);
        kfree(priv);
+out:
+       mlx5_dev_list_unlock();
 }
 
 void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
@@ -162,7 +172,7 @@ void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
        comp = &devcom->priv->components[id];
        down_write(&comp->sem);
        comp->handler = handler;
-       comp->device[devcom->idx].data = data;
+       rcu_assign_pointer(comp->device[devcom->idx].data, data);
        up_write(&comp->sem);
 }
 
@@ -176,8 +186,9 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
 
        comp = &devcom->priv->components[id];
        down_write(&comp->sem);
-       comp->device[devcom->idx].data = NULL;
+       RCU_INIT_POINTER(comp->device[devcom->idx].data, NULL);
        up_write(&comp->sem);
+       synchronize_rcu();
 }
 
 int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
@@ -193,12 +204,15 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
 
        comp = &devcom->priv->components[id];
        down_write(&comp->sem);
-       for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
-               if (i != devcom->idx && comp->device[i].data) {
-                       err = comp->handler(event, comp->device[i].data,
-                                           event_data);
+       for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
+               void *data = rcu_dereference_protected(comp->device[i].data,
+                                                      lockdep_is_held(&comp->sem));
+
+               if (i != devcom->idx && data) {
+                       err = comp->handler(event, data, event_data);
                        break;
                }
+       }
 
        up_write(&comp->sem);
        return err;
@@ -213,7 +227,7 @@ void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
        comp = &devcom->priv->components[id];
        WARN_ON(!rwsem_is_locked(&comp->sem));
 
-       comp->paired = paired;
+       WRITE_ONCE(comp->paired, paired);
 }
 
 bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
@@ -222,7 +236,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
        if (IS_ERR_OR_NULL(devcom))
                return false;
 
-       return devcom->priv->components[id].paired;
+       return READ_ONCE(devcom->priv->components[id].paired);
 }
 
 void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
@@ -236,7 +250,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
 
        comp = &devcom->priv->components[id];
        down_read(&comp->sem);
-       if (!comp->paired) {
+       if (!READ_ONCE(comp->paired)) {
                up_read(&comp->sem);
                return NULL;
        }
@@ -245,7 +259,29 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
                if (i != devcom->idx)
                        break;
 
-       return comp->device[i].data;
+       return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem));
+}
+
+void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id)
+{
+       struct mlx5_devcom_component *comp;
+       int i;
+
+       if (IS_ERR_OR_NULL(devcom))
+               return NULL;
+
+       for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (i != devcom->idx)
+                       break;
+
+       comp = &devcom->priv->components[id];
+       /* This can change concurrently, however 'data' pointer will remain
+        * valid for the duration of RCU read section.
+        */
+       if (!READ_ONCE(comp->paired))
+               return NULL;
+
+       return rcu_dereference(comp->device[i].data);
 }
 
 void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
index 94313c1..9a496f4 100644 (file)
@@ -41,6 +41,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
 
 void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
                                enum mlx5_devcom_components id);
+void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id);
 void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
                                   enum mlx5_devcom_components id);
 
index 995eb2d..d6ee016 100644 (file)
@@ -923,7 +923,6 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct pci_dev *pdev,
        }
 
        mlx5_pci_vsc_init(dev);
-       dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
        return 0;
 
 err_clr_master:
@@ -1049,7 +1048,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
 
        dev->dm = mlx5_dm_create(dev);
        if (IS_ERR(dev->dm))
-               mlx5_core_warn(dev, "Failed to init device memory%d\n", err);
+               mlx5_core_warn(dev, "Failed to init device memory %ld\n", PTR_ERR(dev->dm));
 
        dev->tracer = mlx5_fw_tracer_create(dev);
        dev->hv_vhca = mlx5_hv_vhca_create(dev);
@@ -1155,6 +1154,7 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
                goto err_cmd_cleanup;
        }
 
+       dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev);
        mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP);
 
        mlx5_start_health_poll(dev);
@@ -1802,15 +1802,16 @@ static void remove_one(struct pci_dev *pdev)
        struct devlink *devlink = priv_to_devlink(dev);
 
        set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
-       /* mlx5_drain_fw_reset() is using devlink APIs. Hence, we must drain
-        * fw_reset before unregistering the devlink.
+       /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using
+        * devlink notify APIs.
+        * Hence, we must drain them before unregistering the devlink.
         */
        mlx5_drain_fw_reset(dev);
+       mlx5_drain_health_wq(dev);
        devlink_unregister(devlink);
        mlx5_sriov_disable(pdev);
        mlx5_thermal_uninit(dev);
        mlx5_crdump_disable(dev);
-       mlx5_drain_health_wq(dev);
        mlx5_uninit_one(dev);
        mlx5_pci_close(dev);
        mlx5_mdev_uninit(dev);
index efd0c29..aa403a5 100644 (file)
@@ -15,6 +15,7 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev);
 void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev);
 int mlx5_irq_table_create(struct mlx5_core_dev *dev);
 void mlx5_irq_table_destroy(struct mlx5_core_dev *dev);
+void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev);
 int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table);
 int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table);
 struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev);
index 9d735c3..678f0be 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <linux/kernel.h>
 #include <linux/mlx5/driver.h>
+#include <linux/mlx5/qp.h>
 #include "mlx5_core.h"
 
 int mlx5_core_create_mkey(struct mlx5_core_dev *dev, u32 *mkey, u32 *in,
@@ -122,3 +123,23 @@ int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num)
        return mlx5_cmd_exec_in(dev, destroy_psv, in);
 }
 EXPORT_SYMBOL(mlx5_core_destroy_psv);
+
+__be32 mlx5_core_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev)
+{
+       u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {};
+       u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {};
+       u32 mkey;
+
+       if (!MLX5_CAP_GEN(dev, terminate_scatter_list_mkey))
+               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
+
+       MLX5_SET(query_special_contexts_in, in, opcode,
+                MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
+       if (mlx5_cmd_exec_inout(dev, query_special_contexts, in, out))
+               return MLX5_TERMINATE_SCATTER_LIST_LKEY;
+
+       mkey = MLX5_GET(query_special_contexts_out, out,
+                       terminate_scatter_list_mkey);
+       return cpu_to_be32(mkey);
+}
+EXPORT_SYMBOL(mlx5_core_get_terminate_scatter_list_mkey);
index 2245d3b..843da89 100644 (file)
@@ -32,6 +32,7 @@ struct mlx5_irq {
        struct mlx5_irq_pool *pool;
        int refcount;
        struct msi_map map;
+       u32 pool_index;
 };
 
 struct mlx5_irq_table {
@@ -132,7 +133,7 @@ static void irq_release(struct mlx5_irq *irq)
        struct cpu_rmap *rmap;
 #endif
 
-       xa_erase(&pool->irqs, irq->map.index);
+       xa_erase(&pool->irqs, irq->pool_index);
        /* free_irq requires that affinity_hint and rmap will be cleared before
         * calling it. To satisfy this requirement, we call
         * irq_cpu_rmap_remove() to remove the notifier
@@ -140,7 +141,7 @@ static void irq_release(struct mlx5_irq *irq)
        irq_update_affinity_hint(irq->map.virq, NULL);
 #ifdef CONFIG_RFS_ACCEL
        rmap = mlx5_eq_table_get_rmap(pool->dev);
-       if (rmap && irq->map.index)
+       if (rmap)
                irq_cpu_rmap_remove(rmap, irq->map.virq);
 #endif
 
@@ -231,12 +232,13 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i,
        if (!irq)
                return ERR_PTR(-ENOMEM);
        if (!i || !pci_msix_can_alloc_dyn(dev->pdev)) {
-               /* The vector at index 0 was already allocated.
-                * Just get the irq number. If dynamic irq is not supported
-                * vectors have also been allocated.
+               /* The vector at index 0 is always statically allocated. If
+                * dynamic irq is not supported all vectors are statically
+                * allocated. In both cases just get the irq number and set
+                * the index.
                 */
                irq->map.virq = pci_irq_vector(dev->pdev, i);
-               irq->map.index = 0;
+               irq->map.index = i;
        } else {
                irq->map = pci_msix_alloc_irq_at(dev->pdev, MSI_ANY_INDEX, af_desc);
                if (!irq->map.virq) {
@@ -276,11 +278,11 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i,
        }
        irq->pool = pool;
        irq->refcount = 1;
-       irq->map.index = i;
-       err = xa_err(xa_store(&pool->irqs, irq->map.index, irq, GFP_KERNEL));
+       irq->pool_index = i;
+       err = xa_err(xa_store(&pool->irqs, irq->pool_index, irq, GFP_KERNEL));
        if (err) {
                mlx5_core_err(dev, "Failed to alloc xa entry for irq(%u). err = %d\n",
-                             irq->map.index, err);
+                             irq->pool_index, err);
                goto err_xa;
        }
        return irq;
@@ -567,13 +569,13 @@ int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs,
        struct mlx5_irq *irq;
        int i;
 
-       af_desc.is_managed = 1;
+       af_desc.is_managed = false;
        for (i = 0; i < nirqs; i++) {
+               cpumask_clear(&af_desc.mask);
                cpumask_set_cpu(cpus[i], &af_desc.mask);
                irq = mlx5_irq_request(dev, i + 1, &af_desc, rmap);
                if (IS_ERR(irq))
                        break;
-               cpumask_clear(&af_desc.mask);
                irqs[i] = irq;
        }
 
@@ -691,6 +693,24 @@ static void irq_pools_destroy(struct mlx5_irq_table *table)
        irq_pool_free(table->pcif_pool);
 }
 
+static void mlx5_irq_pool_free_irqs(struct mlx5_irq_pool *pool)
+{
+       struct mlx5_irq *irq;
+       unsigned long index;
+
+       xa_for_each(&pool->irqs, index, irq)
+               free_irq(irq->map.virq, &irq->nh);
+}
+
+static void mlx5_irq_pools_free_irqs(struct mlx5_irq_table *table)
+{
+       if (table->sf_ctrl_pool) {
+               mlx5_irq_pool_free_irqs(table->sf_comp_pool);
+               mlx5_irq_pool_free_irqs(table->sf_ctrl_pool);
+       }
+       mlx5_irq_pool_free_irqs(table->pcif_pool);
+}
+
 /* irq_table API */
 
 int mlx5_irq_table_init(struct mlx5_core_dev *dev)
@@ -774,6 +794,17 @@ void mlx5_irq_table_destroy(struct mlx5_core_dev *dev)
        pci_free_irq_vectors(dev->pdev);
 }
 
+void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev)
+{
+       struct mlx5_irq_table *table = dev->priv.irq_table;
+
+       if (mlx5_core_is_sf(dev))
+               return;
+
+       mlx5_irq_pools_free_irqs(table);
+       pci_free_irq_vectors(dev->pdev);
+}
+
 int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table)
 {
        if (table->sf_comp_pool)
index e2f26d0..0692363 100644 (file)
@@ -63,6 +63,7 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
        struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
        struct devlink *devlink = priv_to_devlink(sf_dev->mdev);
 
+       mlx5_drain_health_wq(sf_dev->mdev);
        devlink_unregister(devlink);
        mlx5_uninit_one(sf_dev->mdev);
        iounmap(sf_dev->mdev->iseg);
index 3835ba3..1aa525e 100644 (file)
@@ -117,6 +117,8 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
        caps->gvmi              = MLX5_CAP_GEN(mdev, vhca_id);
        caps->flex_protocols    = MLX5_CAP_GEN(mdev, flex_parser_protocols);
        caps->sw_format_ver     = MLX5_CAP_GEN(mdev, steering_format_version);
+       caps->roce_caps.fl_rc_qp_when_roce_disabled =
+               MLX5_CAP_GEN(mdev, fl_rc_qp_when_roce_disabled);
 
        if (MLX5_CAP_GEN(mdev, roce)) {
                err = dr_cmd_query_nic_vport_roce_en(mdev, 0, &roce_en);
@@ -124,7 +126,7 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
                        return err;
 
                caps->roce_caps.roce_en = roce_en;
-               caps->roce_caps.fl_rc_qp_when_roce_disabled =
+               caps->roce_caps.fl_rc_qp_when_roce_disabled |=
                        MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_disabled);
                caps->roce_caps.fl_rc_qp_when_roce_enabled =
                        MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_enabled);
index 13e06a6..d6947fe 100644 (file)
@@ -213,6 +213,8 @@ struct mlx5dr_ptrn_mgr *mlx5dr_ptrn_mgr_create(struct mlx5dr_domain *dmn)
        }
 
        INIT_LIST_HEAD(&mgr->ptrn_list);
+       mutex_init(&mgr->modify_hdr_mutex);
+
        return mgr;
 
 free_mgr:
@@ -237,5 +239,6 @@ void mlx5dr_ptrn_mgr_destroy(struct mlx5dr_ptrn_mgr *mgr)
        }
 
        mlx5dr_icm_pool_destroy(mgr->ptrn_icm_pool);
+       mutex_destroy(&mgr->modify_hdr_mutex);
        kfree(mgr);
 }
index 9413aaf..e94fbb0 100644 (file)
@@ -15,7 +15,8 @@ static u32 dr_ste_crc32_calc(const void *input_data, size_t length)
 {
        u32 crc = crc32(0, input_data, length);
 
-       return (__force u32)htonl(crc);
+       return (__force u32)((crc >> 24) & 0xff) | ((crc << 8) & 0xff0000) |
+                           ((crc >> 8) & 0xff00) | ((crc << 24) & 0xff000000);
 }
 
 bool mlx5dr_ste_supp_ttl_cs_recalc(struct mlx5dr_cmd_caps *caps)
index afa3b92..0d5a41a 100644 (file)
@@ -245,12 +245,6 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts)
 
                skb = priv->rx_skb[rx_pi_rem];
 
-               skb_put(skb, datalen);
-
-               skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */
-
-               skb->protocol = eth_type_trans(skb, netdev);
-
                /* Alloc another RX SKB for this same index */
                rx_skb = mlxbf_gige_alloc_skb(priv, MLXBF_GIGE_DEFAULT_BUF_SZ,
                                              &rx_buf_dma, DMA_FROM_DEVICE);
@@ -259,6 +253,13 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts)
                priv->rx_skb[rx_pi_rem] = rx_skb;
                dma_unmap_single(priv->dev, *rx_wqe_addr,
                                 MLXBF_GIGE_DEFAULT_BUF_SZ, DMA_FROM_DEVICE);
+
+               skb_put(skb, datalen);
+
+               skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */
+
+               skb->protocol = eth_type_trans(skb, netdev);
+
                *rx_wqe_addr = rx_buf_dma;
        } else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR) {
                priv->stats.rx_mac_errors++;
index 2b6e046..ee26986 100644 (file)
@@ -1039,6 +1039,16 @@ static int lan966x_reset_switch(struct lan966x *lan966x)
 
        reset_control_reset(switch_reset);
 
+       /* Don't reinitialize the switch core, if it is already initialized. In
+        * case it is initialized twice, some pointers inside the queue system
+        * in HW will get corrupted and then after a while the queue system gets
+        * full and no traffic is passing through the switch. The issue is seen
+        * when loading and unloading the driver and sending traffic through the
+        * switch.
+        */
+       if (lan_rd(lan966x, SYS_RESET_CFG) & SYS_RESET_CFG_CORE_ENA)
+               return 0;
+
        lan_wr(SYS_RESET_CFG_CORE_ENA_SET(0), lan966x, SYS_RESET_CFG);
        lan_wr(SYS_RAM_INIT_RAM_INIT_SET(1), lan966x, SYS_RAM_INIT);
        ret = readx_poll_timeout(lan966x_ram_init, lan966x,
index 06d6292..d907727 100644 (file)
@@ -1279,8 +1279,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
        if (comp_read < 1)
                return;
 
-       apc->eth_stats.tx_cqes = comp_read;
-
        for (i = 0; i < comp_read; i++) {
                struct mana_tx_comp_oob *cqe_oob;
 
@@ -1363,8 +1361,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
                WARN_ON_ONCE(1);
 
        cq->work_done = pkt_transmitted;
-
-       apc->eth_stats.tx_cqes -= pkt_transmitted;
 }
 
 static void mana_post_pkt_rxq(struct mana_rxq *rxq)
@@ -1626,15 +1622,11 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
 {
        struct gdma_comp *comp = cq->gdma_comp_buf;
        struct mana_rxq *rxq = cq->rxq;
-       struct mana_port_context *apc;
        int comp_read, i;
 
-       apc = netdev_priv(rxq->ndev);
-
        comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER);
        WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER);
 
-       apc->eth_stats.rx_cqes = comp_read;
        rxq->xdp_flush = false;
 
        for (i = 0; i < comp_read; i++) {
@@ -1646,8 +1638,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
                        return;
 
                mana_process_rx_cqe(rxq, cq, &comp[i]);
-
-               apc->eth_stats.rx_cqes--;
        }
 
        if (rxq->xdp_flush)
index a64c814..0dc7867 100644 (file)
@@ -13,11 +13,9 @@ static const struct {
 } mana_eth_stats[] = {
        {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)},
        {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)},
-       {"tx_cqes", offsetof(struct mana_ethtool_stats, tx_cqes)},
        {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)},
        {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
                                        tx_cqe_unknown_type)},
-       {"rx_cqes", offsetof(struct mana_ethtool_stats, rx_cqes)},
        {"rx_coalesced_err", offsetof(struct mana_ethtool_stats,
                                        rx_coalesced_err)},
        {"rx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
index 0605d1e..7a549b8 100644 (file)
@@ -6138,6 +6138,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
        return 0;
 
 out_error:
+       nv_mgmt_release_sema(dev);
        if (phystate_orig)
                writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
 out_freering:
index a7e376e..4b19803 100644 (file)
@@ -616,10 +616,10 @@ struct rtl8169_private {
                struct work_struct work;
        } wk;
 
-       spinlock_t config25_lock;
-       spinlock_t mac_ocp_lock;
+       raw_spinlock_t config25_lock;
+       raw_spinlock_t mac_ocp_lock;
 
-       spinlock_t cfg9346_usage_lock;
+       raw_spinlock_t cfg9346_usage_lock;
        int cfg9346_usage_count;
 
        unsigned supports_gmii:1;
@@ -671,20 +671,20 @@ static void rtl_lock_config_regs(struct rtl8169_private *tp)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
+       raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
        if (!--tp->cfg9346_usage_count)
                RTL_W8(tp, Cfg9346, Cfg9346_Lock);
-       spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
 }
 
 static void rtl_unlock_config_regs(struct rtl8169_private *tp)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
+       raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
        if (!tp->cfg9346_usage_count++)
                RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
-       spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
 }
 
 static void rtl_pci_commit(struct rtl8169_private *tp)
@@ -698,10 +698,10 @@ static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
        unsigned long flags;
        u8 val;
 
-       spin_lock_irqsave(&tp->config25_lock, flags);
+       raw_spin_lock_irqsave(&tp->config25_lock, flags);
        val = RTL_R8(tp, Config2);
        RTL_W8(tp, Config2, (val & ~clear) | set);
-       spin_unlock_irqrestore(&tp->config25_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
 }
 
 static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
@@ -709,10 +709,10 @@ static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
        unsigned long flags;
        u8 val;
 
-       spin_lock_irqsave(&tp->config25_lock, flags);
+       raw_spin_lock_irqsave(&tp->config25_lock, flags);
        val = RTL_R8(tp, Config5);
        RTL_W8(tp, Config5, (val & ~clear) | set);
-       spin_unlock_irqrestore(&tp->config25_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
 }
 
 static bool rtl_is_8125(struct rtl8169_private *tp)
@@ -899,9 +899,9 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+       raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
        __r8168_mac_ocp_write(tp, reg, data);
-       spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
 }
 
 static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
@@ -919,9 +919,9 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
        unsigned long flags;
        u16 val;
 
-       spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+       raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
        val = __r8168_mac_ocp_read(tp, reg);
-       spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
 
        return val;
 }
@@ -932,10 +932,10 @@ static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
        unsigned long flags;
        u16 data;
 
-       spin_lock_irqsave(&tp->mac_ocp_lock, flags);
+       raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
        data = __r8168_mac_ocp_read(tp, reg);
        __r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
-       spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
 }
 
 /* Work around a hw issue with RTL8168g PHY, the quirk disables
@@ -1420,14 +1420,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
                        r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
        }
 
-       spin_lock_irqsave(&tp->config25_lock, flags);
+       raw_spin_lock_irqsave(&tp->config25_lock, flags);
        for (i = 0; i < tmp; i++) {
                options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
                if (wolopts & cfg[i].opt)
                        options |= cfg[i].mask;
                RTL_W8(tp, cfg[i].reg, options);
        }
-       spin_unlock_irqrestore(&tp->config25_lock, flags);
+       raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
 
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
@@ -5179,9 +5179,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        tp->eee_adv = -1;
        tp->ocp_base = OCP_STD_PHY_BASE;
 
-       spin_lock_init(&tp->cfg9346_usage_lock);
-       spin_lock_init(&tp->config25_lock);
-       spin_lock_init(&tp->mac_ocp_lock);
+       raw_spin_lock_init(&tp->cfg9346_usage_lock);
+       raw_spin_lock_init(&tp->config25_lock);
+       raw_spin_lock_init(&tp->mac_ocp_lock);
 
        dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
                                                   struct pcpu_sw_netstats);
index 29afadd..aace871 100644 (file)
@@ -1485,7 +1485,7 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
 
        if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - 1) {
                netif_stop_subqueue(ndev, 0);
-               return ret;
+               return NETDEV_TX_BUSY;
        }
 
        if (skb_put_padto(skb, ETH_ZLEN))
index 381b805..ef9971c 100644 (file)
@@ -171,9 +171,14 @@ static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 
        rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
                                     0);
+
+       /* If the partition does not exist, that is not an error. */
+       if (rc == -ENOENT)
+               return 0;
+
        if (rc) {
-               netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
-                         version_name);
+               netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n",
+                         version_name, rc);
                return rc;
        }
 
@@ -187,36 +192,33 @@ static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 static int efx_devlink_info_stored_versions(struct efx_nic *efx,
                                            struct devlink_info_req *req)
 {
-       int rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_BUNDLE,
-                                             DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
-       if (rc)
-               return rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_MC_FIRMWARE,
-                                             DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
-       if (rc)
-               return rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
-                                             EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
-       if (rc)
-               return rc;
-
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_EXPANSION_ROM,
-                                             EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
-       if (rc)
-               return rc;
+       int err;
 
-       rc = efx_devlink_info_nvram_partition(efx, req,
-                                             NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
-                                             EFX_DEVLINK_INFO_VERSION_FW_UEFI);
-       return rc;
+       /* We do not care here about the specific error but just if an error
+        * happened. The specific error will be reported inside the call
+        * through system messages, and if any error happened in any call
+        * below, we report it through extack.
+        */
+       err = efx_devlink_info_nvram_partition(efx, req,
+                                              NVRAM_PARTITION_TYPE_BUNDLE,
+                                              DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_MC_FIRMWARE,
+                                               DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
+                                               EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_EXPANSION_ROM,
+                                               EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
+
+       err |= efx_devlink_info_nvram_partition(efx, req,
+                                               NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
+                                               EFX_DEVLINK_INFO_VERSION_FW_UEFI);
+       return err;
 }
 
 #define EFX_VER_FLAG(_f)       \
@@ -587,27 +589,20 @@ static int efx_devlink_info_get(struct devlink *devlink,
 {
        struct efx_devlink *devlink_private = devlink_priv(devlink);
        struct efx_nic *efx = devlink_private->efx;
-       int rc;
+       int err;
 
-       /* Several different MCDI commands are used. We report first error
-        * through extack returning at that point. Specific error
-        * information via system messages.
+       /* Several different MCDI commands are used. We report if errors
+        * happened through extack. Specific error information via system
+        * messages inside the calls.
         */
-       rc = efx_devlink_info_board_cfg(efx, req);
-       if (rc) {
-               NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
-               return rc;
-       }
-       rc = efx_devlink_info_stored_versions(efx, req);
-       if (rc) {
-               NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
-               return rc;
-       }
-       rc = efx_devlink_info_running_versions(efx, req);
-       if (rc) {
-               NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
-               return rc;
-       }
+       err = efx_devlink_info_board_cfg(efx, req);
+
+       err |= efx_devlink_info_stored_versions(efx, req);
+
+       err |= efx_devlink_info_running_versions(efx, req);
+
+       if (err)
+               NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages");
 
        return 0;
 }
index 0327639..c004443 100644 (file)
@@ -624,13 +624,12 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
        if (!found) { /* We don't care. */
                netif_dbg(efx, drv, efx->net_dev,
                          "Ignoring foreign filter that doesn't egdev us\n");
-               rc = -EOPNOTSUPP;
-               goto release;
+               return -EOPNOTSUPP;
        }
 
        rc = efx_mae_match_check_caps(efx, &match.mask, NULL);
        if (rc)
-               goto release;
+               return rc;
 
        if (efx_tc_match_is_encap(&match.mask)) {
                enum efx_encap_type type;
@@ -639,8 +638,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
                if (type == EFX_ENCAP_TYPE_NONE) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Egress encap match on unsupported tunnel device");
-                       rc = -EOPNOTSUPP;
-                       goto release;
+                       return -EOPNOTSUPP;
                }
 
                rc = efx_mae_check_encap_type_supported(efx, type);
@@ -648,25 +646,24 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
                        NL_SET_ERR_MSG_FMT_MOD(extack,
                                               "Firmware reports no support for %s encap match",
                                               efx_tc_encap_type_name(type));
-                       goto release;
+                       return rc;
                }
 
                rc = efx_tc_flower_record_encap_match(efx, &match, type,
                                                      extack);
                if (rc)
-                       goto release;
+                       return rc;
        } else {
                /* This is not a tunnel decap rule, ignore it */
                netif_dbg(efx, drv, efx->net_dev,
                          "Ignoring foreign filter without encap match\n");
-               rc = -EOPNOTSUPP;
-               goto release;
+               return -EOPNOTSUPP;
        }
 
        rule = kzalloc(sizeof(*rule), GFP_USER);
        if (!rule) {
                rc = -ENOMEM;
-               goto release;
+               goto out_free;
        }
        INIT_LIST_HEAD(&rule->acts.list);
        rule->cookie = tc->cookie;
@@ -678,7 +675,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
                          "Ignoring already-offloaded rule (cookie %lx)\n",
                          tc->cookie);
                rc = -EEXIST;
-               goto release;
+               goto out_free;
        }
 
        act = kzalloc(sizeof(*act), GFP_USER);
@@ -843,6 +840,7 @@ release:
                                       efx_tc_match_action_ht_params);
                efx_tc_free_action_set_list(efx, &rule->acts, false);
        }
+out_free:
        kfree(rule);
        if (match.encap)
                efx_tc_flower_release_encap_match(efx, match.encap);
@@ -899,8 +897,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
                return rc;
        if (efx_tc_match_is_encap(&match.mask)) {
                NL_SET_ERR_MSG_MOD(extack, "Ingress enc_key matches not supported");
-               rc = -EOPNOTSUPP;
-               goto release;
+               return -EOPNOTSUPP;
        }
 
        if (tc->common.chain_index) {
@@ -924,9 +921,9 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
        if (old) {
                netif_dbg(efx, drv, efx->net_dev,
                          "Already offloaded rule (cookie %lx)\n", tc->cookie);
-               rc = -EEXIST;
                NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded");
-               goto release;
+               kfree(rule);
+               return -EEXIST;
        }
 
        /* Parse actions */
index 0fca815..52cab9d 100644 (file)
@@ -7233,8 +7233,7 @@ int stmmac_dvr_probe(struct device *device,
        ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                            NETIF_F_RXCSUM;
        ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                            NETDEV_XDP_ACT_XSK_ZEROCOPY |
-                            NETDEV_XDP_ACT_NDO_XMIT;
+                            NETDEV_XDP_ACT_XSK_ZEROCOPY;
 
        ret = stmmac_tc_init(priv, priv);
        if (!ret) {
index 9d4d8c3..aa6f16d 100644 (file)
@@ -117,6 +117,9 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
                return -EOPNOTSUPP;
        }
 
+       if (!prog)
+               xdp_features_clear_redirect_target(dev);
+
        need_update = !!priv->xdp_prog != !!prog;
        if (if_running && need_update)
                stmmac_xdp_release(dev);
@@ -131,5 +134,8 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
        if (if_running && need_update)
                stmmac_xdp_open(dev);
 
+       if (prog)
+               xdp_features_set_redirect_target(dev, false);
+
        return 0;
 }
index 2ee80ed..afa1d56 100644 (file)
@@ -119,7 +119,7 @@ enum ipa_status_field_id {
 };
 
 /* Size in bytes of an IPA packet status structure */
-#define IPA_STATUS_SIZE                        sizeof(__le32[4])
+#define IPA_STATUS_SIZE                        sizeof(__le32[8])
 
 /* IPA status structure decoder; looks up field values for a structure */
 static u32 ipa_status_extract(struct ipa *ipa, const void *data,
index a50235f..defe5cc 100644 (file)
@@ -179,6 +179,7 @@ enum rgmii_clock_delay {
 #define VSC8502_RGMII_CNTL               20
 #define VSC8502_RGMII_RX_DELAY_MASK      0x0070
 #define VSC8502_RGMII_TX_DELAY_MASK      0x0007
+#define VSC8502_RGMII_RX_CLK_DISABLE     0x0800
 
 #define MSCC_PHY_WOL_LOWER_MAC_ADDR      21
 #define MSCC_PHY_WOL_MID_MAC_ADDR        22
@@ -276,6 +277,7 @@ enum rgmii_clock_delay {
 /* Microsemi PHY ID's
  *   Code assumes lowest nibble is 0
  */
+#define PHY_ID_VSC8501                   0x00070530
 #define PHY_ID_VSC8502                   0x00070630
 #define PHY_ID_VSC8504                   0x000704c0
 #define PHY_ID_VSC8514                   0x00070670
index 62bf99e..28df8a2 100644 (file)
@@ -519,16 +519,27 @@ out_unlock:
  *  * 2.0 ns (which causes the data to be sampled at exactly half way between
  *    clock transitions at 1000 Mbps) if delays should be enabled
  */
-static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
-                                  u16 rgmii_rx_delay_mask,
-                                  u16 rgmii_tx_delay_mask)
+static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
+                                    u16 rgmii_rx_delay_mask,
+                                    u16 rgmii_tx_delay_mask)
 {
        u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
        u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
        u16 reg_val = 0;
-       int rc;
+       u16 mask = 0;
+       int rc = 0;
 
-       mutex_lock(&phydev->lock);
+       /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
+        * to be unset for all PHY modes, so do that as part of the paged
+        * register modification.
+        * For some family members (like VSC8530/31/40/41) this bit is reserved
+        * and read-only, and the RX clock is enabled by default.
+        */
+       if (rgmii_cntl == VSC8502_RGMII_CNTL)
+               mask |= VSC8502_RGMII_RX_CLK_DISABLE;
+
+       if (phy_interface_is_rgmii(phydev))
+               mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
            phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
@@ -537,31 +548,20 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
            phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
                reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
 
-       rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
-                             rgmii_cntl,
-                             rgmii_rx_delay_mask | rgmii_tx_delay_mask,
-                             reg_val);
-
-       mutex_unlock(&phydev->lock);
+       if (mask)
+               rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
+                                     rgmii_cntl, mask, reg_val);
 
        return rc;
 }
 
 static int vsc85xx_default_config(struct phy_device *phydev)
 {
-       int rc;
-
        phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
 
-       if (phy_interface_mode_is_rgmii(phydev->interface)) {
-               rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL,
-                                            VSC8502_RGMII_RX_DELAY_MASK,
-                                            VSC8502_RGMII_TX_DELAY_MASK);
-               if (rc)
-                       return rc;
-       }
-
-       return 0;
+       return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL,
+                                        VSC8502_RGMII_RX_DELAY_MASK,
+                                        VSC8502_RGMII_TX_DELAY_MASK);
 }
 
 static int vsc85xx_get_tunable(struct phy_device *phydev,
@@ -1758,13 +1758,11 @@ static int vsc8584_config_init(struct phy_device *phydev)
        if (ret)
                return ret;
 
-       if (phy_interface_is_rgmii(phydev)) {
-               ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL,
-                                             VSC8572_RGMII_RX_DELAY_MASK,
-                                             VSC8572_RGMII_TX_DELAY_MASK);
-               if (ret)
-                       return ret;
-       }
+       ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL,
+                                       VSC8572_RGMII_RX_DELAY_MASK,
+                                       VSC8572_RGMII_TX_DELAY_MASK);
+       if (ret)
+               return ret;
 
        ret = genphy_soft_reset(phydev);
        if (ret)
@@ -2317,6 +2315,30 @@ static int vsc85xx_probe(struct phy_device *phydev)
 /* Microsemi VSC85xx PHYs */
 static struct phy_driver vsc85xx_driver[] = {
 {
+       .phy_id         = PHY_ID_VSC8501,
+       .name           = "Microsemi GE VSC8501 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_BASIC_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc85xx_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .read_status    = &vsc85xx_read_status,
+       .handle_interrupt = vsc85xx_handle_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc85xx_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
+{
        .phy_id         = PHY_ID_VSC8502,
        .name           = "Microsemi GE VSC8502 SyncE",
        .phy_id_mask    = 0xfffffff0,
@@ -2656,6 +2678,8 @@ static struct phy_driver vsc85xx_driver[] = {
 module_phy_driver(vsc85xx_driver);
 
 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
+       { PHY_ID_VSC8501, 0xfffffff0, },
+       { PHY_ID_VSC8502, 0xfffffff0, },
        { PHY_ID_VSC8504, 0xfffffff0, },
        { PHY_ID_VSC8514, 0xfffffff0, },
        { PHY_ID_VSC8530, 0xfffffff0, },
index 6301a9a..ea1073a 100644 (file)
@@ -274,13 +274,6 @@ static int gpy_config_init(struct phy_device *phydev)
        return ret < 0 ? ret : 0;
 }
 
-static bool gpy_has_broken_mdint(struct phy_device *phydev)
-{
-       /* At least these PHYs are known to have broken interrupt handling */
-       return phydev->drv->phy_id == PHY_ID_GPY215B ||
-              phydev->drv->phy_id == PHY_ID_GPY215C;
-}
-
 static int gpy_probe(struct phy_device *phydev)
 {
        struct device *dev = &phydev->mdio.dev;
@@ -300,8 +293,7 @@ static int gpy_probe(struct phy_device *phydev)
        phydev->priv = priv;
        mutex_init(&priv->mbox_lock);
 
-       if (gpy_has_broken_mdint(phydev) &&
-           !device_property_present(dev, "maxlinear,use-broken-interrupts"))
+       if (!device_property_present(dev, "maxlinear,use-broken-interrupts"))
                phydev->dev_flags |= PHY_F_NO_IRQ;
 
        fw_version = phy_read(phydev, PHY_FWV);
@@ -659,11 +651,9 @@ static irqreturn_t gpy_handle_interrupt(struct phy_device *phydev)
         * frame. Therefore, polling is the best we can do and won't do any more
         * harm.
         * It was observed that this bug happens on link state and link speed
-        * changes on a GPY215B and GYP215C independent of the firmware version
-        * (which doesn't mean that this list is exhaustive).
+        * changes independent of the firmware version.
         */
-       if (gpy_has_broken_mdint(phydev) &&
-           (reg & (PHY_IMASK_LSTC | PHY_IMASK_LSPC))) {
+       if (reg & (PHY_IMASK_LSTC | PHY_IMASK_LSPC)) {
                reg = gpy_mbox_read(phydev, REG_GPIO0_OUT);
                if (reg < 0) {
                        phy_error(phydev);
index d10606f..555b0b1 100644 (file)
@@ -1629,6 +1629,7 @@ static int team_init(struct net_device *dev)
 
        team->dev = dev;
        team_set_no_mode(team);
+       team->notifier_ctx = false;
 
        team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
        if (!team->pcpu_stats)
@@ -3022,7 +3023,11 @@ static int team_device_event(struct notifier_block *unused,
                team_del_slave(port->team->dev, dev);
                break;
        case NETDEV_FEAT_CHANGE:
-               team_compute_features(port->team);
+               if (!port->team->notifier_ctx) {
+                       port->team->notifier_ctx = true;
+                       team_compute_features(port->team);
+                       port->team->notifier_ctx = false;
+               }
                break;
        case NETDEV_PRECHANGEMTU:
                /* Forbid to change mtu of underlaying device */
index 6ce8f4f..db05622 100644 (file)
@@ -181,9 +181,12 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx)
        else
                min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32);
 
-       max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize));
-       if (max == 0)
+       if (le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) == 0)
                max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */
+       else
+               max = clamp_t(u32, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize),
+                             USB_CDC_NCM_NTB_MIN_OUT_SIZE,
+                             CDC_NCM_NTB_MAX_SIZE_TX);
 
        /* some devices set dwNtbOutMaxSize too low for the above default */
        min = min(min, max);
@@ -1244,6 +1247,9 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
                         * further.
                         */
                        if (skb_out == NULL) {
+                               /* If even the smallest allocation fails, abort. */
+                               if (ctx->tx_curr_size == USB_CDC_NCM_NTB_MIN_OUT_SIZE)
+                                       goto alloc_failed;
                                ctx->tx_low_mem_max_cnt = min(ctx->tx_low_mem_max_cnt + 1,
                                                              (unsigned)CDC_NCM_LOW_MEM_MAX_CNT);
                                ctx->tx_low_mem_val = ctx->tx_low_mem_max_cnt;
@@ -1262,13 +1268,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
                        skb_out = alloc_skb(ctx->tx_curr_size, GFP_ATOMIC);
 
                        /* No allocation possible so we will abort */
-                       if (skb_out == NULL) {
-                               if (skb != NULL) {
-                                       dev_kfree_skb_any(skb);
-                                       dev->net->stats.tx_dropped++;
-                               }
-                               goto exit_no_skb;
-                       }
+                       if (!skb_out)
+                               goto alloc_failed;
                        ctx->tx_low_mem_val--;
                }
                if (ctx->is_ndp16) {
@@ -1461,6 +1462,11 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
 
        return skb_out;
 
+alloc_failed:
+       if (skb) {
+               dev_kfree_skb_any(skb);
+               dev->net->stats.tx_dropped++;
+       }
 exit_no_skb:
        /* Start timer, if there is a remaining non-empty skb */
        if (ctx->tx_curr_skb != NULL && n > 0)
index 571e37e..f1865d0 100644 (file)
@@ -1325,7 +1325,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2001, 0x7e3d, 4)},    /* D-Link DWM-222 A2 */
        {QMI_FIXED_INTF(0x2020, 0x2031, 4)},    /* Olicard 600 */
        {QMI_FIXED_INTF(0x2020, 0x2033, 4)},    /* BroadMobi BM806U */
-       {QMI_FIXED_INTF(0x2020, 0x2060, 4)},    /* BroadMobi BM818 */
+       {QMI_QUIRK_SET_DTR(0x2020, 0x2060, 4)}, /* BroadMobi BM818 */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
index 44eeb17..a55381f 100644 (file)
@@ -336,10 +336,6 @@ static struct dentry *nfcsim_debugfs_root;
 static void nfcsim_debugfs_init(void)
 {
        nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
-
-       if (!nfcsim_debugfs_root)
-               pr_err("Could not create debugfs entry\n");
-
 }
 
 static void nfcsim_debugfs_remove(void)
index 3224458..492f319 100644 (file)
@@ -3424,6 +3424,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1e4B, 0x1202),   /* MAXIO MAP1202 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1e4B, 0x1602),   /* MAXIO MAP1602 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1cc1, 0x5350),   /* ADATA XPG GAMMIX S50 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1dbe, 0x5236),   /* ADATA XPG GAMMIX S70 */
index f4e2a88..c525867 100644 (file)
@@ -6003,8 +6003,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c1, aspm_l1_acceptable_latency
 
 #ifdef CONFIG_PCIE_DPC
 /*
- * Intel Tiger Lake and Alder Lake BIOS has a bug that clears the DPC
- * RP PIO Log Size of the integrated Thunderbolt PCIe Root Ports.
+ * Intel Ice Lake, Tiger Lake and Alder Lake BIOS has a bug that clears
+ * the DPC RP PIO Log Size of the integrated Thunderbolt PCIe Root
+ * Ports.
  */
 static void dpc_log_size(struct pci_dev *dev)
 {
@@ -6027,6 +6028,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x461f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x462f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x463f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x466e, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a1d, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a1f, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a21, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a23, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a23, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a25, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a27, dpc_log_size);
index c14089f..cabdddb 100644 (file)
@@ -70,7 +70,7 @@ static int phy_g12a_mipi_dphy_analog_power_on(struct phy *phy)
                     HHI_MIPI_CNTL1_BANDGAP);
 
        regmap_write(priv->regmap, HHI_MIPI_CNTL2,
-                    FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL0, 0x459) |
+                    FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL0, 0x45a) |
                     FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL1, 0x2680));
 
        reg = DSI_LANE_CLK;
index caa9537..8aa7251 100644 (file)
@@ -237,11 +237,11 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw,
         */
        if (tmds_clk < 54 * MEGA)
                txposdiv = 8;
-       else if (tmds_clk >= 54 * MEGA && tmds_clk < 148.35 * MEGA)
+       else if (tmds_clk >= 54 * MEGA && (tmds_clk * 100) < 14835 * MEGA)
                txposdiv = 4;
-       else if (tmds_clk >= 148.35 * MEGA && tmds_clk < 296.7 * MEGA)
+       else if ((tmds_clk * 100) >= 14835 * MEGA && (tmds_clk * 10) < 2967 * MEGA)
                txposdiv = 2;
-       else if (tmds_clk >= 296.7 * MEGA && tmds_clk <= 594 * MEGA)
+       else if ((tmds_clk * 10) >= 2967 * MEGA && tmds_clk <= 594 * MEGA)
                txposdiv = 1;
        else
                return -EINVAL;
@@ -324,12 +324,12 @@ static int mtk_hdmi_pll_drv_setting(struct clk_hw *hw)
                clk_channel_bias = 0x34; /* 20mA */
                impedance_en = 0xf;
                impedance = 0x36; /* 100ohm */
-       } else if (pixel_clk >= 74.175 * MEGA && pixel_clk <= 300 * MEGA) {
+       } else if (((u64)pixel_clk * 1000) >= 74175 * MEGA && pixel_clk <= 300 * MEGA) {
                data_channel_bias = 0x34; /* 20mA */
                clk_channel_bias = 0x2c; /* 16mA */
                impedance_en = 0xf;
                impedance = 0x36; /* 100ohm */
-       } else if (pixel_clk >= 27 * MEGA && pixel_clk < 74.175 * MEGA) {
+       } else if (pixel_clk >= 27 * MEGA && ((u64)pixel_clk * 1000) < 74175 * MEGA) {
                data_channel_bias = 0x14; /* 10mA */
                clk_channel_bias = 0x14; /* 10mA */
                impedance_en = 0x0;
index 6850e04..87b17e5 100644 (file)
@@ -2472,7 +2472,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
        ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
        if (ret) {
                dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-               goto err_unlock;
+               goto err_decrement_count;
        }
 
        ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets);
@@ -2522,7 +2522,8 @@ err_assert_reset:
        reset_control_bulk_assert(cfg->num_resets, qmp->resets);
 err_disable_regulators:
        regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-err_unlock:
+err_decrement_count:
+       qmp->init_count--;
        mutex_unlock(&qmp->phy_mutex);
 
        return ret;
index 09824be..0c603bc 100644 (file)
@@ -379,7 +379,7 @@ static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy)
        ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
        if (ret) {
                dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-               goto err_unlock;
+               goto err_decrement_count;
        }
 
        ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets);
@@ -409,7 +409,8 @@ err_assert_reset:
        reset_control_bulk_assert(cfg->num_resets, qmp->resets);
 err_disable_regulators:
        regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-err_unlock:
+err_decrement_count:
+       qmp->init_count--;
        mutex_unlock(&qmp->phy_mutex);
 
        return ret;
index a590635..6c237f3 100644 (file)
@@ -115,11 +115,11 @@ struct phy_override_seq {
  *
  * @cfg_ahb_clk: AHB2PHY interface clock
  * @ref_clk: phy reference clock
- * @iface_clk: phy interface clock
  * @phy_reset: phy reset control
  * @vregs: regulator supplies bulk data
  * @phy_initialized: if PHY has been initialized correctly
  * @mode: contains the current mode the PHY is in
+ * @update_seq_cfg: tuning parameters for phy init
  */
 struct qcom_snps_hsphy {
        struct phy *phy;
index c2c9b0d..be967d7 100644 (file)
@@ -1348,9 +1348,8 @@ static int mlxbf_pmc_map_counters(struct device *dev)
 
        for (i = 0; i < pmc->total_blocks; ++i) {
                if (strstr(pmc->block_name[i], "tile")) {
-                       ret = sscanf(pmc->block_name[i], "tile%d", &tile_num);
-                       if (ret < 0)
-                               return ret;
+                       if (sscanf(pmc->block_name[i], "tile%d", &tile_num) != 1)
+                               return -EINVAL;
 
                        if (tile_num >= pmc->tile_count)
                                continue;
index d5bb775..ee5f124 100644 (file)
@@ -245,24 +245,29 @@ static const struct pci_device_id pmf_pci_ids[] = {
        { }
 };
 
-int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
+static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
 {
        u64 phys_addr;
        u32 hi, low;
 
-       INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
+       phys_addr = virt_to_phys(dev->buf);
+       hi = phys_addr >> 32;
+       low = phys_addr & GENMASK(31, 0);
+
+       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
+       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
+}
 
+int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
+{
        /* Get Metrics Table Address */
        dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
        if (!dev->buf)
                return -ENOMEM;
 
-       phys_addr = virt_to_phys(dev->buf);
-       hi = phys_addr >> 32;
-       low = phys_addr & GENMASK(31, 0);
+       INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
 
-       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
-       amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
+       amd_pmf_set_dram_addr(dev);
 
        /*
         * Start collecting the metrics data after a small delay
@@ -273,6 +278,18 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
        return 0;
 }
 
+static int amd_pmf_resume_handler(struct device *dev)
+{
+       struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+
+       if (pdev->buf)
+               amd_pmf_set_dram_addr(pdev);
+
+       return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler);
+
 static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 {
        int ret;
@@ -413,6 +430,7 @@ static struct platform_driver amd_pmf_driver = {
                .name = "amd-pmf",
                .acpi_match_table = amd_pmf_acpi_ids,
                .dev_groups = amd_pmf_driver_groups,
+               .pm = pm_sleep_ptr(&amd_pmf_pm),
        },
        .probe = amd_pmf_probe,
        .remove_new = amd_pmf_remove,
index e2c9a68..fdf7da0 100644 (file)
@@ -555,6 +555,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */
        { KE_IGNORE, 0x79, },  /* Charger type dectection notification */
        { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */
+       { KE_IGNORE, 0x7B, }, /* Charger connect/disconnect notification */
        { KE_KEY, 0x7c, { KEY_MICMUTE } },
        { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */
        { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */
@@ -584,6 +585,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0xAE, { KEY_FN_F5 } }, /* Fn+F5 fan mode on 2020+ */
        { KE_KEY, 0xB3, { KEY_PROG4 } }, /* AURA */
        { KE_KEY, 0xB5, { KEY_CALC } },
+       { KE_IGNORE, 0xC0, }, /* External display connect/disconnect notification */
        { KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
        { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
        { KE_IGNORE, 0xC6, },  /* Ambient Light Sensor notification */
index 61dffb4..e6ae826 100644 (file)
@@ -208,7 +208,7 @@ static int scan_chunks_sanity_check(struct device *dev)
                        continue;
                reinit_completion(&ifs_done);
                local_work.dev = dev;
-               INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
+               INIT_WORK_ONSTACK(&local_work.w, copy_hashes_authenticate_chunks);
                schedule_work_on(cpu, &local_work.w);
                wait_for_completion(&ifs_done);
                if (ifsd->loading_error) {
index e0572a2..02fe360 100644 (file)
@@ -304,14 +304,13 @@ struct isst_if_pkg_info {
 static struct isst_if_cpu_info *isst_cpu_info;
 static struct isst_if_pkg_info *isst_pkg_info;
 
-#define ISST_MAX_PCI_DOMAINS   8
-
 static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
 {
        struct pci_dev *matched_pci_dev = NULL;
        struct pci_dev *pci_dev = NULL;
+       struct pci_dev *_pci_dev = NULL;
        int no_matches = 0, pkg_id;
-       int i, bus_number;
+       int bus_number;
 
        if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
            cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
@@ -323,12 +322,11 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
        if (bus_number < 0)
                return NULL;
 
-       for (i = 0; i < ISST_MAX_PCI_DOMAINS; ++i) {
-               struct pci_dev *_pci_dev;
+       for_each_pci_dev(_pci_dev) {
                int node;
 
-               _pci_dev = pci_get_domain_bus_and_slot(i, bus_number, PCI_DEVFN(dev, fn));
-               if (!_pci_dev)
+               if (_pci_dev->bus->number != bus_number ||
+                   _pci_dev->devfn != PCI_DEVFN(dev, fn))
                        continue;
 
                ++no_matches;
index 307ee6f..6f83e99 100644 (file)
@@ -624,10 +624,8 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
  */
 static void ab8500_btemp_external_power_changed(struct power_supply *psy)
 {
-       struct ab8500_btemp *di = power_supply_get_drvdata(psy);
-
-       class_for_each_device(power_supply_class, NULL,
-               di->btemp_psy, ab8500_btemp_get_ext_psy_data);
+       class_for_each_device(power_supply_class, NULL, psy,
+                             ab8500_btemp_get_ext_psy_data);
 }
 
 /* ab8500 btemp driver interrupts and their respective isr */
index 41a7bff..53560fb 100644 (file)
@@ -2407,10 +2407,8 @@ out:
  */
 static void ab8500_fg_external_power_changed(struct power_supply *psy)
 {
-       struct ab8500_fg *di = power_supply_get_drvdata(psy);
-
-       class_for_each_device(power_supply_class, NULL,
-               di->fg_psy, ab8500_fg_get_ext_psy_data);
+       class_for_each_device(power_supply_class, NULL, psy,
+                             ab8500_fg_get_ext_psy_data);
 }
 
 /**
index 05f4131..3be6f3b 100644 (file)
@@ -507,7 +507,7 @@ static void fuel_gauge_external_power_changed(struct power_supply *psy)
        mutex_lock(&info->lock);
        info->valid = 0; /* Force updating of the cached registers */
        mutex_unlock(&info->lock);
-       power_supply_changed(info->bat);
+       power_supply_changed(psy);
 }
 
 static struct power_supply_desc fuel_gauge_desc = {
index de67b98..dc33f00 100644 (file)
@@ -1262,6 +1262,7 @@ static void bq24190_input_current_limit_work(struct work_struct *work)
        bq24190_charger_set_property(bdi->charger,
                                     POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
                                     &val);
+       power_supply_changed(bdi->charger);
 }
 
 /* Sync the input-current-limit with our parent supply (if we have one) */
index 22cde35..f8636cf 100644 (file)
@@ -750,7 +750,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy)
        if (bq->chip_version != BQ25892)
                return;
 
-       ret = power_supply_get_property_from_supplier(bq->charger,
+       ret = power_supply_get_property_from_supplier(psy,
                                                      POWER_SUPPLY_PROP_USB_TYPE,
                                                      &val);
        if (ret)
@@ -775,6 +775,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy)
        }
 
        bq25890_field_write(bq, F_IINLIM, input_current_limit);
+       power_supply_changed(psy);
 }
 
 static int bq25890_get_chip_state(struct bq25890_device *bq,
@@ -1106,6 +1107,8 @@ static void bq25890_pump_express_work(struct work_struct *data)
        dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n",
                 voltage);
 
+       power_supply_changed(bq->charger);
+
        return;
 error_print:
        bq25890_field_write(bq, F_PUMPX_EN, 0);
index 5ff6f44..4296600 100644 (file)
@@ -1083,10 +1083,8 @@ static int poll_interval_param_set(const char *val, const struct kernel_param *k
                return ret;
 
        mutex_lock(&bq27xxx_list_lock);
-       list_for_each_entry(di, &bq27xxx_battery_devices, list) {
-               cancel_delayed_work_sync(&di->work);
-               schedule_delayed_work(&di->work, 0);
-       }
+       list_for_each_entry(di, &bq27xxx_battery_devices, list)
+               mod_delayed_work(system_wq, &di->work, 0);
        mutex_unlock(&bq27xxx_list_lock);
 
        return ret;
@@ -1761,60 +1759,6 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
        return POWER_SUPPLY_HEALTH_GOOD;
 }
 
-void bq27xxx_battery_update(struct bq27xxx_device_info *di)
-{
-       struct bq27xxx_reg_cache cache = {0, };
-       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
-
-       cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
-       if ((cache.flags & 0xff) == 0xff)
-               cache.flags = -1; /* read error */
-       if (cache.flags >= 0) {
-               cache.temperature = bq27xxx_battery_read_temperature(di);
-               if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
-                       cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
-               if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
-                       cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
-               if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
-                       cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
-
-               cache.charge_full = bq27xxx_battery_read_fcc(di);
-               cache.capacity = bq27xxx_battery_read_soc(di);
-               if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
-                       cache.energy = bq27xxx_battery_read_energy(di);
-               di->cache.flags = cache.flags;
-               cache.health = bq27xxx_battery_read_health(di);
-               if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
-                       cache.cycle_count = bq27xxx_battery_read_cyct(di);
-
-               /* We only have to read charge design full once */
-               if (di->charge_design_full <= 0)
-                       di->charge_design_full = bq27xxx_battery_read_dcap(di);
-       }
-
-       if ((di->cache.capacity != cache.capacity) ||
-           (di->cache.flags != cache.flags))
-               power_supply_changed(di->bat);
-
-       if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
-               di->cache = cache;
-
-       di->last_update = jiffies;
-}
-EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
-
-static void bq27xxx_battery_poll(struct work_struct *work)
-{
-       struct bq27xxx_device_info *di =
-                       container_of(work, struct bq27xxx_device_info,
-                                    work.work);
-
-       bq27xxx_battery_update(di);
-
-       if (poll_interval > 0)
-               schedule_delayed_work(&di->work, poll_interval * HZ);
-}
-
 static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags)
 {
        if (di->opts & BQ27XXX_O_ZERO)
@@ -1833,7 +1777,8 @@ static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags)
 static int bq27xxx_battery_current_and_status(
        struct bq27xxx_device_info *di,
        union power_supply_propval *val_curr,
-       union power_supply_propval *val_status)
+       union power_supply_propval *val_status,
+       struct bq27xxx_reg_cache *cache)
 {
        bool single_flags = (di->opts & BQ27XXX_O_ZERO);
        int curr;
@@ -1845,10 +1790,14 @@ static int bq27xxx_battery_current_and_status(
                return curr;
        }
 
-       flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags);
-       if (flags < 0) {
-               dev_err(di->dev, "error reading flags\n");
-               return flags;
+       if (cache) {
+               flags = cache->flags;
+       } else {
+               flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags);
+               if (flags < 0) {
+                       dev_err(di->dev, "error reading flags\n");
+                       return flags;
+               }
        }
 
        if (di->opts & BQ27XXX_O_ZERO) {
@@ -1883,6 +1832,78 @@ static int bq27xxx_battery_current_and_status(
        return 0;
 }
 
+static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+{
+       union power_supply_propval status = di->last_status;
+       struct bq27xxx_reg_cache cache = {0, };
+       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
+
+       cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
+       if ((cache.flags & 0xff) == 0xff)
+               cache.flags = -1; /* read error */
+       if (cache.flags >= 0) {
+               cache.temperature = bq27xxx_battery_read_temperature(di);
+               if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+                       cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+               if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+                       cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+               if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+                       cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+
+               cache.charge_full = bq27xxx_battery_read_fcc(di);
+               cache.capacity = bq27xxx_battery_read_soc(di);
+               if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
+                       cache.energy = bq27xxx_battery_read_energy(di);
+               di->cache.flags = cache.flags;
+               cache.health = bq27xxx_battery_read_health(di);
+               if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+                       cache.cycle_count = bq27xxx_battery_read_cyct(di);
+
+               /*
+                * On gauges with signed current reporting the current must be
+                * checked to detect charging <-> discharging status changes.
+                */
+               if (!(di->opts & BQ27XXX_O_ZERO))
+                       bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
+
+               /* We only have to read charge design full once */
+               if (di->charge_design_full <= 0)
+                       di->charge_design_full = bq27xxx_battery_read_dcap(di);
+       }
+
+       if ((di->cache.capacity != cache.capacity) ||
+           (di->cache.flags != cache.flags) ||
+           (di->last_status.intval != status.intval)) {
+               di->last_status.intval = status.intval;
+               power_supply_changed(di->bat);
+       }
+
+       if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
+               di->cache = cache;
+
+       di->last_update = jiffies;
+
+       if (!di->removed && poll_interval > 0)
+               mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
+}
+
+void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+{
+       mutex_lock(&di->lock);
+       bq27xxx_battery_update_unlocked(di);
+       mutex_unlock(&di->lock);
+}
+EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
+
+static void bq27xxx_battery_poll(struct work_struct *work)
+{
+       struct bq27xxx_device_info *di =
+                       container_of(work, struct bq27xxx_device_info,
+                                    work.work);
+
+       bq27xxx_battery_update(di);
+}
+
 /*
  * Get the average power in ÂµW
  * Return < 0 if something fails.
@@ -1985,10 +2006,8 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
        struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
        mutex_lock(&di->lock);
-       if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
-               cancel_delayed_work_sync(&di->work);
-               bq27xxx_battery_poll(&di->work.work);
-       }
+       if (time_is_before_jiffies(di->last_update + 5 * HZ))
+               bq27xxx_battery_update_unlocked(di);
        mutex_unlock(&di->lock);
 
        if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
@@ -1996,7 +2015,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               ret = bq27xxx_battery_current_and_status(di, NULL, val);
+               ret = bq27xxx_battery_current_and_status(di, NULL, val, NULL);
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                ret = bq27xxx_battery_voltage(di, val);
@@ -2005,7 +2024,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
                val->intval = di->cache.flags < 0 ? 0 : 1;
                break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
-               ret = bq27xxx_battery_current_and_status(di, val, NULL);
+               ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL);
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                ret = bq27xxx_simple_value(di->cache.capacity, val);
@@ -2078,8 +2097,8 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
 {
        struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
-       cancel_delayed_work_sync(&di->work);
-       schedule_delayed_work(&di->work, 0);
+       /* After charger plug in/out wait 0.5s for things to stabilize */
+       mod_delayed_work(system_wq, &di->work, HZ / 2);
 }
 
 int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
@@ -2127,22 +2146,18 @@ EXPORT_SYMBOL_GPL(bq27xxx_battery_setup);
 
 void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
 {
-       /*
-        * power_supply_unregister call bq27xxx_battery_get_property which
-        * call bq27xxx_battery_poll.
-        * Make sure that bq27xxx_battery_poll will not call
-        * schedule_delayed_work again after unregister (which cause OOPS).
-        */
-       poll_interval = 0;
-
-       cancel_delayed_work_sync(&di->work);
-
-       power_supply_unregister(di->bat);
-
        mutex_lock(&bq27xxx_list_lock);
        list_del(&di->list);
        mutex_unlock(&bq27xxx_list_lock);
 
+       /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */
+       mutex_lock(&di->lock);
+       di->removed = true;
+       mutex_unlock(&di->lock);
+
+       cancel_delayed_work_sync(&di->work);
+
+       power_supply_unregister(di->bat);
        mutex_destroy(&di->lock);
 }
 EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
index f876899..6d3c748 100644 (file)
@@ -179,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
        i2c_set_clientdata(client, di);
 
        if (client->irq) {
-               ret = devm_request_threaded_irq(&client->dev, client->irq,
+               ret = request_threaded_irq(client->irq,
                                NULL, bq27xxx_battery_irq_handler_thread,
                                IRQF_ONESHOT,
                                di->name, di);
@@ -209,6 +209,7 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client)
 {
        struct bq27xxx_device_info *di = i2c_get_clientdata(client);
 
+       free_irq(client->irq, di);
        bq27xxx_battery_teardown(di);
 
        mutex_lock(&battery_mutex);
index 92e48e3..1305cba 100644 (file)
@@ -796,7 +796,9 @@ static int mt6360_charger_probe(struct platform_device *pdev)
        mci->vinovp = 6500000;
        mutex_init(&mci->chgdet_lock);
        platform_set_drvdata(pdev, mci);
-       devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work);
+       ret = devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work);
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret, "Failed to set delayed work\n");
 
        ret = device_property_read_u32(&pdev->dev, "richtek,vinovp-microvolt", &mci->vinovp);
        if (ret)
index ab986db..3791aec 100644 (file)
@@ -348,6 +348,10 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
        struct power_supply *psy = dev_get_drvdata(dev);
        unsigned int *count = data;
 
+       if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_SCOPE, &ret))
+               if (ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
+                       return 0;
+
        (*count)++;
        if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
                if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
@@ -366,8 +370,8 @@ int power_supply_is_system_supplied(void)
                                      __power_supply_is_system_supplied);
 
        /*
-        * If no power class device was found at all, most probably we are
-        * running on a desktop system, so assume we are on mains power.
+        * If no system scope power class device was found at all, most probably we
+        * are running on a desktop system, so assume we are on mains power.
         */
        if (count == 0)
                return 1;
@@ -573,7 +577,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
        struct power_supply_battery_info *info;
        struct device_node *battery_np = NULL;
        struct fwnode_reference_args args;
-       struct fwnode_handle *fwnode;
+       struct fwnode_handle *fwnode = NULL;
        const char *value;
        int err, len, index;
        const __be32 *list;
@@ -585,7 +589,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
                        return -ENODEV;
 
                fwnode = fwnode_handle_get(of_fwnode_handle(battery_np));
-       } else {
+       } else if (psy->dev.parent) {
                err = fwnode_property_get_reference_args(
                                        dev_fwnode(psy->dev.parent),
                                        "monitored-battery", NULL, 0, 0, &args);
@@ -595,6 +599,9 @@ int power_supply_get_battery_info(struct power_supply *psy,
                fwnode = args.fwnode;
        }
 
+       if (!fwnode)
+               return -ENOENT;
+
        err = fwnode_property_read_string(fwnode, "compatible", &value);
        if (err)
                goto out_put_node;
index 702bf83..0674483 100644 (file)
@@ -35,8 +35,9 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
                led_trigger_event(psy->charging_full_trig, LED_FULL);
                led_trigger_event(psy->charging_trig, LED_OFF);
                led_trigger_event(psy->full_trig, LED_FULL);
-               led_trigger_event(psy->charging_blink_full_solid_trig,
-                       LED_FULL);
+               /* Going from blink to LED on requires a LED_OFF event to stop blink */
+               led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
+               led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);
                break;
        case POWER_SUPPLY_STATUS_CHARGING:
                led_trigger_event(psy->charging_full_trig, LED_FULL);
index ba3b125..06e5b6b 100644 (file)
@@ -286,7 +286,8 @@ static ssize_t power_supply_show_property(struct device *dev,
 
                if (ret < 0) {
                        if (ret == -ENODATA)
-                               dev_dbg(dev, "driver has no data for `%s' property\n",
+                               dev_dbg_ratelimited(dev,
+                                       "driver has no data for `%s' property\n",
                                        attr->attr.name);
                        else if (ret != -ENODEV && ret != -EAGAIN)
                                dev_err_ratelimited(dev,
index 73f744a..ea33693 100644 (file)
@@ -1023,7 +1023,7 @@ static int rt9467_request_interrupt(struct rt9467_chg_data *data)
        for (i = 0; i < num_chg_irqs; i++) {
                virq = regmap_irq_get_virq(data->irq_chip_data, chg_irqs[i].hwirq);
                if (virq <= 0)
-                       return dev_err_probe(dev, virq, "Failed to get (%s) irq\n",
+                       return dev_err_probe(dev, -EINVAL, "Failed to get (%s) irq\n",
                                             chg_irqs[i].name);
 
                ret = devm_request_threaded_irq(dev, virq, NULL, chg_irqs[i].handler,
index 75ebcbf..a14e89a 100644 (file)
@@ -24,7 +24,7 @@
 #define SBS_CHARGER_REG_STATUS                 0x13
 #define SBS_CHARGER_REG_ALARM_WARNING          0x16
 
-#define SBS_CHARGER_STATUS_CHARGE_INHIBITED    BIT(1)
+#define SBS_CHARGER_STATUS_CHARGE_INHIBITED    BIT(0)
 #define SBS_CHARGER_STATUS_RES_COLD            BIT(9)
 #define SBS_CHARGER_STATUS_RES_HOT             BIT(10)
 #define SBS_CHARGER_STATUS_BATTERY_PRESENT     BIT(14)
index 632977f..bd23c4d 100644 (file)
@@ -733,13 +733,6 @@ static int sc27xx_fgu_set_property(struct power_supply *psy,
        return ret;
 }
 
-static void sc27xx_fgu_external_power_changed(struct power_supply *psy)
-{
-       struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
-
-       power_supply_changed(data->battery);
-}
-
 static int sc27xx_fgu_property_is_writeable(struct power_supply *psy,
                                            enum power_supply_property psp)
 {
@@ -774,7 +767,7 @@ static const struct power_supply_desc sc27xx_fgu_desc = {
        .num_properties         = ARRAY_SIZE(sc27xx_fgu_props),
        .get_property           = sc27xx_fgu_get_property,
        .set_property           = sc27xx_fgu_set_property,
-       .external_power_changed = sc27xx_fgu_external_power_changed,
+       .external_power_changed = power_supply_changed,
        .property_is_writeable  = sc27xx_fgu_property_is_writeable,
        .no_thermal             = true,
 };
index dc741ac..698ab7f 100644 (file)
@@ -5256,7 +5256,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
        }
 
        rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
-       if (!rdev->debugfs) {
+       if (IS_ERR(rdev->debugfs)) {
                rdev_warn(rdev, "Failed to create debugfs directory\n");
                return;
        }
@@ -6178,7 +6178,7 @@ static int __init regulator_init(void)
        ret = class_register(&regulator_class);
 
        debugfs_root = debugfs_create_dir("regulator", NULL);
-       if (!debugfs_root)
+       if (IS_ERR(debugfs_root))
                pr_warn("regulator: Failed to create debugfs directory\n");
 
 #ifdef CONFIG_DEBUG_FS
index 1849566..3eb86ec 100644 (file)
@@ -951,9 +951,12 @@ static int mt6359_regulator_probe(struct platform_device *pdev)
        struct regulator_config config = {};
        struct regulator_dev *rdev;
        struct mt6359_regulator_info *mt6359_info;
-       int i, hw_ver;
+       int i, hw_ver, ret;
+
+       ret = regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
+       if (ret)
+               return ret;
 
-       regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver);
        if (hw_ver >= MT6359P_CHIP_VER)
                mt6359_info = mt6359p_regulators;
        else
index 87a746d..e75dd92 100644 (file)
@@ -264,7 +264,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
                        .vsel_mask = BUCK2OUT_DVS0_MASK,
                        .enable_reg = PCA9450_REG_BUCK2CTRL,
-                       .enable_mask = BUCK1_ENMODE_MASK,
+                       .enable_mask = BUCK2_ENMODE_MASK,
                        .ramp_reg = PCA9450_REG_BUCK2CTRL,
                        .ramp_mask = BUCK2_RAMP_MASK,
                        .ramp_delay_table = pca9450_dvs_buck_ramp_table,
@@ -502,7 +502,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
                        .vsel_mask = BUCK2OUT_DVS0_MASK,
                        .enable_reg = PCA9450_REG_BUCK2CTRL,
-                       .enable_mask = BUCK1_ENMODE_MASK,
+                       .enable_mask = BUCK2_ENMODE_MASK,
                        .ramp_reg = PCA9450_REG_BUCK2CTRL,
                        .ramp_mask = BUCK2_RAMP_MASK,
                        .ramp_delay_table = pca9450_dvs_buck_ramp_table,
index ac85d55..26e6633 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
@@ -301,49 +302,43 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
 }
 
 /**
- * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
+ * cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
  * @xspi:      Pointer to the cdns_spi structure
+ * @ntx:       Number of bytes to pack into the TX FIFO
+ * @nrx:       Number of bytes to drain from the RX FIFO
  */
-static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
+static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
 {
-       unsigned long trans_cnt = 0;
+       ntx = clamp(ntx, 0, xspi->tx_bytes);
+       nrx = clamp(nrx, 0, xspi->rx_bytes);
 
-       while ((trans_cnt < xspi->tx_fifo_depth) &&
-              (xspi->tx_bytes > 0)) {
+       xspi->tx_bytes -= ntx;
+       xspi->rx_bytes -= nrx;
 
+       while (ntx || nrx) {
                /* When xspi in busy condition, bytes may send failed,
                 * then spi control did't work thoroughly, add one byte delay
                 */
-               if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
-                   CDNS_SPI_IXR_TXFULL)
+               if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
                        udelay(10);
 
-               if (xspi->txbuf)
-                       cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
-               else
-                       cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
+               if (ntx) {
+                       if (xspi->txbuf)
+                               cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
+                       else
+                               cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
 
-               xspi->tx_bytes--;
-               trans_cnt++;
-       }
-}
+                       ntx--;
+               }
 
-/**
- * cdns_spi_read_rx_fifo - Reads the RX FIFO with as many bytes as possible
- * @xspi:       Pointer to the cdns_spi structure
- * @count:     Read byte count
- */
-static void cdns_spi_read_rx_fifo(struct cdns_spi *xspi, unsigned long count)
-{
-       u8 data;
-
-       /* Read out the data from the RX FIFO */
-       while (count > 0) {
-               data = cdns_spi_read(xspi, CDNS_SPI_RXD);
-               if (xspi->rxbuf)
-                       *xspi->rxbuf++ = data;
-               xspi->rx_bytes--;
-               count--;
+               if (nrx) {
+                       u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);
+
+                       if (xspi->rxbuf)
+                               *xspi->rxbuf++ = data;
+
+                       nrx--;
+               }
        }
 }
 
@@ -381,33 +376,22 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
                spi_finalize_current_transfer(ctlr);
                status = IRQ_HANDLED;
        } else if (intr_status & CDNS_SPI_IXR_TXOW) {
-               int trans_cnt = cdns_spi_read(xspi, CDNS_SPI_THLD);
+               int threshold = cdns_spi_read(xspi, CDNS_SPI_THLD);
+               int trans_cnt = xspi->rx_bytes - xspi->tx_bytes;
+
+               if (threshold > 1)
+                       trans_cnt -= threshold;
+
                /* Set threshold to one if number of pending are
                 * less than half fifo
                 */
                if (xspi->tx_bytes < xspi->tx_fifo_depth >> 1)
                        cdns_spi_write(xspi, CDNS_SPI_THLD, 1);
 
-               while (trans_cnt) {
-                       cdns_spi_read_rx_fifo(xspi, 1);
-
-                       if (xspi->tx_bytes) {
-                               if (xspi->txbuf)
-                                       cdns_spi_write(xspi, CDNS_SPI_TXD,
-                                                      *xspi->txbuf++);
-                               else
-                                       cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
-                               xspi->tx_bytes--;
-                       }
-                       trans_cnt--;
-               }
-               if (!xspi->tx_bytes) {
-                       /* Fixed delay due to controller limitation with
-                        * RX_NEMPTY incorrect status
-                        * Xilinx AR:65885 contains more details
-                        */
-                       udelay(10);
-                       cdns_spi_read_rx_fifo(xspi, xspi->rx_bytes);
+               if (xspi->tx_bytes) {
+                       cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
+               } else {
+                       cdns_spi_process_fifo(xspi, 0, trans_cnt);
                        cdns_spi_write(xspi, CDNS_SPI_IDR,
                                       CDNS_SPI_IXR_DEFAULT);
                        spi_finalize_current_transfer(ctlr);
@@ -450,16 +434,17 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
        xspi->tx_bytes = transfer->len;
        xspi->rx_bytes = transfer->len;
 
-       if (!spi_controller_is_slave(ctlr))
+       if (!spi_controller_is_slave(ctlr)) {
                cdns_spi_setup_transfer(spi, transfer);
+       } else {
+               /* Set TX empty threshold to half of FIFO depth
+                * only if TX bytes are more than half FIFO depth.
+                */
+               if (xspi->tx_bytes > xspi->tx_fifo_depth)
+                       cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
+       }
 
-       /* Set TX empty threshold to half of FIFO depth
-        * only if TX bytes are more than half FIFO depth.
-        */
-       if (xspi->tx_bytes > (xspi->tx_fifo_depth >> 1))
-               cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
-
-       cdns_spi_fill_tx_fifo(xspi);
+       cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
        spi_transfer_delay_exec(transfer);
 
        cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
index 5e6faa9..5f2aee6 100644 (file)
@@ -264,17 +264,17 @@ static void dw_spi_elba_set_cs(struct spi_device *spi, bool enable)
        struct regmap *syscon = dwsmmio->priv;
        u8 cs;
 
-       cs = spi->chip_select;
+       cs = spi_get_chipselect(spi, 0);
        if (cs < 2)
-               dw_spi_elba_override_cs(syscon, spi->chip_select, enable);
+               dw_spi_elba_override_cs(syscon, spi_get_chipselect(spi, 0), enable);
 
        /*
         * The DW SPI controller needs a native CS bit selected to start
         * the serial engine.
         */
-       spi->chip_select = 0;
+       spi_set_chipselect(spi, 0, 0);
        dw_spi_set_cs(spi, enable);
-       spi->chip_select = cs;
+       spi_get_chipselect(spi, cs);
 }
 
 static int dw_spi_elba_init(struct platform_device *pdev,
index ba7be50..a98b781 100644 (file)
@@ -294,6 +294,8 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag)
        mas->cs_flag = set_flag;
        /* set xfer_mode to FIFO to complete cs_done in isr */
        mas->cur_xfer_mode = GENI_SE_FIFO;
+       geni_se_select_mode(se, mas->cur_xfer_mode);
+
        reinit_completion(&mas->cs_done);
        if (set_flag)
                geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
index 49702cb..3861ae0 100644 (file)
@@ -1004,8 +1004,10 @@ static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid,
 
        invoke_fn(OPTEE_SMC_GET_ASYNC_NOTIF_VALUE, 0, 0, 0, 0, 0, 0, 0, &res);
 
-       if (res.a0)
+       if (res.a0) {
+               *value_valid = false;
                return 0;
+       }
        *value_valid = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID);
        *value_pending = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING);
        return res.a1;
index 810231b..5e11642 100644 (file)
@@ -131,7 +131,7 @@ static ssize_t available_uuids_show(struct device *dev,
 
        for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
                if (priv->uuid_bitmap & (1 << i))
-                       length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
+                       length += sysfs_emit_at(buf, length, "%s\n", int3400_thermal_uuids[i]);
        }
 
        return length;
@@ -149,7 +149,7 @@ static ssize_t current_uuid_show(struct device *dev,
 
        for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
                if (priv->os_uuid_mask & BIT(i))
-                       length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
+                       length += sysfs_emit_at(buf, length, "%s\n", int3400_thermal_uuids[i]);
        }
 
        if (length)
index 3d4dd94..0d2f805 100644 (file)
@@ -860,6 +860,11 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
                if (ret)
                        goto pin_unwind;
 
+               if (!pfn_valid(phys_pfn)) {
+                       ret = -EINVAL;
+                       goto pin_unwind;
+               }
+
                ret = vfio_add_to_pfn_list(dma, iova, phys_pfn);
                if (ret) {
                        if (put_pfn(phys_pfn, dma->prot) && do_accounting)
index a92af08..0742730 100644 (file)
@@ -256,7 +256,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
                 * test_and_set_bit() implies a memory barrier.
                 */
                llist_add(&work->node, &dev->worker->work_list);
-               wake_up_process(dev->worker->vtsk->task);
+               vhost_task_wake(dev->worker->vtsk);
        }
 }
 EXPORT_SYMBOL_GPL(vhost_work_queue);
@@ -333,31 +333,19 @@ static void vhost_vq_reset(struct vhost_dev *dev,
        __vhost_vq_meta_reset(vq);
 }
 
-static int vhost_worker(void *data)
+static bool vhost_worker(void *data)
 {
        struct vhost_worker *worker = data;
        struct vhost_work *work, *work_next;
        struct llist_node *node;
 
-       for (;;) {
-               /* mb paired w/ kthread_stop */
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               if (vhost_task_should_stop(worker->vtsk)) {
-                       __set_current_state(TASK_RUNNING);
-                       break;
-               }
-
-               node = llist_del_all(&worker->work_list);
-               if (!node)
-                       schedule();
-
+       node = llist_del_all(&worker->work_list);
+       if (node) {
                node = llist_reverse_order(node);
                /* make sure flag is seen after deletion */
                smp_wmb();
                llist_for_each_entry_safe(work, work_next, node, node) {
                        clear_bit(VHOST_WORK_QUEUED, &work->flags);
-                       __set_current_state(TASK_RUNNING);
                        kcov_remote_start_common(worker->kcov_handle);
                        work->fn(work);
                        kcov_remote_stop();
@@ -365,7 +353,7 @@ static int vhost_worker(void *data)
                }
        }
 
-       return 0;
+       return !!node;
 }
 
 static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq)
index 1f5219e..7beaf2c 100644 (file)
@@ -325,8 +325,10 @@ static struct sock_mapping *pvcalls_new_active_socket(
        void *page;
 
        map = kzalloc(sizeof(*map), GFP_KERNEL);
-       if (map == NULL)
+       if (map == NULL) {
+               sock_release(sock);
                return NULL;
+       }
 
        map->fedata = fedata;
        map->sock = sock;
@@ -418,10 +420,8 @@ static int pvcalls_back_connect(struct xenbus_device *dev,
                                        req->u.connect.ref,
                                        req->u.connect.evtchn,
                                        sock);
-       if (!map) {
+       if (!map)
                ret = -EFAULT;
-               sock_release(sock);
-       }
 
 out:
        rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
@@ -561,7 +561,6 @@ static void __pvcalls_back_accept(struct work_struct *work)
                                        sock);
        if (!map) {
                ret = -EFAULT;
-               sock_release(sock);
                goto out_error;
        }
 
index cc07a0c..18d034e 100644 (file)
@@ -368,14 +368,7 @@ config NFS_V4_2_SSC_HELPER
 source "net/sunrpc/Kconfig"
 source "fs/ceph/Kconfig"
 
-source "fs/cifs/Kconfig"
-source "fs/ksmbd/Kconfig"
-
-config SMBFS_COMMON
-       tristate
-       default y if CIFS=y || SMB_SERVER=y
-       default m if CIFS=m || SMB_SERVER=m
-
+source "fs/smb/Kconfig"
 source "fs/coda/Kconfig"
 source "fs/afs/Kconfig"
 source "fs/9p/Kconfig"
index 834f1c3..5bfdbf0 100644 (file)
@@ -95,9 +95,7 @@ obj-$(CONFIG_LOCKD)           += lockd/
 obj-$(CONFIG_NLS)              += nls/
 obj-y                          += unicode/
 obj-$(CONFIG_SYSV_FS)          += sysv/
-obj-$(CONFIG_SMBFS_COMMON)     += smbfs_common/
-obj-$(CONFIG_CIFS)             += cifs/
-obj-$(CONFIG_SMB_SERVER)       += ksmbd/
+obj-$(CONFIG_SMBFS)            += smb/
 obj-$(CONFIG_HPFS_FS)          += hpfs/
 obj-$(CONFIG_NTFS_FS)          += ntfs/
 obj-$(CONFIG_NTFS3_FS)         += ntfs3/
index 5379c47..35d34c7 100644 (file)
@@ -330,7 +330,7 @@ static void btrfs_end_bio_work(struct work_struct *work)
        if (bbio->inode && !(bbio->bio.bi_opf & REQ_META))
                btrfs_check_read_bio(bbio, bbio->bio.bi_private);
        else
-               bbio->end_io(bbio);
+               btrfs_orig_bbio_end_io(bbio);
 }
 
 static void btrfs_simple_end_io(struct bio *bio)
index 957ad1c..590b035 100644 (file)
@@ -2818,10 +2818,20 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
        }
 
        ret = inc_block_group_ro(cache, 0);
-       if (!do_chunk_alloc || ret == -ETXTBSY)
-               goto unlock_out;
        if (!ret)
                goto out;
+       if (ret == -ETXTBSY)
+               goto unlock_out;
+
+       /*
+        * Skip chunk alloction if the bg is SYSTEM, this is to avoid system
+        * chunk allocation storm to exhaust the system chunk array.  Otherwise
+        * we still want to try our best to mark the block group read-only.
+        */
+       if (!do_chunk_alloc && ret == -ENOSPC &&
+           (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
+               goto unlock_out;
+
        alloc_flags = btrfs_get_alloc_profile(fs_info, cache->space_info->flags);
        ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE);
        if (ret < 0)
index fbf9006..2b1b227 100644 (file)
@@ -96,7 +96,7 @@ static void csum_tree_block(struct extent_buffer *buf, u8 *result)
        crypto_shash_update(shash, kaddr + BTRFS_CSUM_SIZE,
                            first_page_part - BTRFS_CSUM_SIZE);
 
-       for (i = 1; i < num_pages; i++) {
+       for (i = 1; i < num_pages && INLINE_EXTENT_BUFFER_PAGES > 1; i++) {
                kaddr = page_address(buf->pages[i]);
                crypto_shash_update(shash, kaddr, PAGE_SIZE);
        }
@@ -4936,7 +4936,11 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
                 */
                inode = igrab(&btrfs_inode->vfs_inode);
                if (inode) {
+                       unsigned int nofs_flag;
+
+                       nofs_flag = memalloc_nofs_save();
                        invalidate_inode_pages2(inode->i_mapping);
+                       memalloc_nofs_restore(nofs_flag);
                        iput(inode);
                }
                spin_lock(&root->delalloc_lock);
@@ -5042,7 +5046,12 @@ static void btrfs_cleanup_bg_io(struct btrfs_block_group *cache)
 
        inode = cache->io_ctl.inode;
        if (inode) {
+               unsigned int nofs_flag;
+
+               nofs_flag = memalloc_nofs_save();
                invalidate_inode_pages2(inode->i_mapping);
+               memalloc_nofs_restore(nofs_flag);
+
                BTRFS_I(inode)->generation = 0;
                cache->io_ctl.inode = NULL;
                iput(inode);
index cd4cce9..d1cd0a6 100644 (file)
@@ -792,7 +792,9 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio)
                                sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
                                                      bytes_left), GFP_KERNEL);
                                memalloc_nofs_restore(nofs_flag);
-                               BUG_ON(!sums); /* -ENOMEM */
+                               if (!sums)
+                                       return BLK_STS_RESOURCE;
+
                                sums->len = bytes_left;
                                ordered = btrfs_lookup_ordered_extent(inode,
                                                                offset);
index 836725a..dd37cba 100644 (file)
@@ -2518,13 +2518,20 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
 
                if (ret == 0) {
                        ro_set = 1;
-               } else if (ret == -ENOSPC && !sctx->is_dev_replace) {
+               } else if (ret == -ENOSPC && !sctx->is_dev_replace &&
+                          !(cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK)) {
                        /*
                         * btrfs_inc_block_group_ro return -ENOSPC when it
                         * failed in creating new chunk for metadata.
                         * It is not a problem for scrub, because
                         * metadata are always cowed, and our scrub paused
                         * commit_transactions.
+                        *
+                        * For RAID56 chunks, we have to mark them read-only
+                        * for scrub, as later we would use our own cache
+                        * out of RAID56 realm.
+                        * Thus we want the RAID56 bg to be marked RO to
+                        * prevent RMW from screwing up out cache.
                         */
                        ro_set = 0;
                } else if (ret == -ETXTBSY) {
index 9b212e8..d2755d5 100644 (file)
@@ -6158,7 +6158,7 @@ static int log_delayed_deletions_incremental(struct btrfs_trans_handle *trans,
 {
        struct btrfs_root *log = inode->root->log_root;
        const struct btrfs_delayed_item *curr;
-       u64 last_range_start;
+       u64 last_range_start = 0;
        u64 last_range_end = 0;
        struct btrfs_key key;
 
index ece7bad..88740c5 100644 (file)
@@ -371,7 +371,9 @@ static int zap_process(struct task_struct *start, int exit_code)
                if (t != current && !(t->flags & PF_POSTCOREDUMP)) {
                        sigaddset(&t->pending.signal, SIGKILL);
                        signal_wake_up(t, 1);
-                       nr++;
+                       /* The vhost_worker does not particpate in coredumps */
+                       if ((t->flags & (PF_USER_WORKER | PF_IO_WORKER)) != PF_USER_WORKER)
+                               nr++;
                }
        }
 
index 704fb59..f259d92 100644 (file)
@@ -121,6 +121,7 @@ config EROFS_FS_PCPU_KTHREAD
 config EROFS_FS_PCPU_KTHREAD_HIPRI
        bool "EROFS high priority per-CPU kthread workers"
        depends on EROFS_FS_ZIP && EROFS_FS_PCPU_KTHREAD
+       default y
        help
          This permits EROFS to configure per-CPU kthread workers to run
          at higher priority.
index 99bbc59..a3a98fc 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 obj-$(CONFIG_EROFS_FS) += erofs.o
-erofs-objs := super.o inode.o data.o namei.o dir.o utils.o pcpubuf.o sysfs.o
+erofs-objs := super.o inode.o data.o namei.o dir.o utils.o sysfs.o
 erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o
-erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o
+erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o pcpubuf.o
 erofs-$(CONFIG_EROFS_FS_ZIP_LZMA) += decompressor_lzma.o
 erofs-$(CONFIG_EROFS_FS_ONDEMAND) += fscache.o
index af0431a..1e39c03 100644 (file)
@@ -472,12 +472,6 @@ static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count)
        return NULL;
 }
 
-void *erofs_get_pcpubuf(unsigned int requiredpages);
-void erofs_put_pcpubuf(void *ptr);
-int erofs_pcpubuf_growsize(unsigned int nrpages);
-void __init erofs_pcpubuf_init(void);
-void erofs_pcpubuf_exit(void);
-
 int erofs_register_sysfs(struct super_block *sb);
 void erofs_unregister_sysfs(struct super_block *sb);
 int __init erofs_init_sysfs(void);
@@ -512,6 +506,11 @@ int z_erofs_load_lz4_config(struct super_block *sb,
                            struct z_erofs_lz4_cfgs *lz4, int len);
 int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
                            int flags);
+void *erofs_get_pcpubuf(unsigned int requiredpages);
+void erofs_put_pcpubuf(void *ptr);
+int erofs_pcpubuf_growsize(unsigned int nrpages);
+void __init erofs_pcpubuf_init(void);
+void erofs_pcpubuf_exit(void);
 #else
 static inline void erofs_shrinker_register(struct super_block *sb) {}
 static inline void erofs_shrinker_unregister(struct super_block *sb) {}
@@ -529,6 +528,8 @@ static inline int z_erofs_load_lz4_config(struct super_block *sb,
        }
        return 0;
 }
+static inline void erofs_pcpubuf_init(void) {}
+static inline void erofs_pcpubuf_exit(void) {}
 #endif /* !CONFIG_EROFS_FS_ZIP */
 
 #ifdef CONFIG_EROFS_FS_ZIP_LZMA
index cd80499..bbfe7ce 100644 (file)
@@ -675,7 +675,7 @@ int erofs_xattr_prefixes_init(struct super_block *sb)
        if (!pfs)
                return -ENOMEM;
 
-       if (erofs_sb_has_fragments(sbi))
+       if (sbi->packed_inode)
                buf.inode = sbi->packed_inode;
        else
                erofs_init_metabuf(&buf, sb);
index 45f21db..160b3da 100644 (file)
@@ -369,8 +369,6 @@ static struct kthread_worker *erofs_init_percpu_worker(int cpu)
                return worker;
        if (IS_ENABLED(CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI))
                sched_set_fifo_low(worker->task);
-       else
-               sched_set_normal(worker->task, 0);
        return worker;
 }
 
index 6948d67..8104a21 100644 (file)
@@ -918,11 +918,13 @@ do {                                                                             \
  *                       where the second inode has larger inode number
  *                       than the first
  *  I_DATA_SEM_QUOTA  - Used for quota inodes only
+ *  I_DATA_SEM_EA     - Used for ea_inodes only
  */
 enum {
        I_DATA_SEM_NORMAL = 0,
        I_DATA_SEM_OTHER,
        I_DATA_SEM_QUOTA,
+       I_DATA_SEM_EA
 };
 
 
@@ -2901,7 +2903,8 @@ typedef enum {
        EXT4_IGET_NORMAL =      0,
        EXT4_IGET_SPECIAL =     0x0001, /* OK to iget a system inode */
        EXT4_IGET_HANDLE =      0x0002, /* Inode # is from a handle */
-       EXT4_IGET_BAD =         0x0004  /* Allow to iget a bad inode */
+       EXT4_IGET_BAD =         0x0004, /* Allow to iget a bad inode */
+       EXT4_IGET_EA_INODE =    0x0008  /* Inode should contain an EA value */
 } ext4_iget_flags;
 
 extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
index f65fdb2..2a14320 100644 (file)
@@ -108,6 +108,13 @@ static int ext4_fsync_journal(struct inode *inode, bool datasync,
        journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
        tid_t commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
 
+       /*
+        * Fastcommit does not really support fsync on directories or other
+        * special files. Force a full commit.
+        */
+       if (!S_ISREG(inode->i_mode))
+               return ext4_force_commit(inode->i_sb);
+
        if (journal->j_flags & JBD2_BARRIER &&
            !jbd2_trans_will_send_data_barrier(journal, commit_tid))
                *needs_barrier = true;
index ce5f21b..02de439 100644 (file)
@@ -4641,6 +4641,24 @@ static inline void ext4_inode_set_iversion_queried(struct inode *inode, u64 val)
                inode_set_iversion_queried(inode, val);
 }
 
+static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
+
+{
+       if (flags & EXT4_IGET_EA_INODE) {
+               if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+                       return "missing EA_INODE flag";
+               if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
+                   EXT4_I(inode)->i_file_acl)
+                       return "ea_inode with extended attributes";
+       } else {
+               if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+                       return "unexpected EA_INODE flag";
+       }
+       if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD))
+               return "unexpected bad inode w/o EXT4_IGET_BAD";
+       return NULL;
+}
+
 struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
                          ext4_iget_flags flags, const char *function,
                          unsigned int line)
@@ -4650,6 +4668,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        struct ext4_inode_info *ei;
        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
        struct inode *inode;
+       const char *err_str;
        journal_t *journal = EXT4_SB(sb)->s_journal;
        long ret;
        loff_t size;
@@ -4677,8 +4696,14 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        inode = iget_locked(sb, ino);
        if (!inode)
                return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
+       if (!(inode->i_state & I_NEW)) {
+               if ((err_str = check_igot_inode(inode, flags)) != NULL) {
+                       ext4_error_inode(inode, function, line, 0, err_str);
+                       iput(inode);
+                       return ERR_PTR(-EFSCORRUPTED);
+               }
                return inode;
+       }
 
        ei = EXT4_I(inode);
        iloc.bh = NULL;
@@ -4944,10 +4969,9 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
        if (IS_CASEFOLDED(inode) && !ext4_has_feature_casefold(inode->i_sb))
                ext4_error_inode(inode, function, line, 0,
                                 "casefold flag without casefold feature");
-       if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) {
-               ext4_error_inode(inode, function, line, 0,
-                                "bad inode without EXT4_IGET_BAD flag");
-               ret = -EUCLEAN;
+       if ((err_str = check_igot_inode(inode, flags)) != NULL) {
+               ext4_error_inode(inode, function, line, 0, err_str);
+               ret = -EFSCORRUPTED;
                goto bad_inode;
        }
 
index 9680fe7..56a5d1c 100644 (file)
@@ -6589,18 +6589,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
        }
 
        /*
-        * Reinitialize lazy itable initialization thread based on
-        * current settings
-        */
-       if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
-               ext4_unregister_li_request(sb);
-       else {
-               ext4_group_t first_not_zeroed;
-               first_not_zeroed = ext4_has_uninit_itable(sb);
-               ext4_register_li_request(sb, first_not_zeroed);
-       }
-
-       /*
         * Handle creation of system zone data early because it can fail.
         * Releasing of existing data is done when we are sure remount will
         * succeed.
@@ -6637,6 +6625,18 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
        if (enable_rw)
                sb->s_flags &= ~SB_RDONLY;
 
+       /*
+        * Reinitialize lazy itable initialization thread based on
+        * current settings
+        */
+       if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
+               ext4_unregister_li_request(sb);
+       else {
+               ext4_group_t first_not_zeroed;
+               first_not_zeroed = ext4_has_uninit_itable(sb);
+               ext4_register_li_request(sb, first_not_zeroed);
+       }
+
        if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
                ext4_stop_mmpd(sbi);
 
index dfc2e22..13d7f17 100644 (file)
@@ -121,7 +121,11 @@ ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
 #ifdef CONFIG_LOCKDEP
 void ext4_xattr_inode_set_class(struct inode *ea_inode)
 {
+       struct ext4_inode_info *ei = EXT4_I(ea_inode);
+
        lockdep_set_subclass(&ea_inode->i_rwsem, 1);
+       (void) ei;      /* shut up clang warning if !CONFIG_LOCKDEP */
+       lockdep_set_subclass(&ei->i_data_sem, I_DATA_SEM_EA);
 }
 #endif
 
@@ -433,7 +437,7 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
                return -EFSCORRUPTED;
        }
 
-       inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_NORMAL);
+       inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_EA_INODE);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                ext4_error(parent->i_sb,
@@ -441,23 +445,6 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
                           err);
                return err;
        }
-
-       if (is_bad_inode(inode)) {
-               ext4_error(parent->i_sb,
-                          "error while reading EA inode %lu is_bad_inode",
-                          ea_ino);
-               err = -EIO;
-               goto error;
-       }
-
-       if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
-               ext4_error(parent->i_sb,
-                          "EA inode %lu does not have EXT4_EA_INODE_FL flag",
-                           ea_ino);
-               err = -EINVAL;
-               goto error;
-       }
-
        ext4_xattr_inode_set_class(inode);
 
        /*
@@ -478,9 +465,6 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
 
        *ea_inode = inode;
        return 0;
-error:
-       iput(inode);
-       return err;
 }
 
 /* Remove entry from mbcache when EA inode is getting evicted */
@@ -1556,11 +1540,11 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
 
        while (ce) {
                ea_inode = ext4_iget(inode->i_sb, ce->e_value,
-                                    EXT4_IGET_NORMAL);
-               if (!IS_ERR(ea_inode) &&
-                   !is_bad_inode(ea_inode) &&
-                   (EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL) &&
-                   i_size_read(ea_inode) == value_len &&
+                                    EXT4_IGET_EA_INODE);
+               if (IS_ERR(ea_inode))
+                       goto next_entry;
+               ext4_xattr_inode_set_class(ea_inode);
+               if (i_size_read(ea_inode) == value_len &&
                    !ext4_xattr_inode_read(ea_inode, ea_data, value_len) &&
                    !ext4_xattr_inode_verify_hashes(ea_inode, NULL, ea_data,
                                                    value_len) &&
@@ -1570,9 +1554,8 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
                        kvfree(ea_data);
                        return ea_inode;
                }
-
-               if (!IS_ERR(ea_inode))
-                       iput(ea_inode);
+               iput(ea_inode);
+       next_entry:
                ce = mb_cache_entry_find_next(ea_inode_cache, ce);
        }
        kvfree(ea_data);
index e63c1d4..8f3112e 100644 (file)
@@ -317,7 +317,7 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
 
        name = nfs_readdir_copy_name(entry->name, entry->len);
 
-       array = kmap_atomic(folio_page(folio, 0));
+       array = kmap_local_folio(folio, 0);
        if (!name)
                goto out;
        ret = nfs_readdir_array_can_expand(array);
@@ -340,7 +340,7 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
                nfs_readdir_array_set_eof(array);
 out:
        *cookie = array->last_cookie;
-       kunmap_atomic(array);
+       kunmap_local(array);
        return ret;
 }
 
index 18f25ff..d366539 100644 (file)
@@ -5437,10 +5437,18 @@ static bool nfs4_read_plus_not_supported(struct rpc_task *task,
        return false;
 }
 
-static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
+static inline void nfs4_read_plus_scratch_free(struct nfs_pgio_header *hdr)
 {
-       if (hdr->res.scratch)
+       if (hdr->res.scratch) {
                kfree(hdr->res.scratch);
+               hdr->res.scratch = NULL;
+       }
+}
+
+static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
+{
+       nfs4_read_plus_scratch_free(hdr);
+
        if (!nfs4_sequence_done(task, &hdr->res.seq_res))
                return -EAGAIN;
        if (nfs4_read_stateid_changed(task, &hdr->args))
diff --git a/fs/smb/Kconfig b/fs/smb/Kconfig
new file mode 100644 (file)
index 0000000..ef42578
--- /dev/null
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# smbfs configuration
+
+source "fs/smb/client/Kconfig"
+source "fs/smb/server/Kconfig"
+
+config SMBFS
+       tristate
+       default y if CIFS=y || SMB_SERVER=y
+       default m if CIFS=m || SMB_SERVER=m
diff --git a/fs/smb/Makefile b/fs/smb/Makefile
new file mode 100644 (file)
index 0000000..9a1bf59
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SMBFS)            += common/
+obj-$(CONFIG_CIFS)             += client/
+obj-$(CONFIG_SMB_SERVER)       += server/
similarity index 100%
rename from fs/cifs/Kconfig
rename to fs/smb/client/Kconfig
similarity index 100%
rename from fs/cifs/Makefile
rename to fs/smb/client/Makefile
similarity index 100%
rename from fs/cifs/asn1.c
rename to fs/smb/client/asn1.c
similarity index 99%
rename from fs/cifs/cifs_debug.c
rename to fs/smb/client/cifs_debug.c
index d4ed200..5034b86 100644 (file)
@@ -108,7 +108,7 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
        if ((tcon->seal) ||
            (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
            (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
-               seq_printf(m, " Encrypted");
+               seq_puts(m, " encrypted");
        if (tcon->nocase)
                seq_printf(m, " nocase");
        if (tcon->unix_ext)
@@ -415,8 +415,12 @@ skip_rdma:
 
                        /* dump session id helpful for use with network trace */
                        seq_printf(m, " SessionId: 0x%llx", ses->Suid);
-                       if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
+                       if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) {
                                seq_puts(m, " encrypted");
+                               /* can help in debugging to show encryption type */
+                               if (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+                                       seq_puts(m, "(gcm256)");
+                       }
                        if (ses->sign)
                                seq_puts(m, " signed");
 
similarity index 100%
rename from fs/cifs/cifs_swn.c
rename to fs/smb/client/cifs_swn.c
similarity index 100%
rename from fs/cifs/cifs_swn.h
rename to fs/smb/client/cifs_swn.h
similarity index 100%
rename from fs/cifs/cifsacl.c
rename to fs/smb/client/cifsacl.c
similarity index 100%
rename from fs/cifs/cifsacl.h
rename to fs/smb/client/cifsacl.h
similarity index 99%
rename from fs/cifs/cifsencrypt.c
rename to fs/smb/client/cifsencrypt.c
index 357bd27..ef4c2e3 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/random.h>
 #include <linux/highmem.h>
 #include <linux/fips.h>
-#include "../smbfs_common/arc4.h"
+#include "../common/arc4.h"
 #include <crypto/aead.h>
 
 /*
similarity index 100%
rename from fs/cifs/cifsfs.c
rename to fs/smb/client/cifsfs.c
similarity index 100%
rename from fs/cifs/cifsfs.h
rename to fs/smb/client/cifsfs.h
similarity index 99%
rename from fs/cifs/cifsglob.h
rename to fs/smb/client/cifsglob.h
index 5f8fd20..0d84bb1 100644 (file)
@@ -24,7 +24,7 @@
 #include "cifsacl.h"
 #include <crypto/internal/hash.h>
 #include <uapi/linux/cifs/cifs_mount.h>
-#include "../smbfs_common/smb2pdu.h"
+#include "../common/smb2pdu.h"
 #include "smb2pdu.h"
 #include <linux/filelock.h>
 
similarity index 99%
rename from fs/cifs/cifspdu.h
rename to fs/smb/client/cifspdu.h
index 445e3ea..e17222f 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <net/sock.h>
 #include <asm/unaligned.h>
-#include "../smbfs_common/smbfsctl.h"
+#include "../common/smbfsctl.h"
 
 #define CIFS_PROT   0
 #define POSIX_PROT  (CIFS_PROT+1)
similarity index 100%
rename from fs/cifs/cifsroot.c
rename to fs/smb/client/cifsroot.c
similarity index 100%
rename from fs/cifs/cifssmb.c
rename to fs/smb/client/cifssmb.c
similarity index 100%
rename from fs/cifs/connect.c
rename to fs/smb/client/connect.c
similarity index 99%
rename from fs/cifs/dfs.c
rename to fs/smb/client/dfs.c
index a93dbca..2f93bf8 100644 (file)
@@ -303,7 +303,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
        if (!nodfs) {
                rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL, NULL);
                if (rc) {
-                       if (rc != -ENOENT && rc != -EOPNOTSUPP)
+                       if (rc != -ENOENT && rc != -EOPNOTSUPP && rc != -EIO)
                                goto out;
                        nodfs = true;
                }
similarity index 100%
rename from fs/cifs/dfs.h
rename to fs/smb/client/dfs.h
similarity index 100%
rename from fs/cifs/dir.c
rename to fs/smb/client/dir.c
similarity index 100%
rename from fs/cifs/export.c
rename to fs/smb/client/export.c
similarity index 99%
rename from fs/cifs/file.c
rename to fs/smb/client/file.c
index ba7f2e0..df88b8c 100644 (file)
@@ -3353,9 +3353,10 @@ static size_t cifs_limit_bvec_subset(const struct iov_iter *iter, size_t max_siz
        while (n && ix < nbv) {
                len = min3(n, bvecs[ix].bv_len - skip, max_size);
                span += len;
+               max_size -= len;
                nsegs++;
                ix++;
-               if (span >= max_size || nsegs >= max_segs)
+               if (max_size == 0 || nsegs >= max_segs)
                        break;
                skip = 0;
                n -= len;
similarity index 99%
rename from fs/cifs/fs_context.c
rename to fs/smb/client/fs_context.c
index ace11a1..1bda756 100644 (file)
@@ -904,6 +904,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                        ctx->sfu_remap = false; /* disable SFU mapping */
                }
                break;
+       case Opt_mapchars:
+               if (result.negated)
+                       ctx->sfu_remap = false;
+               else {
+                       ctx->sfu_remap = true;
+                       ctx->remap = false; /* disable SFM (mapposix) mapping */
+               }
+               break;
        case Opt_user_xattr:
                if (result.negated)
                        ctx->no_xattr = 1;
similarity index 100%
rename from fs/cifs/fscache.c
rename to fs/smb/client/fscache.c
similarity index 100%
rename from fs/cifs/fscache.h
rename to fs/smb/client/fscache.h
similarity index 100%
rename from fs/cifs/inode.c
rename to fs/smb/client/inode.c
similarity index 98%
rename from fs/cifs/ioctl.c
rename to fs/smb/client/ioctl.c
index cb3be58..fff092b 100644 (file)
@@ -321,7 +321,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
        struct tcon_link *tlink;
        struct cifs_sb_info *cifs_sb;
        __u64   ExtAttrBits = 0;
+#ifdef CONFIG_CIFS_POSIX
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
        __u64   caps;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+#endif /* CONFIG_CIFS_POSIX */
 
        xid = get_xid();
 
@@ -331,9 +335,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                        if (pSMBFile == NULL)
                                break;
                        tcon = tlink_tcon(pSMBFile->tlink);
-                       caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
 #ifdef CONFIG_CIFS_POSIX
 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+                       caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
                        if (CIFS_UNIX_EXTATTR_CAP & caps) {
                                __u64   ExtAttrMask = 0;
                                rc = CIFSGetExtAttr(xid, tcon,
similarity index 100%
rename from fs/cifs/link.c
rename to fs/smb/client/link.c
similarity index 100%
rename from fs/cifs/misc.c
rename to fs/smb/client/misc.c
similarity index 100%
rename from fs/cifs/netlink.c
rename to fs/smb/client/netlink.c
similarity index 100%
rename from fs/cifs/netlink.h
rename to fs/smb/client/netlink.h
similarity index 100%
rename from fs/cifs/netmisc.c
rename to fs/smb/client/netmisc.c
similarity index 100%
rename from fs/cifs/nterr.c
rename to fs/smb/client/nterr.c
similarity index 100%
rename from fs/cifs/nterr.h
rename to fs/smb/client/nterr.h
similarity index 100%
rename from fs/cifs/ntlmssp.h
rename to fs/smb/client/ntlmssp.h
similarity index 100%
rename from fs/cifs/readdir.c
rename to fs/smb/client/readdir.c
similarity index 100%
rename from fs/cifs/sess.c
rename to fs/smb/client/sess.c
similarity index 100%
rename from fs/cifs/smb1ops.c
rename to fs/smb/client/smb1ops.c
similarity index 100%
rename from fs/cifs/smb2file.c
rename to fs/smb/client/smb2file.c
similarity index 100%
rename from fs/cifs/smb2glob.h
rename to fs/smb/client/smb2glob.h
similarity index 100%
rename from fs/cifs/smb2misc.c
rename to fs/smb/client/smb2misc.c
similarity index 99%
rename from fs/cifs/smb2ops.c
rename to fs/smb/client/smb2ops.c
index 5065398..6e3be58 100644 (file)
@@ -618,7 +618,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
                 * Add a new one instead
                 */
                spin_lock(&ses->iface_lock);
-               iface = niface = NULL;
                list_for_each_entry_safe(iface, niface, &ses->iface_list,
                                         iface_head) {
                        ret = iface_cmp(iface, &tmp_iface);
similarity index 99%
rename from fs/cifs/smb2pdu.c
rename to fs/smb/client/smb2pdu.c
index 9ed61b6..7063b39 100644 (file)
@@ -3725,7 +3725,7 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
                if (*out_data == NULL) {
                        rc = -ENOMEM;
                        goto cnotify_exit;
-               } else
+               } else if (plen)
                        *plen = le32_to_cpu(smb_rsp->OutputBufferLength);
        }
 
similarity index 100%
rename from fs/cifs/smb2pdu.h
rename to fs/smb/client/smb2pdu.h
similarity index 98%
rename from fs/cifs/smbencrypt.c
rename to fs/smb/client/smbencrypt.c
index 4a04877..f0ce264 100644 (file)
@@ -24,7 +24,7 @@
 #include "cifsglob.h"
 #include "cifs_debug.h"
 #include "cifsproto.h"
-#include "../smbfs_common/md4.h"
+#include "../common/md4.h"
 
 #ifndef false
 #define false 0
similarity index 100%
rename from fs/cifs/smberr.h
rename to fs/smb/client/smberr.h
similarity index 100%
rename from fs/cifs/trace.c
rename to fs/smb/client/trace.c
similarity index 100%
rename from fs/cifs/trace.h
rename to fs/smb/client/trace.h
similarity index 100%
rename from fs/cifs/unc.c
rename to fs/smb/client/unc.c
similarity index 100%
rename from fs/cifs/winucase.c
rename to fs/smb/client/winucase.c
similarity index 100%
rename from fs/cifs/xattr.c
rename to fs/smb/client/xattr.c
similarity index 59%
rename from fs/smbfs_common/Makefile
rename to fs/smb/common/Makefile
index cafc61a..c66dbbc 100644 (file)
@@ -3,5 +3,5 @@
 # Makefile for Linux filesystem routines that are shared by client and server.
 #
 
-obj-$(CONFIG_SMBFS_COMMON) += cifs_arc4.o
-obj-$(CONFIG_SMBFS_COMMON) += cifs_md4.o
+obj-$(CONFIG_SMBFS) += cifs_arc4.o
+obj-$(CONFIG_SMBFS) += cifs_md4.o
similarity index 100%
rename from fs/smbfs_common/arc4.h
rename to fs/smb/common/arc4.h
similarity index 100%
rename from fs/smbfs_common/md4.h
rename to fs/smb/common/md4.h
similarity index 100%
rename from fs/ksmbd/Kconfig
rename to fs/smb/server/Kconfig
similarity index 100%
rename from fs/ksmbd/Makefile
rename to fs/smb/server/Makefile
similarity index 100%
rename from fs/ksmbd/asn1.c
rename to fs/smb/server/asn1.c
similarity index 100%
rename from fs/ksmbd/asn1.h
rename to fs/smb/server/asn1.h
similarity index 99%
rename from fs/ksmbd/auth.c
rename to fs/smb/server/auth.c
index df8fb07..5e5e120 100644 (file)
@@ -29,7 +29,7 @@
 #include "mgmt/user_config.h"
 #include "crypto_ctx.h"
 #include "transport_ipc.h"
-#include "../smbfs_common/arc4.h"
+#include "../common/arc4.h"
 
 /*
  * Fixed format data defining GSS header and fixed string
similarity index 100%
rename from fs/ksmbd/auth.h
rename to fs/smb/server/auth.h
similarity index 100%
rename from fs/ksmbd/glob.h
rename to fs/smb/server/glob.h
similarity index 100%
rename from fs/ksmbd/misc.c
rename to fs/smb/server/misc.c
similarity index 100%
rename from fs/ksmbd/misc.h
rename to fs/smb/server/misc.h
similarity index 100%
rename from fs/ksmbd/ndr.c
rename to fs/smb/server/ndr.c
similarity index 100%
rename from fs/ksmbd/ndr.h
rename to fs/smb/server/ndr.h
similarity index 100%
rename from fs/ksmbd/nterr.h
rename to fs/smb/server/nterr.h
similarity index 100%
rename from fs/ksmbd/ntlmssp.h
rename to fs/smb/server/ntlmssp.h
similarity index 98%
rename from fs/ksmbd/oplock.c
rename to fs/smb/server/oplock.c
index 6d1ccb9..db181bd 100644 (file)
@@ -157,13 +157,42 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci)
        rcu_read_lock();
        opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info,
                                        op_entry);
-       if (opinfo && !atomic_inc_not_zero(&opinfo->refcount))
-               opinfo = NULL;
+       if (opinfo) {
+               if (!atomic_inc_not_zero(&opinfo->refcount))
+                       opinfo = NULL;
+               else {
+                       atomic_inc(&opinfo->conn->r_count);
+                       if (ksmbd_conn_releasing(opinfo->conn)) {
+                               atomic_dec(&opinfo->conn->r_count);
+                               atomic_dec(&opinfo->refcount);
+                               opinfo = NULL;
+                       }
+               }
+       }
+
        rcu_read_unlock();
 
        return opinfo;
 }
 
+static void opinfo_conn_put(struct oplock_info *opinfo)
+{
+       struct ksmbd_conn *conn;
+
+       if (!opinfo)
+               return;
+
+       conn = opinfo->conn;
+       /*
+        * Checking waitqueue to dropping pending requests on
+        * disconnection. waitqueue_active is safe because it
+        * uses atomic operation for condition.
+        */
+       if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
+               wake_up(&conn->r_count_q);
+       opinfo_put(opinfo);
+}
+
 void opinfo_put(struct oplock_info *opinfo)
 {
        if (!atomic_dec_and_test(&opinfo->refcount))
@@ -666,13 +695,6 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
 
 out:
        ksmbd_free_work_struct(work);
-       /*
-        * Checking waitqueue to dropping pending requests on
-        * disconnection. waitqueue_active is safe because it
-        * uses atomic operation for condition.
-        */
-       if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
-               wake_up(&conn->r_count_q);
 }
 
 /**
@@ -706,7 +728,6 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
        work->conn = conn;
        work->sess = opinfo->sess;
 
-       atomic_inc(&conn->r_count);
        if (opinfo->op_state == OPLOCK_ACK_WAIT) {
                INIT_WORK(&work->work, __smb2_oplock_break_noti);
                ksmbd_queue_work(work);
@@ -776,13 +797,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
 
 out:
        ksmbd_free_work_struct(work);
-       /*
-        * Checking waitqueue to dropping pending requests on
-        * disconnection. waitqueue_active is safe because it
-        * uses atomic operation for condition.
-        */
-       if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
-               wake_up(&conn->r_count_q);
 }
 
 /**
@@ -822,7 +836,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
        work->conn = conn;
        work->sess = opinfo->sess;
 
-       atomic_inc(&conn->r_count);
        if (opinfo->op_state == OPLOCK_ACK_WAIT) {
                list_for_each_safe(tmp, t, &opinfo->interim_list) {
                        struct ksmbd_work *in_work;
@@ -1144,8 +1157,10 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
        }
        prev_opinfo = opinfo_get_list(ci);
        if (!prev_opinfo ||
-           (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx))
+           (prev_opinfo->level == SMB2_OPLOCK_LEVEL_NONE && lctx)) {
+               opinfo_conn_put(prev_opinfo);
                goto set_lev;
+       }
        prev_op_has_lease = prev_opinfo->is_lease;
        if (prev_op_has_lease)
                prev_op_state = prev_opinfo->o_lease->state;
@@ -1153,19 +1168,19 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
        if (share_ret < 0 &&
            prev_opinfo->level == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
                err = share_ret;
-               opinfo_put(prev_opinfo);
+               opinfo_conn_put(prev_opinfo);
                goto err_out;
        }
 
        if (prev_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
            prev_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
-               opinfo_put(prev_opinfo);
+               opinfo_conn_put(prev_opinfo);
                goto op_break_not_needed;
        }
 
        list_add(&work->interim_entry, &prev_opinfo->interim_list);
        err = oplock_break(prev_opinfo, SMB2_OPLOCK_LEVEL_II);
-       opinfo_put(prev_opinfo);
+       opinfo_conn_put(prev_opinfo);
        if (err == -ENOENT)
                goto set_lev;
        /* Check all oplock was freed by close */
@@ -1228,14 +1243,14 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work,
                return;
        if (brk_opinfo->level != SMB2_OPLOCK_LEVEL_BATCH &&
            brk_opinfo->level != SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
-               opinfo_put(brk_opinfo);
+               opinfo_conn_put(brk_opinfo);
                return;
        }
 
        brk_opinfo->open_trunc = is_trunc;
        list_add(&work->interim_entry, &brk_opinfo->interim_list);
        oplock_break(brk_opinfo, SMB2_OPLOCK_LEVEL_II);
-       opinfo_put(brk_opinfo);
+       opinfo_conn_put(brk_opinfo);
 }
 
 /**
@@ -1263,6 +1278,13 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
        list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) {
                if (!atomic_inc_not_zero(&brk_op->refcount))
                        continue;
+
+               atomic_inc(&brk_op->conn->r_count);
+               if (ksmbd_conn_releasing(brk_op->conn)) {
+                       atomic_dec(&brk_op->conn->r_count);
+                       continue;
+               }
+
                rcu_read_unlock();
                if (brk_op->is_lease && (brk_op->o_lease->state &
                    (~(SMB2_LEASE_READ_CACHING_LE |
@@ -1292,7 +1314,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
                brk_op->open_trunc = is_trunc;
                oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE);
 next:
-               opinfo_put(brk_op);
+               opinfo_conn_put(brk_op);
                rcu_read_lock();
        }
        rcu_read_unlock();
similarity index 100%
rename from fs/ksmbd/oplock.h
rename to fs/smb/server/oplock.h
similarity index 100%
rename from fs/ksmbd/server.c
rename to fs/smb/server/server.c
similarity index 100%
rename from fs/ksmbd/server.h
rename to fs/smb/server/server.h
similarity index 100%
rename from fs/ksmbd/smb2misc.c
rename to fs/smb/server/smb2misc.c
similarity index 100%
rename from fs/ksmbd/smb2ops.c
rename to fs/smb/server/smb2ops.c
similarity index 99%
rename from fs/ksmbd/smb2pdu.c
rename to fs/smb/server/smb2pdu.c
index 717bcd2..7a81541 100644 (file)
@@ -326,13 +326,9 @@ int smb2_set_rsp_credits(struct ksmbd_work *work)
        if (hdr->Command == SMB2_NEGOTIATE)
                aux_max = 1;
        else
-               aux_max = conn->vals->max_credits - credit_charge;
+               aux_max = conn->vals->max_credits - conn->total_credits;
        credits_granted = min_t(unsigned short, credits_requested, aux_max);
 
-       if (conn->vals->max_credits - conn->total_credits < credits_granted)
-               credits_granted = conn->vals->max_credits -
-                       conn->total_credits;
-
        conn->total_credits += credits_granted;
        work->credits_granted += credits_granted;
 
@@ -849,13 +845,14 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
 
 static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
                                  struct smb2_preauth_neg_context *pneg_ctxt,
-                                 int len_of_ctxts)
+                                 int ctxt_len)
 {
        /*
         * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
         * which may not be present. Only check for used HashAlgorithms[1].
         */
-       if (len_of_ctxts < MIN_PREAUTH_CTXT_DATA_LEN)
+       if (ctxt_len <
+           sizeof(struct smb2_neg_context) + MIN_PREAUTH_CTXT_DATA_LEN)
                return STATUS_INVALID_PARAMETER;
 
        if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
@@ -867,15 +864,23 @@ static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
 
 static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
                                struct smb2_encryption_neg_context *pneg_ctxt,
-                               int len_of_ctxts)
+                               int ctxt_len)
 {
-       int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
-       int i, cphs_size = cph_cnt * sizeof(__le16);
+       int cph_cnt;
+       int i, cphs_size;
+
+       if (sizeof(struct smb2_encryption_neg_context) > ctxt_len) {
+               pr_err("Invalid SMB2_ENCRYPTION_CAPABILITIES context size\n");
+               return;
+       }
 
        conn->cipher_type = 0;
 
+       cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
+       cphs_size = cph_cnt * sizeof(__le16);
+
        if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
-           len_of_ctxts) {
+           ctxt_len) {
                pr_err("Invalid cipher count(%d)\n", cph_cnt);
                return;
        }
@@ -923,15 +928,22 @@ static void decode_compress_ctxt(struct ksmbd_conn *conn,
 
 static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
                                 struct smb2_signing_capabilities *pneg_ctxt,
-                                int len_of_ctxts)
+                                int ctxt_len)
 {
-       int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
-       int i, sign_alos_size = sign_algo_cnt * sizeof(__le16);
+       int sign_algo_cnt;
+       int i, sign_alos_size;
+
+       if (sizeof(struct smb2_signing_capabilities) > ctxt_len) {
+               pr_err("Invalid SMB2_SIGNING_CAPABILITIES context length\n");
+               return;
+       }
 
        conn->signing_negotiated = false;
+       sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
+       sign_alos_size = sign_algo_cnt * sizeof(__le16);
 
        if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
-           len_of_ctxts) {
+           ctxt_len) {
                pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
                return;
        }
@@ -969,18 +981,16 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
        len_of_ctxts = len_of_smb - offset;
 
        while (i++ < neg_ctxt_cnt) {
-               int clen;
-
-               /* check that offset is not beyond end of SMB */
-               if (len_of_ctxts == 0)
-                       break;
+               int clen, ctxt_len;
 
                if (len_of_ctxts < sizeof(struct smb2_neg_context))
                        break;
 
                pctx = (struct smb2_neg_context *)((char *)pctx + offset);
                clen = le16_to_cpu(pctx->DataLength);
-               if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts)
+               ctxt_len = clen + sizeof(struct smb2_neg_context);
+
+               if (ctxt_len > len_of_ctxts)
                        break;
 
                if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
@@ -991,7 +1001,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 
                        status = decode_preauth_ctxt(conn,
                                                     (struct smb2_preauth_neg_context *)pctx,
-                                                    len_of_ctxts);
+                                                    ctxt_len);
                        if (status != STATUS_SUCCESS)
                                break;
                } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
@@ -1002,7 +1012,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
 
                        decode_encrypt_ctxt(conn,
                                            (struct smb2_encryption_neg_context *)pctx,
-                                           len_of_ctxts);
+                                           ctxt_len);
                } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
                        ksmbd_debug(SMB,
                                    "deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
@@ -1021,9 +1031,10 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
                } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
                        ksmbd_debug(SMB,
                                    "deassemble SMB2_SIGNING_CAPABILITIES context\n");
+
                        decode_sign_cap_ctxt(conn,
                                             (struct smb2_signing_capabilities *)pctx,
-                                            len_of_ctxts);
+                                            ctxt_len);
                }
 
                /* offsets must be 8 byte aligned */
@@ -1057,16 +1068,16 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
                return rc;
        }
 
-       if (req->DialectCount == 0) {
-               pr_err("malformed packet\n");
+       smb2_buf_len = get_rfc1002_len(work->request_buf);
+       smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
+       if (smb2_neg_size > smb2_buf_len) {
                rsp->hdr.Status = STATUS_INVALID_PARAMETER;
                rc = -EINVAL;
                goto err_out;
        }
 
-       smb2_buf_len = get_rfc1002_len(work->request_buf);
-       smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
-       if (smb2_neg_size > smb2_buf_len) {
+       if (req->DialectCount == 0) {
+               pr_err("malformed packet\n");
                rsp->hdr.Status = STATUS_INVALID_PARAMETER;
                rc = -EINVAL;
                goto err_out;
@@ -4358,21 +4369,6 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
        return 0;
 }
 
-static unsigned long long get_allocation_size(struct inode *inode,
-                                             struct kstat *stat)
-{
-       unsigned long long alloc_size = 0;
-
-       if (!S_ISDIR(stat->mode)) {
-               if ((inode->i_blocks << 9) <= stat->size)
-                       alloc_size = stat->size;
-               else
-                       alloc_size = inode->i_blocks << 9;
-       }
-
-       return alloc_size;
-}
-
 static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
                                   struct ksmbd_file *fp, void *rsp_org)
 {
@@ -4387,7 +4383,7 @@ static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
        sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
        delete_pending = ksmbd_inode_pending_delete(fp);
 
-       sinfo->AllocationSize = cpu_to_le64(get_allocation_size(inode, &stat));
+       sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
        sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
        sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
        sinfo->DeletePending = delete_pending;
@@ -4452,7 +4448,7 @@ static int get_file_all_info(struct ksmbd_work *work,
        file_info->Attributes = fp->f_ci->m_fattr;
        file_info->Pad1 = 0;
        file_info->AllocationSize =
-               cpu_to_le64(get_allocation_size(inode, &stat));
+               cpu_to_le64(inode->i_blocks << 9);
        file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
        file_info->NumberOfLinks =
                        cpu_to_le32(get_nlink(&stat) - delete_pending);
@@ -4641,7 +4637,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
        file_info->ChangeTime = cpu_to_le64(time);
        file_info->Attributes = fp->f_ci->m_fattr;
        file_info->AllocationSize =
-               cpu_to_le64(get_allocation_size(inode, &stat));
+               cpu_to_le64(inode->i_blocks << 9);
        file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
        file_info->Reserved = cpu_to_le32(0);
        rsp->OutputBufferLength =
@@ -5506,7 +5502,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 {
        char *link_name = NULL, *target_name = NULL, *pathname = NULL;
        struct path path;
-       bool file_present = true;
+       bool file_present = false;
        int rc;
 
        if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -5539,8 +5535,8 @@ static int smb2_create_link(struct ksmbd_work *work,
        if (rc) {
                if (rc != -ENOENT)
                        goto out;
-               file_present = false;
-       }
+       } else
+               file_present = true;
 
        if (file_info->ReplaceIfExists) {
                if (file_present) {
similarity index 100%
rename from fs/ksmbd/smb2pdu.h
rename to fs/smb/server/smb2pdu.h
similarity index 99%
rename from fs/ksmbd/smb_common.h
rename to fs/smb/server/smb_common.h
index 9130d2e..6b0d5f1 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "glob.h"
 #include "nterr.h"
-#include "../smbfs_common/smb2pdu.h"
+#include "../common/smb2pdu.h"
 #include "smb2pdu.h"
 
 /* ksmbd's Specific ERRNO */
similarity index 100%
rename from fs/ksmbd/smbacl.c
rename to fs/smb/server/smbacl.c
similarity index 100%
rename from fs/ksmbd/smbacl.h
rename to fs/smb/server/smbacl.h
similarity index 98%
rename from fs/ksmbd/smbfsctl.h
rename to fs/smb/server/smbfsctl.h
index b98418a..ecdf8f6 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 /*
- *   fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
+ *   fs/smb/server/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
  *
  *   Copyright (c) International Business Machines  Corp., 2002,2009
  *   Author(s): Steve French (sfrench@us.ibm.com)
similarity index 99%
rename from fs/ksmbd/smbstatus.h
rename to fs/smb/server/smbstatus.h
index 108a8b6..8963deb 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 /*
- *   fs/cifs/smb2status.h
+ *   fs/server/smb2status.h
  *
  *   SMB2 Status code (network error) definitions
  *   Definitions are from MS-ERREF
similarity index 100%
rename from fs/ksmbd/unicode.c
rename to fs/smb/server/unicode.c
similarity index 100%
rename from fs/ksmbd/unicode.h
rename to fs/smb/server/unicode.h
similarity index 100%
rename from fs/ksmbd/uniupr.h
rename to fs/smb/server/uniupr.h
similarity index 99%
rename from fs/ksmbd/vfs.c
rename to fs/smb/server/vfs.c
index 778c152..6f30291 100644 (file)
@@ -86,12 +86,14 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        err = vfs_path_parent_lookup(filename, flags,
                                     &parent_path, &last, &type,
                                     root_share_path);
-       putname(filename);
-       if (err)
+       if (err) {
+               putname(filename);
                return err;
+       }
 
        if (unlikely(type != LAST_NORM)) {
                path_put(&parent_path);
+               putname(filename);
                return -ENOENT;
        }
 
@@ -108,12 +110,14 @@ 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);
 
        return 0;
 
 err_out:
        inode_unlock(parent_path.dentry->d_inode);
        path_put(&parent_path);
+       putname(filename);
        return -ENOENT;
 }
 
@@ -743,6 +747,7 @@ retry:
        rd.new_dir              = new_path.dentry->d_inode,
        rd.new_dentry           = new_dentry,
        rd.flags                = flags,
+       rd.delegated_inode      = NULL,
        err = vfs_rename(&rd);
        if (err)
                ksmbd_debug(VFS, "vfs_rename failed err %d\n", err);
similarity index 100%
rename from fs/ksmbd/vfs.h
rename to fs/smb/server/vfs.h
similarity index 100%
rename from fs/ksmbd/xattr.h
rename to fs/smb/server/xattr.h
index fcf67d8..e7bbb7f 100644 (file)
@@ -985,9 +985,16 @@ int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
        return 0;
 }
 
-/*
+/**
+ * generic_listxattr - run through a dentry's xattr list() operations
+ * @dentry: dentry to list the xattrs
+ * @buffer: result buffer
+ * @buffer_size: size of @buffer
+ *
  * Combine the results of the list() operation from every xattr_handler in the
- * list.
+ * xattr_handler stack.
+ *
+ * Note that this will not include the entries for POSIX ACLs.
  */
 ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
@@ -996,10 +1003,6 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
        ssize_t remaining_size = buffer_size;
        int err = 0;
 
-       err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size);
-       if (err)
-               return err;
-
        for_each_xattr_handler(handlers, handler) {
                if (!handler->name || (handler->list && !handler->list(dentry)))
                        continue;
index d1f57e4..cebdf1c 100644 (file)
 /*
  * Discard .note.GNU-stack, which is emitted as PROGBITS by the compiler.
  * Otherwise, the type of .notes section would become PROGBITS instead of NOTES.
+ *
+ * Also, discard .note.gnu.property, otherwise it forces the notes section to
+ * be 8-byte aligned which causes alignment mismatches with the kernel's custom
+ * 4-byte aligned notes.
  */
 #define NOTES                                                          \
-       /DISCARD/ : { *(.note.GNU-stack) }                              \
+       /DISCARD/ : {                                                   \
+               *(.note.GNU-stack)                                      \
+               *(.note.gnu.property)                                   \
+       }                                                               \
        .notes : AT(ADDR(.notes) - LOAD_OFFSET) {                       \
                BOUNDED_SECTION_BY(.note.*, _notes)                     \
        } NOTES_HEADERS                                                 \
index 3598839..ad08f83 100644 (file)
@@ -105,6 +105,22 @@ char *drmm_kstrdup(struct drm_device *dev, const char *s, gfp_t gfp);
 
 void drmm_kfree(struct drm_device *dev, void *data);
 
-int drmm_mutex_init(struct drm_device *dev, struct mutex *lock);
+void __drmm_mutex_release(struct drm_device *dev, void *res);
+
+/**
+ * drmm_mutex_init - &drm_device-managed mutex_init()
+ * @dev: DRM device
+ * @lock: lock to be initialized
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ *
+ * This is a &drm_device-managed version of mutex_init(). The initialized
+ * lock is automatically destroyed on the final drm_dev_put().
+ */
+#define drmm_mutex_init(dev, lock) ({                                       \
+       mutex_init(lock);                                                    \
+       drmm_add_action_or_reset(dev, __drmm_mutex_release, lock);           \
+})                                                                          \
 
 #endif
index c87aeec..583fe3b 100644 (file)
@@ -96,6 +96,7 @@
 
 /* FFA Bus/Device/Driver related */
 struct ffa_device {
+       u32 id;
        int vm_id;
        bool mode_32bit;
        uuid_t uuid;
index 1716c01..efb6e2c 100644 (file)
@@ -391,7 +391,7 @@ struct fw_iso_packet {
        u32 tag:2;              /* tx: Tag in packet header             */
        u32 sy:4;               /* tx: Sy in packet header              */
        u32 header_length:8;    /* Length of immediate header           */
-       u32 header[0];          /* tx: Top of 1394 isoch. data_block    */
+       u32 header[];           /* tx: Top of 1394 isoch. data_block    */
 };
 
 #define FW_ISO_CONTEXT_TRANSMIT                        0
index 21a9816..133f064 100644 (file)
@@ -1076,29 +1076,29 @@ extern int send_sigurg(struct fown_struct *fown);
  * sb->s_flags.  Note that these mirror the equivalent MS_* flags where
  * represented in both.
  */
-#define SB_RDONLY       1      /* Mount read-only */
-#define SB_NOSUID       2      /* Ignore suid and sgid bits */
-#define SB_NODEV        4      /* Disallow access to device special files */
-#define SB_NOEXEC       8      /* Disallow program execution */
-#define SB_SYNCHRONOUS 16      /* Writes are synced at once */
-#define SB_MANDLOCK    64      /* Allow mandatory locks on an FS */
-#define SB_DIRSYNC     128     /* Directory modifications are synchronous */
-#define SB_NOATIME     1024    /* Do not update access times. */
-#define SB_NODIRATIME  2048    /* Do not update directory access times */
-#define SB_SILENT      32768
-#define SB_POSIXACL    (1<<16) /* VFS does not apply the umask */
-#define SB_INLINECRYPT (1<<17) /* Use blk-crypto for encrypted files */
-#define SB_KERNMOUNT   (1<<22) /* this is a kern_mount call */
-#define SB_I_VERSION   (1<<23) /* Update inode I_version field */
-#define SB_LAZYTIME    (1<<25) /* Update the on-disk [acm]times lazily */
+#define SB_RDONLY       BIT(0) /* Mount read-only */
+#define SB_NOSUID       BIT(1) /* Ignore suid and sgid bits */
+#define SB_NODEV        BIT(2) /* Disallow access to device special files */
+#define SB_NOEXEC       BIT(3) /* Disallow program execution */
+#define SB_SYNCHRONOUS  BIT(4) /* Writes are synced at once */
+#define SB_MANDLOCK     BIT(6) /* Allow mandatory locks on an FS */
+#define SB_DIRSYNC      BIT(7) /* Directory modifications are synchronous */
+#define SB_NOATIME      BIT(10)        /* Do not update access times. */
+#define SB_NODIRATIME   BIT(11)        /* Do not update directory access times */
+#define SB_SILENT       BIT(15)
+#define SB_POSIXACL     BIT(16)        /* VFS does not apply the umask */
+#define SB_INLINECRYPT  BIT(17)        /* Use blk-crypto for encrypted files */
+#define SB_KERNMOUNT    BIT(22)        /* this is a kern_mount call */
+#define SB_I_VERSION    BIT(23)        /* Update inode I_version field */
+#define SB_LAZYTIME     BIT(25)        /* Update the on-disk [acm]times lazily */
 
 /* These sb flags are internal to the kernel */
-#define SB_SUBMOUNT     (1<<26)
-#define SB_FORCE       (1<<27)
-#define SB_NOSEC       (1<<28)
-#define SB_BORN                (1<<29)
-#define SB_ACTIVE      (1<<30)
-#define SB_NOUSER      (1<<31)
+#define SB_SUBMOUNT     BIT(26)
+#define SB_FORCE        BIT(27)
+#define SB_NOSEC        BIT(28)
+#define SB_BORN         BIT(29)
+#define SB_ACTIVE       BIT(30)
+#define SB_NOUSER       BIT(31)
 
 /* These flags relate to encoding and casefolding */
 #define SB_ENC_STRICT_MODE_FL  (1 << 0)
index fc985e5..8de6b6e 100644 (file)
@@ -208,6 +208,7 @@ struct team {
        bool queue_override_enabled;
        struct list_head *qom_lists; /* array of queue override mapping lists */
        bool port_mtu_change_allowed;
+       bool notifier_ctx;
        struct {
                unsigned int count;
                unsigned int interval; /* in ms */
index b32256e..74bd269 100644 (file)
@@ -344,6 +344,16 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
 #define lockdep_repin_lock(l,c)        lock_repin_lock(&(l)->dep_map, (c))
 #define lockdep_unpin_lock(l,c)        lock_unpin_lock(&(l)->dep_map, (c))
 
+/*
+ * Must use lock_map_aquire_try() with override maps to avoid
+ * lockdep thinking they participate in the block chain.
+ */
+#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type)    \
+       struct lockdep_map _name = {                    \
+               .name = #_name "-wait-type-override",   \
+               .wait_type_inner = _wait_type,          \
+               .lock_type = LD_LOCK_WAIT_OVERRIDE, }
+
 #else /* !CONFIG_LOCKDEP */
 
 static inline void lockdep_init_task(struct task_struct *task)
@@ -432,6 +442,9 @@ extern int lockdep_is_held(const void *);
 #define lockdep_repin_lock(l, c)               do { (void)(l); (void)(c); } while (0)
 #define lockdep_unpin_lock(l, c)               do { (void)(l); (void)(c); } while (0)
 
+#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type)    \
+       struct lockdep_map __maybe_unused _name = {}
+
 #endif /* !LOCKDEP */
 
 enum xhlock_context_t {
@@ -556,6 +569,7 @@ do {                                                                        \
 #define rwsem_release(l, i)                    lock_release(l, i)
 
 #define lock_map_acquire(l)                    lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_)
+#define lock_map_acquire_try(l)                        lock_acquire_exclusive(l, 0, 1, NULL, _THIS_IP_)
 #define lock_map_acquire_read(l)               lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_)
 #define lock_map_acquire_tryread(l)            lock_acquire_shared_recursive(l, 0, 1, NULL, _THIS_IP_)
 #define lock_map_release(l)                    lock_release(l, _THIS_IP_)
index d224308..59f4fb1 100644 (file)
@@ -33,6 +33,7 @@ enum lockdep_wait_type {
 enum lockdep_lock_type {
        LD_LOCK_NORMAL = 0,     /* normal, catch all */
        LD_LOCK_PERCPU,         /* percpu */
+       LD_LOCK_WAIT_OVERRIDE,  /* annotation */
        LD_LOCK_MAX,
 };
 
index a4c4f73..94d2be5 100644 (file)
@@ -1093,6 +1093,7 @@ void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev);
 int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn,
                         int npsvs, u32 *sig_index);
 int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num);
+__be32 mlx5_core_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev);
 void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common);
 int mlx5_query_odp_caps(struct mlx5_core_dev *dev,
                        struct mlx5_odp_caps *odp_caps);
index dc5e2cb..b89778d 100644 (file)
@@ -1705,7 +1705,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         rc[0x1];
 
        u8         uar_4k[0x1];
-       u8         reserved_at_241[0x9];
+       u8         reserved_at_241[0x7];
+       u8         fl_rc_qp_when_roce_disabled[0x1];
+       u8         regexp_params[0x1];
        u8         uar_sz[0x6];
        u8         port_selection_cap[0x1];
        u8         reserved_at_248[0x1];
index cdb14a1..a50ea79 100644 (file)
@@ -383,6 +383,13 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
 void arch_teardown_msi_irqs(struct pci_dev *dev);
+#endif /* CONFIG_PCI_MSI_ARCH_FALLBACKS */
+
+/*
+ * Xen uses non-default msi_domain_ops and hence needs a way to populate sysfs
+ * entries of MSI IRQs.
+ */
+#if defined(CONFIG_PCI_XEN) || defined(CONFIG_PCI_MSI_ARCH_FALLBACKS)
 #ifdef CONFIG_SYSFS
 int msi_device_populate_sysfs(struct device *dev);
 void msi_device_destroy_sysfs(struct device *dev);
@@ -390,7 +397,7 @@ void msi_device_destroy_sysfs(struct device *dev);
 static inline int msi_device_populate_sysfs(struct device *dev) { return 0; }
 static inline void msi_device_destroy_sysfs(struct device *dev) { }
 #endif /* !CONFIG_SYSFS */
-#endif /* CONFIG_PCI_MSI_ARCH_FALLBACKS */
+#endif /* CONFIG_PCI_XEN || CONFIG_PCI_MSI_ARCH_FALLBACKS */
 
 /*
  * The restore hook is still available even for fully irq domain based
index a1aa681..7c8d654 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef __LINUX_BQ27X00_BATTERY_H__
 #define __LINUX_BQ27X00_BATTERY_H__
 
+#include <linux/power_supply.h>
+
 enum bq27xxx_chip {
        BQ27000 = 1, /* bq27000, bq27200 */
        BQ27010, /* bq27010, bq27210 */
@@ -68,7 +70,9 @@ struct bq27xxx_device_info {
        struct bq27xxx_access_methods bus;
        struct bq27xxx_reg_cache cache;
        int charge_design_full;
+       bool removed;
        unsigned long last_update;
+       union power_supply_propval last_status;
        struct delayed_work work;
        struct power_supply *bat;
        struct list_head list;
index 537cbf9..e0f5ac9 100644 (file)
@@ -29,7 +29,6 @@ struct kernel_clone_args {
        u32 io_thread:1;
        u32 user_worker:1;
        u32 no_files:1;
-       u32 ignore_signals:1;
        unsigned long stack;
        unsigned long stack_size;
        unsigned long tls;
index 6123c10..837a236 100644 (file)
@@ -2,22 +2,13 @@
 #ifndef _LINUX_VHOST_TASK_H
 #define _LINUX_VHOST_TASK_H
 
-#include <linux/completion.h>
 
-struct task_struct;
+struct vhost_task;
 
-struct vhost_task {
-       int (*fn)(void *data);
-       void *data;
-       struct completion exited;
-       unsigned long flags;
-       struct task_struct *task;
-};
-
-struct vhost_task *vhost_task_create(int (*fn)(void *), void *arg,
+struct vhost_task *vhost_task_create(bool (*fn)(void *), void *arg,
                                     const char *name);
 void vhost_task_start(struct vhost_task *vtsk);
 void vhost_task_stop(struct vhost_task *vtsk);
-bool vhost_task_should_stop(struct vhost_task *vtsk);
+void vhost_task_wake(struct vhost_task *vtsk);
 
 #endif
index 738776a..0b40417 100644 (file)
@@ -1587,6 +1587,16 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
        to->l4_hash = from->l4_hash;
 };
 
+static inline int skb_cmp_decrypted(const struct sk_buff *skb1,
+                                   const struct sk_buff *skb2)
+{
+#ifdef CONFIG_TLS_DEVICE
+       return skb2->decrypted - skb1->decrypted;
+#else
+       return 0;
+#endif
+}
+
 static inline void skb_copy_decrypted(struct sk_buff *to,
                                      const struct sk_buff *from)
 {
index 84f7874..054d791 100644 (file)
@@ -71,7 +71,6 @@ struct sk_psock_link {
 };
 
 struct sk_psock_work_state {
-       struct sk_buff                  *skb;
        u32                             len;
        u32                             off;
 };
@@ -105,7 +104,7 @@ struct sk_psock {
        struct proto                    *sk_proto;
        struct mutex                    work_mutex;
        struct sk_psock_work_state      work_state;
-       struct work_struct              work;
+       struct delayed_work             work;
        struct rcu_work                 rwork;
 };
 
index 0e37322..7c4a0b7 100644 (file)
@@ -806,6 +806,7 @@ enum {
        FILTER_TRACE_FN,
        FILTER_COMM,
        FILTER_CPU,
+       FILTER_STACKTRACE,
 };
 
 extern int trace_event_raw_init(struct trace_event_call *call);
index 2847f5a..8afa8c3 100644 (file)
 
 #ifdef CONFIG_USER_EVENTS
 struct user_event_mm {
-       struct list_head        link;
+       struct list_head        mms_link;
        struct list_head        enablers;
        struct mm_struct        *mm;
+       /* Used for one-shot lists, protected by event_mutex */
        struct user_event_mm    *next;
        refcount_t              refcnt;
        refcount_t              tasks;
index a6c8aee..8baf346 100644 (file)
@@ -1327,7 +1327,7 @@ int hci_le_create_cis(struct hci_conn *conn);
 
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
                              u8 role);
-int hci_conn_del(struct hci_conn *conn);
+void hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
index 0efef2a..59955ac 100644 (file)
@@ -221,6 +221,7 @@ struct bonding {
        struct   bond_up_slave __rcu *usable_slaves;
        struct   bond_up_slave __rcu *all_slaves;
        bool     force_primary;
+       bool     notifier_ctx;
        s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
        int     (*recv_probe)(const struct sk_buff *, struct bonding *,
                              struct slave *);
index 3352b1a..2e26e43 100644 (file)
@@ -24,6 +24,7 @@ struct tls_handshake_args {
        struct socket           *ta_sock;
        tls_done_func_t         ta_done;
        void                    *ta_data;
+       const char              *ta_peername;
        unsigned int            ta_timeout_ms;
        key_serial_t            ta_keyring;
        key_serial_t            ta_my_cert;
index c3fffaa..acec504 100644 (file)
@@ -76,6 +76,7 @@ struct ipcm_cookie {
        __be32                  addr;
        int                     oif;
        struct ip_options_rcu   *opt;
+       __u8                    protocol;
        __u8                    ttl;
        __s16                   tos;
        char                    priority;
@@ -96,6 +97,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
        ipcm->sockc.tsflags = inet->sk.sk_tsflags;
        ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
        ipcm->addr = inet->inet_saddr;
+       ipcm->protocol = inet->inet_num;
 }
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
index cd386aa..9eef199 100644 (file)
@@ -347,10 +347,8 @@ struct mana_tx_qp {
 struct mana_ethtool_stats {
        u64 stop_queue;
        u64 wake_queue;
-       u64 tx_cqes;
        u64 tx_cqe_err;
        u64 tx_cqe_unknown_type;
-       u64 rx_cqes;
        u64 rx_coalesced_err;
        u64 rx_cqe_unknown_type;
 };
index c8ec2f3..126f9e2 100644 (file)
@@ -399,22 +399,4 @@ static inline void page_pool_nid_changed(struct page_pool *pool, int new_nid)
                page_pool_update_nid(pool, new_nid);
 }
 
-static inline void page_pool_ring_lock(struct page_pool *pool)
-       __acquires(&pool->ring.producer_lock)
-{
-       if (in_softirq())
-               spin_lock(&pool->ring.producer_lock);
-       else
-               spin_lock_bh(&pool->ring.producer_lock);
-}
-
-static inline void page_pool_ring_unlock(struct page_pool *pool)
-       __releases(&pool->ring.producer_lock)
-{
-       if (in_softirq())
-               spin_unlock(&pool->ring.producer_lock);
-       else
-               spin_unlock_bh(&pool->ring.producer_lock);
-}
-
 #endif /* _NET_PAGE_POOL_H */
index 656ea89..b418425 100644 (file)
@@ -336,6 +336,7 @@ struct sk_filter;
   *    @sk_cgrp_data: cgroup data for this cgroup
   *    @sk_memcg: this socket's memory cgroup association
   *    @sk_write_pending: a write to stream socket waits to start
+  *    @sk_wait_pending: number of threads blocked on this socket
   *    @sk_state_change: callback to indicate change in the state of the sock
   *    @sk_data_ready: callback to indicate there is data to be processed
   *    @sk_write_space: callback to indicate there is bf sending space available
@@ -428,6 +429,7 @@ struct sock {
        unsigned int            sk_napi_id;
 #endif
        int                     sk_rcvbuf;
+       int                     sk_wait_pending;
 
        struct sk_filter __rcu  *sk_filter;
        union {
@@ -1174,6 +1176,7 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
 
 #define sk_wait_event(__sk, __timeo, __condition, __wait)              \
        ({      int __rc;                                               \
+               __sk->sk_wait_pending++;                                \
                release_sock(__sk);                                     \
                __rc = __condition;                                     \
                if (!__rc) {                                            \
@@ -1183,6 +1186,7 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
                }                                                       \
                sched_annotate_sleep();                                 \
                lock_sock(__sk);                                        \
+               __sk->sk_wait_pending--;                                \
                __rc = __condition;                                     \
                __rc;                                                   \
        })
index 04a3164..5066e45 100644 (file)
@@ -632,6 +632,7 @@ void tcp_reset(struct sock *sk, struct sk_buff *skb);
 void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
 void tcp_fin(struct sock *sk);
 void tcp_check_space(struct sock *sk);
+void tcp_sack_compress_send_ack(struct sock *sk);
 
 /* tcp_timer.c */
 void tcp_init_xmit_timers(struct sock *);
@@ -1470,6 +1471,8 @@ static inline void tcp_adjust_rcv_ssthresh(struct sock *sk)
 }
 
 void tcp_cleanup_rbuf(struct sock *sk, int copied);
+void __tcp_cleanup_rbuf(struct sock *sk, int copied);
+
 
 /* We provision sk_rcvbuf around 200% of sk_rcvlowat.
  * If 87.5 % (7/8) of the space has been consumed, we want to override
@@ -2326,6 +2329,14 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
 void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
 #endif /* CONFIG_BPF_SYSCALL */
 
+#ifdef CONFIG_INET
+void tcp_eat_skb(struct sock *sk, struct sk_buff *skb);
+#else
+static inline void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
+{
+}
+#endif
+
 int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress,
                          struct sk_msg *msg, u32 bytes, int flags);
 #endif /* CONFIG_NET_SOCK_MSG */
index 6056ce5..596595c 100644 (file)
@@ -126,6 +126,7 @@ struct tls_strparser {
        u32 mark : 8;
        u32 stopped : 1;
        u32 copy_mode : 1;
+       u32 mixed_decrypted : 1;
        u32 msg_ready : 1;
 
        struct strp_msg stm;
index b38fd25..5282790 100644 (file)
@@ -170,6 +170,7 @@ struct snd_soc_acpi_link_adr {
 /* Descriptor for SST ASoC machine driver */
 struct snd_soc_acpi_mach {
        u8 id[ACPI_ID_LEN];
+       const char *uid;
        const struct snd_soc_acpi_codecs *comp_ids;
        const u32 link_mask;
        const struct snd_soc_acpi_link_adr *links;
index 4d6ac76..ebd2475 100644 (file)
@@ -122,6 +122,10 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
 int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
                struct snd_soc_pcm_runtime *be, int stream);
 
+/* can this BE perform prepare */
+int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
+                                struct snd_soc_pcm_runtime *be, int stream);
+
 /* is the current PCM operation for this FE ? */
 int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
 
index 1de4d0b..3d7ea58 100644 (file)
@@ -44,6 +44,7 @@ enum {
        HANDSHAKE_A_ACCEPT_AUTH_MODE,
        HANDSHAKE_A_ACCEPT_PEER_IDENTITY,
        HANDSHAKE_A_ACCEPT_CERTIFICATE,
+       HANDSHAKE_A_ACCEPT_PEERNAME,
 
        __HANDSHAKE_A_ACCEPT_MAX,
        HANDSHAKE_A_ACCEPT_MAX = (__HANDSHAKE_A_ACCEPT_MAX - 1)
index 4b7f2df..e682ab6 100644 (file)
@@ -163,6 +163,7 @@ struct in_addr {
 #define IP_MULTICAST_ALL               49
 #define IP_UNICAST_IF                  50
 #define IP_LOCAL_PORT_RANGE            51
+#define IP_PROTOCOL                    52
 
 #define MCAST_EXCLUDE  0
 #define MCAST_INCLUDE  1
index f29899b..4bf9c4f 100644 (file)
@@ -66,7 +66,8 @@ enum skl_ch_cfg {
        SKL_CH_CFG_DUAL_MONO = 9,
        SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
        SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
-       SKL_CH_CFG_4_CHANNEL = 12,
+       SKL_CH_CFG_7_1 = 12,
+       SKL_CH_CFG_4_CHANNEL = SKL_CH_CFG_7_1,
        SKL_CH_CFG_INVALID
 };
 
index 9db4bc1..5e329e3 100644 (file)
@@ -255,9 +255,13 @@ static int io_sq_thread(void *data)
                        sqt_spin = true;
 
                if (sqt_spin || !time_after(jiffies, timeout)) {
-                       cond_resched();
                        if (sqt_spin)
                                timeout = jiffies + sqd->sq_thread_idle;
+                       if (unlikely(need_resched())) {
+                               mutex_unlock(&sqd->lock);
+                               cond_resched();
+                               mutex_lock(&sqd->lock);
+                       }
                        continue;
                }
 
index 00c253b..9901efe 100644 (file)
@@ -1215,7 +1215,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 
        ret = htab_lock_bucket(htab, b, hash, &flags);
        if (ret)
-               return ret;
+               goto err_lock_bucket;
 
        l_old = lookup_elem_raw(head, hash, key, key_size);
 
@@ -1236,6 +1236,7 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
 err:
        htab_unlock_bucket(htab, b, hash, flags);
 
+err_lock_bucket:
        if (ret)
                htab_lru_push_free(htab, l_new);
        else if (l_old)
@@ -1338,7 +1339,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
 
        ret = htab_lock_bucket(htab, b, hash, &flags);
        if (ret)
-               return ret;
+               goto err_lock_bucket;
 
        l_old = lookup_elem_raw(head, hash, key, key_size);
 
@@ -1361,6 +1362,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
        ret = 0;
 err:
        htab_unlock_bucket(htab, b, hash, flags);
+err_lock_bucket:
        if (l_new)
                bpf_lru_push_free(&htab->lru, &l_new->lru_node);
        return ret;
index d9c9f45..8a26cd8 100644 (file)
@@ -859,4 +859,4 @@ static int __init bpf_offload_init(void)
        return rhashtable_init(&offdevs, &offdevs_params);
 }
 
-late_initcall(bpf_offload_init);
+core_initcall(bpf_offload_init);
index fbcf5a4..5871aa7 100644 (file)
@@ -17033,7 +17033,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
                                        insn_buf[cnt++] = BPF_ALU64_IMM(BPF_RSH,
                                                                        insn->dst_reg,
                                                                        shift);
-                               insn_buf[cnt++] = BPF_ALU64_IMM(BPF_AND, insn->dst_reg,
+                               insn_buf[cnt++] = BPF_ALU32_IMM(BPF_AND, insn->dst_reg,
                                                                (1ULL << size * 8) - 1);
                        }
                }
index 34b90e2..edb50b4 100644 (file)
@@ -411,7 +411,10 @@ static void coredump_task_exit(struct task_struct *tsk)
        tsk->flags |= PF_POSTCOREDUMP;
        core_state = tsk->signal->core_state;
        spin_unlock_irq(&tsk->sighand->siglock);
-       if (core_state) {
+
+       /* The vhost_worker does not particpate in coredumps */
+       if (core_state &&
+           ((tsk->flags & (PF_IO_WORKER | PF_USER_WORKER)) != PF_USER_WORKER)) {
                struct core_thread self;
 
                self.task = current;
index ed4e01d..81cba91 100644 (file)
@@ -2336,16 +2336,16 @@ __latent_entropy struct task_struct *copy_process(
        p->flags &= ~PF_KTHREAD;
        if (args->kthread)
                p->flags |= PF_KTHREAD;
-       if (args->user_worker)
-               p->flags |= PF_USER_WORKER;
-       if (args->io_thread) {
+       if (args->user_worker) {
                /*
-                * Mark us an IO worker, and block any signal that isn't
+                * Mark us a user worker, and block any signal that isn't
                 * fatal or STOP
                 */
-               p->flags |= PF_IO_WORKER;
+               p->flags |= PF_USER_WORKER;
                siginitsetinv(&p->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
        }
+       if (args->io_thread)
+               p->flags |= PF_IO_WORKER;
 
        if (args->name)
                strscpy_pad(p->comm, args->name, sizeof(p->comm));
@@ -2517,9 +2517,6 @@ __latent_entropy struct task_struct *copy_process(
        if (retval)
                goto bad_fork_cleanup_io;
 
-       if (args->ignore_signals)
-               ignore_signals(p);
-
        stackleak_task_init(p);
 
        if (pid != &init_struct_pid) {
index 7a97bcb..b4c31a5 100644 (file)
@@ -542,7 +542,7 @@ fail:
        return ret;
 }
 
-#ifdef CONFIG_PCI_MSI_ARCH_FALLBACKS
+#if defined(CONFIG_PCI_MSI_ARCH_FALLBACKS) || defined(CONFIG_PCI_XEN)
 /**
  * msi_device_populate_sysfs - Populate msi_irqs sysfs entries for a device
  * @dev:       The device (PCI, platform etc) which will get sysfs entries
@@ -574,7 +574,7 @@ void msi_device_destroy_sysfs(struct device *dev)
        msi_for_each_desc(desc, dev, MSI_DESC_ALL)
                msi_sysfs_remove_desc(dev, desc);
 }
-#endif /* CONFIG_PCI_MSI_ARCH_FALLBACK */
+#endif /* CONFIG_PCI_MSI_ARCH_FALLBACK || CONFIG_PCI_XEN */
 #else /* CONFIG_SYSFS */
 static inline int msi_sysfs_create_group(struct device *dev) { return 0; }
 static inline int msi_sysfs_populate_desc(struct device *dev, struct msi_desc *desc) { return 0; }
index dcd1d5b..4dfd2f3 100644 (file)
@@ -2263,6 +2263,9 @@ static inline bool usage_match(struct lock_list *entry, void *mask)
 
 static inline bool usage_skip(struct lock_list *entry, void *mask)
 {
+       if (entry->class->lock_type == LD_LOCK_NORMAL)
+               return false;
+
        /*
         * Skip local_lock() for irq inversion detection.
         *
@@ -2289,14 +2292,16 @@ static inline bool usage_skip(struct lock_list *entry, void *mask)
         * As a result, we will skip local_lock(), when we search for irq
         * inversion bugs.
         */
-       if (entry->class->lock_type == LD_LOCK_PERCPU) {
-               if (DEBUG_LOCKS_WARN_ON(entry->class->wait_type_inner < LD_WAIT_CONFIG))
-                       return false;
+       if (entry->class->lock_type == LD_LOCK_PERCPU &&
+           DEBUG_LOCKS_WARN_ON(entry->class->wait_type_inner < LD_WAIT_CONFIG))
+               return false;
 
-               return true;
-       }
+       /*
+        * Skip WAIT_OVERRIDE for irq inversion detection -- it's not actually
+        * a lock and only used to override the wait_type.
+        */
 
-       return false;
+       return true;
 }
 
 /*
@@ -4768,7 +4773,8 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
 
        for (; depth < curr->lockdep_depth; depth++) {
                struct held_lock *prev = curr->held_locks + depth;
-               u8 prev_inner = hlock_class(prev)->wait_type_inner;
+               struct lock_class *class = hlock_class(prev);
+               u8 prev_inner = class->wait_type_inner;
 
                if (prev_inner) {
                        /*
@@ -4778,6 +4784,14 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
                         * Also due to trylocks.
                         */
                        curr_inner = min(curr_inner, prev_inner);
+
+                       /*
+                        * Allow override for annotations -- this is typically
+                        * only valid/needed for code that only exists when
+                        * CONFIG_PREEMPT_RT=n.
+                        */
+                       if (unlikely(class->lock_type == LD_LOCK_WAIT_OVERRIDE))
+                               curr_inner = prev_inner;
                }
        }
 
index 044aa2c..4e2cf78 100644 (file)
@@ -1521,14 +1521,14 @@ static void __layout_sections(struct module *mod, struct load_info *info, bool i
                MOD_RODATA,
                MOD_RO_AFTER_INIT,
                MOD_DATA,
-               MOD_INVALID,    /* This is needed to match the masks array */
+               MOD_DATA,
        };
        static const int init_m_to_mem_type[] = {
                MOD_INIT_TEXT,
                MOD_INIT_RODATA,
                MOD_INVALID,
                MOD_INIT_DATA,
-               MOD_INVALID,    /* This is needed to match the masks array */
+               MOD_INIT_DATA,
        };
 
        for (m = 0; m < ARRAY_SIZE(masks); ++m) {
index ad7b6ad..6ab2c94 100644 (file)
@@ -276,6 +276,7 @@ static ssize_t read_file_mod_stats(struct file *file, char __user *user_buf,
        struct mod_fail_load *mod_fail;
        unsigned int len, size, count_failed = 0;
        char *buf;
+       int ret;
        u32 live_mod_count, fkreads, fdecompress, fbecoming, floads;
        unsigned long total_size, text_size, ikread_bytes, ibecoming_bytes,
                idecompress_bytes, imod_bytes, total_virtual_lost;
@@ -390,8 +391,9 @@ static ssize_t read_file_mod_stats(struct file *file, char __user *user_buf,
 out_unlock:
        mutex_unlock(&module_mutex);
 out:
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
        kfree(buf);
-        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       return ret;
 }
 #undef MAX_PREAMBLE
 #undef MAX_FAILED_MOD_PRINT
index 8f6330f..2547fa7 100644 (file)
@@ -1368,7 +1368,9 @@ int zap_other_threads(struct task_struct *p)
 
        while_each_thread(p, t) {
                task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
-               count++;
+               /* Don't require de_thread to wait for the vhost_worker */
+               if ((t->flags & (PF_IO_WORKER | PF_USER_WORKER)) != PF_USER_WORKER)
+                       count++;
 
                /* Don't bother with already dead threads */
                if (t->exit_state)
@@ -2861,11 +2863,11 @@ relock:
                }
 
                /*
-                * PF_IO_WORKER threads will catch and exit on fatal signals
+                * PF_USER_WORKER threads will catch and exit on fatal signals
                 * themselves. They have cleanup that must be performed, so
                 * we cannot call do_exit() on their behalf.
                 */
-               if (current->flags & PF_IO_WORKER)
+               if (current->flags & PF_USER_WORKER)
                        goto out;
 
                /*
index ebc5978..64a4dde 100644 (file)
@@ -60,6 +60,7 @@
  */
 bool ring_buffer_expanded;
 
+#ifdef CONFIG_FTRACE_STARTUP_TEST
 /*
  * We need to change this state when a selftest is running.
  * A selftest will lurk into the ring-buffer to count the
@@ -75,7 +76,6 @@ static bool __read_mostly tracing_selftest_running;
  */
 bool __read_mostly tracing_selftest_disabled;
 
-#ifdef CONFIG_FTRACE_STARTUP_TEST
 void __init disable_tracing_selftest(const char *reason)
 {
        if (!tracing_selftest_disabled) {
@@ -83,6 +83,9 @@ void __init disable_tracing_selftest(const char *reason)
                pr_info("Ftrace startup test is disabled due to %s\n", reason);
        }
 }
+#else
+#define tracing_selftest_running       0
+#define tracing_selftest_disabled      0
 #endif
 
 /* Pipe tracepoints to printk */
@@ -1051,7 +1054,10 @@ int __trace_array_puts(struct trace_array *tr, unsigned long ip,
        if (!(tr->trace_flags & TRACE_ITER_PRINTK))
                return 0;
 
-       if (unlikely(tracing_selftest_running || tracing_disabled))
+       if (unlikely(tracing_selftest_running && tr == &global_trace))
+               return 0;
+
+       if (unlikely(tracing_disabled))
                return 0;
 
        alloc = sizeof(*entry) + size + 2; /* possible \n added */
@@ -2041,6 +2047,24 @@ static int run_tracer_selftest(struct tracer *type)
        return 0;
 }
 
+static int do_run_tracer_selftest(struct tracer *type)
+{
+       int ret;
+
+       /*
+        * Tests can take a long time, especially if they are run one after the
+        * other, as does happen during bootup when all the tracers are
+        * registered. This could cause the soft lockup watchdog to trigger.
+        */
+       cond_resched();
+
+       tracing_selftest_running = true;
+       ret = run_tracer_selftest(type);
+       tracing_selftest_running = false;
+
+       return ret;
+}
+
 static __init int init_trace_selftests(void)
 {
        struct trace_selftests *p, *n;
@@ -2092,6 +2116,10 @@ static inline int run_tracer_selftest(struct tracer *type)
 {
        return 0;
 }
+static inline int do_run_tracer_selftest(struct tracer *type)
+{
+       return 0;
+}
 #endif /* CONFIG_FTRACE_STARTUP_TEST */
 
 static void add_tracer_options(struct trace_array *tr, struct tracer *t);
@@ -2127,8 +2155,6 @@ int __init register_tracer(struct tracer *type)
 
        mutex_lock(&trace_types_lock);
 
-       tracing_selftest_running = true;
-
        for (t = trace_types; t; t = t->next) {
                if (strcmp(type->name, t->name) == 0) {
                        /* already found */
@@ -2157,7 +2183,7 @@ int __init register_tracer(struct tracer *type)
        /* store the tracer for __set_tracer_option */
        type->flags->trace = type;
 
-       ret = run_tracer_selftest(type);
+       ret = do_run_tracer_selftest(type);
        if (ret < 0)
                goto out;
 
@@ -2166,7 +2192,6 @@ int __init register_tracer(struct tracer *type)
        add_tracer_options(&global_trace, type);
 
  out:
-       tracing_selftest_running = false;
        mutex_unlock(&trace_types_lock);
 
        if (ret || !default_bootup_tracer)
@@ -3490,7 +3515,7 @@ __trace_array_vprintk(struct trace_buffer *buffer,
        unsigned int trace_ctx;
        char *tbuffer;
 
-       if (tracing_disabled || tracing_selftest_running)
+       if (tracing_disabled)
                return 0;
 
        /* Don't pollute graph traces with trace_vprintk internals */
@@ -3538,6 +3563,9 @@ __printf(3, 0)
 int trace_array_vprintk(struct trace_array *tr,
                        unsigned long ip, const char *fmt, va_list args)
 {
+       if (tracing_selftest_running && tr == &global_trace)
+               return 0;
+
        return __trace_array_vprintk(tr->array_buffer.buffer, ip, fmt, args);
 }
 
@@ -5752,7 +5780,7 @@ static const char readme_msg[] =
        "\t    table using the key(s) and value(s) named, and the value of a\n"
        "\t    sum called 'hitcount' is incremented.  Keys and values\n"
        "\t    correspond to fields in the event's format description.  Keys\n"
-       "\t    can be any field, or the special string 'stacktrace'.\n"
+       "\t    can be any field, or the special string 'common_stacktrace'.\n"
        "\t    Compound keys consisting of up to two fields can be specified\n"
        "\t    by the 'keys' keyword.  Values must correspond to numeric\n"
        "\t    fields.  Sort keys consisting of up to two fields can be\n"
index 654ffa4..57e539d 100644 (file)
@@ -194,6 +194,8 @@ static int trace_define_generic_fields(void)
        __generic_field(int, common_cpu, FILTER_CPU);
        __generic_field(char *, COMM, FILTER_COMM);
        __generic_field(char *, comm, FILTER_COMM);
+       __generic_field(char *, stacktrace, FILTER_STACKTRACE);
+       __generic_field(char *, STACKTRACE, FILTER_STACKTRACE);
 
        return ret;
 }
index 486cca3..b97d3ad 100644 (file)
@@ -1364,7 +1364,7 @@ static const char *hist_field_name(struct hist_field *field,
                if (field->field)
                        field_name = field->field->name;
                else
-                       field_name = "stacktrace";
+                       field_name = "common_stacktrace";
        } else if (field->flags & HIST_FIELD_FL_HITCOUNT)
                field_name = "hitcount";
 
@@ -2367,7 +2367,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
                hist_data->enable_timestamps = true;
                if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS)
                        hist_data->attrs->ts_in_usecs = true;
-       } else if (strcmp(field_name, "stacktrace") == 0) {
+       } else if (strcmp(field_name, "common_stacktrace") == 0) {
                *flags |= HIST_FIELD_FL_STACKTRACE;
        } else if (strcmp(field_name, "common_cpu") == 0)
                *flags |= HIST_FIELD_FL_CPU;
@@ -2378,11 +2378,15 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
                if (!field || !field->size) {
                        /*
                         * For backward compatibility, if field_name
-                        * was "cpu", then we treat this the same as
-                        * common_cpu. This also works for "CPU".
+                        * was "cpu" or "stacktrace", then we treat this
+                        * the same as common_cpu and common_stacktrace
+                        * respectively. This also works for "CPU", and
+                        * "STACKTRACE".
                         */
                        if (field && field->filter_type == FILTER_CPU) {
                                *flags |= HIST_FIELD_FL_CPU;
+                       } else if (field && field->filter_type == FILTER_STACKTRACE) {
+                               *flags |= HIST_FIELD_FL_STACKTRACE;
                        } else {
                                hist_err(tr, HIST_ERR_FIELD_NOT_FOUND,
                                         errpos(field_name));
@@ -4238,13 +4242,19 @@ static int __create_val_field(struct hist_trigger_data *hist_data,
                goto out;
        }
 
-       /* Some types cannot be a value */
-       if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
-                                HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2 |
-                                HIST_FIELD_FL_SYM | HIST_FIELD_FL_SYM_OFFSET |
-                                HIST_FIELD_FL_SYSCALL | HIST_FIELD_FL_STACKTRACE)) {
-               hist_err(file->tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(field_str));
-               ret = -EINVAL;
+       /* values and variables should not have some modifiers */
+       if (hist_field->flags & HIST_FIELD_FL_VAR) {
+               /* Variable */
+               if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
+                                        HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2))
+                       goto err;
+       } else {
+               /* Value */
+               if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
+                                        HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2 |
+                                        HIST_FIELD_FL_SYM | HIST_FIELD_FL_SYM_OFFSET |
+                                        HIST_FIELD_FL_SYSCALL | HIST_FIELD_FL_STACKTRACE))
+                       goto err;
        }
 
        hist_data->fields[val_idx] = hist_field;
@@ -4256,6 +4266,9 @@ static int __create_val_field(struct hist_trigger_data *hist_data,
                ret = -EINVAL;
  out:
        return ret;
+ err:
+       hist_err(file->tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(field_str));
+       return -EINVAL;
 }
 
 static int create_val_field(struct hist_trigger_data *hist_data,
@@ -5385,7 +5398,7 @@ static void hist_trigger_print_key(struct seq_file *m,
                        if (key_field->field)
                                seq_printf(m, "%s.stacktrace", key_field->field->name);
                        else
-                               seq_puts(m, "stacktrace:\n");
+                               seq_puts(m, "common_stacktrace:\n");
                        hist_trigger_stacktrace_print(m,
                                                      key + key_field->offset,
                                                      HIST_STACKTRACE_DEPTH);
@@ -5968,7 +5981,7 @@ static int event_hist_trigger_print(struct seq_file *m,
                        if (field->field)
                                seq_printf(m, "%s.stacktrace", field->field->name);
                        else
-                               seq_puts(m, "stacktrace");
+                               seq_puts(m, "common_stacktrace");
                } else
                        hist_field_print(m, field);
        }
index b1ecd76..dbb1470 100644 (file)
@@ -96,12 +96,12 @@ struct user_event {
  * these to track enablement sites that are tied to an event.
  */
 struct user_event_enabler {
-       struct list_head        link;
+       struct list_head        mm_enablers_link;
        struct user_event       *event;
        unsigned long           addr;
 
        /* Track enable bit, flags, etc. Aligned for bitops. */
-       unsigned int            values;
+       unsigned long           values;
 };
 
 /* Bits 0-5 are for the bit to update upon enable/disable (0-63 allowed) */
@@ -116,7 +116,9 @@ struct user_event_enabler {
 /* Only duplicate the bit value */
 #define ENABLE_VAL_DUP_MASK ENABLE_VAL_BIT_MASK
 
-#define ENABLE_BITOPS(e) ((unsigned long *)&(e)->values)
+#define ENABLE_BITOPS(e) (&(e)->values)
+
+#define ENABLE_BIT(e) ((int)((e)->values & ENABLE_VAL_BIT_MASK))
 
 /* Used for asynchronous faulting in of pages */
 struct user_event_enabler_fault {
@@ -153,7 +155,7 @@ struct user_event_file_info {
 #define VALIDATOR_REL (1 << 1)
 
 struct user_event_validator {
-       struct list_head        link;
+       struct list_head        user_event_link;
        int                     offset;
        int                     flags;
 };
@@ -259,7 +261,7 @@ error:
 
 static void user_event_enabler_destroy(struct user_event_enabler *enabler)
 {
-       list_del_rcu(&enabler->link);
+       list_del_rcu(&enabler->mm_enablers_link);
 
        /* No longer tracking the event via the enabler */
        refcount_dec(&enabler->event->refcnt);
@@ -423,9 +425,9 @@ static int user_event_enabler_write(struct user_event_mm *mm,
 
        /* Update bit atomically, user tracers must be atomic as well */
        if (enabler->event && enabler->event->status)
-               set_bit(enabler->values & ENABLE_VAL_BIT_MASK, ptr);
+               set_bit(ENABLE_BIT(enabler), ptr);
        else
-               clear_bit(enabler->values & ENABLE_VAL_BIT_MASK, ptr);
+               clear_bit(ENABLE_BIT(enabler), ptr);
 
        kunmap_local(kaddr);
        unpin_user_pages_dirty_lock(&page, 1, true);
@@ -437,11 +439,9 @@ static bool user_event_enabler_exists(struct user_event_mm *mm,
                                      unsigned long uaddr, unsigned char bit)
 {
        struct user_event_enabler *enabler;
-       struct user_event_enabler *next;
 
-       list_for_each_entry_safe(enabler, next, &mm->enablers, link) {
-               if (enabler->addr == uaddr &&
-                   (enabler->values & ENABLE_VAL_BIT_MASK) == bit)
+       list_for_each_entry(enabler, &mm->enablers, mm_enablers_link) {
+               if (enabler->addr == uaddr && ENABLE_BIT(enabler) == bit)
                        return true;
        }
 
@@ -451,23 +451,36 @@ static bool user_event_enabler_exists(struct user_event_mm *mm,
 static void user_event_enabler_update(struct user_event *user)
 {
        struct user_event_enabler *enabler;
-       struct user_event_mm *mm = user_event_mm_get_all(user);
        struct user_event_mm *next;
+       struct user_event_mm *mm;
        int attempt;
 
+       lockdep_assert_held(&event_mutex);
+
+       /*
+        * We need to build a one-shot list of all the mms that have an
+        * enabler for the user_event passed in. This list is only valid
+        * while holding the event_mutex. The only reason for this is due
+        * to the global mm list being RCU protected and we use methods
+        * which can wait (mmap_read_lock and pin_user_pages_remote).
+        *
+        * NOTE: user_event_mm_get_all() increments the ref count of each
+        * mm that is added to the list to prevent removal timing windows.
+        * We must always put each mm after they are used, which may wait.
+        */
+       mm = user_event_mm_get_all(user);
+
        while (mm) {
                next = mm->next;
                mmap_read_lock(mm->mm);
-               rcu_read_lock();
 
-               list_for_each_entry_rcu(enabler, &mm->enablers, link) {
+               list_for_each_entry(enabler, &mm->enablers, mm_enablers_link) {
                        if (enabler->event == user) {
                                attempt = 0;
                                user_event_enabler_write(mm, enabler, true, &attempt);
                        }
                }
 
-               rcu_read_unlock();
                mmap_read_unlock(mm->mm);
                user_event_mm_put(mm);
                mm = next;
@@ -495,7 +508,9 @@ static bool user_event_enabler_dup(struct user_event_enabler *orig,
        enabler->values = orig->values & ENABLE_VAL_DUP_MASK;
 
        refcount_inc(&enabler->event->refcnt);
-       list_add_rcu(&enabler->link, &mm->enablers);
+
+       /* Enablers not exposed yet, RCU not required */
+       list_add(&enabler->mm_enablers_link, &mm->enablers);
 
        return true;
 }
@@ -514,6 +529,14 @@ static struct user_event_mm *user_event_mm_get_all(struct user_event *user)
        struct user_event_mm *mm;
 
        /*
+        * We use the mm->next field to build a one-shot list from the global
+        * RCU protected list. To build this list the event_mutex must be held.
+        * This lets us build a list without requiring allocs that could fail
+        * when user based events are most wanted for diagnostics.
+        */
+       lockdep_assert_held(&event_mutex);
+
+       /*
         * We do not want to block fork/exec while enablements are being
         * updated, so we use RCU to walk the current tasks that have used
         * user_events ABI for 1 or more events. Each enabler found in each
@@ -525,23 +548,24 @@ static struct user_event_mm *user_event_mm_get_all(struct user_event *user)
         */
        rcu_read_lock();
 
-       list_for_each_entry_rcu(mm, &user_event_mms, link)
-               list_for_each_entry_rcu(enabler, &mm->enablers, link)
+       list_for_each_entry_rcu(mm, &user_event_mms, mms_link) {
+               list_for_each_entry_rcu(enabler, &mm->enablers, mm_enablers_link) {
                        if (enabler->event == user) {
                                mm->next = found;
                                found = user_event_mm_get(mm);
                                break;
                        }
+               }
+       }
 
        rcu_read_unlock();
 
        return found;
 }
 
-static struct user_event_mm *user_event_mm_create(struct task_struct *t)
+static struct user_event_mm *user_event_mm_alloc(struct task_struct *t)
 {
        struct user_event_mm *user_mm;
-       unsigned long flags;
 
        user_mm = kzalloc(sizeof(*user_mm), GFP_KERNEL_ACCOUNT);
 
@@ -553,12 +577,6 @@ static struct user_event_mm *user_event_mm_create(struct task_struct *t)
        refcount_set(&user_mm->refcnt, 1);
        refcount_set(&user_mm->tasks, 1);
 
-       spin_lock_irqsave(&user_event_mms_lock, flags);
-       list_add_rcu(&user_mm->link, &user_event_mms);
-       spin_unlock_irqrestore(&user_event_mms_lock, flags);
-
-       t->user_event_mm = user_mm;
-
        /*
         * The lifetime of the memory descriptor can slightly outlast
         * the task lifetime if a ref to the user_event_mm is taken
@@ -572,6 +590,17 @@ static struct user_event_mm *user_event_mm_create(struct task_struct *t)
        return user_mm;
 }
 
+static void user_event_mm_attach(struct user_event_mm *user_mm, struct task_struct *t)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&user_event_mms_lock, flags);
+       list_add_rcu(&user_mm->mms_link, &user_event_mms);
+       spin_unlock_irqrestore(&user_event_mms_lock, flags);
+
+       t->user_event_mm = user_mm;
+}
+
 static struct user_event_mm *current_user_event_mm(void)
 {
        struct user_event_mm *user_mm = current->user_event_mm;
@@ -579,10 +608,12 @@ static struct user_event_mm *current_user_event_mm(void)
        if (user_mm)
                goto inc;
 
-       user_mm = user_event_mm_create(current);
+       user_mm = user_event_mm_alloc(current);
 
        if (!user_mm)
                goto error;
+
+       user_event_mm_attach(user_mm, current);
 inc:
        refcount_inc(&user_mm->refcnt);
 error:
@@ -593,7 +624,7 @@ static void user_event_mm_destroy(struct user_event_mm *mm)
 {
        struct user_event_enabler *enabler, *next;
 
-       list_for_each_entry_safe(enabler, next, &mm->enablers, link)
+       list_for_each_entry_safe(enabler, next, &mm->enablers, mm_enablers_link)
                user_event_enabler_destroy(enabler);
 
        mmdrop(mm->mm);
@@ -630,7 +661,7 @@ void user_event_mm_remove(struct task_struct *t)
 
        /* Remove the mm from the list, so it can no longer be enabled */
        spin_lock_irqsave(&user_event_mms_lock, flags);
-       list_del_rcu(&mm->link);
+       list_del_rcu(&mm->mms_link);
        spin_unlock_irqrestore(&user_event_mms_lock, flags);
 
        /*
@@ -670,7 +701,7 @@ void user_event_mm_remove(struct task_struct *t)
 
 void user_event_mm_dup(struct task_struct *t, struct user_event_mm *old_mm)
 {
-       struct user_event_mm *mm = user_event_mm_create(t);
+       struct user_event_mm *mm = user_event_mm_alloc(t);
        struct user_event_enabler *enabler;
 
        if (!mm)
@@ -678,16 +709,18 @@ void user_event_mm_dup(struct task_struct *t, struct user_event_mm *old_mm)
 
        rcu_read_lock();
 
-       list_for_each_entry_rcu(enabler, &old_mm->enablers, link)
+       list_for_each_entry_rcu(enabler, &old_mm->enablers, mm_enablers_link) {
                if (!user_event_enabler_dup(enabler, mm))
                        goto error;
+       }
 
        rcu_read_unlock();
 
+       user_event_mm_attach(mm, t);
        return;
 error:
        rcu_read_unlock();
-       user_event_mm_remove(t);
+       user_event_mm_destroy(mm);
 }
 
 static bool current_user_event_enabler_exists(unsigned long uaddr,
@@ -748,7 +781,7 @@ retry:
         */
        if (!*write_result) {
                refcount_inc(&enabler->event->refcnt);
-               list_add_rcu(&enabler->link, &user_mm->enablers);
+               list_add_rcu(&enabler->mm_enablers_link, &user_mm->enablers);
        }
 
        mutex_unlock(&event_mutex);
@@ -904,8 +937,8 @@ static void user_event_destroy_validators(struct user_event *user)
        struct user_event_validator *validator, *next;
        struct list_head *head = &user->validators;
 
-       list_for_each_entry_safe(validator, next, head, link) {
-               list_del(&validator->link);
+       list_for_each_entry_safe(validator, next, head, user_event_link) {
+               list_del(&validator->user_event_link);
                kfree(validator);
        }
 }
@@ -959,7 +992,7 @@ add_validator:
        validator->offset = offset;
 
        /* Want sequential access when validating */
-       list_add_tail(&validator->link, &user->validators);
+       list_add_tail(&validator->user_event_link, &user->validators);
 
 add_field:
        field->type = type;
@@ -1349,7 +1382,7 @@ static int user_event_validate(struct user_event *user, void *data, int len)
        void *pos, *end = data + len;
        u32 loc, offset, size;
 
-       list_for_each_entry(validator, head, link) {
+       list_for_each_entry(validator, head, user_event_link) {
                pos = data + validator->offset;
 
                /* Already done min_size check, no bounds check here */
@@ -2270,9 +2303,9 @@ static long user_events_ioctl_unreg(unsigned long uarg)
         */
        mutex_lock(&event_mutex);
 
-       list_for_each_entry_safe(enabler, next, &mm->enablers, link)
+       list_for_each_entry_safe(enabler, next, &mm->enablers, mm_enablers_link) {
                if (enabler->addr == reg.disable_addr &&
-                   (enabler->values & ENABLE_VAL_BIT_MASK) == reg.disable_bit) {
+                   ENABLE_BIT(enabler) == reg.disable_bit) {
                        set_bit(ENABLE_VAL_FREEING_BIT, ENABLE_BITOPS(enabler));
 
                        if (!test_bit(ENABLE_VAL_FAULTING_BIT, ENABLE_BITOPS(enabler)))
@@ -2281,6 +2314,7 @@ static long user_events_ioctl_unreg(unsigned long uarg)
                        /* Removed at least one */
                        ret = 0;
                }
+       }
 
        mutex_unlock(&event_mutex);
 
index efbbec2..e97e3fa 100644 (file)
@@ -1652,6 +1652,8 @@ static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
                        osnoise_stop_tracing();
                        notify_new_max_latency(diff);
 
+                       wake_up_process(tlat->kthread);
+
                        return HRTIMER_NORESTART;
                }
        }
index a931d9a..5295904 100644 (file)
@@ -848,6 +848,12 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        }
 
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+       /*
+        * These tests can take some time to run. Make sure on non PREEMPT
+        * kernels, we do not trigger the softlockup detector.
+        */
+       cond_resched();
+
        tracing_reset_online_cpus(&tr->array_buffer);
        set_graph_array(tr);
 
@@ -869,6 +875,8 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        if (ret)
                goto out;
 
+       cond_resched();
+
        ret = register_ftrace_graph(&fgraph_ops);
        if (ret) {
                warn_failed_init_tracer(trace, ret);
@@ -891,6 +899,8 @@ trace_selftest_startup_function_graph(struct tracer *trace,
        if (ret)
                goto out;
 
+       cond_resched();
+
        tracing_start();
 
        if (!ret && !count) {
index b7cbd66..f80d5c5 100644 (file)
@@ -12,58 +12,88 @@ enum vhost_task_flags {
        VHOST_TASK_FLAGS_STOP,
 };
 
+struct vhost_task {
+       bool (*fn)(void *data);
+       void *data;
+       struct completion exited;
+       unsigned long flags;
+       struct task_struct *task;
+};
+
 static int vhost_task_fn(void *data)
 {
        struct vhost_task *vtsk = data;
-       int ret;
+       bool dead = false;
+
+       for (;;) {
+               bool did_work;
+
+               /* mb paired w/ vhost_task_stop */
+               if (test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags))
+                       break;
+
+               if (!dead && signal_pending(current)) {
+                       struct ksignal ksig;
+                       /*
+                        * Calling get_signal will block in SIGSTOP,
+                        * or clear fatal_signal_pending, but remember
+                        * what was set.
+                        *
+                        * This thread won't actually exit until all
+                        * of the file descriptors are closed, and
+                        * the release function is called.
+                        */
+                       dead = get_signal(&ksig);
+                       if (dead)
+                               clear_thread_flag(TIF_SIGPENDING);
+               }
+
+               did_work = vtsk->fn(vtsk->data);
+               if (!did_work) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       schedule();
+               }
+       }
 
-       ret = vtsk->fn(vtsk->data);
        complete(&vtsk->exited);
-       do_exit(ret);
+       do_exit(0);
+}
+
+/**
+ * vhost_task_wake - wakeup the vhost_task
+ * @vtsk: vhost_task to wake
+ *
+ * wake up the vhost_task worker thread
+ */
+void vhost_task_wake(struct vhost_task *vtsk)
+{
+       wake_up_process(vtsk->task);
 }
+EXPORT_SYMBOL_GPL(vhost_task_wake);
 
 /**
  * vhost_task_stop - stop a vhost_task
  * @vtsk: vhost_task to stop
  *
- * Callers must call vhost_task_should_stop and return from their worker
- * function when it returns true;
+ * vhost_task_fn ensures the worker thread exits after
+ * VHOST_TASK_FLAGS_SOP becomes true.
  */
 void vhost_task_stop(struct vhost_task *vtsk)
 {
-       pid_t pid = vtsk->task->pid;
-
        set_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
-       wake_up_process(vtsk->task);
+       vhost_task_wake(vtsk);
        /*
         * Make sure vhost_task_fn is no longer accessing the vhost_task before
-        * freeing it below. If userspace crashed or exited without closing,
-        * then the vhost_task->task could already be marked dead so
-        * kernel_wait will return early.
+        * freeing it below.
         */
        wait_for_completion(&vtsk->exited);
-       /*
-        * If we are just closing/removing a device and the parent process is
-        * not exiting then reap the task.
-        */
-       kernel_wait4(pid, NULL, __WCLONE, NULL);
        kfree(vtsk);
 }
 EXPORT_SYMBOL_GPL(vhost_task_stop);
 
 /**
- * vhost_task_should_stop - should the vhost task return from the work function
- * @vtsk: vhost_task to stop
- */
-bool vhost_task_should_stop(struct vhost_task *vtsk)
-{
-       return test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
-}
-EXPORT_SYMBOL_GPL(vhost_task_should_stop);
-
-/**
- * vhost_task_create - create a copy of a process to be used by the kernel
- * @fn: thread stack
+ * vhost_task_create - create a copy of a task to be used by the kernel
+ * @fn: vhost worker function
  * @arg: data to be passed to fn
  * @name: the thread's name
  *
@@ -71,17 +101,17 @@ EXPORT_SYMBOL_GPL(vhost_task_should_stop);
  * failure. The returned task is inactive, and the caller must fire it up
  * through vhost_task_start().
  */
-struct vhost_task *vhost_task_create(int (*fn)(void *), void *arg,
+struct vhost_task *vhost_task_create(bool (*fn)(void *), void *arg,
                                     const char *name)
 {
        struct kernel_clone_args args = {
-               .flags          = CLONE_FS | CLONE_UNTRACED | CLONE_VM,
+               .flags          = CLONE_FS | CLONE_UNTRACED | CLONE_VM |
+                                 CLONE_THREAD | CLONE_SIGHAND,
                .exit_signal    = 0,
                .fn             = vhost_task_fn,
                .name           = name,
                .user_worker    = 1,
                .no_files       = 1,
-               .ignore_signals = 1,
        };
        struct vhost_task *vtsk;
        struct task_struct *tsk;
index 003edc5..984985c 100644 (file)
@@ -126,7 +126,7 @@ static const char *obj_states[ODEBUG_STATE_MAX] = {
 
 static void fill_pool(void)
 {
-       gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
+       gfp_t gfp = __GFP_HIGH | __GFP_NOWARN;
        struct debug_obj *obj;
        unsigned long flags;
 
@@ -591,10 +591,21 @@ static void debug_objects_fill_pool(void)
 {
        /*
         * On RT enabled kernels the pool refill must happen in preemptible
-        * context:
+        * context -- for !RT kernels we rely on the fact that spinlock_t and
+        * raw_spinlock_t are basically the same type and this lock-type
+        * inversion works just fine.
         */
-       if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible())
+       if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible()) {
+               /*
+                * Annotate away the spinlock_t inside raw_spinlock_t warning
+                * by temporarily raising the wait-type to WAIT_SLEEP, matching
+                * the preemptible() condition above.
+                */
+               static DEFINE_WAIT_OVERRIDE_MAP(fill_pool_map, LD_WAIT_SLEEP);
+               lock_map_acquire_try(&fill_pool_map);
                fill_pool();
+               lock_map_release(&fill_pool_map);
+       }
 }
 
 static void
index 640b951..f75ef12 100644 (file)
@@ -1083,8 +1083,28 @@ static void hci_conn_unlink(struct hci_conn *conn)
        if (!conn->parent) {
                struct hci_link *link, *t;
 
-               list_for_each_entry_safe(link, t, &conn->link_list, list)
-                       hci_conn_unlink(link->conn);
+               list_for_each_entry_safe(link, t, &conn->link_list, list) {
+                       struct hci_conn *child = link->conn;
+
+                       hci_conn_unlink(child);
+
+                       /* If hdev is down it means
+                        * hci_dev_close_sync/hci_conn_hash_flush is in progress
+                        * and links don't need to be cleanup as all connections
+                        * would be cleanup.
+                        */
+                       if (!test_bit(HCI_UP, &hdev->flags))
+                               continue;
+
+                       /* Due to race, SCO connection might be not established
+                        * yet at this point. Delete it now, otherwise it is
+                        * possible for it to be stuck and can't be deleted.
+                        */
+                       if ((child->type == SCO_LINK ||
+                            child->type == ESCO_LINK) &&
+                           child->handle == HCI_CONN_HANDLE_UNSET)
+                               hci_conn_del(child);
+               }
 
                return;
        }
@@ -1092,35 +1112,30 @@ static void hci_conn_unlink(struct hci_conn *conn)
        if (!conn->link)
                return;
 
-       hci_conn_put(conn->parent);
-       conn->parent = NULL;
-
        list_del_rcu(&conn->link->list);
        synchronize_rcu();
 
+       hci_conn_drop(conn->parent);
+       hci_conn_put(conn->parent);
+       conn->parent = NULL;
+
        kfree(conn->link);
        conn->link = NULL;
-
-       /* Due to race, SCO connection might be not established
-        * yet at this point. Delete it now, otherwise it is
-        * possible for it to be stuck and can't be deleted.
-        */
-       if (conn->handle == HCI_CONN_HANDLE_UNSET)
-               hci_conn_del(conn);
 }
 
-int hci_conn_del(struct hci_conn *conn)
+void hci_conn_del(struct hci_conn *conn)
 {
        struct hci_dev *hdev = conn->hdev;
 
        BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle);
 
+       hci_conn_unlink(conn);
+
        cancel_delayed_work_sync(&conn->disc_work);
        cancel_delayed_work_sync(&conn->auto_accept_work);
        cancel_delayed_work_sync(&conn->idle_work);
 
        if (conn->type == ACL_LINK) {
-               hci_conn_unlink(conn);
                /* Unacked frames */
                hdev->acl_cnt += conn->sent;
        } else if (conn->type == LE_LINK) {
@@ -1131,13 +1146,6 @@ int hci_conn_del(struct hci_conn *conn)
                else
                        hdev->acl_cnt += conn->sent;
        } else {
-               struct hci_conn *acl = conn->parent;
-
-               if (acl) {
-                       hci_conn_unlink(conn);
-                       hci_conn_drop(acl);
-               }
-
                /* Unacked ISO frames */
                if (conn->type == ISO_LINK) {
                        if (hdev->iso_pkts)
@@ -1160,8 +1168,6 @@ int hci_conn_del(struct hci_conn *conn)
         * rest of hci_conn_del.
         */
        hci_conn_cleanup(conn);
-
-       return 0;
 }
 
 struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
@@ -2462,22 +2468,21 @@ timer:
 /* Drop all connection on the device */
 void hci_conn_hash_flush(struct hci_dev *hdev)
 {
-       struct hci_conn_hash *h = &hdev->conn_hash;
-       struct hci_conn *c, *n;
+       struct list_head *head = &hdev->conn_hash.list;
+       struct hci_conn *conn;
 
        BT_DBG("hdev %s", hdev->name);
 
-       list_for_each_entry_safe(c, n, &h->list, list) {
-               c->state = BT_CLOSED;
-
-               hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
-
-               /* Unlink before deleting otherwise it is possible that
-                * hci_conn_del removes the link which may cause the list to
-                * contain items already freed.
-                */
-               hci_conn_unlink(c);
-               hci_conn_del(c);
+       /* We should not traverse the list here, because hci_conn_del
+        * can remove extra links, which may cause the list traversal
+        * to hit items that have already been released.
+        */
+       while ((conn = list_first_entry_or_null(head,
+                                               struct hci_conn,
+                                               list)) != NULL) {
+               conn->state = BT_CLOSED;
+               hci_disconn_cfm(conn, HCI_ERROR_LOCAL_HOST_TERM);
+               hci_conn_del(conn);
        }
 }
 
index e212e9d..a3e12a6 100644 (file)
@@ -134,6 +134,29 @@ EXPORT_SYMBOL(page_pool_ethtool_stats_get);
 #define recycle_stat_add(pool, __stat, val)
 #endif
 
+static bool page_pool_producer_lock(struct page_pool *pool)
+       __acquires(&pool->ring.producer_lock)
+{
+       bool in_softirq = in_softirq();
+
+       if (in_softirq)
+               spin_lock(&pool->ring.producer_lock);
+       else
+               spin_lock_bh(&pool->ring.producer_lock);
+
+       return in_softirq;
+}
+
+static void page_pool_producer_unlock(struct page_pool *pool,
+                                     bool in_softirq)
+       __releases(&pool->ring.producer_lock)
+{
+       if (in_softirq)
+               spin_unlock(&pool->ring.producer_lock);
+       else
+               spin_unlock_bh(&pool->ring.producer_lock);
+}
+
 static int page_pool_init(struct page_pool *pool,
                          const struct page_pool_params *params)
 {
@@ -617,6 +640,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,
                             int count)
 {
        int i, bulk_len = 0;
+       bool in_softirq;
 
        for (i = 0; i < count; i++) {
                struct page *page = virt_to_head_page(data[i]);
@@ -635,7 +659,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,
                return;
 
        /* Bulk producer into ptr_ring page_pool cache */
-       page_pool_ring_lock(pool);
+       in_softirq = page_pool_producer_lock(pool);
        for (i = 0; i < bulk_len; i++) {
                if (__ptr_ring_produce(&pool->ring, data[i])) {
                        /* ring full */
@@ -644,7 +668,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,
                }
        }
        recycle_stat_add(pool, ring, i);
-       page_pool_ring_unlock(pool);
+       page_pool_producer_unlock(pool, in_softirq);
 
        /* Hopefully all pages was return into ptr_ring */
        if (likely(i == bulk_len))
index 653901a..41de3a2 100644 (file)
@@ -2385,6 +2385,37 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
                if (tb[IFLA_BROADCAST] &&
                    nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
                        return -EINVAL;
+
+               if (tb[IFLA_GSO_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GSO_MAX_SIZE]) > dev->tso_max_size) {
+                       NL_SET_ERR_MSG(extack, "too big gso_max_size");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GSO_MAX_SEGS] &&
+                   (nla_get_u32(tb[IFLA_GSO_MAX_SEGS]) > GSO_MAX_SEGS ||
+                    nla_get_u32(tb[IFLA_GSO_MAX_SEGS]) > dev->tso_max_segs)) {
+                       NL_SET_ERR_MSG(extack, "too big gso_max_segs");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GRO_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GRO_MAX_SIZE]) > GRO_MAX_SIZE) {
+                       NL_SET_ERR_MSG(extack, "too big gro_max_size");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GSO_IPV4_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GSO_IPV4_MAX_SIZE]) > dev->tso_max_size) {
+                       NL_SET_ERR_MSG(extack, "too big gso_ipv4_max_size");
+                       return -EINVAL;
+               }
+
+               if (tb[IFLA_GRO_IPV4_MAX_SIZE] &&
+                   nla_get_u32(tb[IFLA_GRO_IPV4_MAX_SIZE]) > GRO_MAX_SIZE) {
+                       NL_SET_ERR_MSG(extack, "too big gro_ipv4_max_size");
+                       return -EINVAL;
+               }
        }
 
        if (tb[IFLA_AF_SPEC]) {
@@ -2858,11 +2889,6 @@ static int do_setlink(const struct sk_buff *skb,
        if (tb[IFLA_GSO_MAX_SIZE]) {
                u32 max_size = nla_get_u32(tb[IFLA_GSO_MAX_SIZE]);
 
-               if (max_size > dev->tso_max_size) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
                if (dev->gso_max_size ^ max_size) {
                        netif_set_gso_max_size(dev, max_size);
                        status |= DO_SETLINK_MODIFIED;
@@ -2872,11 +2898,6 @@ static int do_setlink(const struct sk_buff *skb,
        if (tb[IFLA_GSO_MAX_SEGS]) {
                u32 max_segs = nla_get_u32(tb[IFLA_GSO_MAX_SEGS]);
 
-               if (max_segs > GSO_MAX_SEGS || max_segs > dev->tso_max_segs) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
                if (dev->gso_max_segs ^ max_segs) {
                        netif_set_gso_max_segs(dev, max_segs);
                        status |= DO_SETLINK_MODIFIED;
@@ -2895,11 +2916,6 @@ static int do_setlink(const struct sk_buff *skb,
        if (tb[IFLA_GSO_IPV4_MAX_SIZE]) {
                u32 max_size = nla_get_u32(tb[IFLA_GSO_IPV4_MAX_SIZE]);
 
-               if (max_size > dev->tso_max_size) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
                if (dev->gso_ipv4_max_size ^ max_size) {
                        netif_set_gso_ipv4_max_size(dev, max_size);
                        status |= DO_SETLINK_MODIFIED;
@@ -3285,6 +3301,7 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
        struct net_device *dev;
        unsigned int num_tx_queues = 1;
        unsigned int num_rx_queues = 1;
+       int err;
 
        if (tb[IFLA_NUM_TX_QUEUES])
                num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]);
@@ -3320,13 +3337,18 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
        if (!dev)
                return ERR_PTR(-ENOMEM);
 
+       err = validate_linkmsg(dev, tb, extack);
+       if (err < 0) {
+               free_netdev(dev);
+               return ERR_PTR(err);
+       }
+
        dev_net_set(dev, net);
        dev->rtnl_link_ops = ops;
        dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
 
        if (tb[IFLA_MTU]) {
                u32 mtu = nla_get_u32(tb[IFLA_MTU]);
-               int err;
 
                err = dev_validate_mtu(dev, mtu, extack);
                if (err) {
index 515ec5c..cea28d3 100644 (file)
@@ -5224,8 +5224,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
        } else {
                skb = skb_clone(orig_skb, GFP_ATOMIC);
 
-               if (skb_orphan_frags_rx(skb, GFP_ATOMIC))
+               if (skb_orphan_frags_rx(skb, GFP_ATOMIC)) {
+                       kfree_skb(skb);
                        return;
+               }
        }
        if (!skb)
                return;
index f818837..a9060e1 100644 (file)
@@ -481,8 +481,6 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                msg_rx = sk_psock_peek_msg(psock);
        }
 out:
-       if (psock->work_state.skb && copied > 0)
-               schedule_work(&psock->work);
        return copied;
 }
 EXPORT_SYMBOL_GPL(sk_msg_recvmsg);
@@ -624,42 +622,33 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,
 
 static void sk_psock_skb_state(struct sk_psock *psock,
                               struct sk_psock_work_state *state,
-                              struct sk_buff *skb,
                               int len, int off)
 {
        spin_lock_bh(&psock->ingress_lock);
        if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
-               state->skb = skb;
                state->len = len;
                state->off = off;
-       } else {
-               sock_drop(psock->sk, skb);
        }
        spin_unlock_bh(&psock->ingress_lock);
 }
 
 static void sk_psock_backlog(struct work_struct *work)
 {
-       struct sk_psock *psock = container_of(work, struct sk_psock, work);
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct sk_psock *psock = container_of(dwork, struct sk_psock, work);
        struct sk_psock_work_state *state = &psock->work_state;
        struct sk_buff *skb = NULL;
+       u32 len = 0, off = 0;
        bool ingress;
-       u32 len, off;
        int ret;
 
        mutex_lock(&psock->work_mutex);
-       if (unlikely(state->skb)) {
-               spin_lock_bh(&psock->ingress_lock);
-               skb = state->skb;
+       if (unlikely(state->len)) {
                len = state->len;
                off = state->off;
-               state->skb = NULL;
-               spin_unlock_bh(&psock->ingress_lock);
        }
-       if (skb)
-               goto start;
 
-       while ((skb = skb_dequeue(&psock->ingress_skb))) {
+       while ((skb = skb_peek(&psock->ingress_skb))) {
                len = skb->len;
                off = 0;
                if (skb_bpf_strparser(skb)) {
@@ -668,7 +657,6 @@ static void sk_psock_backlog(struct work_struct *work)
                        off = stm->offset;
                        len = stm->full_len;
                }
-start:
                ingress = skb_bpf_ingress(skb);
                skb_bpf_redirect_clear(skb);
                do {
@@ -678,22 +666,28 @@ start:
                                                          len, ingress);
                        if (ret <= 0) {
                                if (ret == -EAGAIN) {
-                                       sk_psock_skb_state(psock, state, skb,
-                                                          len, off);
+                                       sk_psock_skb_state(psock, state, len, off);
+
+                                       /* Delay slightly to prioritize any
+                                        * other work that might be here.
+                                        */
+                                       if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
+                                               schedule_delayed_work(&psock->work, 1);
                                        goto end;
                                }
                                /* Hard errors break pipe and stop xmit. */
                                sk_psock_report_error(psock, ret ? -ret : EPIPE);
                                sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
-                               sock_drop(psock->sk, skb);
                                goto end;
                        }
                        off += ret;
                        len -= ret;
                } while (len);
 
-               if (!ingress)
+               skb = skb_dequeue(&psock->ingress_skb);
+               if (!ingress) {
                        kfree_skb(skb);
+               }
        }
 end:
        mutex_unlock(&psock->work_mutex);
@@ -734,7 +728,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
        INIT_LIST_HEAD(&psock->link);
        spin_lock_init(&psock->link_lock);
 
-       INIT_WORK(&psock->work, sk_psock_backlog);
+       INIT_DELAYED_WORK(&psock->work, sk_psock_backlog);
        mutex_init(&psock->work_mutex);
        INIT_LIST_HEAD(&psock->ingress_msg);
        spin_lock_init(&psock->ingress_lock);
@@ -786,11 +780,6 @@ static void __sk_psock_zap_ingress(struct sk_psock *psock)
                skb_bpf_redirect_clear(skb);
                sock_drop(psock->sk, skb);
        }
-       kfree_skb(psock->work_state.skb);
-       /* We null the skb here to ensure that calls to sk_psock_backlog
-        * do not pick up the free'd skb.
-        */
-       psock->work_state.skb = NULL;
        __sk_psock_purge_ingress_msg(psock);
 }
 
@@ -809,7 +798,6 @@ void sk_psock_stop(struct sk_psock *psock)
        spin_lock_bh(&psock->ingress_lock);
        sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
        sk_psock_cork_free(psock);
-       __sk_psock_zap_ingress(psock);
        spin_unlock_bh(&psock->ingress_lock);
 }
 
@@ -823,7 +811,8 @@ static void sk_psock_destroy(struct work_struct *work)
 
        sk_psock_done_strp(psock);
 
-       cancel_work_sync(&psock->work);
+       cancel_delayed_work_sync(&psock->work);
+       __sk_psock_zap_ingress(psock);
        mutex_destroy(&psock->work_mutex);
 
        psock_progs_drop(&psock->progs);
@@ -938,7 +927,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb)
        }
 
        skb_queue_tail(&psock_other->ingress_skb, skb);
-       schedule_work(&psock_other->work);
+       schedule_delayed_work(&psock_other->work, 0);
        spin_unlock_bh(&psock_other->ingress_lock);
        return 0;
 }
@@ -990,10 +979,8 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
                err = -EIO;
                sk_other = psock->sk;
                if (sock_flag(sk_other, SOCK_DEAD) ||
-                   !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
-                       skb_bpf_redirect_clear(skb);
+                   !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
                        goto out_free;
-               }
 
                skb_bpf_set_ingress(skb);
 
@@ -1018,22 +1005,23 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
                        spin_lock_bh(&psock->ingress_lock);
                        if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
                                skb_queue_tail(&psock->ingress_skb, skb);
-                               schedule_work(&psock->work);
+                               schedule_delayed_work(&psock->work, 0);
                                err = 0;
                        }
                        spin_unlock_bh(&psock->ingress_lock);
-                       if (err < 0) {
-                               skb_bpf_redirect_clear(skb);
+                       if (err < 0)
                                goto out_free;
-                       }
                }
                break;
        case __SK_REDIRECT:
+               tcp_eat_skb(psock->sk, skb);
                err = sk_psock_skb_redirect(psock, skb);
                break;
        case __SK_DROP:
        default:
 out_free:
+               skb_bpf_redirect_clear(skb);
+               tcp_eat_skb(psock->sk, skb);
                sock_drop(psock->sk, skb);
        }
 
@@ -1049,7 +1037,7 @@ static void sk_psock_write_space(struct sock *sk)
        psock = sk_psock(sk);
        if (likely(psock)) {
                if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
-                       schedule_work(&psock->work);
+                       schedule_delayed_work(&psock->work, 0);
                write_space = psock->saved_write_space;
        }
        rcu_read_unlock();
@@ -1078,8 +1066,7 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
                skb_dst_drop(skb);
                skb_bpf_redirect_clear(skb);
                ret = bpf_prog_run_pin_on_cpu(prog, skb);
-               if (ret == SK_PASS)
-                       skb_bpf_set_strparser(skb);
+               skb_bpf_set_strparser(skb);
                ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
                skb->sk = NULL;
        }
@@ -1183,12 +1170,11 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)
        int ret = __SK_DROP;
        int len = skb->len;
 
-       skb_get(skb);
-
        rcu_read_lock();
        psock = sk_psock(sk);
        if (unlikely(!psock)) {
                len = 0;
+               tcp_eat_skb(sk, skb);
                sock_drop(sk, skb);
                goto out;
        }
@@ -1212,12 +1198,21 @@ out:
 static void sk_psock_verdict_data_ready(struct sock *sk)
 {
        struct socket *sock = sk->sk_socket;
+       int copied;
 
        trace_sk_data_ready(sk);
 
        if (unlikely(!sock || !sock->ops || !sock->ops->read_skb))
                return;
-       sock->ops->read_skb(sk, sk_psock_verdict_recv);
+       copied = sock->ops->read_skb(sk, sk_psock_verdict_recv);
+       if (copied >= 0) {
+               struct sk_psock *psock;
+
+               rcu_read_lock();
+               psock = sk_psock(sk);
+               psock->saved_data_ready(sk);
+               rcu_read_unlock();
+       }
 }
 
 void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)
index 5440e67..24f2761 100644 (file)
@@ -2381,7 +2381,6 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 {
        u32 max_segs = 1;
 
-       sk_dst_set(sk, dst);
        sk->sk_route_caps = dst->dev->features;
        if (sk_is_tcp(sk))
                sk->sk_route_caps |= NETIF_F_GSO;
@@ -2400,6 +2399,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
                }
        }
        sk->sk_gso_max_segs = max_segs;
+       sk_dst_set(sk, dst);
 }
 EXPORT_SYMBOL_GPL(sk_setup_caps);
 
index 7c189c2..00afb66 100644 (file)
@@ -1644,9 +1644,10 @@ void sock_map_close(struct sock *sk, long timeout)
                rcu_read_unlock();
                sk_psock_stop(psock);
                release_sock(sk);
-               cancel_work_sync(&psock->work);
+               cancel_delayed_work_sync(&psock->work);
                sk_psock_put(sk, psock);
        }
+
        /* Make sure we do not recurse. This is a bug.
         * Leak the socket instead of crashing on a stack overflow.
         */
index e6adc5d..6d37bab 100644 (file)
@@ -102,7 +102,7 @@ struct handshake_req_alloc_test_param handshake_req_alloc_params[] = {
        {
                .desc                   = "handshake_req_alloc excessive privsize",
                .proto                  = &handshake_req_alloc_proto_6,
-               .gfp                    = GFP_KERNEL,
+               .gfp                    = GFP_KERNEL | __GFP_NOWARN,
                .expect_success         = false,
        },
        {
@@ -209,6 +209,7 @@ static void handshake_req_submit_test4(struct kunit *test)
 {
        struct handshake_req *req, *result;
        struct socket *sock;
+       struct file *filp;
        int err;
 
        /* Arrange */
@@ -218,9 +219,10 @@ static void handshake_req_submit_test4(struct kunit *test)
        err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
        KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -241,6 +243,7 @@ static void handshake_req_submit_test5(struct kunit *test)
        struct handshake_req *req;
        struct handshake_net *hn;
        struct socket *sock;
+       struct file *filp;
        struct net *net;
        int saved, err;
 
@@ -251,9 +254,10 @@ static void handshake_req_submit_test5(struct kunit *test)
        err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
        KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+       sock->file = filp;
 
        net = sock_net(sock->sk);
        hn = handshake_pernet(net);
@@ -276,6 +280,7 @@ static void handshake_req_submit_test6(struct kunit *test)
 {
        struct handshake_req *req1, *req2;
        struct socket *sock;
+       struct file *filp;
        int err;
 
        /* Arrange */
@@ -287,9 +292,10 @@ static void handshake_req_submit_test6(struct kunit *test)
        err = __sock_create(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP,
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
        KUNIT_ASSERT_NOT_NULL(test, sock->sk);
+       sock->file = filp;
 
        /* Act */
        err = handshake_req_submit(sock, req1, GFP_KERNEL);
@@ -307,6 +313,7 @@ static void handshake_req_cancel_test1(struct kunit *test)
 {
        struct handshake_req *req;
        struct socket *sock;
+       struct file *filp;
        bool result;
        int err;
 
@@ -318,8 +325,9 @@ static void handshake_req_cancel_test1(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -340,6 +348,7 @@ static void handshake_req_cancel_test2(struct kunit *test)
        struct handshake_req *req, *next;
        struct handshake_net *hn;
        struct socket *sock;
+       struct file *filp;
        struct net *net;
        bool result;
        int err;
@@ -352,8 +361,9 @@ static void handshake_req_cancel_test2(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -380,6 +390,7 @@ static void handshake_req_cancel_test3(struct kunit *test)
        struct handshake_req *req, *next;
        struct handshake_net *hn;
        struct socket *sock;
+       struct file *filp;
        struct net *net;
        bool result;
        int err;
@@ -392,8 +403,9 @@ static void handshake_req_cancel_test3(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
@@ -436,6 +448,7 @@ static void handshake_req_destroy_test1(struct kunit *test)
 {
        struct handshake_req *req;
        struct socket *sock;
+       struct file *filp;
        int err;
 
        /* Arrange */
@@ -448,8 +461,9 @@ static void handshake_req_destroy_test1(struct kunit *test)
                            &sock, 1);
        KUNIT_ASSERT_EQ(test, err, 0);
 
-       sock->file = sock_alloc_file(sock, O_NONBLOCK, NULL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sock->file);
+       filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filp);
+       sock->file = filp;
 
        err = handshake_req_submit(sock, req, GFP_KERNEL);
        KUNIT_ASSERT_EQ(test, err, 0);
index 4dac965..8aeaadc 100644 (file)
@@ -31,6 +31,7 @@ struct handshake_req {
        struct list_head                hr_list;
        struct rhash_head               hr_rhash;
        unsigned long                   hr_flags;
+       struct file                     *hr_file;
        const struct handshake_proto    *hr_proto;
        struct sock                     *hr_sk;
        void                            (*hr_odestruct)(struct sock *sk);
index 35c9c44..1086653 100644 (file)
@@ -48,7 +48,7 @@ int handshake_genl_notify(struct net *net, const struct handshake_proto *proto,
                                proto->hp_handler_class))
                return -ESRCH;
 
-       msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, flags);
        if (!msg)
                return -ENOMEM;
 
@@ -99,9 +99,6 @@ static int handshake_dup(struct socket *sock)
        struct file *file;
        int newfd;
 
-       if (!sock->file)
-               return -EBADF;
-
        file = get_file(sock->file);
        newfd = get_unused_fd_flags(O_CLOEXEC);
        if (newfd < 0) {
@@ -142,15 +139,16 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
                goto out_complete;
        }
        err = req->hr_proto->hp_accept(req, info, fd);
-       if (err)
+       if (err) {
+               fput(sock->file);
                goto out_complete;
+       }
 
        trace_handshake_cmd_accept(net, req, req->hr_sk, fd);
        return 0;
 
 out_complete:
        handshake_complete(req, -EIO, NULL);
-       fput(sock->file);
 out_status:
        trace_handshake_cmd_accept_err(net, req, NULL, err);
        return err;
@@ -159,8 +157,8 @@ out_status:
 int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info)
 {
        struct net *net = sock_net(skb->sk);
+       struct handshake_req *req = NULL;
        struct socket *sock = NULL;
-       struct handshake_req *req;
        int fd, status, err;
 
        if (GENL_REQ_ATTR_CHECK(info, HANDSHAKE_A_DONE_SOCKFD))
index 94d5cef..d78d41a 100644 (file)
@@ -239,6 +239,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
        }
        req->hr_odestruct = req->hr_sk->sk_destruct;
        req->hr_sk->sk_destruct = handshake_sk_destruct;
+       req->hr_file = sock->file;
 
        ret = -EOPNOTSUPP;
        net = sock_net(req->hr_sk);
@@ -334,6 +335,9 @@ bool handshake_req_cancel(struct sock *sk)
                return false;
        }
 
+       /* Request accepted and waiting for DONE */
+       fput(req->hr_file);
+
 out_true:
        trace_handshake_cancel(net, req, sk);
 
index fcbeb63..b735f5c 100644 (file)
@@ -31,6 +31,7 @@ struct tls_handshake_req {
        int                     th_type;
        unsigned int            th_timeout_ms;
        int                     th_auth_mode;
+       const char              *th_peername;
        key_serial_t            th_keyring;
        key_serial_t            th_certificate;
        key_serial_t            th_privkey;
@@ -48,6 +49,7 @@ tls_handshake_req_init(struct handshake_req *req,
        treq->th_timeout_ms = args->ta_timeout_ms;
        treq->th_consumer_done = args->ta_done;
        treq->th_consumer_data = args->ta_data;
+       treq->th_peername = args->ta_peername;
        treq->th_keyring = args->ta_keyring;
        treq->th_num_peerids = 0;
        treq->th_certificate = TLS_NO_CERT;
@@ -214,6 +216,12 @@ static int tls_handshake_accept(struct handshake_req *req,
        ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_MESSAGE_TYPE, treq->th_type);
        if (ret < 0)
                goto out_cancel;
+       if (treq->th_peername) {
+               ret = nla_put_string(msg, HANDSHAKE_A_ACCEPT_PEERNAME,
+                                    treq->th_peername);
+               if (ret < 0)
+                       goto out_cancel;
+       }
        if (treq->th_timeout_ms) {
                ret = nla_put_u32(msg, HANDSHAKE_A_ACCEPT_TIMEOUT, treq->th_timeout_ms);
                if (ret < 0)
index c4aab3a..4a76ebf 100644 (file)
@@ -586,6 +586,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)
 
        add_wait_queue(sk_sleep(sk), &wait);
        sk->sk_write_pending += writebias;
+       sk->sk_wait_pending++;
 
        /* Basic assumption: if someone sets sk->sk_err, he _must_
         * change state of the socket from TCP_SYN_*.
@@ -601,6 +602,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)
        }
        remove_wait_queue(sk_sleep(sk), &wait);
        sk->sk_write_pending -= writebias;
+       sk->sk_wait_pending--;
        return timeo;
 }
 
index 65ad425..1386787 100644 (file)
@@ -1142,6 +1142,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
        if (newsk) {
                struct inet_connection_sock *newicsk = inet_csk(newsk);
 
+               newsk->sk_wait_pending = 0;
                inet_sk_set_state(newsk, TCP_SYN_RECV);
                newicsk->icsk_bind_hash = NULL;
                newicsk->icsk_bind2_hash = NULL;
index b511ff0..8e97d8d 100644 (file)
@@ -317,7 +317,14 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
                        ipc->tos = val;
                        ipc->priority = rt_tos2priority(ipc->tos);
                        break;
-
+               case IP_PROTOCOL:
+                       if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
+                               return -EINVAL;
+                       val = *(int *)CMSG_DATA(cmsg);
+                       if (val < 1 || val > 255)
+                               return -EINVAL;
+                       ipc->protocol = val;
+                       break;
                default:
                        return -EINVAL;
                }
@@ -1761,6 +1768,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
        case IP_LOCAL_PORT_RANGE:
                val = inet->local_port_range.hi << 16 | inet->local_port_range.lo;
                break;
+       case IP_PROTOCOL:
+               val = inet_sk(sk)->inet_num;
+               break;
        default:
                sockopt_release_sock(sk);
                return -ENOPROTOOPT;
index ff712bf..eadf1c9 100644 (file)
@@ -532,6 +532,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        }
 
        ipcm_init_sk(&ipc, inet);
+       /* Keep backward compat */
+       if (hdrincl)
+               ipc.protocol = IPPROTO_RAW;
 
        if (msg->msg_controllen) {
                err = ip_cmsg_send(sk, msg, &ipc, false);
@@ -599,7 +602,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos,
                           RT_SCOPE_UNIVERSE,
-                          hdrincl ? IPPROTO_RAW : sk->sk_protocol,
+                          hdrincl ? ipc.protocol : sk->sk_protocol,
                           inet_sk_flowi_flags(sk) |
                            (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0, sk->sk_uid);
index 4d6392c..8d20d92 100644 (file)
@@ -1571,7 +1571,7 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len)
  * calculation of whether or not we must ACK for the sake of
  * a window update.
  */
-static void __tcp_cleanup_rbuf(struct sock *sk, int copied)
+void __tcp_cleanup_rbuf(struct sock *sk, int copied)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        bool time_to_ack = false;
@@ -1773,7 +1773,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
                tcp_flags = TCP_SKB_CB(skb)->tcp_flags;
                used = recv_actor(sk, skb);
-               consume_skb(skb);
                if (used < 0) {
                        if (!copied)
                                copied = used;
@@ -1787,14 +1786,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                        break;
                }
        }
-       WRITE_ONCE(tp->copied_seq, seq);
-
-       tcp_rcv_space_adjust(sk);
-
-       /* Clean up data we have read: This will do ACK frames. */
-       if (copied > 0)
-               __tcp_cleanup_rbuf(sk, copied);
-
        return copied;
 }
 EXPORT_SYMBOL(tcp_read_skb);
@@ -3090,6 +3081,12 @@ int tcp_disconnect(struct sock *sk, int flags)
        int old_state = sk->sk_state;
        u32 seq;
 
+       /* Deny disconnect if other threads are blocked in sk_wait_event()
+        * or inet_wait_for_connect().
+        */
+       if (sk->sk_wait_pending)
+               return -EBUSY;
+
        if (old_state != TCP_CLOSE)
                tcp_set_state(sk, TCP_CLOSE);
 
@@ -4081,7 +4078,8 @@ int do_tcp_getsockopt(struct sock *sk, int level,
        switch (optname) {
        case TCP_MAXSEG:
                val = tp->mss_cache;
-               if (!val && ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
+               if (tp->rx_opt.user_mss &&
+                   ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))
                        val = tp->rx_opt.user_mss;
                if (tp->repair)
                        val = tp->rx_opt.mss_clamp;
index 2e95474..5f93918 100644 (file)
 #include <net/inet_common.h>
 #include <net/tls.h>
 
+void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
+{
+       struct tcp_sock *tcp;
+       int copied;
+
+       if (!skb || !skb->len || !sk_is_tcp(sk))
+               return;
+
+       if (skb_bpf_strparser(skb))
+               return;
+
+       tcp = tcp_sk(sk);
+       copied = tcp->copied_seq + skb->len;
+       WRITE_ONCE(tcp->copied_seq, copied);
+       tcp_rcv_space_adjust(sk);
+       __tcp_cleanup_rbuf(sk, skb->len);
+}
+
 static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
                           struct sk_msg *msg, u32 apply_bytes, int flags)
 {
@@ -174,14 +192,34 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
        return ret;
 }
 
+static bool is_next_msg_fin(struct sk_psock *psock)
+{
+       struct scatterlist *sge;
+       struct sk_msg *msg_rx;
+       int i;
+
+       msg_rx = sk_psock_peek_msg(psock);
+       i = msg_rx->sg.start;
+       sge = sk_msg_elem(msg_rx, i);
+       if (!sge->length) {
+               struct sk_buff *skb = msg_rx->skb;
+
+               if (skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+                       return true;
+       }
+       return false;
+}
+
 static int tcp_bpf_recvmsg_parser(struct sock *sk,
                                  struct msghdr *msg,
                                  size_t len,
                                  int flags,
                                  int *addr_len)
 {
+       struct tcp_sock *tcp = tcp_sk(sk);
+       u32 seq = tcp->copied_seq;
        struct sk_psock *psock;
-       int copied;
+       int copied = 0;
 
        if (unlikely(flags & MSG_ERRQUEUE))
                return inet_recv_error(sk, msg, len, addr_len);
@@ -194,8 +232,43 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
                return tcp_recvmsg(sk, msg, len, flags, addr_len);
 
        lock_sock(sk);
+
+       /* We may have received data on the sk_receive_queue pre-accept and
+        * then we can not use read_skb in this context because we haven't
+        * assigned a sk_socket yet so have no link to the ops. The work-around
+        * is to check the sk_receive_queue and in these cases read skbs off
+        * queue again. The read_skb hook is not running at this point because
+        * of lock_sock so we avoid having multiple runners in read_skb.
+        */
+       if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) {
+               tcp_data_ready(sk);
+               /* This handles the ENOMEM errors if we both receive data
+                * pre accept and are already under memory pressure. At least
+                * let user know to retry.
+                */
+               if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) {
+                       copied = -EAGAIN;
+                       goto out;
+               }
+       }
+
 msg_bytes_ready:
        copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
+       /* The typical case for EFAULT is the socket was gracefully
+        * shutdown with a FIN pkt. So check here the other case is
+        * some error on copy_page_to_iter which would be unexpected.
+        * On fin return correct return code to zero.
+        */
+       if (copied == -EFAULT) {
+               bool is_fin = is_next_msg_fin(psock);
+
+               if (is_fin) {
+                       copied = 0;
+                       seq++;
+                       goto out;
+               }
+       }
+       seq += copied;
        if (!copied) {
                long timeo;
                int data;
@@ -233,6 +306,10 @@ msg_bytes_ready:
                copied = -EAGAIN;
        }
 out:
+       WRITE_ONCE(tcp->copied_seq, seq);
+       tcp_rcv_space_adjust(sk);
+       if (copied > 0)
+               __tcp_cleanup_rbuf(sk, copied);
        release_sock(sk);
        sk_psock_put(sk, psock);
        return copied;
index 61b6710..bf8b222 100644 (file)
@@ -4530,7 +4530,7 @@ static void tcp_sack_maybe_coalesce(struct tcp_sock *tp)
        }
 }
 
-static void tcp_sack_compress_send_ack(struct sock *sk)
+void tcp_sack_compress_send_ack(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
index b839c2f..39eb947 100644 (file)
@@ -290,9 +290,19 @@ static int tcp_write_timeout(struct sock *sk)
 void tcp_delack_timer_handler(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
+       struct tcp_sock *tp = tcp_sk(sk);
 
-       if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
-           !(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
+       if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))
+               return;
+
+       /* Handling the sack compression case */
+       if (tp->compressed_ack) {
+               tcp_mstamp_refresh(tp);
+               tcp_sack_compress_send_ack(sk);
+               return;
+       }
+
+       if (!(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
                return;
 
        if (time_after(icsk->icsk_ack.timeout, jiffies)) {
@@ -312,7 +322,7 @@ void tcp_delack_timer_handler(struct sock *sk)
                        inet_csk_exit_pingpong_mode(sk);
                        icsk->icsk_ack.ato      = TCP_ATO_MIN;
                }
-               tcp_mstamp_refresh(tcp_sk(sk));
+               tcp_mstamp_refresh(tp);
                tcp_send_ack(sk);
                __NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS);
        }
index aa32afd..9482def 100644 (file)
@@ -1818,7 +1818,7 @@ EXPORT_SYMBOL(__skb_recv_udp);
 int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
 {
        struct sk_buff *skb;
-       int err, copied;
+       int err;
 
 try_again:
        skb = skb_recv_udp(sk, MSG_DONTWAIT, &err);
@@ -1837,10 +1837,7 @@ try_again:
        }
 
        WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
-       copied = recv_actor(sk, skb);
-       kfree_skb(skb);
-
-       return copied;
+       return recv_actor(sk, skb);
 }
 EXPORT_SYMBOL(udp_read_skb);
 
index e0c9cc3..56d94d2 100644 (file)
@@ -64,6 +64,8 @@ struct proto  udplite_prot = {
        .per_cpu_fw_alloc  = &udp_memory_per_cpu_fw_alloc,
 
        .sysctl_mem        = sysctl_udp_mem,
+       .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
+       .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
        .obj_size          = sizeof(struct udp_sock),
        .h.udp_table       = &udplite_table,
 };
index da46c42..49e31e4 100644 (file)
@@ -143,6 +143,8 @@ int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type)
                        optlen = 1;
                        break;
                default:
+                       if (len < 2)
+                               goto bad;
                        optlen = nh[offset + 1] + 2;
                        if (optlen > len)
                                goto bad;
index 7d0adb6..44ee7a2 100644 (file)
@@ -793,7 +793,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
                if (!proto)
                        proto = inet->inet_num;
-               else if (proto != inet->inet_num)
+               else if (proto != inet->inet_num &&
+                        inet->inet_num != IPPROTO_RAW)
                        return -EINVAL;
 
                if (proto > 255)
index 67eaf3c..3bab0cc 100644 (file)
@@ -60,6 +60,8 @@ struct proto udplitev6_prot = {
        .per_cpu_fw_alloc  = &udp_memory_per_cpu_fw_alloc,
 
        .sysctl_mem        = sysctl_udp_mem,
+       .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
+       .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
        .obj_size          = sizeof(struct udp6_sock),
        .h.udp_table       = &udplite_table,
 };
index 08dc53f..67311e7 100644 (file)
@@ -90,8 +90,8 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
        if (err)
                return err;
 
-       msk->first = ssock->sk;
-       msk->subflow = ssock;
+       WRITE_ONCE(msk->first, ssock->sk);
+       WRITE_ONCE(msk->subflow, ssock);
        subflow = mptcp_subflow_ctx(ssock->sk);
        list_add(&subflow->node, &msk->conn_list);
        sock_hold(ssock->sk);
@@ -603,7 +603,7 @@ static bool mptcp_check_data_fin(struct sock *sk)
                WRITE_ONCE(msk->ack_seq, msk->ack_seq + 1);
                WRITE_ONCE(msk->rcv_data_fin, 0);
 
-               sk->sk_shutdown |= RCV_SHUTDOWN;
+               WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
                smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
 
                switch (sk->sk_state) {
@@ -825,6 +825,13 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
        mptcp_data_unlock(sk);
 }
 
+static void mptcp_subflow_joined(struct mptcp_sock *msk, struct sock *ssk)
+{
+       mptcp_subflow_ctx(ssk)->map_seq = READ_ONCE(msk->ack_seq);
+       WRITE_ONCE(msk->allow_infinite_fallback, false);
+       mptcp_event(MPTCP_EVENT_SUB_ESTABLISHED, msk, ssk, GFP_ATOMIC);
+}
+
 static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
 {
        struct sock *sk = (struct sock *)msk;
@@ -839,6 +846,7 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
                mptcp_sock_graft(ssk, sk->sk_socket);
 
        mptcp_sockopt_sync_locked(msk, ssk);
+       mptcp_subflow_joined(msk, ssk);
        return true;
 }
 
@@ -910,7 +918,7 @@ static void mptcp_check_for_eof(struct mptcp_sock *msk)
                /* hopefully temporary hack: propagate shutdown status
                 * to msk, when all subflows agree on it
                 */
-               sk->sk_shutdown |= RCV_SHUTDOWN;
+               WRITE_ONCE(sk->sk_shutdown, sk->sk_shutdown | RCV_SHUTDOWN);
 
                smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
                sk->sk_data_ready(sk);
@@ -1702,7 +1710,6 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 
        lock_sock(ssk);
        msg->msg_flags |= MSG_DONTWAIT;
-       msk->connect_flags = O_NONBLOCK;
        msk->fastopening = 1;
        ret = tcp_sendmsg_fastopen(ssk, msg, copied_syn, len, NULL);
        msk->fastopening = 0;
@@ -2283,7 +2290,7 @@ static void mptcp_dispose_initial_subflow(struct mptcp_sock *msk)
 {
        if (msk->subflow) {
                iput(SOCK_INODE(msk->subflow));
-               msk->subflow = NULL;
+               WRITE_ONCE(msk->subflow, NULL);
        }
 }
 
@@ -2420,7 +2427,7 @@ out_release:
        sock_put(ssk);
 
        if (ssk == msk->first)
-               msk->first = NULL;
+               WRITE_ONCE(msk->first, NULL);
 
 out:
        if (ssk == msk->last_snd)
@@ -2527,7 +2534,7 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)
        }
 
        inet_sk_state_store(sk, TCP_CLOSE);
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
        smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
        set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags);
 
@@ -2721,7 +2728,7 @@ static int __mptcp_init_sock(struct sock *sk)
        WRITE_ONCE(msk->rmem_released, 0);
        msk->timer_ival = TCP_RTO_MIN;
 
-       msk->first = NULL;
+       WRITE_ONCE(msk->first, NULL);
        inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
        WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk)));
        WRITE_ONCE(msk->allow_infinite_fallback, true);
@@ -2959,7 +2966,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
        bool do_cancel_work = false;
        int subflows_alive = 0;
 
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       WRITE_ONCE(sk->sk_shutdown, SHUTDOWN_MASK);
 
        if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) {
                mptcp_listen_inuse_dec(sk);
@@ -3039,7 +3046,7 @@ static void mptcp_close(struct sock *sk, long timeout)
        sock_put(sk);
 }
 
-void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
+static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
 {
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
        const struct ipv6_pinfo *ssk6 = inet6_sk(ssk);
@@ -3102,7 +3109,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
        mptcp_pm_data_reset(msk);
        mptcp_ca_reset(sk);
 
-       sk->sk_shutdown = 0;
+       WRITE_ONCE(sk->sk_shutdown, 0);
        sk_error_report(sk);
        return 0;
 }
@@ -3116,9 +3123,10 @@ static struct ipv6_pinfo *mptcp_inet6_sk(const struct sock *sk)
 }
 #endif
 
-struct sock *mptcp_sk_clone(const struct sock *sk,
-                           const struct mptcp_options_received *mp_opt,
-                           struct request_sock *req)
+struct sock *mptcp_sk_clone_init(const struct sock *sk,
+                                const struct mptcp_options_received *mp_opt,
+                                struct sock *ssk,
+                                struct request_sock *req)
 {
        struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
        struct sock *nsk = sk_clone_lock(sk, GFP_ATOMIC);
@@ -3137,7 +3145,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
        msk = mptcp_sk(nsk);
        msk->local_key = subflow_req->local_key;
        msk->token = subflow_req->token;
-       msk->subflow = NULL;
+       WRITE_ONCE(msk->subflow, NULL);
        msk->in_accept_queue = 1;
        WRITE_ONCE(msk->fully_established, false);
        if (mp_opt->suboptions & OPTION_MPTCP_CSUMREQD)
@@ -3150,10 +3158,30 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
        msk->setsockopt_seq = mptcp_sk(sk)->setsockopt_seq;
 
        sock_reset_flag(nsk, SOCK_RCU_FREE);
-       /* will be fully established after successful MPC subflow creation */
-       inet_sk_state_store(nsk, TCP_SYN_RECV);
-
        security_inet_csk_clone(nsk, req);
+
+       /* this can't race with mptcp_close(), as the msk is
+        * not yet exposted to user-space
+        */
+       inet_sk_state_store(nsk, TCP_ESTABLISHED);
+
+       /* The msk maintain a ref to each subflow in the connections list */
+       WRITE_ONCE(msk->first, ssk);
+       list_add(&mptcp_subflow_ctx(ssk)->node, &msk->conn_list);
+       sock_hold(ssk);
+
+       /* new mpc subflow takes ownership of the newly
+        * created mptcp socket
+        */
+       mptcp_token_accept(subflow_req, msk);
+
+       /* set msk addresses early to ensure mptcp_pm_get_local_id()
+        * uses the correct data
+        */
+       mptcp_copy_inaddrs(nsk, ssk);
+       mptcp_propagate_sndbuf(nsk, ssk);
+
+       mptcp_rcv_space_init(msk, ssk);
        bh_unlock_sock(nsk);
 
        /* note: the newly allocated socket refcount is 2 now */
@@ -3185,7 +3213,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
        struct socket *listener;
        struct sock *newsk;
 
-       listener = msk->subflow;
+       listener = READ_ONCE(msk->subflow);
        if (WARN_ON_ONCE(!listener)) {
                *err = -EINVAL;
                return NULL;
@@ -3465,14 +3493,16 @@ bool mptcp_finish_join(struct sock *ssk)
                return false;
        }
 
-       if (!list_empty(&subflow->node))
-               goto out;
+       /* active subflow, already present inside the conn_list */
+       if (!list_empty(&subflow->node)) {
+               mptcp_subflow_joined(msk, ssk);
+               return true;
+       }
 
        if (!mptcp_pm_allow_new_subflow(msk))
                goto err_prohibited;
 
-       /* active connections are already on conn_list.
-        * If we can't acquire msk socket lock here, let the release callback
+       /* If we can't acquire msk socket lock here, let the release callback
         * handle it
         */
        mptcp_data_lock(parent);
@@ -3495,11 +3525,6 @@ err_prohibited:
                return false;
        }
 
-       subflow->map_seq = READ_ONCE(msk->ack_seq);
-       WRITE_ONCE(msk->allow_infinite_fallback, false);
-
-out:
-       mptcp_event(MPTCP_EVENT_SUB_ESTABLISHED, msk, ssk, GFP_ATOMIC);
        return true;
 }
 
@@ -3617,9 +3642,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
         * acquired the subflow socket lock, too.
         */
        if (msk->fastopening)
-               err = __inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags, 1);
+               err = __inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK, 1);
        else
-               err = inet_stream_connect(ssock, uaddr, addr_len, msk->connect_flags);
+               err = inet_stream_connect(ssock, uaddr, addr_len, O_NONBLOCK);
        inet_sk(sk)->defer_connect = inet_sk(ssock->sk)->defer_connect;
 
        /* on successful connect, the msk state will be moved to established by
@@ -3632,12 +3657,10 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 
        mptcp_copy_inaddrs(sk, ssock->sk);
 
-       /* unblocking connect, mptcp-level inet_stream_connect will error out
-        * without changing the socket state, update it here.
+       /* silence EINPROGRESS and let the caller inet_stream_connect
+        * handle the connection in progress
         */
-       if (err == -EINPROGRESS)
-               sk->sk_socket->state = ssock->state;
-       return err;
+       return 0;
 }
 
 static struct proto mptcp_prot = {
@@ -3696,18 +3719,6 @@ unlock:
        return err;
 }
 
-static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
-                               int addr_len, int flags)
-{
-       int ret;
-
-       lock_sock(sock->sk);
-       mptcp_sk(sock->sk)->connect_flags = flags;
-       ret = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
-       release_sock(sock->sk);
-       return ret;
-}
-
 static int mptcp_listen(struct socket *sock, int backlog)
 {
        struct mptcp_sock *msk = mptcp_sk(sock->sk);
@@ -3751,10 +3762,10 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
 
        pr_debug("msk=%p", msk);
 
-       /* buggy applications can call accept on socket states other then LISTEN
+       /* Buggy applications can call accept on socket states other then LISTEN
         * but no need to allocate the first subflow just to error out.
         */
-       ssock = msk->subflow;
+       ssock = READ_ONCE(msk->subflow);
        if (!ssock)
                return -EINVAL;
 
@@ -3800,9 +3811,6 @@ static __poll_t mptcp_check_writeable(struct mptcp_sock *msk)
 {
        struct sock *sk = (struct sock *)msk;
 
-       if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN))
-               return EPOLLOUT | EPOLLWRNORM;
-
        if (sk_stream_is_writeable(sk))
                return EPOLLOUT | EPOLLWRNORM;
 
@@ -3820,6 +3828,7 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk;
        struct mptcp_sock *msk;
        __poll_t mask = 0;
+       u8 shutdown;
        int state;
 
        msk = mptcp_sk(sk);
@@ -3828,23 +3837,30 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
        state = inet_sk_state_load(sk);
        pr_debug("msk=%p state=%d flags=%lx", msk, state, msk->flags);
        if (state == TCP_LISTEN) {
-               if (WARN_ON_ONCE(!msk->subflow || !msk->subflow->sk))
+               struct socket *ssock = READ_ONCE(msk->subflow);
+
+               if (WARN_ON_ONCE(!ssock || !ssock->sk))
                        return 0;
 
-               return inet_csk_listen_poll(msk->subflow->sk);
+               return inet_csk_listen_poll(ssock->sk);
        }
 
+       shutdown = READ_ONCE(sk->sk_shutdown);
+       if (shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
+               mask |= EPOLLHUP;
+       if (shutdown & RCV_SHUTDOWN)
+               mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
+
        if (state != TCP_SYN_SENT && state != TCP_SYN_RECV) {
                mask |= mptcp_check_readable(msk);
-               mask |= mptcp_check_writeable(msk);
+               if (shutdown & SEND_SHUTDOWN)
+                       mask |= EPOLLOUT | EPOLLWRNORM;
+               else
+                       mask |= mptcp_check_writeable(msk);
        } else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
                /* cf tcp_poll() note about TFO */
                mask |= EPOLLOUT | EPOLLWRNORM;
        }
-       if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
-               mask |= EPOLLHUP;
-       if (sk->sk_shutdown & RCV_SHUTDOWN)
-               mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
 
        /* This barrier is coupled with smp_wmb() in __mptcp_error_report() */
        smp_rmb();
@@ -3859,7 +3875,7 @@ static const struct proto_ops mptcp_stream_ops = {
        .owner             = THIS_MODULE,
        .release           = inet_release,
        .bind              = mptcp_bind,
-       .connect           = mptcp_stream_connect,
+       .connect           = inet_stream_connect,
        .socketpair        = sock_no_socketpair,
        .accept            = mptcp_stream_accept,
        .getname           = inet_getname,
@@ -3954,7 +3970,7 @@ static const struct proto_ops mptcp_v6_stream_ops = {
        .owner             = THIS_MODULE,
        .release           = inet6_release,
        .bind              = mptcp_bind,
-       .connect           = mptcp_stream_connect,
+       .connect           = inet_stream_connect,
        .socketpair        = sock_no_socketpair,
        .accept            = mptcp_stream_accept,
        .getname           = inet6_getname,
index 2d7b2c8..c525525 100644 (file)
@@ -297,7 +297,6 @@ struct mptcp_sock {
                        nodelay:1,
                        fastopening:1,
                        in_accept_queue:1;
-       int             connect_flags;
        struct work_struct work;
        struct sk_buff  *ooo_last_skb;
        struct rb_root  out_of_order_queue;
@@ -306,7 +305,11 @@ struct mptcp_sock {
        struct list_head rtx_queue;
        struct mptcp_data_frag *first_pending;
        struct list_head join_list;
-       struct socket   *subflow; /* outgoing connect/listener/!mp_capable */
+       struct socket   *subflow; /* outgoing connect/listener/!mp_capable
+                                  * The mptcp ops can safely dereference, using suitable
+                                  * ONCE annotation, the subflow outside the socket
+                                  * lock as such sock is freed after close().
+                                  */
        struct sock     *first;
        struct mptcp_pm_data    pm;
        struct {
@@ -613,7 +616,6 @@ int mptcp_is_checksum_enabled(const struct net *net);
 int mptcp_allow_join_id0(const struct net *net);
 unsigned int mptcp_stale_loss_cnt(const struct net *net);
 int mptcp_get_pm_type(const struct net *net);
-void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk);
 void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
                                     const struct mptcp_options_received *mp_opt);
 bool __mptcp_retransmit_pending_data(struct sock *sk);
@@ -683,9 +685,10 @@ void __init mptcp_proto_init(void);
 int __init mptcp_proto_v6_init(void);
 #endif
 
-struct sock *mptcp_sk_clone(const struct sock *sk,
-                           const struct mptcp_options_received *mp_opt,
-                           struct request_sock *req);
+struct sock *mptcp_sk_clone_init(const struct sock *sk,
+                                const struct mptcp_options_received *mp_opt,
+                                struct sock *ssk,
+                                struct request_sock *req);
 void mptcp_get_options(const struct sk_buff *skb,
                       struct mptcp_options_received *mp_opt);
 
index ba065b6..4688daa 100644 (file)
@@ -815,38 +815,12 @@ create_child:
                ctx->setsockopt_seq = listener->setsockopt_seq;
 
                if (ctx->mp_capable) {
-                       ctx->conn = mptcp_sk_clone(listener->conn, &mp_opt, req);
+                       ctx->conn = mptcp_sk_clone_init(listener->conn, &mp_opt, child, req);
                        if (!ctx->conn)
                                goto fallback;
 
                        owner = mptcp_sk(ctx->conn);
-
-                       /* this can't race with mptcp_close(), as the msk is
-                        * not yet exposted to user-space
-                        */
-                       inet_sk_state_store(ctx->conn, TCP_ESTABLISHED);
-
-                       /* record the newly created socket as the first msk
-                        * subflow, but don't link it yet into conn_list
-                        */
-                       WRITE_ONCE(owner->first, child);
-
-                       /* new mpc subflow takes ownership of the newly
-                        * created mptcp socket
-                        */
-                       owner->setsockopt_seq = ctx->setsockopt_seq;
                        mptcp_pm_new_connection(owner, child, 1);
-                       mptcp_token_accept(subflow_req, owner);
-
-                       /* set msk addresses early to ensure mptcp_pm_get_local_id()
-                        * uses the correct data
-                        */
-                       mptcp_copy_inaddrs(ctx->conn, child);
-                       mptcp_propagate_sndbuf(ctx->conn, child);
-
-                       mptcp_rcv_space_init(owner, child);
-                       list_add(&ctx->node, &owner->conn_list);
-                       sock_hold(child);
 
                        /* with OoO packets we can reach here without ingress
                         * mpc option
index c878041..3a1e0fd 100644 (file)
@@ -1779,7 +1779,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
                                break;
                        }
                }
-               if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
+               if (put_user(ALIGN(BITS_TO_BYTES(nlk->ngroups), sizeof(u32)), optlen))
                        err = -EFAULT;
                netlink_unlock_table();
                return err;
index 3f99b43..e2d2af9 100644 (file)
@@ -123,7 +123,7 @@ void nr_write_internal(struct sock *sk, int frametype)
        unsigned char  *dptr;
        int len, timeout;
 
-       len = NR_NETWORK_LEN + NR_TRANSPORT_LEN;
+       len = NR_TRANSPORT_LEN;
 
        switch (frametype & 0x0F) {
        case NR_CONNREQ:
@@ -141,7 +141,8 @@ void nr_write_internal(struct sock *sk, int frametype)
                return;
        }
 
-       if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
+       skb = alloc_skb(NR_NETWORK_LEN + len, GFP_ATOMIC);
+       if (!skb)
                return;
 
        /*
@@ -149,7 +150,7 @@ void nr_write_internal(struct sock *sk, int frametype)
         */
        skb_reserve(skb, NR_NETWORK_LEN);
 
-       dptr = skb_put(skb, skb_tailroom(skb));
+       dptr = skb_put(skb, len);
 
        switch (frametype & 0x0F) {
        case NR_CONNREQ:
index 94c6a1f..a2dbeb2 100644 (file)
@@ -3201,6 +3201,9 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex,
 
        lock_sock(sk);
        spin_lock(&po->bind_lock);
+       if (!proto)
+               proto = po->num;
+
        rcu_read_lock();
 
        if (po->fanout) {
@@ -3299,7 +3302,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
        memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data_min));
        name[sizeof(uaddr->sa_data_min)] = 0;
 
-       return packet_do_bind(sk, name, 0, pkt_sk(sk)->num);
+       return packet_do_bind(sk, name, 0, 0);
 }
 
 static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
@@ -3316,8 +3319,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
        if (sll->sll_family != AF_PACKET)
                return -EINVAL;
 
-       return packet_do_bind(sk, NULL, sll->sll_ifindex,
-                             sll->sll_protocol ? : pkt_sk(sk)->num);
+       return packet_do_bind(sk, NULL, sll->sll_ifindex, sll->sll_protocol);
 }
 
 static struct proto packet_proto = {
index d0c4eda..f6b200c 100644 (file)
@@ -143,7 +143,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
        rp = nlmsg_data(nlh);
        rp->pdiag_family = AF_PACKET;
        rp->pdiag_type = sk->sk_type;
-       rp->pdiag_num = ntohs(po->num);
+       rp->pdiag_num = ntohs(READ_ONCE(po->num));
        rp->pdiag_ino = sk_ino;
        sock_diag_save_cookie(sk, rp->pdiag_cookie);
 
index 31f738d..da0b3b5 100644 (file)
@@ -980,6 +980,7 @@ static int __init af_rxrpc_init(void)
        BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof_field(struct sk_buff, cb));
 
        ret = -ENOMEM;
+       rxrpc_gen_version_string();
        rxrpc_call_jar = kmem_cache_create(
                "rxrpc_call_jar", sizeof(struct rxrpc_call), 0,
                SLAB_HWCACHE_ALIGN, NULL);
index 5d44dc0..e8e14c6 100644 (file)
@@ -1068,6 +1068,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t,
 /*
  * local_event.c
  */
+void rxrpc_gen_version_string(void);
 void rxrpc_send_version_request(struct rxrpc_local *local,
                                struct rxrpc_host_header *hdr,
                                struct sk_buff *skb);
index 5e69ea6..993c69f 100644 (file)
 #include <generated/utsrelease.h>
 #include "ar-internal.h"
 
-static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";
+static char rxrpc_version_string[65]; // "linux-" UTS_RELEASE " AF_RXRPC";
+
+/*
+ * Generate the VERSION packet string.
+ */
+void rxrpc_gen_version_string(void)
+{
+       snprintf(rxrpc_version_string, sizeof(rxrpc_version_string),
+                "linux-%.49s AF_RXRPC", UTS_RELEASE);
+}
 
 /*
  * Reply to a version request
index 9dbc433..815c3e4 100644 (file)
@@ -1153,6 +1153,9 @@ static int fl_set_geneve_opt(const struct nlattr *nla, struct fl_flow_key *key,
        if (option_len > sizeof(struct geneve_opt))
                data_len = option_len - sizeof(struct geneve_opt);
 
+       if (key->enc_opts.len > FLOW_DIS_TUN_OPTS_MAX - 4)
+               return -ERANGE;
+
        opt = (struct geneve_opt *)&key->enc_opts.data[key->enc_opts.len];
        memset(opt, 0xff, option_len);
        opt->length = data_len / 4;
index fdb8f42..014209b 100644 (file)
@@ -1252,7 +1252,12 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
        sch->parent = parent;
 
        if (handle == TC_H_INGRESS) {
-               sch->flags |= TCQ_F_INGRESS;
+               if (!(sch->flags & TCQ_F_INGRESS)) {
+                       NL_SET_ERR_MSG(extack,
+                                      "Specified parent ID is reserved for ingress and clsact Qdiscs");
+                       err = -EINVAL;
+                       goto err_out3;
+               }
                handle = TC_H_MAKE(TC_H_INGRESS, 0);
        } else {
                if (handle == 0) {
@@ -1591,11 +1596,20 @@ replay:
                                        NL_SET_ERR_MSG(extack, "Invalid qdisc name");
                                        return -EINVAL;
                                }
+                               if (q->flags & TCQ_F_INGRESS) {
+                                       NL_SET_ERR_MSG(extack,
+                                                      "Cannot regraft ingress or clsact Qdiscs");
+                                       return -EINVAL;
+                               }
                                if (q == p ||
                                    (p && check_loop(q, p, 0))) {
                                        NL_SET_ERR_MSG(extack, "Qdisc parent/child loop detected");
                                        return -ELOOP;
                                }
+                               if (clid == TC_H_INGRESS) {
+                                       NL_SET_ERR_MSG(extack, "Ingress cannot graft directly");
+                                       return -EINVAL;
+                               }
                                qdisc_refcount_inc(q);
                                goto graft;
                        } else {
index 8483812..e43a454 100644 (file)
@@ -80,6 +80,9 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
        struct net_device *dev = qdisc_dev(sch);
        int err;
 
+       if (sch->parent != TC_H_INGRESS)
+               return -EOPNOTSUPP;
+
        net_inc_ingress_queue();
 
        mini_qdisc_pair_init(&q->miniqp, sch, &dev->miniq_ingress);
@@ -101,6 +104,9 @@ static void ingress_destroy(struct Qdisc *sch)
 {
        struct ingress_sched_data *q = qdisc_priv(sch);
 
+       if (sch->parent != TC_H_INGRESS)
+               return;
+
        tcf_block_put_ext(q->block, sch, &q->block_info);
        net_dec_ingress_queue();
 }
@@ -134,7 +140,7 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
        .cl_ops                 =       &ingress_class_ops,
        .id                     =       "ingress",
        .priv_size              =       sizeof(struct ingress_sched_data),
-       .static_flags           =       TCQ_F_CPUSTATS,
+       .static_flags           =       TCQ_F_INGRESS | TCQ_F_CPUSTATS,
        .init                   =       ingress_init,
        .destroy                =       ingress_destroy,
        .dump                   =       ingress_dump,
@@ -219,6 +225,9 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
        struct net_device *dev = qdisc_dev(sch);
        int err;
 
+       if (sch->parent != TC_H_CLSACT)
+               return -EOPNOTSUPP;
+
        net_inc_ingress_queue();
        net_inc_egress_queue();
 
@@ -248,6 +257,9 @@ static void clsact_destroy(struct Qdisc *sch)
 {
        struct clsact_sched_data *q = qdisc_priv(sch);
 
+       if (sch->parent != TC_H_CLSACT)
+               return;
+
        tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info);
        tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info);
 
@@ -269,7 +281,7 @@ static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
        .cl_ops                 =       &clsact_class_ops,
        .id                     =       "clsact",
        .priv_size              =       sizeof(struct clsact_sched_data),
-       .static_flags           =       TCQ_F_CPUSTATS,
+       .static_flags           =       TCQ_F_INGRESS | TCQ_F_CPUSTATS,
        .init                   =       clsact_init,
        .destroy                =       clsact_destroy,
        .dump                   =       ingress_dump,
index 2f66a20..2abe45a 100644 (file)
@@ -324,9 +324,12 @@ bool sctp_transport_pl_recv(struct sctp_transport *t)
                t->pl.probe_size += SCTP_PL_BIG_STEP;
        } else if (t->pl.state == SCTP_PL_SEARCH) {
                if (!t->pl.probe_high) {
-                       t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_BIG_STEP,
-                                              SCTP_MAX_PLPMTU);
-                       return false;
+                       if (t->pl.probe_size < SCTP_MAX_PLPMTU) {
+                               t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_BIG_STEP,
+                                                      SCTP_MAX_PLPMTU);
+                               return false;
+                       }
+                       t->pl.probe_high = SCTP_MAX_PLPMTU;
                }
                t->pl.probe_size += SCTP_PL_MIN_STEP;
                if (t->pl.probe_size >= t->pl.probe_high) {
@@ -341,7 +344,7 @@ bool sctp_transport_pl_recv(struct sctp_transport *t)
        } else if (t->pl.state == SCTP_PL_COMPLETE) {
                /* Raise probe_size again after 30 * interval in Search Complete */
                t->pl.state = SCTP_PL_SEARCH; /* Search Complete -> Search */
-               t->pl.probe_size += SCTP_PL_MIN_STEP;
+               t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_MIN_STEP, SCTP_MAX_PLPMTU);
        }
 
        return t->pl.state == SCTP_PL_COMPLETE;
index 50c38b6..538e9c6 100644 (file)
@@ -2000,8 +2000,10 @@ static int smc_listen_rdma_init(struct smc_sock *new_smc,
                return rc;
 
        /* create send buffer and rmb */
-       if (smc_buf_create(new_smc, false))
+       if (smc_buf_create(new_smc, false)) {
+               smc_conn_abort(new_smc, ini->first_contact_local);
                return SMC_CLC_DECL_MEM;
+       }
 
        return 0;
 }
@@ -2217,8 +2219,11 @@ static void smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
        smcr_version = ini->smcr_version;
        ini->smcr_version = SMC_V2;
        rc = smc_listen_rdma_init(new_smc, ini);
-       if (!rc)
+       if (!rc) {
                rc = smc_listen_rdma_reg(new_smc, ini->first_contact_local);
+               if (rc)
+                       smc_conn_abort(new_smc, ini->first_contact_local);
+       }
        if (!rc)
                return;
        ini->smcr_version = smcr_version;
index 4543567..3f465fa 100644 (file)
@@ -127,6 +127,7 @@ static int smcr_lgr_conn_assign_link(struct smc_connection *conn, bool first)
        int i, j;
 
        /* do link balancing */
+       conn->lnk = NULL;       /* reset conn->lnk first */
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                struct smc_link *lnk = &conn->lgr->lnk[i];
 
index a0840b8..7a8d916 100644 (file)
@@ -578,7 +578,10 @@ static struct smc_buf_desc *smc_llc_get_next_rmb(struct smc_link_group *lgr,
 {
        struct smc_buf_desc *buf_next;
 
-       if (!buf_pos || list_is_last(&buf_pos->list, &lgr->rmbs[*buf_lst])) {
+       if (!buf_pos)
+               return _smc_llc_get_next_rmb(lgr, buf_lst);
+
+       if (list_is_last(&buf_pos->list, &lgr->rmbs[*buf_lst])) {
                (*buf_lst)++;
                return _smc_llc_get_next_rmb(lgr, buf_lst);
        }
@@ -614,6 +617,8 @@ static int smc_llc_fill_ext_v2(struct smc_llc_msg_add_link_v2_ext *ext,
                goto out;
        buf_pos = smc_llc_get_first_rmb(lgr, &buf_lst);
        for (i = 0; i < ext->num_rkeys; i++) {
+               while (buf_pos && !(buf_pos)->used)
+                       buf_pos = smc_llc_get_next_rmb(lgr, &buf_lst, buf_pos);
                if (!buf_pos)
                        break;
                rmb = buf_pos;
@@ -623,8 +628,6 @@ static int smc_llc_fill_ext_v2(struct smc_llc_msg_add_link_v2_ext *ext,
                        cpu_to_be64((uintptr_t)rmb->cpu_addr) :
                        cpu_to_be64((u64)sg_dma_address(rmb->sgt[lnk_idx].sgl));
                buf_pos = smc_llc_get_next_rmb(lgr, &buf_lst, buf_pos);
-               while (buf_pos && !(buf_pos)->used)
-                       buf_pos = smc_llc_get_next_rmb(lgr, &buf_lst, buf_pos);
        }
        len += i * sizeof(ext->rt[0]);
 out:
index c8321de..6debf4f 100644 (file)
@@ -927,11 +927,10 @@ static void __rpc_execute(struct rpc_task *task)
                 */
                do_action = task->tk_action;
                /* Tasks with an RPC error status should exit */
-               if (do_action != rpc_exit_task &&
+               if (do_action && do_action != rpc_exit_task &&
                    (status = READ_ONCE(task->tk_rpc_status)) != 0) {
                        task->tk_status = status;
-                       if (do_action != NULL)
-                               do_action = rpc_exit_task;
+                       do_action = rpc_exit_task;
                }
                /* Callbacks override all actions */
                if (task->tk_callback) {
index 804c388..0672aca 100644 (file)
@@ -167,6 +167,11 @@ static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
        return ctx->strp.msg_ready;
 }
 
+static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
+{
+       return ctx->strp.mixed_decrypted;
+}
+
 #ifdef CONFIG_TLS_DEVICE
 int tls_device_init(void);
 void tls_device_cleanup(void);
index a7cc4f9..bf69c9d 100644 (file)
@@ -1007,20 +1007,14 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx)
        struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(tls_ctx);
        struct sk_buff *skb = tls_strp_msg(sw_ctx);
        struct strp_msg *rxm = strp_msg(skb);
-       int is_decrypted = skb->decrypted;
-       int is_encrypted = !is_decrypted;
-       struct sk_buff *skb_iter;
-       int left;
-
-       left = rxm->full_len - skb->len;
-       /* Check if all the data is decrypted already */
-       skb_iter = skb_shinfo(skb)->frag_list;
-       while (skb_iter && left > 0) {
-               is_decrypted &= skb_iter->decrypted;
-               is_encrypted &= !skb_iter->decrypted;
-
-               left -= skb_iter->len;
-               skb_iter = skb_iter->next;
+       int is_decrypted, is_encrypted;
+
+       if (!tls_strp_msg_mixed_decrypted(sw_ctx)) {
+               is_decrypted = skb->decrypted;
+               is_encrypted = !is_decrypted;
+       } else {
+               is_decrypted = 0;
+               is_encrypted = 0;
        }
 
        trace_tls_device_decrypted(sk, tcp_sk(sk)->copied_seq - rxm->full_len,
index 955ac3e..f37f4a0 100644 (file)
@@ -20,7 +20,9 @@ static void tls_strp_abort_strp(struct tls_strparser *strp, int err)
        strp->stopped = 1;
 
        /* Report an error on the lower socket */
-       strp->sk->sk_err = -err;
+       WRITE_ONCE(strp->sk->sk_err, -err);
+       /* Paired with smp_rmb() in tcp_poll() */
+       smp_wmb();
        sk_error_report(strp->sk);
 }
 
@@ -29,34 +31,50 @@ static void tls_strp_anchor_free(struct tls_strparser *strp)
        struct skb_shared_info *shinfo = skb_shinfo(strp->anchor);
 
        DEBUG_NET_WARN_ON_ONCE(atomic_read(&shinfo->dataref) != 1);
-       shinfo->frag_list = NULL;
+       if (!strp->copy_mode)
+               shinfo->frag_list = NULL;
        consume_skb(strp->anchor);
        strp->anchor = NULL;
 }
 
-/* Create a new skb with the contents of input copied to its page frags */
-static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
+static struct sk_buff *
+tls_strp_skb_copy(struct tls_strparser *strp, struct sk_buff *in_skb,
+                 int offset, int len)
 {
-       struct strp_msg *rxm;
        struct sk_buff *skb;
-       int i, err, offset;
+       int i, err;
 
-       skb = alloc_skb_with_frags(0, strp->stm.full_len, TLS_PAGE_ORDER,
+       skb = alloc_skb_with_frags(0, len, TLS_PAGE_ORDER,
                                   &err, strp->sk->sk_allocation);
        if (!skb)
                return NULL;
 
-       offset = strp->stm.offset;
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-               WARN_ON_ONCE(skb_copy_bits(strp->anchor, offset,
+               WARN_ON_ONCE(skb_copy_bits(in_skb, offset,
                                           skb_frag_address(frag),
                                           skb_frag_size(frag)));
                offset += skb_frag_size(frag);
        }
 
-       skb_copy_header(skb, strp->anchor);
+       skb->len = len;
+       skb->data_len = len;
+       skb_copy_header(skb, in_skb);
+       return skb;
+}
+
+/* Create a new skb with the contents of input copied to its page frags */
+static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
+{
+       struct strp_msg *rxm;
+       struct sk_buff *skb;
+
+       skb = tls_strp_skb_copy(strp, strp->anchor, strp->stm.offset,
+                               strp->stm.full_len);
+       if (!skb)
+               return NULL;
+
        rxm = strp_msg(skb);
        rxm->offset = 0;
        return skb;
@@ -180,22 +198,22 @@ static void tls_strp_flush_anchor_copy(struct tls_strparser *strp)
        for (i = 0; i < shinfo->nr_frags; i++)
                __skb_frag_unref(&shinfo->frags[i], false);
        shinfo->nr_frags = 0;
+       if (strp->copy_mode) {
+               kfree_skb_list(shinfo->frag_list);
+               shinfo->frag_list = NULL;
+       }
        strp->copy_mode = 0;
+       strp->mixed_decrypted = 0;
 }
 
-static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
-                          unsigned int offset, size_t in_len)
+static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff *skb,
+                               struct sk_buff *in_skb, unsigned int offset,
+                               size_t in_len)
 {
-       struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
-       struct sk_buff *skb;
-       skb_frag_t *frag;
        size_t len, chunk;
+       skb_frag_t *frag;
        int sz;
 
-       if (strp->msg_ready)
-               return 0;
-
-       skb = strp->anchor;
        frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE];
 
        len = in_len;
@@ -208,19 +226,26 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
                                           skb_frag_size(frag),
                                           chunk));
 
-               sz = tls_rx_msg_size(strp, strp->anchor);
-               if (sz < 0) {
-                       desc->error = sz;
-                       return 0;
-               }
-
-               /* We may have over-read, sz == 0 is guaranteed under-read */
-               if (sz > 0)
-                       chunk = min_t(size_t, chunk, sz - skb->len);
-
                skb->len += chunk;
                skb->data_len += chunk;
                skb_frag_size_add(frag, chunk);
+
+               sz = tls_rx_msg_size(strp, skb);
+               if (sz < 0)
+                       return sz;
+
+               /* We may have over-read, sz == 0 is guaranteed under-read */
+               if (unlikely(sz && sz < skb->len)) {
+                       int over = skb->len - sz;
+
+                       WARN_ON_ONCE(over > chunk);
+                       skb->len -= over;
+                       skb->data_len -= over;
+                       skb_frag_size_add(frag, -over);
+
+                       chunk -= over;
+               }
+
                frag++;
                len -= chunk;
                offset += chunk;
@@ -247,15 +272,99 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
                offset += chunk;
        }
 
-       if (strp->stm.full_len == skb->len) {
+read_done:
+       return in_len - len;
+}
+
+static int tls_strp_copyin_skb(struct tls_strparser *strp, struct sk_buff *skb,
+                              struct sk_buff *in_skb, unsigned int offset,
+                              size_t in_len)
+{
+       struct sk_buff *nskb, *first, *last;
+       struct skb_shared_info *shinfo;
+       size_t chunk;
+       int sz;
+
+       if (strp->stm.full_len)
+               chunk = strp->stm.full_len - skb->len;
+       else
+               chunk = TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE;
+       chunk = min(chunk, in_len);
+
+       nskb = tls_strp_skb_copy(strp, in_skb, offset, chunk);
+       if (!nskb)
+               return -ENOMEM;
+
+       shinfo = skb_shinfo(skb);
+       if (!shinfo->frag_list) {
+               shinfo->frag_list = nskb;
+               nskb->prev = nskb;
+       } else {
+               first = shinfo->frag_list;
+               last = first->prev;
+               last->next = nskb;
+               first->prev = nskb;
+       }
+
+       skb->len += chunk;
+       skb->data_len += chunk;
+
+       if (!strp->stm.full_len) {
+               sz = tls_rx_msg_size(strp, skb);
+               if (sz < 0)
+                       return sz;
+
+               /* We may have over-read, sz == 0 is guaranteed under-read */
+               if (unlikely(sz && sz < skb->len)) {
+                       int over = skb->len - sz;
+
+                       WARN_ON_ONCE(over > chunk);
+                       skb->len -= over;
+                       skb->data_len -= over;
+                       __pskb_trim(nskb, nskb->len - over);
+
+                       chunk -= over;
+               }
+
+               strp->stm.full_len = sz;
+       }
+
+       return chunk;
+}
+
+static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
+                          unsigned int offset, size_t in_len)
+{
+       struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
+       struct sk_buff *skb;
+       int ret;
+
+       if (strp->msg_ready)
+               return 0;
+
+       skb = strp->anchor;
+       if (!skb->len)
+               skb_copy_decrypted(skb, in_skb);
+       else
+               strp->mixed_decrypted |= !!skb_cmp_decrypted(skb, in_skb);
+
+       if (IS_ENABLED(CONFIG_TLS_DEVICE) && strp->mixed_decrypted)
+               ret = tls_strp_copyin_skb(strp, skb, in_skb, offset, in_len);
+       else
+               ret = tls_strp_copyin_frag(strp, skb, in_skb, offset, in_len);
+       if (ret < 0) {
+               desc->error = ret;
+               ret = 0;
+       }
+
+       if (strp->stm.full_len && strp->stm.full_len == skb->len) {
                desc->count = 0;
 
                strp->msg_ready = 1;
                tls_rx_msg_ready(strp);
        }
 
-read_done:
-       return in_len - len;
+       return ret;
 }
 
 static int tls_strp_read_copyin(struct tls_strparser *strp)
@@ -315,15 +424,19 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
        return 0;
 }
 
-static bool tls_strp_check_no_dup(struct tls_strparser *strp)
+static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
 {
        unsigned int len = strp->stm.offset + strp->stm.full_len;
-       struct sk_buff *skb;
+       struct sk_buff *first, *skb;
        u32 seq;
 
-       skb = skb_shinfo(strp->anchor)->frag_list;
-       seq = TCP_SKB_CB(skb)->seq;
+       first = skb_shinfo(strp->anchor)->frag_list;
+       skb = first;
+       seq = TCP_SKB_CB(first)->seq;
 
+       /* Make sure there's no duplicate data in the queue,
+        * and the decrypted status matches.
+        */
        while (skb->len < len) {
                seq += skb->len;
                len -= skb->len;
@@ -331,6 +444,8 @@ static bool tls_strp_check_no_dup(struct tls_strparser *strp)
 
                if (TCP_SKB_CB(skb)->seq != seq)
                        return false;
+               if (skb_cmp_decrypted(first, skb))
+                       return false;
        }
 
        return true;
@@ -411,7 +526,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
                        return tls_strp_read_copy(strp, true);
        }
 
-       if (!tls_strp_check_no_dup(strp))
+       if (!tls_strp_check_queue_ok(strp))
                return tls_strp_read_copy(strp, false);
 
        strp->msg_ready = 1;
index 635b8bf..1a53c8f 100644 (file)
@@ -70,7 +70,9 @@ noinline void tls_err_abort(struct sock *sk, int err)
 {
        WARN_ON_ONCE(err >= 0);
        /* sk->sk_err should contain a positive error code. */
-       sk->sk_err = -err;
+       WRITE_ONCE(sk->sk_err, -err);
+       /* Paired with smp_rmb() in tcp_poll() */
+       smp_wmb();
        sk_error_report(sk);
 }
 
@@ -2304,10 +2306,14 @@ static void tls_data_ready(struct sock *sk)
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
        struct sk_psock *psock;
+       gfp_t alloc_save;
 
        trace_sk_data_ready(sk);
 
+       alloc_save = sk->sk_allocation;
+       sk->sk_allocation = GFP_ATOMIC;
        tls_strp_data_ready(&ctx->strp);
+       sk->sk_allocation = alloc_save;
 
        psock = sk_psock_get(sk);
        if (psock) {
index cc695c9..e7728b5 100644 (file)
@@ -2553,7 +2553,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
 {
        struct unix_sock *u = unix_sk(sk);
        struct sk_buff *skb;
-       int err, copied;
+       int err;
 
        mutex_lock(&u->iolock);
        skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err);
@@ -2561,10 +2561,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
        if (!skb)
                return err;
 
-       copied = recv_actor(sk, skb);
-       kfree_skb(skb);
-
-       return copied;
+       return recv_actor(sk, skb);
 }
 
 /*
index e487855..b769fc2 100644 (file)
@@ -1441,7 +1441,6 @@ int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t recv_acto
        struct sock *sk = sk_vsock(vsk);
        struct sk_buff *skb;
        int off = 0;
-       int copied;
        int err;
 
        spin_lock_bh(&vvs->rx_lock);
@@ -1454,9 +1453,7 @@ int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t recv_acto
        if (!skb)
                return err;
 
-       copied = recv_actor(sk, skb);
-       kfree_skb(skb);
-       return copied;
+       return recv_actor(sk, skb);
 }
 EXPORT_SYMBOL_GPL(virtio_transport_read_skb);
 
index 6448b78..bf66277 100644 (file)
@@ -498,7 +498,6 @@ int main(int argc, char **argv)
                                        "Option -%c requires an argument.\n\n",
                                        optopt);
                case 'h':
-                       __fallthrough;
                default:
                        Usage();
                        return 0;
index accc9d2..6c043fb 100644 (file)
@@ -611,7 +611,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm);
 int snd_hdac_keep_power_up(struct hdac_device *codec)
 {
        if (!atomic_inc_not_zero(&codec->in_pm)) {
-               int ret = pm_runtime_get_if_in_use(&codec->dev);
+               int ret = pm_runtime_get_if_active(&codec->dev, true);
                if (!ret)
                        return -1;
                if (ret < 0)
index 099722e..748a3c4 100644 (file)
@@ -1306,6 +1306,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
        SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
        SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
+       SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI),
        SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
        SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
index a7e4765..7b5f194 100644 (file)
@@ -11719,6 +11719,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
+       SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
+       SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
index 8538e28..1e42052 100644 (file)
@@ -46,7 +46,7 @@ static const struct reg_default cs35l41_reg[] = {
        { CS35L41_DSP1_RX5_SRC,                 0x00000020 },
        { CS35L41_DSP1_RX6_SRC,                 0x00000021 },
        { CS35L41_DSP1_RX7_SRC,                 0x0000003A },
-       { CS35L41_DSP1_RX8_SRC,                 0x00000001 },
+       { CS35L41_DSP1_RX8_SRC,                 0x0000003B },
        { CS35L41_NGATE1_SRC,                   0x00000008 },
        { CS35L41_NGATE2_SRC,                   0x00000009 },
        { CS35L41_AMP_DIG_VOL_CTRL,             0x00008000 },
@@ -58,8 +58,8 @@ static const struct reg_default cs35l41_reg[] = {
        { CS35L41_IRQ1_MASK2,                   0xFFFFFFFF },
        { CS35L41_IRQ1_MASK3,                   0xFFFF87FF },
        { CS35L41_IRQ1_MASK4,                   0xFEFFFFFF },
-       { CS35L41_GPIO1_CTRL1,                  0xE1000001 },
-       { CS35L41_GPIO2_CTRL1,                  0xE1000001 },
+       { CS35L41_GPIO1_CTRL1,                  0x81000001 },
+       { CS35L41_GPIO2_CTRL1,                  0x81000001 },
        { CS35L41_MIXER_NGATE_CFG,              0x00000000 },
        { CS35L41_MIXER_NGATE_CH1_CFG,          0x00000303 },
        { CS35L41_MIXER_NGATE_CH2_CFG,          0x00000303 },
index da6fcf7..de978c3 100644 (file)
@@ -746,6 +746,8 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
        struct tx_macro *tx = snd_soc_component_get_drvdata(component);
 
        val = ucontrol->value.enumerated.item[0];
+       if (val >= e->items)
+               return -EINVAL;
 
        switch (e->reg) {
        case CDC_TX_INP_MUX_ADC_MUX0_CFG0:
@@ -772,6 +774,9 @@ static int tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
        case CDC_TX_INP_MUX_ADC_MUX7_CFG0:
                mic_sel_reg = CDC_TX7_TX_PATH_CFG0;
                break;
+       default:
+               dev_err(component->dev, "Error in configuration!!\n");
+               return -EINVAL;
        }
 
        if (val != 0) {
index 2935c1b..5bc46b0 100644 (file)
@@ -267,7 +267,9 @@ static int rt5682_i2c_probe(struct i2c_client *i2c)
                ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
                        rt5682_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
                        | IRQF_ONESHOT, "rt5682", rt5682);
-               if (ret)
+               if (!ret)
+                       rt5682->irq = i2c->irq;
+               else
                        dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
        }
 
index f6c798b..5d99254 100644 (file)
@@ -2959,6 +2959,9 @@ static int rt5682_suspend(struct snd_soc_component *component)
        if (rt5682->is_sdw)
                return 0;
 
+       if (rt5682->irq)
+               disable_irq(rt5682->irq);
+
        cancel_delayed_work_sync(&rt5682->jack_detect_work);
        cancel_delayed_work_sync(&rt5682->jd_check_work);
        if (rt5682->hs_jack && (rt5682->jack_type & SND_JACK_HEADSET) == SND_JACK_HEADSET) {
@@ -3027,6 +3030,9 @@ static int rt5682_resume(struct snd_soc_component *component)
        mod_delayed_work(system_power_efficient_wq,
                &rt5682->jack_detect_work, msecs_to_jiffies(0));
 
+       if (rt5682->irq)
+               enable_irq(rt5682->irq);
+
        return 0;
 }
 #else
index d568c69..e8efd8a 100644 (file)
@@ -1462,6 +1462,7 @@ struct rt5682_priv {
        int pll_out[RT5682_PLLS];
 
        int jack_type;
+       int irq;
        int irq_work_delay_time;
 };
 
index ca20cad..399a489 100644 (file)
@@ -183,30 +183,6 @@ static void i2s_stop(struct dw_i2s_dev *dev,
        }
 }
 
-static int dw_i2s_startup(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *cpu_dai)
-{
-       struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-       union dw_i2s_snd_dma_data *dma_data = NULL;
-
-       if (!(dev->capability & DWC_I2S_RECORD) &&
-                       (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
-               return -EINVAL;
-
-       if (!(dev->capability & DWC_I2S_PLAY) &&
-                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
-               return -EINVAL;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_data = &dev->play_dma_data;
-       else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-               dma_data = &dev->capture_dma_data;
-
-       snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
-
-       return 0;
-}
-
 static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
 {
        u32 ch_reg;
@@ -305,12 +281,6 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
-               struct snd_soc_dai *dai)
-{
-       snd_soc_dai_set_dma_data(dai, substream, NULL);
-}
-
 static int dw_i2s_prepare(struct snd_pcm_substream *substream,
                          struct snd_soc_dai *dai)
 {
@@ -382,8 +352,6 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 }
 
 static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
-       .startup        = dw_i2s_startup,
-       .shutdown       = dw_i2s_shutdown,
        .hw_params      = dw_i2s_hw_params,
        .prepare        = dw_i2s_prepare,
        .trigger        = dw_i2s_trigger,
@@ -625,6 +593,14 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
 
 }
 
+static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, &dev->capture_dma_data);
+       return 0;
+}
+
 static int dw_i2s_probe(struct platform_device *pdev)
 {
        const struct i2s_platform_data *pdata = pdev->dev.platform_data;
@@ -643,6 +619,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        dw_i2s_dai->ops = &dw_i2s_dai_ops;
+       dw_i2s_dai->probe = dw_i2s_dai_probe;
 
        dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
        if (IS_ERR(dev->i2s_base))
index 02683dc..1860099 100644 (file)
@@ -169,6 +169,7 @@ static bool apl_lp_streaming(struct avs_dev *adev)
 {
        struct avs_path *path;
 
+       spin_lock(&adev->path_list_lock);
        /* Any gateway without buffer allocated in LP area disqualifies D0IX. */
        list_for_each_entry(path, &adev->path_list, node) {
                struct avs_path_pipeline *ppl;
@@ -188,11 +189,14 @@ static bool apl_lp_streaming(struct avs_dev *adev)
                                if (cfg->copier.dma_type == INVALID_OBJECT_ID)
                                        continue;
 
-                               if (!mod->gtw_attrs.lp_buffer_alloc)
+                               if (!mod->gtw_attrs.lp_buffer_alloc) {
+                                       spin_unlock(&adev->path_list_lock);
                                        return false;
+                               }
                        }
                }
        }
+       spin_unlock(&adev->path_list_lock);
 
        return true;
 }
index d7fccdc..0cf38c9 100644 (file)
@@ -283,8 +283,8 @@ void avs_release_firmwares(struct avs_dev *adev);
 
 int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
                        u8 core_id, u8 domain, void *param, u32 param_size,
-                       u16 *instance_id);
-void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
+                       u8 *instance_id);
+void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
                           u8 ppl_instance_id, u8 core_id);
 int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
                            bool lp, u16 attributes, u8 *instance_id);
index b2823c2..60f8fb0 100644 (file)
@@ -443,7 +443,7 @@ static int avs_register_i2s_boards(struct avs_dev *adev)
        }
 
        for (mach = boards->machs; mach->id[0]; mach++) {
-               if (!acpi_dev_present(mach->id, NULL, -1))
+               if (!acpi_dev_present(mach->id, mach->uid, -1))
                        continue;
 
                if (mach->machine_quirk)
index a8b14b7..3dfa2e9 100644 (file)
@@ -21,17 +21,25 @@ static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol)
        return to_avs_dev(w->dapm->component->dev);
 }
 
-static struct avs_path_module *avs_get_kcontrol_module(struct avs_dev *adev, u32 id)
+static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id)
 {
        struct avs_path *path;
        struct avs_path_pipeline *ppl;
        struct avs_path_module *mod;
 
-       list_for_each_entry(path, &adev->path_list, node)
-               list_for_each_entry(ppl, &path->ppl_list, node)
-                       list_for_each_entry(mod, &ppl->mod_list, node)
-                               if (mod->template->ctl_id && mod->template->ctl_id == id)
+       spin_lock(&adev->path_list_lock);
+       list_for_each_entry(path, &adev->path_list, node) {
+               list_for_each_entry(ppl, &path->ppl_list, node) {
+                       list_for_each_entry(mod, &ppl->mod_list, node) {
+                               if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID)
+                                   && mod->template->ctl_id == id) {
+                                       spin_unlock(&adev->path_list_lock);
                                        return mod;
+                               }
+                       }
+               }
+       }
+       spin_unlock(&adev->path_list_lock);
 
        return NULL;
 }
@@ -49,7 +57,7 @@ int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
        /* prevent access to modules while path is being constructed */
        mutex_lock(&adev->path_mutex);
 
-       active_module = avs_get_kcontrol_module(adev, ctl_data->id);
+       active_module = avs_get_volume_module(adev, ctl_data->id);
        if (active_module) {
                ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
                                                 active_module->instance_id, &dspvols,
@@ -89,7 +97,7 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
                changed = 1;
        }
 
-       active_module = avs_get_kcontrol_module(adev, ctl_data->id);
+       active_module = avs_get_volume_module(adev, ctl_data->id);
        if (active_module) {
                dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
                dspvol.target_volume = *volume;
index b881100..aa03af4 100644 (file)
@@ -225,7 +225,7 @@ err:
 
 int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
                        u8 core_id, u8 domain, void *param, u32 param_size,
-                       u16 *instance_id)
+                       u8 *instance_id)
 {
        struct avs_module_entry mentry;
        bool was_loaded = false;
@@ -272,7 +272,7 @@ err_mod_entry:
        return ret;
 }
 
-void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
+void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
                           u8 ppl_instance_id, u8 core_id)
 {
        struct avs_module_entry mentry;
index d3b60ae..7f23a30 100644 (file)
@@ -619,7 +619,7 @@ enum avs_channel_config {
        AVS_CHANNEL_CONFIG_DUAL_MONO = 9,
        AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10,
        AVS_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11,
-       AVS_CHANNEL_CONFIG_4_CHANNEL = 12,
+       AVS_CHANNEL_CONFIG_7_1 = 12,
        AVS_CHANNEL_CONFIG_INVALID
 };
 
index 197222c..657f7b0 100644 (file)
@@ -37,7 +37,7 @@ struct avs_path_pipeline {
 
 struct avs_path_module {
        u16 module_id;
-       u16 instance_id;
+       u8 instance_id;
        union avs_gtw_attributes gtw_attrs;
 
        struct avs_tplg_module *template;
index 31c032a..1fbb2c2 100644 (file)
@@ -468,21 +468,34 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so
 
        host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST);
        if (!host_stream) {
-               kfree(data);
-               return -EBUSY;
+               ret = -EBUSY;
+               goto err;
        }
 
        data->host_stream = host_stream;
-       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto err;
+
        /* avoid wrap-around with wall-clock */
-       snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
+       ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000);
+       if (ret < 0)
+               goto err;
+
+       ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates);
+       if (ret < 0)
+               goto err;
+
        snd_pcm_set_sync(substream);
 
        dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p",
                __func__, hdac_stream(host_stream)->stream_tag, substream);
 
        return 0;
+
+err:
+       kfree(data);
+       return ret;
 }
 
 static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
index 70a9420..2759282 100644 (file)
@@ -18,7 +18,7 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id
 {
        struct avs_probe_cfg cfg = {{0}};
        struct avs_module_entry mentry;
-       u16 dummy;
+       u8 dummy;
 
        avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
 
index adb69d7..4fb1ac8 100644 (file)
@@ -2405,6 +2405,9 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
                if (!snd_soc_dpcm_be_can_update(fe, be, stream))
                        continue;
 
+               if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
+                       continue;
+
                if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
@@ -3042,3 +3045,20 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
        return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
 }
 EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
+
+/*
+ * We can only prepare a BE DAI if any of it's FE are not prepared,
+ * running or paused for the specified stream direction.
+ */
+int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
+                                struct snd_soc_pcm_runtime *be, int stream)
+{
+       const enum snd_soc_dpcm_state state[] = {
+               SND_SOC_DPCM_STATE_START,
+               SND_SOC_DPCM_STATE_PAUSED,
+               SND_SOC_DPCM_STATE_PREPARE,
+       };
+
+       return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
+}
+EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);
index c61d061..52a0be4 100644 (file)
@@ -94,7 +94,7 @@ static void print_attributes(struct gpio_v2_line_info *info)
        for (i = 0; i < info->num_attrs; i++) {
                if (info->attrs[i].id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE)
                        fprintf(stdout, ", debounce_period=%dusec",
-                               info->attrs[0].debounce_period_us);
+                               info->attrs[i].debounce_period_us);
        }
 }
 
index cef3b1c..51ac441 100644 (file)
  */
 #define CORESIGHT_LEGACY_CPU_TRACE_ID(cpu)  (0x10 + (cpu * 2))
 
-/* CoreSight trace ID is currently the bottom 7 bits of the value */
-#define CORESIGHT_TRACE_ID_VAL_MASK    GENMASK(6, 0)
-
-/*
- * perf record will set the legacy meta data values as unused initially.
- * This allows perf report to manage the decoders created when dynamic
- * allocation in operation.
- */
-#define CORESIGHT_TRACE_ID_UNUSED_FLAG BIT(31)
-
-/* Value to set for unused trace ID values */
-#define CORESIGHT_TRACE_ID_UNUSED_VAL  0x7F
-
 /*
  * Below are the definition of bit offsets for perf option, and works as
  * arbitrary values for all ETM versions.
index 4b7f2df..e682ab6 100644 (file)
@@ -163,6 +163,7 @@ struct in_addr {
 #define IP_MULTICAST_ALL               49
 #define IP_UNICAST_IF                  50
 #define IP_LOCAL_PORT_RANGE            51
+#define IP_PROTOCOL                    52
 
 #define MCAST_EXCLUDE  0
 #define MCAST_INCLUDE  1
index aa77bca..3144f33 100644 (file)
@@ -591,8 +591,9 @@ class YnlFamily(SpecFamily):
                         print('Unexpected message: ' + repr(gm))
                         continue
 
-                rsp.append(self._decode(gm.raw_attrs, op.attr_set.name)
-                           | gm.fixed_header_attrs)
+                rsp_msg = self._decode(gm.raw_attrs, op.attr_set.name)
+                rsp_msg.update(gm.fixed_header_attrs)
+                rsp.append(rsp_msg)
 
         if not rsp:
             return None
index 7026844..a794d9e 100644 (file)
@@ -927,6 +927,7 @@ ifndef NO_DEMANGLE
     EXTLIBS += -lstdc++
     CFLAGS += -DHAVE_CXA_DEMANGLE_SUPPORT
     CXXFLAGS += -DHAVE_CXA_DEMANGLE_SUPPORT
+    $(call detected,CONFIG_CXX_DEMANGLE)
   endif
   ifdef BUILD_NONDISTRO
     ifeq ($(filter -liberty,$(EXTLIBS)),)
index 1593c5d..f487948 100644 (file)
@@ -181,7 +181,6 @@ HOSTCC  ?= gcc
 HOSTLD  ?= ld
 HOSTAR  ?= ar
 CLANG   ?= clang
-LLVM_STRIP ?= llvm-strip
 
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
 
@@ -1083,7 +1082,7 @@ $(BPFTOOL): | $(SKEL_TMP_OUT)
 
 $(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) | $(SKEL_TMP_OUT)
        $(QUIET_CLANG)$(CLANG) -g -O2 -target bpf -Wall -Werror $(BPF_INCLUDE) $(TOOLS_UAPI_INCLUDE) \
-         -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@ && $(LLVM_STRIP) -g $@
+         -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@
 
 $(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o | $(BPFTOOL)
        $(QUIET_GENSKEL)$(BPFTOOL) gen skeleton $< > $@
index 860a8b4..a9623b1 100644 (file)
@@ -12,7 +12,7 @@
 #include "arm-spe.h"
 #include "hisi-ptt.h"
 #include "../../../util/pmu.h"
-#include "../cs-etm.h"
+#include "../../../util/cs-etm.h"
 
 struct perf_event_attr
 *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
index 810e337..f9906f5 100644 (file)
@@ -1175,7 +1175,7 @@ int cmd_ftrace(int argc, const char **argv)
        OPT_BOOLEAN('b', "use-bpf", &ftrace.target.use_bpf,
                    "Use BPF to measure function latency"),
 #endif
-       OPT_BOOLEAN('n', "--use-nsec", &ftrace.use_nsec,
+       OPT_BOOLEAN('n', "use-nsec", &ftrace.use_nsec,
                    "Use nano-second histogram"),
        OPT_PARENT(common_options),
        };
index bd18fe5..f9df1df 100644 (file)
@@ -214,7 +214,7 @@ perf-$(CONFIG_ZSTD) += zstd.o
 
 perf-$(CONFIG_LIBCAP) += cap.o
 
-perf-y += demangle-cxx.o
+perf-$(CONFIG_CXX_DEMANGLE) += demangle-cxx.o
 perf-y += demangle-ocaml.o
 perf-y += demangle-java.o
 perf-y += demangle-rust.o
index cffe493..fb94f52 100644 (file)
@@ -25,7 +25,7 @@ struct perf_sample_data___new {
 } __attribute__((preserve_access_index));
 
 /* new kernel perf_mem_data_src definition */
-union perf_mem_data_src__new {
+union perf_mem_data_src___new {
        __u64 val;
        struct {
                __u64   mem_op:5,       /* type of opcode */
@@ -108,7 +108,7 @@ static inline __u64 perf_get_sample(struct bpf_perf_event_data_kern *kctx,
                if (entry->part == 7)
                        return kctx->data->data_src.mem_blk;
                if (entry->part == 8) {
-                       union perf_mem_data_src__new *data = (void *)&kctx->data->data_src;
+                       union perf_mem_data_src___new *data = (void *)&kctx->data->data_src;
 
                        if (bpf_core_field_exists(data->mem_hops))
                                return data->mem_hops;
index 70cac03..ecca407 100644 (file)
@@ -227,6 +227,19 @@ struct cs_etm_packet_queue {
 #define INFO_HEADER_SIZE (sizeof(((struct perf_record_auxtrace_info *)0)->type) + \
                          sizeof(((struct perf_record_auxtrace_info *)0)->reserved__))
 
+/* CoreSight trace ID is currently the bottom 7 bits of the value */
+#define CORESIGHT_TRACE_ID_VAL_MASK    GENMASK(6, 0)
+
+/*
+ * perf record will set the legacy meta data values as unused initially.
+ * This allows perf report to manage the decoders created when dynamic
+ * allocation in operation.
+ */
+#define CORESIGHT_TRACE_ID_UNUSED_FLAG BIT(31)
+
+/* Value to set for unused trace ID values */
+#define CORESIGHT_TRACE_ID_UNUSED_VAL  0x7F
+
 int cs_etm__process_auxtrace_info(union perf_event *event,
                                  struct perf_session *session);
 struct perf_event_attr *cs_etm_get_default_config(struct perf_pmu *pmu);
index 2f5910b..c2dbb56 100644 (file)
@@ -282,6 +282,7 @@ void evsel__init(struct evsel *evsel,
        evsel->bpf_fd      = -1;
        INIT_LIST_HEAD(&evsel->config_terms);
        INIT_LIST_HEAD(&evsel->bpf_counter_list);
+       INIT_LIST_HEAD(&evsel->bpf_filters);
        perf_evsel__object.init(evsel);
        evsel->sample_size = __evsel__sample_size(attr->sample_type);
        evsel__calc_id_pos(evsel);
index df89287..0f54f28 100644 (file)
@@ -151,10 +151,8 @@ struct evsel {
         */
        struct bpf_counter_ops  *bpf_counter_ops;
 
-       union {
-               struct list_head        bpf_counter_list; /* for perf-stat -b */
-               struct list_head        bpf_filters; /* for perf-record --filter */
-       };
+       struct list_head        bpf_counter_list; /* for perf-stat -b */
+       struct list_head        bpf_filters; /* for perf-record --filter */
 
        /* for perf-stat --use-bpf */
        int                     bperf_leader_prog_fd;
index b2ed9cc..63882a4 100644 (file)
 #include <bfd.h>
 #endif
 
+#if defined(HAVE_LIBBFD_SUPPORT) || defined(HAVE_CPLUS_DEMANGLE_SUPPORT)
+#ifndef DMGL_PARAMS
+#define DMGL_PARAMS     (1 << 0)  /* Include function args */
+#define DMGL_ANSI       (1 << 1)  /* Include const, volatile, etc */
+#endif
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64     183  /* ARM 64 bit */
 #endif
@@ -271,6 +278,26 @@ static bool want_demangle(bool is_kernel_sym)
        return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
 }
 
+/*
+ * Demangle C++ function signature, typically replaced by demangle-cxx.cpp
+ * version.
+ */
+__weak char *cxx_demangle_sym(const char *str __maybe_unused, bool params __maybe_unused,
+                             bool modifiers __maybe_unused)
+{
+#ifdef HAVE_LIBBFD_SUPPORT
+       int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);
+
+       return bfd_demangle(NULL, str, flags);
+#elif defined(HAVE_CPLUS_DEMANGLE_SUPPORT)
+       int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);
+
+       return cplus_demangle(str, flags);
+#else
+       return NULL;
+#endif
+}
+
 static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
 {
        char *demangled = NULL;
index fba7bec..6f9347a 100644 (file)
@@ -6,6 +6,7 @@ ldflags-y += --wrap=acpi_pci_find_root
 ldflags-y += --wrap=nvdimm_bus_register
 ldflags-y += --wrap=devm_cxl_port_enumerate_dports
 ldflags-y += --wrap=devm_cxl_setup_hdm
+ldflags-y += --wrap=devm_cxl_enable_hdm
 ldflags-y += --wrap=devm_cxl_add_passthrough_decoder
 ldflags-y += --wrap=devm_cxl_enumerate_decoders
 ldflags-y += --wrap=cxl_await_media_ready
index ba572d0..34b4802 100644 (file)
@@ -1256,6 +1256,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)
        if (rc)
                return rc;
 
+       cxlds->media_ready = true;
        rc = cxl_dev_state_identify(cxlds);
        if (rc)
                return rc;
index de3933a..2844165 100644 (file)
@@ -149,6 +149,21 @@ struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port,
 }
 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL);
 
+int __wrap_devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm)
+{
+       int index, rc;
+       struct cxl_mock_ops *ops = get_cxl_mock_ops(&index);
+
+       if (ops && ops->is_mock_port(port->uport))
+               rc = 0;
+       else
+               rc = devm_cxl_enable_hdm(port, cxlhdm);
+       put_cxl_mock_ops(index);
+
+       return rc;
+}
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enable_hdm, CXL);
+
 int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port)
 {
        int rc, index;
index c49e540..28d2c77 100644 (file)
@@ -197,7 +197,7 @@ $(OUTPUT)/urandom_read: urandom_read.c urandom_read_aux.c $(OUTPUT)/liburandom_r
 
 $(OUTPUT)/sign-file: ../../../../scripts/sign-file.c
        $(call msg,SIGN-FILE,,$@)
-       $(Q)$(CC) $(shell $(HOSTPKG_CONFIG)--cflags libcrypto 2> /dev/null) \
+       $(Q)$(CC) $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) \
                  $< -o $@ \
                  $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto)
 
index 0ce25a9..064cc5e 100644 (file)
@@ -2,6 +2,7 @@
 // Copyright (c) 2020 Cloudflare
 #include <error.h>
 #include <netinet/tcp.h>
+#include <sys/epoll.h>
 
 #include "test_progs.h"
 #include "test_skmsg_load_helpers.skel.h"
@@ -9,8 +10,12 @@
 #include "test_sockmap_invalid_update.skel.h"
 #include "test_sockmap_skb_verdict_attach.skel.h"
 #include "test_sockmap_progs_query.skel.h"
+#include "test_sockmap_pass_prog.skel.h"
+#include "test_sockmap_drop_prog.skel.h"
 #include "bpf_iter_sockmap.skel.h"
 
+#include "sockmap_helpers.h"
+
 #define TCP_REPAIR             19      /* TCP sock is under repair right now */
 
 #define TCP_REPAIR_ON          1
@@ -350,6 +355,126 @@ out:
        test_sockmap_progs_query__destroy(skel);
 }
 
+#define MAX_EVENTS 10
+static void test_sockmap_skb_verdict_shutdown(void)
+{
+       struct epoll_event ev, events[MAX_EVENTS];
+       int n, err, map, verdict, s, c1, p1;
+       struct test_sockmap_pass_prog *skel;
+       int epollfd;
+       int zero = 0;
+       char b;
+
+       skel = test_sockmap_pass_prog__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "open_and_load"))
+               return;
+
+       verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
+       map = bpf_map__fd(skel->maps.sock_map_rx);
+
+       err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
+       if (!ASSERT_OK(err, "bpf_prog_attach"))
+               goto out;
+
+       s = socket_loopback(AF_INET, SOCK_STREAM);
+       if (s < 0)
+               goto out;
+       err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1);
+       if (err < 0)
+               goto out;
+
+       err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
+       if (err < 0)
+               goto out_close;
+
+       shutdown(p1, SHUT_WR);
+
+       ev.events = EPOLLIN;
+       ev.data.fd = c1;
+
+       epollfd = epoll_create1(0);
+       if (!ASSERT_GT(epollfd, -1, "epoll_create(0)"))
+               goto out_close;
+       err = epoll_ctl(epollfd, EPOLL_CTL_ADD, c1, &ev);
+       if (!ASSERT_OK(err, "epoll_ctl(EPOLL_CTL_ADD)"))
+               goto out_close;
+       err = epoll_wait(epollfd, events, MAX_EVENTS, -1);
+       if (!ASSERT_EQ(err, 1, "epoll_wait(fd)"))
+               goto out_close;
+
+       n = recv(c1, &b, 1, SOCK_NONBLOCK);
+       ASSERT_EQ(n, 0, "recv_timeout(fin)");
+out_close:
+       close(c1);
+       close(p1);
+out:
+       test_sockmap_pass_prog__destroy(skel);
+}
+
+static void test_sockmap_skb_verdict_fionread(bool pass_prog)
+{
+       int expected, zero = 0, sent, recvd, avail;
+       int err, map, verdict, s, c0, c1, p0, p1;
+       struct test_sockmap_pass_prog *pass;
+       struct test_sockmap_drop_prog *drop;
+       char buf[256] = "0123456789";
+
+       if (pass_prog) {
+               pass = test_sockmap_pass_prog__open_and_load();
+               if (!ASSERT_OK_PTR(pass, "open_and_load"))
+                       return;
+               verdict = bpf_program__fd(pass->progs.prog_skb_verdict);
+               map = bpf_map__fd(pass->maps.sock_map_rx);
+               expected = sizeof(buf);
+       } else {
+               drop = test_sockmap_drop_prog__open_and_load();
+               if (!ASSERT_OK_PTR(drop, "open_and_load"))
+                       return;
+               verdict = bpf_program__fd(drop->progs.prog_skb_verdict);
+               map = bpf_map__fd(drop->maps.sock_map_rx);
+               /* On drop data is consumed immediately and copied_seq inc'd */
+               expected = 0;
+       }
+
+
+       err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
+       if (!ASSERT_OK(err, "bpf_prog_attach"))
+               goto out;
+
+       s = socket_loopback(AF_INET, SOCK_STREAM);
+       if (!ASSERT_GT(s, -1, "socket_loopback(s)"))
+               goto out;
+       err = create_socket_pairs(s, AF_INET, SOCK_STREAM, &c0, &c1, &p0, &p1);
+       if (!ASSERT_OK(err, "create_socket_pairs(s)"))
+               goto out;
+
+       err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
+       if (!ASSERT_OK(err, "bpf_map_update_elem(c1)"))
+               goto out_close;
+
+       sent = xsend(p1, &buf, sizeof(buf), 0);
+       ASSERT_EQ(sent, sizeof(buf), "xsend(p0)");
+       err = ioctl(c1, FIONREAD, &avail);
+       ASSERT_OK(err, "ioctl(FIONREAD) error");
+       ASSERT_EQ(avail, expected, "ioctl(FIONREAD)");
+       /* On DROP test there will be no data to read */
+       if (pass_prog) {
+               recvd = recv_timeout(c1, &buf, sizeof(buf), SOCK_NONBLOCK, IO_TIMEOUT_SEC);
+               ASSERT_EQ(recvd, sizeof(buf), "recv_timeout(c0)");
+       }
+
+out_close:
+       close(c0);
+       close(p0);
+       close(c1);
+       close(p1);
+out:
+       if (pass_prog)
+               test_sockmap_pass_prog__destroy(pass);
+       else
+               test_sockmap_drop_prog__destroy(drop);
+}
+
 void test_sockmap_basic(void)
 {
        if (test__start_subtest("sockmap create_update_free"))
@@ -384,4 +509,10 @@ void test_sockmap_basic(void)
                test_sockmap_progs_query(BPF_SK_SKB_STREAM_VERDICT);
        if (test__start_subtest("sockmap skb_verdict progs query"))
                test_sockmap_progs_query(BPF_SK_SKB_VERDICT);
+       if (test__start_subtest("sockmap skb_verdict shutdown"))
+               test_sockmap_skb_verdict_shutdown();
+       if (test__start_subtest("sockmap skb_verdict fionread"))
+               test_sockmap_skb_verdict_fionread(true);
+       if (test__start_subtest("sockmap skb_verdict fionread on drop"))
+               test_sockmap_skb_verdict_fionread(false);
 }
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h b/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h
new file mode 100644 (file)
index 0000000..d126654
--- /dev/null
@@ -0,0 +1,390 @@
+#ifndef __SOCKMAP_HELPERS__
+#define __SOCKMAP_HELPERS__
+
+#include <linux/vm_sockets.h>
+
+#define IO_TIMEOUT_SEC 30
+#define MAX_STRERR_LEN 256
+#define MAX_TEST_NAME 80
+
+/* workaround for older vm_sockets.h */
+#ifndef VMADDR_CID_LOCAL
+#define VMADDR_CID_LOCAL 1
+#endif
+
+#define __always_unused        __attribute__((__unused__))
+
+#define _FAIL(errnum, fmt...)                                                  \
+       ({                                                                     \
+               error_at_line(0, (errnum), __func__, __LINE__, fmt);           \
+               CHECK_FAIL(true);                                              \
+       })
+#define FAIL(fmt...) _FAIL(0, fmt)
+#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
+#define FAIL_LIBBPF(err, msg)                                                  \
+       ({                                                                     \
+               char __buf[MAX_STRERR_LEN];                                    \
+               libbpf_strerror((err), __buf, sizeof(__buf));                  \
+               FAIL("%s: %s", (msg), __buf);                                  \
+       })
+
+/* Wrappers that fail the test on error and report it. */
+
+#define xaccept_nonblock(fd, addr, len)                                        \
+       ({                                                                     \
+               int __ret =                                                    \
+                       accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC);   \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("accept");                                  \
+               __ret;                                                         \
+       })
+
+#define xbind(fd, addr, len)                                                   \
+       ({                                                                     \
+               int __ret = bind((fd), (addr), (len));                         \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("bind");                                    \
+               __ret;                                                         \
+       })
+
+#define xclose(fd)                                                             \
+       ({                                                                     \
+               int __ret = close((fd));                                       \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("close");                                   \
+               __ret;                                                         \
+       })
+
+#define xconnect(fd, addr, len)                                                \
+       ({                                                                     \
+               int __ret = connect((fd), (addr), (len));                      \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("connect");                                 \
+               __ret;                                                         \
+       })
+
+#define xgetsockname(fd, addr, len)                                            \
+       ({                                                                     \
+               int __ret = getsockname((fd), (addr), (len));                  \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("getsockname");                             \
+               __ret;                                                         \
+       })
+
+#define xgetsockopt(fd, level, name, val, len)                                 \
+       ({                                                                     \
+               int __ret = getsockopt((fd), (level), (name), (val), (len));   \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("getsockopt(" #name ")");                   \
+               __ret;                                                         \
+       })
+
+#define xlisten(fd, backlog)                                                   \
+       ({                                                                     \
+               int __ret = listen((fd), (backlog));                           \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("listen");                                  \
+               __ret;                                                         \
+       })
+
+#define xsetsockopt(fd, level, name, val, len)                                 \
+       ({                                                                     \
+               int __ret = setsockopt((fd), (level), (name), (val), (len));   \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("setsockopt(" #name ")");                   \
+               __ret;                                                         \
+       })
+
+#define xsend(fd, buf, len, flags)                                             \
+       ({                                                                     \
+               ssize_t __ret = send((fd), (buf), (len), (flags));             \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("send");                                    \
+               __ret;                                                         \
+       })
+
+#define xrecv_nonblock(fd, buf, len, flags)                                    \
+       ({                                                                     \
+               ssize_t __ret = recv_timeout((fd), (buf), (len), (flags),      \
+                                            IO_TIMEOUT_SEC);                  \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("recv");                                    \
+               __ret;                                                         \
+       })
+
+#define xsocket(family, sotype, flags)                                         \
+       ({                                                                     \
+               int __ret = socket(family, sotype, flags);                     \
+               if (__ret == -1)                                               \
+                       FAIL_ERRNO("socket");                                  \
+               __ret;                                                         \
+       })
+
+#define xbpf_map_delete_elem(fd, key)                                          \
+       ({                                                                     \
+               int __ret = bpf_map_delete_elem((fd), (key));                  \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("map_delete");                              \
+               __ret;                                                         \
+       })
+
+#define xbpf_map_lookup_elem(fd, key, val)                                     \
+       ({                                                                     \
+               int __ret = bpf_map_lookup_elem((fd), (key), (val));           \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("map_lookup");                              \
+               __ret;                                                         \
+       })
+
+#define xbpf_map_update_elem(fd, key, val, flags)                              \
+       ({                                                                     \
+               int __ret = bpf_map_update_elem((fd), (key), (val), (flags));  \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("map_update");                              \
+               __ret;                                                         \
+       })
+
+#define xbpf_prog_attach(prog, target, type, flags)                            \
+       ({                                                                     \
+               int __ret =                                                    \
+                       bpf_prog_attach((prog), (target), (type), (flags));    \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("prog_attach(" #type ")");                  \
+               __ret;                                                         \
+       })
+
+#define xbpf_prog_detach2(prog, target, type)                                  \
+       ({                                                                     \
+               int __ret = bpf_prog_detach2((prog), (target), (type));        \
+               if (__ret < 0)                                               \
+                       FAIL_ERRNO("prog_detach2(" #type ")");                 \
+               __ret;                                                         \
+       })
+
+#define xpthread_create(thread, attr, func, arg)                               \
+       ({                                                                     \
+               int __ret = pthread_create((thread), (attr), (func), (arg));   \
+               errno = __ret;                                                 \
+               if (__ret)                                                     \
+                       FAIL_ERRNO("pthread_create");                          \
+               __ret;                                                         \
+       })
+
+#define xpthread_join(thread, retval)                                          \
+       ({                                                                     \
+               int __ret = pthread_join((thread), (retval));                  \
+               errno = __ret;                                                 \
+               if (__ret)                                                     \
+                       FAIL_ERRNO("pthread_join");                            \
+               __ret;                                                         \
+       })
+
+static inline int poll_read(int fd, unsigned int timeout_sec)
+{
+       struct timeval timeout = { .tv_sec = timeout_sec };
+       fd_set rfds;
+       int r;
+
+       FD_ZERO(&rfds);
+       FD_SET(fd, &rfds);
+
+       r = select(fd + 1, &rfds, NULL, NULL, &timeout);
+       if (r == 0)
+               errno = ETIME;
+
+       return r == 1 ? 0 : -1;
+}
+
+static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
+                                unsigned int timeout_sec)
+{
+       if (poll_read(fd, timeout_sec))
+               return -1;
+
+       return accept(fd, addr, len);
+}
+
+static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
+                              unsigned int timeout_sec)
+{
+       if (poll_read(fd, timeout_sec))
+               return -1;
+
+       return recv(fd, buf, len, flags);
+}
+
+static inline void init_addr_loopback4(struct sockaddr_storage *ss,
+                                      socklen_t *len)
+{
+       struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
+
+       addr4->sin_family = AF_INET;
+       addr4->sin_port = 0;
+       addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       *len = sizeof(*addr4);
+}
+
+static inline void init_addr_loopback6(struct sockaddr_storage *ss,
+                                      socklen_t *len)
+{
+       struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
+
+       addr6->sin6_family = AF_INET6;
+       addr6->sin6_port = 0;
+       addr6->sin6_addr = in6addr_loopback;
+       *len = sizeof(*addr6);
+}
+
+static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
+                                           socklen_t *len)
+{
+       struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
+
+       addr->svm_family = AF_VSOCK;
+       addr->svm_port = VMADDR_PORT_ANY;
+       addr->svm_cid = VMADDR_CID_LOCAL;
+       *len = sizeof(*addr);
+}
+
+static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
+                                     socklen_t *len)
+{
+       switch (family) {
+       case AF_INET:
+               init_addr_loopback4(ss, len);
+               return;
+       case AF_INET6:
+               init_addr_loopback6(ss, len);
+               return;
+       case AF_VSOCK:
+               init_addr_loopback_vsock(ss, len);
+               return;
+       default:
+               FAIL("unsupported address family %d", family);
+       }
+}
+
+static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
+{
+       return (struct sockaddr *)ss;
+}
+
+static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
+{
+       u64 value;
+       u32 key;
+       int err;
+
+       key = 0;
+       value = fd1;
+       err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
+       if (err)
+               return err;
+
+       key = 1;
+       value = fd2;
+       return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
+}
+
+static inline int create_pair(int s, int family, int sotype, int *c, int *p)
+{
+       struct sockaddr_storage addr;
+       socklen_t len;
+       int err = 0;
+
+       len = sizeof(addr);
+       err = xgetsockname(s, sockaddr(&addr), &len);
+       if (err)
+               return err;
+
+       *c = xsocket(family, sotype, 0);
+       if (*c < 0)
+               return errno;
+       err = xconnect(*c, sockaddr(&addr), len);
+       if (err) {
+               err = errno;
+               goto close_cli0;
+       }
+
+       *p = xaccept_nonblock(s, NULL, NULL);
+       if (*p < 0) {
+               err = errno;
+               goto close_cli0;
+       }
+       return err;
+close_cli0:
+       close(*c);
+       return err;
+}
+
+static inline int create_socket_pairs(int s, int family, int sotype,
+                                     int *c0, int *c1, int *p0, int *p1)
+{
+       int err;
+
+       err = create_pair(s, family, sotype, c0, p0);
+       if (err)
+               return err;
+
+       err = create_pair(s, family, sotype, c1, p1);
+       if (err) {
+               close(*c0);
+               close(*p0);
+       }
+       return err;
+}
+
+static inline int enable_reuseport(int s, int progfd)
+{
+       int err, one = 1;
+
+       err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+       if (err)
+               return -1;
+       err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
+                         sizeof(progfd));
+       if (err)
+               return -1;
+
+       return 0;
+}
+
+static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
+{
+       struct sockaddr_storage addr;
+       socklen_t len;
+       int err, s;
+
+       init_addr_loopback(family, &addr, &len);
+
+       s = xsocket(family, sotype, 0);
+       if (s == -1)
+               return -1;
+
+       if (progfd >= 0)
+               enable_reuseport(s, progfd);
+
+       err = xbind(s, sockaddr(&addr), len);
+       if (err)
+               goto close;
+
+       if (sotype & SOCK_DGRAM)
+               return s;
+
+       err = xlisten(s, SOMAXCONN);
+       if (err)
+               goto close;
+
+       return s;
+close:
+       xclose(s);
+       return -1;
+}
+
+static inline int socket_loopback(int family, int sotype)
+{
+       return socket_loopback_reuseport(family, sotype, -1);
+}
+
+
+#endif // __SOCKMAP_HELPERS__
index 141c1e5..b4f6f3a 100644 (file)
 #include <unistd.h>
 #include <linux/vm_sockets.h>
 
-/* workaround for older vm_sockets.h */
-#ifndef VMADDR_CID_LOCAL
-#define VMADDR_CID_LOCAL 1
-#endif
-
 #include <bpf/bpf.h>
 #include <bpf/libbpf.h>
 
 #include "test_progs.h"
 #include "test_sockmap_listen.skel.h"
 
-#define IO_TIMEOUT_SEC 30
-#define MAX_STRERR_LEN 256
-#define MAX_TEST_NAME 80
-
-#define __always_unused        __attribute__((__unused__))
-
-#define _FAIL(errnum, fmt...)                                                  \
-       ({                                                                     \
-               error_at_line(0, (errnum), __func__, __LINE__, fmt);           \
-               CHECK_FAIL(true);                                              \
-       })
-#define FAIL(fmt...) _FAIL(0, fmt)
-#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
-#define FAIL_LIBBPF(err, msg)                                                  \
-       ({                                                                     \
-               char __buf[MAX_STRERR_LEN];                                    \
-               libbpf_strerror((err), __buf, sizeof(__buf));                  \
-               FAIL("%s: %s", (msg), __buf);                                  \
-       })
-
-/* Wrappers that fail the test on error and report it. */
-
-#define xaccept_nonblock(fd, addr, len)                                        \
-       ({                                                                     \
-               int __ret =                                                    \
-                       accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC);   \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("accept");                                  \
-               __ret;                                                         \
-       })
-
-#define xbind(fd, addr, len)                                                   \
-       ({                                                                     \
-               int __ret = bind((fd), (addr), (len));                         \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("bind");                                    \
-               __ret;                                                         \
-       })
-
-#define xclose(fd)                                                             \
-       ({                                                                     \
-               int __ret = close((fd));                                       \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("close");                                   \
-               __ret;                                                         \
-       })
-
-#define xconnect(fd, addr, len)                                                \
-       ({                                                                     \
-               int __ret = connect((fd), (addr), (len));                      \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("connect");                                 \
-               __ret;                                                         \
-       })
-
-#define xgetsockname(fd, addr, len)                                            \
-       ({                                                                     \
-               int __ret = getsockname((fd), (addr), (len));                  \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("getsockname");                             \
-               __ret;                                                         \
-       })
-
-#define xgetsockopt(fd, level, name, val, len)                                 \
-       ({                                                                     \
-               int __ret = getsockopt((fd), (level), (name), (val), (len));   \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("getsockopt(" #name ")");                   \
-               __ret;                                                         \
-       })
-
-#define xlisten(fd, backlog)                                                   \
-       ({                                                                     \
-               int __ret = listen((fd), (backlog));                           \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("listen");                                  \
-               __ret;                                                         \
-       })
-
-#define xsetsockopt(fd, level, name, val, len)                                 \
-       ({                                                                     \
-               int __ret = setsockopt((fd), (level), (name), (val), (len));   \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("setsockopt(" #name ")");                   \
-               __ret;                                                         \
-       })
-
-#define xsend(fd, buf, len, flags)                                             \
-       ({                                                                     \
-               ssize_t __ret = send((fd), (buf), (len), (flags));             \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("send");                                    \
-               __ret;                                                         \
-       })
-
-#define xrecv_nonblock(fd, buf, len, flags)                                    \
-       ({                                                                     \
-               ssize_t __ret = recv_timeout((fd), (buf), (len), (flags),      \
-                                            IO_TIMEOUT_SEC);                  \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("recv");                                    \
-               __ret;                                                         \
-       })
-
-#define xsocket(family, sotype, flags)                                         \
-       ({                                                                     \
-               int __ret = socket(family, sotype, flags);                     \
-               if (__ret == -1)                                               \
-                       FAIL_ERRNO("socket");                                  \
-               __ret;                                                         \
-       })
-
-#define xbpf_map_delete_elem(fd, key)                                          \
-       ({                                                                     \
-               int __ret = bpf_map_delete_elem((fd), (key));                  \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("map_delete");                              \
-               __ret;                                                         \
-       })
-
-#define xbpf_map_lookup_elem(fd, key, val)                                     \
-       ({                                                                     \
-               int __ret = bpf_map_lookup_elem((fd), (key), (val));           \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("map_lookup");                              \
-               __ret;                                                         \
-       })
-
-#define xbpf_map_update_elem(fd, key, val, flags)                              \
-       ({                                                                     \
-               int __ret = bpf_map_update_elem((fd), (key), (val), (flags));  \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("map_update");                              \
-               __ret;                                                         \
-       })
-
-#define xbpf_prog_attach(prog, target, type, flags)                            \
-       ({                                                                     \
-               int __ret =                                                    \
-                       bpf_prog_attach((prog), (target), (type), (flags));    \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("prog_attach(" #type ")");                  \
-               __ret;                                                         \
-       })
-
-#define xbpf_prog_detach2(prog, target, type)                                  \
-       ({                                                                     \
-               int __ret = bpf_prog_detach2((prog), (target), (type));        \
-               if (__ret < 0)                                               \
-                       FAIL_ERRNO("prog_detach2(" #type ")");                 \
-               __ret;                                                         \
-       })
-
-#define xpthread_create(thread, attr, func, arg)                               \
-       ({                                                                     \
-               int __ret = pthread_create((thread), (attr), (func), (arg));   \
-               errno = __ret;                                                 \
-               if (__ret)                                                     \
-                       FAIL_ERRNO("pthread_create");                          \
-               __ret;                                                         \
-       })
-
-#define xpthread_join(thread, retval)                                          \
-       ({                                                                     \
-               int __ret = pthread_join((thread), (retval));                  \
-               errno = __ret;                                                 \
-               if (__ret)                                                     \
-                       FAIL_ERRNO("pthread_join");                            \
-               __ret;                                                         \
-       })
-
-static int poll_read(int fd, unsigned int timeout_sec)
-{
-       struct timeval timeout = { .tv_sec = timeout_sec };
-       fd_set rfds;
-       int r;
-
-       FD_ZERO(&rfds);
-       FD_SET(fd, &rfds);
-
-       r = select(fd + 1, &rfds, NULL, NULL, &timeout);
-       if (r == 0)
-               errno = ETIME;
-
-       return r == 1 ? 0 : -1;
-}
-
-static int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
-                         unsigned int timeout_sec)
-{
-       if (poll_read(fd, timeout_sec))
-               return -1;
-
-       return accept(fd, addr, len);
-}
-
-static int recv_timeout(int fd, void *buf, size_t len, int flags,
-                       unsigned int timeout_sec)
-{
-       if (poll_read(fd, timeout_sec))
-               return -1;
-
-       return recv(fd, buf, len, flags);
-}
-
-static void init_addr_loopback4(struct sockaddr_storage *ss, socklen_t *len)
-{
-       struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
-
-       addr4->sin_family = AF_INET;
-       addr4->sin_port = 0;
-       addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       *len = sizeof(*addr4);
-}
-
-static void init_addr_loopback6(struct sockaddr_storage *ss, socklen_t *len)
-{
-       struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
-
-       addr6->sin6_family = AF_INET6;
-       addr6->sin6_port = 0;
-       addr6->sin6_addr = in6addr_loopback;
-       *len = sizeof(*addr6);
-}
-
-static void init_addr_loopback_vsock(struct sockaddr_storage *ss, socklen_t *len)
-{
-       struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
-
-       addr->svm_family = AF_VSOCK;
-       addr->svm_port = VMADDR_PORT_ANY;
-       addr->svm_cid = VMADDR_CID_LOCAL;
-       *len = sizeof(*addr);
-}
-
-static void init_addr_loopback(int family, struct sockaddr_storage *ss,
-                              socklen_t *len)
-{
-       switch (family) {
-       case AF_INET:
-               init_addr_loopback4(ss, len);
-               return;
-       case AF_INET6:
-               init_addr_loopback6(ss, len);
-               return;
-       case AF_VSOCK:
-               init_addr_loopback_vsock(ss, len);
-               return;
-       default:
-               FAIL("unsupported address family %d", family);
-       }
-}
-
-static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
-{
-       return (struct sockaddr *)ss;
-}
-
-static int enable_reuseport(int s, int progfd)
-{
-       int err, one = 1;
-
-       err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
-       if (err)
-               return -1;
-       err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
-                         sizeof(progfd));
-       if (err)
-               return -1;
-
-       return 0;
-}
-
-static int socket_loopback_reuseport(int family, int sotype, int progfd)
-{
-       struct sockaddr_storage addr;
-       socklen_t len;
-       int err, s;
-
-       init_addr_loopback(family, &addr, &len);
-
-       s = xsocket(family, sotype, 0);
-       if (s == -1)
-               return -1;
-
-       if (progfd >= 0)
-               enable_reuseport(s, progfd);
-
-       err = xbind(s, sockaddr(&addr), len);
-       if (err)
-               goto close;
-
-       if (sotype & SOCK_DGRAM)
-               return s;
-
-       err = xlisten(s, SOMAXCONN);
-       if (err)
-               goto close;
-
-       return s;
-close:
-       xclose(s);
-       return -1;
-}
-
-static int socket_loopback(int family, int sotype)
-{
-       return socket_loopback_reuseport(family, sotype, -1);
-}
+#include "sockmap_helpers.h"
 
 static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused,
                                int family, int sotype, int mapfd)
@@ -984,31 +671,12 @@ static const char *redir_mode_str(enum redir_mode mode)
        }
 }
 
-static int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
-{
-       u64 value;
-       u32 key;
-       int err;
-
-       key = 0;
-       value = fd1;
-       err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
-       if (err)
-               return err;
-
-       key = 1;
-       value = fd2;
-       return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
-}
-
 static void redir_to_connected(int family, int sotype, int sock_mapfd,
                               int verd_mapfd, enum redir_mode mode)
 {
        const char *log_prefix = redir_mode_str(mode);
-       struct sockaddr_storage addr;
        int s, c0, c1, p0, p1;
        unsigned int pass;
-       socklen_t len;
        int err, n;
        u32 key;
        char b;
@@ -1019,36 +687,13 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
        if (s < 0)
                return;
 
-       len = sizeof(addr);
-       err = xgetsockname(s, sockaddr(&addr), &len);
+       err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
        if (err)
                goto close_srv;
 
-       c0 = xsocket(family, sotype, 0);
-       if (c0 < 0)
-               goto close_srv;
-       err = xconnect(c0, sockaddr(&addr), len);
-       if (err)
-               goto close_cli0;
-
-       p0 = xaccept_nonblock(s, NULL, NULL);
-       if (p0 < 0)
-               goto close_cli0;
-
-       c1 = xsocket(family, sotype, 0);
-       if (c1 < 0)
-               goto close_peer0;
-       err = xconnect(c1, sockaddr(&addr), len);
-       if (err)
-               goto close_cli1;
-
-       p1 = xaccept_nonblock(s, NULL, NULL);
-       if (p1 < 0)
-               goto close_cli1;
-
        err = add_to_sockmap(sock_mapfd, p0, p1);
        if (err)
-               goto close_peer1;
+               goto close;
 
        n = write(mode == REDIR_INGRESS ? c1 : p1, "a", 1);
        if (n < 0)
@@ -1056,12 +701,12 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
        if (n == 0)
                FAIL("%s: incomplete write", log_prefix);
        if (n < 1)
-               goto close_peer1;
+               goto close;
 
        key = SK_PASS;
        err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass);
        if (err)
-               goto close_peer1;
+               goto close;
        if (pass != 1)
                FAIL("%s: want pass count 1, have %d", log_prefix, pass);
        n = recv_timeout(c0, &b, 1, 0, IO_TIMEOUT_SEC);
@@ -1070,13 +715,10 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
        if (n == 0)
                FAIL("%s: incomplete recv", log_prefix);
 
-close_peer1:
+close:
        xclose(p1);
-close_cli1:
        xclose(c1);
-close_peer0:
        xclose(p0);
-close_cli0:
        xclose(c0);
 close_srv:
        xclose(s);
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c b/tools/testing/selftests/bpf/progs/test_sockmap_drop_prog.c
new file mode 100644 (file)
index 0000000..2931480
--- /dev/null
@@ -0,0 +1,32 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_rx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_tx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_msg SEC(".maps");
+
+SEC("sk_skb")
+int prog_skb_verdict(struct __sk_buff *skb)
+{
+       return SK_DROP;
+}
+
+char _license[] SEC("license") = "GPL";
index baf9ebc..99d2ea9 100644 (file)
@@ -191,7 +191,7 @@ SEC("sockops")
 int bpf_sockmap(struct bpf_sock_ops *skops)
 {
        __u32 lport, rport;
-       int op, err, ret;
+       int op, ret;
 
        op = (int) skops->op;
 
@@ -203,10 +203,10 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
                if (lport == 10000) {
                        ret = 1;
 #ifdef SOCKMAP
-                       err = bpf_sock_map_update(skops, &sock_map, &ret,
+                       bpf_sock_map_update(skops, &sock_map, &ret,
                                                  BPF_NOEXIST);
 #else
-                       err = bpf_sock_hash_update(skops, &sock_map, &ret,
+                       bpf_sock_hash_update(skops, &sock_map, &ret,
                                                   BPF_NOEXIST);
 #endif
                }
@@ -218,10 +218,10 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
                if (bpf_ntohl(rport) == 10001) {
                        ret = 10;
 #ifdef SOCKMAP
-                       err = bpf_sock_map_update(skops, &sock_map, &ret,
+                       bpf_sock_map_update(skops, &sock_map, &ret,
                                                  BPF_NOEXIST);
 #else
-                       err = bpf_sock_hash_update(skops, &sock_map, &ret,
+                       bpf_sock_hash_update(skops, &sock_map, &ret,
                                                   BPF_NOEXIST);
 #endif
                }
@@ -230,8 +230,6 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
                break;
        }
 
-       __sink(err);
-
        return 0;
 }
 
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c b/tools/testing/selftests/bpf/progs/test_sockmap_pass_prog.c
new file mode 100644 (file)
index 0000000..1d86a71
--- /dev/null
@@ -0,0 +1,32 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_rx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_tx SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_SOCKMAP);
+       __uint(max_entries, 20);
+       __type(key, int);
+       __type(value, int);
+} sock_map_msg SEC(".maps");
+
+SEC("sk_skb")
+int prog_skb_verdict(struct __sk_buff *skb)
+{
+       return SK_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack-legacy.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack-legacy.tc
new file mode 100644 (file)
index 0000000..d0cd91a
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: event trigger - test inter-event histogram trigger trace action with dynamic string param (legacy stack)
+# requires: set_event synthetic_events events/sched/sched_process_exec/hist "long[] stack' >> synthetic_events":README
+
+fail() { #msg
+    echo $1
+    exit_fail
+}
+
+echo "Test create synthetic event with stack"
+
+# Test the old stacktrace keyword (for backward compatibility)
+echo 's:wake_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
+echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace  if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
+echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(wake_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
+echo 1 > events/synthetic/wake_lat/enable
+sleep 1
+
+if ! grep -q "=>.*sched" trace; then
+    fail "Failed to create synthetic event with stack"
+fi
+
+exit 0
index 755dbe9..8f1cc9a 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: event trigger - test inter-event histogram trigger trace action with dynamic string param
-# requires: set_event synthetic_events events/sched/sched_process_exec/hist "long[]' >> synthetic_events":README
+# requires: set_event synthetic_events events/sched/sched_process_exec/hist "can be any field, or the special string 'common_stacktrace'":README
 
 fail() { #msg
     echo $1
@@ -10,9 +10,8 @@ fail() { #msg
 
 echo "Test create synthetic event with stack"
 
-
 echo 's:wake_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
-echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace  if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
+echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=common_stacktrace  if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
 echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(wake_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
 echo 1 > events/synthetic/wake_lat/enable
 sleep 1
index 9f539d4..fa2ce2b 100755 (executable)
@@ -389,6 +389,9 @@ create_chip chip
 create_bank chip bank
 set_num_lines chip bank 8
 enable_chip chip
+DEVNAME=`configfs_dev_name chip`
+CHIPNAME=`configfs_chip_name chip bank`
+SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
 $BASE_DIR/gpio-mockup-cdev -b pull-up /dev/`configfs_chip_name chip bank` 0
 test `cat $SYSFS_PATH` = "1" || fail "bias setting does not work"
 remove_chip chip
index 7da8ec8..35d89df 100755 (executable)
@@ -68,7 +68,7 @@ setup()
 cleanup()
 {
        $IP link del dev dummy0 &> /dev/null
-       ip netns del ns1
+       ip netns del ns1 &> /dev/null
        ip netns del ns2 &> /dev/null
 }
 
index 43a7236..7b936a9 100644 (file)
@@ -9,7 +9,7 @@ TEST_PROGS := mptcp_connect.sh pm_netlink.sh mptcp_join.sh diag.sh \
 
 TEST_GEN_FILES = mptcp_connect pm_nl_ctl mptcp_sockopt mptcp_inq
 
-TEST_FILES := settings
+TEST_FILES := mptcp_lib.sh settings
 
 EXTRA_CLEAN := *.pcap
 
index ef628b1..4eacdb1 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 sec=$(date +%s)
 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
 ns="ns1-$rndh"
@@ -31,6 +33,8 @@ cleanup()
        ip netns del $ns
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index a43d3e2..c1f7bac 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 time_start=$(date +%s)
 
 optstring="S:R:d:e:l:r:h4cm:f:tC"
@@ -141,6 +143,8 @@ cleanup()
        done
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index 26310c1..96f6317 100755 (executable)
@@ -10,6 +10,8 @@
 # because it's invoked by variable name, see how the "tests" array is used
 #shellcheck disable=SC2317
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 ret=0
 sin=""
 sinfail=""
@@ -17,6 +19,7 @@ sout=""
 cin=""
 cinfail=""
 cinsent=""
+tmpfile=""
 cout=""
 capout=""
 ns1=""
@@ -136,6 +139,8 @@ cleanup_partial()
 
 check_tools()
 {
+       mptcp_lib_check_mptcp
+
        if ! ip -Version &> /dev/null; then
                echo "SKIP: Could not run test without ip tool"
                exit $ksft_skip
@@ -175,6 +180,7 @@ cleanup()
 {
        rm -f "$cin" "$cout" "$sinfail"
        rm -f "$sin" "$sout" "$cinsent" "$cinfail"
+       rm -f "$tmpfile"
        rm -rf $evts_ns1 $evts_ns2
        cleanup_partial
 }
@@ -383,9 +389,16 @@ check_transfer()
                        fail_test
                        return 1
                fi
-               bytes="--bytes=${bytes}"
+
+               # note: BusyBox's "cmp" command doesn't support --bytes
+               tmpfile=$(mktemp)
+               head --bytes="$bytes" "$in" > "$tmpfile"
+               mv "$tmpfile" "$in"
+               head --bytes="$bytes" "$out" > "$tmpfile"
+               mv "$tmpfile" "$out"
+               tmpfile=""
        fi
-       cmp -l "$in" "$out" ${bytes} | while read -r i a b; do
+       cmp -l "$in" "$out" | while read -r i a b; do
                local sum=$((0${a} + 0${b}))
                if [ $check_invert -eq 0 ] || [ $sum -ne $((0xff)) ]; then
                        echo "[ FAIL ] $what does not match (in, out):"
diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh
new file mode 100644 (file)
index 0000000..3286536
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+readonly KSFT_FAIL=1
+readonly KSFT_SKIP=4
+
+# SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES env var can be set when validating all
+# features using the last version of the kernel and the selftests to make sure
+# a test is not being skipped by mistake.
+mptcp_lib_expect_all_features() {
+       [ "${SELFTESTS_MPTCP_LIB_EXPECT_ALL_FEATURES:-}" = "1" ]
+}
+
+# $1: msg
+mptcp_lib_fail_if_expected_feature() {
+       if mptcp_lib_expect_all_features; then
+               echo "ERROR: missing feature: ${*}"
+               exit ${KSFT_FAIL}
+       fi
+
+       return 1
+}
+
+# $1: file
+mptcp_lib_has_file() {
+       local f="${1}"
+
+       if [ -f "${f}" ]; then
+               return 0
+       fi
+
+       mptcp_lib_fail_if_expected_feature "${f} file not found"
+}
+
+mptcp_lib_check_mptcp() {
+       if ! mptcp_lib_has_file "/proc/sys/net/mptcp/enabled"; then
+               echo "SKIP: MPTCP support is not available"
+               exit ${KSFT_SKIP}
+       fi
+}
index 1b70c0a..ff5adbb 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 ret=0
 sin=""
 sout=""
@@ -84,6 +86,8 @@ cleanup()
        rm -f "$sin" "$sout"
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index 89839d1..32f7533 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 ksft_skip=4
 ret=0
 
@@ -34,6 +36,8 @@ cleanup()
        ip netns del $ns1
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index 9f22f7e..36a3c9d 100755 (executable)
@@ -1,6 +1,8 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
 sec=$(date +%s)
 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
 ns1="ns1-$rndh"
@@ -34,6 +36,8 @@ cleanup()
        done
 }
 
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Could not run test without ip tool"
index b1eb7bc..8092399 100755 (executable)
@@ -1,6 +1,10 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+. "$(dirname "${0}")/mptcp_lib.sh"
+
+mptcp_lib_check_mptcp
+
 ip -Version > /dev/null 2>&1
 if [ $? -ne 0 ];then
        echo "SKIP: Cannot not run test without ip tool"