Merge branch 'for-5.4/apple' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Sun, 22 Sep 2019 20:29:00 +0000 (22:29 +0200)
committerJiri Kosina <jkosina@suse.cz>
Sun, 22 Sep 2019 20:29:00 +0000 (22:29 +0200)
- stuck 'fn' key fix for hid-apple from Joao Moreno

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
771 files changed:
Documentation/admin-guide/sysctl/net.rst
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
Documentation/devicetree/bindings/riscv/cpus.txt [deleted file]
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/devicetree/bindings/riscv/sifive.yaml
Documentation/filesystems/cifs/TODO
Documentation/networking/tls-offload.rst
Documentation/networking/tuntap.txt
MAINTAINERS
Makefile
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/signal.c
arch/arm/kvm/coproc.c
arch/arm/mach-ep93xx/crunch.c
arch/arm/mach-tegra/reset.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/plat-omap/dma.c
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/ftrace.c
arch/arm64/kernel/traps.c
arch/arm64/kvm/hyp/debug-sr.c
arch/arm64/kvm/regmap.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/dma-mapping.c
arch/mips/cavium-octeon/octeon-usb.c
arch/mips/kernel/cacheinfo.c
arch/mips/kernel/i8253.c
arch/mips/kvm/emulate.c
arch/mips/kvm/mips.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/ops-bcm63xx.c
arch/parisc/math-emu/Makefile
arch/powerpc/Kconfig
arch/powerpc/include/asm/cache.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/dma-common.c [deleted file]
arch/powerpc/kvm/powerpc.c
arch/riscv/configs/defconfig
arch/riscv/configs/rv32_defconfig
arch/riscv/include/asm/switch_to.h
arch/riscv/include/asm/tlbflush.h
arch/riscv/kernel/process.c
arch/riscv/lib/Makefile
arch/riscv/lib/delay.c
arch/riscv/lib/udivdi3.S [deleted file]
arch/s390/boot/ipl_parm.c
arch/s390/kernel/dumpstack.c
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/setup.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/kvm-s390.c
arch/s390/mm/dump_pagetables.c
arch/s390/scripts/Makefile.chkbss
arch/sh/kernel/disassemble.c
arch/sh/kernel/hw_breakpoint.c
arch/x86/boot/string.c
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/cpu/mtrr/cyrix.c
arch/x86/kernel/cpu/umwait.c
arch/x86/kernel/kvm.c
arch/x86/kernel/ptrace.c
arch/x86/kvm/debugfs.c
arch/x86/kvm/lapic.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/cpu.c
arch/x86/math-emu/errors.c
arch/x86/math-emu/fpu_trig.c
arch/x86/net/bpf_jit_comp.c
arch/x86/purgatory/Makefile
arch/x86/purgatory/purgatory.c
arch/x86/purgatory/string.c [deleted file]
arch/xtensa/kernel/setup.c
block/bfq-iosched.c
block/blk-mq.c
block/blk-sysfs.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_rb532_cf.c
drivers/atm/iphase.c
drivers/auxdisplay/Kconfig
drivers/auxdisplay/charlcd.c
drivers/auxdisplay/charlcd.h [new file with mode: 0644]
drivers/auxdisplay/hd44780.c
drivers/auxdisplay/panel.c
drivers/base/core.c
drivers/base/platform.c
drivers/base/regmap/Kconfig
drivers/block/aoe/aoedev.c
drivers/block/drbd/drbd_main.c
drivers/block/loop.c
drivers/block/xen-blkback/xenbus.c
drivers/bluetooth/btqca.c
drivers/bluetooth/btqca.h
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_qca.c
drivers/clk/clk.c
drivers/clk/samsung/clk-exynos5-subcmu.c
drivers/clk/samsung/clk-exynos5-subcmu.h
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/socfpga/clk-periph-s10.c
drivers/clocksource/timer-riscv.c
drivers/cpufreq/cpufreq.c
drivers/crypto/ccp/ccp-crypto-aes-galois.c
drivers/crypto/ccp/ccp-ops.c
drivers/crypto/ux500/cryp/cryp.c
drivers/dma/dw-edma/dw-edma-core.h
drivers/dma/dw-edma/dw-edma-pcie.c
drivers/dma/dw-edma/dw-edma-v0-core.c
drivers/dma/dw-edma/dw-edma-v0-debugfs.c
drivers/dma/ste_dma40.c
drivers/dma/stm32-mdma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/omap-dma.c
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_post.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/vlv_dsi_pll.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
drivers/hid/hid-apple.c
drivers/hv/hv_trace.h
drivers/hwmon/lm75.c
drivers/hwmon/nct7802.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/intel_th/msu.h
drivers/hwtracing/intel_th/pti.h
drivers/i2c/busses/i2c-emev2.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-stm32.h
drivers/iio/accel/cros_ec_accel_legacy.c
drivers/iio/adc/ingenic-adc.c
drivers/iio/adc/max9611.c
drivers/iio/adc/rcar-gyroadc.c
drivers/iio/frequency/adf4371.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/infiniband/core/counters.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/sw/siw/Kconfig
drivers/infiniband/sw/siw/siw.h
drivers/infiniband/sw/siw/siw_main.c
drivers/infiniband/sw/siw/siw_qp.c
drivers/infiniband/sw/siw/siw_verbs.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/applespi.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/input/tablet/kbtab.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/iommu/arm-smmu-v3.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu-debugfs.c
drivers/iommu/intel-iommu.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/md/bcache/sysfs.c
drivers/media/platform/omap/omap_vout_vrfb.c
drivers/media/platform/vivid/vivid-core.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/omap-usb-host.c
drivers/misc/Kconfig
drivers/misc/habanalabs/command_submission.c
drivers/misc/habanalabs/device.c
drivers/misc/habanalabs/firmware_if.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/goya/goyaP.h
drivers/misc/habanalabs/habanalabs.h
drivers/misc/habanalabs/hw_queue.c
drivers/misc/habanalabs/include/goya/goya_packets.h
drivers/misc/habanalabs/irq.c
drivers/misc/habanalabs/memory.c
drivers/mmc/host/cavium.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-of-at91.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-sprd.c
drivers/mmc/host/sdhci-xenon.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/spi-nor/spi-nor.c
drivers/net/arcnet/arc-rimi.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com90io.c
drivers/net/arcnet/com90xx.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/rcar/rcar_canfd.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/qca8k.c
drivers/net/dsa/sja1105/sja1105_dynamic_config.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/ethernet/8390/Kconfig
drivers/net/ethernet/agere/et131x.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/Kconfig
drivers/net/ethernet/apple/Kconfig
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/cavium/common/cavium_ptp.c
drivers/net/ethernet/cavium/liquidio/request_manager.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/ezchip/nps_enet.h
drivers/net/ethernet/freescale/enetc/Kconfig
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_rx.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mediatek/Kconfig
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/params.h
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/port.h
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.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_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
drivers/net/ethernet/mellanox/mlx5/core/lib/crypto.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_flower.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/ni/Kconfig
drivers/net/ethernet/packetengines/Kconfig
drivers/net/ethernet/packetengines/Makefile
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/samsung/Kconfig
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/tundra/tsi108_eth.c
drivers/net/ethernet/xscale/Kconfig
drivers/net/hamradio/baycom_epp.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/fib.c
drivers/net/netdevsim/netdev.c
drivers/net/netdevsim/netdevsim.h
drivers/net/phy/at803x.c
drivers/net/phy/fixed_phy.c
drivers/net/phy/mscc.c
drivers/net/phy/phy-c45.c
drivers/net/phy/phy_device.c
drivers/net/phy/phy_led_triggers.c
drivers/net/phy/phylink.c
drivers/net/ppp/pppoe.c
drivers/net/ppp/pppox.c
drivers/net/ppp/pptp.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/cx82310_eth.c
drivers/net/usb/kalmia.c
drivers/net/usb/lan78xx.c
drivers/net/usb/pegasus.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/wan/sdla.c
drivers/net/wimax/i2400m/fw.c
drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.h
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/mwifiex/main.h
drivers/net/wireless/marvell/mwifiex/scan.c
drivers/net/xen-netback/netback.c
drivers/nfc/nfcmrvl/main.c
drivers/nfc/nfcmrvl/uart.c
drivers/nfc/nfcmrvl/usb.c
drivers/nfc/st-nci/se.c
drivers/nfc/st21nfca/se.c
drivers/ntb/msi.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/loop.c
drivers/nvme/target/nvmet.h
drivers/nvmem/nvmem-sysfs.c
drivers/of/irq.c
drivers/of/resolver.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pcmcia/db1xxx_ss.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
drivers/pinctrl/aspeed/pinctrl-aspeed.c
drivers/pinctrl/aspeed/pinmux-aspeed.c
drivers/pinctrl/aspeed/pinmux-aspeed.h
drivers/pwm/core.c
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/scsi/arm/fas216.c
drivers/scsi/lpfc/lpfc_init.c
drivers/soundwire/Kconfig
drivers/soundwire/Makefile
drivers/soundwire/cadence_master.c
drivers/staging/android/ion/ion_page_pool.c
drivers/staging/comedi/drivers/dt3000.c
drivers/staging/fbtft/fb_bd663474.c
drivers/staging/fbtft/fb_ili9163.c
drivers/staging/fbtft/fb_ili9325.c
drivers/staging/fbtft/fb_s6d1121.c
drivers/staging/fbtft/fb_ssd1289.c
drivers/staging/fbtft/fb_ssd1331.c
drivers/staging/fbtft/fb_upd161704.c
drivers/staging/fbtft/fbtft-bus.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/gasket/apex_driver.c
drivers/staging/unisys/visornic/visornic_main.c
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
drivers/tty/serial/kgdboc.c
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/buffer.c
drivers/usb/core/devio.c
drivers/usb/core/file.c
drivers/usb/core/hcd.c
drivers/usb/core/message.c
drivers/usb/core/sysfs.c
drivers/usb/core/usb.h
drivers/usb/dwc2/hcd.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/fotg210-hcd.c
drivers/usb/host/xhci-rcar.c
drivers/usb/host/xhci.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/rio500.c
drivers/usb/misc/yurex.c
drivers/usb/serial/option.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi_ccg.c
drivers/video/fbdev/omap/omapfb_main.c
drivers/watchdog/ar7_wdt.c
drivers/watchdog/pcwd.c
drivers/watchdog/riowd.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/scx200_wdt.c
drivers/watchdog/wdt.c
drivers/watchdog/wdt977.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/file.c
fs/afs/vlclient.c
fs/block_dev.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/volumes.c
fs/cifs/connect.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/compat_ioctl.c
fs/dax.c
fs/gfs2/bmap.c
fs/io_uring.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/fscache.c
fs/nfs/fscache.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pnfs.c
fs/nfs/super.c
fs/seq_file.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_da_btree.c
fs/xfs/libxfs/xfs_dir2_node.c
fs/xfs/xfs_log.c
include/asm-generic/5level-fixup.h
include/kvm/arm_pmu.h
include/kvm/arm_vgic.h
include/linux/blk_types.h
include/linux/ccp.h
include/linux/dim.h
include/linux/dma-noncoherent.h
include/linux/filter.h
include/linux/gfp.h
include/linux/if_pppox.h
include/linux/if_rmnet.h
include/linux/key.h
include/linux/kvm_host.h
include/linux/memcontrol.h
include/linux/mempolicy.h
include/linux/mlx5/device.h
include/linux/mlx5/fs.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm_types.h
include/linux/pci.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/skmsg.h
include/linux/socket.h
include/linux/usb.h
include/linux/usb/hcd.h
include/misc/charlcd.h [deleted file]
include/net/bluetooth/hci_core.h
include/net/cfg80211.h
include/net/inet_frag.h
include/net/net_namespace.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nf_tables_offload.h
include/net/netlink.h
include/net/pkt_cls.h
include/net/sock.h
include/net/tc_act/tc_police.h
include/net/tc_act/tc_sample.h
include/net/tcp.h
include/net/tls.h
include/sound/simple_card_utils.h
include/trace/events/rxrpc.h
include/uapi/linux/bpf.h
include/uapi/linux/kfd_ioctl.h
include/uapi/linux/netfilter/xt_connlabel.h
include/uapi/linux/socket.h
include/uapi/rdma/siw-abi.h
include/uapi/sound/sof/fw.h
include/uapi/sound/sof/header.h
kernel/bpf/verifier.c
kernel/configs.c
kernel/dma/direct.c
kernel/dma/mapping.c
kernel/dma/remap.c
kernel/irq/affinity.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/deadline.c
kernel/sched/psi.c
kernel/signal.c
lib/dim/dim.c
lib/dim/net_dim.c
mm/huge_memory.c
mm/hugetlb.c
mm/kmemleak.c
mm/memcontrol.c
mm/mempolicy.c
mm/memremap.c
mm/rmap.c
mm/shmem.c
mm/usercopy.c
mm/vmalloc.c
mm/vmscan.c
mm/workingset.c
mm/z3fold.c
net/batman-adv/multicast.c
net/bluetooth/hci_core.c
net/bluetooth/hci_debugfs.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bridge/br.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/nft_meta_bridge.c
net/can/gw.c
net/core/dev.c
net/core/filter.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_diag.c
net/core/sock_map.c
net/dsa/switch.c
net/dsa/tag_sja1105.c
net/ieee802154/6lowpan/reassembly.c
net/ipv4/inet_fragment.c
net/ipv4/ip_fragment.c
net/ipv4/ipip.c
net/ipv4/tcp.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_output.c
net/ipv4/tcp_ulp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/iucv/af_iucv.c
net/l2tp/l2tp_ppp.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/util.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_ipmac.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_meta.c
net/netrom/af_netrom.c
net/openvswitch/datapath.c
net/packet/af_packet.c
net/rds/rdma_transport.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_event.c
net/rxrpc/input.c
net/rxrpc/local_object.c
net/rxrpc/output.c
net/rxrpc/peer_event.c
net/rxrpc/peer_object.c
net/rxrpc/recvmsg.c
net/rxrpc/sendmsg.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_mirred.c
net/sched/act_mpls.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c
net/sched/sch_codel.c
net/sched/sch_taprio.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/stream.c
net/smc/af_smc.c
net/tipc/addr.c
net/tipc/link.c
net/tipc/msg.h
net/tipc/netlink_compat.c
net/tipc/socket.c
net/tls/tls_device.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/vmw_vsock/hyperv_transport.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/util.c
samples/auxdisplay/cfag12864b-example.c
scripts/Makefile.build
scripts/Makefile.modpost
scripts/coccinelle/api/atomic_as_refcounter.cocci
security/keys/trusted.c
sound/firewire/packets-buffer.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/codecs/cs42xx8.c
sound/soc/codecs/max98357a.c
sound/soc/codecs/max98373.c
sound/soc/codecs/max98373.h
sound/soc/codecs/pcm3060-i2c.c
sound/soc/codecs/pcm3060-spi.c
sound/soc/codecs/pcm3060.c
sound/soc/codecs/pcm3060.h
sound/soc/codecs/rt1011.c
sound/soc/codecs/rt1308.c [changed mode: 0755->0644]
sound/soc/codecs/rt1308.h [changed mode: 0755->0644]
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card-utils.c
sound/soc/generic/simple-card.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/common/soc-acpi-intel-bxt-match.c
sound/soc/intel/common/soc-acpi-intel-byt-match.c
sound/soc/intel/common/soc-acpi-intel-cht-match.c
sound/soc/intel/common/soc-acpi-intel-cnl-match.c
sound/soc/intel/common/soc-acpi-intel-glk-match.c
sound/soc/intel/common/soc-acpi-intel-hda-match.c
sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
sound/soc/intel/common/soc-acpi-intel-icl-match.c
sound/soc/intel/common/soc-acpi-intel-kbl-match.c
sound/soc/intel/common/soc-acpi-intel-skl-match.c
sound/soc/qcom/apq8016_sbc.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/rockchip/rockchip_max98090.c
sound/soc/samsung/odroid.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/sof/intel/cnl.c
sound/soc/sof/intel/hda-ipc.c
sound/soc/sunxi/sun4i-i2s.c
sound/soc/ti/davinci-mcasp.c
sound/sound_core.c
sound/usb/hiface/pcm.c
sound/usb/mixer.c
sound/usb/stream.c
tools/bpf/bpftool/common.c
tools/hv/hv_get_dhcp_info.sh
tools/hv/hv_kvp_daemon.c
tools/hv/hv_set_ifconfig.sh
tools/hv/hv_vss_daemon.c
tools/hv/lsvmbus
tools/include/uapi/linux/bpf.h
tools/lib/bpf/btf.c
tools/lib/bpf/libbpf.c
tools/lib/bpf/xsk.c
tools/perf/Documentation/Makefile
tools/perf/arch/s390/util/machine.c
tools/perf/bench/numa.c
tools/perf/builtin-ftrace.c
tools/perf/pmu-events/jevents.c
tools/perf/ui/browser.c
tools/perf/ui/tui/progress.c
tools/perf/util/annotate.c
tools/perf/util/cpumap.c
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/thread.c
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/progs/sendmsg6_prog.c
tools/testing/selftests/bpf/test_xdp_vlan.sh
tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh [new file with mode: 0755]
tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh [new file with mode: 0755]
tools/testing/selftests/bpf/verifier/ctx_skb.c
tools/testing/selftests/bpf/verifier/loops1.c
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/config [new file with mode: 0644]
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/forwarding/gre_multipath.sh
tools/testing/selftests/net/tcp_fastopen_backup_key.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/netfilter/nft_flowtable.sh
tools/testing/selftests/tc-testing/tc-tests/actions/skbedit.json
tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
virt/kvm/arm/arm.c
virt/kvm/arm/hyp/vgic-v3-sr.c
virt/kvm/arm/pmu.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/arm/vgic/vgic.h
virt/kvm/kvm_main.c

index a7d44e71019d680f283b2e7bcbe25e59e079c1bb..287b98708a40915a80ba76455621b507cce161bd 100644 (file)
@@ -39,7 +39,6 @@ Table : Subdirectories in /proc/sys/net
  802       E802 protocol         ax25       AX25
  ethernet  Ethernet protocol     rose       X.25 PLP layer
  ipv4      IP version 4          x25        X.25 protocol
- ipx       IPX                   token-ring IBM token ring
  bridge    Bridging              decnet     DEC net
  ipv6      IP version 6          tipc       TIPC
  ========= =================== = ========== ==================
@@ -401,33 +400,7 @@ interface.
 (network) that the route leads to, the router (may be directly connected), the
 route flags, and the device the route is using.
 
-
-5. IPX
-------
-
-The IPX protocol has no tunable values in proc/sys/net.
-
-The IPX  protocol  does,  however,  provide  proc/net/ipx. This lists each IPX
-socket giving  the  local  and  remote  addresses  in  Novell  format (that is
-network:node:port). In  accordance  with  the  strange  Novell  tradition,
-everything but the port is in hex. Not_Connected is displayed for sockets that
-are not  tied to a specific remote address. The Tx and Rx queue sizes indicate
-the number  of  bytes  pending  for  transmission  and  reception.  The  state
-indicates the  state  the  socket  is  in and the uid is the owning uid of the
-socket.
-
-The /proc/net/ipx_interface  file lists all IPX interfaces. For each interface
-it gives  the network number, the node number, and indicates if the network is
-the primary  network.  It  also  indicates  which  device  it  is bound to (or
-Internal for  internal  networks)  and  the  Frame  Type if appropriate. Linux
-supports 802.3,  802.2,  802.2  SNAP  and DIX (Blue Book) ethernet framing for
-IPX.
-
-The /proc/net/ipx_route  table  holds  a list of IPX routes. For each route it
-gives the  destination  network, the router node (or Directly) and the network
-address of the router (or Connected) for internal networks.
-
-6. TIPC
+5. TIPC
 -------
 
 tipc_rmem
index 6b0dfd5c17baccb3232f032738a7a5c53efd28c9..5138a2f6232aa23cdc98211d2e3fcaaa2890030e 100644 (file)
@@ -19,7 +19,9 @@ quiet_cmd_mk_schema = SCHEMA  $@
 
 DT_DOCS = $(shell \
        cd $(srctree)/$(src) && \
-       find * \( -name '*.yaml' ! -name $(DT_TMP_SCHEMA) \) \
+       find * \( -name '*.yaml' ! \
+               -name $(DT_TMP_SCHEMA) ! \
+               -name '*.example.dt.yaml' \) \
        )
 
 DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
index 2d41fb96ce0a2b66acf309071f1534c6437f52cf..5b88fae0307d153e50a6faac33d6152bdf2711d4 100644 (file)
@@ -7,18 +7,6 @@ Required properties:
 - phy-mode : See ethernet.txt file in the same directory
 
 Optional properties:
-- phy-reset-gpios : Should specify the gpio for phy reset
-- phy-reset-duration : Reset duration in milliseconds.  Should present
-  only if property "phy-reset-gpios" is available.  Missing the property
-  will have the duration be 1 millisecond.  Numbers greater than 1000 are
-  invalid and 1 millisecond will be used instead.
-- phy-reset-active-high : If present then the reset sequence using the GPIO
-  specified in the "phy-reset-gpios" property is reversed (H=reset state,
-  L=operation state).
-- phy-reset-post-delay : Post reset delay in milliseconds. If present then
-  a delay of phy-reset-post-delay milliseconds will be observed after the
-  phy-reset-gpios has been toggled. Can be omitted thus no delay is
-  observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
 - phy-supply : regulator that powers the Ethernet PHY.
 - phy-handle : phandle to the PHY device connected to this device.
 - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
@@ -47,11 +35,27 @@ Optional properties:
   For imx6sx, "int0" handles all 3 queues and ENET_MII. "pps" is for the pulse
   per second interrupt associated with 1588 precision time protocol(PTP).
 
-
 Optional subnodes:
 - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
   according to phy.txt in the same directory
 
+Deprecated optional properties:
+       To avoid these, create a phy node according to phy.txt in the same
+       directory, and point the fec's "phy-handle" property to it. Then use
+       the phy's reset binding, again described by phy.txt.
+- phy-reset-gpios : Should specify the gpio for phy reset
+- phy-reset-duration : Reset duration in milliseconds.  Should present
+  only if property "phy-reset-gpios" is available.  Missing the property
+  will have the duration be 1 millisecond.  Numbers greater than 1000 are
+  invalid and 1 millisecond will be used instead.
+- phy-reset-active-high : If present then the reset sequence using the GPIO
+  specified in the "phy-reset-gpios" property is reversed (H=reset state,
+  L=operation state).
+- phy-reset-post-delay : Post reset delay in milliseconds. If present then
+  a delay of phy-reset-post-delay milliseconds will be observed after the
+  phy-reset-gpios has been toggled. Can be omitted thus no delay is
+  observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
+
 Example:
 
 ethernet@83fec000 {
index 91d3e78b3395cd3b23b07826f6fcee9cda71166e..400df2da018a32f0ee2b0e036ac3432912dac0a4 100644 (file)
@@ -37,7 +37,8 @@ properties:
   hwlocks: true
 
   st,syscfg:
-    $ref: "/schemas/types.yaml#/definitions/phandle-array"
+    allOf:
+      - $ref: "/schemas/types.yaml#/definitions/phandle-array"
     description: Should be phandle/offset/mask
     items:
       - description: Phandle to the syscon node which includes IRQ mux selection.
diff --git a/Documentation/devicetree/bindings/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt
deleted file mode 100644 (file)
index adf7b7a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-===================
-RISC-V CPU Bindings
-===================
-
-The device tree allows to describe the layout of CPUs in a system through
-the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
-defining properties for every cpu.
-
-Bindings for CPU nodes follow the Devicetree Specification, available from:
-
-https://www.devicetree.org/specifications/
-
-with updates for 32-bit and 64-bit RISC-V systems provided in this document.
-
-===========
-Terminology
-===========
-
-This document uses some terminology common to the RISC-V community that is not
-widely used, the definitions of which are listed here:
-
-* hart: A hardware execution context, which contains all the state mandated by
-  the RISC-V ISA: a PC and some registers.  This terminology is designed to
-  disambiguate software's view of execution contexts from any particular
-  microarchitectural implementation strategy.  For example, my Intel laptop is
-  described as having one socket with two cores, each of which has two hyper
-  threads.  Therefore this system has four harts.
-
-=====================================
-cpus and cpu node bindings definition
-=====================================
-
-The RISC-V architecture, in accordance with the Devicetree Specification,
-requires the cpus and cpu nodes to be present and contain the properties
-described below.
-
-- cpus node
-
-        Description: Container of cpu nodes
-
-        The node name must be "cpus".
-
-        A cpus node must define the following properties:
-
-        - #address-cells
-                Usage: required
-                Value type: <u32>
-                Definition: must be set to 1
-        - #size-cells
-                Usage: required
-                Value type: <u32>
-                Definition: must be set to 0
-
-- cpu node
-
-        Description: Describes a hart context
-
-        PROPERTIES
-
-        - device_type
-                Usage: required
-                Value type: <string>
-                Definition: must be "cpu"
-        - reg
-                Usage: required
-                Value type: <u32>
-                Definition: The hart ID of this CPU node
-        - compatible:
-                Usage: required
-                Value type: <stringlist>
-                Definition: must contain "riscv", may contain one of
-                            "sifive,rocket0"
-        - mmu-type:
-                Usage: optional
-                Value type: <string>
-                Definition: Specifies the CPU's MMU type.  Possible values are
-                            "riscv,sv32"
-                            "riscv,sv39"
-                            "riscv,sv48"
-        - riscv,isa:
-                Usage: required
-                Value type: <string>
-                Definition: Contains the RISC-V ISA string of this hart.  These
-                            ISA strings are defined by the RISC-V ISA manual.
-
-Example: SiFive Freedom U540G Development Kit
----------------------------------------------
-
-This system contains two harts: a hart marked as disabled that's used for
-low-level system tasks and should be ignored by Linux, and a second hart that
-Linux is allowed to run on.
-
-        cpus {
-                #address-cells = <1>;
-                #size-cells = <0>;
-                timebase-frequency = <1000000>;
-                cpu@0 {
-                        clock-frequency = <1600000000>;
-                        compatible = "sifive,rocket0", "riscv";
-                        device_type = "cpu";
-                        i-cache-block-size = <64>;
-                        i-cache-sets = <128>;
-                        i-cache-size = <16384>;
-                        next-level-cache = <&L15 &L0>;
-                        reg = <0>;
-                        riscv,isa = "rv64imac";
-                        status = "disabled";
-                        L10: interrupt-controller {
-                                #interrupt-cells = <1>;
-                                compatible = "riscv,cpu-intc";
-                                interrupt-controller;
-                        };
-                };
-                cpu@1 {
-                        clock-frequency = <1600000000>;
-                        compatible = "sifive,rocket0", "riscv";
-                        d-cache-block-size = <64>;
-                        d-cache-sets = <64>;
-                        d-cache-size = <32768>;
-                        d-tlb-sets = <1>;
-                        d-tlb-size = <32>;
-                        device_type = "cpu";
-                        i-cache-block-size = <64>;
-                        i-cache-sets = <64>;
-                        i-cache-size = <32768>;
-                        i-tlb-sets = <1>;
-                        i-tlb-size = <32>;
-                        mmu-type = "riscv,sv39";
-                        next-level-cache = <&L15 &L0>;
-                        reg = <1>;
-                        riscv,isa = "rv64imafdc";
-                        status = "okay";
-                        tlb-split;
-                        L13: interrupt-controller {
-                                #interrupt-cells = <1>;
-                                compatible = "riscv,cpu-intc";
-                                interrupt-controller;
-                        };
-                };
-        };
-
-Example: Spike ISA Simulator with 1 Hart
-----------------------------------------
-
-This device tree matches the Spike ISA golden model as run with `spike -p1`.
-
-        cpus {
-                cpu@0 {
-                        device_type = "cpu";
-                        reg = <0x00000000>;
-                        status = "okay";
-                        compatible = "riscv";
-                        riscv,isa = "rv64imafdc";
-                        mmu-type = "riscv,sv48";
-                        clock-frequency = <0x3b9aca00>;
-                        interrupt-controller {
-                                #interrupt-cells = <0x00000001>;
-                                interrupt-controller;
-                                compatible = "riscv,cpu-intc";
-                        }
-                }
-        }
index c899111aa5e3799cf84524d932dbd55448164c0f..b261a3015f84f3c7982397123d908beabe45e9cd 100644 (file)
@@ -10,6 +10,18 @@ maintainers:
   - Paul Walmsley <paul.walmsley@sifive.com>
   - Palmer Dabbelt <palmer@sifive.com>
 
+description: |
+  This document uses some terminology common to the RISC-V community
+  that is not widely used, the definitions of which are listed here:
+
+  hart: A hardware execution context, which contains all the state
+  mandated by the RISC-V ISA: a PC and some registers.  This
+  terminology is designed to disambiguate software's view of execution
+  contexts from any particular microarchitectural implementation
+  strategy.  For example, an Intel laptop containing one socket with
+  two cores, each of which has two hyperthreads, could be described as
+  having four harts.
+
 properties:
   compatible:
     items:
@@ -50,6 +62,10 @@ properties:
       User-Level ISA document, available from
       https://riscv.org/specifications/
 
+      While the isa strings in ISA specification are case
+      insensitive, letters in the riscv,isa string must be all
+      lowercase to simplify parsing.
+
   timebase-frequency:
     type: integer
     minimum: 1
index 9d17dc2f3f843611ca2cbda105d8c537b98b4322..3ab532713dc12dfe0273f320b0ff9700e764890f 100644 (file)
@@ -19,7 +19,7 @@ properties:
   compatible:
     items:
       - enum:
-          - sifive,freedom-unleashed-a00
+          - sifive,hifive-unleashed-a00
       - const: sifive,fu540-c000
       - const: sifive,fu540
 ...
index 9267f3fb131f9b5cf0e027ba9bdd9ff51a93d5b8..edbbccda1942e4c84bf5b3dd3e5d3c1bd7959b32 100644 (file)
@@ -13,7 +13,8 @@ a) SMB3 (and SMB3.1.1) missing optional features:
    - T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
      currently the only two server side copy mechanisms supported)
 
-b) improved sparse file support
+b) improved sparse file support (fiemap and SEEK_HOLE are implemented
+but additional features would be supportable by the protocol).
 
 c) Directory entry caching relies on a 1 second timer, rather than
 using Directory Leases, currently only the root file handle is cached longer
@@ -21,9 +22,13 @@ using Directory Leases, currently only the root file handle is cached longer
 d) quota support (needs minor kernel change since quota calls
 to make it to network filesystems or deviceless filesystems)
 
-e) Additional use cases where we use "compoounding" (e.g. open/query/close
-and open/setinfo/close) to reduce the number of roundtrips, and also
-open to reduce redundant opens (using deferred close and reference counts more).
+e) Additional use cases can be optimized to use "compounding"
+(e.g. open/query/close and open/setinfo/close) to reduce the number
+of roundtrips to the server and improve performance. Various cases
+(stat, statfs, create, unlink, mkdir) already have been improved by
+using compounding but more can be done.  In addition we could significantly
+reduce redundant opens by using deferred close (with handle caching leases)
+and better using reference counters on file handles.
 
 f) Finish inotify support so kde and gnome file list windows
 will autorefresh (partially complete by Asser). Needs minor kernel
@@ -43,18 +48,17 @@ mount or a per server basis to client UIDs or nobody if no mapping
 exists. Also better integration with winbind for resolving SID owners
 
 k) Add tools to take advantage of more smb3 specific ioctls and features
-(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server
-is in progress, and a passthrough query_info call is already implemented
-in cifs.ko to allow smb3 info levels queries to be sent from userspace)
+(passthrough ioctl/fsctl is now implemented in cifs.ko to allow sending
+various SMB3 fsctls and query info and set info calls directly from user space)
+Add tools to make setting various non-POSIX metadata attributes easier
+from tools (e.g. extending what was done in smb-info tool).
 
 l) encrypted file support
 
 m) improved stats gathering tools (perhaps integration with nfsometer?)
 to extend and make easier to use what is currently in /proc/fs/cifs/Stats
 
-n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
-file attribute via chflags) and improve user space tools for managing and
-viewing them.
+n) Add support for claims based ACLs ("DAC")
 
 o) mount helper GUI (to simplify the various configuration options on mount)
 
@@ -82,6 +86,8 @@ so far).
 w) Add support for additional strong encryption types, and additional spnego
 authentication mechanisms (see MS-SMB2)
 
+x) Finish support for SMB3.1.1 compression
+
 KNOWN BUGS
 ====================================
 See http://bugzilla.samba.org - search on product "CifsVFS" for
index 048e5ca44824b4bd7304ee26b5a4c0b7185f828c..0dd3f748239f2858f49ec24590433ea3c8843230 100644 (file)
@@ -424,13 +424,24 @@ Statistics
 Following minimum set of TLS-related statistics should be reported
 by the driver:
 
- * ``rx_tls_decrypted`` - number of successfully decrypted TLS segments
- * ``tx_tls_encrypted`` - number of in-order TLS segments passed to device
-   for encryption
+ * ``rx_tls_decrypted_packets`` - number of successfully decrypted RX packets
+   which were part of a TLS stream.
+ * ``rx_tls_decrypted_bytes`` - number of TLS payload bytes in RX packets
+   which were successfully decrypted.
+ * ``tx_tls_encrypted_packets`` - number of TX packets passed to the device
+   for encryption of their TLS payload.
+ * ``tx_tls_encrypted_bytes`` - number of TLS payload bytes in TX packets
+   passed to the device for encryption.
+ * ``tx_tls_ctx`` - number of TLS TX HW offload contexts added to device for
+   encryption.
  * ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
-   but did not arrive in the expected order
- * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
-   they arrived out of order and associated record could not be found
+   but did not arrive in the expected order.
+ * ``tx_tls_drop_no_sync_data`` - number of TX packets which were part of
+   a TLS stream dropped, because they arrived out of order and associated
+   record could not be found.
+ * ``tx_tls_drop_bypass_req`` - number of TX packets which were part of a TLS
+   stream dropped, because they contain both data that has been encrypted by
+   software and data that expects hardware crypto offload.
 
 Notable corner cases, exceptions and additional requirements
 ============================================================
@@ -495,21 +506,3 @@ Drivers should ignore the changes to TLS the device feature flags.
 These flags will be acted upon accordingly by the core ``ktls`` code.
 TLS device feature flags only control adding of new TLS connection
 offloads, old connections will remain active after flags are cleared.
-
-Known bugs
-==========
-
-skb_orphan() leaks clear text
------------------------------
-
-Currently drivers depend on the :c:member:`sk` member of
-:c:type:`struct sk_buff <sk_buff>` to identify segments requiring
-encryption. Any operation which removes or does not preserve the socket
-association such as :c:func:`skb_orphan` or :c:func:`skb_clone`
-will cause the driver to miss the packets and lead to clear text leaks.
-
-Redirects leak clear text
--------------------------
-
-In the RX direction, if segment has already been decrypted by the device
-and it gets redirected or mirrored - clear text will be transmitted out.
index 949d5dcdd9a348fd646f89c62f604d9d29433d2c..0104830d5075ff255b539c34adabfb6b70f7ea45 100644 (file)
@@ -204,8 +204,8 @@ Ethernet device, which instead of receiving packets from a physical
 media, receives them from user space program and instead of sending 
 packets via physical media sends them to the user space program. 
 
-Let's say that you configured IPX on the tap0, then whenever 
-the kernel sends an IPX packet to tap0, it is passed to the application
+Let's say that you configured IPv6 on the tap0, then whenever
+the kernel sends an IPv6 packet to tap0, it is passed to the application
 (VTun for example). The application encrypts, compresses and sends it to 
 the other side over TCP or UDP. The application on the other side decompresses
 and decrypts the data received and writes the packet to the TAP device, 
index a2c343ee3b2ca13e4cbe7257a9e4a58d69a11285..08176d64eed5afd0a8c024ce74d0f5b0b22c42f4 100644 (file)
@@ -183,7 +183,7 @@ M:  Realtek linux nic maintainers <nic_swsd@realtek.com>
 M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ethernet/realtek/r8169.c
+F:     drivers/net/ethernet/realtek/r8169*
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -6065,7 +6065,7 @@ M:        Florian Fainelli <f.fainelli@gmail.com>
 M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     Documentation/ABI/testing/sysfs-bus-mdio
+F:     Documentation/ABI/testing/sysfs-class-net-phydev
 F:     Documentation/devicetree/bindings/net/ethernet-phy.yaml
 F:     Documentation/devicetree/bindings/net/mdio*
 F:     Documentation/networking/phy.rst
@@ -6344,7 +6344,7 @@ FPGA MANAGER FRAMEWORK
 M:     Moritz Fischer <mdf@kernel.org>
 L:     linux-fpga@vger.kernel.org
 S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git
 Q:     http://patchwork.kernel.org/project/linux-fpga/list/
 F:     Documentation/fpga/
 F:     Documentation/driver-api/fpga/
@@ -6377,7 +6377,7 @@ FRAMEBUFFER LAYER
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
 L:     dri-devel@lists.freedesktop.org
 L:     linux-fbdev@vger.kernel.org
-T:     git git://github.com/bzolnier/linux.git
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 Q:     http://patchwork.kernel.org/project/linux-fbdev/list/
 S:     Maintained
 F:     Documentation/fb/
@@ -6441,6 +6441,14 @@ S:       Maintained
 F:     drivers/perf/fsl_imx8_ddr_perf.c
 F:     Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt
 
+FREESCALE IMX I2C DRIVER
+M:     Oleksij Rempel <o.rempel@pengutronix.de>
+R:     Pengutronix Kernel Team <kernel@pengutronix.de>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-imx.c
+F:     Documentation/devicetree/bindings/i2c/i2c-imx.txt
+
 FREESCALE IMX LPI2C DRIVER
 M:     Dong Aisheng <aisheng.dong@nxp.com>
 L:     linux-i2c@vger.kernel.org
@@ -6827,13 +6835,6 @@ F:       Documentation/filesystems/gfs2*.txt
 F:     fs/gfs2/
 F:     include/uapi/linux/gfs2_ondisk.h
 
-GIGASET ISDN DRIVERS
-M:     Paul Bolle <pebolle@tiscali.nl>
-L:     gigaset307x-common@lists.sourceforge.net
-W:     http://gigaset307x.sourceforge.net/
-S:     Odd Fixes
-F:     drivers/staging/isdn/gigaset/
-
 GNSS SUBSYSTEM
 M:     Johan Hovold <johan@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss.git
@@ -7459,7 +7460,7 @@ F:        drivers/net/hyperv/
 F:     drivers/scsi/storvsc_drv.c
 F:     drivers/uio/uio_hv_generic.c
 F:     drivers/video/fbdev/hyperv_fb.c
-F:     drivers/iommu/hyperv_iommu.c
+F:     drivers/iommu/hyperv-iommu.c
 F:     net/vmw_vsock/hyperv_transport.c
 F:     include/clocksource/hyperv_timer.h
 F:     include/linux/hyperv.h
@@ -8049,6 +8050,7 @@ S:        Maintained
 F:     drivers/video/fbdev/i810/
 
 INTEL ASoC DRIVERS
+M:     Cezary Rojewski <cezary.rojewski@intel.com>
 M:     Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
 M:     Liam Girdwood <liam.r.girdwood@linux.intel.com>
 M:     Jie Yang <yang.jie@linux.intel.com>
@@ -8070,6 +8072,13 @@ T:       git git://git.code.sf.net/p/intel-sas/isci
 S:     Supported
 F:     drivers/scsi/isci/
 
+INTEL CPU family model numbers
+M:     Tony Luck <tony.luck@intel.com>
+M:     x86@kernel.org
+L:     linux-kernel@vger.kernel.org
+S:     Supported
+F:     arch/x86/include/asm/intel-family.h
+
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Jani Nikula <jani.nikula@linux.intel.com>
 M:     Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
@@ -8421,7 +8430,6 @@ L:        linux-xfs@vger.kernel.org
 L:     linux-fsdevel@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
 S:     Supported
-F:     fs/iomap.c
 F:     fs/iomap/
 F:     include/linux/iomap.h
 
@@ -11149,6 +11157,7 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 W:     https://fedorahosted.org/dropwatch/
 F:     net/core/drop_monitor.c
+F:     include/uapi/linux/net_dropmon.h
 
 NETWORKING DRIVERS
 M:     "David S. Miller" <davem@davemloft.net>
@@ -11287,6 +11296,7 @@ M:      Aviad Yehezkel <aviadye@mellanox.com>
 M:     Dave Watson <davejwatson@fb.com>
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     Jakub Kicinski <jakub.kicinski@netronome.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     net/tls/*
@@ -16089,7 +16099,7 @@ S:      Maintained
 F:     drivers/net/ethernet/ti/netcp*
 
 TI PCM3060 ASoC CODEC DRIVER
-M:     Kirill Marinushkin <kmarinushkin@birdec.tech>
+M:     Kirill Marinushkin <kmarinushkin@birdec.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/sound/pcm3060.txt
@@ -17565,7 +17575,6 @@ M:      Jakub Kicinski <jakub.kicinski@netronome.com>
 M:     Jesper Dangaard Brouer <hawk@kernel.org>
 M:     John Fastabend <john.fastabend@gmail.com>
 L:     netdev@vger.kernel.org
-L:     xdp-newbies@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
 F:     net/core/xdp.c
index 23cdf1f4136468e78053a488306a0c7024384ad7..9fa18613566f468d6345cf505a8102898f2b9536 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc5
 NAME = Bobtail Squid
 
 # *DOCUMENTATION*
@@ -419,6 +419,7 @@ NM          = $(CROSS_COMPILE)nm
 STRIP          = $(CROSS_COMPILE)strip
 OBJCOPY                = $(CROSS_COMPILE)objcopy
 OBJDUMP                = $(CROSS_COMPILE)objdump
+OBJSIZE                = $(CROSS_COMPILE)size
 PAHOLE         = pahole
 LEX            = flex
 YACC           = bison
@@ -475,9 +476,9 @@ GCC_PLUGINS_CFLAGS :=
 CLANG_FLAGS :=
 
 export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP PAHOLE KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS
-export MAKE LEX YACC AWK INSTALLKERNEL PERL PYTHON PYTHON2 PYTHON3 UTS_MACHINE
-export HOSTCXX KBUILD_HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
+export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
+export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
 
 export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
@@ -845,7 +846,7 @@ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 KBUILD_CFLAGS += -Wdeclaration-after-statement
 
 # Warn about unmarked fall-throughs in switch statement.
-KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough=3,)
+KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,)
 
 # Variable Length Arrays (VLAs) should not be used anywhere in the kernel
 KBUILD_CFLAGS += -Wvla
@@ -1002,6 +1003,8 @@ endif
 
 PHONY += prepare0
 
+export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
+
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
 
@@ -1771,13 +1774,22 @@ build-dir = $(patsubst %/,%,$(dir $(build-target)))
        $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
 %.symtypes: prepare FORCE
        $(Q)$(MAKE) $(build)=$(build-dir) $(build-target)
+ifeq ($(KBUILD_EXTMOD),)
+# For the single build of an in-tree module, use a temporary file to avoid
+# the situation of modules_install installing an invalid modules.order.
+%.ko: MODORDER := .modules.tmp
+endif
+%.ko: prepare FORCE
+       $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod)
+       $(Q)echo $(build-target) > $(MODORDER)
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
 
 # Modules
 PHONY += /
 /: ./
 
 %/: prepare FORCE
-       $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir)
+       $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1
 
 # FIXME Should go into a make.lib or something
 # ===========================================================================
index af8b8e15f589d0dee271c6217373ee296476cd66..b0c195e3a06df00ac7d07f65113f7820b13b6db5 100644 (file)
@@ -544,6 +544,7 @@ static int arch_build_bp_info(struct perf_event *bp,
                if ((hw->ctrl.type != ARM_BREAKPOINT_EXECUTE)
                        && max_watchpoint_len >= 8)
                        break;
+               /* Else, fall through */
        default:
                return -EINVAL;
        }
@@ -608,10 +609,12 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
                /* Allow halfword watchpoints and breakpoints. */
                if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
                        break;
+               /* Else, fall through */
        case 3:
                /* Allow single byte watchpoint. */
                if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
                        break;
+               /* Else, fall through */
        default:
                ret = -EINVAL;
                goto out;
@@ -861,6 +864,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
                break;
        case ARM_ENTRY_ASYNC_WATCHPOINT:
                WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
+               /* Fall through */
        case ARM_ENTRY_SYNC_WATCHPOINT:
                watchpoint_handler(addr, fsr, regs);
                break;
@@ -909,6 +913,7 @@ static bool core_has_os_save_restore(void)
                ARM_DBG_READ(c1, c1, 4, oslsr);
                if (oslsr & ARM_OSLSR_OSLM0)
                        return true;
+               /* Else, fall through */
        default:
                return false;
        }
index 09f6fdd419745c891b3c9ebaf853ac8ef2b76c7f..ab2568996ddb0c73bdcb3633b648b983a0b27b68 100644 (file)
@@ -596,6 +596,7 @@ static int do_signal(struct pt_regs *regs, int syscall)
                switch (retval) {
                case -ERESTART_RESTARTBLOCK:
                        restart -= 2;
+                       /* Fall through */
                case -ERESTARTNOHAND:
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
index d2806bcff8bbb29a6be18d6e8c255bab19f33c8c..07745ee022a121aa482361bcce51dccee7ab8ef6 100644 (file)
@@ -651,13 +651,22 @@ int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
 }
 
 static void reset_coproc_regs(struct kvm_vcpu *vcpu,
-                             const struct coproc_reg *table, size_t num)
+                             const struct coproc_reg *table, size_t num,
+                             unsigned long *bmap)
 {
        unsigned long i;
 
        for (i = 0; i < num; i++)
-               if (table[i].reset)
+               if (table[i].reset) {
+                       int reg = table[i].reg;
+
                        table[i].reset(vcpu, &table[i]);
+                       if (reg > 0 && reg < NR_CP15_REGS) {
+                               set_bit(reg, bmap);
+                               if (table[i].is_64bit)
+                                       set_bit(reg + 1, bmap);
+                       }
+               }
 }
 
 static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
@@ -1432,17 +1441,15 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
 {
        size_t num;
        const struct coproc_reg *table;
-
-       /* Catch someone adding a register without putting in reset entry. */
-       memset(vcpu->arch.ctxt.cp15, 0x42, sizeof(vcpu->arch.ctxt.cp15));
+       DECLARE_BITMAP(bmap, NR_CP15_REGS) = { 0, };
 
        /* Generic chip reset first (so target could override). */
-       reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
+       reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs), bmap);
 
        table = get_target_table(vcpu->arch.target, &num);
-       reset_coproc_regs(vcpu, table, num);
+       reset_coproc_regs(vcpu, table, num, bmap);
 
        for (num = 1; num < NR_CP15_REGS; num++)
-               WARN(vcpu_cp15(vcpu, num) == 0x42424242,
+               WARN(!test_bit(num, bmap),
                     "Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
index 1c9a4be8b5036d9fea7d0a8e9a001bccedb7cb52..1c05c5bf7e5c89331f9b72771334b819c4ec8a2c 100644 (file)
@@ -49,6 +49,7 @@ static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
                 * FALLTHROUGH: Ensure we don't try to overwrite our newly
                 * initialised state information on the first fault.
                 */
+               /* Fall through */
 
        case THREAD_NOTIFY_EXIT:
                crunch_task_release(thread);
index 5a67a71f80cc4f9dcd47738cf5c6eead43d45e19..76a65df42d10f2968de89c8e935215ab1da11977 100644 (file)
@@ -70,7 +70,7 @@ static void __init tegra_cpu_reset_handler_enable(void)
        switch (err) {
        case -ENOSYS:
                tegra_cpu_reset_handler_set(reset_address);
-               /* pass-through */
+               /* fall through */
        case 0:
                is_enabled = true;
                break;
index 8cdb78642e9316612be1deb340c4bf4dd0c45e1f..04b36436cbc04877a060b10670bf453dd2ed0e2d 100644 (file)
@@ -695,7 +695,7 @@ thumb2arm(u16 tinstr)
                        return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] |
                            (tinstr & 255);             /* register_list */
                }
-               /* Else fall through for illegal instruction case */
+               /* Else, fall through - for illegal instruction case */
 
        default:
                return BAD_INSTR;
@@ -751,6 +751,8 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
        case 0xe8e0:
        case 0xe9e0:
                poffset->un = (tinst2 & 0xff) << 2;
+               /* Fall through */
+
        case 0xe940:
        case 0xe9c0:
                return do_alignment_ldrdstrd;
index 6774b03aa405ca4e2dd057fcfe65aa9b9a43a878..d42557ee69c28fbcfd2f7f6c909f5b9b534779a8 100644 (file)
@@ -2405,9 +2405,7 @@ long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
 pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
                unsigned long attrs)
 {
-       if (!dev_is_dma_coherent(dev))
-               return __get_dma_pgprot(attrs, prot);
-       return prot;
+       return __get_dma_pgprot(attrs, prot);
 }
 
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
index 79f43acf9acb541487cad85bf7b49fb7f695d0d6..08c99413d02caac340f9855ebd162a59ac1126ed 100644 (file)
@@ -388,17 +388,15 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
                /*
                 * not supported by current hardware on OMAP1
                 * w |= (0x03 << 7);
-                * fall through
                 */
+               /* fall through */
        case OMAP_DMA_DATA_BURST_16:
                if (dma_omap2plus()) {
                        burst = 0x3;
                        break;
                }
-               /*
-                * OMAP1 don't support burst 16
-                * fall through
-                */
+               /* OMAP1 don't support burst 16 */
+               /* fall through */
        default:
                BUG();
        }
@@ -474,10 +472,8 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
                        burst = 0x3;
                        break;
                }
-               /*
-                * OMAP1 don't support burst 16
-                * fall through
-                */
+               /* OMAP1 don't support burst 16 */
+               /* fall through */
        default:
                printk(KERN_ERR "Invalid DMA burst mode\n");
                BUG();
index a8b205e5c4a8658ffa255795217e856c6e6080d5..ddf9d762ac62298a9c16bdff5acf348976280247 100644 (file)
 
 #define kvm_arm_exception_class \
        ECN(UNKNOWN), ECN(WFx), ECN(CP15_32), ECN(CP15_64), ECN(CP14_MR), \
-       ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(CP14_64), ECN(SVC64), \
-       ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(IMP_DEF), ECN(IABT_LOW), \
-       ECN(IABT_CUR), ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
+       ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(PAC), ECN(CP14_64), \
+       ECN(SVC64), ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(SVE), \
+       ECN(IMP_DEF), ECN(IABT_LOW), ECN(IABT_CUR), \
+       ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
        ECN(SP_ALIGN), ECN(FP_EXC32), ECN(FP_EXC64), ECN(SERROR), \
        ECN(BREAKPT_LOW), ECN(BREAKPT_CUR), ECN(SOFTSTP_LOW), \
        ECN(SOFTSTP_CUR), ECN(WATCHPT_LOW), ECN(WATCHPT_CUR), \
index 5fdcfe2373389ba630cf72ff94c062b61ca1b025..e09760ece844fe55cbd39dc8c32910a7bfdb6708 100644 (file)
@@ -209,7 +209,7 @@ static inline pmd_t pmd_mkcont(pmd_t pmd)
 
 static inline pte_t pte_mkdevmap(pte_t pte)
 {
-       return set_pte_bit(pte, __pgprot(PTE_DEVMAP));
+       return set_pte_bit(pte, __pgprot(PTE_DEVMAP | PTE_SPECIAL));
 }
 
 static inline void set_pte(pte_t *ptep, pte_t pte)
@@ -396,7 +396,10 @@ static inline int pmd_protnone(pmd_t pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_devmap(pmd)                pte_devmap(pmd_pte(pmd))
 #endif
-#define pmd_mkdevmap(pmd)      pte_pmd(pte_mkdevmap(pmd_pte(pmd)))
+static inline pmd_t pmd_mkdevmap(pmd_t pmd)
+{
+       return pte_pmd(set_pte_bit(pmd_pte(pmd), __pgprot(PTE_DEVMAP)));
+}
 
 #define __pmd_to_phys(pmd)     __pte_to_phys(pmd_pte(pmd))
 #define __phys_to_pmd_val(phys)        __phys_to_pte_val(phys)
index d19d14ba9ae401558e6e387bed2ef0b45aa211ce..b1fdc486aed8239c681acdcab1d98550bbdf60d9 100644 (file)
@@ -184,9 +184,17 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
-       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
-       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+       /*
+        * We already refuse to boot CPUs that don't support our configured
+        * page size, so we can only detect mismatches for a page size other
+        * than the one we're currently using. Unfortunately, SoCs like this
+        * exist in the wild so, even though we don't like it, we'll have to go
+        * along with it and treat them as non-strict.
+        */
+       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
+       S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
+
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
        /* Linux shouldn't care about secure memory */
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
index 1285c7b2947fa74cf50e66b83ec163b2d7a21027..17177325797420cea45062f349f5dde71b72119b 100644 (file)
@@ -73,7 +73,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
        if (offset < -SZ_128M || offset >= SZ_128M) {
 #ifdef CONFIG_ARM64_MODULE_PLTS
-               struct plt_entry trampoline;
+               struct plt_entry trampoline, *dst;
                struct module *mod;
 
                /*
@@ -106,23 +106,27 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
                 * to check if the actual opcodes are in fact identical,
                 * regardless of the offset in memory so use memcmp() instead.
                 */
-               trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline);
-               if (memcmp(mod->arch.ftrace_trampoline, &trampoline,
-                          sizeof(trampoline))) {
-                       if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) {
+               dst = mod->arch.ftrace_trampoline;
+               trampoline = get_plt_entry(addr, dst);
+               if (memcmp(dst, &trampoline, sizeof(trampoline))) {
+                       if (plt_entry_is_initialized(dst)) {
                                pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
                                return -EINVAL;
                        }
 
                        /* point the trampoline to our ftrace entry point */
                        module_disable_ro(mod);
-                       *mod->arch.ftrace_trampoline = trampoline;
+                       *dst = trampoline;
                        module_enable_ro(mod, true);
 
-                       /* update trampoline before patching in the branch */
-                       smp_wmb();
+                       /*
+                        * Ensure updated trampoline is visible to instruction
+                        * fetch before we patch in the branch.
+                        */
+                       __flush_icache_range((unsigned long)&dst[0],
+                                            (unsigned long)&dst[1]);
                }
-               addr = (unsigned long)(void *)mod->arch.ftrace_trampoline;
+               addr = (unsigned long)dst;
 #else /* CONFIG_ARM64_MODULE_PLTS */
                return -EINVAL;
 #endif /* CONFIG_ARM64_MODULE_PLTS */
index d3313797cca92b63cfe7ada88b40618c5bdfc6d0..32893b3d9164e70ec7d0dcf11619840f07def078 100644 (file)
@@ -733,6 +733,7 @@ static const char *esr_class_str[] = {
        [ESR_ELx_EC_CP14_LS]            = "CP14 LDC/STC",
        [ESR_ELx_EC_FP_ASIMD]           = "ASIMD",
        [ESR_ELx_EC_CP10_ID]            = "CP10 MRC/VMRS",
+       [ESR_ELx_EC_PAC]                = "PAC",
        [ESR_ELx_EC_CP14_64]            = "CP14 MCRR/MRRC",
        [ESR_ELx_EC_ILL]                = "PSTATE.IL",
        [ESR_ELx_EC_SVC32]              = "SVC (AArch32)",
index 26781da3ad3e2258153693470ec2d39914133d2e..0fc9872a1467107203dfca22867c6887f3eff551 100644 (file)
 #define save_debug(ptr,reg,nr)                                         \
        switch (nr) {                                                   \
        case 15:        ptr[15] = read_debug(reg, 15);                  \
+                       /* Fall through */                              \
        case 14:        ptr[14] = read_debug(reg, 14);                  \
+                       /* Fall through */                              \
        case 13:        ptr[13] = read_debug(reg, 13);                  \
+                       /* Fall through */                              \
        case 12:        ptr[12] = read_debug(reg, 12);                  \
+                       /* Fall through */                              \
        case 11:        ptr[11] = read_debug(reg, 11);                  \
+                       /* Fall through */                              \
        case 10:        ptr[10] = read_debug(reg, 10);                  \
+                       /* Fall through */                              \
        case 9:         ptr[9] = read_debug(reg, 9);                    \
+                       /* Fall through */                              \
        case 8:         ptr[8] = read_debug(reg, 8);                    \
+                       /* Fall through */                              \
        case 7:         ptr[7] = read_debug(reg, 7);                    \
+                       /* Fall through */                              \
        case 6:         ptr[6] = read_debug(reg, 6);                    \
+                       /* Fall through */                              \
        case 5:         ptr[5] = read_debug(reg, 5);                    \
+                       /* Fall through */                              \
        case 4:         ptr[4] = read_debug(reg, 4);                    \
+                       /* Fall through */                              \
        case 3:         ptr[3] = read_debug(reg, 3);                    \
+                       /* Fall through */                              \
        case 2:         ptr[2] = read_debug(reg, 2);                    \
+                       /* Fall through */                              \
        case 1:         ptr[1] = read_debug(reg, 1);                    \
+                       /* Fall through */                              \
        default:        ptr[0] = read_debug(reg, 0);                    \
        }
 
 #define restore_debug(ptr,reg,nr)                                      \
        switch (nr) {                                                   \
        case 15:        write_debug(ptr[15], reg, 15);                  \
+                       /* Fall through */                              \
        case 14:        write_debug(ptr[14], reg, 14);                  \
+                       /* Fall through */                              \
        case 13:        write_debug(ptr[13], reg, 13);                  \
+                       /* Fall through */                              \
        case 12:        write_debug(ptr[12], reg, 12);                  \
+                       /* Fall through */                              \
        case 11:        write_debug(ptr[11], reg, 11);                  \
+                       /* Fall through */                              \
        case 10:        write_debug(ptr[10], reg, 10);                  \
+                       /* Fall through */                              \
        case 9:         write_debug(ptr[9], reg, 9);                    \
+                       /* Fall through */                              \
        case 8:         write_debug(ptr[8], reg, 8);                    \
+                       /* Fall through */                              \
        case 7:         write_debug(ptr[7], reg, 7);                    \
+                       /* Fall through */                              \
        case 6:         write_debug(ptr[6], reg, 6);                    \
+                       /* Fall through */                              \
        case 5:         write_debug(ptr[5], reg, 5);                    \
+                       /* Fall through */                              \
        case 4:         write_debug(ptr[4], reg, 4);                    \
+                       /* Fall through */                              \
        case 3:         write_debug(ptr[3], reg, 3);                    \
+                       /* Fall through */                              \
        case 2:         write_debug(ptr[2], reg, 2);                    \
+                       /* Fall through */                              \
        case 1:         write_debug(ptr[1], reg, 1);                    \
+                       /* Fall through */                              \
        default:        write_debug(ptr[0], reg, 0);                    \
        }
 
index 0d60e4f0af6659df6ddf4dd7bafe0dc34749c798..a900181e386786a9ae09a7bc49eaa9e5e39db84a 100644 (file)
@@ -178,13 +178,18 @@ void vcpu_write_spsr32(struct kvm_vcpu *vcpu, unsigned long v)
        switch (spsr_idx) {
        case KVM_SPSR_SVC:
                write_sysreg_el1(v, SYS_SPSR);
+               break;
        case KVM_SPSR_ABT:
                write_sysreg(v, spsr_abt);
+               break;
        case KVM_SPSR_UND:
                write_sysreg(v, spsr_und);
+               break;
        case KVM_SPSR_IRQ:
                write_sysreg(v, spsr_irq);
+               break;
        case KVM_SPSR_FIQ:
                write_sysreg(v, spsr_fiq);
+               break;
        }
 }
index f26e181d881c36f3bd15618a3e0813f56b84c446..2071260a275bd236923da5650da86a012eaa5b4a 100644 (file)
@@ -632,7 +632,7 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
         */
        val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
               | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
-       __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+       __vcpu_sys_reg(vcpu, r->reg) = val;
 }
 
 static bool check_pmu_access_disabled(struct kvm_vcpu *vcpu, u64 flags)
@@ -981,13 +981,13 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
 #define DBG_BCR_BVR_WCR_WVR_EL1(n)                                     \
        { SYS_DESC(SYS_DBGBVRn_EL1(n)),                                 \
-         trap_bvr, reset_bvr, n, 0, get_bvr, set_bvr },                \
+         trap_bvr, reset_bvr, 0, 0, get_bvr, set_bvr },                \
        { SYS_DESC(SYS_DBGBCRn_EL1(n)),                                 \
-         trap_bcr, reset_bcr, n, 0, get_bcr, set_bcr },                \
+         trap_bcr, reset_bcr, 0, 0, get_bcr, set_bcr },                \
        { SYS_DESC(SYS_DBGWVRn_EL1(n)),                                 \
-         trap_wvr, reset_wvr, n, 0,  get_wvr, set_wvr },               \
+         trap_wvr, reset_wvr, 0, 0,  get_wvr, set_wvr },               \
        { SYS_DESC(SYS_DBGWCRn_EL1(n)),                                 \
-         trap_wcr, reset_wcr, n, 0,  get_wcr, set_wcr }
+         trap_wcr, reset_wcr, 0, 0,  get_wcr, set_wcr }
 
 /* Macro to expand the PMEVCNTRn_EL0 register */
 #define PMU_PMEVCNTR_EL0(n)                                            \
@@ -1540,7 +1540,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
        { SYS_DESC(SYS_CTR_EL0), access_ctr },
 
-       { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, },
+       { SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
        { SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
        { SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
        { SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
@@ -2254,13 +2254,19 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
 }
 
 static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
-                             const struct sys_reg_desc *table, size_t num)
+                               const struct sys_reg_desc *table, size_t num,
+                               unsigned long *bmap)
 {
        unsigned long i;
 
        for (i = 0; i < num; i++)
-               if (table[i].reset)
+               if (table[i].reset) {
+                       int reg = table[i].reg;
+
                        table[i].reset(vcpu, &table[i]);
+                       if (reg > 0 && reg < NR_SYS_REGS)
+                               set_bit(reg, bmap);
+               }
 }
 
 /**
@@ -2774,18 +2780,16 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
 {
        size_t num;
        const struct sys_reg_desc *table;
-
-       /* Catch someone adding a register without putting in reset entry. */
-       memset(&vcpu->arch.ctxt.sys_regs, 0x42, sizeof(vcpu->arch.ctxt.sys_regs));
+       DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
 
        /* Generic chip reset first (so target could override). */
-       reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
+       reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
 
        table = get_target_table(vcpu->arch.target, true, &num);
-       reset_sys_reg_descs(vcpu, table, num);
+       reset_sys_reg_descs(vcpu, table, num, bmap);
 
        for (num = 1; num < NR_SYS_REGS; num++) {
-               if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
+               if (WARN(!test_bit(num, bmap),
                         "Didn't reset __vcpu_sys_reg(%zi)\n", num))
                        break;
        }
index 1d3f0b5a99400757bf361c4127e43f38c3916dee..bd2b039f43a622d6ce190cef0643ac8fb12dbe2d 100644 (file)
@@ -14,9 +14,7 @@
 pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
                unsigned long attrs)
 {
-       if (!dev_is_dma_coherent(dev) || (attrs & DMA_ATTR_WRITE_COMBINE))
-               return pgprot_writecombine(prot);
-       return prot;
+       return pgprot_writecombine(prot);
 }
 
 void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
index 1f730ded52245739e5aadcb404acdde23a10c573..cc88a08bc1f736422a561a093f3cd24cf757ea2b 100644 (file)
@@ -398,6 +398,7 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base)
        default:
                dev_err(dev, "Invalid ref_clk %u, using 100000000 instead\n",
                        clock_rate);
+               /* fall through */
        case 100000000:
                mpll_mul = 0x19;
                if (ref_clk_sel < 2)
index e0dd66881da68ce927bf17a9b9aa0ed064b0cc7a..f777e44653d5767b953483f22158d24e84e6461f 100644 (file)
@@ -69,6 +69,8 @@ static int __populate_cache_leaves(unsigned int cpu)
        if (c->tcache.waysize)
                populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED);
 
+       this_cpu_ci->cpu_map_populated = true;
+
        return 0;
 }
 
index 5f209f111e59e3ad9c6e31bee8352623cacc3e68..df7ddd246eaac730333bc24cc361f1893be100aa 100644 (file)
@@ -32,7 +32,8 @@ void __init setup_pit_timer(void)
 
 static int __init init_pit_clocksource(void)
 {
-       if (num_possible_cpus() > 1) /* PIT does not scale! */
+       if (num_possible_cpus() > 1 || /* PIT does not scale! */
+           !clockevent_state_periodic(&i8253_clockevent))
                return 0;
 
        return clocksource_i8253_init();
index e5de6bac81979122f0a8464d66c2df81c1eeafd2..754094b40a75332c1f8cb58266a5181a44ef142d 100644 (file)
@@ -140,6 +140,7 @@ static int kvm_compute_return_epc(struct kvm_vcpu *vcpu, unsigned long instpc,
                /* These are unconditional and in j_format. */
        case jal_op:
                arch->gprs[31] = instpc + 8;
+               /* fall through */
        case j_op:
                epc += 4;
                epc >>= 28;
index 2cfe839f0b3a776898595c480d66807d161910f4..1109924560d8c7c8a437e45fd1af5904a16a4075 100644 (file)
@@ -150,16 +150,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        return 0;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
 void kvm_mips_free_vcpus(struct kvm *kvm)
 {
        unsigned int i;
index 7c04b17f4a488aa8e50186be84dd0fcc50125ba2..96c13a0ab0788904d7e06319c26927f4a11da260 100644 (file)
@@ -172,12 +172,15 @@ static void mipsxx_cpu_setup(void *args)
        case 4:
                w_c0_perfctrl3(0);
                w_c0_perfcntr3(reg.counter[3]);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(0);
                w_c0_perfcntr2(reg.counter[2]);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(0);
                w_c0_perfcntr1(reg.counter[1]);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(0);
                w_c0_perfcntr0(reg.counter[0]);
@@ -195,10 +198,13 @@ static void mipsxx_cpu_start(void *args)
        switch (counters) {
        case 4:
                w_c0_perfctrl3(WHAT | reg.control[3]);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(WHAT | reg.control[2]);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(WHAT | reg.control[1]);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(WHAT | reg.control[0]);
        }
@@ -215,10 +221,13 @@ static void mipsxx_cpu_stop(void *args)
        switch (counters) {
        case 4:
                w_c0_perfctrl3(0);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(0);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(0);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(0);
        }
@@ -236,6 +245,7 @@ static int mipsxx_perfcount_handler(void)
 
        switch (counters) {
 #define HANDLE_COUNTER(n)                                              \
+       /* fall through */                                              \
        case n + 1:                                                     \
                control = r_c0_perfctrl ## n();                         \
                counter = r_c0_perfcntr ## n();                         \
@@ -297,12 +307,15 @@ static void reset_counters(void *arg)
        case 4:
                w_c0_perfctrl3(0);
                w_c0_perfcntr3(0);
+               /* fall through */
        case 3:
                w_c0_perfctrl2(0);
                w_c0_perfcntr2(0);
+               /* fall through */
        case 2:
                w_c0_perfctrl1(0);
                w_c0_perfcntr1(0);
+               /* fall through */
        case 1:
                w_c0_perfctrl0(0);
                w_c0_perfcntr0(0);
index d02eb9d16b55590e9740d1bde1e1b1178569896a..925c72348fb6ea5c95d1483acb7875c6bc613045 100644 (file)
@@ -474,6 +474,7 @@ static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
                if (PCI_SLOT(devfn) == 0)
                        return bcm_pcie_readl(PCIE_DLSTATUS_REG)
                                        & DLSTATUS_PHYLINKUP;
+               /* else, fall through */
        default:
                return false;
        }
index 55c1396580a4b051c2b2efa6bbf9173a4966d152..3747a0cbd3b8fc1b150e67fb067c3994149119e1 100644 (file)
@@ -18,4 +18,4 @@ obj-y  := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
 # other very old or stripped-down PA-RISC CPUs -- not currently supported
 
 obj-$(CONFIG_MATH_EMULATION)   += unimplemented-math-emulation.o
-CFLAGS_REMOVE_fpudispatch.o    = -Wimplicit-fallthrough=3
+CFLAGS_REMOVE_fpudispatch.o    = -Wimplicit-fallthrough
index 77f6ebf97113cea548e360c942b81041a7b10027..d8dcd8820369eb4be85e4493bf325779f3645e5f 100644 (file)
@@ -121,7 +121,6 @@ config PPC
        select ARCH_32BIT_OFF_T if PPC32
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEVMEM_IS_ALLOWED
-       select ARCH_HAS_DMA_MMAP_PGPROT
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
index b3388d95f4510e0d919f8d068cb2b191a675ae26..45e3137ccd71c21fb835a1938c8cd36aa16d5949 100644 (file)
@@ -107,22 +107,22 @@ extern void _set_L3CR(unsigned long);
 
 static inline void dcbz(void *addr)
 {
-       __asm__ __volatile__ ("dcbz %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbz 0, %0" : : "r"(addr) : "memory");
 }
 
 static inline void dcbi(void *addr)
 {
-       __asm__ __volatile__ ("dcbi %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbi 0, %0" : : "r"(addr) : "memory");
 }
 
 static inline void dcbf(void *addr)
 {
-       __asm__ __volatile__ ("dcbf %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbf 0, %0" : : "r"(addr) : "memory");
 }
 
 static inline void dcbst(void *addr)
 {
-       __asm__ __volatile__ ("dcbst %y0" : : "Z"(*(u8 *)addr) : "memory");
+       __asm__ __volatile__ ("dcbst 0, %0" : : "r"(addr) : "memory");
 }
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
index ea0c692367892381f4e2984efc26e474066627c2..56dfa7a2a6f2a09f7d3d3d385147f4b77714932c 100644 (file)
@@ -49,8 +49,7 @@ obj-y                         := cputable.o ptrace.o syscalls.o \
                                   signal.o sysfs.o cacheinfo.o time.o \
                                   prom.o traps.o setup-common.o \
                                   udbg.o misc.o io.o misc_$(BITS).o \
-                                  of_platform.o prom_parse.o \
-                                  dma-common.o
+                                  of_platform.o prom_parse.o
 obj-$(CONFIG_PPC64)            += setup_64.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
                                   paca.o nvram_64.o firmware.o
diff --git a/arch/powerpc/kernel/dma-common.c b/arch/powerpc/kernel/dma-common.c
deleted file mode 100644 (file)
index dc7ef6b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Contains common dma routines for all powerpc platforms.
- *
- * Copyright (C) 2019 Shawn Anastasio.
- */
-
-#include <linux/mm.h>
-#include <linux/dma-noncoherent.h>
-
-pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
-               unsigned long attrs)
-{
-       if (!dev_is_dma_coherent(dev))
-               return pgprot_noncached(prot);
-       return prot;
-}
index 0dba7eb24f92072616460ae7cee6f90205025917..3e566c2e6066748c82cb3c43eed2fe27d255f982 100644 (file)
@@ -50,6 +50,11 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
        return !!(v->arch.pending_exceptions) || kvm_request_pending(v);
 }
 
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       return kvm_arch_vcpu_runnable(vcpu);
+}
+
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
 {
        return false;
@@ -452,16 +457,6 @@ err_out:
        return -EINVAL;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        unsigned int i;
index 93205c0bf71df1b066f25abbaf8945ae0fbbe880..3efff552a261e2745bd0fd05dd873125d6877e19 100644 (file)
@@ -54,6 +54,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
 CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
 CONFIG_SPI=y
 CONFIG_SPI_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
index d5449ef805a340eba735b3ac7a1688cbdcd2b30e..7da93e494445e10bfbc4e1c715d30a5a387011e2 100644 (file)
@@ -34,6 +34,7 @@ CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
@@ -53,6 +54,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
 CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
index 853b65ef656da42d52b5c3c46f9ac8f75ce8774d..f0227bdce0f0614925ae772dc80588b8828f2ec0 100644 (file)
@@ -16,7 +16,13 @@ extern void __fstate_restore(struct task_struct *restore_from);
 
 static inline void __fstate_clean(struct pt_regs *regs)
 {
-       regs->sstatus |= (regs->sstatus & ~(SR_FS)) | SR_FS_CLEAN;
+       regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_CLEAN;
+}
+
+static inline void fstate_off(struct task_struct *task,
+                             struct pt_regs *regs)
+{
+       regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_OFF;
 }
 
 static inline void fstate_save(struct task_struct *task,
index 687dd19735a7e6483afb98a319376706ed426cef..4d9bbe8438bf6a7cff301cfd2c6fec0d268a607c 100644 (file)
@@ -53,10 +53,17 @@ static inline void remote_sfence_vma(struct cpumask *cmask, unsigned long start,
 }
 
 #define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
-#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
+
 #define flush_tlb_range(vma, start, end) \
        remote_sfence_vma(mm_cpumask((vma)->vm_mm), start, (end) - (start))
-#define flush_tlb_mm(mm) \
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                                 unsigned long addr)
+{
+       flush_tlb_range(vma, addr, addr + PAGE_SIZE);
+}
+
+#define flush_tlb_mm(mm)                               \
        remote_sfence_vma(mm_cpumask(mm), 0, -1)
 
 #endif /* CONFIG_SMP */
index f23794bd1e90c2f1dad70d1d9ed18507c2b58cd1..fb3a082362eb87554ff297f3e026d9663c5a8044 100644 (file)
@@ -64,8 +64,14 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
        unsigned long sp)
 {
        regs->sstatus = SR_SPIE;
-       if (has_fpu)
+       if (has_fpu) {
                regs->sstatus |= SR_FS_INITIAL;
+               /*
+                * Restore the initial value to the FP register
+                * before starting the user program.
+                */
+               fstate_restore(current, regs);
+       }
        regs->sepc = pc;
        regs->sp = sp;
        set_fs(USER_DS);
@@ -75,10 +81,11 @@ void flush_thread(void)
 {
 #ifdef CONFIG_FPU
        /*
-        * Reset FPU context
+        * Reset FPU state and context
         *      frm: round to nearest, ties to even (IEEE default)
         *      fflags: accrued exceptions cleared
         */
+       fstate_off(current, task_pt_regs(current));
        memset(&current->thread.fstate, 0, sizeof(current->thread.fstate));
 #endif
 }
index 8e364ebf37dedf325f5a415d866bfdf30b08bb25..267feaa10f6ad2f3ad5a7b8bdf82a86ac434c7aa 100644 (file)
@@ -5,5 +5,3 @@ lib-y   += memset.o
 lib-y  += uaccess.o
 
 lib-$(CONFIG_64BIT) += tishift.o
-
-lib-$(CONFIG_32BIT) += udivdi3.o
index 87ff89e88f2ca95bfc1fb47e10e0cb7e88b0880a..f51c9a03bca1e7ca4c71faecba4c2e4b5f9e0d65 100644 (file)
@@ -81,9 +81,13 @@ EXPORT_SYMBOL(__delay);
 void udelay(unsigned long usecs)
 {
        u64 ucycles = (u64)usecs * lpj_fine * UDELAY_MULT;
+       u64 n;
 
        if (unlikely(usecs > MAX_UDELAY_US)) {
-               __delay((u64)usecs * riscv_timebase / 1000000ULL);
+               n = (u64)usecs * riscv_timebase;
+               do_div(n, 1000000);
+
+               __delay(n);
                return;
        }
 
diff --git a/arch/riscv/lib/udivdi3.S b/arch/riscv/lib/udivdi3.S
deleted file mode 100644 (file)
index 3f07476..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2016-2017 Free Software Foundation, Inc.
- */
-
-#include <linux/linkage.h>
-
-ENTRY(__udivdi3)
-       mv      a2, a1
-       mv      a1, a0
-       li      a0, -1
-       beqz    a2, .L5
-       li      a3, 1
-       bgeu    a2, a1, .L2
-.L1:
-       blez    a2, .L2
-       slli    a2, a2, 1
-       slli    a3, a3, 1
-       bgtu    a1, a2, .L1
-.L2:
-       li      a0, 0
-.L3:
-       bltu    a1, a2, .L4
-       sub     a1, a1, a2
-       or      a0, a0, a3
-.L4:
-       srli    a3, a3, 1
-       srli    a2, a2, 1
-       bnez    a3, .L3
-.L5:
-       ret
-ENDPROC(__udivdi3)
index 3c49bde8aa5e3d6f82d3e1c2157b35421e9cd7e4..b8aa6a9f937b2e27839f27ab598adab074e706a3 100644 (file)
@@ -48,9 +48,7 @@ void store_ipl_parmblock(void)
 {
        int rc;
 
-       uv_set_shared(__pa(&ipl_block));
        rc = __diag308(DIAG308_STORE, &ipl_block);
-       uv_remove_shared(__pa(&ipl_block));
        if (rc == DIAG308_RC_OK &&
            ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
                ipl_block_valid = 1;
index ac06c3949ab342eb521a9161a4c1197f428eab39..34bdc60c0b11d348946b2b363e76fb7b6dcdf195 100644 (file)
@@ -114,12 +114,8 @@ recursion_check:
         * If it comes up a second time then there's something wrong going on:
         * just break out and report an unknown stack type.
         */
-       if (*visit_mask & (1UL << info->type)) {
-               printk_deferred_once(KERN_WARNING
-                       "WARNING: stack recursion on stack type %d\n",
-                       info->type);
+       if (*visit_mask & (1UL << info->type))
                goto unknown;
-       }
        *visit_mask |= 1UL << info->type;
        return 0;
 unknown:
index 5aea1a527443004f455f56637f017d023077ab19..f384a18e6c2609ef50c03afb288575893b2730c1 100644 (file)
@@ -60,12 +60,5 @@ ENTRY(startup_continue)
 
        .align  16
 .LPG1:
-.Lpcmsk:.quad  0x0000000180000000
-.L4malign:.quad 0xffffffffffc00000
-.Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
-.Lnop: .long   0x07000700
-.Lparmaddr:
-       .quad   PARMAREA
-       .align  64
 .Ldw:  .quad   0x0002000180000000,0x0000000000000000
 .Laregs:.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
index 2c0a515428d61879082bcdcc42fe4558ef8dc664..6837affc19e8185cef726000b5eca49971a1c1d5 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/os_info.h>
 #include <asm/sections.h>
 #include <asm/boot_data.h>
-#include <asm/uv.h>
 #include "entry.h"
 
 #define IPL_PARM_BLOCK_VERSION 0
@@ -892,21 +891,15 @@ static void __reipl_run(void *unused)
 {
        switch (reipl_type) {
        case IPL_TYPE_CCW:
-               uv_set_shared(__pa(reipl_block_ccw));
                diag308(DIAG308_SET, reipl_block_ccw);
-               uv_remove_shared(__pa(reipl_block_ccw));
                diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case IPL_TYPE_FCP:
-               uv_set_shared(__pa(reipl_block_fcp));
                diag308(DIAG308_SET, reipl_block_fcp);
-               uv_remove_shared(__pa(reipl_block_fcp));
                diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case IPL_TYPE_NSS:
-               uv_set_shared(__pa(reipl_block_nss));
                diag308(DIAG308_SET, reipl_block_nss);
-               uv_remove_shared(__pa(reipl_block_nss));
                diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case IPL_TYPE_UNKNOWN:
@@ -1176,9 +1169,7 @@ static struct kset *dump_kset;
 
 static void diag308_dump(void *dump_block)
 {
-       uv_set_shared(__pa(dump_block));
        diag308(DIAG308_SET, dump_block);
-       uv_remove_shared(__pa(dump_block));
        while (1) {
                if (diag308(DIAG308_LOAD_NORMAL_DUMP, NULL) != 0x302)
                        break;
index 2b94b0ad358827d4e961a3fbce8be9bd5fb41cd2..2531779009503700f7d117e56f11c81df20d2108 100644 (file)
@@ -1114,8 +1114,7 @@ void __init setup_arch(char **cmdline_p)
 
         ROOT_DEV = Root_RAM0;
 
-       /* Is init_mm really needed? */
-       init_mm.start_code = PAGE_OFFSET;
+       init_mm.start_code = (unsigned long) _text;
        init_mm.end_code = (unsigned long) _etext;
        init_mm.end_data = (unsigned long) _edata;
        init_mm.brk = (unsigned long) _end;
index 243d8b1185bfcdbf39d0480aa7245f11c7eb89cc..c6bc190f3c28c967604fc50d099cc05f25278736 100644 (file)
@@ -216,11 +216,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        if (!vdso_enabled)
                return 0;
-       /*
-        * Only map the vdso for dynamically linked elf binaries.
-        */
-       if (!uses_interp)
-               return 0;
 
        vdso_pages = vdso64_pages;
 #ifdef CONFIG_COMPAT_VDSO
index 49d55327de0bcaa2412d035a58a4f1a4fe3dca79..7e0eb40209177ad1014d34d9c1fc3360fa8d1b24 100644 (file)
@@ -32,10 +32,9 @@ PHDRS {
 SECTIONS
 {
        . = 0x100000;
-       _stext = .;             /* Start of text section */
        .text : {
-               /* Text and read-only data */
-               _text = .;
+               _stext = .;             /* Start of text section */
+               _text = .;              /* Text and read-only data */
                HEAD_TEXT
                TEXT_TEXT
                SCHED_TEXT
@@ -47,11 +46,10 @@ SECTIONS
                *(.text.*_indirect_*)
                *(.fixup)
                *(.gnu.warning)
+               . = ALIGN(PAGE_SIZE);
+               _etext = .;             /* End of text section */
        } :text = 0x0700
 
-       . = ALIGN(PAGE_SIZE);
-       _etext = .;             /* End of text section */
-
        NOTES :text :note
 
        .dummy : { *(.dummy) } :data
index 3f520cd837fb8ccea849adc1b36d7e4a2026090b..f329dcb3f44cda289d7ab9291c57a153a307d686 100644 (file)
@@ -2516,16 +2516,6 @@ out_err:
        return rc;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
-{
-       return 0;
-}
-
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
        VCPU_EVENT(vcpu, 3, "%s", "free cpu");
index 3b93ba0b5d8d6e03b3289f861c4f244681e2826f..5d67b81c704a49214b500c3fce7af3f728860353 100644 (file)
@@ -161,9 +161,9 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
        }
 #endif
 
-       for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++) {
+       pmd = pmd_offset(pud, addr);
+       for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++, pmd++) {
                st->current_address = addr;
-               pmd = pmd_offset(pud, addr);
                if (!pmd_none(*pmd)) {
                        if (pmd_large(*pmd)) {
                                prot = pmd_val(*pmd) &
@@ -192,9 +192,9 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
        }
 #endif
 
-       for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++) {
+       pud = pud_offset(p4d, addr);
+       for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++, pud++) {
                st->current_address = addr;
-               pud = pud_offset(p4d, addr);
                if (!pud_none(*pud))
                        if (pud_large(*pud)) {
                                prot = pud_val(*pud) &
@@ -222,9 +222,9 @@ static void walk_p4d_level(struct seq_file *m, struct pg_state *st,
        }
 #endif
 
-       for (i = 0; i < PTRS_PER_P4D && addr < max_addr; i++) {
+       p4d = p4d_offset(pgd, addr);
+       for (i = 0; i < PTRS_PER_P4D && addr < max_addr; i++, p4d++) {
                st->current_address = addr;
-               p4d = p4d_offset(pgd, addr);
                if (!p4d_none(*p4d))
                        walk_pud_level(m, st, p4d, addr);
                else
index 884a9caff5fb8be71c80fce894d78ef1fe5f955d..f4f4c2c6dee9eeae8a0b197538ed16d7cf1ed51d 100644 (file)
@@ -11,8 +11,7 @@ chkbss: $(addprefix $(obj)/, $(chkbss-files))
 
 quiet_cmd_chkbss = CHKBSS  $<
       cmd_chkbss = \
-       if $(OBJDUMP) -h $< | grep -q "\.bss" && \
-          ! $(OBJDUMP) -j .bss -w -h $< | awk 'END { if ($$3) exit 1 }'; then \
+       if ! $(OBJSIZE) --common $< | $(AWK) 'END { if ($$3) exit 1 }'; then \
                echo "error: $< .bss section is not empty" >&2; exit 1; \
        fi; \
        touch $@;
index defebf1a9c8af223ad6ea4ed9af2f315acbc2202..845543780cc5501406f0817bf3312ef5aedd4bdb 100644 (file)
@@ -475,8 +475,6 @@ static void print_sh_insn(u32 memaddr, u16 insn)
                                printk("dbr");
                                break;
                        case FD_REG_N:
-                               if (0)
-                                       goto d_reg_n;
                        case F_REG_N:
                                printk("fr%d", rn);
                                break;
@@ -488,7 +486,7 @@ static void print_sh_insn(u32 memaddr, u16 insn)
                                        printk("xd%d", rn & ~1);
                                        break;
                                }
-                       d_reg_n:
+                               /* else, fall through */
                        case D_REG_N:
                                printk("dr%d", rn);
                                break;
@@ -497,6 +495,7 @@ static void print_sh_insn(u32 memaddr, u16 insn)
                                        printk("xd%d", rm & ~1);
                                        break;
                                }
+                               /* else, fall through */
                        case D_REG_M:
                                printk("dr%d", rm);
                                break;
index 3bd010b4c55f58e49f0e761693bab35dd070c36d..f10d64311127baa9aca0a80003fda2ed9aeecf3f 100644 (file)
@@ -157,6 +157,7 @@ int arch_bp_generic_fields(int sh_len, int sh_type,
        switch (sh_type) {
        case SH_BREAKPOINT_READ:
                *gen_type = HW_BREAKPOINT_R;
+               break;
        case SH_BREAKPOINT_WRITE:
                *gen_type = HW_BREAKPOINT_W;
                break;
index 401e30ca0a7589e73b0ad2bec7b0c28963de2602..8272a44928444ec6a679819db52c6e1adefc5f80 100644 (file)
@@ -37,6 +37,14 @@ int memcmp(const void *s1, const void *s2, size_t len)
        return diff;
 }
 
+/*
+ * Clang may lower `memcmp == 0` to `bcmp == 0`.
+ */
+int bcmp(const void *s1, const void *s2, size_t len)
+{
+       return memcmp(s1, s2, len);
+}
+
 int strcmp(const char *str1, const char *str2)
 {
        const unsigned char *s1 = (const unsigned char *)str1;
index 101eb944f13c2c8ad6b4d9af9ec8e3264fb1f5a7..f5e90a849bca6c1ab6493d03b0d7ad76a69086f9 100644 (file)
  * Note: efi_info is commonly left uninitialized, but that field has a
  * private magic, so it is better to leave it unchanged.
  */
+
+#define sizeof_mbr(type, member) ({ sizeof(((type *)0)->member); })
+
+#define BOOT_PARAM_PRESERVE(struct_member)                             \
+       {                                                               \
+               .start = offsetof(struct boot_params, struct_member),   \
+               .len   = sizeof_mbr(struct boot_params, struct_member), \
+       }
+
+struct boot_params_to_save {
+       unsigned int start;
+       unsigned int len;
+};
+
 static void sanitize_boot_params(struct boot_params *boot_params)
 {
        /* 
@@ -35,21 +49,40 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         * problems again.
         */
        if (boot_params->sentinel) {
-               /* fields in boot_params are left uninitialized, clear them */
-               boot_params->acpi_rsdp_addr = 0;
-               memset(&boot_params->ext_ramdisk_image, 0,
-                      (char *)&boot_params->efi_info -
-                       (char *)&boot_params->ext_ramdisk_image);
-               memset(&boot_params->kbd_status, 0,
-                      (char *)&boot_params->hdr -
-                      (char *)&boot_params->kbd_status);
-               memset(&boot_params->_pad7[0], 0,
-                      (char *)&boot_params->edd_mbr_sig_buffer[0] -
-                       (char *)&boot_params->_pad7[0]);
-               memset(&boot_params->_pad8[0], 0,
-                      (char *)&boot_params->eddbuf[0] -
-                       (char *)&boot_params->_pad8[0]);
-               memset(&boot_params->_pad9[0], 0, sizeof(boot_params->_pad9));
+               static struct boot_params scratch;
+               char *bp_base = (char *)boot_params;
+               char *save_base = (char *)&scratch;
+               int i;
+
+               const struct boot_params_to_save to_save[] = {
+                       BOOT_PARAM_PRESERVE(screen_info),
+                       BOOT_PARAM_PRESERVE(apm_bios_info),
+                       BOOT_PARAM_PRESERVE(tboot_addr),
+                       BOOT_PARAM_PRESERVE(ist_info),
+                       BOOT_PARAM_PRESERVE(acpi_rsdp_addr),
+                       BOOT_PARAM_PRESERVE(hd0_info),
+                       BOOT_PARAM_PRESERVE(hd1_info),
+                       BOOT_PARAM_PRESERVE(sys_desc_table),
+                       BOOT_PARAM_PRESERVE(olpc_ofw_header),
+                       BOOT_PARAM_PRESERVE(efi_info),
+                       BOOT_PARAM_PRESERVE(alt_mem_k),
+                       BOOT_PARAM_PRESERVE(scratch),
+                       BOOT_PARAM_PRESERVE(e820_entries),
+                       BOOT_PARAM_PRESERVE(eddbuf_entries),
+                       BOOT_PARAM_PRESERVE(edd_mbr_sig_buf_entries),
+                       BOOT_PARAM_PRESERVE(edd_mbr_sig_buffer),
+                       BOOT_PARAM_PRESERVE(e820_table),
+                       BOOT_PARAM_PRESERVE(eddbuf),
+               };
+
+               memset(&scratch, 0, sizeof(scratch));
+
+               for (i = 0; i < ARRAY_SIZE(to_save); i++) {
+                       memcpy(save_base + to_save[i].start,
+                              bp_base + to_save[i].start, to_save[i].len);
+               }
+
+               memcpy(boot_params, save_base, sizeof(*boot_params));
        }
 }
 
index 7b0a4ee7731312730338343bcb97c73fcdfed38e..74e88e5edd9cf42792cd6e17fa4f5f516b91eff8 100644 (file)
@@ -35,6 +35,8 @@
 #include <asm/kvm_vcpu_regs.h>
 #include <asm/hyperv-tlfs.h>
 
+#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
+
 #define KVM_MAX_VCPUS 288
 #define KVM_SOFT_MAX_VCPUS 240
 #define KVM_MAX_VCPU_ID 1023
@@ -1175,6 +1177,7 @@ struct kvm_x86_ops {
        int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq,
                              uint32_t guest_irq, bool set);
        void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
+       bool (*dy_apicv_has_pending_interrupt)(struct kvm_vcpu *vcpu);
 
        int (*set_hv_timer)(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc,
                            bool *expired);
index 1492799b8f43f93b3cc9c196893cfea1a5719a4f..ee2d91e382f1c576aead6dc28b719c5129c85a16 100644 (file)
@@ -184,7 +184,8 @@ void __init default_setup_apic_routing(void)
                                def_to_bigsmp = 0;
                                break;
                        }
-                       /* If P4 and above fall through */
+                       /* P4 and above */
+                       /* fall through */
                case X86_VENDOR_HYGON:
                case X86_VENDOR_AMD:
                        def_to_bigsmp = 1;
index 4296c702a3f71bdc33fa83081b5ea797a564980e..72182809b3339bc610c5c1fa23633ee236d66359 100644 (file)
@@ -98,6 +98,7 @@ cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
        case 7:
                if (size < 0x40)
                        break;
+               /* Else, fall through */
        case 6:
        case 5:
        case 4:
index 6a204e7336c12211de4de8fcf3ba1477f1d39160..32b4dc9030aa9fbcd482b39ef427b5804ec6499c 100644 (file)
  */
 static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
 
+/*
+ * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
+ * hardware or BIOS before kernel boot.
+ */
+static u32 orig_umwait_control_cached __ro_after_init;
+
 /*
  * Serialize access to umwait_control_cached and IA32_UMWAIT_CONTROL MSR in
  * the sysfs write functions.
@@ -52,6 +58,23 @@ static int umwait_cpu_online(unsigned int cpu)
        return 0;
 }
 
+/*
+ * The CPU hotplug callback sets the control MSR to the original control
+ * value.
+ */
+static int umwait_cpu_offline(unsigned int cpu)
+{
+       /*
+        * This code is protected by the CPU hotplug already and
+        * orig_umwait_control_cached is never changed after it caches
+        * the original control MSR value in umwait_init(). So there
+        * is no race condition here.
+        */
+       wrmsr(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached, 0);
+
+       return 0;
+}
+
 /*
  * On resume, restore IA32_UMWAIT_CONTROL MSR on the boot processor which
  * is the only active CPU at this time. The MSR is set up on the APs via the
@@ -185,8 +208,22 @@ static int __init umwait_init(void)
        if (!boot_cpu_has(X86_FEATURE_WAITPKG))
                return -ENODEV;
 
+       /*
+        * Cache the original control MSR value before the control MSR is
+        * changed. This is the only place where orig_umwait_control_cached
+        * is modified.
+        */
+       rdmsrl(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached);
+
        ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "umwait:online",
-                               umwait_cpu_online, NULL);
+                               umwait_cpu_online, umwait_cpu_offline);
+       if (ret < 0) {
+               /*
+                * On failure, the control MSR on all CPUs has the
+                * original control value.
+                */
+               return ret;
+       }
 
        register_syscore_ops(&umwait_syscore_ops);
 
index b7f34fe2171e472f7f64bf7f93c9bdfcaefba710..4ab377c9fffede8af8c93b620bdb9d90803fd353 100644 (file)
@@ -308,9 +308,6 @@ static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
 
 static void kvm_guest_cpu_init(void)
 {
-       if (!kvm_para_available())
-               return;
-
        if (kvm_para_has_feature(KVM_FEATURE_ASYNC_PF) && kvmapf) {
                u64 pa = slow_virt_to_phys(this_cpu_ptr(&apf_reason));
 
@@ -625,9 +622,6 @@ static void __init kvm_guest_init(void)
 {
        int i;
 
-       if (!kvm_para_available())
-               return;
-
        paravirt_ops_setup();
        register_reboot_notifier(&kvm_pv_reboot_nb);
        for (i = 0; i < KVM_TASK_SLEEP_HASHSIZE; i++)
@@ -848,8 +842,6 @@ asm(
  */
 void __init kvm_spinlock_init(void)
 {
-       if (!kvm_para_available())
-               return;
        /* Does host kernel support KVM_FEATURE_PV_UNHALT? */
        if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
                return;
index 0fdbe89d0754058c6d61be12e42134b1a4359045..3c5bbe8e412087f15cf3280a43c921fe32f54e0a 100644 (file)
@@ -201,6 +201,7 @@ static int set_segment_reg(struct task_struct *task,
        case offsetof(struct user_regs_struct, ss):
                if (unlikely(value == 0))
                        return -EIO;
+               /* Else, fall through */
 
        default:
                *pt_regs_access(task_pt_regs(task), offset) = value;
index 329361b69d5e38fbb598fd40b652112f92057ac8..018aebce33ff407f764d17151c3d3647e8014263 100644 (file)
@@ -8,11 +8,6 @@
 #include <linux/debugfs.h>
 #include "lapic.h"
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return true;
-}
-
 static int vcpu_get_timer_advance_ns(void *data, u64 *val)
 {
        struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
@@ -48,37 +43,22 @@ static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val)
 
 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_frac_fops, vcpu_get_tsc_scaling_frac_bits, NULL, "%llu\n");
 
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
+void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
-       struct dentry *ret;
-
-       ret = debugfs_create_file("tsc-offset", 0444,
-                                                       vcpu->debugfs_dentry,
-                                                       vcpu, &vcpu_tsc_offset_fops);
-       if (!ret)
-               return -ENOMEM;
+       debugfs_create_file("tsc-offset", 0444, vcpu->debugfs_dentry, vcpu,
+                           &vcpu_tsc_offset_fops);
 
-       if (lapic_in_kernel(vcpu)) {
-               ret = debugfs_create_file("lapic_timer_advance_ns", 0444,
-                                                               vcpu->debugfs_dentry,
-                                                               vcpu, &vcpu_timer_advance_ns_fops);
-               if (!ret)
-                       return -ENOMEM;
-       }
+       if (lapic_in_kernel(vcpu))
+               debugfs_create_file("lapic_timer_advance_ns", 0444,
+                                   vcpu->debugfs_dentry, vcpu,
+                                   &vcpu_timer_advance_ns_fops);
 
        if (kvm_has_tsc_control) {
-               ret = debugfs_create_file("tsc-scaling-ratio", 0444,
-                                                       vcpu->debugfs_dentry,
-                                                       vcpu, &vcpu_tsc_scaling_fops);
-               if (!ret)
-                       return -ENOMEM;
-               ret = debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
-                                                       vcpu->debugfs_dentry,
-                                                       vcpu, &vcpu_tsc_scaling_frac_fops);
-               if (!ret)
-                       return -ENOMEM;
-
+               debugfs_create_file("tsc-scaling-ratio", 0444,
+                                   vcpu->debugfs_dentry, vcpu,
+                                   &vcpu_tsc_scaling_fops);
+               debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
+                                   vcpu->debugfs_dentry, vcpu,
+                                   &vcpu_tsc_scaling_frac_fops);
        }
-
-       return 0;
 }
index 0aa158657f20cff83270f4251d1294030076c1bb..685d17c1146106a5ebf8333c02bd5f029a47d071 100644 (file)
@@ -1548,7 +1548,6 @@ static void kvm_apic_inject_pending_timer_irqs(struct kvm_lapic *apic)
 static void apic_timer_expired(struct kvm_lapic *apic)
 {
        struct kvm_vcpu *vcpu = apic->vcpu;
-       struct swait_queue_head *q = &vcpu->wq;
        struct kvm_timer *ktimer = &apic->lapic_timer;
 
        if (atomic_read(&apic->lapic_timer.pending))
@@ -1566,13 +1565,6 @@ static void apic_timer_expired(struct kvm_lapic *apic)
 
        atomic_inc(&apic->lapic_timer.pending);
        kvm_set_pending_timer(vcpu);
-
-       /*
-        * For x86, the atomic_inc() is serialized, thus
-        * using swait_active() is safe.
-        */
-       if (swait_active(q))
-               swake_up_one(q);
 }
 
 static void start_sw_tscdeadline(struct kvm_lapic *apic)
index 7eafc6907861e6d0f6b9ccfac1b2b6071238cd82..d685491fce4d1091f0b0bf0382cfa5d0fe77796e 100644 (file)
@@ -5190,6 +5190,11 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
                kvm_vcpu_wake_up(vcpu);
 }
 
+static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+       return false;
+}
+
 static void svm_ir_list_del(struct vcpu_svm *svm, struct amd_iommu_pi_data *pi)
 {
        unsigned long flags;
@@ -7314,6 +7319,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 
        .pmu_ops = &amd_pmu_ops,
        .deliver_posted_interrupt = svm_deliver_avic_intr,
+       .dy_apicv_has_pending_interrupt = svm_dy_apicv_has_pending_interrupt,
        .update_pi_irte = svm_update_pi_irte,
        .setup_mce = svm_setup_mce,
 
index 074385c86c094be7c79606392dd840118331b9ef..42ed3faa6af8364733b4900895e4b503934538ec 100644 (file)
@@ -6117,6 +6117,11 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
        return max_irr;
 }
 
+static bool vmx_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
+{
+       return pi_test_on(vcpu_to_pi_desc(vcpu));
+}
+
 static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
 {
        if (!kvm_vcpu_apicv_active(vcpu))
@@ -7726,6 +7731,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
        .sync_pir_to_irr = vmx_sync_pir_to_irr,
        .deliver_posted_interrupt = vmx_deliver_posted_interrupt,
+       .dy_apicv_has_pending_interrupt = vmx_dy_apicv_has_pending_interrupt,
 
        .set_tss_addr = vmx_set_tss_addr,
        .set_identity_map_addr = vmx_set_identity_map_addr,
index c6d951cbd76ce794866495b8658b37c751421f7e..93b0bd45ac738f6fefea3c7a834758d2e5d91340 100644 (file)
@@ -9698,6 +9698,22 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
        return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
 }
 
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       if (READ_ONCE(vcpu->arch.pv.pv_unhalted))
+               return true;
+
+       if (kvm_test_request(KVM_REQ_NMI, vcpu) ||
+               kvm_test_request(KVM_REQ_SMI, vcpu) ||
+                kvm_test_request(KVM_REQ_EVENT, vcpu))
+               return true;
+
+       if (vcpu->arch.apicv_active && kvm_x86_ops->dy_apicv_has_pending_interrupt(vcpu))
+               return true;
+
+       return false;
+}
+
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.preempted_in_kernel;
index 04967cdce5d12c97441c030405a90a7f2e79e1fa..7ad68917a51e8e123eb19b0d5d3956870aee56ed 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <linux/types.h>
 #include <linux/export.h>
+#include <asm/cpu.h>
 
 unsigned int x86_family(unsigned int sig)
 {
index 6b468517ab7167fcffd0fed7f4f0134e71f70b50..73dc66d887f354a78d9e48efcee214be22cb866a 100644 (file)
@@ -178,13 +178,15 @@ void FPU_printall(void)
        for (i = 0; i < 8; i++) {
                FPU_REG *r = &st(i);
                u_char tagi = FPU_gettagi(i);
+
                switch (tagi) {
                case TAG_Empty:
                        continue;
-                       break;
                case TAG_Zero:
                case TAG_Special:
+                       /* Update tagi for the printk below */
                        tagi = FPU_Special(r);
+                       /* fall through */
                case TAG_Valid:
                        printk("st(%d)  %c .%04lx %04lx %04lx %04lx e%+-6d ", i,
                               getsign(r) ? '-' : '+',
@@ -198,7 +200,6 @@ void FPU_printall(void)
                        printk("Whoops! Error in errors.c: tag%d is %d ", i,
                               tagi);
                        continue;
-                       break;
                }
                printk("%s\n", tag_desc[(int)(unsigned)tagi]);
        }
index 783c509f957a6975401d5c9a5693468f5027d57e..127ea54122d75f48b97633cfa96b589ada8f5f19 100644 (file)
@@ -1352,7 +1352,7 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
                case TW_Denormal:
                        if (denormal_operand() < 0)
                                return;
-
+                       /* fall through */
                case TAG_Zero:
                case TAG_Valid:
                        setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
index eaaed5bfc4a4429a92e980252c2f993047eb90bb..991549a1c5f3ae193aedd8ae9abae4148aed0a5f 100644 (file)
@@ -390,8 +390,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
 
        emit_prologue(&prog, bpf_prog->aux->stack_depth,
                      bpf_prog_was_classic(bpf_prog));
+       addrs[0] = prog - temp;
 
-       for (i = 0; i < insn_cnt; i++, insn++) {
+       for (i = 1; i <= insn_cnt; i++, insn++) {
                const s32 imm32 = insn->imm;
                u32 dst_reg = insn->dst_reg;
                u32 src_reg = insn->src_reg;
@@ -1105,7 +1106,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                extra_pass = true;
                goto skip_init_addrs;
        }
-       addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL);
+       addrs = kmalloc_array(prog->len + 1, sizeof(*addrs), GFP_KERNEL);
        if (!addrs) {
                prog = orig_prog;
                goto out_addrs;
@@ -1115,7 +1116,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
         * Before first pass, make a rough estimation of addrs[]
         * each BPF instruction is translated to less than 64 bytes
         */
-       for (proglen = 0, i = 0; i < prog->len; i++) {
+       for (proglen = 0, i = 0; i <= prog->len; i++) {
                proglen += 64;
                addrs[i] = proglen;
        }
@@ -1180,7 +1181,7 @@ out_image:
 
        if (!image || !prog->is_func || extra_pass) {
                if (image)
-                       bpf_prog_fill_jited_linfo(prog, addrs);
+                       bpf_prog_fill_jited_linfo(prog, addrs + 1);
 out_addrs:
                kfree(addrs);
                kfree(jit_data);
index 3cf302b2633222ff45323b2528f3499233b650c5..8901a1f89cf57bd16cbf79d6625a804274c6afe4 100644 (file)
@@ -6,6 +6,9 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string
 targets += $(purgatory-y)
 PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
 
+$(obj)/string.o: $(srctree)/arch/x86/boot/compressed/string.c FORCE
+       $(call if_changed_rule,cc_o_c)
+
 $(obj)/sha256.o: $(srctree)/lib/sha256.c FORCE
        $(call if_changed_rule,cc_o_c)
 
@@ -17,11 +20,34 @@ KCOV_INSTRUMENT := n
 
 # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
 # in turn leaves some undefined symbols like __fentry__ in purgatory and not
-# sure how to relocate those. Like kexec-tools, use custom flags.
-
-KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -Os -mcmodel=large
-KBUILD_CFLAGS += -m$(BITS)
-KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
+# sure how to relocate those.
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_sha256.o         += $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_purgatory.o      += $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_string.o         += $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_kexec-purgatory.o        += $(CC_FLAGS_FTRACE)
+endif
+
+ifdef CONFIG_STACKPROTECTOR
+CFLAGS_REMOVE_sha256.o         += -fstack-protector
+CFLAGS_REMOVE_purgatory.o      += -fstack-protector
+CFLAGS_REMOVE_string.o         += -fstack-protector
+CFLAGS_REMOVE_kexec-purgatory.o        += -fstack-protector
+endif
+
+ifdef CONFIG_STACKPROTECTOR_STRONG
+CFLAGS_REMOVE_sha256.o         += -fstack-protector-strong
+CFLAGS_REMOVE_purgatory.o      += -fstack-protector-strong
+CFLAGS_REMOVE_string.o         += -fstack-protector-strong
+CFLAGS_REMOVE_kexec-purgatory.o        += -fstack-protector-strong
+endif
+
+ifdef CONFIG_RETPOLINE
+CFLAGS_REMOVE_sha256.o         += $(RETPOLINE_CFLAGS)
+CFLAGS_REMOVE_purgatory.o      += $(RETPOLINE_CFLAGS)
+CFLAGS_REMOVE_string.o         += $(RETPOLINE_CFLAGS)
+CFLAGS_REMOVE_kexec-purgatory.o        += $(RETPOLINE_CFLAGS)
+endif
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
index 6d8d5a34c377245f65d005e34a2c9b0ef7993740..b607bda786f6b9ff0c60cb5889b4f99353d0edcb 100644 (file)
@@ -68,3 +68,9 @@ void purgatory(void)
        }
        copy_backup_region();
 }
+
+/*
+ * Defined in order to reuse memcpy() and memset() from
+ * arch/x86/boot/compressed/string.c
+ */
+void warn(const char *msg) {}
diff --git a/arch/x86/purgatory/string.c b/arch/x86/purgatory/string.c
deleted file mode 100644 (file)
index 01ad438..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Simple string functions.
- *
- * Copyright (C) 2014 Red Hat Inc.
- *
- * Author:
- *       Vivek Goyal <vgoyal@redhat.com>
- */
-
-#include <linux/types.h>
-
-#include "../boot/string.c"
-
-void *memcpy(void *dst, const void *src, size_t len)
-{
-       return __builtin_memcpy(dst, src, len);
-}
-
-void *memset(void *dst, int c, size_t len)
-{
-       return __builtin_memset(dst, c, len);
-}
index 5cb8a62e091c77619081973fe488b04a79437dd7..7c3106093c7584e44daaa2e6af660afa05ff4132 100644 (file)
@@ -511,6 +511,7 @@ void cpu_reset(void)
                                      "add      %2, %2, %7\n\t"
                                      "addi     %0, %0, -1\n\t"
                                      "bnez     %0, 1b\n\t"
+                                     "isync\n\t"
                                      /* Jump to identity mapping */
                                      "jx       %3\n"
                                      "2:\n\t"
index 586fcfe227eae6ca777f26e45a7605644451643d..b33be928d164fef34f5d2f00863d9034e38ef1a2 100644 (file)
@@ -1924,12 +1924,13 @@ static void bfq_add_request(struct request *rq)
                 * confirmed no later than during the next
                 * I/O-plugging interval for bfqq.
                 */
-               if (!bfq_bfqq_has_short_ttime(bfqq) &&
+               if (bfqd->last_completed_rq_bfqq &&
+                   !bfq_bfqq_has_short_ttime(bfqq) &&
                    ktime_get_ns() - bfqd->last_completion <
                    200 * NSEC_PER_USEC) {
                        if (bfqd->last_completed_rq_bfqq != bfqq &&
-                                  bfqd->last_completed_rq_bfqq !=
-                                  bfqq->waker_bfqq) {
+                           bfqd->last_completed_rq_bfqq !=
+                           bfqq->waker_bfqq) {
                                /*
                                 * First synchronization detected with
                                 * a candidate waker queue, or with a
@@ -2250,9 +2251,14 @@ static void bfq_request_merged(struct request_queue *q, struct request *req,
            blk_rq_pos(container_of(rb_prev(&req->rb_node),
                                    struct request, rb_node))) {
                struct bfq_queue *bfqq = bfq_init_rq(req);
-               struct bfq_data *bfqd = bfqq->bfqd;
+               struct bfq_data *bfqd;
                struct request *prev, *next_rq;
 
+               if (!bfqq)
+                       return;
+
+               bfqd = bfqq->bfqd;
+
                /* Reposition request in its sort_list */
                elv_rb_del(&bfqq->sort_list, req);
                elv_rb_add(&bfqq->sort_list, req);
@@ -2299,6 +2305,9 @@ static void bfq_requests_merged(struct request_queue *q, struct request *rq,
        struct bfq_queue *bfqq = bfq_init_rq(rq),
                *next_bfqq = bfq_init_rq(next);
 
+       if (!bfqq)
+               return;
+
        /*
         * If next and rq belong to the same bfq_queue and next is older
         * than rq, then reposition rq in the fifo (by substituting next
@@ -4764,6 +4773,8 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
  */
 void bfq_put_queue(struct bfq_queue *bfqq)
 {
+       struct bfq_queue *item;
+       struct hlist_node *n;
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
        struct bfq_group *bfqg = bfqq_group(bfqq);
 #endif
@@ -4808,6 +4819,36 @@ void bfq_put_queue(struct bfq_queue *bfqq)
                        bfqq->bfqd->burst_size--;
        }
 
+       /*
+        * bfqq does not exist any longer, so it cannot be woken by
+        * any other queue, and cannot wake any other queue. Then bfqq
+        * must be removed from the woken list of its possible waker
+        * queue, and all queues in the woken list of bfqq must stop
+        * having a waker queue. Strictly speaking, these updates
+        * should be performed when bfqq remains with no I/O source
+        * attached to it, which happens before bfqq gets freed. In
+        * particular, this happens when the last process associated
+        * with bfqq exits or gets associated with a different
+        * queue. However, both events lead to bfqq being freed soon,
+        * and dangling references would come out only after bfqq gets
+        * freed. So these updates are done here, as a simple and safe
+        * way to handle all cases.
+        */
+       /* remove bfqq from woken list */
+       if (!hlist_unhashed(&bfqq->woken_list_node))
+               hlist_del_init(&bfqq->woken_list_node);
+
+       /* reset waker for all queues in woken list */
+       hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
+                                 woken_list_node) {
+               item->waker_bfqq = NULL;
+               bfq_clear_bfqq_has_waker(item);
+               hlist_del_init(&item->woken_list_node);
+       }
+
+       if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
+               bfqq->bfqd->last_completed_rq_bfqq = NULL;
+
        kmem_cache_free(bfq_pool, bfqq);
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
        bfqg_and_blkg_put(bfqg);
@@ -4835,9 +4876,6 @@ static void bfq_put_cooperator(struct bfq_queue *bfqq)
 
 static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 {
-       struct bfq_queue *item;
-       struct hlist_node *n;
-
        if (bfqq == bfqd->in_service_queue) {
                __bfq_bfqq_expire(bfqd, bfqq, BFQQE_BUDGET_TIMEOUT);
                bfq_schedule_dispatch(bfqd);
@@ -4847,18 +4885,6 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 
        bfq_put_cooperator(bfqq);
 
-       /* remove bfqq from woken list */
-       if (!hlist_unhashed(&bfqq->woken_list_node))
-               hlist_del_init(&bfqq->woken_list_node);
-
-       /* reset waker for all queues in woken list */
-       hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
-                                 woken_list_node) {
-               item->waker_bfqq = NULL;
-               bfq_clear_bfqq_has_waker(item);
-               hlist_del_init(&item->woken_list_node);
-       }
-
        bfq_put_queue(bfqq); /* release process reference */
 }
 
@@ -5436,12 +5462,12 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 
        spin_lock_irq(&bfqd->lock);
        bfqq = bfq_init_rq(rq);
-       if (at_head || blk_rq_is_passthrough(rq)) {
+       if (!bfqq || at_head || blk_rq_is_passthrough(rq)) {
                if (at_head)
                        list_add(&rq->queuelist, &bfqd->dispatch);
                else
                        list_add_tail(&rq->queuelist, &bfqd->dispatch);
-       } else { /* bfqq is assumed to be non null here */
+       } else {
                idle_timer_disabled = __bfq_insert_request(bfqd, rq);
                /*
                 * Update bfqq, because, if a queue merge has occurred
index f78d3287dd823f6b431c87eec675580c1e987d55..0835f4d8d42e7e34c043acc040d8f5406b2e2268 100644 (file)
@@ -1958,13 +1958,9 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
        rq = blk_mq_get_request(q, bio, &data);
        if (unlikely(!rq)) {
                rq_qos_cleanup(q, bio);
-
-               cookie = BLK_QC_T_NONE;
-               if (bio->bi_opf & REQ_NOWAIT_INLINE)
-                       cookie = BLK_QC_T_EAGAIN;
-               else if (bio->bi_opf & REQ_NOWAIT)
+               if (bio->bi_opf & REQ_NOWAIT)
                        bio_wouldblock_error(bio);
-               return cookie;
+               return BLK_QC_T_NONE;
        }
 
        trace_block_getrq(q, bio, bio->bi_opf);
@@ -2666,8 +2662,6 @@ void blk_mq_release(struct request_queue *q)
        struct blk_mq_hw_ctx *hctx, *next;
        int i;
 
-       cancel_delayed_work_sync(&q->requeue_work);
-
        queue_for_each_hw_ctx(q, hctx, i)
                WARN_ON_ONCE(hctx && list_empty(&hctx->hctx_list));
 
index 977c659dcd1846f193ee525b36cd1c6ccecb2684..9bfa3ea4ed63038606067f1bb9d2f0c957a90279 100644 (file)
@@ -892,6 +892,9 @@ static void __blk_release_queue(struct work_struct *work)
 
        blk_free_queue_stats(q->stats);
 
+       if (queue_is_mq(q))
+               cancel_delayed_work_sync(&q->requeue_work);
+
        blk_exit_queue(q);
 
        blk_queue_free_zone_bitmaps(q);
index 391ac0503dc075e7de0957c56aa7a30f966927e4..76d0f9de767bcec3d19b59a390cf95d9954c4025 100644 (file)
@@ -1786,6 +1786,21 @@ nothing_to_do:
        return 1;
 }
 
+static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
+{
+       struct request *rq = scmd->request;
+       u32 req_blocks;
+
+       if (!blk_rq_is_passthrough(rq))
+               return true;
+
+       req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size;
+       if (n_blocks > req_blocks)
+               return false;
+
+       return true;
+}
+
 /**
  *     ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
  *     @qc: Storage for translated ATA taskfile
@@ -1830,6 +1845,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                scsi_10_lba_len(cdb, &block, &n_block);
                if (cdb[1] & (1 << 3))
                        tf_flags |= ATA_TFLAG_FUA;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        case READ_6:
        case WRITE_6:
@@ -1844,6 +1861,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                 */
                if (!n_block)
                        n_block = 256;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        case READ_16:
        case WRITE_16:
@@ -1854,6 +1873,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                scsi_16_lba_len(cdb, &block, &n_block);
                if (cdb[1] & (1 << 3))
                        tf_flags |= ATA_TFLAG_FUA;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        default:
                DPRINTK("no-byte command\n");
index 10aa2788214279b1682135e77fc22ac0007e6190..4f115adb4ee83b3836f1d596e1350ce3785011d6 100644 (file)
@@ -658,6 +658,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
        unsigned int offset;
        unsigned char *buf;
 
+       if (!qc->cursg) {
+               qc->curbytes = qc->nbytes;
+               return;
+       }
        if (qc->curbytes == qc->nbytes - qc->sect_size)
                ap->hsm_task_state = HSM_ST_LAST;
 
@@ -683,6 +687,8 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
 
        if (qc->cursg_ofs == qc->cursg->length) {
                qc->cursg = sg_next(qc->cursg);
+               if (!qc->cursg)
+                       ap->hsm_task_state = HSM_ST_LAST;
                qc->cursg_ofs = 0;
        }
 }
index 7c37f2ff09e4169f30b42fbb12798abc19de228e..deae466395de1a656d5cba27720fb8f345e6c332 100644 (file)
@@ -158,7 +158,6 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
 static int rb532_pata_driver_remove(struct platform_device *pdev)
 {
        struct ata_host *ah = platform_get_drvdata(pdev);
-       struct rb532_cf_info *info = ah->private_data;
 
        ata_host_detach(ah);
 
index 302cf0ba16008740d8f0ecd231b6f27c73f0f97e..8c7a996d1f16cfd5d2b86a73effe5562ce1732b0 100644 (file)
@@ -63,6 +63,7 @@
 #include <asm/byteorder.h>  
 #include <linux/vmalloc.h>
 #include <linux/jiffies.h>
+#include <linux/nospec.h>
 #include "iphase.h"              
 #include "suni.h"                
 #define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
@@ -2760,8 +2761,11 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
    }
    if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT; 
    board = ia_cmds.status;
-   if ((board < 0) || (board > iadev_count))
-         board = 0;    
+
+       if ((board < 0) || (board > iadev_count))
+               board = 0;
+       board = array_index_nospec(board, iadev_count + 1);
+
    iadev = ia_dev[board];
    switch (ia_cmds.cmd) {
    case MEMDUMP:
index dd61fdd400f05a0a9d5438241a52a7e6436e9e8f..68489d1f00bb33a275100e280bd68341aa31c8d1 100644 (file)
@@ -448,6 +448,11 @@ config PANEL_BOOT_MESSAGE
 choice
        prompt "Backlight initial state"
        default CHARLCD_BL_FLASH
+       ---help---
+         Select the initial backlight state on boot or module load.
+
+         Previously, there was no option for this: the backlight flashed
+         briefly on init. Now you can also turn it off/on.
 
        config CHARLCD_BL_OFF
                bool "Off"
index 92745efefb540e5d723f5bbaa3aefd11735b0f29..bef6b85778b6e2e04056fac1de5f1e9e56f834c4 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <generated/utsrelease.h>
 
-#include <misc/charlcd.h>
+#include "charlcd.h"
 
 #define LCD_MINOR              156
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
new file mode 100644 (file)
index 0000000..00911ad
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Character LCD driver for Linux
+ *
+ * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
+ * Copyright (C) 2016-2017 Glider bvba
+ */
+
+#ifndef _CHARLCD_H
+#define _CHARLCD_H
+
+struct charlcd {
+       const struct charlcd_ops *ops;
+       const unsigned char *char_conv; /* Optional */
+
+       int ifwidth;                    /* 4-bit or 8-bit (default) */
+       int height;
+       int width;
+       int bwidth;                     /* Default set by charlcd_alloc() */
+       int hwidth;                     /* Default set by charlcd_alloc() */
+
+       void *drvdata;                  /* Set by charlcd_alloc() */
+};
+
+struct charlcd_ops {
+       /* Required */
+       void (*write_cmd)(struct charlcd *lcd, int cmd);
+       void (*write_data)(struct charlcd *lcd, int data);
+
+       /* Optional */
+       void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
+       void (*clear_fast)(struct charlcd *lcd);
+       void (*backlight)(struct charlcd *lcd, int on);
+};
+
+struct charlcd *charlcd_alloc(unsigned int drvdata_size);
+void charlcd_free(struct charlcd *lcd);
+
+int charlcd_register(struct charlcd *lcd);
+int charlcd_unregister(struct charlcd *lcd);
+
+void charlcd_poke(struct charlcd *lcd);
+
+#endif /* CHARLCD_H */
index ab15b64707ad22ef429a7ee6911d72ec9a284bd5..bcbe1309232760235239d94479f23e076a76cd9f 100644 (file)
@@ -14,8 +14,7 @@
 #include <linux/property.h>
 #include <linux/slab.h>
 
-#include <misc/charlcd.h>
-
+#include "charlcd.h"
 
 enum hd44780_pin {
        /* Order does matter due to writing to GPIO array subsets! */
index e06de63497cf8f00edde8d2d7bcffa5b25cc8e81..85965953683e4cf78e58081c1f8eb17107a74df1 100644 (file)
@@ -55,7 +55,7 @@
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
-#include <misc/charlcd.h>
+#include "charlcd.h"
 
 #define KEYPAD_MINOR           185
 
@@ -1617,6 +1617,8 @@ static void panel_attach(struct parport *port)
        return;
 
 err_lcd_unreg:
+       if (scan_timer.function)
+               del_timer_sync(&scan_timer);
        if (lcd.enabled)
                charlcd_unregister(lcd.charlcd);
 err_unreg_device:
index 636058bbf48a3d902dc7d7f64b902d6e31abf5c3..1669d41fcddccde2cfbb35f1ccc7be37ef0b3dc0 100644 (file)
@@ -1823,12 +1823,63 @@ static inline struct kobject *get_glue_dir(struct device *dev)
  */
 static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 {
+       unsigned int ref;
+
        /* see if we live in a "glue" directory */
        if (!live_in_glue_dir(glue_dir, dev))
                return;
 
        mutex_lock(&gdp_mutex);
-       if (!kobject_has_children(glue_dir))
+       /**
+        * There is a race condition between removing glue directory
+        * and adding a new device under the glue directory.
+        *
+        * CPU1:                                         CPU2:
+        *
+        * device_add()
+        *   get_device_parent()
+        *     class_dir_create_and_add()
+        *       kobject_add_internal()
+        *         create_dir()    // create glue_dir
+        *
+        *                                               device_add()
+        *                                                 get_device_parent()
+        *                                                   kobject_get() // get glue_dir
+        *
+        * device_del()
+        *   cleanup_glue_dir()
+        *     kobject_del(glue_dir)
+        *
+        *                                               kobject_add()
+        *                                                 kobject_add_internal()
+        *                                                   create_dir() // in glue_dir
+        *                                                     sysfs_create_dir_ns()
+        *                                                       kernfs_create_dir_ns(sd)
+        *
+        *       sysfs_remove_dir() // glue_dir->sd=NULL
+        *       sysfs_put()        // free glue_dir->sd
+        *
+        *                                                         // sd is freed
+        *                                                         kernfs_new_node(sd)
+        *                                                           kernfs_get(glue_dir)
+        *                                                           kernfs_add_one()
+        *                                                           kernfs_put()
+        *
+        * Before CPU1 remove last child device under glue dir, if CPU2 add
+        * a new device under glue dir, the glue_dir kobject reference count
+        * will be increase to 2 in kobject_get(k). And CPU2 has been called
+        * kernfs_create_dir_ns(). Meanwhile, CPU1 call sysfs_remove_dir()
+        * and sysfs_put(). This result in glue_dir->sd is freed.
+        *
+        * Then the CPU2 will see a stale "empty" but still potentially used
+        * glue dir around in kernfs_new_node().
+        *
+        * In order to avoid this happening, we also should make sure that
+        * kernfs_node for glue_dir is released in CPU1 only when refcount
+        * for glue_dir kobj is 1.
+        */
+       ref = kref_read(&glue_dir->kref);
+       if (!kobject_has_children(glue_dir) && !--ref)
                kobject_del(glue_dir);
        kobject_put(glue_dir);
        mutex_unlock(&gdp_mutex);
index 506a0175a5a781cf297cc0153038dc4aa9b48d86..ec974ba9c0c4ca93a3b1cfcaf541c6e4a4a3bd9c 100644 (file)
@@ -157,8 +157,13 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
         * the device will only expose one IRQ, and this fallback
         * allows a common code path across either kind of resource.
         */
-       if (num == 0 && has_acpi_companion(&dev->dev))
-               return acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+       if (num == 0 && has_acpi_companion(&dev->dev)) {
+               int ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num);
+
+               /* Our callers expect -ENXIO for missing IRQs. */
+               if (ret >= 0 || ret == -EPROBE_DEFER)
+                       return ret;
+       }
 
        return -ENXIO;
 #endif
index a4984136c19d50d61ec5ab23bcaa2916bdc91d55..0fd6f97ee523fdec13623b859d76dc1dd3d0e355 100644 (file)
@@ -44,7 +44,7 @@ config REGMAP_IRQ
 
 config REGMAP_SOUNDWIRE
        tristate
-       depends on SOUNDWIRE_BUS
+       depends on SOUNDWIRE
 
 config REGMAP_SCCB
        tristate
index 5b49f1b33ebec4cff30ec71347c97f119041b351..e2ea2356da0610c6872724e0295e4f8335ded013 100644 (file)
@@ -323,10 +323,14 @@ flush(const char __user *str, size_t cnt, int exiting)
        }
 
        flush_scheduled_work();
-       /* pass one: without sleeping, do aoedev_downdev */
+       /* pass one: do aoedev_downdev, which might sleep */
+restart1:
        spin_lock_irqsave(&devlist_lock, flags);
        for (d = devlist; d; d = d->next) {
                spin_lock(&d->lock);
+               if (d->flags & DEVFL_TKILL)
+                       goto cont;
+
                if (exiting) {
                        /* unconditionally take each device down */
                } else if (specified) {
@@ -338,8 +342,11 @@ flush(const char __user *str, size_t cnt, int exiting)
                || d->ref)
                        goto cont;
 
+               spin_unlock(&d->lock);
+               spin_unlock_irqrestore(&devlist_lock, flags);
                aoedev_downdev(d);
                d->flags |= DEVFL_TKILL;
+               goto restart1;
 cont:
                spin_unlock(&d->lock);
        }
@@ -348,7 +355,7 @@ cont:
        /* pass two: call freedev, which might sleep,
         * for aoedevs marked with DEVFL_TKILL
         */
-restart:
+restart2:
        spin_lock_irqsave(&devlist_lock, flags);
        for (d = devlist; d; d = d->next) {
                spin_lock(&d->lock);
@@ -357,7 +364,7 @@ restart:
                        spin_unlock(&d->lock);
                        spin_unlock_irqrestore(&devlist_lock, flags);
                        freedev(d);
-                       goto restart;
+                       goto restart2;
                }
                spin_unlock(&d->lock);
        }
index 9bd4ddd12b25c542ae9fad6fae963f66414b496c..5b248763a672414e925f217216fc21c9a2a257fb 100644 (file)
@@ -322,6 +322,8 @@ static int drbd_thread_setup(void *arg)
                 thi->name[0],
                 resource->name);
 
+       allow_kernel_signal(DRBD_SIGKILL);
+       allow_kernel_signal(SIGXCPU);
 restart:
        retval = thi->function(thi);
 
index 3036883fc9f878f1714dcdfe1d6803a27853304a..ab7ca5989097ac70372f77f4fb60964a98c98177 100644 (file)
@@ -885,7 +885,7 @@ static void loop_unprepare_queue(struct loop_device *lo)
 
 static int loop_kthread_worker_fn(void *worker_ptr)
 {
-       current->flags |= PF_LESS_THROTTLE;
+       current->flags |= PF_LESS_THROTTLE | PF_MEMALLOC_NOIO;
        return kthread_worker_fn(worker_ptr);
 }
 
index 3ac6a5d18071729a7747a72835223f02234e240f..b90dbcd99c03e9c4e1ae0bc5f22180b80c5903e1 100644 (file)
@@ -965,6 +965,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
                }
        }
 
+       err = -ENOMEM;
        for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
                req = kzalloc(sizeof(*req), GFP_KERNEL);
                if (!req)
@@ -987,7 +988,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir)
        err = xen_blkif_map(ring, ring_ref, nr_grefs, evtchn);
        if (err) {
                xenbus_dev_fatal(dev, err, "mapping ring-ref port %u", evtchn);
-               return err;
+               goto fail;
        }
 
        return 0;
@@ -1007,8 +1008,7 @@ fail:
                }
                kfree(req);
        }
-       return -ENOMEM;
-
+       return err;
 }
 
 static int connect_ring(struct backend_info *be)
index 8b33128dccee1a0d26965b889190ca37e8d8372d..0875470a7806f8658c45b2b4a15f6e2b029bf0c2 100644 (file)
@@ -99,6 +99,27 @@ static int qca_send_reset(struct hci_dev *hdev)
        return 0;
 }
 
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+       struct sk_buff *skb;
+       int err;
+
+       bt_dev_dbg(hdev, "QCA pre shutdown cmd");
+
+       skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
+                               NULL, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb)) {
+               err = PTR_ERR(skb);
+               bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err);
+               return err;
+       }
+
+       kfree_skb(skb);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
 static void qca_tlv_check_data(struct rome_config *config,
                                const struct firmware *fw)
 {
@@ -119,6 +140,7 @@ static void qca_tlv_check_data(struct rome_config *config,
        BT_DBG("Length\t\t : %d bytes", length);
 
        config->dnld_mode = ROME_SKIP_EVT_NONE;
+       config->dnld_type = ROME_SKIP_EVT_NONE;
 
        switch (config->type) {
        case TLV_TYPE_PATCH:
@@ -268,7 +290,7 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
 
        evt = skb_put(skb, sizeof(*evt));
        evt->ncmd = 1;
-       evt->opcode = QCA_HCI_CC_OPCODE;
+       evt->opcode = cpu_to_le16(QCA_HCI_CC_OPCODE);
 
        skb_put_u8(skb, QCA_HCI_CC_SUCCESS);
 
@@ -323,7 +345,7 @@ static int qca_download_firmware(struct hci_dev *hdev,
         */
        if (config->dnld_type == ROME_SKIP_EVT_VSE_CC ||
            config->dnld_type == ROME_SKIP_EVT_VSE)
-               return qca_inject_cmd_complete_event(hdev);
+               ret = qca_inject_cmd_complete_event(hdev);
 
 out:
        release_firmware(fw);
@@ -388,6 +410,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                return err;
        }
 
+       /* Give the controller some time to get ready to receive the NVM */
+       msleep(10);
+
        /* Download NVM configuration */
        config.type = TLV_TYPE_NVM;
        if (firmware_name)
index 6a291a7a5d9658c1987cf8c01ad34c47e3d4bfc9..69c5315a65fd2630346591e5df2d3faf51690099 100644 (file)
@@ -13,6 +13,7 @@
 #define EDL_PATCH_TLV_REQ_CMD          (0x1E)
 #define EDL_NVM_ACCESS_SET_REQ_CMD     (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT       (243)
+#define QCA_PRE_SHUTDOWN_CMD           (0xFC08)
 
 #define EDL_CMD_REQ_RES_EVT            (0x00)
 #define EDL_PATCH_VER_RES_EVT          (0x19)
@@ -135,6 +136,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
                   const char *firmware_name);
 int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
 int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
 static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
        return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998;
@@ -167,4 +169,9 @@ static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
        return false;
 }
+
+static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+{
+       return -EOPNOTSUPP;
+}
 #endif
index 3876fee6ad13fa617858d9b1da34ba5b43da13c9..5cf0734eb31bf923de8c18cb8e8ad5d23a284a2f 100644 (file)
@@ -2762,8 +2762,10 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
        fw_size = fw->size;
 
        /* The size of patch header is 30 bytes, should be skip */
-       if (fw_size < 30)
+       if (fw_size < 30) {
+               err = -EINVAL;
                goto err_release_fw;
+       }
 
        fw_size -= 30;
        fw_ptr += 30;
index 82a0a3691a63c701075e03ed44a408d13d7c4e66..9a970fd1975aab411d96912593606b5096d81180 100644 (file)
@@ -705,7 +705,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
        unsigned long flags;
        struct qca_data *qca = hu->priv;
 
-       BT_DBG("hu %p want to sleep", hu);
+       BT_DBG("hu %p want to sleep in %d state", hu, qca->rx_ibs_state);
 
        spin_lock_irqsave(&qca->hci_ibs_lock, flags);
 
@@ -720,7 +720,7 @@ static void device_want_to_sleep(struct hci_uart *hu)
                break;
 
        case HCI_IBS_RX_ASLEEP:
-               /* Fall through */
+               break;
 
        default:
                /* Any other state is illegal */
@@ -912,7 +912,7 @@ static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
                if (hdr->evt == HCI_EV_VENDOR)
                        complete(&qca->drop_ev_comp);
 
-               kfree(skb);
+               kfree_skb(skb);
 
                return 0;
        }
@@ -1386,6 +1386,9 @@ static int qca_power_off(struct hci_dev *hdev)
 {
        struct hci_uart *hu = hci_get_drvdata(hdev);
 
+       /* Perform pre shutdown command */
+       qca_send_pre_shutdown_cmd(hdev);
+
        qca_power_shutdown(hu);
        return 0;
 }
index c0990703ce5403c1092bda6d982c56dffd70e6a0..1c46babeb09330e8e2a98060ad310fabba65aa2d 100644 (file)
@@ -324,6 +324,25 @@ static struct clk_core *clk_core_lookup(const char *name)
        return NULL;
 }
 
+#ifdef CONFIG_OF
+static int of_parse_clkspec(const struct device_node *np, int index,
+                           const char *name, struct of_phandle_args *out_args);
+static struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec);
+#else
+static inline int of_parse_clkspec(const struct device_node *np, int index,
+                                  const char *name,
+                                  struct of_phandle_args *out_args)
+{
+       return -ENOENT;
+}
+static inline struct clk_hw *
+of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
+{
+       return ERR_PTR(-ENOENT);
+}
+#endif
+
 /**
  * clk_core_get - Find the clk_core parent of a clk
  * @core: clk to find parent of
@@ -355,8 +374,9 @@ static struct clk_core *clk_core_lookup(const char *name)
  *      };
  *
  * Returns: -ENOENT when the provider can't be found or the clk doesn't
- * exist in the provider. -EINVAL when the name can't be found. NULL when the
- * provider knows about the clk but it isn't provided on this system.
+ * exist in the provider or the name can't be found in the DT node or
+ * in a clkdev lookup. NULL when the provider knows about the clk but it
+ * isn't provided on this system.
  * A valid clk_core pointer when the clk can be found in the provider.
  */
 static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
@@ -367,17 +387,19 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
        struct device *dev = core->dev;
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct device_node *np = core->of_node;
+       struct of_phandle_args clkspec;
 
-       if (np && (name || index >= 0))
-               hw = of_clk_get_hw(np, index, name);
-
-       /*
-        * If the DT search above couldn't find the provider or the provider
-        * didn't know about this clk, fallback to looking up via clkdev based
-        * clk_lookups
-        */
-       if (PTR_ERR(hw) == -ENOENT && name)
+       if (np && (name || index >= 0) &&
+           !of_parse_clkspec(np, index, name, &clkspec)) {
+               hw = of_clk_get_hw_from_clkspec(&clkspec);
+               of_node_put(clkspec.np);
+       } else if (name) {
+               /*
+                * If the DT search above couldn't find the provider fallback to
+                * looking up via clkdev based clk_lookups.
+                */
                hw = clk_find_hw(dev_id, name);
+       }
 
        if (IS_ERR(hw))
                return ERR_CAST(hw);
@@ -401,7 +423,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
                        parent = ERR_PTR(-EPROBE_DEFER);
        } else {
                parent = clk_core_get(core, index);
-               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
+               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT && entry->name)
                        parent = clk_core_lookup(entry->name);
        }
 
@@ -1632,7 +1654,8 @@ static int clk_fetch_parent_index(struct clk_core *core,
                        break;
 
                /* Fallback to comparing globally unique names */
-               if (!strcmp(parent->name, core->parents[i].name))
+               if (core->parents[i].name &&
+                   !strcmp(parent->name, core->parents[i].name))
                        break;
        }
 
index 91db7894125df5bcf6cc1b5c014d4307a9520c25..65c82d922b05cbb0e22bd9438627d8fde7120542 100644 (file)
@@ -14,7 +14,7 @@
 #include "clk-exynos5-subcmu.h"
 
 static struct samsung_clk_provider *ctx;
-static const struct exynos5_subcmu_info *cmu;
+static const struct exynos5_subcmu_info **cmu;
 static int nr_cmus;
 
 static void exynos5_subcmu_clk_save(void __iomem *base,
@@ -56,17 +56,17 @@ static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
  * when OF-core populates all device-tree nodes.
  */
 void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus,
-                         const struct exynos5_subcmu_info *_cmu)
+                         const struct exynos5_subcmu_info **_cmu)
 {
        ctx = _ctx;
        cmu = _cmu;
        nr_cmus = _nr_cmus;
 
        for (; _nr_cmus--; _cmu++) {
-               exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks,
-                                         _cmu->nr_gate_clks);
-               exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs,
-                                       _cmu->nr_suspend_regs);
+               exynos5_subcmu_defer_gate(ctx, (*_cmu)->gate_clks,
+                                         (*_cmu)->nr_gate_clks);
+               exynos5_subcmu_clk_save(ctx->reg_base, (*_cmu)->suspend_regs,
+                                       (*_cmu)->nr_suspend_regs);
        }
 }
 
@@ -163,9 +163,9 @@ static int __init exynos5_clk_probe(struct platform_device *pdev)
                if (of_property_read_string(np, "label", &name) < 0)
                        continue;
                for (i = 0; i < nr_cmus; i++)
-                       if (strcmp(cmu[i].pd_name, name) == 0)
+                       if (strcmp(cmu[i]->pd_name, name) == 0)
                                exynos5_clk_register_subcmu(&pdev->dev,
-                                                           &cmu[i], np);
+                                                           cmu[i], np);
        }
        return 0;
 }
index 755ee8aaa3de5670f41ae60b1b691436fa5f457b..9ae5356f25aa4170fa5a91834a7fa926246e71f4 100644 (file)
@@ -21,6 +21,6 @@ struct exynos5_subcmu_info {
 };
 
 void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus,
-                         const struct exynos5_subcmu_info *cmu);
+                         const struct exynos5_subcmu_info **cmu);
 
 #endif
index f2b8968817682458d13c0eb1452179219ec242e9..931c70a4da196871cb75a7026908a30c1f5c286c 100644 (file)
@@ -681,6 +681,10 @@ static const struct exynos5_subcmu_info exynos5250_disp_subcmu = {
        .pd_name        = "DISP1",
 };
 
+static const struct exynos5_subcmu_info *exynos5250_subcmus[] = {
+       &exynos5250_disp_subcmu,
+};
+
 static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
        /* sorted in descending order */
        /* PLL_36XX_RATE(rate, m, p, s, k) */
@@ -843,7 +847,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
 
        samsung_clk_sleep_init(reg_base, exynos5250_clk_regs,
                               ARRAY_SIZE(exynos5250_clk_regs));
-       exynos5_subcmus_init(ctx, 1, &exynos5250_disp_subcmu);
+       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5250_subcmus),
+                            exynos5250_subcmus);
 
        samsung_clk_of_add_provider(np, ctx);
 
index 01bca5a498b2a1e330287e465401aa7f330a37ae..7670cc596c74245205babf39e339c8e0b5e087f6 100644 (file)
@@ -534,8 +534,6 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
                                GATE_BUS_TOP, 24, 0, 0),
        GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
                                GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
-       GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
-                       SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
 };
 
 static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
@@ -577,8 +575,13 @@ static const struct samsung_div_clock exynos5420_div_clks[] __initconst = {
 
 static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = {
        GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0),
+       /* Maudio Block */
        GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
                        SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
@@ -890,9 +893,6 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
        /* GSCL Block */
        DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
 
-       /* MSCL Block */
-       DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
-
        /* PSGEN */
        DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1),
        DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1),
@@ -1017,12 +1017,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
                        GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0),
 
-       /* Maudio Block */
-       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
-               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
-       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
-               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
-
        /* FSYS Block */
        GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0),
        GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0),
@@ -1162,17 +1156,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
                        GATE_IP_GSCL1, 17, 0, 0),
 
-       /* MSCL Block */
-       GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
-       GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
-       GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
-       GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
-                       GATE_IP_MSCL, 8, 0, 0),
-       GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
-                       GATE_IP_MSCL, 9, 0, 0),
-       GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
-                       GATE_IP_MSCL, 10, 0, 0),
-
        /* ISP */
        GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
                        GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0),
@@ -1281,32 +1264,103 @@ static struct exynos5_subcmu_reg_dump exynos5x_mfc_suspend_regs[] = {
        { DIV4_RATIO, 0, 0x3 },                 /* DIV dout_mfc_blk */
 };
 
-static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
-       {
-               .div_clks       = exynos5x_disp_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
-               .gate_clks      = exynos5x_disp_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
-               .suspend_regs   = exynos5x_disp_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
-               .pd_name        = "DISP",
-       }, {
-               .div_clks       = exynos5x_gsc_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
-               .gate_clks      = exynos5x_gsc_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
-               .suspend_regs   = exynos5x_gsc_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
-               .pd_name        = "GSC",
-       }, {
-               .div_clks       = exynos5x_mfc_div_clks,
-               .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
-               .gate_clks      = exynos5x_mfc_gate_clks,
-               .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
-               .suspend_regs   = exynos5x_mfc_suspend_regs,
-               .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
-               .pd_name        = "MFC",
-       },
+static const struct samsung_gate_clock exynos5x_mscl_gate_clks[] __initconst = {
+       /* MSCL Block */
+       GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
+       GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
+       GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
+       GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
+                       GATE_IP_MSCL, 8, 0, 0),
+       GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
+                       GATE_IP_MSCL, 9, 0, 0),
+       GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
+                       GATE_IP_MSCL, 10, 0, 0),
+};
+
+static const struct samsung_div_clock exynos5x_mscl_div_clks[] __initconst = {
+       DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_mscl_suspend_regs[] = {
+       { GATE_IP_MSCL, 0xffffffff, 0xffffffff }, /* MSCL gates */
+       { SRC_TOP3, 0, BIT(4) },                /* MUX mout_user_aclk400_mscl */
+       { DIV2_RATIO0, 0, 0x30000000 },         /* DIV dout_mscl_blk */
+};
+
+static const struct samsung_gate_clock exynos5800_mau_gate_clks[] __initconst = {
+       GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
+                       SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
+               GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
+               GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5800_mau_suspend_regs[] = {
+       { SRC_TOP9, 0, BIT(8) },        /* MUX mout_user_mau_epll */
+};
+
+static const struct exynos5_subcmu_info exynos5x_disp_subcmu = {
+       .div_clks       = exynos5x_disp_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_disp_div_clks),
+       .gate_clks      = exynos5x_disp_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_disp_gate_clks),
+       .suspend_regs   = exynos5x_disp_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
+       .pd_name        = "DISP",
+};
+
+static const struct exynos5_subcmu_info exynos5x_gsc_subcmu = {
+       .div_clks       = exynos5x_gsc_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_gsc_div_clks),
+       .gate_clks      = exynos5x_gsc_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_gsc_gate_clks),
+       .suspend_regs   = exynos5x_gsc_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
+       .pd_name        = "GSC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mfc_subcmu = {
+       .div_clks       = exynos5x_mfc_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
+       .gate_clks      = exynos5x_mfc_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_mfc_gate_clks),
+       .suspend_regs   = exynos5x_mfc_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
+       .pd_name        = "MFC",
+};
+
+static const struct exynos5_subcmu_info exynos5x_mscl_subcmu = {
+       .div_clks       = exynos5x_mscl_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(exynos5x_mscl_div_clks),
+       .gate_clks      = exynos5x_mscl_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_mscl_gate_clks),
+       .suspend_regs   = exynos5x_mscl_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_mscl_suspend_regs),
+       .pd_name        = "MSC",
+};
+
+static const struct exynos5_subcmu_info exynos5800_mau_subcmu = {
+       .gate_clks      = exynos5800_mau_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5800_mau_gate_clks),
+       .suspend_regs   = exynos5800_mau_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5800_mau_suspend_regs),
+       .pd_name        = "MAU",
+};
+
+static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
+       &exynos5x_disp_subcmu,
+       &exynos5x_gsc_subcmu,
+       &exynos5x_mfc_subcmu,
+       &exynos5x_mscl_subcmu,
+};
+
+static const struct exynos5_subcmu_info *exynos5800_subcmus[] = {
+       &exynos5x_disp_subcmu,
+       &exynos5x_gsc_subcmu,
+       &exynos5x_mfc_subcmu,
+       &exynos5x_mscl_subcmu,
+       &exynos5800_mau_subcmu,
 };
 
 static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
@@ -1539,11 +1593,17 @@ static void __init exynos5x_clk_init(struct device_node *np,
        samsung_clk_extended_sleep_init(reg_base,
                exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs),
                exynos5420_set_clksrc, ARRAY_SIZE(exynos5420_set_clksrc));
-       if (soc == EXYNOS5800)
+
+       if (soc == EXYNOS5800) {
                samsung_clk_sleep_init(reg_base, exynos5800_clk_regs,
                                       ARRAY_SIZE(exynos5800_clk_regs));
-       exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
-                            exynos5x_subcmus);
+
+               exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5800_subcmus),
+                                    exynos5800_subcmus);
+       } else {
+               exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
+                                    exynos5x_subcmus);
+       }
 
        samsung_clk_of_add_provider(np, ctx);
 }
index 5c50e723ecae7e945c85da36eacf514ffc71d81c..1a191eeeebbab915705bca2284c4cdbeba22bbd2 100644 (file)
@@ -38,7 +38,7 @@ static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
        if (socfpgaclk->fixed_div) {
                div = socfpgaclk->fixed_div;
        } else {
-               if (!socfpgaclk->bypass_reg)
+               if (socfpgaclk->hw.reg)
                        div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
        }
 
index 5e6038fbf115d10bc82cc77548b709c3145e4a43..09e031176bc6bae860133bb478d7fb5428b25469 100644 (file)
@@ -55,7 +55,7 @@ static u64 riscv_sched_clock(void)
        return get_cycles64();
 }
 
-static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = {
+static struct clocksource riscv_clocksource = {
        .name           = "riscv_clocksource",
        .rating         = 300,
        .mask           = CLOCKSOURCE_MASK(64),
@@ -92,7 +92,6 @@ void riscv_timer_interrupt(void)
 static int __init riscv_timer_init_dt(struct device_node *n)
 {
        int cpuid, hartid, error;
-       struct clocksource *cs;
 
        hartid = riscv_of_processor_hartid(n);
        if (hartid < 0) {
@@ -112,8 +111,7 @@ static int __init riscv_timer_init_dt(struct device_node *n)
 
        pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
               __func__, cpuid, hartid);
-       cs = per_cpu_ptr(&riscv_clocksource, cpuid);
-       error = clocksource_register_hz(cs, riscv_timebase);
+       error = clocksource_register_hz(&riscv_clocksource, riscv_timebase);
        if (error) {
                pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
                       error, cpuid);
index 8dda62367816f331420eedd58a7c686f0d68a04f..c28ebf2810f11508a1c36cb1660bdd949ef3aeff 100644 (file)
@@ -2528,7 +2528,7 @@ static int cpufreq_boost_set_sw(int state)
                }
 
                ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
-               if (ret)
+               if (ret < 0)
                        break;
        }
 
index f9fec2ddf56aef0e3ec72039395bc6044403f8f9..94c1ad7eeddf7ca84d11f685b90756c2edefcf2f 100644 (file)
@@ -58,6 +58,19 @@ static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
 static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm,
                                   unsigned int authsize)
 {
+       switch (authsize) {
+       case 16:
+       case 15:
+       case 14:
+       case 13:
+       case 12:
+       case 8:
+       case 4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -104,6 +117,7 @@ static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt)
        memset(&rctx->cmd, 0, sizeof(rctx->cmd));
        INIT_LIST_HEAD(&rctx->cmd.entry);
        rctx->cmd.engine = CCP_ENGINE_AES;
+       rctx->cmd.u.aes.authsize = crypto_aead_authsize(tfm);
        rctx->cmd.u.aes.type = ctx->u.aes.type;
        rctx->cmd.u.aes.mode = ctx->u.aes.mode;
        rctx->cmd.u.aes.action = encrypt;
index c69ed4bae2eb1045dfab71f0f884954756cde4f1..9bc3c62157d7dc500b3b00c3d4d74bd37d5fd531 100644 (file)
@@ -622,6 +622,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
 
        unsigned long long *final;
        unsigned int dm_offset;
+       unsigned int authsize;
        unsigned int jobid;
        unsigned int ilen;
        bool in_place = true; /* Default value */
@@ -643,6 +644,21 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
        if (!aes->key) /* Gotta have a key SGL */
                return -EINVAL;
 
+       /* Zero defaults to 16 bytes, the maximum size */
+       authsize = aes->authsize ? aes->authsize : AES_BLOCK_SIZE;
+       switch (authsize) {
+       case 16:
+       case 15:
+       case 14:
+       case 13:
+       case 12:
+       case 8:
+       case 4:
+               break;
+       default:
+               return -EINVAL;
+       }
+
        /* First, decompose the source buffer into AAD & PT,
         * and the destination buffer into AAD, CT & tag, or
         * the input into CT & tag.
@@ -657,7 +673,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
                p_tag = scatterwalk_ffwd(sg_tag, p_outp, ilen);
        } else {
                /* Input length for decryption includes tag */
-               ilen = aes->src_len - AES_BLOCK_SIZE;
+               ilen = aes->src_len - authsize;
                p_tag = scatterwalk_ffwd(sg_tag, p_inp, ilen);
        }
 
@@ -766,8 +782,7 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
                while (src.sg_wa.bytes_left) {
                        ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true);
                        if (!src.sg_wa.bytes_left) {
-                               unsigned int nbytes = aes->src_len
-                                                     % AES_BLOCK_SIZE;
+                               unsigned int nbytes = ilen % AES_BLOCK_SIZE;
 
                                if (nbytes) {
                                        op.eom = 1;
@@ -839,19 +854,19 @@ static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q,
 
        if (aes->action == CCP_AES_ACTION_ENCRYPT) {
                /* Put the ciphered tag after the ciphertext. */
-               ccp_get_dm_area(&final_wa, 0, p_tag, 0, AES_BLOCK_SIZE);
+               ccp_get_dm_area(&final_wa, 0, p_tag, 0, authsize);
        } else {
                /* Does this ciphered tag match the input? */
-               ret = ccp_init_dm_workarea(&tag, cmd_q, AES_BLOCK_SIZE,
+               ret = ccp_init_dm_workarea(&tag, cmd_q, authsize,
                                           DMA_BIDIRECTIONAL);
                if (ret)
                        goto e_tag;
-               ret = ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE);
+               ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize);
                if (ret)
                        goto e_tag;
 
                ret = crypto_memneq(tag.address, final_wa.address,
-                                   AES_BLOCK_SIZE) ? -EBADMSG : 0;
+                                   authsize) ? -EBADMSG : 0;
                ccp_dm_free(&tag);
        }
 
@@ -859,11 +874,11 @@ e_tag:
        ccp_dm_free(&final_wa);
 
 e_dst:
-       if (aes->src_len && !in_place)
+       if (ilen > 0 && !in_place)
                ccp_free_data(&dst, cmd_q);
 
 e_src:
-       if (aes->src_len)
+       if (ilen > 0)
                ccp_free_data(&src, cmd_q);
 
 e_aad:
index ece83a363e1130008b06f0a4b3feea72b163e7d6..f22f6fa612b379efb674383e8470c3e526d9f5e9 100644 (file)
@@ -314,14 +314,17 @@ void cryp_save_device_context(struct cryp_device_data *device_data,
        case CRYP_KEY_SIZE_256:
                ctx->key_4_l = readl_relaxed(&src_reg->key_4_l);
                ctx->key_4_r = readl_relaxed(&src_reg->key_4_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_192:
                ctx->key_3_l = readl_relaxed(&src_reg->key_3_l);
                ctx->key_3_r = readl_relaxed(&src_reg->key_3_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_128:
                ctx->key_2_l = readl_relaxed(&src_reg->key_2_l);
                ctx->key_2_r = readl_relaxed(&src_reg->key_2_r);
+               /* Fall through */
 
        default:
                ctx->key_1_l = readl_relaxed(&src_reg->key_1_l);
@@ -361,14 +364,17 @@ void cryp_restore_device_context(struct cryp_device_data *device_data,
        case CRYP_KEY_SIZE_256:
                writel_relaxed(ctx->key_4_l, &reg->key_4_l);
                writel_relaxed(ctx->key_4_r, &reg->key_4_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_192:
                writel_relaxed(ctx->key_3_l, &reg->key_3_l);
                writel_relaxed(ctx->key_3_r, &reg->key_3_r);
+               /* Fall through */
 
        case CRYP_KEY_SIZE_128:
                writel_relaxed(ctx->key_2_l, &reg->key_2_l);
                writel_relaxed(ctx->key_2_r, &reg->key_2_r);
+               /* Fall through */
 
        default:
                writel_relaxed(ctx->key_1_l, &reg->key_1_l);
index b6cc90cbc9dc244734fd763a9ed34829419c994a..4e5f9f6e901baec4f3c87f9fd3ed0f7b5bb5874b 100644 (file)
@@ -50,7 +50,7 @@ struct dw_edma_burst {
 
 struct dw_edma_region {
        phys_addr_t                     paddr;
-       dma_addr_t                      vaddr;
+       void                            __iomem *vaddr;
        size_t                          sz;
 };
 
index 4c96e1c948f2be68489b264b69f488523f520995..dc85f55e1bb8ce3c3d9410d181c7362f9801ed7e 100644 (file)
@@ -130,19 +130,19 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
        chip->id = pdev->devfn;
        chip->irq = pdev->irq;
 
-       dw->rg_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->rg_bar];
+       dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg_bar];
        dw->rg_region.vaddr += pdata->rg_off;
        dw->rg_region.paddr = pdev->resource[pdata->rg_bar].start;
        dw->rg_region.paddr += pdata->rg_off;
        dw->rg_region.sz = pdata->rg_sz;
 
-       dw->ll_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->ll_bar];
+       dw->ll_region.vaddr = pcim_iomap_table(pdev)[pdata->ll_bar];
        dw->ll_region.vaddr += pdata->ll_off;
        dw->ll_region.paddr = pdev->resource[pdata->ll_bar].start;
        dw->ll_region.paddr += pdata->ll_off;
        dw->ll_region.sz = pdata->ll_sz;
 
-       dw->dt_region.vaddr = (dma_addr_t)pcim_iomap_table(pdev)[pdata->dt_bar];
+       dw->dt_region.vaddr = pcim_iomap_table(pdev)[pdata->dt_bar];
        dw->dt_region.vaddr += pdata->dt_off;
        dw->dt_region.paddr = pdev->resource[pdata->dt_bar].start;
        dw->dt_region.paddr += pdata->dt_off;
@@ -158,17 +158,17 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
        pci_dbg(pdev, "Mode:\t%s\n",
                dw->mode == EDMA_MODE_LEGACY ? "Legacy" : "Unroll");
 
-       pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+       pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
                pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
-               &dw->rg_region.vaddr, &dw->rg_region.paddr);
+               dw->rg_region.vaddr, &dw->rg_region.paddr);
 
-       pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+       pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
                pdata->ll_bar, pdata->ll_off, pdata->ll_sz,
-               &dw->ll_region.vaddr, &dw->ll_region.paddr);
+               dw->ll_region.vaddr, &dw->ll_region.paddr);
 
-       pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%pa, p=%pa)\n",
+       pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
                pdata->dt_bar, pdata->dt_off, pdata->dt_sz,
-               &dw->dt_region.vaddr, &dw->dt_region.paddr);
+               dw->dt_region.vaddr, &dw->dt_region.paddr);
 
        pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
 
index 8a3180ed49a60940492d5c32f31518618e8ff97a..692de47b16701dc7b9f75aefa657618a352149d5 100644 (file)
@@ -25,7 +25,7 @@ enum dw_edma_control {
 
 static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
 {
-       return (struct dw_edma_v0_regs __iomem *)dw->rg_region.vaddr;
+       return dw->rg_region.vaddr;
 }
 
 #define SET(dw, name, value)                           \
@@ -192,13 +192,12 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
 static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 {
        struct dw_edma_burst *child;
-       struct dw_edma_v0_lli *lli;
-       struct dw_edma_v0_llp *llp;
+       struct dw_edma_v0_lli __iomem *lli;
+       struct dw_edma_v0_llp __iomem *llp;
        u32 control = 0, i = 0;
-       u64 sar, dar, addr;
        int j;
 
-       lli = (struct dw_edma_v0_lli *)chunk->ll_region.vaddr;
+       lli = chunk->ll_region.vaddr;
 
        if (chunk->cb)
                control = DW_EDMA_V0_CB;
@@ -214,17 +213,15 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
                /* Transfer size */
                SET_LL(&lli[i].transfer_size, child->sz);
                /* SAR - low, high */
-               sar = cpu_to_le64(child->sar);
-               SET_LL(&lli[i].sar_low, lower_32_bits(sar));
-               SET_LL(&lli[i].sar_high, upper_32_bits(sar));
+               SET_LL(&lli[i].sar_low, lower_32_bits(child->sar));
+               SET_LL(&lli[i].sar_high, upper_32_bits(child->sar));
                /* DAR - low, high */
-               dar = cpu_to_le64(child->dar);
-               SET_LL(&lli[i].dar_low, lower_32_bits(dar));
-               SET_LL(&lli[i].dar_high, upper_32_bits(dar));
+               SET_LL(&lli[i].dar_low, lower_32_bits(child->dar));
+               SET_LL(&lli[i].dar_high, upper_32_bits(child->dar));
                i++;
        }
 
-       llp = (struct dw_edma_v0_llp *)&lli[i];
+       llp = (void __iomem *)&lli[i];
        control = DW_EDMA_V0_LLP | DW_EDMA_V0_TCB;
        if (!chunk->cb)
                control |= DW_EDMA_V0_CB;
@@ -232,9 +229,8 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
        /* Channel control */
        SET_LL(&llp->control, control);
        /* Linked list  - low, high */
-       addr = cpu_to_le64(chunk->ll_region.paddr);
-       SET_LL(&llp->llp_low, lower_32_bits(addr));
-       SET_LL(&llp->llp_high, upper_32_bits(addr));
+       SET_LL(&llp->llp_low, lower_32_bits(chunk->ll_region.paddr));
+       SET_LL(&llp->llp_high, upper_32_bits(chunk->ll_region.paddr));
 }
 
 void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
@@ -242,7 +238,6 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
        struct dw_edma_chan *chan = chunk->chan;
        struct dw_edma *dw = chan->chip->dw;
        u32 tmp;
-       u64 llp;
 
        dw_edma_v0_core_write_chunk(chunk);
 
@@ -262,9 +257,10 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
                SET_CH(dw, chan->dir, chan->id, ch_control1,
                       (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
                /* Linked list - low, high */
-               llp = cpu_to_le64(chunk->ll_region.paddr);
-               SET_CH(dw, chan->dir, chan->id, llp_low, lower_32_bits(llp));
-               SET_CH(dw, chan->dir, chan->id, llp_high, upper_32_bits(llp));
+               SET_CH(dw, chan->dir, chan->id, llp_low,
+                      lower_32_bits(chunk->ll_region.paddr));
+               SET_CH(dw, chan->dir, chan->id, llp_high,
+                      upper_32_bits(chunk->ll_region.paddr));
        }
        /* Doorbell */
        SET_RW(dw, chan->dir, doorbell,
index 3226f528cc11395409ae503f45ce9816ead6d8bc..42739508c0d854c669ea3f40baf2c0e8e61a59c9 100644 (file)
@@ -14,7 +14,7 @@
 #include "dw-edma-core.h"
 
 #define REGS_ADDR(name) \
-       ((dma_addr_t *)&regs->name)
+       ((void __force *)&regs->name)
 #define REGISTER(name) \
        { #name, REGS_ADDR(name) }
 
 
 static struct dentry                           *base_dir;
 static struct dw_edma                          *dw;
-static struct dw_edma_v0_regs                  *regs;
+static struct dw_edma_v0_regs                  __iomem *regs;
 
 static struct {
-       void                                    *start;
-       void                                    *end;
+       void                                    __iomem *start;
+       void                                    __iomem *end;
 } lim[2][EDMA_V0_MAX_NR_CH];
 
 struct debugfs_entries {
-       char                                    name[24];
+       const char                              *name;
        dma_addr_t                              *reg;
 };
 
 static int dw_edma_debugfs_u32_get(void *data, u64 *val)
 {
+       void __iomem *reg = (void __force __iomem *)data;
        if (dw->mode == EDMA_MODE_LEGACY &&
-           data >= (void *)&regs->type.legacy.ch) {
-               void *ptr = (void *)&regs->type.legacy.ch;
+           reg >= (void __iomem *)&regs->type.legacy.ch) {
+               void __iomem *ptr = &regs->type.legacy.ch;
                u32 viewport_sel = 0;
                unsigned long flags;
                u16 ch;
 
                for (ch = 0; ch < dw->wr_ch_cnt; ch++)
-                       if (lim[0][ch].start >= data && data < lim[0][ch].end) {
-                               ptr += (data - lim[0][ch].start);
+                       if (lim[0][ch].start >= reg && reg < lim[0][ch].end) {
+                               ptr += (reg - lim[0][ch].start);
                                goto legacy_sel_wr;
                        }
 
                for (ch = 0; ch < dw->rd_ch_cnt; ch++)
-                       if (lim[1][ch].start >= data && data < lim[1][ch].end) {
-                               ptr += (data - lim[1][ch].start);
+                       if (lim[1][ch].start >= reg && reg < lim[1][ch].end) {
+                               ptr += (reg - lim[1][ch].start);
                                goto legacy_sel_rd;
                        }
 
@@ -86,7 +87,7 @@ legacy_sel_wr:
 
                raw_spin_unlock_irqrestore(&dw->lock, flags);
        } else {
-               *val = readl(data);
+               *val = readl(reg);
        }
 
        return 0;
@@ -105,7 +106,7 @@ static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],
        }
 }
 
-static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs *regs,
+static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
                                    struct dentry *dir)
 {
        int nr_entries;
@@ -288,7 +289,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
        if (!dw)
                return;
 
-       regs = (struct dw_edma_v0_regs *)dw->rg_region.vaddr;
+       regs = dw->rg_region.vaddr;
        if (!regs)
                return;
 
index 89d710899010d3d804a2acc3d92d07f287366d4c..de8bfd9a76e9ebc87d678002de85096b85d80810 100644 (file)
@@ -142,7 +142,7 @@ enum d40_events {
  * when the DMA hw is powered off.
  * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works.
  */
-static u32 d40_backup_regs[] = {
+static __maybe_unused u32 d40_backup_regs[] = {
        D40_DREG_LCPA,
        D40_DREG_LCLA,
        D40_DREG_PRMSE,
@@ -211,7 +211,7 @@ static u32 d40_backup_regs_v4b[] = {
 
 #define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b)
 
-static u32 d40_backup_regs_chan[] = {
+static __maybe_unused u32 d40_backup_regs_chan[] = {
        D40_CHAN_REG_SSCFG,
        D40_CHAN_REG_SSELT,
        D40_CHAN_REG_SSPTR,
index d6e919d3936a295e75271329035f02ad7239e076..1311de74bfdde5f817937fd2a929a1e02ce00c0f 100644 (file)
@@ -1366,7 +1366,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
 
        chan = &dmadev->chan[id];
        if (!chan) {
-               dev_err(chan2dev(chan), "MDMA channel not initialized\n");
+               dev_dbg(mdma2dev(dmadev), "MDMA channel not initialized\n");
                goto exit;
        }
 
index 2805853e963fcf6f9076e8360ebd519585efa94e..b33cf6e8ab8ef85b67a885fafa8161ee1c989d68 100644 (file)
@@ -712,7 +712,7 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
        return chan;
 }
 
-static int tegra_adma_runtime_suspend(struct device *dev)
+static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
 {
        struct tegra_adma *tdma = dev_get_drvdata(dev);
        struct tegra_adma_chan_regs *ch_reg;
@@ -744,7 +744,7 @@ clk_disable:
        return 0;
 }
 
-static int tegra_adma_runtime_resume(struct device *dev)
+static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
 {
        struct tegra_adma *tdma = dev_get_drvdata(dev);
        struct tegra_adma_chan_regs *ch_reg;
index ba2489d4ea246604ade12f48bf1e077e1ccd30e6..ba27802efcd0a900609893931e2f2fc4555dac0c 100644 (file)
@@ -1234,7 +1234,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
        if (src_icg) {
                d->ccr |= CCR_SRC_AMODE_DBLIDX;
                d->ei = 1;
-               d->fi = src_icg;
+               d->fi = src_icg + 1;
        } else if (xt->src_inc) {
                d->ccr |= CCR_SRC_AMODE_POSTINC;
                d->fi = 0;
@@ -1249,7 +1249,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_interleaved(
        if (dst_icg) {
                d->ccr |= CCR_DST_AMODE_DBLIDX;
                sg->ei = 1;
-               sg->fi = dst_icg;
+               sg->fi = dst_icg + 1;
        } else if (xt->dst_inc) {
                d->ccr |= CCR_DST_AMODE_POSTINC;
                sg->fi = 0;
index 1db780c0f07be671073e8d7a063dbc58aa6e2698..3caae7f2cf56772936b6f77484ef1f7e1a2b42c2 100644 (file)
@@ -927,17 +927,33 @@ fail:
        return status;
 }
 
+#define GET_EFI_CONFIG_TABLE(bits)                                     \
+static void *get_efi_config_table##bits(efi_system_table_t *_sys_table,        \
+                                       efi_guid_t guid)                \
+{                                                                      \
+       efi_system_table_##bits##_t *sys_table;                         \
+       efi_config_table_##bits##_t *tables;                            \
+       int i;                                                          \
+                                                                       \
+       sys_table = (typeof(sys_table))_sys_table;                      \
+       tables = (typeof(tables))(unsigned long)sys_table->tables;      \
+                                                                       \
+       for (i = 0; i < sys_table->nr_tables; i++) {                    \
+               if (efi_guidcmp(tables[i].guid, guid) != 0)             \
+                       continue;                                       \
+                                                                       \
+               return (void *)(unsigned long)tables[i].table;          \
+       }                                                               \
+                                                                       \
+       return NULL;                                                    \
+}
+GET_EFI_CONFIG_TABLE(32)
+GET_EFI_CONFIG_TABLE(64)
+
 void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 {
-       efi_config_table_t *tables = (efi_config_table_t *)sys_table->tables;
-       int i;
-
-       for (i = 0; i < sys_table->nr_tables; i++) {
-               if (efi_guidcmp(tables[i].guid, guid) != 0)
-                       continue;
-
-               return (void *)tables[i].table;
-       }
-
-       return NULL;
+       if (efi_is_64bit())
+               return get_efi_config_table64(sys_table, guid);
+       else
+               return get_efi_config_table32(sys_table, guid);
 }
index df8a2355483172fa6bc45303d93439036f681f2c..f6ac1e9548f276d4279d2830a15e7ca45428973f 100644 (file)
@@ -32,7 +32,6 @@ struct amdgpu_gds {
        uint32_t gws_size;
        uint32_t oa_size;
        uint32_t gds_compute_max_wave_id;
-       uint32_t vgt_gs_max_wave_id;
 };
 
 struct amdgpu_gds_reg_offset {
index 99f14fcc1460550c66e0bf7dfdfedcfc8b297723..19661c645703e56809c584b61916d141d5ed32d0 100644 (file)
@@ -30,6 +30,7 @@
 #define AMDGPU_VCN_FIRMWARE_OFFSET     256
 #define AMDGPU_VCN_MAX_ENC_RINGS       3
 
+#define VCN_DEC_KMD_CMD                0x80000000
 #define VCN_DEC_CMD_FENCE              0x00000000
 #define VCN_DEC_CMD_TRAP               0x00000001
 #define VCN_DEC_CMD_WRITE_REG          0x00000004
index 32773b7523d204a8b29266931fb4a9e577c571a4..f41287f9000da599accefb3382575d405c8a030b 100644 (file)
@@ -4206,15 +4206,6 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
        unsigned vmid = AMDGPU_JOB_GET_VMID(job);
        u32 header, control = 0;
 
-       /* Prevent a hw deadlock due to a wave ID mismatch between ME and GDS.
-        * This resets the wave ID counters. (needed by transform feedback)
-        * TODO: This might only be needed on a VMID switch when we change
-        *       the GDS OA mapping, not sure.
-        */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       amdgpu_ring_write(ring, mmVGT_GS_MAX_WAVE_ID);
-       amdgpu_ring_write(ring, ring->adev->gds.vgt_gs_max_wave_id);
-
        if (ib->flags & AMDGPU_IB_FLAG_CE)
                header = PACKET3(PACKET3_INDIRECT_BUFFER_CNST, 2);
        else
@@ -4961,7 +4952,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
                5 + /* HDP_INVL */
                8 + 8 + /* FENCE x2 */
                2, /* SWITCH_BUFFER */
-       .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_gfx */
+       .emit_ib_size = 4, /* gfx_v10_0_ring_emit_ib_gfx */
        .emit_ib = gfx_v10_0_ring_emit_ib_gfx,
        .emit_fence = gfx_v10_0_ring_emit_fence,
        .emit_pipeline_sync = gfx_v10_0_ring_emit_pipeline_sync,
@@ -5112,7 +5103,6 @@ static void gfx_v10_0_set_gds_init(struct amdgpu_device *adev)
        default:
                adev->gds.gds_size = 0x10000;
                adev->gds.gds_compute_max_wave_id = 0x4ff;
-               adev->gds.vgt_gs_max_wave_id = 0x3ff;
                break;
        }
 
index 751567f78567357c0099cf426c550fe7d9d72b3f..ee1ccdcf2d30e128751b82f9839397618bc2fb08 100644 (file)
@@ -1321,6 +1321,39 @@ static int gfx_v8_0_rlc_init(struct amdgpu_device *adev)
        return 0;
 }
 
+static int gfx_v8_0_csb_vram_pin(struct amdgpu_device *adev)
+{
+       int r;
+
+       r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+       if (unlikely(r != 0))
+               return r;
+
+       r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
+                       AMDGPU_GEM_DOMAIN_VRAM);
+       if (!r)
+               adev->gfx.rlc.clear_state_gpu_addr =
+                       amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
+
+       amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+
+       return r;
+}
+
+static void gfx_v8_0_csb_vram_unpin(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (!adev->gfx.rlc.clear_state_obj)
+               return;
+
+       r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
+       if (likely(r == 0)) {
+               amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
+               amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+       }
+}
+
 static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
 {
        amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -4785,6 +4818,10 @@ static int gfx_v8_0_hw_init(void *handle)
        gfx_v8_0_init_golden_registers(adev);
        gfx_v8_0_constants_init(adev);
 
+       r = gfx_v8_0_csb_vram_pin(adev);
+       if (r)
+               return r;
+
        r = adev->gfx.rlc.funcs->resume(adev);
        if (r)
                return r;
@@ -4901,6 +4938,9 @@ static int gfx_v8_0_hw_fini(void *handle)
        else
                pr_err("rlc is busy, skip halt rlc\n");
        amdgpu_gfx_rlc_exit_safe_mode(adev);
+
+       gfx_v8_0_csb_vram_unpin(adev);
+
        return 0;
 }
 
index 1cf639a511783c9cb1280f86a6ddbc3a5577c349..04b8ac4432c700ca92d877879c664862ab20ffaf 100644 (file)
@@ -4869,7 +4869,7 @@ static void gfx_v9_0_ring_soft_recovery(struct amdgpu_ring *ring, unsigned vmid)
        value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
        value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
        value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
-       WREG32(mmSQ_CMD, value);
+       WREG32_SOC15(GC, 0, mmSQ_CMD, value);
 }
 
 static void gfx_v9_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
index 1cfc2620b2dd46b4105d5e69bae8e55551f1905b..dfde886cc6bd161928835e9c79f23b176329d15a 100644 (file)
@@ -1485,7 +1485,7 @@ static void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET, 0));
        amdgpu_ring_write(ring, 0);
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
-       amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_START << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
 }
 
 /**
@@ -1498,7 +1498,7 @@ static void vcn_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
 static void vcn_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
 {
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
-       amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_END << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_END << 1));
 }
 
 /**
@@ -1543,7 +1543,7 @@ static void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
        amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
-       amdgpu_ring_write(ring, VCN_DEC_CMD_FENCE << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_FENCE << 1));
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0_INTERNAL_OFFSET, 0));
        amdgpu_ring_write(ring, 0);
@@ -1553,7 +1553,7 @@ static void vcn_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
 
-       amdgpu_ring_write(ring, VCN_DEC_CMD_TRAP << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_TRAP << 1));
 }
 
 /**
@@ -1597,7 +1597,7 @@ static void vcn_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring,
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
 
-       amdgpu_ring_write(ring, VCN_DEC_CMD_REG_READ_COND_WAIT << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_REG_READ_COND_WAIT << 1));
 }
 
 static void vcn_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
@@ -1626,7 +1626,7 @@ static void vcn_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
 
        amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
 
-       amdgpu_ring_write(ring, VCN_DEC_CMD_WRITE_REG << 1);
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_WRITE_REG << 1));
 }
 
 /**
@@ -2079,6 +2079,36 @@ static int vcn_v2_0_process_interrupt(struct amdgpu_device *adev,
        return 0;
 }
 
+static int vcn_v2_0_dec_ring_test_ring(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+       uint32_t tmp = 0;
+       unsigned i;
+       int r;
+
+       WREG32(adev->vcn.external.scratch9, 0xCAFEDEAD);
+       r = amdgpu_ring_alloc(ring, 4);
+       if (r)
+               return r;
+       amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET, 0));
+       amdgpu_ring_write(ring, VCN_DEC_KMD_CMD | (VCN_DEC_CMD_PACKET_START << 1));
+       amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
+       amdgpu_ring_write(ring, 0xDEADBEEF);
+       amdgpu_ring_commit(ring);
+       for (i = 0; i < adev->usec_timeout; i++) {
+               tmp = RREG32(adev->vcn.external.scratch9);
+               if (tmp == 0xDEADBEEF)
+                       break;
+               DRM_UDELAY(1);
+       }
+
+       if (i >= adev->usec_timeout)
+               r = -ETIMEDOUT;
+
+       return r;
+}
+
+
 static int vcn_v2_0_set_powergating_state(void *handle,
                                          enum amd_powergating_state state)
 {
@@ -2142,7 +2172,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
        .emit_ib = vcn_v2_0_dec_ring_emit_ib,
        .emit_fence = vcn_v2_0_dec_ring_emit_fence,
        .emit_vm_flush = vcn_v2_0_dec_ring_emit_vm_flush,
-       .test_ring = amdgpu_vcn_dec_ring_test_ring,
+       .test_ring = vcn_v2_0_dec_ring_test_ring,
        .test_ib = amdgpu_vcn_dec_ring_test_ib,
        .insert_nop = vcn_v2_0_dec_ring_insert_nop,
        .insert_start = vcn_v2_0_dec_ring_insert_start,
index 26b15cc56c31c60b624ba13eaf566cfad3525747..1d3cd5c50d5f2b06191e5bf8ff1fee7bed7a6225 100644 (file)
@@ -1567,32 +1567,6 @@ copy_from_user_failed:
        return err;
 }
 
-static int kfd_ioctl_alloc_queue_gws(struct file *filep,
-               struct kfd_process *p, void *data)
-{
-       int retval;
-       struct kfd_ioctl_alloc_queue_gws_args *args = data;
-       struct kfd_dev *dev;
-
-       if (!hws_gws_support)
-               return -ENODEV;
-
-       dev = kfd_device_by_id(args->gpu_id);
-       if (!dev) {
-               pr_debug("Could not find gpu id 0x%x\n", args->gpu_id);
-               return -ENODEV;
-       }
-       if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
-               return -ENODEV;
-
-       mutex_lock(&p->mutex);
-       retval = pqm_set_gws(&p->pqm, args->queue_id, args->num_gws ? dev->gws : NULL);
-       mutex_unlock(&p->mutex);
-
-       args->first_gws = 0;
-       return retval;
-}
-
 static int kfd_ioctl_get_dmabuf_info(struct file *filep,
                struct kfd_process *p, void *data)
 {
@@ -1795,8 +1769,6 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
        AMDKFD_IOCTL_DEF(AMDKFD_IOC_IMPORT_DMABUF,
                                kfd_ioctl_import_dmabuf, 0),
 
-       AMDKFD_IOCTL_DEF(AMDKFD_IOC_ALLOC_QUEUE_GWS,
-                       kfd_ioctl_alloc_queue_gws, 0),
 };
 
 #define AMDKFD_CORE_IOCTL_COUNT        ARRAY_SIZE(amdkfd_ioctls)
index fa20201eef3a8b03765a03158865bca006edcba9..cbc480a333764130878e64b880ef2073a1b440ff 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/mm.h>
 
 #include "dm_services.h"
 
@@ -1171,8 +1172,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
 
 struct dc_state *dc_create_state(struct dc *dc)
 {
-       struct dc_state *context = kzalloc(sizeof(struct dc_state),
-                                          GFP_KERNEL);
+       struct dc_state *context = kvzalloc(sizeof(struct dc_state),
+                                           GFP_KERNEL);
 
        if (!context)
                return NULL;
@@ -1192,11 +1193,11 @@ struct dc_state *dc_create_state(struct dc *dc)
 struct dc_state *dc_copy_state(struct dc_state *src_ctx)
 {
        int i, j;
-       struct dc_state *new_ctx = kmemdup(src_ctx,
-                       sizeof(struct dc_state), GFP_KERNEL);
+       struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
 
        if (!new_ctx)
                return NULL;
+       memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
 
        for (i = 0; i < MAX_PIPES; i++) {
                        struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
@@ -1230,7 +1231,7 @@ static void dc_state_free(struct kref *kref)
 {
        struct dc_state *context = container_of(kref, struct dc_state, refcount);
        dc_resource_state_destruct(context);
-       kfree(context);
+       kvfree(context);
 }
 
 void dc_release_state(struct dc_state *context)
index 0685a3388e38ce7ae2667319a22726b0b26c947e..8a3eadeebdcb611c4bd685376514802679d48601 100644 (file)
@@ -315,6 +315,8 @@ int smu_get_power_num_states(struct smu_context *smu,
 int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
                           void *data, uint32_t *size)
 {
+       struct smu_power_context *smu_power = &smu->smu_power;
+       struct smu_power_gate *power_gate = &smu_power->power_gate;
        int ret = 0;
 
        switch (sensor) {
@@ -339,7 +341,7 @@ int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
                *size = 4;
                break;
        case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
-               *(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT) ? 1 : 0;
+               *(uint32_t *)data = power_gate->vcn_gated ? 0 : 1;
                *size = 4;
                break;
        default:
index 208e6711d5068fc16d7359acaa198190ea7a5a94..a0f52c86d8c7efa608221d4f56627894cfd2a244 100644 (file)
@@ -451,6 +451,7 @@ struct smu_dpm_context {
 struct smu_power_gate {
        bool uvd_gated;
        bool vce_gated;
+       bool vcn_gated;
 };
 
 struct smu_power_context {
index cc0a3b2256aff71ff8d2f4c03499d45190b088fe..b81c7e715dc943b00b3c0d456c17d42f5c01240e 100644 (file)
@@ -502,6 +502,8 @@ static int navi10_store_powerplay_table(struct smu_context *smu)
 
 static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
 {
+       struct smu_table_context *smu_table = &smu->smu_table;
+
        SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
                       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
        SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
@@ -516,9 +518,35 @@ static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
                       sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
                       AMDGPU_GEM_DOMAIN_VRAM);
 
+       smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+       if (!smu_table->metrics_table)
+               return -ENOMEM;
+       smu_table->metrics_time = 0;
+
        return 0;
 }
 
+static int navi10_get_metrics_table(struct smu_context *smu,
+                                   SmuMetrics_t *metrics_table)
+{
+       struct smu_table_context *smu_table= &smu->smu_table;
+       int ret = 0;
+
+       if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
+               ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
+                               (void *)smu_table->metrics_table, false);
+               if (ret) {
+                       pr_info("Failed to export SMU metrics table!\n");
+                       return ret;
+               }
+               smu_table->metrics_time = jiffies;
+       }
+
+       memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+
+       return ret;
+}
+
 static int navi10_allocate_dpm_context(struct smu_context *smu)
 {
        struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
@@ -577,20 +605,27 @@ static int navi10_set_default_dpm_table(struct smu_context *smu)
 
 static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
 {
+       struct smu_power_context *smu_power = &smu->smu_power;
+       struct smu_power_gate *power_gate = &smu_power->power_gate;
        int ret = 0;
 
        if (enable) {
-               ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
-               if (ret)
-                       return ret;
+               /* vcn dpm on is a prerequisite for vcn power gate messages */
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
+                       if (ret)
+                               return ret;
+               }
+               power_gate->vcn_gated = false;
        } else {
-               ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
-               if (ret)
-                       return ret;
+               if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+                       ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
+                       if (ret)
+                               return ret;
+               }
+               power_gate->vcn_gated = true;
        }
 
-       ret = smu_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, enable);
-
        return ret;
 }
 
@@ -598,15 +633,10 @@ static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
                                       enum smu_clk_type clk_type,
                                       uint32_t *value)
 {
-       static SmuMetrics_t metrics;
        int ret = 0, clk_id = 0;
+       SmuMetrics_t metrics;
 
-       if (!value)
-               return -EINVAL;
-
-       memset(&metrics, 0, sizeof(metrics));
-
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
        if (ret)
                return ret;
 
@@ -894,8 +924,9 @@ static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
        if (!value)
                return -EINVAL;
 
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics,
-                              false);
+       ret = navi10_get_metrics_table(smu, &metrics);
+       if (ret)
+               return ret;
        if (ret)
                return ret;
 
@@ -914,10 +945,7 @@ static int navi10_get_current_activity_percent(struct smu_context *smu,
        if (!value)
                return -EINVAL;
 
-       msleep(1);
-
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
-                              (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
        if (ret)
                return ret;
 
@@ -956,10 +984,9 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu,
        if (!speed)
                return -EINVAL;
 
-       memset(&metrics, 0, sizeof(metrics));
-
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
-                              (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
+       if (ret)
+               return ret;
        if (ret)
                return ret;
 
@@ -1307,7 +1334,7 @@ static int navi10_thermal_get_temperature(struct smu_context *smu,
        if (!value)
                return -EINVAL;
 
-       ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)&metrics, false);
+       ret = navi10_get_metrics_table(smu, &metrics);
        if (ret)
                return ret;
 
index ac5b26228e753e2071d32c10e3562aabc97c449f..5fde5cf65b4240a7428e3c89be0dabc0ea12902f 100644 (file)
@@ -1391,7 +1391,7 @@ smu_v11_0_smc_fan_control(struct smu_context *smu, bool start)
 {
        int ret = 0;
 
-       if (smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
+       if (!smu_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
                return 0;
 
        ret = smu_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, start);
index 4c7e31cb45ffaf14073ab3ccf286dee27823f9d6..a5d1494a3dc44b853d6b19472305341c18c504fd 100644 (file)
@@ -131,8 +131,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 
 
        /* Enable extended register access */
-       ast_enable_mmio(dev);
        ast_open_key(ast);
+       ast_enable_mmio(dev);
 
        /* Find out whether P2A works or whether to use device-tree */
        ast_detect_config_mode(dev, &scu_rev);
@@ -576,6 +576,9 @@ void ast_driver_unload(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
 
+       /* enable standard VGA decode */
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04);
+
        ast_release_firmware(dev);
        kfree(ast->dp501_fw_addr);
        ast_mode_fini(dev);
index ffccbef962a41d44d331e1b8da970a0246483b2b..a1cb020e07e502197428bc0fca447c650c381110 100644 (file)
@@ -604,7 +604,7 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc,
                return -EINVAL;
        ast_open_key(ast);
 
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
 
        ast_set_std_reg(crtc, adjusted_mode, &vbios_mode);
        ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode);
index f7d421359d564756ff86d78c64293e37eea74c7e..c1d1ac51d1c207c0cb0b2f08825aa19ca7761bde 100644 (file)
@@ -46,7 +46,7 @@ void ast_enable_mmio(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
 
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
 }
 
 
index 80fcd5dc155889dbdbc64d422980b5566a00674e..b0369e690f36cf67a9d60eac23f7b767dbb66074 100644 (file)
@@ -1770,7 +1770,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
        }
 
        if (named_mode) {
-               strncpy(mode->name, name, mode_end);
+               if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
+                       return false;
+               strscpy(mode->name, name, mode_end + 1);
        } else {
                ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
                                                      parse_extras,
index bc3a94d491c4d0992b24346d011840318ade13d2..27bd7276a82dcfad356e2bc81d861d93ac99a000 100644 (file)
@@ -536,7 +536,8 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
 
        if (drm_hdcp_check_ksvs_revoked(dev, ksv_fifo, num_downstream)) {
                DRM_ERROR("Revoked Ksv(s) in ksv_fifo\n");
-               return -EPERM;
+               ret = -EPERM;
+               goto err;
        }
 
        /*
index 99cc3e2e9c2cdc9b74b65714cf567f6a2ea2fb49..f016a776a39e32bf96f77dbd363997b7ad5caf1b 100644 (file)
@@ -396,8 +396,8 @@ static void glk_dsi_program_esc_clock(struct drm_device *dev,
        else
                txesc2_div = 10;
 
-       I915_WRITE(MIPIO_TXESC_CLK_DIV1, txesc1_div & GLK_TX_ESC_CLK_DIV1_MASK);
-       I915_WRITE(MIPIO_TXESC_CLK_DIV2, txesc2_div & GLK_TX_ESC_CLK_DIV2_MASK);
+       I915_WRITE(MIPIO_TXESC_CLK_DIV1, (1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK);
+       I915_WRITE(MIPIO_TXESC_CLK_DIV2, (1 << (txesc2_div - 1)) & GLK_TX_ESC_CLK_DIV2_MASK);
 }
 
 /* Program BXT Mipi clocks and dividers */
index 5fae0e50aad06881a53bc70c708ceccb7cbfe7d7..41dab9ea33cd4e566396550b0d9cc7aa299442ff 100644 (file)
@@ -1628,6 +1628,7 @@ static int check_relocations(const struct drm_i915_gem_exec_object2 *entry)
 
 static int eb_copy_relocations(const struct i915_execbuffer *eb)
 {
+       struct drm_i915_gem_relocation_entry *relocs;
        const unsigned int count = eb->buffer_count;
        unsigned int i;
        int err;
@@ -1635,7 +1636,6 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
        for (i = 0; i < count; i++) {
                const unsigned int nreloc = eb->exec[i].relocation_count;
                struct drm_i915_gem_relocation_entry __user *urelocs;
-               struct drm_i915_gem_relocation_entry *relocs;
                unsigned long size;
                unsigned long copied;
 
@@ -1663,14 +1663,8 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb)
 
                        if (__copy_from_user((char *)relocs + copied,
                                             (char __user *)urelocs + copied,
-                                            len)) {
-end_user:
-                               user_access_end();
-end:
-                               kvfree(relocs);
-                               err = -EFAULT;
-                               goto err;
-                       }
+                                            len))
+                               goto end;
 
                        copied += len;
                } while (copied < size);
@@ -1699,10 +1693,14 @@ end:
 
        return 0;
 
+end_user:
+       user_access_end();
+end:
+       kvfree(relocs);
+       err = -EFAULT;
 err:
        while (i--) {
-               struct drm_i915_gem_relocation_entry *relocs =
-                       u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
+               relocs = u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr);
                if (eb->exec[i].relocation_count)
                        kvfree(relocs);
        }
index 9f3fd7d96a694a6fe890978dd19e3c38160965e4..75baff657e4331f28fc58d938c7a9de7087e0fcc 100644 (file)
@@ -1528,9 +1528,9 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
                        if (!intel_gvt_ggtt_validate_range(vgpu,
                                workload->wa_ctx.indirect_ctx.guest_gma,
                                workload->wa_ctx.indirect_ctx.size)) {
-                               kmem_cache_free(s->workloads, workload);
                                gvt_vgpu_err("invalid wa_ctx at: 0x%lx\n",
                                    workload->wa_ctx.indirect_ctx.guest_gma);
+                               kmem_cache_free(s->workloads, workload);
                                return ERR_PTR(-EINVAL);
                        }
                }
@@ -1542,9 +1542,9 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
                        if (!intel_gvt_ggtt_validate_range(vgpu,
                                workload->wa_ctx.per_ctx.guest_gma,
                                CACHELINE_BYTES)) {
-                               kmem_cache_free(s->workloads, workload);
                                gvt_vgpu_err("invalid per_ctx at: 0x%lx\n",
                                        workload->wa_ctx.per_ctx.guest_gma);
+                               kmem_cache_free(s->workloads, workload);
                                return ERR_PTR(-EINVAL);
                        }
                }
index 126703816794e77a521437271e09a34a09015f4b..5c36c75232e6d0364f4d90419b7a7010da8985e9 100644 (file)
@@ -771,16 +771,20 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
        struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
        int slots;
 
-       /* When restoring duplicated states, we need to make sure that the
-        * bw remains the same and avoid recalculating it, as the connector's
-        * bpc may have changed after the state was duplicated
-        */
-       if (!state->duplicated)
-               asyh->dp.pbn =
-                       drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
-                                            connector->display_info.bpc * 3);
+       if (crtc_state->mode_changed || crtc_state->connectors_changed) {
+               /*
+                * When restoring duplicated states, we need to make sure that
+                * the bw remains the same and avoid recalculating it, as the
+                * connector's bpc may have changed after the state was
+                * duplicated
+                */
+               if (!state->duplicated) {
+                       const int bpp = connector->display_info.bpc * 3;
+                       const int clock = crtc_state->adjusted_mode.clock;
+
+                       asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
+               }
 
-       if (crtc_state->mode_changed) {
                slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
                                                      mstc->port,
                                                      asyh->dp.pbn);
index 95e5c517a15f766132981eebc148f488e13a4074..9aae3d8e99ef426743d21533f3b1168449a56fe5 100644 (file)
@@ -432,7 +432,7 @@ static int rockchip_dp_resume(struct device *dev)
 
 static const struct dev_pm_ops rockchip_dp_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
-       .suspend = rockchip_dp_suspend,
+       .suspend_late = rockchip_dp_suspend,
        .resume_early = rockchip_dp_resume,
 #endif
 };
index 35ddbec1375ae880bba180a4d7f46173b38e2ec2..671c90f34ede6ba6ed6eb40e3159243cf142e7be 100644 (file)
@@ -95,7 +95,7 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity)
        rmb(); /* for list_empty to work without lock */
 
        if (list_empty(&entity->list) ||
-           spsc_queue_peek(&entity->job_queue) == NULL)
+           spsc_queue_count(&entity->job_queue) == 0)
                return true;
 
        return false;
@@ -281,7 +281,7 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity)
        /* Consumption of existing IBs wasn't completed. Forcefully
         * remove them here.
         */
-       if (spsc_queue_peek(&entity->job_queue)) {
+       if (spsc_queue_count(&entity->job_queue)) {
                if (sched) {
                        /* Park the kernel for a moment to make sure it isn't processing
                         * our enity.
index 274cb955e2e19f496ed0be39c0610fe98609d645..bdcaa4c7168cfac967290347808bf08642dbe576 100644 (file)
@@ -126,8 +126,12 @@ int tegra_output_probe(struct tegra_output *output)
                                                       "nvidia,hpd-gpio", 0,
                                                       GPIOD_IN,
                                                       "HDMI hotplug detect");
-       if (IS_ERR(output->hpd_gpio))
-               return PTR_ERR(output->hpd_gpio);
+       if (IS_ERR(output->hpd_gpio)) {
+               if (PTR_ERR(output->hpd_gpio) != -ENOENT)
+                       return PTR_ERR(output->hpd_gpio);
+
+               output->hpd_gpio = NULL;
+       }
 
        if (output->hpd_gpio) {
                err = gpiod_to_irq(output->hpd_gpio);
index e4e09d47c5c0e001934a14a2df103e13a7a328aa..59e9d05ab928b49f2c6ca1f3a0cd5fbecdd56a1b 100644 (file)
@@ -389,8 +389,10 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
                break;
        }
 
-       if (retries == RETRIES)
+       if (retries == RETRIES) {
+               kfree(reply);
                return -EINVAL;
+       }
 
        *msg_len = reply_len;
        *msg     = reply;
index 81df62f48c4c32b8d1b89a89ea3f85b95450281c..6ac8becc2372efdd303ba29d14a246e9f5290239 100644 (file)
@@ -54,7 +54,6 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\")
 struct apple_sc {
        unsigned long quirks;
        unsigned int fn_on;
-       DECLARE_BITMAP(pressed_fn, KEY_CNT);
        DECLARE_BITMAP(pressed_numlock, KEY_CNT);
 };
 
@@ -181,6 +180,8 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
 {
        struct apple_sc *asc = hid_get_drvdata(hid);
        const struct apple_key_translation *trans, *table;
+       bool do_translate;
+       u16 code = 0;
 
        if (usage->code == KEY_FN) {
                asc->fn_on = !!value;
@@ -189,8 +190,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
        }
 
        if (fnmode) {
-               int do_translate;
-
                if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
                                hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
                        table = macbookair_fn_keys;
@@ -202,25 +201,33 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
                trans = apple_find_translation (table, usage->code);
 
                if (trans) {
-                       if (test_bit(usage->code, asc->pressed_fn))
-                               do_translate = 1;
-                       else if (trans->flags & APPLE_FLAG_FKEY)
-                               do_translate = (fnmode == 2 && asc->fn_on) ||
-                                       (fnmode == 1 && !asc->fn_on);
-                       else
-                               do_translate = asc->fn_on;
-
-                       if (do_translate) {
-                               if (value)
-                                       set_bit(usage->code, asc->pressed_fn);
-                               else
-                                       clear_bit(usage->code, asc->pressed_fn);
-
-                               input_event(input, usage->type, trans->to,
-                                               value);
-
-                               return 1;
+                       if (test_bit(trans->from, input->key))
+                               code = trans->from;
+                       else if (test_bit(trans->to, input->key))
+                               code = trans->to;
+
+                       if (!code) {
+                               if (trans->flags & APPLE_FLAG_FKEY) {
+                                       switch (fnmode) {
+                                       case 1:
+                                               do_translate = !asc->fn_on;
+                                               break;
+                                       case 2:
+                                               do_translate = asc->fn_on;
+                                               break;
+                                       default:
+                                               /* should never happen */
+                                               do_translate = false;
+                                       }
+                               } else {
+                                       do_translate = asc->fn_on;
+                               }
+
+                               code = do_translate ? trans->to : trans->from;
                        }
+
+                       input_event(input, usage->type, code, value);
+                       return 1;
                }
 
                if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
index 999f80a63bffab43abf57c5daf5bd1a2b952d797..e70783e33680f1ec2ffa6b2bf46b266093907e57 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM hyperv
index 3fb9c0a2d6d0bc2241d6777901d9a7da49057ceb..ce5ec403ec739c819ee8f896e5958d63380246ee 100644 (file)
@@ -343,7 +343,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                data->sample_time = MSEC_PER_SEC / 2;
                break;
        case tmp75b:  /* not one-shot mode, Conversion rate 37Hz */
-               clr_mask |= 1 << 15 | 0x3 << 13;
+               clr_mask |= 1 << 7 | 0x3 << 5;
                data->resolution = 12;
                data->sample_time = MSEC_PER_SEC / 37;
                break;
index ec7bcf8d7cd66d3280e752481c21774c2310fc17..f3dd2a17bd426244d72d26a8d027fa24523cbb00 100644 (file)
@@ -704,7 +704,7 @@ static struct attribute *nct7802_in_attrs[] = {
        &sensor_dev_attr_in3_alarm.dev_attr.attr,
        &sensor_dev_attr_in3_beep.dev_attr.attr,
 
-       &sensor_dev_attr_in4_input.dev_attr.attr,       /* 17 */
+       &sensor_dev_attr_in4_input.dev_attr.attr,       /* 16 */
        &sensor_dev_attr_in4_min.dev_attr.attr,
        &sensor_dev_attr_in4_max.dev_attr.attr,
        &sensor_dev_attr_in4_alarm.dev_attr.attr,
@@ -730,9 +730,9 @@ static umode_t nct7802_in_is_visible(struct kobject *kobj,
 
        if (index >= 6 && index < 11 && (reg & 0x03) != 0x03)   /* VSEN1 */
                return 0;
-       if (index >= 11 && index < 17 && (reg & 0x0c) != 0x0c)  /* VSEN2 */
+       if (index >= 11 && index < 16 && (reg & 0x0c) != 0x0c)  /* VSEN2 */
                return 0;
-       if (index >= 17 && (reg & 0x30) != 0x30)                /* VSEN3 */
+       if (index >= 16 && (reg & 0x30) != 0x30)                /* VSEN3 */
                return 0;
 
        return attr->mode;
index 5c1ca0df5cb0064d3e0c633805bf42b8ef00622c..84f1dcb6982724c88980285c239e9342b08da6b0 100644 (file)
@@ -544,6 +544,7 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)
        /* See function coresight_get_sink_by_id() to know where this is used */
        hash = hashlen_hash(hashlen_string(NULL, name));
 
+       sysfs_attr_init(&ea->attr.attr);
        ea->attr.attr.name = devm_kstrdup(dev, name, GFP_KERNEL);
        if (!ea->attr.attr.name)
                return -ENOMEM;
index 574c16004cb2e266f892ef73d0c3e88fa0fbbb68..13d9b141daaaaf3da7e4b8195e2ec6c41929fb42 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Intel(R) Trace Hub Memory Storage Unit (MSU) data structures
  *
index e9381babc84c37f662ee8e822806a99a1dd9bab3..7dfc0431333b77f81f822ffd0bd988de259c5bbe 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Intel(R) Trace Hub PTI output data structures
  *
index 35b302d983e0d93d74b255d57f113226f9c799f9..959d4912ec0d5ce1082c4713cee86e13b10a228d 100644 (file)
@@ -69,6 +69,7 @@ struct em_i2c_device {
        struct completion msg_done;
        struct clk *sclk;
        struct i2c_client *slave;
+       int irq;
 };
 
 static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
@@ -339,6 +340,12 @@ static int em_i2c_unreg_slave(struct i2c_client *slave)
 
        writeb(0, priv->base + I2C_OFS_SVA0);
 
+       /*
+        * Wait for interrupt to finish. New slave irqs cannot happen because we
+        * cleared the slave address and, thus, only extension codes will be
+        * detected which do not use the slave ptr.
+        */
+       synchronize_irq(priv->irq);
        priv->slave = NULL;
 
        return 0;
@@ -355,7 +362,7 @@ static int em_i2c_probe(struct platform_device *pdev)
 {
        struct em_i2c_device *priv;
        struct resource *r;
-       int irq, ret;
+       int ret;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -390,8 +397,8 @@ static int em_i2c_probe(struct platform_device *pdev)
 
        em_i2c_reset(&priv->adap);
 
-       irq = platform_get_irq(pdev, 0);
-       ret = devm_request_irq(&pdev->dev, irq, em_i2c_irq_handler, 0,
+       priv->irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
                                "em_i2c", priv);
        if (ret)
                goto err_clk;
@@ -401,7 +408,8 @@ static int em_i2c_probe(struct platform_device *pdev)
        if (ret)
                goto err_clk;
 
-       dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr, irq);
+       dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr,
+                priv->irq);
 
        return 0;
 
index b1b8b938d7f423714b52582d0c203c4143846409..15f6cde6452f7113b30cd85784bf22a40a40b25c 100644 (file)
@@ -273,8 +273,8 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,
 }
 
 /* Functions for DMA support */
-static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
-                              dma_addr_t phy_addr)
+static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
+                                               dma_addr_t phy_addr)
 {
        struct imx_i2c_dma *dma;
        struct dma_slave_config dma_sconfig;
@@ -283,7 +283,7 @@ static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
 
        dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
        if (!dma)
-               return -ENOMEM;
+               return;
 
        dma->chan_tx = dma_request_chan(dev, "tx");
        if (IS_ERR(dma->chan_tx)) {
@@ -328,7 +328,7 @@ static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,
        dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
                dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
 
-       return 0;
+       return;
 
 fail_rx:
        dma_release_channel(dma->chan_rx);
@@ -336,8 +336,6 @@ fail_tx:
        dma_release_channel(dma->chan_tx);
 fail_al:
        devm_kfree(dev, dma);
-       /* return successfully if there is no dma support */
-       return ret == -ENODEV ? 0 : ret;
 }
 
 static void i2c_imx_dma_callback(void *arg)
@@ -1165,17 +1163,13 @@ static int i2c_imx_probe(struct platform_device *pdev)
        dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
        dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
                i2c_imx->adapter.name);
+       dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
 
        /* Init DMA config if supported */
-       ret = i2c_imx_dma_request(i2c_imx, phy_addr);
-       if (ret < 0)
-               goto del_adapter;
+       i2c_imx_dma_request(i2c_imx, phy_addr);
 
-       dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
        return 0;   /* Return OK */
 
-del_adapter:
-       i2c_del_adapter(&i2c_imx->adapter);
 clk_notifier_unregister:
        clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
 rpm_disable:
index d39a4606f72d3d7849d2727a4f83cad298bd58e3..531c01100b560be3c4960e0ff916b533505267a9 100644 (file)
@@ -139,6 +139,7 @@ struct rcar_i2c_priv {
        enum dma_data_direction dma_direction;
 
        struct reset_control *rstc;
+       int irq;
 };
 
 #define rcar_i2c_priv_to_dev(p)                ((p)->adap.dev.parent)
@@ -861,9 +862,11 @@ static int rcar_unreg_slave(struct i2c_client *slave)
 
        WARN_ON(!priv->slave);
 
+       /* disable irqs and ensure none is running before clearing ptr */
        rcar_i2c_write(priv, ICSIER, 0);
        rcar_i2c_write(priv, ICSCR, 0);
 
+       synchronize_irq(priv->irq);
        priv->slave = NULL;
 
        pm_runtime_put(rcar_i2c_priv_to_dev(priv));
@@ -918,7 +921,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        struct i2c_adapter *adap;
        struct device *dev = &pdev->dev;
        struct i2c_timings i2c_t;
-       int irq, ret;
+       int ret;
 
        /* Otherwise logic will break because some bytes must always use PIO */
        BUILD_BUG_ON_MSG(RCAR_MIN_DMA_LEN < 3, "Invalid min DMA length");
@@ -984,10 +987,10 @@ static int rcar_i2c_probe(struct platform_device *pdev)
                pm_runtime_put(dev);
 
 
-       irq = platform_get_irq(pdev, 0);
-       ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv);
+       priv->irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv);
        if (ret < 0) {
-               dev_err(dev, "cannot get irq %d\n", irq);
+               dev_err(dev, "cannot get irq %d\n", priv->irq);
                goto out_pm_disable;
        }
 
index 868755f82f884be35c67aa30edcba5f16057f9f6..2c21893905a30148f622e362f969cba32e94122e 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * i2c-stm32.h
  *
index 46bb2e421bb91a2a21fd6ee6ee08b04616d30509..ad19d9c716f41e4611af354511b1354711e2701c 100644 (file)
@@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = {
                .modified = 1,                                          \
                .info_mask_separate =                                   \
                        BIT(IIO_CHAN_INFO_RAW) |                        \
-                       BIT(IIO_CHAN_INFO_SCALE) |                      \
                        BIT(IIO_CHAN_INFO_CALIBBIAS),                   \
                .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),    \
                .ext_info = cros_ec_accel_legacy_ext_info,              \
index 92b1d5037ac984a4a013ccfb395342996f6ffb45..e234970b7150fb743e33f56e5cb28662b3ecf92c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/iio/iio.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #define JZ_ADC_REG_ADTCH               0x18
 #define JZ_ADC_REG_ADBDAT              0x1c
 #define JZ_ADC_REG_ADSDAT              0x20
+#define JZ_ADC_REG_ADCLK               0x28
 
 #define JZ_ADC_REG_CFG_BAT_MD          BIT(4)
+#define JZ_ADC_REG_ADCLK_CLKDIV_LSB    0
+#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB        16
 
 #define JZ_ADC_AUX_VREF                                3300
 #define JZ_ADC_AUX_VREF_BITS                   12
@@ -34,6 +38,8 @@
 #define JZ4740_ADC_BATTERY_HIGH_VREF           (7500 * 0.986)
 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS      12
 
+struct ingenic_adc;
+
 struct ingenic_adc_soc_data {
        unsigned int battery_high_vref;
        unsigned int battery_high_vref_bits;
@@ -41,6 +47,7 @@ struct ingenic_adc_soc_data {
        size_t battery_raw_avail_size;
        const int *battery_scale_avail;
        size_t battery_scale_avail_size;
+       int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
 };
 
 struct ingenic_adc {
@@ -151,6 +158,42 @@ static const int jz4740_adc_battery_scale_avail[] = {
        JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
 };
 
+static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
+{
+       struct clk *parent_clk;
+       unsigned long parent_rate, rate;
+       unsigned int div_main, div_10us;
+
+       parent_clk = clk_get_parent(adc->clk);
+       if (!parent_clk) {
+               dev_err(dev, "ADC clock has no parent\n");
+               return -ENODEV;
+       }
+       parent_rate = clk_get_rate(parent_clk);
+
+       /*
+        * The JZ4725B ADC works at 500 kHz to 8 MHz.
+        * We pick the highest rate possible.
+        * In practice we typically get 6 MHz, half of the 12 MHz EXT clock.
+        */
+       div_main = DIV_ROUND_UP(parent_rate, 8000000);
+       div_main = clamp(div_main, 1u, 64u);
+       rate = parent_rate / div_main;
+       if (rate < 500000 || rate > 8000000) {
+               dev_err(dev, "No valid divider for ADC main clock\n");
+               return -EINVAL;
+       }
+
+       /* We also need a divider that produces a 10us clock. */
+       div_10us = DIV_ROUND_UP(rate, 100000);
+
+       writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+              (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
+              adc->base + JZ_ADC_REG_ADCLK);
+
+       return 0;
+}
+
 static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
        .battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
        .battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
@@ -158,6 +201,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
        .battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
        .battery_scale_avail = jz4725b_adc_battery_scale_avail,
        .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+       .init_clk_div = jz4725b_adc_init_clk_div,
 };
 
 static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
@@ -167,6 +211,7 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
        .battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
        .battery_scale_avail = jz4740_adc_battery_scale_avail,
        .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+       .init_clk_div = NULL, /* no ADCLK register on JZ4740 */
 };
 
 static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
@@ -317,6 +362,15 @@ static int ingenic_adc_probe(struct platform_device *pdev)
                return ret;
        }
 
+       /* Set clock dividers. */
+       if (soc_data->init_clk_div) {
+               ret = soc_data->init_clk_div(dev, adc);
+               if (ret) {
+                       clk_disable_unprepare(adc->clk);
+                       return ret;
+               }
+       }
+
        /* Put hardware in a known passive state. */
        writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
        writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
index 917223d5ff5bb635125bca95c38150471d7e772b..da073d72f649f829997f6f3ca9a43c13399aba0d 100644 (file)
@@ -83,7 +83,7 @@
 #define MAX9611_TEMP_MAX_POS           0x7f80
 #define MAX9611_TEMP_MAX_NEG           0xff80
 #define MAX9611_TEMP_MIN_NEG           0xd980
-#define MAX9611_TEMP_MASK              GENMASK(7, 15)
+#define MAX9611_TEMP_MASK              GENMASK(15, 7)
 #define MAX9611_TEMP_SHIFT             0x07
 #define MAX9611_TEMP_RAW(_r)           ((_r) >> MAX9611_TEMP_SHIFT)
 #define MAX9611_TEMP_SCALE_NUM         1000000
@@ -480,7 +480,7 @@ static int max9611_init(struct max9611_dev *max9611)
        if (ret)
                return ret;
 
-       regval = ret & MAX9611_TEMP_MASK;
+       regval &= MAX9611_TEMP_MASK;
 
        if ((regval > MAX9611_TEMP_MAX_POS &&
             regval < MAX9611_TEMP_MIN_NEG) ||
index 2d685730f8673e650e1f32d16dc22fe481445438..c37f201294b2ae95f25b8c4636ee1b07c5b996ab 100644 (file)
@@ -382,7 +382,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
                                dev_err(dev,
                                        "Only %i channels supported with %pOFn, but reg = <%i>.\n",
                                        num_channels, child, reg);
-                               return ret;
+                               return -EINVAL;
                        }
                }
 
@@ -391,7 +391,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
                        dev_err(dev,
                                "Channel %i uses different ADC mode than the rest.\n",
                                reg);
-                       return ret;
+                       return -EINVAL;
                }
 
                /* Channel is valid, grab the regulator. */
index e48f15cc9ab5c36d0f140a3f5210e8087fa42acf..ff82863cbf42d4d1f7b59edbe8c1e3052135cf71 100644 (file)
@@ -276,11 +276,11 @@ static int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq,
        st->buf[0] = st->integer >> 8;
        st->buf[1] = 0x40; /* REG12 default */
        st->buf[2] = 0x00;
-       st->buf[3] = st->fract2 & 0xFF;
-       st->buf[4] = st->fract2 >> 7;
-       st->buf[5] = st->fract2 >> 15;
+       st->buf[3] = st->fract1 & 0xFF;
+       st->buf[4] = st->fract1 >> 8;
+       st->buf[5] = st->fract1 >> 16;
        st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) |
-                    ADF4371_FRAC1WORD(st->fract1 >> 23);
+                    ADF4371_FRAC1WORD(st->fract1 >> 24);
        st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7);
        st->buf[8] = st->mod2 & 0xFF;
        st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8);
index 53a59957cc5428d4ae6905b19f958acb8bfa4707..8a704cd5bddb7d7399bf8dc6d7d39652974267d7 100644 (file)
@@ -845,6 +845,25 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
        INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
 };
 
+static const unsigned long inv_mpu_scan_masks[] = {
+       /* 3-axis accel */
+       BIT(INV_MPU6050_SCAN_ACCL_X)
+               | BIT(INV_MPU6050_SCAN_ACCL_Y)
+               | BIT(INV_MPU6050_SCAN_ACCL_Z),
+       /* 3-axis gyro */
+       BIT(INV_MPU6050_SCAN_GYRO_X)
+               | BIT(INV_MPU6050_SCAN_GYRO_Y)
+               | BIT(INV_MPU6050_SCAN_GYRO_Z),
+       /* 6-axis accel + gyro */
+       BIT(INV_MPU6050_SCAN_ACCL_X)
+               | BIT(INV_MPU6050_SCAN_ACCL_Y)
+               | BIT(INV_MPU6050_SCAN_ACCL_Z)
+               | BIT(INV_MPU6050_SCAN_GYRO_X)
+               | BIT(INV_MPU6050_SCAN_GYRO_Y)
+               | BIT(INV_MPU6050_SCAN_GYRO_Z),
+       0,
+};
+
 static const struct iio_chan_spec inv_icm20602_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
        {
@@ -871,6 +890,28 @@ static const struct iio_chan_spec inv_icm20602_channels[] = {
        INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_ICM20602_SCAN_ACCL_Z),
 };
 
+static const unsigned long inv_icm20602_scan_masks[] = {
+       /* 3-axis accel + temp (mandatory) */
+       BIT(INV_ICM20602_SCAN_ACCL_X)
+               | BIT(INV_ICM20602_SCAN_ACCL_Y)
+               | BIT(INV_ICM20602_SCAN_ACCL_Z)
+               | BIT(INV_ICM20602_SCAN_TEMP),
+       /* 3-axis gyro + temp (mandatory) */
+       BIT(INV_ICM20602_SCAN_GYRO_X)
+               | BIT(INV_ICM20602_SCAN_GYRO_Y)
+               | BIT(INV_ICM20602_SCAN_GYRO_Z)
+               | BIT(INV_ICM20602_SCAN_TEMP),
+       /* 6-axis accel + gyro + temp (mandatory) */
+       BIT(INV_ICM20602_SCAN_ACCL_X)
+               | BIT(INV_ICM20602_SCAN_ACCL_Y)
+               | BIT(INV_ICM20602_SCAN_ACCL_Z)
+               | BIT(INV_ICM20602_SCAN_GYRO_X)
+               | BIT(INV_ICM20602_SCAN_GYRO_Y)
+               | BIT(INV_ICM20602_SCAN_GYRO_Z)
+               | BIT(INV_ICM20602_SCAN_TEMP),
+       0,
+};
+
 /*
  * The user can choose any frequency between INV_MPU6050_MIN_FIFO_RATE and
  * INV_MPU6050_MAX_FIFO_RATE, but only these frequencies are matched by the
@@ -1130,9 +1171,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
        if (chip_type == INV_ICM20602) {
                indio_dev->channels = inv_icm20602_channels;
                indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels);
+               indio_dev->available_scan_masks = inv_icm20602_scan_masks;
        } else {
                indio_dev->channels = inv_mpu_channels;
                indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+               indio_dev->available_scan_masks = inv_mpu_scan_masks;
        }
 
        indio_dev->info = &mpu_info;
index 45d5164e9574af247ae3bb53dd63d9791957ae18..b79890739a2c6b14f0d653c1e6e5a61ec3747680 100644 (file)
@@ -38,6 +38,9 @@ int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port,
        int ret;
 
        port_counter = &dev->port_data[port].port_counter;
+       if (!port_counter->hstats)
+               return -EOPNOTSUPP;
+
        mutex_lock(&port_counter->lock);
        if (on) {
                ret = __counter_set_mode(&port_counter->mode,
@@ -509,6 +512,9 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,
        if (!rdma_is_port_valid(dev, port))
                return -EINVAL;
 
+       if (!dev->port_data[port].port_counter.hstats)
+               return -EOPNOTSUPP;
+
        qp = rdma_counter_get_qp(dev, qp_num);
        if (!qp)
                return -ENOENT;
index 783e465e7c412988903088911fa655c4aa169346..87d40d1ecdde8064ae36b03dce5963c3e9a390bc 100644 (file)
@@ -1952,12 +1952,16 @@ static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        if (fill_nldev_handle(msg, device) ||
            nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, port) ||
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode))
+           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_MODE, mode)) {
+               ret = -EMSGSIZE;
                goto err_msg;
+       }
 
        if ((mode == RDMA_COUNTER_MODE_AUTO) &&
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask))
+           nla_put_u32(msg, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK, mask)) {
+               ret = -EMSGSIZE;
                goto err_msg;
+       }
 
        nlmsg_end(msg, nlh);
        ib_device_put(device);
index 2a75c6f8d8270e5ca07610684fbe9e5156f72708..c0e15db346808db3efc8222eddb14abc1212be05 100644 (file)
@@ -112,10 +112,6 @@ static int ib_umem_notifier_release_trampoline(struct ib_umem_odp *umem_odp,
         * prevent any further fault handling on this MR.
         */
        ib_umem_notifier_start_account(umem_odp);
-       umem_odp->dying = 1;
-       /* Make sure that the fact the umem is dying is out before we release
-        * all pending page faults. */
-       smp_wmb();
        complete_all(&umem_odp->notifier_completion);
        umem_odp->umem.context->invalidate_range(
                umem_odp, ib_umem_start(umem_odp), ib_umem_end(umem_odp));
index ec4370f9938127f94d70533f2ebf8cc9f44b48a2..af5bbb35c0589364794ca131a1e741392cfe5931 100644 (file)
@@ -2026,7 +2026,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(
                        event_sub->eventfd =
                                eventfd_ctx_fdget(redirect_fd);
 
-                       if (IS_ERR(event_sub)) {
+                       if (IS_ERR(event_sub->eventfd)) {
                                err = PTR_ERR(event_sub->eventfd);
                                event_sub->eventfd = NULL;
                                goto err;
@@ -2644,12 +2644,13 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
        struct devx_async_event_file *ev_file = filp->private_data;
        struct devx_event_subscription *event_sub, *event_sub_tmp;
        struct devx_async_event_data *entry, *tmp;
+       struct mlx5_ib_dev *dev = ev_file->dev;
 
-       mutex_lock(&ev_file->dev->devx_event_table.event_xa_lock);
+       mutex_lock(&dev->devx_event_table.event_xa_lock);
        /* delete the subscriptions which are related to this FD */
        list_for_each_entry_safe(event_sub, event_sub_tmp,
                                 &ev_file->subscribed_events_list, file_list) {
-               devx_cleanup_subscription(ev_file->dev, event_sub);
+               devx_cleanup_subscription(dev, event_sub);
                if (event_sub->eventfd)
                        eventfd_ctx_put(event_sub->eventfd);
 
@@ -2658,7 +2659,7 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
                kfree_rcu(event_sub, rcu);
        }
 
-       mutex_unlock(&ev_file->dev->devx_event_table.event_xa_lock);
+       mutex_unlock(&dev->devx_event_table.event_xa_lock);
 
        /* free the pending events allocation */
        if (!ev_file->omit_data) {
@@ -2670,7 +2671,7 @@ static int devx_async_event_close(struct inode *inode, struct file *filp)
        }
 
        uverbs_close_fd(filp);
-       put_device(&ev_file->dev->ib_dev.dev);
+       put_device(&dev->ib_dev.dev);
        return 0;
 }
 
index 81da82050d05ec2579bcd4145c2902a55b488cd7..1d257d1b3b0da0b1a1035a469100ab6d613b54f6 100644 (file)
@@ -579,7 +579,6 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
                        u32 flags)
 {
        int npages = 0, current_seq, page_shift, ret, np;
-       bool implicit = false;
        struct ib_umem_odp *odp_mr = to_ib_umem_odp(mr->umem);
        bool downgrade = flags & MLX5_PF_FLAGS_DOWNGRADE;
        bool prefetch = flags & MLX5_PF_FLAGS_PREFETCH;
@@ -594,7 +593,6 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
                if (IS_ERR(odp))
                        return PTR_ERR(odp);
                mr = odp->private;
-               implicit = true;
        } else {
                odp = odp_mr;
        }
@@ -682,19 +680,15 @@ next_mr:
 
 out:
        if (ret == -EAGAIN) {
-               if (implicit || !odp->dying) {
-                       unsigned long timeout =
-                               msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
-
-                       if (!wait_for_completion_timeout(
-                                       &odp->notifier_completion,
-                                       timeout)) {
-                               mlx5_ib_warn(dev, "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
-                                            current_seq, odp->notifiers_seq, odp->notifiers_count);
-                       }
-               } else {
-                       /* The MR is being killed, kill the QP as well. */
-                       ret = -EFAULT;
+               unsigned long timeout = msecs_to_jiffies(MMU_NOTIFIER_TIMEOUT);
+
+               if (!wait_for_completion_timeout(&odp->notifier_completion,
+                                                timeout)) {
+                       mlx5_ib_warn(
+                               dev,
+                               "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
+                               current_seq, odp->notifiers_seq,
+                               odp->notifiers_count);
                }
        }
 
index dace276aea1413baa46f292a7e522381c6f00250..b622fc62f2cd6d4699cb9a1ed6ead9e44cd6bee2 100644 (file)
@@ -1,6 +1,6 @@
 config RDMA_SIW
        tristate "Software RDMA over TCP/IP (iWARP) driver"
-       depends on INET && INFINIBAND && LIBCRC32C && 64BIT
+       depends on INET && INFINIBAND && LIBCRC32C
        select DMA_VIRT_OPS
        help
        This driver implements the iWARP RDMA transport over
index 03fd7b2f595f1f35c5a535e068a60913d5b879ed..77b1aabf6ff357245ea7b3c3b04ee570320eb9b1 100644 (file)
@@ -214,7 +214,7 @@ struct siw_wqe {
 struct siw_cq {
        struct ib_cq base_cq;
        spinlock_t lock;
-       u64 *notify;
+       struct siw_cq_ctrl *notify;
        struct siw_cqe *queue;
        u32 cq_put;
        u32 cq_get;
index d0f140daf65924287833ad03716c4a26e8fb8058..05a92f997f603bfbc64138ae2bdda31486baa36c 100644 (file)
@@ -160,10 +160,8 @@ static int siw_init_cpulist(void)
 
 out_err:
        siw_cpu_info.num_nodes = 0;
-       while (i) {
+       while (--i >= 0)
                kfree(siw_cpu_info.tx_valid_cpus[i]);
-               siw_cpu_info.tx_valid_cpus[i--] = NULL;
-       }
        kfree(siw_cpu_info.tx_valid_cpus);
        siw_cpu_info.tx_valid_cpus = NULL;
 
index e27bd5b35b966280e5ecfc2c2cc2affbc75ec597..0990307c5d2cde951d646b2d06e990670f44a709 100644 (file)
@@ -1013,18 +1013,24 @@ out:
  */
 static bool siw_cq_notify_now(struct siw_cq *cq, u32 flags)
 {
-       u64 cq_notify;
+       u32 cq_notify;
 
        if (!cq->base_cq.comp_handler)
                return false;
 
-       cq_notify = READ_ONCE(*cq->notify);
+       /* Read application shared notification state */
+       cq_notify = READ_ONCE(cq->notify->flags);
 
        if ((cq_notify & SIW_NOTIFY_NEXT_COMPLETION) ||
            ((cq_notify & SIW_NOTIFY_SOLICITED) &&
             (flags & SIW_WQE_SOLICITED))) {
-               /* dis-arm CQ */
-               smp_store_mb(*cq->notify, SIW_NOTIFY_NOT);
+               /*
+                * CQ notification is one-shot: Since the
+                * current CQE causes user notification,
+                * the CQ gets dis-aremd and must be re-aremd
+                * by the user for a new notification.
+                */
+               WRITE_ONCE(cq->notify->flags, SIW_NOTIFY_NOT);
 
                return true;
        }
index 32dc79d0e8981770ddf2069f69b286adc5116b3d..e7f3a2379d9d87858ddb83bd7abce843ed330a7a 100644 (file)
@@ -1049,7 +1049,7 @@ int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr,
 
        spin_lock_init(&cq->lock);
 
-       cq->notify = &((struct siw_cq_ctrl *)&cq->queue[size])->notify;
+       cq->notify = (struct siw_cq_ctrl *)&cq->queue[size];
 
        if (udata) {
                struct siw_uresp_create_cq uresp = {};
@@ -1141,11 +1141,17 @@ int siw_req_notify_cq(struct ib_cq *base_cq, enum ib_cq_notify_flags flags)
        siw_dbg_cq(cq, "flags: 0x%02x\n", flags);
 
        if ((flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
-               /* CQ event for next solicited completion */
-               smp_store_mb(*cq->notify, SIW_NOTIFY_SOLICITED);
+               /*
+                * Enable CQ event for next solicited completion.
+                * and make it visible to all associated producers.
+                */
+               smp_store_mb(cq->notify->flags, SIW_NOTIFY_SOLICITED);
        else
-               /* CQ event for any signalled completion */
-               smp_store_mb(*cq->notify, SIW_NOTIFY_ALL);
+               /*
+                * Enable CQ event for any signalled completion.
+                * and make it visible to all associated producers.
+                */
+               smp_store_mb(cq->notify->flags, SIW_NOTIFY_ALL);
 
        if (flags & IB_CQ_REPORT_MISSED_EVENTS)
                return cq->cq_put - cq->cq_get;
index 29abfeeef9a5f58e9e3840f42ee7a10ab78df210..6c554c11a7ac3f35a33b318f7f6bef589a8c6b81 100644 (file)
@@ -201,7 +201,12 @@ static int iforce_usb_probe(struct usb_interface *intf,
                return -ENODEV;
 
        epirq = &interface->endpoint[0].desc;
+       if (!usb_endpoint_is_int_in(epirq))
+               return -ENODEV;
+
        epout = &interface->endpoint[1].desc;
+       if (!usb_endpoint_is_int_out(epout))
+               return -ENODEV;
 
        iforce_usb = kzalloc(sizeof(*iforce_usb), GFP_KERNEL);
        if (!iforce_usb)
index 8e9c3ea9d5e799c2873d165db109a850cff7e868..90e8a7f2f07c863196762633930bc46a5c659319 100644 (file)
@@ -76,6 +76,8 @@ config KEYBOARD_APPLESPI
        depends on ACPI && EFI
        depends on SPI
        depends on X86 || COMPILE_TEST
+       depends on LEDS_CLASS
+       select CRC16
        help
          Say Y here if you are running Linux on any Apple MacBook8,1 or later,
          or any MacBookPro13,* or MacBookPro14,*.
index 548737e7aedaec459bddd261609d774dc6b1d52c..584289b67fb3cbccc20f9a26200c624fea468ef9 100644 (file)
@@ -134,10 +134,10 @@ struct keyboard_protocol {
  * struct tp_finger - single trackpad finger structure, le16-aligned
  *
  * @origin:            zero when switching track finger
- * @abs_x:             absolute x coodinate
- * @abs_y:             absolute y coodinate
- * @rel_x:             relative x coodinate
- * @rel_y:             relative y coodinate
+ * @abs_x:             absolute x coordinate
+ * @abs_y:             absolute y coordinate
+ * @rel_x:             relative x coordinate
+ * @rel_y:             relative y coordinate
  * @tool_major:                tool area, major axis
  * @tool_minor:                tool area, minor axis
  * @orientation:       16384 when point, else 15 bit angle
@@ -944,10 +944,14 @@ static inline int le16_to_int(__le16 x)
 static void applespi_debug_update_dimensions(struct applespi_data *applespi,
                                             const struct tp_finger *f)
 {
-       applespi->tp_dim_min_x = min_t(int, applespi->tp_dim_min_x, f->abs_x);
-       applespi->tp_dim_max_x = max_t(int, applespi->tp_dim_max_x, f->abs_x);
-       applespi->tp_dim_min_y = min_t(int, applespi->tp_dim_min_y, f->abs_y);
-       applespi->tp_dim_max_y = max_t(int, applespi->tp_dim_max_y, f->abs_y);
+       applespi->tp_dim_min_x = min(applespi->tp_dim_min_x,
+                                    le16_to_int(f->abs_x));
+       applespi->tp_dim_max_x = max(applespi->tp_dim_max_x,
+                                    le16_to_int(f->abs_x));
+       applespi->tp_dim_min_y = min(applespi->tp_dim_min_y,
+                                    le16_to_int(f->abs_y));
+       applespi->tp_dim_max_y = max(applespi->tp_dim_max_y,
+                                    le16_to_int(f->abs_y));
 }
 
 static int applespi_tp_dim_open(struct inode *inode, struct file *file)
@@ -1490,8 +1494,7 @@ static void applespi_got_data(struct applespi_data *applespi)
                size_t tp_len;
 
                tp = &message->touchpad;
-               tp_len = sizeof(*tp) +
-                        tp->number_of_fingers * sizeof(tp->fingers[0]);
+               tp_len = struct_size(tp, fingers, tp->number_of_fingers);
 
                if (le16_to_cpu(message->length) + 2 != tp_len) {
                        dev_warn_ratelimited(&applespi->spi->dev,
@@ -1611,8 +1614,8 @@ static void applespi_save_bl_level(struct applespi_data *applespi,
        efi_attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
                   EFI_VARIABLE_RUNTIME_ACCESS;
 
-       sts = efivar_entry_set_safe(EFI_BL_LEVEL_NAME, efi_guid, efi_attr, true,
-                                   efi_data_len, &efi_data);
+       sts = efivar_entry_set_safe((efi_char16_t *)EFI_BL_LEVEL_NAME, efi_guid,
+                                   efi_attr, true, efi_data_len, &efi_data);
        if (sts)
                dev_warn(&applespi->spi->dev,
                         "Error saving backlight level to EFI vars: %d\n", sts);
@@ -1953,7 +1956,7 @@ static const struct acpi_device_id applespi_acpi_match[] = {
 };
 MODULE_DEVICE_TABLE(acpi, applespi_acpi_match);
 
-const struct dev_pm_ops applespi_pm_ops = {
+static const struct dev_pm_ops applespi_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(applespi_suspend, applespi_resume)
        .poweroff_late  = applespi_poweroff_late,
 };
index 2d8434b7b62381a85abdb28daba2391fdd117e40..04fe43440a3c8740d58ee1cb944fc3b7099aa981 100644 (file)
@@ -1827,6 +1827,31 @@ static int elantech_create_smbus(struct psmouse *psmouse,
                                  leave_breadcrumbs);
 }
 
+static bool elantech_use_host_notify(struct psmouse *psmouse,
+                                    struct elantech_device_info *info)
+{
+       if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+               return true;
+
+       switch (info->bus) {
+       case ETP_BUS_PS2_ONLY:
+               /* expected case */
+               break;
+       case ETP_BUS_SMB_HST_NTFY_ONLY:
+       case ETP_BUS_PS2_SMB_HST_NTFY:
+               /* SMbus implementation is stable since 2018 */
+               if (dmi_get_bios_year() >= 2018)
+                       return true;
+               /* fall through */
+       default:
+               psmouse_dbg(psmouse,
+                           "Ignoring SMBus bus provider %d\n", info->bus);
+               break;
+       }
+
+       return false;
+}
+
 /**
  * elantech_setup_smbus - called once the PS/2 devices are enumerated
  * and decides to instantiate a SMBus InterTouch device.
@@ -1846,7 +1871,7 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
                 * i2c_blacklist_pnp_ids.
                 * Old ICs are up to the user to decide.
                 */
-               if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) ||
+               if (!elantech_use_host_notify(psmouse, info) ||
                    psmouse_matches_pnp_id(psmouse, i2c_blacklist_pnp_ids))
                        return -ENXIO;
        }
@@ -1866,34 +1891,6 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
        return 0;
 }
 
-static bool elantech_use_host_notify(struct psmouse *psmouse,
-                                    struct elantech_device_info *info)
-{
-       if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
-               return true;
-
-       switch (info->bus) {
-       case ETP_BUS_PS2_ONLY:
-               /* expected case */
-               break;
-       case ETP_BUS_SMB_ALERT_ONLY:
-               /* fall-through  */
-       case ETP_BUS_PS2_SMB_ALERT:
-               psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n");
-               break;
-       case ETP_BUS_SMB_HST_NTFY_ONLY:
-               /* fall-through  */
-       case ETP_BUS_PS2_SMB_HST_NTFY:
-               return true;
-       default:
-               psmouse_dbg(psmouse,
-                           "Ignoring SMBus bus provider %d.\n",
-                           info->bus);
-       }
-
-       return false;
-}
-
 int elantech_init_smbus(struct psmouse *psmouse)
 {
        struct elantech_device_info info;
index b1956ed4c0ddeaf35b1f3cf65c0773e851a7c07d..46bbe99d651135b093ba6b3de6473243103e5493 100644 (file)
@@ -182,6 +182,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN2055", /* E580 */
        "SYN3052", /* HP EliteBook 840 G4 */
        "SYN3221", /* HP 15-ay000 */
+       "SYN323d", /* HP Spectre X360 13-w013dx */
        NULL
 };
 
index 04b85571f41e3c03b0767ee335c96853c236b4e4..aa577898e952b48c495f3214abd690a80106df99 100644 (file)
@@ -117,6 +117,10 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        if (intf->cur_altsetting->desc.bNumEndpoints < 1)
                return -ENODEV;
 
+       endpoint = &intf->cur_altsetting->endpoint[0].desc;
+       if (!usb_endpoint_is_int_in(endpoint))
+               return -ENODEV;
+
        kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!kbtab || !input_dev)
@@ -155,8 +159,6 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0);
        input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0);
 
-       endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
        usb_fill_int_urb(kbtab->irq, dev,
                         usb_rcvintpipe(dev, endpoint->bEndpointAddress),
                         kbtab->data, 8,
index a2cec6cacf576e4a387d8f4aa2bc5ca953a66a22..16d70201de4a3334fc4dd49dc3d205ce4d96bc52 100644 (file)
@@ -1659,6 +1659,8 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (!usbtouch || !input_dev)
                goto out_free;
 
+       mutex_init(&usbtouch->pm_mutex);
+
        type = &usbtouch_dev_info[id->driver_info];
        usbtouch->type = type;
        if (!type->process_pkt)
index a9a9fabd396804a26b77039d0fe804cea3dc56dc..c5c93e48b4dbdf7409ca3b8008a24a4ab3214a49 100644 (file)
@@ -1186,8 +1186,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
                        ste_live = true;
                        break;
                case STRTAB_STE_0_CFG_ABORT:
-                       if (disable_bypass)
-                               break;
+                       BUG_ON(!disable_bypass);
+                       break;
                default:
                        BUG(); /* STE corruption */
                }
index a7f9c3edbcb299f83f8d4c6093c274a0bc5b3387..d991d40f797fb62e9f6659060c1e92d4abb3bddc 100644 (file)
@@ -459,13 +459,11 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
 {
        struct iommu_domain *domain = iommu_get_dma_domain(dev);
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
-       size_t iova_off = 0;
+       struct iova_domain *iovad = &cookie->iovad;
+       size_t iova_off = iova_offset(iovad, phys);
        dma_addr_t iova;
 
-       if (cookie->type == IOMMU_DMA_IOVA_COOKIE) {
-               iova_off = iova_offset(&cookie->iovad, phys);
-               size = iova_align(&cookie->iovad, size + iova_off);
-       }
+       size = iova_align(iovad, size + iova_off);
 
        iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
        if (!iova)
@@ -574,7 +572,7 @@ static void *iommu_dma_alloc_remap(struct device *dev, size_t size,
        struct iova_domain *iovad = &cookie->iovad;
        bool coherent = dev_is_dma_coherent(dev);
        int ioprot = dma_info_to_prot(DMA_BIDIRECTIONAL, coherent, attrs);
-       pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
+       pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
        unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
        struct page **pages;
        struct sg_table sgt;
@@ -764,7 +762,7 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
                 * - and wouldn't make the resulting output segment too long
                 */
                if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
-                   (cur_len + s_length <= max_len)) {
+                   (max_len - cur_len >= s_length)) {
                        /* ...then concatenate it with the previous one */
                        cur_len += s_length;
                } else {
@@ -975,7 +973,7 @@ static void *iommu_dma_alloc_pages(struct device *dev, size_t size,
                return NULL;
 
        if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
-               pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
+               pgprot_t prot = dma_pgprot(dev, PAGE_KERNEL, attrs);
 
                cpu_addr = dma_common_contiguous_remap(page, alloc_size,
                                VM_USERMAP, prot, __builtin_return_address(0));
@@ -1035,7 +1033,7 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
        unsigned long pfn, off = vma->vm_pgoff;
        int ret;
 
-       vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
+       vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
 
        if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
                return ret;
@@ -1147,16 +1145,21 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
        if (!msi_page)
                return NULL;
 
-       iova = __iommu_dma_map(dev, msi_addr, size, prot);
-       if (iova == DMA_MAPPING_ERROR)
+       iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
+       if (!iova)
                goto out_free_page;
 
+       if (iommu_map(domain, iova, msi_addr, size, prot))
+               goto out_free_iova;
+
        INIT_LIST_HEAD(&msi_page->list);
        msi_page->phys = msi_addr;
        msi_page->iova = iova;
        list_add(&msi_page->list, &cookie->msi_page_list);
        return msi_page;
 
+out_free_iova:
+       iommu_dma_free_iova(cookie, iova, size);
 out_free_page:
        kfree(msi_page);
        return NULL;
index 2b25d9c5933604eb70d6a83a7e1a91daa10e29d7..471f05d452e0198f3d2837f2a83e13d0984e1a12 100644 (file)
@@ -235,7 +235,7 @@ static void ctx_tbl_walk(struct seq_file *m, struct intel_iommu *iommu, u16 bus)
                tbl_wlk.ctx_entry = context;
                m->private = &tbl_wlk;
 
-               if (pasid_supported(iommu) && is_pasid_enabled(context)) {
+               if (dmar_readq(iommu->reg + DMAR_RTADDR_REG) & DMA_RTADDR_SMT) {
                        pasid_dir_ptr = context->lo & VTD_PAGE_MASK;
                        pasid_dir_size = get_pasid_dir_size(context);
                        pasid_dir_walk(m, pasid_dir_ptr, pasid_dir_size);
index bdaed2da8a55e5a96904d0a182b9d44db8843777..12d094d08c0a2e982fb712b9310ceadf7213013d 100644 (file)
@@ -3449,6 +3449,7 @@ static bool iommu_need_mapping(struct device *dev)
                                dmar_domain = to_dmar_domain(domain);
                                dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
                        }
+                       dmar_remove_one_dev_info(dev);
                        get_private_domain_for_dev(dev);
                }
 
@@ -4790,7 +4791,8 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
 
        /* free the private domain */
        if (domain->flags & DOMAIN_FLAG_LOSE_CHILDREN &&
-           !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY))
+           !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+           list_empty(&domain->devices))
                domain_exit(info->domain);
 
        free_devinfo_mem(info);
@@ -4803,7 +4805,8 @@ static void dmar_remove_one_dev_info(struct device *dev)
 
        spin_lock_irqsave(&device_domain_lock, flags);
        info = dev->archdata.iommu;
-       __dmar_remove_one_dev_info(info);
+       if (info)
+               __dmar_remove_one_dev_info(info);
        spin_unlock_irqrestore(&device_domain_lock, flags);
 }
 
@@ -5281,6 +5284,7 @@ static int intel_iommu_add_device(struct device *dev)
                if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) {
                        ret = iommu_request_dm_for_dev(dev);
                        if (ret) {
+                               dmar_remove_one_dev_info(dev);
                                dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
                                domain_add_dev_info(si_domain, dev);
                                dev_info(dev,
@@ -5291,6 +5295,7 @@ static int intel_iommu_add_device(struct device *dev)
                if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) {
                        ret = iommu_request_dma_domain_for_dev(dev);
                        if (ret) {
+                               dmar_remove_one_dev_info(dev);
                                dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
                                if (!get_private_domain_for_dev(dev)) {
                                        dev_warn(dev,
@@ -5316,6 +5321,8 @@ static void intel_iommu_remove_device(struct device *dev)
        if (!iommu)
                return;
 
+       dmar_remove_one_dev_info(dev);
+
        iommu_group_remove_device(dev);
 
        iommu_device_unlink(&iommu->iommu, dev);
index 0e224232f74644e1a1b620ca9c3d1067891e34d9..008a74a1ed444720a29537f037dedfac821d46d1 100644 (file)
@@ -1394,6 +1394,7 @@ start_isoc_chain(struct usb_fifo *fifo, int num_packets_per_urb,
                                printk(KERN_DEBUG
                                       "%s: %s: alloc urb for fifo %i failed",
                                       hw->name, __func__, fifo->fifonum);
+                               continue;
                        }
                        fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
                        fifo->iso[i].indx = i;
@@ -1692,13 +1693,23 @@ hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel)
 static int
 setup_hfcsusb(struct hfcsusb *hw)
 {
+       void *dmabuf = kmalloc(sizeof(u_char), GFP_KERNEL);
        u_char b;
+       int ret;
 
        if (debug & DBG_HFC_CALL_TRACE)
                printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
 
+       if (!dmabuf)
+               return -ENOMEM;
+
+       ret = read_reg_atomic(hw, HFCUSB_CHIP_ID, dmabuf);
+
+       memcpy(&b, dmabuf, sizeof(u_char));
+       kfree(dmabuf);
+
        /* check the chip id */
-       if (read_reg_atomic(hw, HFCUSB_CHIP_ID, &b) != 1) {
+       if (ret != 1) {
                printk(KERN_DEBUG "%s: %s: cannot read chip id\n",
                       hw->name, __func__);
                return 1;
index 9f0826712845050ab6ee3d54abe69980eb8d9216..e2059af9079181e9193795757b2ed5b448741f48 100644 (file)
@@ -23,24 +23,28 @@ static const char * const bch_cache_modes[] = {
        "writethrough",
        "writeback",
        "writearound",
-       "none"
+       "none",
+       NULL
 };
 
 /* Default is 0 ("auto") */
 static const char * const bch_stop_on_failure_modes[] = {
        "auto",
-       "always"
+       "always",
+       NULL
 };
 
 static const char * const cache_replacement_policies[] = {
        "lru",
        "fifo",
-       "random"
+       "random",
+       NULL
 };
 
 static const char * const error_actions[] = {
        "unregister",
-       "panic"
+       "panic",
+       NULL
 };
 
 write_attribute(attach);
@@ -338,7 +342,7 @@ STORE(__cached_dev)
        }
 
        if (attr == &sysfs_cache_mode) {
-               v = sysfs_match_string(bch_cache_modes, buf);
+               v = __sysfs_match_string(bch_cache_modes, -1, buf);
                if (v < 0)
                        return v;
 
@@ -349,7 +353,7 @@ STORE(__cached_dev)
        }
 
        if (attr == &sysfs_stop_when_cache_set_failed) {
-               v = sysfs_match_string(bch_stop_on_failure_modes, buf);
+               v = __sysfs_match_string(bch_stop_on_failure_modes, -1, buf);
                if (v < 0)
                        return v;
 
@@ -816,7 +820,7 @@ STORE(__bch_cache_set)
                            0, UINT_MAX);
 
        if (attr == &sysfs_errors) {
-               v = sysfs_match_string(error_actions, buf);
+               v = __sysfs_match_string(error_actions, -1, buf);
                if (v < 0)
                        return v;
 
@@ -1088,7 +1092,7 @@ STORE(__bch_cache)
        }
 
        if (attr == &sysfs_cache_replacement_policy) {
-               v = sysfs_match_string(cache_replacement_policies, buf);
+               v = __sysfs_match_string(cache_replacement_policies, -1, buf);
                if (v < 0)
                        return v;
 
index 29e3f5da59c1ff61137f66d93b75b865521ed5e1..11ec048929e80109e6702249aea0b345e79378d3 100644 (file)
@@ -253,8 +253,7 @@ int omap_vout_prepare_vrfb(struct omap_vout_device *vout,
         */
 
        pixsize = vout->bpp * vout->vrfb_bpp;
-       dst_icg = ((MAX_PIXELS_PER_LINE * pixsize) -
-                 (vout->pix.width * vout->bpp)) + 1;
+       dst_icg = MAX_PIXELS_PER_LINE * pixsize - vout->pix.width * vout->bpp;
 
        xt->src_start = vout->buf_phy_addr[vb->i];
        xt->dst_start = vout->vrfb_context[vb->i].paddr[0];
index bc2a176937a447d3ebd3b3e67bbaec038c7a993f..d535aac68ce168c37fb8542cbfa2599a056b3686 100644 (file)
@@ -1099,6 +1099,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 
        /* start creating the vb2 queues */
        if (dev->has_vid_cap) {
+               snprintf(dev->vid_cap_dev.name, sizeof(dev->vid_cap_dev.name),
+                        "vivid-%03d-vid-cap", inst);
                /* initialize vid_cap queue */
                q = &dev->vb_vid_cap_q;
                q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
@@ -1122,6 +1124,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        }
 
        if (dev->has_vid_out) {
+               snprintf(dev->vid_out_dev.name, sizeof(dev->vid_out_dev.name),
+                        "vivid-%03d-vid-out", inst);
                /* initialize vid_out queue */
                q = &dev->vb_vid_out_q;
                q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
@@ -1265,8 +1269,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
        /* finally start creating the device nodes */
        if (dev->has_vid_cap) {
                vfd = &dev->vid_cap_dev;
-               snprintf(vfd->name, sizeof(vfd->name),
-                        "vivid-%03d-vid-cap", inst);
                vfd->fops = &vivid_fops;
                vfd->ioctl_ops = &vivid_ioctl_ops;
                vfd->device_caps = dev->vid_cap_caps;
@@ -1312,8 +1314,6 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 
        if (dev->has_vid_out) {
                vfd = &dev->vid_out_dev;
-               snprintf(vfd->name, sizeof(vfd->name),
-                        "vivid-%03d-vid-out", inst);
                vfd->vfl_dir = VFL_DIR_TX;
                vfd->fops = &vivid_fops;
                vfd->ioctl_ops = &vivid_ioctl_ops;
index 3f21e26b8d36e7c906603dc65f4b64aa1301dfe2..90e0f21bc49c55045bb03ff7582200b403b320a7 100644 (file)
@@ -1590,8 +1590,10 @@ static unsigned long dsiclk_rate(u8 n)
        switch (divsel) {
        case PRCM_DSI_PLLOUT_SEL_PHI_4:
                div *= 2;
+               /* Fall through */
        case PRCM_DSI_PLLOUT_SEL_PHI_2:
                div *= 2;
+               /* Fall through */
        case PRCM_DSI_PLLOUT_SEL_PHI:
                return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK),
                        PLL_RAW) / div;
index 792b855a9104311f62b980e81a9aa3ab5500e0a5..4798d9f3f9d50bbbb50a6c4443421378704565f2 100644 (file)
@@ -308,7 +308,7 @@ static int usbhs_runtime_resume(struct device *dev)
                                         i, r);
                                }
                        }
-               /* Fall through as HSIC mode needs utmi_clk */
+               /* Fall through as HSIC mode needs utmi_clk */
 
                case OMAP_EHCI_PORT_MODE_TLL:
                        if (!IS_ERR(omap->utmi_clk[i])) {
@@ -344,7 +344,7 @@ static int usbhs_runtime_suspend(struct device *dev)
 
                        if (!IS_ERR(omap->hsic480m_clk[i]))
                                clk_disable_unprepare(omap->hsic480m_clk[i]);
-               /* Fall through as utmi_clks were used in HSIC mode */
+               /* Fall through as utmi_clks were used in HSIC mode */
 
                case OMAP_EHCI_PORT_MODE_TLL:
                        if (!IS_ERR(omap->utmi_clk[i]))
index 6abfc8e92fcc14b2584cc7baa7e2d4be77cb5243..16900357afc25a7d65a9a717c14de156b6fe7c28 100644 (file)
@@ -465,6 +465,7 @@ config PCI_ENDPOINT_TEST
 
 config XILINX_SDFEC
        tristate "Xilinx SDFEC 16"
+       depends on HAS_IOMEM
        help
          This option enables support for the Xilinx SDFEC (Soft Decision
          Forward Error Correction) driver. This enables a char driver
index 6ad83d5ef4b006759351962d54795b724e0dc590..f00d1c32f6d6f83a3e523abc0d8301057d6cadc5 100644 (file)
@@ -683,7 +683,7 @@ int hl_cs_ioctl(struct hl_fpriv *hpriv, void *data)
 
                rc = hl_poll_timeout_memory(hdev,
                        &ctx->thread_ctx_switch_wait_token, tmp, (tmp == 1),
-                       100, jiffies_to_usecs(hdev->timeout_jiffies));
+                       100, jiffies_to_usecs(hdev->timeout_jiffies), false);
 
                if (rc == -ETIMEDOUT) {
                        dev_err(hdev->dev,
index 0c4894dd9c02a9e8c5e8ac648d3052715a6c17aa..7a8f9d0b71b54a81b4cce20fcbad3734c0369db9 100644 (file)
@@ -970,7 +970,8 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
        rc = hl_ctx_init(hdev, hdev->kernel_ctx, true);
        if (rc) {
                dev_err(hdev->dev, "failed to initialize kernel context\n");
-               goto free_ctx;
+               kfree(hdev->kernel_ctx);
+               goto mmu_fini;
        }
 
        rc = hl_cb_pool_init(hdev);
@@ -1053,8 +1054,6 @@ release_ctx:
        if (hl_ctx_put(hdev->kernel_ctx) != 1)
                dev_err(hdev->dev,
                        "kernel ctx is still alive on initialization failure\n");
-free_ctx:
-       kfree(hdev->kernel_ctx);
 mmu_fini:
        hl_mmu_fini(hdev);
 eq_fini:
index cc8168bacb24b3b90d2c8b7cf196246e8f1df7fe..ea2ca67fbfbfaf9fc01f8160b539a57149bd8e0f 100644 (file)
@@ -24,7 +24,7 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
 {
        const struct firmware *fw;
        const u64 *fw_data;
-       size_t fw_size, i;
+       size_t fw_size;
        int rc;
 
        rc = request_firmware(&fw, fw_name, hdev->dev);
@@ -45,22 +45,7 @@ int hl_fw_push_fw_to_device(struct hl_device *hdev, const char *fw_name,
 
        fw_data = (const u64 *) fw->data;
 
-       if ((fw->size % 8) != 0)
-               fw_size -= 8;
-
-       for (i = 0 ; i < fw_size ; i += 8, fw_data++, dst += 8) {
-               if (!(i & (0x80000 - 1))) {
-                       dev_dbg(hdev->dev,
-                               "copied so far %zu out of %zu for %s firmware",
-                               i, fw_size, fw_name);
-                       usleep_range(20, 100);
-               }
-
-               writeq(*fw_data, dst);
-       }
-
-       if ((fw->size % 8) != 0)
-               writel(*(const u32 *) fw_data, dst);
+       memcpy_toio(dst, fw_data, fw_size);
 
 out:
        release_firmware(fw);
@@ -112,7 +97,8 @@ int hl_fw_send_cpu_message(struct hl_device *hdev, u32 hw_queue_id, u32 *msg,
        }
 
        rc = hl_poll_timeout_memory(hdev, &pkt->fence, tmp,
-                               (tmp == ARMCP_PACKET_FENCE_VAL), 1000, timeout);
+                               (tmp == ARMCP_PACKET_FENCE_VAL), 1000,
+                               timeout, true);
 
        hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
 
index 1a2c062a57d4de9d09e41a36914921251e47b072..271c5c8f53b4e72887b21c887c0920879512d79b 100644 (file)
@@ -2729,9 +2729,10 @@ void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi)
                                GOYA_ASYNC_EVENT_ID_PI_UPDATE);
 }
 
-void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val)
+void goya_pqe_write(struct hl_device *hdev, __le64 *pqe, struct hl_bd *bd)
 {
-       /* Not needed in Goya */
+       /* The QMANs are on the SRAM so need to copy to IO space */
+       memcpy_toio((void __iomem *) pqe, bd, sizeof(struct hl_bd));
 }
 
 static void *goya_dma_alloc_coherent(struct hl_device *hdev, size_t size,
@@ -2864,7 +2865,8 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job)
        }
 
        rc = hl_poll_timeout_memory(hdev, fence_ptr, tmp,
-                               (tmp == GOYA_QMAN0_FENCE_VAL), 1000, timeout);
+                               (tmp == GOYA_QMAN0_FENCE_VAL), 1000,
+                               timeout, true);
 
        hl_hw_queue_inc_ci_kernel(hdev, GOYA_QUEUE_ID_DMA_0);
 
@@ -2945,7 +2947,7 @@ int goya_test_queue(struct hl_device *hdev, u32 hw_queue_id)
        }
 
        rc = hl_poll_timeout_memory(hdev, fence_ptr, tmp, (tmp == fence_val),
-                                       1000, GOYA_TEST_QUEUE_WAIT_USEC);
+                                       1000, GOYA_TEST_QUEUE_WAIT_USEC, true);
 
        hl_hw_queue_inc_ci_kernel(hdev, hw_queue_id);
 
@@ -3312,9 +3314,11 @@ static int goya_validate_dma_pkt_no_mmu(struct hl_device *hdev,
        int rc;
 
        dev_dbg(hdev->dev, "DMA packet details:\n");
-       dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
-       dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
-       dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+       dev_dbg(hdev->dev, "source == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->src_addr));
+       dev_dbg(hdev->dev, "destination == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->dst_addr));
+       dev_dbg(hdev->dev, "size == %u\n", le32_to_cpu(user_dma_pkt->tsize));
 
        ctl = le32_to_cpu(user_dma_pkt->ctl);
        user_dir = (ctl & GOYA_PKT_LIN_DMA_CTL_DMA_DIR_MASK) >>
@@ -3343,9 +3347,11 @@ static int goya_validate_dma_pkt_mmu(struct hl_device *hdev,
                                struct packet_lin_dma *user_dma_pkt)
 {
        dev_dbg(hdev->dev, "DMA packet details:\n");
-       dev_dbg(hdev->dev, "source == 0x%llx\n", user_dma_pkt->src_addr);
-       dev_dbg(hdev->dev, "destination == 0x%llx\n", user_dma_pkt->dst_addr);
-       dev_dbg(hdev->dev, "size == %u\n", user_dma_pkt->tsize);
+       dev_dbg(hdev->dev, "source == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->src_addr));
+       dev_dbg(hdev->dev, "destination == 0x%llx\n",
+               le64_to_cpu(user_dma_pkt->dst_addr));
+       dev_dbg(hdev->dev, "size == %u\n", le32_to_cpu(user_dma_pkt->tsize));
 
        /*
         * WA for HW-23.
@@ -3385,7 +3391,8 @@ static int goya_validate_wreg32(struct hl_device *hdev,
 
        dev_dbg(hdev->dev, "WREG32 packet details:\n");
        dev_dbg(hdev->dev, "reg_offset == 0x%x\n", reg_offset);
-       dev_dbg(hdev->dev, "value      == 0x%x\n", wreg_pkt->value);
+       dev_dbg(hdev->dev, "value      == 0x%x\n",
+               le32_to_cpu(wreg_pkt->value));
 
        if (reg_offset != (mmDMA_CH_0_WR_COMP_ADDR_LO & 0x1FFF)) {
                dev_err(hdev->dev, "WREG32 packet with illegal address 0x%x\n",
@@ -3427,12 +3434,13 @@ static int goya_validate_cb(struct hl_device *hdev,
        while (cb_parsed_length < parser->user_cb_size) {
                enum packet_id pkt_id;
                u16 pkt_size;
-               void *user_pkt;
+               struct goya_packet *user_pkt;
 
-               user_pkt = (void *) (uintptr_t)
+               user_pkt = (struct goya_packet *) (uintptr_t)
                        (parser->user_cb->kernel_address + cb_parsed_length);
 
-               pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+               pkt_id = (enum packet_id) (
+                               (le64_to_cpu(user_pkt->header) &
                                PACKET_HEADER_PACKET_ID_MASK) >>
                                        PACKET_HEADER_PACKET_ID_SHIFT);
 
@@ -3452,7 +3460,8 @@ static int goya_validate_cb(struct hl_device *hdev,
                         * need to validate here as well because patch_cb() is
                         * not called in MMU path while this function is called
                         */
-                       rc = goya_validate_wreg32(hdev, parser, user_pkt);
+                       rc = goya_validate_wreg32(hdev,
+                               parser, (struct packet_wreg32 *) user_pkt);
                        break;
 
                case PACKET_WREG_BULK:
@@ -3480,10 +3489,10 @@ static int goya_validate_cb(struct hl_device *hdev,
                case PACKET_LIN_DMA:
                        if (is_mmu)
                                rc = goya_validate_dma_pkt_mmu(hdev, parser,
-                                               user_pkt);
+                                       (struct packet_lin_dma *) user_pkt);
                        else
                                rc = goya_validate_dma_pkt_no_mmu(hdev, parser,
-                                               user_pkt);
+                                       (struct packet_lin_dma *) user_pkt);
                        break;
 
                case PACKET_MSG_LONG:
@@ -3656,15 +3665,16 @@ static int goya_patch_cb(struct hl_device *hdev,
                enum packet_id pkt_id;
                u16 pkt_size;
                u32 new_pkt_size = 0;
-               void *user_pkt, *kernel_pkt;
+               struct goya_packet *user_pkt, *kernel_pkt;
 
-               user_pkt = (void *) (uintptr_t)
+               user_pkt = (struct goya_packet *) (uintptr_t)
                        (parser->user_cb->kernel_address + cb_parsed_length);
-               kernel_pkt = (void *) (uintptr_t)
+               kernel_pkt = (struct goya_packet *) (uintptr_t)
                        (parser->patched_cb->kernel_address +
                                        cb_patched_cur_length);
 
-               pkt_id = (enum packet_id) (((*(u64 *) user_pkt) &
+               pkt_id = (enum packet_id) (
+                               (le64_to_cpu(user_pkt->header) &
                                PACKET_HEADER_PACKET_ID_MASK) >>
                                        PACKET_HEADER_PACKET_ID_SHIFT);
 
@@ -3679,15 +3689,18 @@ static int goya_patch_cb(struct hl_device *hdev,
 
                switch (pkt_id) {
                case PACKET_LIN_DMA:
-                       rc = goya_patch_dma_packet(hdev, parser, user_pkt,
-                                               kernel_pkt, &new_pkt_size);
+                       rc = goya_patch_dma_packet(hdev, parser,
+                                       (struct packet_lin_dma *) user_pkt,
+                                       (struct packet_lin_dma *) kernel_pkt,
+                                       &new_pkt_size);
                        cb_patched_cur_length += new_pkt_size;
                        break;
 
                case PACKET_WREG_32:
                        memcpy(kernel_pkt, user_pkt, pkt_size);
                        cb_patched_cur_length += pkt_size;
-                       rc = goya_validate_wreg32(hdev, parser, kernel_pkt);
+                       rc = goya_validate_wreg32(hdev, parser,
+                                       (struct packet_wreg32 *) kernel_pkt);
                        break;
 
                case PACKET_WREG_BULK:
@@ -4351,6 +4364,8 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
        size_t total_pkt_size;
        long result;
        int rc;
+       int irq_num_entries, irq_arr_index;
+       __le32 *goya_irq_arr;
 
        total_pkt_size = sizeof(struct armcp_unmask_irq_arr_packet) +
                        irq_arr_size;
@@ -4368,8 +4383,16 @@ static int goya_unmask_irq_arr(struct hl_device *hdev, u32 *irq_arr,
        if (!pkt)
                return -ENOMEM;
 
-       pkt->length = cpu_to_le32(irq_arr_size / sizeof(irq_arr[0]));
-       memcpy(&pkt->irqs, irq_arr, irq_arr_size);
+       irq_num_entries = irq_arr_size / sizeof(irq_arr[0]);
+       pkt->length = cpu_to_le32(irq_num_entries);
+
+       /* We must perform any necessary endianness conversation on the irq
+        * array being passed to the goya hardware
+        */
+       for (irq_arr_index = 0, goya_irq_arr = (__le32 *) &pkt->irqs;
+                       irq_arr_index < irq_num_entries ; irq_arr_index++)
+               goya_irq_arr[irq_arr_index] =
+                               cpu_to_le32(irq_arr[irq_arr_index]);
 
        pkt->armcp_pkt.ctl = cpu_to_le32(ARMCP_PACKET_UNMASK_RAZWI_IRQ_ARRAY <<
                                                ARMCP_PKT_CTL_OPCODE_SHIFT);
@@ -5041,7 +5064,7 @@ static const struct hl_asic_funcs goya_funcs = {
        .resume = goya_resume,
        .cb_mmap = goya_cb_mmap,
        .ring_doorbell = goya_ring_doorbell,
-       .flush_pq_write = goya_flush_pq_write,
+       .pqe_write = goya_pqe_write,
        .asic_dma_alloc_coherent = goya_dma_alloc_coherent,
        .asic_dma_free_coherent = goya_dma_free_coherent,
        .get_int_queue_base = goya_get_int_queue_base,
index f8c611883dc12b844465b9879beeeb84872c6c15..d7f48c9c41cdc7f6549b5a42441f3bfd1fb897e0 100644 (file)
@@ -177,7 +177,7 @@ int goya_late_init(struct hl_device *hdev);
 void goya_late_fini(struct hl_device *hdev);
 
 void goya_ring_doorbell(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
-void goya_flush_pq_write(struct hl_device *hdev, u64 *pq, u64 exp_val);
+void goya_pqe_write(struct hl_device *hdev, __le64 *pqe, struct hl_bd *bd);
 void goya_update_eq_ci(struct hl_device *hdev, u32 val);
 void goya_restore_phase_topology(struct hl_device *hdev);
 int goya_context_switch(struct hl_device *hdev, u32 asid);
index 10da9940ee0dd1ac2cbad4291dee1d297897877a..ce83adafcf2d97561cd37ae97b63187422af3085 100644 (file)
@@ -441,7 +441,11 @@ enum hl_pll_frequency {
  * @resume: handles IP specific H/W or SW changes for resume.
  * @cb_mmap: maps a CB.
  * @ring_doorbell: increment PI on a given QMAN.
- * @flush_pq_write: flush PQ entry write if necessary, WARN if flushing failed.
+ * @pqe_write: Write the PQ entry to the PQ. This is ASIC-specific
+ *             function because the PQs are located in different memory areas
+ *             per ASIC (SRAM, DRAM, Host memory) and therefore, the method of
+ *             writing the PQE must match the destination memory area
+ *             properties.
  * @asic_dma_alloc_coherent: Allocate coherent DMA memory by calling
  *                           dma_alloc_coherent(). This is ASIC function because
  *                           its implementation is not trivial when the driver
@@ -510,7 +514,8 @@ struct hl_asic_funcs {
        int (*cb_mmap)(struct hl_device *hdev, struct vm_area_struct *vma,
                        u64 kaddress, phys_addr_t paddress, u32 size);
        void (*ring_doorbell)(struct hl_device *hdev, u32 hw_queue_id, u32 pi);
-       void (*flush_pq_write)(struct hl_device *hdev, u64 *pq, u64 exp_val);
+       void (*pqe_write)(struct hl_device *hdev, __le64 *pqe,
+                       struct hl_bd *bd);
        void* (*asic_dma_alloc_coherent)(struct hl_device *hdev, size_t size,
                                        dma_addr_t *dma_handle, gfp_t flag);
        void (*asic_dma_free_coherent)(struct hl_device *hdev, size_t size,
@@ -1062,9 +1067,17 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
 /*
  * address in this macro points always to a memory location in the
  * host's (server's) memory. That location is updated asynchronously
- * either by the direct access of the device or by another core
+ * either by the direct access of the device or by another core.
+ *
+ * To work both in LE and BE architectures, we need to distinguish between the
+ * two states (device or another core updates the memory location). Therefore,
+ * if mem_written_by_device is true, the host memory being polled will be
+ * updated directly by the device. If false, the host memory being polled will
+ * be updated by host CPU. Required so host knows whether or not the memory
+ * might need to be byte-swapped before returning value to caller.
  */
-#define hl_poll_timeout_memory(hdev, addr, val, cond, sleep_us, timeout_us) \
+#define hl_poll_timeout_memory(hdev, addr, val, cond, sleep_us, timeout_us, \
+                               mem_written_by_device) \
 ({ \
        ktime_t __timeout; \
        /* timeout should be longer when working with simulator */ \
@@ -1077,10 +1090,14 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
                /* Verify we read updates done by other cores or by device */ \
                mb(); \
                (val) = *((u32 *) (uintptr_t) (addr)); \
+               if (mem_written_by_device) \
+                       (val) = le32_to_cpu(val); \
                if (cond) \
                        break; \
                if (timeout_us && ktime_compare(ktime_get(), __timeout) > 0) { \
                        (val) = *((u32 *) (uintptr_t) (addr)); \
+                       if (mem_written_by_device) \
+                               (val) = le32_to_cpu(val); \
                        break; \
                } \
                if (sleep_us) \
index e3b5517897eabf1de40c28d54b28dd540282d5f3..5f5673b749852a66e8180f3488c287396980a1ce 100644 (file)
@@ -290,23 +290,19 @@ static void int_hw_queue_schedule_job(struct hl_cs_job *job)
        struct hl_device *hdev = job->cs->ctx->hdev;
        struct hl_hw_queue *q = &hdev->kernel_queues[job->hw_queue_id];
        struct hl_bd bd;
-       u64 *pi, *pbd = (u64 *) &bd;
+       __le64 *pi;
 
        bd.ctl = 0;
-       bd.len = __cpu_to_le32(job->job_cb_size);
-       bd.ptr = __cpu_to_le64((u64) (uintptr_t) job->user_cb);
+       bd.len = cpu_to_le32(job->job_cb_size);
+       bd.ptr = cpu_to_le64((u64) (uintptr_t) job->user_cb);
 
-       pi = (u64 *) (uintptr_t) (q->kernel_address +
+       pi = (__le64 *) (uintptr_t) (q->kernel_address +
                ((q->pi & (q->int_queue_len - 1)) * sizeof(bd)));
 
-       pi[0] = pbd[0];
-       pi[1] = pbd[1];
-
        q->pi++;
        q->pi &= ((q->int_queue_len << 1) - 1);
 
-       /* Flush PQ entry write. Relevant only for specific ASICs */
-       hdev->asic_funcs->flush_pq_write(hdev, pi, pbd[0]);
+       hdev->asic_funcs->pqe_write(hdev, pi, &bd);
 
        hdev->asic_funcs->ring_doorbell(hdev, q->hw_queue_id, q->pi);
 }
index a14407b975e4e9d5608cb551826bda8ec4fa6136..ef54bad2050991a2d863fb2c03afe2e52a42210f 100644 (file)
@@ -52,6 +52,19 @@ enum goya_dma_direction {
 #define GOYA_PKT_CTL_MB_SHIFT          31
 #define GOYA_PKT_CTL_MB_MASK           0x80000000
 
+/* All packets have, at least, an 8-byte header, which contains
+ * the packet type. The kernel driver uses the packet header for packet
+ * validation and to perform any necessary required preparation before
+ * sending them off to the hardware.
+ */
+struct goya_packet {
+       __le64 header;
+       /* The rest of the packet data follows. Use the corresponding
+        * packet_XXX struct to deference the data, based on packet type
+        */
+       u8 contents[0];
+};
+
 struct packet_nop {
        __le32 reserved;
        __le32 ctl;
index ea9f72ff456cf9fe23aae5e55d38fe03b88afc31..199791b57caf2746a719349dce45e23d5d9639be 100644 (file)
@@ -80,8 +80,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
        struct hl_cs_job *job;
        bool shadow_index_valid;
        u16 shadow_index;
-       u32 *cq_entry;
-       u32 *cq_base;
+       struct hl_cq_entry *cq_entry, *cq_base;
 
        if (hdev->disabled) {
                dev_dbg(hdev->dev,
@@ -90,29 +89,29 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                return IRQ_HANDLED;
        }
 
-       cq_base = (u32 *) (uintptr_t) cq->kernel_address;
+       cq_base = (struct hl_cq_entry *) (uintptr_t) cq->kernel_address;
 
        while (1) {
-               bool entry_ready = ((cq_base[cq->ci] & CQ_ENTRY_READY_MASK)
+               bool entry_ready = ((le32_to_cpu(cq_base[cq->ci].data) &
+                                       CQ_ENTRY_READY_MASK)
                                                >> CQ_ENTRY_READY_SHIFT);
 
                if (!entry_ready)
                        break;
 
-               cq_entry = (u32 *) &cq_base[cq->ci];
+               cq_entry = (struct hl_cq_entry *) &cq_base[cq->ci];
 
-               /*
-                * Make sure we read CQ entry contents after we've
+               /* Make sure we read CQ entry contents after we've
                 * checked the ownership bit.
                 */
                dma_rmb();
 
-               shadow_index_valid =
-                       ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
+               shadow_index_valid = ((le32_to_cpu(cq_entry->data) &
+                                       CQ_ENTRY_SHADOW_INDEX_VALID_MASK)
                                        >> CQ_ENTRY_SHADOW_INDEX_VALID_SHIFT);
 
-               shadow_index = (u16)
-                       ((*cq_entry & CQ_ENTRY_SHADOW_INDEX_MASK)
+               shadow_index = (u16) ((le32_to_cpu(cq_entry->data) &
+                                       CQ_ENTRY_SHADOW_INDEX_MASK)
                                        >> CQ_ENTRY_SHADOW_INDEX_SHIFT);
 
                queue = &hdev->kernel_queues[cq->hw_queue_id];
@@ -122,8 +121,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                        queue_work(hdev->cq_wq, &job->finish_work);
                }
 
-               /*
-                * Update ci of the context's queue. There is no
+               /* Update ci of the context's queue. There is no
                 * need to protect it with spinlock because this update is
                 * done only inside IRQ and there is a different IRQ per
                 * queue
@@ -131,7 +129,8 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
                queue->ci = hl_queue_inc_ptr(queue->ci);
 
                /* Clear CQ entry ready bit */
-               cq_base[cq->ci] &= ~CQ_ENTRY_READY_MASK;
+               cq_entry->data = cpu_to_le32(le32_to_cpu(cq_entry->data) &
+                                               ~CQ_ENTRY_READY_MASK);
 
                cq->ci = hl_cq_inc_ptr(cq->ci);
 
index 42d237cae1dc571419ee1a107960996b2b6f3d85..365fb0cb8dfffa87291dad6eeeb8625ce0de3212 100644 (file)
@@ -1629,6 +1629,8 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx)
                        dev_dbg(hdev->dev,
                                "page list 0x%p of asid %d is still alive\n",
                                phys_pg_list, ctx->asid);
+                       atomic64_sub(phys_pg_list->total_size,
+                                       &hdev->dram_used_mem);
                        free_phys_pg_pack(hdev, phys_pg_list);
                        idr_remove(&vm->phys_pg_pack_handles, i);
                }
index ed5cefb8376838b401aba0ac394c6a69e37dd818..89deb451e0ac6225c9481dc21ca21373f46c2d7c 100644 (file)
@@ -374,6 +374,7 @@ static int finish_dma_single(struct cvm_mmc_host *host, struct mmc_data *data)
 {
        data->bytes_xfered = data->blocks * data->blksz;
        data->error = 0;
+       dma_unmap_sg(host->dev, data->sg, data->sg_len, get_dma_dir(data));
        return 1;
 }
 
@@ -1046,7 +1047,8 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
                mmc->max_segs = 1;
 
        /* DMA size field can address up to 8 MB */
-       mmc->max_seg_size = 8 * 1024 * 1024;
+       mmc->max_seg_size = min_t(unsigned int, 8 * 1024 * 1024,
+                                 dma_get_max_seg_size(host->dev));
        mmc->max_req_size = mmc->max_seg_size;
        /* External DMA is in 512 byte blocks */
        mmc->max_blk_size = 512;
index b3a130a9ee23312348ef8369c34182089e82d0a8..1604f512c7bd183b85d8b3ed0c91634ed715a4cf 100644 (file)
@@ -883,7 +883,7 @@ static int sdhci_acpi_runtime_resume(struct device *dev)
 
        sdhci_acpi_byt_setting(&c->pdev->dev);
 
-       return sdhci_runtime_resume_host(c->host);
+       return sdhci_runtime_resume_host(c->host, 0);
 }
 
 #endif
index c391510e9ef407d54c25f4326a574a2b4b059ce6..776a942162488e87e14f3d48fd2b285ab9ecd1cf 100644 (file)
@@ -1705,7 +1705,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
                esdhc_pltfm_set_clock(host, imx_data->actual_clock);
        }
 
-       err = sdhci_runtime_resume_host(host);
+       err = sdhci_runtime_resume_host(host, 0);
        if (err)
                goto disable_ipg_clk;
 
index e377b9bc55a46d293353f3473050cae9b2494027..d4e7e8b7be772dadfb8d07206770f98e31c0801c 100644 (file)
@@ -289,7 +289,7 @@ static int sdhci_at91_runtime_resume(struct device *dev)
        }
 
 out:
-       return sdhci_runtime_resume_host(host);
+       return sdhci_runtime_resume_host(host, 0);
 }
 #endif /* CONFIG_PM */
 
index 4041878eb0f3ab92c2873d0f8787a3f8d528c06c..7d06e2860c36515f996a732fb624ce17a359417e 100644 (file)
@@ -167,7 +167,7 @@ static int sdhci_pci_runtime_suspend_host(struct sdhci_pci_chip *chip)
 
 err_pci_runtime_suspend:
        while (--i >= 0)
-               sdhci_runtime_resume_host(chip->slots[i]->host);
+               sdhci_runtime_resume_host(chip->slots[i]->host, 0);
        return ret;
 }
 
@@ -181,7 +181,7 @@ static int sdhci_pci_runtime_resume_host(struct sdhci_pci_chip *chip)
                if (!slot)
                        continue;
 
-               ret = sdhci_runtime_resume_host(slot->host);
+               ret = sdhci_runtime_resume_host(slot->host, 0);
                if (ret)
                        return ret;
        }
index 3ddecf47929585d6ca236fe17047316b9f8a1af5..e55037ceda734ff0e581fc8e2eecb664d882363f 100644 (file)
@@ -554,7 +554,7 @@ static int sdhci_pxav3_runtime_resume(struct device *dev)
        if (!IS_ERR(pxa->clk_core))
                clk_prepare_enable(pxa->clk_core);
 
-       return sdhci_runtime_resume_host(host);
+       return sdhci_runtime_resume_host(host, 0);
 }
 #endif
 
index 8e4a8ba33f0503bc52903755d3bd422bec233224..f5753aef71511d8bb495610858469ab3f1df028f 100644 (file)
@@ -745,7 +745,7 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
        clk_prepare_enable(busclk);
        if (ourhost->cur_clk >= 0)
                clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
-       ret = sdhci_runtime_resume_host(host);
+       ret = sdhci_runtime_resume_host(host, 0);
        return ret;
 }
 #endif
index 603a5d9f045a87d3b56191d6ef0642f38c8fcdc4..83a4767ca680f45f5ebe1fcddf3f2491ccb310cc 100644 (file)
@@ -696,7 +696,7 @@ static int sdhci_sprd_runtime_resume(struct device *dev)
        if (ret)
                goto clk_disable;
 
-       sdhci_runtime_resume_host(host);
+       sdhci_runtime_resume_host(host, 1);
        return 0;
 
 clk_disable:
index 8a18f14cf842df20afd0609e973a7e5d5546349d..1dea1ba66f7b4e8a05e48a8a0f4fbac8875c2a14 100644 (file)
@@ -638,7 +638,7 @@ static int xenon_runtime_resume(struct device *dev)
                priv->restore_needed = false;
        }
 
-       ret = sdhci_runtime_resume_host(host);
+       ret = sdhci_runtime_resume_host(host, 0);
        if (ret)
                goto out;
        return 0;
index 59acf8e3331ee189fce0fbf2468478b48c41154c..a5dc5aae973e6e14f3915dae1c44d247a7ac7bfb 100644 (file)
@@ -3320,7 +3320,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
 }
 EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
 
-int sdhci_runtime_resume_host(struct sdhci_host *host)
+int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
 {
        struct mmc_host *mmc = host->mmc;
        unsigned long flags;
@@ -3331,7 +3331,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
                        host->ops->enable_dma(host);
        }
 
-       sdhci_init(host, 0);
+       sdhci_init(host, soft_reset);
 
        if (mmc->ios.power_mode != MMC_POWER_UNDEFINED &&
            mmc->ios.power_mode != MMC_POWER_OFF) {
index 89fd96596a1f75e18f600761a41302d455124f64..902f855efe8f8b0aad28731b1040ad56c086f688 100644 (file)
@@ -781,7 +781,7 @@ void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
 int sdhci_suspend_host(struct sdhci_host *host);
 int sdhci_resume_host(struct sdhci_host *host);
 int sdhci_runtime_suspend_host(struct sdhci_host *host);
-int sdhci_runtime_resume_host(struct sdhci_host *host);
+int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset);
 #endif
 
 void sdhci_cqe_enable(struct mmc_host *mmc);
index 03cc788511d59e22935f2b03762191e24e14b663..654bdc41fc99e4aee9a2ce3b0472769c0706f079 100644 (file)
@@ -3780,8 +3780,6 @@ static int spi_nor_init_params(struct spi_nor *nor,
                default:
                        /* Kept only for backward compatibility purpose. */
                        params->quad_enable = spansion_quad_enable;
-                       if (nor->clear_sr_bp)
-                               nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
                        break;
                }
 
@@ -4035,6 +4033,9 @@ static int spi_nor_init(struct spi_nor *nor)
        int err;
 
        if (nor->clear_sr_bp) {
+               if (nor->quad_enable == spansion_quad_enable)
+                       nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
+
                err = nor->clear_sr_bp(nor);
                if (err) {
                        dev_err(nor->dev,
index 11c5bad95226698ab2888f2ad971220a2c5df8e4..14a5fb3781453526914bdab493c9b68beaa596b3 100644 (file)
@@ -363,10 +363,13 @@ static int __init arcrimi_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_err("Too many arguments\n");
+               /* Fall through */
        case 3:         /* Node ID */
                node = ints[3];
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index 28510e33924fbd7099f232a869c7715656eccc4e..cd27fdc1059b908900fe72d7e23503750dface0a 100644 (file)
@@ -197,16 +197,22 @@ static int __init com20020isa_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_info("Too many arguments\n");
+               /* Fall through */
        case 6:         /* Timeout */
                timeout = ints[6];
+               /* Fall through */
        case 5:         /* CKP value */
                clockp = ints[5];
+               /* Fall through */
        case 4:         /* Backplane flag */
                backplane = ints[4];
+               /* Fall through */
        case 3:         /* Node ID */
                node = ints[3];
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index 2c546013a98014b4c83b759d293ed24f91b3c940..186bbf87bc849f1e3e80180068412de2a5ff1606 100644 (file)
@@ -363,8 +363,10 @@ static int __init com90io_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_err("Too many arguments\n");
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index ca4a57c30bf89ed8d565d228aca9953153a3adf4..bd75d06ad7dfc98c982a3c7f033508a8e398d3ae 100644 (file)
@@ -693,10 +693,13 @@ static int __init com90xx_setup(char *s)
        switch (ints[0]) {
        default:                /* ERROR */
                pr_err("Too many arguments\n");
+               /* Fall through */
        case 3:         /* Mem address */
                shmem = ints[3];
+               /* Fall through */
        case 2:         /* IRQ */
                irq = ints[2];
+               /* Fall through */
        case 1:         /* IO address */
                io = ints[1];
        }
index 9b7016abca2f6c4a89185fb23b0bd719e18c08e4..931d9d9356869b400c1b653414164a3e5ecb0b51 100644 (file)
@@ -1126,6 +1126,8 @@ static void bond_compute_features(struct bonding *bond)
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+                                   NETIF_F_HW_VLAN_CTAG_TX |
+                                   NETIF_F_HW_VLAN_STAG_TX |
                                    NETIF_F_GSO_UDP_L4;
        bond_dev->mpls_features = mpls_features;
        bond_dev->gso_max_segs = gso_max_segs;
@@ -2196,6 +2198,15 @@ static void bond_miimon_commit(struct bonding *bond)
        bond_for_each_slave(bond, slave, iter) {
                switch (slave->new_link) {
                case BOND_LINK_NOCHANGE:
+                       /* For 802.3ad mode, check current slave speed and
+                        * duplex again in case its port was disabled after
+                        * invalid speed/duplex reporting but recovered before
+                        * link monitoring could make a decision on the actual
+                        * link status
+                        */
+                       if (BOND_MODE(bond) == BOND_MODE_8023AD &&
+                           slave->link == BOND_LINK_UP)
+                               bond_3ad_adapter_speed_duplex_changed(slave);
                        continue;
 
                case BOND_LINK_UP:
index b6b93a2d93a59293dccbfe00158857aae5a21965..483d270664cc87efd828993641406e24818db334 100644 (file)
@@ -1249,6 +1249,8 @@ int register_candev(struct net_device *dev)
                return -EINVAL;
 
        dev->rtnl_link_ops = &can_link_ops;
+       netif_carrier_off(dev);
+
        return register_netdev(dev);
 }
 EXPORT_SYMBOL_GPL(register_candev);
index f2fe344593d58ce66697515326efae700dab22ce..fcec8bcb53d64cd246b1e003de157432ec32bd41 100644 (file)
@@ -400,9 +400,10 @@ static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
        priv->write(reg_mcr, &regs->mcr);
 }
 
-static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
+static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int ackval;
        u32 reg_mcr;
 
        reg_mcr = priv->read(&regs->mcr);
@@ -412,20 +413,37 @@ static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
        /* enable stop request */
        regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
                           1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
+
+       /* get stop acknowledgment */
+       if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
+                                    ackval, ackval & (1 << priv->stm.ack_bit),
+                                    0, FLEXCAN_TIMEOUT_US))
+               return -ETIMEDOUT;
+
+       return 0;
 }
 
-static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv)
+static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int ackval;
        u32 reg_mcr;
 
        /* remove stop request */
        regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
                           1 << priv->stm.req_bit, 0);
 
+       /* get stop acknowledgment */
+       if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
+                                    ackval, !(ackval & (1 << priv->stm.ack_bit)),
+                                    0, FLEXCAN_TIMEOUT_US))
+               return -ETIMEDOUT;
+
        reg_mcr = priv->read(&regs->mcr);
        reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
        priv->write(reg_mcr, &regs->mcr);
+
+       return 0;
 }
 
 static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
@@ -1437,10 +1455,10 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
 
        priv = netdev_priv(dev);
        priv->stm.gpr = syscon_node_to_regmap(gpr_np);
-       of_node_put(gpr_np);
        if (IS_ERR(priv->stm.gpr)) {
                dev_dbg(&pdev->dev, "could not find gpr regmap\n");
-               return PTR_ERR(priv->stm.gpr);
+               ret = PTR_ERR(priv->stm.gpr);
+               goto out_put_node;
        }
 
        priv->stm.req_gpr = out_val[1];
@@ -1455,7 +1473,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
 
        device_set_wakeup_capable(&pdev->dev, true);
 
-       return 0;
+out_put_node:
+       of_node_put(gpr_np);
+       return ret;
 }
 
 static const struct of_device_id flexcan_of_match[] = {
@@ -1612,7 +1632,9 @@ static int __maybe_unused flexcan_suspend(struct device *device)
                 */
                if (device_may_wakeup(device)) {
                        enable_irq_wake(dev->irq);
-                       flexcan_enter_stop_mode(priv);
+                       err = flexcan_enter_stop_mode(priv);
+                       if (err)
+                               return err;
                } else {
                        err = flexcan_chip_disable(priv);
                        if (err)
@@ -1662,10 +1684,13 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
 {
        struct net_device *dev = dev_get_drvdata(device);
        struct flexcan_priv *priv = netdev_priv(dev);
+       int err;
 
        if (netif_running(dev) && device_may_wakeup(device)) {
                flexcan_enable_wakeup_irq(priv, false);
-               flexcan_exit_stop_mode(priv);
+               err = flexcan_exit_stop_mode(priv);
+               if (err)
+                       return err;
        }
 
        return 0;
index 05410008aa6b6ee2ac1a6a957c2b0b838f9ee2fc..de34a4b82d4ad474ff2ba253ba29f52d5347d8f3 100644 (file)
@@ -1508,10 +1508,11 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota)
 
        /* All packets processed */
        if (num_pkts < quota) {
-               napi_complete_done(napi, num_pkts);
-               /* Enable Rx FIFO interrupts */
-               rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx),
-                                  RCANFD_RFCC_RFIE);
+               if (napi_complete_done(napi, num_pkts)) {
+                       /* Enable Rx FIFO interrupts */
+                       rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx),
+                                          RCANFD_RFCC_RFIE);
+               }
        }
        return num_pkts;
 }
index 185c7f7d38a4ae15f64e6c38539534e007273411..5e0d5e8101c86913955525f93c1aacad0b83268b 100644 (file)
@@ -479,7 +479,7 @@ static void pcan_free_channels(struct pcan_pccard *card)
                if (!netdev)
                        continue;
 
-               strncpy(name, netdev->name, IFNAMSIZ);
+               strlcpy(name, netdev->name, IFNAMSIZ);
 
                unregister_sja1000dev(netdev);
 
index 234cf1042df6b03bc48af4e35f808b8d329c7231..12358f06d19400bed0dab5d094d04e5e3da2a436 100644 (file)
@@ -664,17 +664,6 @@ static int mcp251x_power_enable(struct regulator *reg, int enable)
                return regulator_disable(reg);
 }
 
-static void mcp251x_open_clean(struct net_device *net)
-{
-       struct mcp251x_priv *priv = netdev_priv(net);
-       struct spi_device *spi = priv->spi;
-
-       free_irq(spi->irq, priv);
-       mcp251x_hw_sleep(spi);
-       mcp251x_power_enable(priv->transceiver, 0);
-       close_candev(net);
-}
-
 static int mcp251x_stop(struct net_device *net)
 {
        struct mcp251x_priv *priv = netdev_priv(net);
@@ -941,37 +930,43 @@ static int mcp251x_open(struct net_device *net)
                                   flags | IRQF_ONESHOT, DEVICE_NAME, priv);
        if (ret) {
                dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
-               mcp251x_power_enable(priv->transceiver, 0);
-               close_candev(net);
-               goto open_unlock;
+               goto out_close;
        }
 
        priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
                                   0);
+       if (!priv->wq) {
+               ret = -ENOMEM;
+               goto out_clean;
+       }
        INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
        INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);
 
        ret = mcp251x_hw_reset(spi);
-       if (ret) {
-               mcp251x_open_clean(net);
-               goto open_unlock;
-       }
+       if (ret)
+               goto out_free_wq;
        ret = mcp251x_setup(net, spi);
-       if (ret) {
-               mcp251x_open_clean(net);
-               goto open_unlock;
-       }
+       if (ret)
+               goto out_free_wq;
        ret = mcp251x_set_normal_mode(spi);
-       if (ret) {
-               mcp251x_open_clean(net);
-               goto open_unlock;
-       }
+       if (ret)
+               goto out_free_wq;
 
        can_led_event(net, CAN_LED_EVENT_OPEN);
 
        netif_wake_queue(net);
+       mutex_unlock(&priv->mcp_lock);
 
-open_unlock:
+       return 0;
+
+out_free_wq:
+       destroy_workqueue(priv->wq);
+out_clean:
+       free_irq(spi->irq, priv);
+       mcp251x_hw_sleep(spi);
+out_close:
+       mcp251x_power_enable(priv->transceiver, 0);
+       close_candev(net);
        mutex_unlock(&priv->mcp_lock);
        return ret;
 }
index 458154c9b48298b45c1e93a83fc98afe47eb1caa..65dce642b86b54c8378bece93bfdc738573470ae 100644 (file)
@@ -568,16 +568,16 @@ static int peak_usb_ndo_stop(struct net_device *netdev)
        dev->state &= ~PCAN_USB_STATE_STARTED;
        netif_stop_queue(netdev);
 
+       close_candev(netdev);
+
+       dev->can.state = CAN_STATE_STOPPED;
+
        /* unlink all pending urbs and free used memory */
        peak_usb_unlink_all_urbs(dev);
 
        if (dev->adapter->dev_stop)
                dev->adapter->dev_stop(dev);
 
-       close_candev(netdev);
-
-       dev->can.state = CAN_STATE_STOPPED;
-
        /* can set bus off now */
        if (dev->adapter->dev_set_bus) {
                int err = dev->adapter->dev_set_bus(dev, 0);
@@ -855,7 +855,7 @@ static void peak_usb_disconnect(struct usb_interface *intf)
 
                dev_prev_siblings = dev->prev_siblings;
                dev->state &= ~PCAN_USB_STATE_CONNECTED;
-               strncpy(name, netdev->name, IFNAMSIZ);
+               strlcpy(name, netdev->name, IFNAMSIZ);
 
                unregister_netdev(netdev);
 
index 34761c3a62867d1001f48224bd9e51b1685bbb74..47cc1ff5b88e828fe65899b8ef38b447ae1da098 100644 (file)
@@ -841,7 +841,7 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
                        goto err_out;
 
                /* allocate command buffer once for all for the interface */
-               pdev->cmd_buffer_addr = kmalloc(PCAN_UFD_CMD_BUFFER_SIZE,
+               pdev->cmd_buffer_addr = kzalloc(PCAN_UFD_CMD_BUFFER_SIZE,
                                                GFP_KERNEL);
                if (!pdev->cmd_buffer_addr)
                        goto err_out_1;
index 178bb7cff0c1a10378ea711af07d380367021b26..53cb2f72bdd0574b4fe6bcd654dd12cf57179546 100644 (file)
@@ -494,7 +494,7 @@ static int pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
        u8 *buffer;
        int err;
 
-       buffer = kmalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
+       buffer = kzalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
 
index 6b17cd961d061285b7f3c258ab37445559e8b04f..d0a97eb73a37678b8fba381a200399c7736769cc 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/platform_data/mv88e6xxx.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
-#include <linux/phy.h>
 #include <linux/phylink.h>
 #include <net/dsa.h>
 
@@ -430,7 +429,7 @@ int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
                return 0;
 
        /* Port's MAC control must not be changed unless the link is down */
-       err = chip->info->ops->port_set_link(chip, port, 0);
+       err = chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN);
        if (err)
                return err;
 
@@ -482,30 +481,6 @@ static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
        return port < chip->info->num_internal_phys;
 }
 
-/* We expect the switch to perform auto negotiation if there is a real
- * phy. However, in the case of a fixed link phy, we force the port
- * settings from the fixed link settings.
- */
-static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
-                                 struct phy_device *phydev)
-{
-       struct mv88e6xxx_chip *chip = ds->priv;
-       int err;
-
-       if (!phy_is_pseudo_fixed_link(phydev) &&
-           mv88e6xxx_phy_is_internal(ds, port))
-               return;
-
-       mv88e6xxx_reg_lock(chip);
-       err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
-                                      phydev->duplex, phydev->pause,
-                                      phydev->interface);
-       mv88e6xxx_reg_unlock(chip);
-
-       if (err && err != -EOPNOTSUPP)
-               dev_err(ds->dev, "p%d: failed to configure MAC\n", port);
-}
-
 static void mv88e6065_phylink_validate(struct mv88e6xxx_chip *chip, int port,
                                       unsigned long *mask,
                                       struct phylink_link_state *state)
@@ -2721,6 +2696,7 @@ static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
                        err = mv88e6xxx_mdio_register(chip, child, true);
                        if (err) {
                                mv88e6xxx_mdios_unregister(chip);
+                               of_node_put(child);
                                return err;
                        }
                }
@@ -4638,7 +4614,6 @@ static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
 static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
        .get_tag_protocol       = mv88e6xxx_get_tag_protocol,
        .setup                  = mv88e6xxx_setup,
-       .adjust_link            = mv88e6xxx_adjust_link,
        .phylink_validate       = mv88e6xxx_validate,
        .phylink_mac_link_state = mv88e6xxx_link_state,
        .phylink_mac_config     = mv88e6xxx_mac_config,
index 232e8cc96f6dee10ecfba315cc9fc9eb7a9975fb..16f15c93a102c9b66d76c22ae0e8e310a6b6edf5 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name>
  * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved.
  * Copyright (c) 2016 John Crispin <john@phrozen.org>
  */
 
@@ -583,8 +583,11 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
 
        for_each_available_child_of_node(ports, port) {
                err = of_property_read_u32(port, "reg", &reg);
-               if (err)
+               if (err) {
+                       of_node_put(port);
+                       of_node_put(ports);
                        return err;
+               }
 
                if (!dsa_is_user_port(priv->ds, reg))
                        continue;
@@ -595,6 +598,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
                        internal_mdio_mask |= BIT(reg);
        }
 
+       of_node_put(ports);
        if (!external_mdio_mask && !internal_mdio_mask) {
                dev_err(priv->dev, "no PHYs are defined.\n");
                return -EINVAL;
@@ -935,6 +939,8 @@ qca8k_port_enable(struct dsa_switch *ds, int port,
        qca8k_port_set_status(priv, port, 1);
        priv->port_sts[port].enabled = 1;
 
+       phy_support_asym_pause(phy);
+
        return 0;
 }
 
index 6bfb1696a6f2806dc4b875329b9e0ae720517d90..9988c9d185678a678ca262e9dfdc6b5f09ce30ae 100644 (file)
@@ -277,6 +277,18 @@ sja1105et_l2_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
                        SJA1105ET_SIZE_L2_LOOKUP_ENTRY, op);
 }
 
+static size_t sja1105et_dyn_l2_lookup_entry_packing(void *buf, void *entry_ptr,
+                                                   enum packing_op op)
+{
+       struct sja1105_l2_lookup_entry *entry = entry_ptr;
+       u8 *cmd = buf + SJA1105ET_SIZE_L2_LOOKUP_ENTRY;
+       const int size = SJA1105_SIZE_DYN_CMD;
+
+       sja1105_packing(cmd, &entry->lockeds, 28, 28, size, op);
+
+       return sja1105et_l2_lookup_entry_packing(buf, entry_ptr, op);
+}
+
 static void
 sja1105et_mgmt_route_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
                                 enum packing_op op)
@@ -477,7 +489,7 @@ sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
 /* SJA1105E/T: First generation */
 struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
        [BLK_IDX_L2_LOOKUP] = {
-               .entry_packing = sja1105et_l2_lookup_entry_packing,
+               .entry_packing = sja1105et_dyn_l2_lookup_entry_packing,
                .cmd_packing = sja1105et_l2_lookup_cmd_packing,
                .access = (OP_READ | OP_WRITE | OP_DEL),
                .max_entry_count = SJA1105_MAX_L2_LOOKUP_COUNT,
index 32bf3a7cc3b6db9961ec7df11cc0e9bb127de4a8..df976b259e43d24dc226d1e347c6338412868fe6 100644 (file)
@@ -218,7 +218,7 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv)
                /* This selects between Independent VLAN Learning (IVL) and
                 * Shared VLAN Learning (SVL)
                 */
-               .shared_learn = false,
+               .shared_learn = true,
                /* Don't discard management traffic based on ENFPORT -
                 * we don't perform SMAC port enforcement anyway, so
                 * what we are setting here doesn't matter.
@@ -625,6 +625,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
                if (of_property_read_u32(child, "reg", &index) < 0) {
                        dev_err(dev, "Port number not defined in device tree "
                                "(property \"reg\")\n");
+                       of_node_put(child);
                        return -ENODEV;
                }
 
@@ -634,6 +635,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
                        dev_err(dev, "Failed to read phy-mode or "
                                "phy-interface-type property for port %d\n",
                                index);
+                       of_node_put(child);
                        return -ENODEV;
                }
                ports[index].phy_mode = phy_mode;
@@ -643,6 +645,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
                        if (!of_phy_is_fixed_link(child)) {
                                dev_err(dev, "phy-handle or fixed-link "
                                        "properties missing!\n");
+                               of_node_put(child);
                                return -ENODEV;
                        }
                        /* phy-handle is missing, but fixed-link isn't.
@@ -1089,8 +1092,13 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port,
        l2_lookup.vlanid = vid;
        l2_lookup.iotag = SJA1105_S_TAG;
        l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0);
-       l2_lookup.mask_vlanid = VLAN_VID_MASK;
-       l2_lookup.mask_iotag = BIT(0);
+       if (dsa_port_is_vlan_filtering(&ds->ports[port])) {
+               l2_lookup.mask_vlanid = VLAN_VID_MASK;
+               l2_lookup.mask_iotag = BIT(0);
+       } else {
+               l2_lookup.mask_vlanid = 0;
+               l2_lookup.mask_iotag = 0;
+       }
        l2_lookup.destports = BIT(port);
 
        rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
@@ -1147,8 +1155,13 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port,
        l2_lookup.vlanid = vid;
        l2_lookup.iotag = SJA1105_S_TAG;
        l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0);
-       l2_lookup.mask_vlanid = VLAN_VID_MASK;
-       l2_lookup.mask_iotag = BIT(0);
+       if (dsa_port_is_vlan_filtering(&ds->ports[port])) {
+               l2_lookup.mask_vlanid = VLAN_VID_MASK;
+               l2_lookup.mask_iotag = BIT(0);
+       } else {
+               l2_lookup.mask_vlanid = 0;
+               l2_lookup.mask_iotag = 0;
+       }
        l2_lookup.destports = BIT(port);
 
        rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
@@ -1178,60 +1191,31 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
                           const unsigned char *addr, u16 vid)
 {
        struct sja1105_private *priv = ds->priv;
-       u16 rx_vid, tx_vid;
-       int rc, i;
 
-       if (dsa_port_is_vlan_filtering(&ds->ports[port]))
-               return priv->info->fdb_add_cmd(ds, port, addr, vid);
-
-       /* Since we make use of VLANs even when the bridge core doesn't tell us
-        * to, translate these FDB entries into the correct dsa_8021q ones.
-        * The basic idea (also repeats for removal below) is:
-        * - Each of the other front-panel ports needs to be able to forward a
-        *   pvid-tagged (aka tagged with their rx_vid) frame that matches this
-        *   DMAC.
-        * - The CPU port (aka the tx_vid of this port) needs to be able to
-        *   send a frame matching this DMAC to the specified port.
-        * For a better picture see net/dsa/tag_8021q.c.
+       /* dsa_8021q is in effect when the bridge's vlan_filtering isn't,
+        * so the switch still does some VLAN processing internally.
+        * But Shared VLAN Learning (SVL) is also active, and it will take
+        * care of autonomous forwarding between the unique pvid's of each
+        * port.  Here we just make sure that users can't add duplicate FDB
+        * entries when in this mode - the actual VID doesn't matter except
+        * for what gets printed in 'bridge fdb show'.  In the case of zero,
+        * no VID gets printed at all.
         */
-       for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-               if (i == port)
-                       continue;
-               if (i == dsa_upstream_port(priv->ds, port))
-                       continue;
+       if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+               vid = 0;
 
-               rx_vid = dsa_8021q_rx_vid(ds, i);
-               rc = priv->info->fdb_add_cmd(ds, port, addr, rx_vid);
-               if (rc < 0)
-                       return rc;
-       }
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-       return priv->info->fdb_add_cmd(ds, port, addr, tx_vid);
+       return priv->info->fdb_add_cmd(ds, port, addr, vid);
 }
 
 static int sja1105_fdb_del(struct dsa_switch *ds, int port,
                           const unsigned char *addr, u16 vid)
 {
        struct sja1105_private *priv = ds->priv;
-       u16 rx_vid, tx_vid;
-       int rc, i;
 
-       if (dsa_port_is_vlan_filtering(&ds->ports[port]))
-               return priv->info->fdb_del_cmd(ds, port, addr, vid);
+       if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+               vid = 0;
 
-       for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-               if (i == port)
-                       continue;
-               if (i == dsa_upstream_port(priv->ds, port))
-                       continue;
-
-               rx_vid = dsa_8021q_rx_vid(ds, i);
-               rc = priv->info->fdb_del_cmd(ds, port, addr, rx_vid);
-               if (rc < 0)
-                       return rc;
-       }
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-       return priv->info->fdb_del_cmd(ds, port, addr, tx_vid);
+       return priv->info->fdb_del_cmd(ds, port, addr, vid);
 }
 
 static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
@@ -1239,12 +1223,8 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
 {
        struct sja1105_private *priv = ds->priv;
        struct device *dev = ds->dev;
-       u16 rx_vid, tx_vid;
        int i;
 
-       rx_vid = dsa_8021q_rx_vid(ds, port);
-       tx_vid = dsa_8021q_tx_vid(ds, port);
-
        for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
                struct sja1105_l2_lookup_entry l2_lookup = {0};
                u8 macaddr[ETH_ALEN];
@@ -1270,39 +1250,9 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
                        continue;
                u64_to_ether_addr(l2_lookup.macaddr, macaddr);
 
-               /* On SJA1105 E/T, the switch doesn't implement the LOCKEDS
-                * bit, so it doesn't tell us whether a FDB entry is static
-                * or not.
-                * But, of course, we can find out - we're the ones who added
-                * it in the first place.
-                */
-               if (priv->info->device_id == SJA1105E_DEVICE_ID ||
-                   priv->info->device_id == SJA1105T_DEVICE_ID) {
-                       int match;
-
-                       match = sja1105_find_static_fdb_entry(priv, port,
-                                                             &l2_lookup);
-                       l2_lookup.lockeds = (match >= 0);
-               }
-
-               /* We need to hide the dsa_8021q VLANs from the user. This
-                * basically means hiding the duplicates and only showing
-                * the pvid that is supposed to be active in standalone and
-                * non-vlan_filtering modes (aka 1).
-                * - For statically added FDB entries (bridge fdb add), we
-                *   can convert the TX VID (coming from the CPU port) into the
-                *   pvid and ignore the RX VIDs of the other ports.
-                * - For dynamically learned FDB entries, a single entry with
-                *   no duplicates is learned - that which has the real port's
-                *   pvid, aka RX VID.
-                */
-               if (!dsa_port_is_vlan_filtering(&ds->ports[port])) {
-                       if (l2_lookup.vlanid == tx_vid ||
-                           l2_lookup.vlanid == rx_vid)
-                               l2_lookup.vlanid = 1;
-                       else
-                               continue;
-               }
+               /* We need to hide the dsa_8021q VLANs from the user. */
+               if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
+                       l2_lookup.vlanid = 0;
                cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
        }
        return 0;
@@ -1594,6 +1544,7 @@ static int sja1105_vlan_prepare(struct dsa_switch *ds, int port,
  */
 static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 {
+       struct sja1105_l2_lookup_params_entry *l2_lookup_params;
        struct sja1105_general_params_entry *general_params;
        struct sja1105_private *priv = ds->priv;
        struct sja1105_table *table;
@@ -1622,6 +1573,28 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
        general_params->incl_srcpt1 = enabled;
        general_params->incl_srcpt0 = enabled;
 
+       /* VLAN filtering => independent VLAN learning.
+        * No VLAN filtering => shared VLAN learning.
+        *
+        * In shared VLAN learning mode, untagged traffic still gets
+        * pvid-tagged, and the FDB table gets populated with entries
+        * containing the "real" (pvid or from VLAN tag) VLAN ID.
+        * However the switch performs a masked L2 lookup in the FDB,
+        * effectively only looking up a frame's DMAC (and not VID) for the
+        * forwarding decision.
+        *
+        * This is extremely convenient for us, because in modes with
+        * vlan_filtering=0, dsa_8021q actually installs unique pvid's into
+        * each front panel port. This is good for identification but breaks
+        * learning badly - the VID of the learnt FDB entry is unique, aka
+        * no frames coming from any other port are going to have it. So
+        * for forwarding purposes, this is as though learning was broken
+        * (all frames get flooded).
+        */
+       table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS];
+       l2_lookup_params = table->entries;
+       l2_lookup_params->shared_learn = !enabled;
+
        rc = sja1105_static_config_reload(priv);
        if (rc)
                dev_err(ds->dev, "Failed to change VLAN Ethertype\n");
@@ -1751,6 +1724,8 @@ static void sja1105_teardown(struct dsa_switch *ds)
 
        cancel_work_sync(&priv->tagger_data.rxtstamp_work);
        skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue);
+       sja1105_ptp_clock_unregister(priv);
+       sja1105_static_config_free(&priv->static_config);
 }
 
 static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
@@ -2208,9 +2183,7 @@ static int sja1105_remove(struct spi_device *spi)
 {
        struct sja1105_private *priv = spi_get_drvdata(spi);
 
-       sja1105_ptp_clock_unregister(priv);
        dsa_unregister_switch(priv->ds);
-       sja1105_static_config_free(&priv->static_config);
        return 0;
 }
 
index d19cfdf681af499ad4cae2e03aa0b9e73a754f03..d8e8dd59f3d1bba07a9b1c2a5a415818b7444020 100644 (file)
@@ -369,16 +369,15 @@ int sja1105_ptp_clock_register(struct sja1105_private *priv)
                .mult = SJA1105_CC_MULT,
        };
        mutex_init(&priv->ptp_lock);
-       INIT_DELAYED_WORK(&priv->refresh_work, sja1105_ptp_overflow_check);
-
-       schedule_delayed_work(&priv->refresh_work, SJA1105_REFRESH_INTERVAL);
-
        priv->ptp_caps = sja1105_ptp_caps;
 
        priv->clock = ptp_clock_register(&priv->ptp_caps, ds->dev);
        if (IS_ERR_OR_NULL(priv->clock))
                return PTR_ERR(priv->clock);
 
+       INIT_DELAYED_WORK(&priv->refresh_work, sja1105_ptp_overflow_check);
+       schedule_delayed_work(&priv->refresh_work, SJA1105_REFRESH_INTERVAL);
+
        return sja1105_ptp_reset(priv);
 }
 
index 2a3e2450968eeb066a8636001442d12413f78f3c..a9478577b49560f21a1b4c0f54f49f1dda0f15c4 100644 (file)
@@ -12,8 +12,8 @@ config NET_VENDOR_8390
 
          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about Western Digital cards. If you say Y, you will be
-         asked for your specific card in the following questions.
+         the questions about National Semiconductor 8390 cards. If you say Y,
+         you will be asked for your specific card in the following questions.
 
 if NET_VENDOR_8390
 
index ea34bcb868b57fba300df2d9d393aaa2ad82a926..edbb4b3604c751e9b02e4c4643b0406021514ed9 100644 (file)
@@ -2362,7 +2362,7 @@ static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter)
 
        /* Allocate memory for the TCB's (Transmit Control Block) */
        tx_ring->tcb_ring = kcalloc(NUM_TCB, sizeof(struct tcb),
-                                   GFP_ATOMIC | GFP_DMA);
+                                   GFP_KERNEL | GFP_DMA);
        if (!tx_ring->tcb_ring)
                return -ENOMEM;
 
index 3434730a76990b6ed78f4207428c1eabc8d49155..0537df06a9b58ae47f3f139266d12dd906ce9be6 100644 (file)
@@ -860,7 +860,9 @@ static int emac_probe(struct platform_device *pdev)
                goto out_clk_disable_unprepare;
        }
 
-       db->phy_node = of_parse_phandle(np, "phy", 0);
+       db->phy_node = of_parse_phandle(np, "phy-handle", 0);
+       if (!db->phy_node)
+               db->phy_node = of_parse_phandle(np, "phy", 0);
        if (!db->phy_node) {
                dev_err(&pdev->dev, "no associated PHY\n");
                ret = -ENODEV;
index de4950d2022e0a6d6efdc4a255cba93e2edbd77b..9f965cdfff5c99db9ff3f8d1d94a1f753cbbbd3a 100644 (file)
@@ -14,7 +14,7 @@ config NET_VENDOR_AMD
          say Y.
 
          Note that the answer to this question does not directly affect
-         the kernel: saying N will just case the configurator to skip all
+         the kernel: saying N will just cause the configurator to skip all
          the questions regarding AMD chipsets. If you say Y, you will be asked
          for your specific chipset/driver in the following questions.
 
index fde7ae33e302b6bc169469928c4e25bde2e2161b..f78b9c841296c94b92089c40d1c82e33a75f689c 100644 (file)
@@ -11,8 +11,8 @@ config NET_VENDOR_APPLE
          If you have a network (Ethernet) card belonging to this class, say Y.
 
          Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about IBM devices. If you say Y, you will be asked for
+         kernel: saying N will just cause the configurator to skip all the
+         questions about Apple devices. If you say Y, you will be asked for
          your specific card in the following questions.
 
 if NET_VENDOR_APPLE
index 8b69d0d7e7269e0b8d6c92f942ad5b0df535a55a..6703960c7cf5035a6af2fd8af53fa39e9a026d96 100644 (file)
@@ -1141,7 +1141,7 @@ static int ag71xx_rings_init(struct ag71xx *ag)
 
        tx->descs_cpu = dma_alloc_coherent(&ag->pdev->dev,
                                           ring_size * AG71XX_DESC_SIZE,
-                                          &tx->descs_dma, GFP_ATOMIC);
+                                          &tx->descs_dma, GFP_KERNEL);
        if (!tx->descs_cpu) {
                kfree(tx->buf);
                tx->buf = NULL;
index e9017caf024dcf33fba30506bb8a953b686ad560..e24f5d2b6afe35477940a4a6b86c55795f855a07 100644 (file)
@@ -14,9 +14,9 @@ config NET_VENDOR_BROADCOM
          say Y.
 
          Note that the answer to this question does not directly affect
-         the kernel: saying N will just case the configurator to skip all
-         the questions regarding AMD chipsets. If you say Y, you will be asked
-         for your specific chipset/driver in the following questions.
+         the kernel: saying N will just cause the configurator to skip all
+         the questions regarding Broadcom chipsets. If you say Y, you will
+         be asked for your specific chipset/driver in the following questions.
 
 if NET_VENDOR_BROADCOM
 
index b9c5cea8db168c2284846cd8b9e1f980ae78189e..9483553ce44452e6b742b278f18c277691568ed6 100644 (file)
@@ -992,7 +992,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
 {
        struct bcm_sysport_priv *priv =
                container_of(napi, struct bcm_sysport_priv, napi);
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
        unsigned int work_done = 0;
 
        work_done = bcm_sysport_desc_rx(priv, budget);
index e2be5a685130dce81c5371dcd9df8d6ff72ccc0c..d10b421ed1f19939bb4046ede23d74b55ebb5beb 100644 (file)
@@ -1934,8 +1934,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
        }
 
        /* select a non-FCoE queue */
-       return netdev_pick_tx(dev, skb, NULL) %
-              (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
+       return netdev_pick_tx(dev, skb, NULL) % (BNX2X_NUM_ETH_QUEUES(bp));
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -3058,12 +3057,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        /* if VF indicate to PF this function is going down (PF will delete sp
         * elements and clear initializations
         */
-       if (IS_VF(bp))
+       if (IS_VF(bp)) {
+               bnx2x_clear_vlan_info(bp);
                bnx2x_vfpf_close_vf(bp);
-       else if (unload_mode != UNLOAD_RECOVERY)
+       } else if (unload_mode != UNLOAD_RECOVERY) {
                /* if this is a normal/close unload need to clean up chip*/
                bnx2x_chip_cleanup(bp, unload_mode, keep_link);
-       else {
+       else {
                /* Send the UNLOAD_REQUEST to the MCP */
                bnx2x_send_unload_req(bp, unload_mode);
 
index c2f6e44e9a3f7e75b41f2542fedb9595fa2ef154..8b08cb18e36387e8465dda447f3b42150cab28bb 100644 (file)
@@ -425,6 +425,8 @@ void bnx2x_set_reset_global(struct bnx2x *bp);
 void bnx2x_disable_close_the_gate(struct bnx2x *bp);
 int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
 
+void bnx2x_clear_vlan_info(struct bnx2x *bp);
+
 /**
  * bnx2x_sp_event - handle ramrods completion.
  *
index 2cc14db8f0ec9c1d0ee8b922ea9926320cc5bb96..192ff8d5da3247c5f9f3b2fa0d7382adbdd83fb6 100644 (file)
@@ -8482,11 +8482,21 @@ int bnx2x_set_vlan_one(struct bnx2x *bp, u16 vlan,
        return rc;
 }
 
+void bnx2x_clear_vlan_info(struct bnx2x *bp)
+{
+       struct bnx2x_vlan_entry *vlan;
+
+       /* Mark that hw forgot all entries */
+       list_for_each_entry(vlan, &bp->vlan_reg, link)
+               vlan->hw = false;
+
+       bp->vlan_cnt = 0;
+}
+
 static int bnx2x_del_all_vlans(struct bnx2x *bp)
 {
        struct bnx2x_vlan_mac_obj *vlan_obj = &bp->sp_objs[0].vlan_obj;
        unsigned long ramrod_flags = 0, vlan_flags = 0;
-       struct bnx2x_vlan_entry *vlan;
        int rc;
 
        __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
@@ -8495,10 +8505,7 @@ static int bnx2x_del_all_vlans(struct bnx2x *bp)
        if (rc)
                return rc;
 
-       /* Mark that hw forgot all entries */
-       list_for_each_entry(vlan, &bp->vlan_reg, link)
-               vlan->hw = false;
-       bp->vlan_cnt = 0;
+       bnx2x_clear_vlan_info(bp);
 
        return 0;
 }
index 7134d2c3eb1c4ccdcdd9cdd97497adedddefa159..8dce4069472b6c02ed6d5d9cb58cce5a7b1ddeaf 100644 (file)
@@ -2021,9 +2021,9 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
        if (bnapi->events & BNXT_RX_EVENT) {
                struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
 
-               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                if (bnapi->events & BNXT_AGG_EVENT)
                        bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
        }
        bnapi->events = 0;
 }
@@ -2136,7 +2136,7 @@ static int bnxt_poll(struct napi_struct *napi, int budget)
                }
        }
        if (bp->flags & BNXT_FLAG_DIM) {
-               struct dim_sample dim_sample;
+               struct dim_sample dim_sample = {};
 
                dim_update_sample(cpr->event_ctr,
                                  cpr->rx_packets,
@@ -5064,6 +5064,7 @@ static void bnxt_set_db(struct bnxt *bp, struct bnxt_db_info *db, u32 ring_type,
 
 static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
 {
+       bool agg_rings = !!(bp->flags & BNXT_FLAG_AGG_RINGS);
        int i, rc = 0;
        u32 type;
 
@@ -5139,7 +5140,9 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                if (rc)
                        goto err_out;
                bnxt_set_db(bp, &rxr->rx_db, type, map_idx, ring->fw_ring_id);
-               bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
+               /* If we have agg rings, post agg buffers first. */
+               if (!agg_rings)
+                       bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                bp->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id;
                if (bp->flags & BNXT_FLAG_CHIP_P5) {
                        struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
@@ -5158,7 +5161,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                }
        }
 
-       if (bp->flags & BNXT_FLAG_AGG_RINGS) {
+       if (agg_rings) {
                type = HWRM_RING_ALLOC_AGG;
                for (i = 0; i < bp->rx_nr_rings; i++) {
                        struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -5174,6 +5177,7 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                        bnxt_set_db(bp, &rxr->rx_agg_db, type, map_idx,
                                    ring->fw_ring_id);
                        bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
+                       bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
                        bp->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id;
                }
        }
@@ -7016,19 +7020,29 @@ static void bnxt_hwrm_clear_vnic_rss(struct bnxt *bp)
                bnxt_hwrm_vnic_set_rss(bp, i, false);
 }
 
-static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
-                                   bool irq_re_init)
+static void bnxt_clear_vnic(struct bnxt *bp)
 {
-       if (bp->vnic_info) {
-               bnxt_hwrm_clear_vnic_filter(bp);
+       if (!bp->vnic_info)
+               return;
+
+       bnxt_hwrm_clear_vnic_filter(bp);
+       if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
                /* clear all RSS setting before free vnic ctx */
                bnxt_hwrm_clear_vnic_rss(bp);
                bnxt_hwrm_vnic_ctx_free(bp);
-               /* before free the vnic, undo the vnic tpa settings */
-               if (bp->flags & BNXT_FLAG_TPA)
-                       bnxt_set_tpa(bp, false);
-               bnxt_hwrm_vnic_free(bp);
        }
+       /* before free the vnic, undo the vnic tpa settings */
+       if (bp->flags & BNXT_FLAG_TPA)
+               bnxt_set_tpa(bp, false);
+       bnxt_hwrm_vnic_free(bp);
+       if (bp->flags & BNXT_FLAG_CHIP_P5)
+               bnxt_hwrm_vnic_ctx_free(bp);
+}
+
+static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path,
+                                   bool irq_re_init)
+{
+       bnxt_clear_vnic(bp);
        bnxt_hwrm_ring_free(bp, close_path);
        bnxt_hwrm_ring_grp_free(bp);
        if (irq_re_init) {
index 549c90d3e465f2fd4f7eb494cee47373b953aaf5..c05d663212b20519a89f18d9d9429d897ac99bdf 100644 (file)
@@ -98,10 +98,13 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
        if (idx)
                req->dimensions = cpu_to_le16(1);
 
-       if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE))
+       if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
                memcpy(data_addr, buf, bytesize);
-
-       rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+               rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
+       } else {
+               rc = hwrm_send_message_silent(bp, msg, msg_len,
+                                             HWRM_CMD_TIMEOUT);
+       }
        if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE))
                memcpy(buf, data_addr, bytesize);
 
index c7ee63d6967983d77087a9dcdda2638b683afcf1..8445a0cce849c0c8781a14dc5f11874cba1a53a5 100644 (file)
@@ -2016,21 +2016,19 @@ static int bnxt_flash_package_from_file(struct net_device *dev,
        mutex_lock(&bp->hwrm_cmd_lock);
        hwrm_err = _hwrm_send_message(bp, &install, sizeof(install),
                                      INSTALL_PACKAGE_TIMEOUT);
-       if (hwrm_err)
-               goto flash_pkg_exit;
-
-       if (resp->error_code) {
+       if (hwrm_err) {
                u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
 
-               if (error_code == NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
+               if (resp->error_code && error_code ==
+                   NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
                        install.flags |= cpu_to_le16(
                               NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
                        hwrm_err = _hwrm_send_message(bp, &install,
                                                      sizeof(install),
                                                      INSTALL_PACKAGE_TIMEOUT);
-                       if (hwrm_err)
-                               goto flash_pkg_exit;
                }
+               if (hwrm_err)
+                       goto flash_pkg_exit;
        }
 
        if (resp->result) {
index 6fe4a7174271b8286cac810b94e5fa8b95c1a9b5..dd621f6bd1271c8c594185b5a82b8e892b3e6576 100644 (file)
@@ -1236,7 +1236,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
 static void bnxt_tc_set_flow_dir(struct bnxt *bp, struct bnxt_tc_flow *flow,
                                 u16 src_fid)
 {
-       flow->dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
+       flow->l2_key.dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
 }
 
 static void bnxt_tc_set_src_fid(struct bnxt *bp, struct bnxt_tc_flow *flow,
@@ -1285,9 +1285,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
                goto free_node;
 
        bnxt_tc_set_src_fid(bp, flow, src_fid);
-
-       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
-               bnxt_tc_set_flow_dir(bp, flow, src_fid);
+       bnxt_tc_set_flow_dir(bp, flow, flow->src_fid);
 
        if (!bnxt_tc_can_offload(bp, flow)) {
                rc = -EOPNOTSUPP;
@@ -1407,7 +1405,7 @@ static void bnxt_fill_cfa_stats_req(struct bnxt *bp,
                 * 2. 15th bit of flow_handle must specify the flow
                 *    direction (TX/RX).
                 */
-               if (flow_node->flow.dir == BNXT_DIR_RX)
+               if (flow_node->flow.l2_key.dir == BNXT_DIR_RX)
                        handle = CFA_FLOW_INFO_REQ_FLOW_HANDLE_DIR_RX |
                                 CFA_FLOW_INFO_REQ_FLOW_HANDLE_MAX_MASK;
                else
index ffec57d1a5ecf2830e191c64bbd270905da209e7..4f05305052f2f27905646188a2d3047683ab419f 100644 (file)
@@ -23,6 +23,9 @@ struct bnxt_tc_l2_key {
        __be16          inner_vlan_tci;
        __be16          ether_type;
        u8              num_vlans;
+       u8              dir;
+#define BNXT_DIR_RX    1
+#define BNXT_DIR_TX    0
 };
 
 struct bnxt_tc_l3_key {
@@ -98,9 +101,6 @@ struct bnxt_tc_flow {
 
        /* flow applicable to pkts ingressing on this fid */
        u16                             src_fid;
-       u8                              dir;
-#define BNXT_DIR_RX    1
-#define BNXT_DIR_TX    0
        struct bnxt_tc_l2_key           l2_key;
        struct bnxt_tc_l2_key           l2_mask;
        struct bnxt_tc_l3_key           l3_key;
index a2b57807453b6f4c57fc53c408e488d10b217b66..d3a0b614dbfa2148d4243238bf18495bf36c456f 100644 (file)
@@ -1895,7 +1895,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
 {
        struct bcmgenet_rx_ring *ring = container_of(napi,
                        struct bcmgenet_rx_ring, napi);
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
        unsigned int work_done;
 
        work_done = bcmgenet_desc_rx(ring, budget);
index 73632b84374985cffdba907ad605499a6d71d420..b821c9e1604cff9c9b6ea412615140f293d5ee68 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "cavium_ptp.h"
 
-#define DRV_NAME       "Cavium PTP Driver"
+#define DRV_NAME "cavium_ptp"
 
 #define PCI_DEVICE_ID_CAVIUM_PTP       0xA00C
 #define PCI_DEVICE_ID_CAVIUM_RST       0xA00E
index 032224178b647e004dbf509594dbc249822d6806..6dd65f9b347cbc4573434385daaf5ad6e17e8be4 100644 (file)
@@ -237,8 +237,10 @@ int octeon_setup_iq(struct octeon_device *oct,
        }
 
        oct->num_iqs++;
-       if (oct->fn_list.enable_io_queues(oct))
+       if (oct->fn_list.enable_io_queues(oct)) {
+               octeon_delete_instr_queue(oct, iq_no);
                return 1;
+       }
 
        return 0;
 }
index ad22554857bf35df096408cea9184e5d786f7dc3..acb016834f0470ffbb9f0f79a57ef8809d2e567e 100644 (file)
@@ -1381,24 +1381,18 @@ static int acpi_get_mac_address(struct device *dev, struct acpi_device *adev,
                                u8 *dst)
 {
        u8 mac[ETH_ALEN];
-       int ret;
+       u8 *addr;
 
-       ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
-                                           "mac-address", mac, ETH_ALEN);
-       if (ret)
-               goto out;
-
-       if (!is_valid_ether_addr(mac)) {
+       addr = fwnode_get_mac_address(acpi_fwnode_handle(adev), mac, ETH_ALEN);
+       if (!addr) {
                dev_err(dev, "MAC address invalid: %pM\n", mac);
-               ret = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        dev_info(dev, "MAC address set to: %pM\n", mac);
 
-       memcpy(dst, mac, ETH_ALEN);
-out:
-       return ret;
+       ether_addr_copy(dst, mac);
+       return 0;
 }
 
 /* Currently only sets the MAC address. */
index 1e82b9efe447191799f8e5c881d32da7e7cf96ec..58f89f6a040fe39ef02d18d1fa65123d7cc7619a 100644 (file)
@@ -3269,7 +3269,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!adapter->regs) {
                dev_err(&pdev->dev, "cannot map device registers\n");
                err = -ENOMEM;
-               goto out_free_adapter;
+               goto out_free_adapter_nofail;
        }
 
        adapter->pdev = pdev;
@@ -3397,6 +3397,9 @@ out_free_dev:
                if (adapter->port[i])
                        free_netdev(adapter->port[i]);
 
+out_free_adapter_nofail:
+       kfree_skb(adapter->nofail_skb);
+
 out_free_adapter:
        kfree(adapter);
 
index 02959035ed3f21287a3673f93c55f0e76b549de1..d692251ee252c2e98bb46423002acda19829bf8f 100644 (file)
@@ -3236,8 +3236,10 @@ static ssize_t blocked_fl_write(struct file *filp, const char __user *ubuf,
                return -ENOMEM;
 
        err = bitmap_parse_user(ubuf, count, t, adap->sge.egr_sz);
-       if (err)
+       if (err) {
+               kvfree(t);
                return err;
+       }
 
        bitmap_copy(adap->sge.blocked_fl, t, adap->sge.egr_sz);
        kvfree(t);
index ef5d61d57597d25de28e5ce613f9a378a9878a06..323976c811e96f74c5f834c0fa29ddf62ff9d0e7 100644 (file)
@@ -550,7 +550,7 @@ int be_process_mcc(struct be_adapter *adapter)
        int num = 0, status = 0;
        struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
-       spin_lock(&adapter->mcc_cq_lock);
+       spin_lock_bh(&adapter->mcc_cq_lock);
 
        while ((compl = be_mcc_compl_get(adapter))) {
                if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
@@ -566,7 +566,7 @@ int be_process_mcc(struct be_adapter *adapter)
        if (num)
                be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
 
-       spin_unlock(&adapter->mcc_cq_lock);
+       spin_unlock_bh(&adapter->mcc_cq_lock);
        return status;
 }
 
@@ -581,9 +581,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
                if (be_check_error(adapter, BE_ERROR_ANY))
                        return -EIO;
 
-               local_bh_disable();
                status = be_process_mcc(adapter);
-               local_bh_enable();
 
                if (atomic_read(&mcc_obj->q.used) == 0)
                        break;
index 2edb86ec9fe9ec5945c0de54706eb79dd187d967..4d8e40ac66d23144ea8b6c864c264f9a1ee98d31 100644 (file)
@@ -5630,9 +5630,7 @@ static void be_worker(struct work_struct *work)
         * mcc completions
         */
        if (!netif_running(adapter->netdev)) {
-               local_bh_disable();
                be_process_mcc(adapter);
-               local_bh_enable();
                goto reschedule;
        }
 
index 133acca0bf31b448ac0c3f51594dbaef65ed3704..092da2d90026fab2e455f0ba9831ad2788042a74 100644 (file)
@@ -167,7 +167,7 @@ struct nps_enet_priv {
 };
 
 /**
- * nps_reg_set - Sets ENET register with provided value.
+ * nps_enet_reg_set - Sets ENET register with provided value.
  * @priv:       Pointer to EZchip ENET private data structure.
  * @reg:        Register offset from base address.
  * @value:      Value to set in register.
@@ -179,7 +179,7 @@ static inline void nps_enet_reg_set(struct nps_enet_priv *priv,
 }
 
 /**
- * nps_reg_get - Gets value of specified ENET register.
+ * nps_enet_reg_get - Gets value of specified ENET register.
  * @priv:       Pointer to EZchip ENET private data structure.
  * @reg:        Register offset from base address.
  *
index ed0d010c7cf260f0e8cfb98f8935207bfdbc9114..04a59db03f2bc93073dc6e0d8a71024f33bd7b02 100644 (file)
@@ -2,6 +2,7 @@
 config FSL_ENETC
        tristate "ENETC PF driver"
        depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+       select PHYLIB
        help
          This driver supports NXP ENETC gigabit ethernet controller PCIe
          physical function (PF) devices, managing ENETC Ports at a privileged
@@ -12,6 +13,7 @@ config FSL_ENETC
 config FSL_ENETC_VF
        tristate "ENETC VF driver"
        depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
+       select PHYLIB
        help
          This driver supports NXP ENETC gigabit ethernet controller PCIe
          virtual function (VF) devices enabled by the ENETC PF driver.
index e80fedb27cee81411019914f483590c7ec6c1871..210749bf1eac11537376244a7bd7b68740a5bba8 100644 (file)
@@ -2439,9 +2439,6 @@ MODULE_PARM_DESC(fsl_fm_rx_extra_headroom, "Extra headroom for Rx buffers");
  * buffers when not using jumbo frames.
  * Must be large enough to accommodate the network MTU, but small enough
  * to avoid wasting skb memory.
- *
- * Could be overridden once, at boot-time, via the
- * fm_set_max_frm() callback.
  */
 static int fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE;
 module_param(fsl_fm_max_frm, int, 0);
index 92372dc43be877807849fda3b90869cb5b618880..ebc37e2569221a9c6425704f3dade054ab86c9f1 100644 (file)
@@ -31,9 +31,6 @@
 struct gve_rx_desc_queue {
        struct gve_rx_desc *desc_ring; /* the descriptor ring */
        dma_addr_t bus; /* the bus for the desc_ring */
-       u32 cnt; /* free-running total number of completed packets */
-       u32 fill_cnt; /* free-running total number of descriptors posted */
-       u32 mask; /* masks the cnt to the size of the ring */
        u8 seqno; /* the next expected seqno for this desc*/
 };
 
@@ -60,8 +57,6 @@ struct gve_rx_data_queue {
        dma_addr_t data_bus; /* dma mapping of the slots */
        struct gve_rx_slot_page_info *page_info; /* page info of the buffers */
        struct gve_queue_page_list *qpl; /* qpl assigned to this queue */
-       u32 mask; /* masks the cnt to the size of the ring */
-       u32 cnt; /* free-running total number of completed packets */
 };
 
 struct gve_priv;
@@ -73,6 +68,9 @@ struct gve_rx_ring {
        struct gve_rx_data_queue data;
        u64 rbytes; /* free-running bytes received */
        u64 rpackets; /* free-running packets received */
+       u32 cnt; /* free-running total number of completed packets */
+       u32 fill_cnt; /* free-running total number of descs and buffs posted */
+       u32 mask; /* masks the cnt and fill_cnt to the size of the ring */
        u32 q_num; /* queue index */
        u32 ntfy_id; /* notification block index */
        struct gve_queue_resources *q_resources; /* head and tail pointer idx */
index 26540b8565410d558050177bec051305a4cc6891..d8fa816f44737ceed90cd731d46488dfb0ceb72a 100644 (file)
@@ -138,8 +138,8 @@ gve_get_ethtool_stats(struct net_device *netdev,
                for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
                        struct gve_rx_ring *rx = &priv->rx[ring];
 
-                       data[i++] = rx->desc.cnt;
-                       data[i++] = rx->desc.fill_cnt;
+                       data[i++] = rx->cnt;
+                       data[i++] = rx->fill_cnt;
                }
        } else {
                i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
index 1914b8350da7022434fcd70e6316bc0010bda24e..59564ac99d2a6df5c589d89521b5513f78ae16fc 100644 (file)
@@ -37,7 +37,7 @@ static void gve_rx_free_ring(struct gve_priv *priv, int idx)
        rx->data.qpl = NULL;
        kvfree(rx->data.page_info);
 
-       slots = rx->data.mask + 1;
+       slots = rx->mask + 1;
        bytes = sizeof(*rx->data.data_ring) * slots;
        dma_free_coherent(dev, bytes, rx->data.data_ring,
                          rx->data.data_bus);
@@ -64,7 +64,7 @@ static int gve_prefill_rx_pages(struct gve_rx_ring *rx)
        /* Allocate one page per Rx queue slot. Each page is split into two
         * packet buffers, when possible we "page flip" between the two.
         */
-       slots = rx->data.mask + 1;
+       slots = rx->mask + 1;
 
        rx->data.page_info = kvzalloc(slots *
                                      sizeof(*rx->data.page_info), GFP_KERNEL);
@@ -111,7 +111,7 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
        rx->q_num = idx;
 
        slots = priv->rx_pages_per_qpl;
-       rx->data.mask = slots - 1;
+       rx->mask = slots - 1;
 
        /* alloc rx data ring */
        bytes = sizeof(*rx->data.data_ring) * slots;
@@ -125,7 +125,7 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
                err = -ENOMEM;
                goto abort_with_slots;
        }
-       rx->desc.fill_cnt = filled_pages;
+       rx->fill_cnt = filled_pages;
        /* Ensure data ring slots (packet buffers) are visible. */
        dma_wmb();
 
@@ -156,8 +156,8 @@ static int gve_rx_alloc_ring(struct gve_priv *priv, int idx)
                err = -ENOMEM;
                goto abort_with_q_resources;
        }
-       rx->desc.mask = slots - 1;
-       rx->desc.cnt = 0;
+       rx->mask = slots - 1;
+       rx->cnt = 0;
        rx->desc.seqno = 1;
        gve_rx_add_to_block(priv, idx);
 
@@ -213,7 +213,7 @@ void gve_rx_write_doorbell(struct gve_priv *priv, struct gve_rx_ring *rx)
 {
        u32 db_idx = be32_to_cpu(rx->q_resources->db_index);
 
-       iowrite32be(rx->desc.fill_cnt, &priv->db_bar2[db_idx]);
+       iowrite32be(rx->fill_cnt, &priv->db_bar2[db_idx]);
 }
 
 static enum pkt_hash_types gve_rss_type(__be16 pkt_flags)
@@ -273,7 +273,7 @@ static void gve_rx_flip_buff(struct gve_rx_slot_page_info *page_info,
 }
 
 static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
-                  netdev_features_t feat)
+                  netdev_features_t feat, u32 idx)
 {
        struct gve_rx_slot_page_info *page_info;
        struct gve_priv *priv = rx->gve;
@@ -282,14 +282,12 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
        struct sk_buff *skb;
        int pagecount;
        u16 len;
-       u32 idx;
 
        /* drop this packet */
        if (unlikely(rx_desc->flags_seq & GVE_RXF_ERR))
                return true;
 
        len = be16_to_cpu(rx_desc->len) - GVE_RX_PAD;
-       idx = rx->data.cnt & rx->data.mask;
        page_info = &rx->data.page_info[idx];
 
        /* gvnic can only receive into registered segments. If the buffer
@@ -340,8 +338,6 @@ have_skb:
        if (!skb)
                return true;
 
-       rx->data.cnt++;
-
        if (likely(feat & NETIF_F_RXCSUM)) {
                /* NIC passes up the partial sum */
                if (rx_desc->csum)
@@ -370,7 +366,7 @@ static bool gve_rx_work_pending(struct gve_rx_ring *rx)
        __be16 flags_seq;
        u32 next_idx;
 
-       next_idx = rx->desc.cnt & rx->desc.mask;
+       next_idx = rx->cnt & rx->mask;
        desc = rx->desc.desc_ring + next_idx;
 
        flags_seq = desc->flags_seq;
@@ -385,8 +381,8 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
 {
        struct gve_priv *priv = rx->gve;
        struct gve_rx_desc *desc;
-       u32 cnt = rx->desc.cnt;
-       u32 idx = cnt & rx->desc.mask;
+       u32 cnt = rx->cnt;
+       u32 idx = cnt & rx->mask;
        u32 work_done = 0;
        u64 bytes = 0;
 
@@ -401,10 +397,10 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
                           rx->q_num, GVE_SEQNO(desc->flags_seq),
                           rx->desc.seqno);
                bytes += be16_to_cpu(desc->len) - GVE_RX_PAD;
-               if (!gve_rx(rx, desc, feat))
+               if (!gve_rx(rx, desc, feat, idx))
                        gve_schedule_reset(priv);
                cnt++;
-               idx = cnt & rx->desc.mask;
+               idx = cnt & rx->mask;
                desc = rx->desc.desc_ring + idx;
                rx->desc.seqno = gve_next_seqno(rx->desc.seqno);
                work_done++;
@@ -417,8 +413,8 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
        rx->rpackets += work_done;
        rx->rbytes += bytes;
        u64_stats_update_end(&rx->statss);
-       rx->desc.cnt = cnt;
-       rx->desc.fill_cnt += work_done;
+       rx->cnt = cnt;
+       rx->fill_cnt += work_done;
 
        /* restock desc ring slots */
        dma_wmb();      /* Ensure descs are visible before ringing doorbell */
index d60452845539f3acbd42cdfebc94865bf2f61e02..c84167447abe650c36186eae40343b2584ac4fbb 100644 (file)
@@ -220,6 +220,7 @@ struct hip04_priv {
        unsigned int reg_inten;
 
        struct napi_struct napi;
+       struct device *dev;
        struct net_device *ndev;
 
        struct tx_desc *tx_desc;
@@ -248,7 +249,7 @@ struct hip04_priv {
 
 static inline unsigned int tx_count(unsigned int head, unsigned int tail)
 {
-       return (head - tail) % (TX_DESC_NUM - 1);
+       return (head - tail) % TX_DESC_NUM;
 }
 
 static void hip04_config_port(struct net_device *ndev, u32 speed, u32 duplex)
@@ -465,7 +466,7 @@ static int hip04_tx_reclaim(struct net_device *ndev, bool force)
                }
 
                if (priv->tx_phys[tx_tail]) {
-                       dma_unmap_single(&ndev->dev, priv->tx_phys[tx_tail],
+                       dma_unmap_single(priv->dev, priv->tx_phys[tx_tail],
                                         priv->tx_skb[tx_tail]->len,
                                         DMA_TO_DEVICE);
                        priv->tx_phys[tx_tail] = 0;
@@ -516,8 +517,8 @@ hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                return NETDEV_TX_BUSY;
        }
 
-       phys = dma_map_single(&ndev->dev, skb->data, skb->len, DMA_TO_DEVICE);
-       if (dma_mapping_error(&ndev->dev, phys)) {
+       phys = dma_map_single(priv->dev, skb->data, skb->len, DMA_TO_DEVICE);
+       if (dma_mapping_error(priv->dev, phys)) {
                dev_kfree_skb(skb);
                return NETDEV_TX_OK;
        }
@@ -585,6 +586,9 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
        u16 len;
        u32 err;
 
+       /* clean up tx descriptors */
+       tx_remaining = hip04_tx_reclaim(ndev, false);
+
        while (cnt && !last) {
                buf = priv->rx_buf[priv->rx_head];
                skb = build_skb(buf, priv->rx_buf_size);
@@ -593,7 +597,7 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
                        goto refill;
                }
 
-               dma_unmap_single(&ndev->dev, priv->rx_phys[priv->rx_head],
+               dma_unmap_single(priv->dev, priv->rx_phys[priv->rx_head],
                                 RX_BUF_SIZE, DMA_FROM_DEVICE);
                priv->rx_phys[priv->rx_head] = 0;
 
@@ -622,9 +626,9 @@ refill:
                buf = netdev_alloc_frag(priv->rx_buf_size);
                if (!buf)
                        goto done;
-               phys = dma_map_single(&ndev->dev, buf,
+               phys = dma_map_single(priv->dev, buf,
                                      RX_BUF_SIZE, DMA_FROM_DEVICE);
-               if (dma_mapping_error(&ndev->dev, phys))
+               if (dma_mapping_error(priv->dev, phys))
                        goto done;
                priv->rx_buf[priv->rx_head] = buf;
                priv->rx_phys[priv->rx_head] = phys;
@@ -645,8 +649,7 @@ refill:
        }
        napi_complete_done(napi, rx);
 done:
-       /* clean up tx descriptors and start a new timer if necessary */
-       tx_remaining = hip04_tx_reclaim(ndev, false);
+       /* start a new timer if necessary */
        if (rx < budget && tx_remaining)
                hip04_start_tx_timer(priv);
 
@@ -728,9 +731,9 @@ static int hip04_mac_open(struct net_device *ndev)
        for (i = 0; i < RX_DESC_NUM; i++) {
                dma_addr_t phys;
 
-               phys = dma_map_single(&ndev->dev, priv->rx_buf[i],
+               phys = dma_map_single(priv->dev, priv->rx_buf[i],
                                      RX_BUF_SIZE, DMA_FROM_DEVICE);
-               if (dma_mapping_error(&ndev->dev, phys))
+               if (dma_mapping_error(priv->dev, phys))
                        return -EIO;
 
                priv->rx_phys[i] = phys;
@@ -764,7 +767,7 @@ static int hip04_mac_stop(struct net_device *ndev)
 
        for (i = 0; i < RX_DESC_NUM; i++) {
                if (priv->rx_phys[i]) {
-                       dma_unmap_single(&ndev->dev, priv->rx_phys[i],
+                       dma_unmap_single(priv->dev, priv->rx_phys[i],
                                         RX_BUF_SIZE, DMA_FROM_DEVICE);
                        priv->rx_phys[i] = 0;
                }
@@ -907,6 +910,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        priv = netdev_priv(ndev);
+       priv->dev = d;
        priv->ndev = ndev;
        platform_set_drvdata(pdev, ndev);
        SET_NETDEV_DEV(ndev, &pdev->dev);
index 4138a84803478a5b0b3ad9c7adce1e0e51f28cb3..cca71ba7a74a02b72d3c188368d6197278864243 100644 (file)
@@ -3251,7 +3251,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
        switch (action) {
        case MEM_CANCEL_OFFLINE:
                pr_info("memory offlining canceled");
-               /* Fall through: re-add canceled memory block */
+               /* Fall through - re-add canceled memory block */
 
        case MEM_ONLINE:
                pr_info("memory is going online");
index d654c234aaf75364416d3a1eadfa4fb8fa6924ba..c5be4ebd84373ec9ff8ade34b4bae3031e937652 100644 (file)
@@ -1605,7 +1605,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
        struct net_device *netdev;
        struct ibmveth_adapter *adapter;
        unsigned char *mac_addr_p;
-       unsigned int *mcastFilterSize_p;
+       __be32 *mcastFilterSize_p;
        long ret;
        unsigned long ret_attr;
 
@@ -1627,8 +1627,9 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
                return -EINVAL;
        }
 
-       mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev,
-                                               VETH_MCAST_FILTER_SIZE, NULL);
+       mcastFilterSize_p = (__be32 *)vio_get_attribute(dev,
+                                                       VETH_MCAST_FILTER_SIZE,
+                                                       NULL);
        if (!mcastFilterSize_p) {
                dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE "
                        "attribute\n");
@@ -1645,7 +1646,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        adapter->vdev = dev;
        adapter->netdev = netdev;
-       adapter->mcastFilterSize = *mcastFilterSize_p;
+       adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p);
        adapter->pool_config = 0;
 
        netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
index 3da6800732656477bd5d932373dde23d1b4dde9c..cebd20f3128d4a6c6344c94b80496875e091d8d7 100644 (file)
@@ -1568,6 +1568,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
                                               (u64)tx_buff->indir_dma,
                                               (u64)num_entries);
+               dma_unmap_single(dev, tx_buff->indir_dma,
+                                sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
        } else {
                tx_buff->num_entries = num_entries;
                lpar_rc = send_subcrq(adapter, handle_array[queue_num],
@@ -2788,7 +2790,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
        union sub_crq *next;
        int index;
        int i, j;
-       u8 *first;
 
 restart_loop:
        while (pending_scrq(adapter, scrq)) {
@@ -2818,14 +2819,6 @@ restart_loop:
 
                                txbuff->data_dma[j] = 0;
                        }
-                       /* if sub_crq was sent indirectly */
-                       first = &txbuff->indir_arr[0].generic.first;
-                       if (*first == IBMVNIC_CRQ_CMD) {
-                               dma_unmap_single(dev, txbuff->indir_dma,
-                                                sizeof(txbuff->indir_arr),
-                                                DMA_TO_DEVICE);
-                               *first = 0;
-                       }
 
                        if (txbuff->last_frag) {
                                dev_kfree_skb_any(txbuff->skb);
index cbaf712d6529bf0e1d20289c8d0d4a0466b79623..7882148abb4320ccf3a979b565fa93990366f991 100644 (file)
@@ -7897,11 +7897,8 @@ static void ixgbe_service_task(struct work_struct *work)
                return;
        }
        if (ixgbe_check_fw_error(adapter)) {
-               if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
-                       rtnl_lock();
+               if (!test_bit(__IXGBE_DOWN, &adapter->state))
                        unregister_netdev(adapter->netdev);
-                       rtnl_unlock();
-               }
                ixgbe_service_event_complete(adapter);
                return;
        }
index f660cc2b82583fdc6d20cd1e0761dc71b294603b..0b9e851f3da4fb1a37989e1aed311a5ad282353f 100644 (file)
@@ -319,20 +319,33 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
        init_waitqueue_head(&dev->smi_busy_wait);
 
-       for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
-               dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
-               if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
+       if (pdev->dev.of_node) {
+               for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
+                       dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
+                       if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
+                               ret = -EPROBE_DEFER;
+                               goto out_clk;
+                       }
+                       if (IS_ERR(dev->clk[i]))
+                               break;
+                       clk_prepare_enable(dev->clk[i]);
+               }
+
+               if (!IS_ERR(of_clk_get(pdev->dev.of_node,
+                                      ARRAY_SIZE(dev->clk))))
+                       dev_warn(&pdev->dev,
+                                "unsupported number of clocks, limiting to the first "
+                                __stringify(ARRAY_SIZE(dev->clk)) "\n");
+       } else {
+               dev->clk[0] = clk_get(&pdev->dev, NULL);
+               if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
                        ret = -EPROBE_DEFER;
                        goto out_clk;
                }
-               if (IS_ERR(dev->clk[i]))
-                       break;
-               clk_prepare_enable(dev->clk[i]);
+               if (!IS_ERR(dev->clk[0]))
+                       clk_prepare_enable(dev->clk[0]);
        }
 
-       if (!IS_ERR(of_clk_get(pdev->dev.of_node, ARRAY_SIZE(dev->clk))))
-               dev_warn(&pdev->dev, "unsupported number of clocks, limiting to the first "
-                        __stringify(ARRAY_SIZE(dev->clk)) "\n");
 
        dev->err_interrupt = platform_get_irq(pdev, 0);
        if (dev->err_interrupt > 0 &&
index c51f1d5b550b1131d18fc7240e5503d461c43f4f..ccdd47f3b8fb5dbf474e2086711b2569f62a46bd 100644 (file)
@@ -811,6 +811,26 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
        return 0;
 }
 
+static void mvpp2_set_hw_csum(struct mvpp2_port *port,
+                             enum mvpp2_bm_pool_log_num new_long_pool)
+{
+       const netdev_features_t csums = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+       /* Update L4 checksum when jumbo enable/disable on port.
+        * Only port 0 supports hardware checksum offload due to
+        * the Tx FIFO size limitation.
+        * Also, don't set NETIF_F_HW_CSUM because L3_offset in TX descriptor
+        * has 7 bits, so the maximum L3 offset is 128.
+        */
+       if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
+               port->dev->features &= ~csums;
+               port->dev->hw_features &= ~csums;
+       } else {
+               port->dev->features |= csums;
+               port->dev->hw_features |= csums;
+       }
+}
+
 static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
 {
        struct mvpp2_port *port = netdev_priv(dev);
@@ -843,15 +863,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
                /* Add port to new short & long pool */
                mvpp2_swf_bm_pool_init(port);
 
-               /* Update L4 checksum when jumbo enable/disable on port */
-               if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
-                       dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-                       dev->hw_features &= ~(NETIF_F_IP_CSUM |
-                                             NETIF_F_IPV6_CSUM);
-               } else {
-                       dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-                       dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-               }
+               mvpp2_set_hw_csum(port, new_long_pool);
        }
 
        dev->mtu = mtu;
@@ -3700,6 +3712,7 @@ static int mvpp2_set_mac_address(struct net_device *dev, void *p)
 static int mvpp2_change_mtu(struct net_device *dev, int mtu)
 {
        struct mvpp2_port *port = netdev_priv(dev);
+       bool running = netif_running(dev);
        int err;
 
        if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
@@ -3708,40 +3721,24 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu)
                mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
        }
 
-       if (!netif_running(dev)) {
-               err = mvpp2_bm_update_mtu(dev, mtu);
-               if (!err) {
-                       port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
-                       return 0;
-               }
-
-               /* Reconfigure BM to the original MTU */
-               err = mvpp2_bm_update_mtu(dev, dev->mtu);
-               if (err)
-                       goto log_error;
-       }
-
-       mvpp2_stop_dev(port);
+       if (running)
+               mvpp2_stop_dev(port);
 
        err = mvpp2_bm_update_mtu(dev, mtu);
-       if (!err) {
+       if (err) {
+               netdev_err(dev, "failed to change MTU\n");
+               /* Reconfigure BM to the original MTU */
+               mvpp2_bm_update_mtu(dev, dev->mtu);
+       } else {
                port->pkt_size =  MVPP2_RX_PKT_SIZE(mtu);
-               goto out_start;
        }
 
-       /* Reconfigure BM to the original MTU */
-       err = mvpp2_bm_update_mtu(dev, dev->mtu);
-       if (err)
-               goto log_error;
-
-out_start:
-       mvpp2_start_dev(port);
-       mvpp2_egress_enable(port);
-       mvpp2_ingress_enable(port);
+       if (running) {
+               mvpp2_start_dev(port);
+               mvpp2_egress_enable(port);
+               mvpp2_ingress_enable(port);
+       }
 
-       return 0;
-log_error:
-       netdev_err(dev, "failed to change MTU\n");
        return err;
 }
 
@@ -4739,9 +4736,9 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
        else
                ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
 
-       ctrl4 &= ~MVPP22_XLG_CTRL4_MACMODSELECT_GMAC;
-       ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC |
-                MVPP22_XLG_CTRL4_EN_IDLE_CHECK;
+       ctrl4 &= ~(MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
+                  MVPP22_XLG_CTRL4_EN_IDLE_CHECK);
+       ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC;
 
        if (old_ctrl0 != ctrl0)
                writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
@@ -5208,10 +5205,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
                dev->features |= NETIF_F_NTUPLE;
        }
 
-       if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) {
-               dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-               dev->hw_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-       }
+       mvpp2_set_hw_csum(port, port->pool_long->id);
 
        dev->vlan_features |= features;
        dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
@@ -5759,9 +5753,6 @@ static int mvpp2_remove(struct platform_device *pdev)
 
        mvpp2_dbgfs_cleanup(priv);
 
-       flush_workqueue(priv->stats_queue);
-       destroy_workqueue(priv->stats_queue);
-
        fwnode_for_each_available_child_node(fwnode, port_fwnode) {
                if (priv->port_list[i]) {
                        mutex_destroy(&priv->port_list[i]->gather_stats_lock);
@@ -5770,6 +5761,8 @@ static int mvpp2_remove(struct platform_device *pdev)
                i++;
        }
 
+       destroy_workqueue(priv->stats_queue);
+
        for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
                struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
 
index f518312ffe695470bf1dd4239d9e2b1b08e5ea54..a01c75ede871a378ac6e32e7b939c4bdd1d112a6 100644 (file)
@@ -4924,6 +4924,13 @@ static const struct dmi_system_id msi_blacklist[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "P5W DH Deluxe"),
                },
        },
+       {
+               .ident = "ASUS P6T",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "P6T"),
+               },
+       },
        {}
 };
 
index 263cd0909fe0de39eb6d48c39e194f904b39b846..1f7fff81f24dbb96a964326ae0a306315198afa2 100644 (file)
@@ -9,7 +9,6 @@ if NET_VENDOR_MEDIATEK
 
 config NET_MEDIATEK_SOC
        tristate "MediaTek SoC Gigabit Ethernet support"
-       depends on NET_VENDOR_MEDIATEK
        select PHYLIB
        ---help---
          This driver supports the gigabit ethernet MACs in the
index 6c01314e87b09716ca076cbe4a91621b9e474fba..db3552f2d0877e37ce8dcf215d4c273e91c2326c 100644 (file)
@@ -1187,7 +1187,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
        err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, rss_map->indir_qp);
        if (err) {
                en_err(priv, "Failed to allocate RSS indirection QP\n");
-               goto rss_err;
+               goto qp_alloc_err;
        }
 
        rss_map->indir_qp->event = mlx4_en_sqp_event;
@@ -1241,6 +1241,7 @@ indir_err:
                       MLX4_QP_STATE_RST, NULL, 0, 0, rss_map->indir_qp);
        mlx4_qp_remove(mdev->dev, rss_map->indir_qp);
        mlx4_qp_free(mdev->dev, rss_map->indir_qp);
+qp_alloc_err:
        kfree(rss_map->indir_qp);
        rss_map->indir_qp = NULL;
 rss_err:
index 5bb6a26ea2672ea3ce25a8ddd6750be2ecb7733a..50862275544e52cd0610831694f8c415e1da8ed0 100644 (file)
@@ -213,7 +213,7 @@ void mlx5_unregister_device(struct mlx5_core_dev *dev)
        struct mlx5_interface *intf;
 
        mutex_lock(&mlx5_intf_mutex);
-       list_for_each_entry(intf, &intf_list, list)
+       list_for_each_entry_reverse(intf, &intf_list, list)
                mlx5_remove_device(intf, priv);
        list_del(&priv->dev_list);
        mutex_unlock(&mlx5_intf_mutex);
index 79d93d6c7d7a7fc2175d53052108a411bd3960c6..65bec19a438f15c5db9f0e0d28bd3ac53a7a0c83 100644 (file)
@@ -159,7 +159,7 @@ do {                                                            \
 enum mlx5e_rq_group {
        MLX5E_RQ_GROUP_REGULAR,
        MLX5E_RQ_GROUP_XSK,
-       MLX5E_NUM_RQ_GROUPS /* Keep last. */
+#define MLX5E_NUM_RQ_GROUPS(g) (1 + MLX5E_RQ_GROUP_##g)
 };
 
 static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size)
@@ -182,18 +182,15 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
                min_t(int, mlx5_comp_vectors_count(mdev), MLX5E_MAX_NUM_CHANNELS);
 }
 
-/* Use this function to get max num channels after netdev was created */
-static inline int mlx5e_get_netdev_max_channels(struct net_device *netdev)
-{
-       return min_t(unsigned int,
-                    netdev->num_rx_queues / MLX5E_NUM_RQ_GROUPS,
-                    netdev->num_tx_queues);
-}
-
 struct mlx5e_tx_wqe {
        struct mlx5_wqe_ctrl_seg ctrl;
-       struct mlx5_wqe_eth_seg  eth;
-       struct mlx5_wqe_data_seg data[0];
+       union {
+               struct {
+                       struct mlx5_wqe_eth_seg  eth;
+                       struct mlx5_wqe_data_seg data[0];
+               };
+               u8 tls_progress_params_ctx[0];
+       };
 };
 
 struct mlx5e_rx_wqe_ll {
@@ -830,6 +827,7 @@ struct mlx5e_priv {
        struct net_device         *netdev;
        struct mlx5e_stats         stats;
        struct mlx5e_channel_stats channel_stats[MLX5E_MAX_NUM_CHANNELS];
+       u16                        max_nch;
        u8                         max_opened_tc;
        struct hwtstamp_config     tstamp;
        u16                        q_counter;
@@ -871,6 +869,7 @@ struct mlx5e_profile {
                mlx5e_fp_handle_rx_cqe handle_rx_cqe_mpwqe;
        } rx_handlers;
        int     max_tc;
+       u8      rq_groups;
 };
 
 void mlx5e_build_ptys2ethtool_map(void);
@@ -1106,6 +1105,8 @@ u32 mlx5e_ethtool_get_rxfh_key_size(struct mlx5e_priv *priv);
 u32 mlx5e_ethtool_get_rxfh_indir_size(struct mlx5e_priv *priv);
 int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
                              struct ethtool_ts_info *info);
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+                              struct ethtool_flash *flash);
 void mlx5e_ethtool_get_pauseparam(struct mlx5e_priv *priv,
                                  struct ethtool_pauseparam *pauseparam);
 int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
index bd882b5ee9a746f7a6ccca891835b167a19d1ccb..3a615d663d84ec51c2142514bdbfde897cb18f2d 100644 (file)
@@ -66,9 +66,10 @@ static inline void mlx5e_qid_get_ch_and_group(struct mlx5e_params *params,
        *group = qid / nch;
 }
 
-static inline bool mlx5e_qid_validate(struct mlx5e_params *params, u64 qid)
+static inline bool mlx5e_qid_validate(const struct mlx5e_profile *profile,
+                                     struct mlx5e_params *params, u64 qid)
 {
-       return qid < params->num_channels * MLX5E_NUM_RQ_GROUPS;
+       return qid < params->num_channels * profile->rq_groups;
 }
 
 /* Parameter calculations */
index d5e5afbdca6dcbacb776571c97eef74e033cf356..f777994f3005ea2b68b707bbadb0440ecb9c51e9 100644 (file)
@@ -78,9 +78,10 @@ static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
 };
 
 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
-                                    const u32 **arr, u32 *size)
+                                    const u32 **arr, u32 *size,
+                                    bool force_legacy)
 {
-       bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+       bool ext = force_legacy ? false : MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
 
        *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
                      ARRAY_SIZE(mlx5e_link_speed);
@@ -152,7 +153,8 @@ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
                            sizeof(out), MLX5_REG_PTYS, 0, 1);
 }
 
-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
+                         bool force_legacy)
 {
        unsigned long temp = eth_proto_oper;
        const u32 *table;
@@ -160,7 +162,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
        u32 max_size;
        int i;
 
-       mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+       mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
        i = find_first_bit(&temp, max_size);
        if (i < max_size)
                speed = table[i];
@@ -170,6 +172,7 @@ u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
 {
        struct mlx5e_port_eth_proto eproto;
+       bool force_legacy = false;
        bool ext;
        int err;
 
@@ -177,8 +180,13 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
        if (err)
                goto out;
-
-       *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
+       if (ext && !eproto.admin) {
+               force_legacy = true;
+               err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
+               if (err)
+                       goto out;
+       }
+       *speed = mlx5e_port_ptys2speed(mdev, eproto.oper, force_legacy);
        if (!(*speed))
                err = -EINVAL;
 
@@ -201,7 +209,7 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        if (err)
                return err;
 
-       mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+       mlx5e_port_get_speed_arr(mdev, &table, &max_size, false);
        for (i = 0; i < max_size; ++i)
                if (eproto.cap & MLX5E_PROT_MASK(i))
                        max_speed = max(max_speed, table[i]);
@@ -210,14 +218,15 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
        return 0;
 }
 
-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
+                              bool force_legacy)
 {
        u32 link_modes = 0;
        const u32 *table;
        u32 max_size;
        int i;
 
-       mlx5e_port_get_speed_arr(mdev, &table, &max_size);
+       mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy);
        for (i = 0; i < max_size; ++i) {
                if (table[i] == speed)
                        link_modes |= MLX5E_PROT_MASK(i);
index 70f536ec51c47523b76070a1f0971de668698b1d..4a7f4497692bc7655ce6852cc497807a935e6a59 100644 (file)
@@ -48,10 +48,12 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
                                 u8 *an_disable_cap, u8 *an_disable_admin);
 int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
                           u32 proto_admin, bool ext);
-u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper);
+u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper,
+                         bool force_legacy);
 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
-u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed);
+u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
+                              bool force_legacy);
 
 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
index f3d98748b2117575ad64c83b2bb962ec7a718786..c7f86453c63843c619d6fdad7d078c0ec2acacd3 100644 (file)
@@ -76,26 +76,21 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
        u8 state;
        int err;
 
-       if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state))
-               return 0;
-
        err = mlx5_core_query_sq_state(mdev, sq->sqn, &state);
        if (err) {
                netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n",
                           sq->sqn, err);
-               return err;
+               goto out;
        }
 
-       if (state != MLX5_SQC_STATE_ERR) {
-               netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn);
-               return -EINVAL;
-       }
+       if (state != MLX5_SQC_STATE_ERR)
+               goto out;
 
        mlx5e_tx_disable_queue(sq->txq);
 
        err = mlx5e_wait_for_sq_flush(sq);
        if (err)
-               return err;
+               goto out;
 
        /* At this point, no new packets will arrive from the stack as TXQ is
         * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all
@@ -104,13 +99,17 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq)
 
        err = mlx5e_sq_to_ready(sq, state);
        if (err)
-               return err;
+               goto out;
 
        mlx5e_reset_txqsq_cc_pc(sq);
        sq->stats->recover++;
+       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
        mlx5e_activate_txqsq(sq);
 
        return 0;
+out:
+       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
+       return err;
 }
 
 static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter,
index aaffa6f68dc01c161999896175ea21661be33d81..7f78c004d12f767b2d8f78b281261bebc9bc3557 100644 (file)
@@ -143,7 +143,10 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c)
 {
        set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
        /* TX queue is created active. */
+
+       spin_lock(&c->xskicosq_lock);
        mlx5e_trigger_irq(&c->xskicosq);
+       spin_unlock(&c->xskicosq_lock);
 }
 
 void mlx5e_deactivate_xsk(struct mlx5e_channel *c)
index 407da83474efa08a6c73e74fdebbe58503ff3e3b..b7298f9ee3d3f7d7a2adcb5cd2895d5ab2a0d78f 100644 (file)
 #include "accel/tls.h"
 
 #define MLX5E_KTLS_STATIC_UMR_WQE_SZ \
-       (sizeof(struct mlx5e_umr_wqe) + MLX5_ST_SZ_BYTES(tls_static_params))
+       (offsetof(struct mlx5e_umr_wqe, tls_static_params_ctx) + \
+        MLX5_ST_SZ_BYTES(tls_static_params))
 #define MLX5E_KTLS_STATIC_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_BB))
 
 #define MLX5E_KTLS_PROGRESS_WQE_SZ \
-       (sizeof(struct mlx5e_tx_wqe) + MLX5_ST_SZ_BYTES(tls_progress_params))
+       (offsetof(struct mlx5e_tx_wqe, tls_progress_params_ctx) + \
+        MLX5_ST_SZ_BYTES(tls_progress_params))
 #define MLX5E_KTLS_PROGRESS_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
 #define MLX5E_KTLS_MAX_DUMP_WQEBBS 2
index ea032f54197e17a8b829d4b6b37a24573fe7237e..8b93101e1a09b633bb4f84c932ee3b6207f5895d 100644 (file)
@@ -69,7 +69,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
        cseg->qpn_ds           = cpu_to_be32((sqn << MLX5_WQE_CTRL_QPN_SHIFT) |
                                             STATIC_PARAMS_DS_CNT);
        cseg->fm_ce_se         = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
-       cseg->imm              = cpu_to_be32(priv_tx->tisn);
+       cseg->tisn             = cpu_to_be32(priv_tx->tisn << 8);
 
        ucseg->flags = MLX5_UMR_INLINE;
        ucseg->bsf_octowords = cpu_to_be16(MLX5_ST_SZ_BYTES(tls_static_params) / 16);
@@ -80,7 +80,7 @@ build_static_params(struct mlx5e_umr_wqe *wqe, u16 pc, u32 sqn,
 static void
 fill_progress_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
 {
-       MLX5_SET(tls_progress_params, ctx, pd, priv_tx->tisn);
+       MLX5_SET(tls_progress_params, ctx, tisn, priv_tx->tisn);
        MLX5_SET(tls_progress_params, ctx, record_tracker_state,
                 MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START);
        MLX5_SET(tls_progress_params, ctx, auth_state,
@@ -104,7 +104,7 @@ build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn,
                                             PROGRESS_PARAMS_DS_CNT);
        cseg->fm_ce_se         = fence ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
 
-       fill_progress_params_ctx(wqe->data, priv_tx);
+       fill_progress_params_ctx(wqe->tls_progress_params_ctx, priv_tx);
 }
 
 static void tx_fill_wi(struct mlx5e_txqsq *sq,
@@ -278,7 +278,7 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, struct sk_buff *skb,
 
        cseg->opmod_idx_opcode = cpu_to_be32((sq->pc << 8)  | MLX5_OPCODE_DUMP);
        cseg->qpn_ds           = cpu_to_be32((sq->sqn << 8) | ds_cnt);
-       cseg->imm              = cpu_to_be32(tisn);
+       cseg->tisn             = cpu_to_be32(tisn << 8);
        cseg->fm_ce_se         = first ? MLX5_FENCE_MODE_INITIATOR_SMALL : 0;
 
        eseg->inline_hdr.sz = cpu_to_be16(ihs);
@@ -412,7 +412,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
                goto out;
 
        tls_ctx = tls_get_ctx(skb->sk);
-       if (unlikely(tls_ctx->netdev != netdev))
+       if (unlikely(WARN_ON_ONCE(tls_ctx->netdev != netdev)))
                goto err_out;
 
        priv_tx = mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
@@ -434,7 +434,7 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
        priv_tx->expected_seq = seq + datalen;
 
        cseg = &(*wqe)->ctrl;
-       cseg->imm = cpu_to_be32(priv_tx->tisn);
+       cseg->tisn = cpu_to_be32(priv_tx->tisn << 8);
 
        stats->tls_encrypted_packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
        stats->tls_encrypted_bytes   += datalen;
index 8657e0f26995b442545dabd3b7b8d5b299b5a380..2c75b2752f58de0e7d0c3e9760736d7ee8035211 100644 (file)
@@ -437,12 +437,6 @@ arfs_hash_bucket(struct arfs_table *arfs_t, __be16 src_port,
        return &arfs_t->rules_hash[bucket_idx];
 }
 
-static u8 arfs_get_ip_proto(const struct sk_buff *skb)
-{
-       return (skb->protocol == htons(ETH_P_IP)) ?
-               ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr;
-}
-
 static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
                                         u8 ip_proto, __be16 etype)
 {
@@ -602,31 +596,9 @@ out:
        arfs_may_expire_flow(priv);
 }
 
-/* return L4 destination port from ip4/6 packets */
-static __be16 arfs_get_dst_port(const struct sk_buff *skb)
-{
-       char *transport_header;
-
-       transport_header = skb_transport_header(skb);
-       if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
-               return ((struct tcphdr *)transport_header)->dest;
-       return ((struct udphdr *)transport_header)->dest;
-}
-
-/* return L4 source port from ip4/6 packets */
-static __be16 arfs_get_src_port(const struct sk_buff *skb)
-{
-       char *transport_header;
-
-       transport_header = skb_transport_header(skb);
-       if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
-               return ((struct tcphdr *)transport_header)->source;
-       return ((struct udphdr *)transport_header)->source;
-}
-
 static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
                                         struct arfs_table *arfs_t,
-                                        const struct sk_buff *skb,
+                                        const struct flow_keys *fk,
                                         u16 rxq, u32 flow_id)
 {
        struct arfs_rule *rule;
@@ -641,19 +613,19 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        INIT_WORK(&rule->arfs_work, arfs_handle_work);
 
        tuple = &rule->tuple;
-       tuple->etype = skb->protocol;
+       tuple->etype = fk->basic.n_proto;
+       tuple->ip_proto = fk->basic.ip_proto;
        if (tuple->etype == htons(ETH_P_IP)) {
-               tuple->src_ipv4 = ip_hdr(skb)->saddr;
-               tuple->dst_ipv4 = ip_hdr(skb)->daddr;
+               tuple->src_ipv4 = fk->addrs.v4addrs.src;
+               tuple->dst_ipv4 = fk->addrs.v4addrs.dst;
        } else {
-               memcpy(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
+               memcpy(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
                       sizeof(struct in6_addr));
-               memcpy(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
+               memcpy(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
                       sizeof(struct in6_addr));
        }
-       tuple->ip_proto = arfs_get_ip_proto(skb);
-       tuple->src_port = arfs_get_src_port(skb);
-       tuple->dst_port = arfs_get_dst_port(skb);
+       tuple->src_port = fk->ports.src;
+       tuple->dst_port = fk->ports.dst;
 
        rule->flow_id = flow_id;
        rule->filter_id = priv->fs.arfs.last_filter_id++ % RPS_NO_FILTER;
@@ -664,37 +636,33 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        return rule;
 }
 
-static bool arfs_cmp_ips(struct arfs_tuple *tuple,
-                        const struct sk_buff *skb)
+static bool arfs_cmp(const struct arfs_tuple *tuple, const struct flow_keys *fk)
 {
-       if (tuple->etype == htons(ETH_P_IP) &&
-           tuple->src_ipv4 == ip_hdr(skb)->saddr &&
-           tuple->dst_ipv4 == ip_hdr(skb)->daddr)
-               return true;
-       if (tuple->etype == htons(ETH_P_IPV6) &&
-           (!memcmp(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
-                    sizeof(struct in6_addr))) &&
-           (!memcmp(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
-                    sizeof(struct in6_addr))))
-               return true;
+       if (tuple->src_port != fk->ports.src || tuple->dst_port != fk->ports.dst)
+               return false;
+       if (tuple->etype != fk->basic.n_proto)
+               return false;
+       if (tuple->etype == htons(ETH_P_IP))
+               return tuple->src_ipv4 == fk->addrs.v4addrs.src &&
+                      tuple->dst_ipv4 == fk->addrs.v4addrs.dst;
+       if (tuple->etype == htons(ETH_P_IPV6))
+               return !memcmp(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
+                              sizeof(struct in6_addr)) &&
+                      !memcmp(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
+                              sizeof(struct in6_addr));
        return false;
 }
 
 static struct arfs_rule *arfs_find_rule(struct arfs_table *arfs_t,
-                                       const struct sk_buff *skb)
+                                       const struct flow_keys *fk)
 {
        struct arfs_rule *arfs_rule;
        struct hlist_head *head;
-       __be16 src_port = arfs_get_src_port(skb);
-       __be16 dst_port = arfs_get_dst_port(skb);
 
-       head = arfs_hash_bucket(arfs_t, src_port, dst_port);
+       head = arfs_hash_bucket(arfs_t, fk->ports.src, fk->ports.dst);
        hlist_for_each_entry(arfs_rule, head, hlist) {
-               if (arfs_rule->tuple.src_port == src_port &&
-                   arfs_rule->tuple.dst_port == dst_port &&
-                   arfs_cmp_ips(&arfs_rule->tuple, skb)) {
+               if (arfs_cmp(&arfs_rule->tuple, fk))
                        return arfs_rule;
-               }
        }
 
        return NULL;
@@ -707,20 +675,24 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
        struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
        struct arfs_table *arfs_t;
        struct arfs_rule *arfs_rule;
+       struct flow_keys fk;
+
+       if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+               return -EPROTONOSUPPORT;
 
-       if (skb->protocol != htons(ETH_P_IP) &&
-           skb->protocol != htons(ETH_P_IPV6))
+       if (fk.basic.n_proto != htons(ETH_P_IP) &&
+           fk.basic.n_proto != htons(ETH_P_IPV6))
                return -EPROTONOSUPPORT;
 
        if (skb->encapsulation)
                return -EPROTONOSUPPORT;
 
-       arfs_t = arfs_get_table(arfs, arfs_get_ip_proto(skb), skb->protocol);
+       arfs_t = arfs_get_table(arfs, fk.basic.ip_proto, fk.basic.n_proto);
        if (!arfs_t)
                return -EPROTONOSUPPORT;
 
        spin_lock_bh(&arfs->arfs_lock);
-       arfs_rule = arfs_find_rule(arfs_t, skb);
+       arfs_rule = arfs_find_rule(arfs_t, &fk);
        if (arfs_rule) {
                if (arfs_rule->rxq == rxq_index) {
                        spin_unlock_bh(&arfs->arfs_lock);
@@ -728,8 +700,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                }
                arfs_rule->rxq = rxq_index;
        } else {
-               arfs_rule = arfs_alloc_rule(priv, arfs_t, skb,
-                                           rxq_index, flow_id);
+               arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id);
                if (!arfs_rule) {
                        spin_unlock_bh(&arfs->arfs_lock);
                        return -ENOMEM;
index 126ec41812865d99b8d32ea0ca9c2908d68763ca..20e628c907e53a3020c211575e059ab800c22e50 100644 (file)
@@ -391,7 +391,7 @@ void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv,
 {
        mutex_lock(&priv->state_lock);
 
-       ch->max_combined   = mlx5e_get_netdev_max_channels(priv->netdev);
+       ch->max_combined   = priv->max_nch;
        ch->combined_count = priv->channels.params.num_channels;
        if (priv->xsk.refcnt) {
                /* The upper half are XSK queues. */
@@ -785,7 +785,7 @@ static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings
 }
 
 static void get_speed_duplex(struct net_device *netdev,
-                            u32 eth_proto_oper,
+                            u32 eth_proto_oper, bool force_legacy,
                             struct ethtool_link_ksettings *link_ksettings)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -795,7 +795,7 @@ static void get_speed_duplex(struct net_device *netdev,
        if (!netif_carrier_ok(netdev))
                goto out;
 
-       speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
+       speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper, force_legacy);
        if (!speed) {
                speed = SPEED_UNKNOWN;
                goto out;
@@ -914,8 +914,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        /* Fields: eth_proto_admin and ext_eth_proto_admin  are
         * mutually exclusive. Hence try reading legacy advertising
         * when extended advertising is zero.
-        * admin_ext indicates how eth_proto_admin should be
-        * interpreted
+        * admin_ext indicates which proto_admin (ext vs. legacy)
+        * should be read and interpreted
         */
        admin_ext = ext;
        if (ext && !eth_proto_admin) {
@@ -924,7 +924,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
                admin_ext = false;
        }
 
-       eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
+       eth_proto_oper   = MLX5_GET_ETH_PROTO(ptys_reg, out, admin_ext,
                                              eth_proto_oper);
        eth_proto_lp        = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
        an_disable_admin    = MLX5_GET(ptys_reg, out, an_disable_admin);
@@ -939,7 +939,8 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        get_supported(mdev, eth_proto_cap, link_ksettings);
        get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings,
                        admin_ext);
-       get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings);
+       get_speed_duplex(priv->netdev, eth_proto_oper, !admin_ext,
+                        link_ksettings);
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 
@@ -1016,45 +1017,77 @@ static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes)
        return ptys_modes;
 }
 
+static bool ext_link_mode_requested(const unsigned long *adver)
+{
+#define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
+       int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT;
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(modes);
+
+       bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size);
+       return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
+}
+
+static bool ext_speed_requested(u32 speed)
+{
+#define MLX5E_MAX_PTYS_LEGACY_SPEED 100000
+       return !!(speed > MLX5E_MAX_PTYS_LEGACY_SPEED);
+}
+
+static bool ext_requested(u8 autoneg, const unsigned long *adver, u32 speed)
+{
+       bool ext_link_mode = ext_link_mode_requested(adver);
+       bool ext_speed = ext_speed_requested(speed);
+
+       return  autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_speed;
+}
+
 int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
                                     const struct ethtool_link_ksettings *link_ksettings)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_port_eth_proto eproto;
+       const unsigned long *adver;
        bool an_changes = false;
        u8 an_disable_admin;
        bool ext_supported;
-       bool ext_requested;
        u8 an_disable_cap;
        bool an_disable;
        u32 link_modes;
        u8 an_status;
+       u8 autoneg;
        u32 speed;
+       bool ext;
        int err;
 
        u32 (*ethtool2ptys_adver_func)(const unsigned long *adver);
 
-#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1)
+       adver = link_ksettings->link_modes.advertising;
+       autoneg = link_ksettings->base.autoneg;
+       speed = link_ksettings->base.speed;
 
-       ext_requested = !!(link_ksettings->link_modes.advertising[0] >
-                       MLX5E_PTYS_EXT ||
-                       link_ksettings->link_modes.advertising[1]);
+       ext = ext_requested(autoneg, adver, speed),
        ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
-       ext_requested &= ext_supported;
+       if (!ext_supported && ext)
+               return -EOPNOTSUPP;
 
-       speed = link_ksettings->base.speed;
-       ethtool2ptys_adver_func = ext_requested ?
-                                 mlx5e_ethtool2ptys_ext_adver_link :
+       ethtool2ptys_adver_func = ext ? mlx5e_ethtool2ptys_ext_adver_link :
                                  mlx5e_ethtool2ptys_adver_link;
-       err = mlx5_port_query_eth_proto(mdev, 1, ext_requested, &eproto);
+       err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
        if (err) {
                netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
                           __func__, err);
                goto out;
        }
-       link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
-               ethtool2ptys_adver_func(link_ksettings->link_modes.advertising) :
-               mlx5e_port_speed2linkmodes(mdev, speed);
+       link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
+               mlx5e_port_speed2linkmodes(mdev, speed, !ext);
+
+       if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
+           autoneg != AUTONEG_ENABLE) {
+               netdev_err(priv->netdev, "%s: 56G link speed requires autoneg enabled\n",
+                          __func__);
+               err = -EINVAL;
+               goto out;
+       }
 
        link_modes = link_modes & eproto.cap;
        if (!link_modes) {
@@ -1067,14 +1100,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
        mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap,
                                    &an_disable_admin);
 
-       an_disable = link_ksettings->base.autoneg == AUTONEG_DISABLE;
+       an_disable = autoneg == AUTONEG_DISABLE;
        an_changes = ((!an_disable && an_disable_admin) ||
                      (an_disable && !an_disable_admin));
 
        if (!an_changes && link_modes == eproto.admin)
                goto out;
 
-       mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_requested);
+       mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
        mlx5_toggle_port_link(mdev);
 
 out:
@@ -1313,6 +1346,9 @@ int mlx5e_ethtool_set_pauseparam(struct mlx5e_priv *priv,
        struct mlx5_core_dev *mdev = priv->mdev;
        int err;
 
+       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+               return -EOPNOTSUPP;
+
        if (pauseparam->autoneg)
                return -EINVAL;
 
@@ -1654,6 +1690,40 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
        return 0;
 }
 
+int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
+                              struct ethtool_flash *flash)
+{
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct net_device *dev = priv->netdev;
+       const struct firmware *fw;
+       int err;
+
+       if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
+               return -EOPNOTSUPP;
+
+       err = request_firmware_direct(&fw, flash->data, &dev->dev);
+       if (err)
+               return err;
+
+       dev_hold(dev);
+       rtnl_unlock();
+
+       err = mlx5_firmware_flash(mdev, fw, NULL);
+       release_firmware(fw);
+
+       rtnl_lock();
+       dev_put(dev);
+       return err;
+}
+
+static int mlx5e_flash_device(struct net_device *dev,
+                             struct ethtool_flash *flash)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+
+       return mlx5e_ethtool_flash_device(priv, flash);
+}
+
 static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable,
                                     bool is_rx_cq)
 {
@@ -1936,6 +2006,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
        .set_wol           = mlx5e_set_wol,
        .get_module_info   = mlx5e_get_module_info,
        .get_module_eeprom = mlx5e_get_module_eeprom,
+       .flash_device      = mlx5e_flash_device,
        .get_priv_flags    = mlx5e_get_priv_flags,
        .set_priv_flags    = mlx5e_set_priv_flags,
        .self_test         = mlx5e_self_test,
index ea3a490b569a58c46b49196b3637bec4923b7843..94304abc49e98102c50a6a1fcb63ca468335af96 100644 (file)
@@ -611,7 +611,8 @@ static int validate_flow(struct mlx5e_priv *priv,
                return -ENOSPC;
 
        if (fs->ring_cookie != RX_CLS_FLOW_DISC)
-               if (!mlx5e_qid_validate(&priv->channels.params, fs->ring_cookie))
+               if (!mlx5e_qid_validate(priv->profile, &priv->channels.params,
+                                       fs->ring_cookie))
                        return -EINVAL;
 
        switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
index 47eea6b3a1c385dc97339f671a1d56b49dc3c92b..9d5f6e56188f825bbbe605f1bfb3af09604d5e42 100644 (file)
@@ -331,12 +331,11 @@ static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
 
 static void mlx5e_init_frags_partition(struct mlx5e_rq *rq)
 {
-       struct mlx5e_wqe_frag_info next_frag, *prev;
+       struct mlx5e_wqe_frag_info next_frag = {};
+       struct mlx5e_wqe_frag_info *prev = NULL;
        int i;
 
        next_frag.di = &rq->wqe.di[0];
-       next_frag.offset = 0;
-       prev = NULL;
 
        for (i = 0; i < mlx5_wq_cyc_get_size(&rq->wqe.wq); i++) {
                struct mlx5e_rq_frag_info *frag_info = &rq->wqe.info.arr[0];
@@ -1322,7 +1321,6 @@ err_free_txqsq:
 void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
 {
        sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
-       clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
        set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
        netdev_tx_reset_queue(sq->txq);
        netif_tx_start_queue(sq->txq);
@@ -1677,10 +1675,10 @@ static int mlx5e_open_sqs(struct mlx5e_channel *c,
                          struct mlx5e_channel_param *cparam)
 {
        struct mlx5e_priv *priv = c->priv;
-       int err, tc, max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
+       int err, tc;
 
        for (tc = 0; tc < params->num_tc; tc++) {
-               int txq_ix = c->ix + tc * max_nch;
+               int txq_ix = c->ix + tc * priv->max_nch;
 
                err = mlx5e_open_txqsq(c, c->priv->tisn[tc], txq_ix,
                                       params, &cparam->sq, &c->sq[tc], tc);
@@ -2438,11 +2436,10 @@ int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv)
 
 int mlx5e_create_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int err;
        int ix;
 
-       for (ix = 0; ix < max_nch; ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                err = mlx5e_create_rqt(priv, 1 /*size */, &tirs[ix].rqt);
                if (unlikely(err))
                        goto err_destroy_rqts;
@@ -2460,10 +2457,9 @@ err_destroy_rqts:
 
 void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int i;
 
-       for (i = 0; i < max_nch; i++)
+       for (i = 0; i < priv->max_nch; i++)
                mlx5e_destroy_rqt(priv, &tirs[i].rqt);
 }
 
@@ -2557,7 +2553,7 @@ static void mlx5e_redirect_rqts(struct mlx5e_priv *priv,
                mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, rrp);
        }
 
-       for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                struct mlx5e_redirect_rqt_param direct_rrp = {
                        .is_rss = false,
                        {
@@ -2758,7 +2754,7 @@ static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
                        goto free_in;
        }
 
-       for (ix = 0; ix < mlx5e_get_netdev_max_channels(priv->netdev); ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                err = mlx5_core_modify_tir(mdev, priv->direct_tir[ix].tirn,
                                           in, inlen);
                if (err)
@@ -2858,12 +2854,11 @@ static void mlx5e_netdev_set_tcs(struct net_device *netdev)
 
 static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int i, tc;
 
-       for (i = 0; i < max_nch; i++)
+       for (i = 0; i < priv->max_nch; i++)
                for (tc = 0; tc < priv->profile->max_tc; tc++)
-                       priv->channel_tc2txq[i][tc] = i + tc * max_nch;
+                       priv->channel_tc2txq[i][tc] = i + tc * priv->max_nch;
 }
 
 static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
@@ -2884,7 +2879,7 @@ static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
 void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 {
        int num_txqs = priv->channels.num * priv->channels.params.num_tc;
-       int num_rxqs = priv->channels.num * MLX5E_NUM_RQ_GROUPS;
+       int num_rxqs = priv->channels.num * priv->profile->rq_groups;
        struct net_device *netdev = priv->netdev;
 
        mlx5e_netdev_set_tcs(netdev);
@@ -3306,7 +3301,6 @@ err_destroy_inner_tirs:
 
 int mlx5e_create_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        struct mlx5e_tir *tir;
        void *tirc;
        int inlen;
@@ -3319,7 +3313,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
        if (!in)
                return -ENOMEM;
 
-       for (ix = 0; ix < max_nch; ix++) {
+       for (ix = 0; ix < priv->max_nch; ix++) {
                memset(in, 0, inlen);
                tir = &tirs[ix];
                tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
@@ -3358,10 +3352,9 @@ void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc)
 
 void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv, struct mlx5e_tir *tirs)
 {
-       const int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        int i;
 
-       for (i = 0; i < max_nch; i++)
+       for (i = 0; i < priv->max_nch; i++)
                mlx5e_destroy_tir(priv->mdev, &tirs[i]);
 }
 
@@ -3487,7 +3480,7 @@ void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
 {
        int i;
 
-       for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+       for (i = 0; i < priv->max_nch; i++) {
                struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i];
                struct mlx5e_rq_stats *xskrq_stats = &channel_stats->xskrq;
                struct mlx5e_rq_stats *rq_stats = &channel_stats->rq;
@@ -4960,8 +4953,7 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
                return err;
 
        mlx5e_build_nic_params(mdev, &priv->xsk, rss, &priv->channels.params,
-                              mlx5e_get_netdev_max_channels(netdev),
-                              netdev->mtu);
+                              priv->max_nch, netdev->mtu);
 
        mlx5e_timestamp_init(priv);
 
@@ -5164,6 +5156,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe,
        .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc            = MLX5E_MAX_NUM_TC,
+       .rq_groups         = MLX5E_NUM_RQ_GROUPS(XSK),
 };
 
 /* mlx5e generic netdev management API (move to en_common.c) */
@@ -5181,6 +5174,7 @@ int mlx5e_netdev_init(struct net_device *netdev,
        priv->profile     = profile;
        priv->ppriv       = ppriv;
        priv->msglevel    = MLX5E_MSG_LEVEL;
+       priv->max_nch     = netdev->num_rx_queues / max_t(u8, profile->rq_groups, 1);
        priv->max_opened_tc = 1;
 
        mutex_init(&priv->state_lock);
@@ -5218,7 +5212,7 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
 
        netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
                                    nch * profile->max_tc,
-                                   nch * MLX5E_NUM_RQ_GROUPS);
+                                   nch * profile->rq_groups);
        if (!netdev) {
                mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
                return NULL;
index 7f747cb1a4f4b6ba072cd75596cf042ae7380da7..d0684fdb69e1424cee0e17d147755d20fa938e85 100644 (file)
@@ -1701,6 +1701,7 @@ static const struct mlx5e_profile mlx5e_rep_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe_rep,
        .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc                 = 1,
+       .rq_groups              = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
@@ -1718,6 +1719,7 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe_rep,
        .rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
        .max_tc                 = MLX5E_MAX_NUM_TC,
+       .rq_groups              = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 static bool
index 539b4d3656da1e3af54a2977024d4a0346c584f2..57f9f346d213b0ba9be9449c2947c06442d6c6c5 100644 (file)
@@ -172,7 +172,7 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
 
        memset(s, 0, sizeof(*s));
 
-       for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) {
+       for (i = 0; i < priv->max_nch; i++) {
                struct mlx5e_channel_stats *channel_stats =
                        &priv->channel_stats[i];
                struct mlx5e_xdpsq_stats *xdpsq_red_stats = &channel_stats->xdpsq;
@@ -1395,7 +1395,7 @@ static const struct counter_desc ch_stats_desc[] = {
 
 static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
+       int max_nch = priv->max_nch;
 
        return (NUM_RQ_STATS * max_nch) +
               (NUM_CH_STATS * max_nch) +
@@ -1409,8 +1409,8 @@ static int mlx5e_grp_channels_get_num_stats(struct mlx5e_priv *priv)
 static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data,
                                           int idx)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        bool is_xsk = priv->xsk.ever_used;
+       int max_nch = priv->max_nch;
        int i, j, tc;
 
        for (i = 0; i < max_nch; i++)
@@ -1452,8 +1452,8 @@ static int mlx5e_grp_channels_fill_strings(struct mlx5e_priv *priv, u8 *data,
 static int mlx5e_grp_channels_fill_stats(struct mlx5e_priv *priv, u64 *data,
                                         int idx)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        bool is_xsk = priv->xsk.ever_used;
+       int max_nch = priv->max_nch;
        int i, j, tc;
 
        for (i = 0; i < max_nch; i++)
index cc096f6011d964051405dd5fa3514b428086cc5a..00b2d4a86159f142e491278769fe1679ce5a2d20 100644 (file)
@@ -1230,13 +1230,13 @@ static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow)
 void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
 {
        struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
-       u64 bytes, packets, lastuse = 0;
        struct mlx5e_tc_flow *flow;
        struct mlx5e_encap_entry *e;
        struct mlx5_fc *counter;
        struct neigh_table *tbl;
        bool neigh_used = false;
        struct neighbour *n;
+       u64 lastuse;
 
        if (m_neigh->family == AF_INET)
                tbl = &arp_tbl;
@@ -1256,7 +1256,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
                                            encaps[efi->index]);
                        if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
                                counter = mlx5e_tc_get_counter(flow);
-                               mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+                               lastuse = mlx5_fc_query_lastuse(counter);
                                if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
                                        neigh_used = true;
                                        break;
@@ -1480,7 +1480,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
                              struct flow_cls_offload *f,
                              struct net_device *filter_dev,
-                             u8 *match_level, u8 *tunnel_match_level)
+                             u8 *inner_match_level, u8 *outer_match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1495,8 +1495,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
        struct flow_dissector *dissector = rule->match.dissector;
        u16 addr_type = 0;
        u8 ip_proto = 0;
+       u8 *match_level;
 
-       *match_level = MLX5_MATCH_NONE;
+       match_level = outer_match_level;
 
        if (dissector->used_keys &
            ~(BIT(FLOW_DISSECTOR_KEY_META) |
@@ -1524,12 +1525,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
        }
 
        if (mlx5e_get_tc_tun(filter_dev)) {
-               if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
+               if (parse_tunnel_attr(priv, spec, f, filter_dev,
+                                     outer_match_level))
                        return -EOPNOTSUPP;
 
-               /* In decap flow, header pointers should point to the inner
+               /* At this point, header pointers should point to the inner
                 * headers, outer header were already set by parse_tunnel_attr
                 */
+               match_level = inner_match_level;
                headers_c = get_match_headers_criteria(MLX5_FLOW_CONTEXT_ACTION_DECAP,
                                                       spec);
                headers_v = get_match_headers_value(MLX5_FLOW_CONTEXT_ACTION_DECAP,
@@ -1831,35 +1834,41 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
                            struct flow_cls_offload *f,
                            struct net_device *filter_dev)
 {
+       u8 inner_match_level, outer_match_level, non_tunnel_match_level;
        struct netlink_ext_ack *extack = f->common.extack;
        struct mlx5_core_dev *dev = priv->mdev;
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
-       u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
        struct mlx5_eswitch_rep *rep;
        int err;
 
-       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
+       inner_match_level = MLX5_MATCH_NONE;
+       outer_match_level = MLX5_MATCH_NONE;
+
+       err = __parse_cls_flower(priv, spec, f, filter_dev, &inner_match_level,
+                                &outer_match_level);
+       non_tunnel_match_level = (inner_match_level == MLX5_MATCH_NONE) ?
+                                outer_match_level : inner_match_level;
 
        if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
                rep = rpriv->rep;
                if (rep->vport != MLX5_VPORT_UPLINK &&
                    (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
-                   esw->offloads.inline_mode < match_level)) {
+                   esw->offloads.inline_mode < non_tunnel_match_level)) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Flow is not offloaded due to min inline setting");
                        netdev_warn(priv->netdev,
                                    "Flow is not offloaded due to min inline setting, required %d actual %d\n",
-                                   match_level, esw->offloads.inline_mode);
+                                   non_tunnel_match_level, esw->offloads.inline_mode);
                        return -EOPNOTSUPP;
                }
        }
 
        if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
-               flow->esw_attr->match_level = match_level;
-               flow->esw_attr->tunnel_match_level = tunnel_match_level;
+               flow->esw_attr->inner_match_level = inner_match_level;
+               flow->esw_attr->outer_match_level = outer_match_level;
        } else {
-               flow->nic_attr->match_level = match_level;
+               flow->nic_attr->match_level = non_tunnel_match_level;
        }
 
        return err;
@@ -3158,7 +3167,7 @@ mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr,
 
        esw_attr->parse_attr = parse_attr;
        esw_attr->chain = f->common.chain_index;
-       esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16;
+       esw_attr->prio = f->common.prio;
 
        esw_attr->in_rep = in_rep;
        esw_attr->in_mdev = in_mdev;
index c50b6f0769c8c5086946fb8618ca42fdc4f2079c..49b06b256c92955d8b0054ade614b2d33ee41c1e 100644 (file)
@@ -49,7 +49,7 @@ static inline bool mlx5e_channel_no_affinity_change(struct mlx5e_channel *c)
 static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
 {
        struct mlx5e_sq_stats *stats = sq->stats;
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
 
        if (unlikely(!test_bit(MLX5E_SQ_STATE_AM, &sq->state)))
                return;
@@ -61,7 +61,7 @@ static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
 static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
 {
        struct mlx5e_rq_stats *stats = rq->stats;
-       struct dim_sample dim_sample;
+       struct dim_sample dim_sample = {};
 
        if (unlikely(!test_bit(MLX5E_RQ_STATE_AM, &rq->state)))
                return;
index a38e8a3c7c9a3b71b6a51c9f440b25878508340f..04685dbb280cfad006007a070ac0d2414a5fd894 100644 (file)
@@ -377,8 +377,8 @@ struct mlx5_esw_flow_attr {
                struct mlx5_termtbl_handle *termtbl;
        } dests[MLX5_MAX_FLOW_FWD_VPORTS];
        u32     mod_hdr_id;
-       u8      match_level;
-       u8      tunnel_match_level;
+       u8      inner_match_level;
+       u8      outer_match_level;
        struct mlx5_fc *counter;
        u32     chain;
        u16     prio;
index 089ae4d48a82dda15e47c49530f9a4e513577acb..0323fd078271bce17cff6a8c963cf803b7437fda 100644 (file)
@@ -207,14 +207,10 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
-       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
-               if (attr->tunnel_match_level != MLX5_MATCH_NONE)
-                       spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
-               if (attr->match_level != MLX5_MATCH_NONE)
-                       spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
-       } else if (attr->match_level != MLX5_MATCH_NONE) {
+       if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
-       }
+       if (attr->inner_match_level != MLX5_MATCH_NONE)
+               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                flow_act.modify_id = attr->mod_hdr_id;
@@ -290,7 +286,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
        spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
-       if (attr->match_level != MLX5_MATCH_NONE)
+       if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
 
        rule = mlx5_add_flow_rules(fast_fdb, spec, &flow_act, dest, i);
index c48c382f926f33b5747c5f5603c18713a03e6bd0..c1252d6be0ef13f38fbe573e724b0a814f319230 100644 (file)
@@ -68,7 +68,7 @@ enum fs_flow_table_type {
        FS_FT_SNIFFER_RX        = 0X5,
        FS_FT_SNIFFER_TX        = 0X6,
        FS_FT_RDMA_RX           = 0X7,
-       FS_FT_MAX_TYPE = FS_FT_SNIFFER_TX,
+       FS_FT_MAX_TYPE = FS_FT_RDMA_RX,
 };
 
 enum fs_flow_table_op_mod {
@@ -275,7 +275,8 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
        (type == FS_FT_FDB) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :           \
        (type == FS_FT_SNIFFER_RX) ? MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) :         \
        (type == FS_FT_SNIFFER_TX) ? MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) :         \
-       (BUILD_BUG_ON_ZERO(FS_FT_SNIFFER_TX != FS_FT_MAX_TYPE))\
+       (type == FS_FT_RDMA_RX) ? MLX5_CAP_FLOWTABLE_RDMA_RX(mdev, cap) :               \
+       (BUILD_BUG_ON_ZERO(FS_FT_RDMA_RX != FS_FT_MAX_TYPE))\
        )
 
 #endif
index b3762123a69c2188f1745965aaeeb80ca8d80bf6..1834d9f3aa1c019ee9057b141bfe86068ac757c2 100644 (file)
@@ -369,6 +369,11 @@ int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
 }
 EXPORT_SYMBOL(mlx5_fc_query);
 
+u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter)
+{
+       return counter->cache.lastuse;
+}
+
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse)
 {
index ebd81f6b556e9e6b00e3cf3534a5260a8f01e7ad..90cb50fe17fd95de3a5f295a8cbe60f97cabafa8 100644 (file)
@@ -122,6 +122,14 @@ static int mlx5i_get_ts_info(struct net_device *netdev,
        return mlx5e_ethtool_get_ts_info(priv, info);
 }
 
+static int mlx5i_flash_device(struct net_device *netdev,
+                             struct ethtool_flash *flash)
+{
+       struct mlx5e_priv *priv = mlx5i_epriv(netdev);
+
+       return mlx5e_ethtool_flash_device(priv, flash);
+}
+
 enum mlx5_ptys_width {
        MLX5_PTYS_WIDTH_1X      = 1 << 0,
        MLX5_PTYS_WIDTH_2X      = 1 << 1,
@@ -233,6 +241,7 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
        .get_ethtool_stats  = mlx5i_get_ethtool_stats,
        .get_ringparam      = mlx5i_get_ringparam,
        .set_ringparam      = mlx5i_set_ringparam,
+       .flash_device       = mlx5i_flash_device,
        .get_channels       = mlx5i_get_channels,
        .set_channels       = mlx5i_set_channels,
        .get_coalesce       = mlx5i_get_coalesce,
index 6bfaaab362dc48dac5f5e76d91eb41578585b2fb..1a2560e3bf7c54d85390b1f8a93600ad5a84ead9 100644 (file)
@@ -88,8 +88,7 @@ int mlx5i_init(struct mlx5_core_dev *mdev,
        netdev->mtu = netdev->max_mtu;
 
        mlx5e_build_nic_params(mdev, NULL, &priv->rss_params, &priv->channels.params,
-                              mlx5e_get_netdev_max_channels(netdev),
-                              netdev->mtu);
+                              priv->max_nch, netdev->mtu);
        mlx5i_build_nic_params(mdev, &priv->channels.params);
 
        mlx5e_timestamp_init(priv);
@@ -118,11 +117,10 @@ void mlx5i_cleanup(struct mlx5e_priv *priv)
 
 static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv)
 {
-       int max_nch = mlx5e_get_netdev_max_channels(priv->netdev);
        struct mlx5e_sw_stats s = { 0 };
        int i, j;
 
-       for (i = 0; i < max_nch; i++) {
+       for (i = 0; i < priv->max_nch; i++) {
                struct mlx5e_channel_stats *channel_stats;
                struct mlx5e_rq_stats *rq_stats;
 
@@ -436,6 +434,7 @@ static const struct mlx5e_profile mlx5i_nic_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5i_handle_rx_cqe,
        .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
        .max_tc            = MLX5I_MAX_NUM_TC,
+       .rq_groups         = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 /* mlx5i netdev NDos */
index 6e56fa769d2eb97b593b2c3da4c5aa5c40c1afdc..c5a491e22e55547def2706fa6b28c8c08fa858d1 100644 (file)
@@ -355,6 +355,7 @@ static const struct mlx5e_profile mlx5i_pkey_nic_profile = {
        .rx_handlers.handle_rx_cqe       = mlx5i_handle_rx_cqe,
        .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
        .max_tc            = MLX5I_MAX_NUM_TC,
+       .rq_groups         = MLX5E_NUM_RQ_GROUPS(REGULAR),
 };
 
 const struct mlx5e_profile *mlx5i_pkey_get_profile(void)
index ea9ee88491e5d13e120efed9556af2241eec92c6..ea1d4d26ece06a242b86182fe77aff766c76fbf7 100644 (file)
@@ -27,6 +27,7 @@ int mlx5_create_encryption_key(struct mlx5_core_dev *mdev,
        case 128:
                general_obj_key_size =
                        MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_KEY_SIZE_128;
+               key_p += sz_bytes;
                break;
        case 256:
                general_obj_key_size =
index 650638152bbc5d6bd5d06949c6920f175fb4f9ee..eda9c23e87b28fcca50b8935e006fb9c94e990c3 100644 (file)
@@ -6330,7 +6330,7 @@ static int __init mlxsw_sp_module_init(void)
        return 0;
 
 err_sp2_pci_driver_register:
-       mlxsw_pci_driver_unregister(&mlxsw_sp2_pci_driver);
+       mlxsw_pci_driver_unregister(&mlxsw_sp1_pci_driver);
 err_sp1_pci_driver_register:
        mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
 err_sp2_core_driver_register:
index 131f62ce9297a05e0ba5406995beb1a16c14bdfa..6664119fb0c8cfc39ffd24c8963657de2e47c98b 100644 (file)
@@ -951,4 +951,8 @@ void mlxsw_sp_port_nve_fini(struct mlxsw_sp_port *mlxsw_sp_port);
 int mlxsw_sp_nve_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp);
 
+/* spectrum_nve_vxlan.c */
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp);
+
 #endif
index e8ac90564dbe5ee36d3206542fa06145b51bfb3b..84a87d0593338845ef6d900d9ae865763729ead4 100644 (file)
@@ -471,7 +471,7 @@ int mlxsw_sp_acl_rulei_commit(struct mlxsw_sp_acl_rule_info *rulei)
 void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei,
                                 unsigned int priority)
 {
-       rulei->priority = priority >> 16;
+       rulei->priority = priority;
 }
 
 void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei,
index 1537f70bc26d0fbef771b91e4c92f6d9dae1ac4f..888ba4300bcc3b5d1888e7d3c87b28d51200e7f7 100644 (file)
@@ -437,8 +437,8 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
                           MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
 };
 
-#define MLXSW_SP2_SB_PR_INGRESS_SIZE   38128752
-#define MLXSW_SP2_SB_PR_EGRESS_SIZE    38128752
+#define MLXSW_SP2_SB_PR_INGRESS_SIZE   35297568
+#define MLXSW_SP2_SB_PR_EGRESS_SIZE    35297568
 #define MLXSW_SP2_SB_PR_CPU_SIZE       (256 * 1000)
 
 /* Order according to mlxsw_sp2_sb_pool_dess */
index 1df164a4b06d3516b45dd034b8dbd71cb7988ab1..17f334b46c4056c6689d41d8288d3812a263a406 100644 (file)
@@ -775,6 +775,7 @@ static void mlxsw_sp_nve_tunnel_fini(struct mlxsw_sp *mlxsw_sp)
                ops->fini(nve);
                mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
                                   nve->tunnel_index);
+               memset(&nve->config, 0, sizeof(nve->config));
        }
        nve->num_nve_tunnels--;
 }
index 0035640156a16ebbee0391f8c105b4bbd455dfb0..12f664f42f2108abfc85b381959905713d8971cf 100644 (file)
@@ -29,6 +29,7 @@ struct mlxsw_sp_nve {
        unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX];
        u32 tunnel_index;
        u16 ul_rif_index;       /* Reserved for Spectrum */
+       unsigned int inc_parsing_depth_refs;
 };
 
 struct mlxsw_sp_nve_ops {
index 93ccd9fc22662d78ea91f12de0d9a2ea01ab4d30..05517c7feaa563fe0b8d1a365ce26980ea93b4a4 100644 (file)
@@ -103,9 +103,9 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve,
        config->udp_dport = cfg->dst_port;
 }
 
-static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
-                                   unsigned int parsing_depth,
-                                   __be16 udp_dport)
+static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+                                     unsigned int parsing_depth,
+                                     __be16 udp_dport)
 {
        char mprs_pl[MLXSW_REG_MPRS_LEN];
 
@@ -113,6 +113,56 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
 }
 
+static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+                                   __be16 udp_dport)
+{
+       int parsing_depth = mlxsw_sp->nve->inc_parsing_depth_refs ?
+                               MLXSW_SP_NVE_VXLAN_PARSING_DEPTH :
+                               MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH;
+
+       return __mlxsw_sp_nve_parsing_set(mlxsw_sp, parsing_depth, udp_dport);
+}
+
+static int
+__mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp,
+                                    __be16 udp_dport)
+{
+       int err;
+
+       mlxsw_sp->nve->inc_parsing_depth_refs++;
+
+       err = mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+       if (err)
+               goto err_nve_parsing_set;
+       return 0;
+
+err_nve_parsing_set:
+       mlxsw_sp->nve->inc_parsing_depth_refs--;
+       return err;
+}
+
+static void
+__mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp,
+                                    __be16 udp_dport)
+{
+       mlxsw_sp->nve->inc_parsing_depth_refs--;
+       mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+}
+
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp)
+{
+       __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+       return __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, udp_dport);
+}
+
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp)
+{
+       __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, udp_dport);
+}
+
 static void
 mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl,
                                  const struct mlxsw_sp_nve_config *config)
@@ -176,9 +226,7 @@ static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve,
        struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
        int err;
 
-       err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
-                                      MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
-                                      config->udp_dport);
+       err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
        if (err)
                return err;
 
@@ -203,8 +251,7 @@ err_promote_decap:
 err_rtdp_set:
        mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
 err_config_set:
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
        return err;
 }
 
@@ -216,8 +263,7 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
        mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
                                         config->ul_proto, &config->ul_sip);
        mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
 }
 
 static int
@@ -320,9 +366,7 @@ static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
        struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
        int err;
 
-       err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
-                                      MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
-                                      config->udp_dport);
+       err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
        if (err)
                return err;
 
@@ -348,8 +392,7 @@ err_promote_decap:
 err_rtdp_set:
        mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
 err_config_set:
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
        return err;
 }
 
@@ -361,8 +404,7 @@ static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
        mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
                                         config->ul_proto, &config->ul_sip);
        mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
 }
 
 const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
index bd9c2bc2d5d6e0569935ad77aedf56f1db198594..38bb1cfe4e8c566153c138b61babb7b59bc58059 100644 (file)
@@ -29,7 +29,7 @@
 
 struct mlxsw_sp_ptp_state {
        struct mlxsw_sp *mlxsw_sp;
-       struct rhashtable unmatched_ht;
+       struct rhltable unmatched_ht;
        spinlock_t unmatched_lock; /* protects the HT */
        struct delayed_work ht_gc_dw;
        u32 gc_cycle;
@@ -45,7 +45,7 @@ struct mlxsw_sp1_ptp_key {
 
 struct mlxsw_sp1_ptp_unmatched {
        struct mlxsw_sp1_ptp_key key;
-       struct rhash_head ht_node;
+       struct rhlist_head ht_node;
        struct rcu_head rcu;
        struct sk_buff *skb;
        u64 timestamp;
@@ -359,7 +359,7 @@ static int mlxsw_sp_ptp_parse(struct sk_buff *skb,
 /* Returns NULL on successful insertion, a pointer on conflict, or an ERR_PTR on
  * error.
  */
-static struct mlxsw_sp1_ptp_unmatched *
+static int
 mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
                             struct mlxsw_sp1_ptp_key key,
                             struct sk_buff *skb,
@@ -368,41 +368,51 @@ mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp,
        int cycles = MLXSW_SP1_PTP_HT_GC_TIMEOUT / MLXSW_SP1_PTP_HT_GC_INTERVAL;
        struct mlxsw_sp_ptp_state *ptp_state = mlxsw_sp->ptp_state;
        struct mlxsw_sp1_ptp_unmatched *unmatched;
-       struct mlxsw_sp1_ptp_unmatched *conflict;
+       int err;
 
        unmatched = kzalloc(sizeof(*unmatched), GFP_ATOMIC);
        if (!unmatched)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
        unmatched->key = key;
        unmatched->skb = skb;
        unmatched->timestamp = timestamp;
        unmatched->gc_cycle = mlxsw_sp->ptp_state->gc_cycle + cycles;
 
-       conflict = rhashtable_lookup_get_insert_fast(&ptp_state->unmatched_ht,
-                                           &unmatched->ht_node,
-                                           mlxsw_sp1_ptp_unmatched_ht_params);
-       if (conflict)
+       err = rhltable_insert(&ptp_state->unmatched_ht, &unmatched->ht_node,
+                             mlxsw_sp1_ptp_unmatched_ht_params);
+       if (err)
                kfree(unmatched);
 
-       return conflict;
+       return err;
 }
 
 static struct mlxsw_sp1_ptp_unmatched *
 mlxsw_sp1_ptp_unmatched_lookup(struct mlxsw_sp *mlxsw_sp,
-                              struct mlxsw_sp1_ptp_key key)
+                              struct mlxsw_sp1_ptp_key key, int *p_length)
 {
-       return rhashtable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
-                                mlxsw_sp1_ptp_unmatched_ht_params);
+       struct mlxsw_sp1_ptp_unmatched *unmatched, *last = NULL;
+       struct rhlist_head *tmp, *list;
+       int length = 0;
+
+       list = rhltable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key,
+                              mlxsw_sp1_ptp_unmatched_ht_params);
+       rhl_for_each_entry_rcu(unmatched, tmp, list, ht_node) {
+               last = unmatched;
+               length++;
+       }
+
+       *p_length = length;
+       return last;
 }
 
 static int
 mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp,
                               struct mlxsw_sp1_ptp_unmatched *unmatched)
 {
-       return rhashtable_remove_fast(&mlxsw_sp->ptp_state->unmatched_ht,
-                                     &unmatched->ht_node,
-                                     mlxsw_sp1_ptp_unmatched_ht_params);
+       return rhltable_remove(&mlxsw_sp->ptp_state->unmatched_ht,
+                              &unmatched->ht_node,
+                              mlxsw_sp1_ptp_unmatched_ht_params);
 }
 
 /* This function is called in the following scenarios:
@@ -489,75 +499,38 @@ static void mlxsw_sp1_ptp_got_piece(struct mlxsw_sp *mlxsw_sp,
                                    struct mlxsw_sp1_ptp_key key,
                                    struct sk_buff *skb, u64 timestamp)
 {
-       struct mlxsw_sp1_ptp_unmatched *unmatched, *conflict;
+       struct mlxsw_sp1_ptp_unmatched *unmatched;
+       int length;
        int err;
 
        rcu_read_lock();
 
-       unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key);
-
        spin_lock(&mlxsw_sp->ptp_state->unmatched_lock);
 
-       if (unmatched) {
-               /* There was an unmatched entry when we looked, but it may have
-                * been removed before we took the lock.
-                */
-               err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
-               if (err)
-                       unmatched = NULL;
-       }
-
-       if (!unmatched) {
-               /* We have no unmatched entry, but one may have been added after
-                * we looked, but before we took the lock.
-                */
-               unmatched = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
-                                                        skb, timestamp);
-               if (IS_ERR(unmatched)) {
-                       if (skb)
-                               mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
-                                                           key.local_port,
-                                                           key.ingress, NULL);
-                       unmatched = NULL;
-               } else if (unmatched) {
-                       /* Save just told us, under lock, that the entry is
-                        * there, so this has to work.
-                        */
-                       err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp,
-                                                            unmatched);
-                       WARN_ON_ONCE(err);
-               }
-       }
-
-       /* If unmatched is non-NULL here, it comes either from the lookup, or
-        * from the save attempt above. In either case the entry was removed
-        * from the hash table. If unmatched is NULL, a new unmatched entry was
-        * added to the hash table, and there was no conflict.
-        */
-
+       unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key, &length);
        if (skb && unmatched && unmatched->timestamp) {
                unmatched->skb = skb;
        } else if (timestamp && unmatched && unmatched->skb) {
                unmatched->timestamp = timestamp;
-       } else if (unmatched) {
-               /* unmatched holds an older entry of the same type: either an
-                * skb if we are handling skb, or a timestamp if we are handling
-                * timestamp. We can't match that up, so save what we have.
+       } else {
+               /* Either there is no entry to match, or one that is there is
+                * incompatible.
                 */
-               conflict = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
-                                                       skb, timestamp);
-               if (IS_ERR(conflict)) {
-                       if (skb)
-                               mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
-                                                           key.local_port,
-                                                           key.ingress, NULL);
-               } else {
-                       /* Above, we removed an object with this key from the
-                        * hash table, under lock, so conflict can not be a
-                        * valid pointer.
-                        */
-                       WARN_ON_ONCE(conflict);
-               }
+               if (length < 100)
+                       err = mlxsw_sp1_ptp_unmatched_save(mlxsw_sp, key,
+                                                          skb, timestamp);
+               else
+                       err = -E2BIG;
+               if (err && skb)
+                       mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb,
+                                                   key.local_port,
+                                                   key.ingress, NULL);
+               unmatched = NULL;
+       }
+
+       if (unmatched) {
+               err = mlxsw_sp1_ptp_unmatched_remove(mlxsw_sp, unmatched);
+               WARN_ON_ONCE(err);
        }
 
        spin_unlock(&mlxsw_sp->ptp_state->unmatched_lock);
@@ -669,9 +642,8 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state,
        local_bh_disable();
 
        spin_lock(&ptp_state->unmatched_lock);
-       err = rhashtable_remove_fast(&ptp_state->unmatched_ht,
-                                    &unmatched->ht_node,
-                                    mlxsw_sp1_ptp_unmatched_ht_params);
+       err = rhltable_remove(&ptp_state->unmatched_ht, &unmatched->ht_node,
+                             mlxsw_sp1_ptp_unmatched_ht_params);
        spin_unlock(&ptp_state->unmatched_lock);
 
        if (err)
@@ -702,7 +674,7 @@ static void mlxsw_sp1_ptp_ht_gc(struct work_struct *work)
        ptp_state = container_of(dwork, struct mlxsw_sp_ptp_state, ht_gc_dw);
        gc_cycle = ptp_state->gc_cycle++;
 
-       rhashtable_walk_enter(&ptp_state->unmatched_ht, &iter);
+       rhltable_walk_enter(&ptp_state->unmatched_ht, &iter);
        rhashtable_walk_start(&iter);
        while ((obj = rhashtable_walk_next(&iter))) {
                if (IS_ERR(obj))
@@ -855,8 +827,8 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp)
 
        spin_lock_init(&ptp_state->unmatched_lock);
 
-       err = rhashtable_init(&ptp_state->unmatched_ht,
-                             &mlxsw_sp1_ptp_unmatched_ht_params);
+       err = rhltable_init(&ptp_state->unmatched_ht,
+                           &mlxsw_sp1_ptp_unmatched_ht_params);
        if (err)
                goto err_hashtable_init;
 
@@ -891,7 +863,7 @@ err_fifo_clr:
 err_mtptpt1_set:
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
 err_mtptpt_set:
-       rhashtable_destroy(&ptp_state->unmatched_ht);
+       rhltable_destroy(&ptp_state->unmatched_ht);
 err_hashtable_init:
        kfree(ptp_state);
        return ERR_PTR(err);
@@ -906,8 +878,8 @@ void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
        mlxsw_sp1_ptp_set_fifo_clr_on_trap(mlxsw_sp, false);
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP1, 0);
        mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP0, 0);
-       rhashtable_free_and_destroy(&ptp_state->unmatched_ht,
-                                   &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
+       rhltable_free_and_destroy(&ptp_state->unmatched_ht,
+                                 &mlxsw_sp1_ptp_unmatched_free_fn, NULL);
        kfree(ptp_state);
 }
 
@@ -979,6 +951,9 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        struct mlxsw_sp_port *tmp;
+       u16 orig_ing_types = 0;
+       u16 orig_egr_types = 0;
+       int err;
        int i;
 
        /* MTPPPC configures timestamping globally, not per port. Find the
@@ -986,12 +961,26 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
         */
        for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) {
                tmp = mlxsw_sp->ports[i];
+               if (tmp) {
+                       orig_ing_types |= tmp->ptp.ing_types;
+                       orig_egr_types |= tmp->ptp.egr_types;
+               }
                if (tmp && tmp != mlxsw_sp_port) {
                        ing_types |= tmp->ptp.ing_types;
                        egr_types |= tmp->ptp.egr_types;
                }
        }
 
+       if ((ing_types || egr_types) && !(orig_ing_types || orig_egr_types)) {
+               err = mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp);
+               if (err) {
+                       netdev_err(mlxsw_sp_port->dev, "Failed to increase parsing depth");
+                       return err;
+               }
+       }
+       if (!(ing_types || egr_types) && (orig_ing_types || orig_egr_types))
+               mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp);
+
        return mlxsw_sp1_ptp_mtpppc_set(mlxsw_sp_port->mlxsw_sp,
                                       ing_types, egr_types);
 }
index b71e4ecbe469a5ec19699ed740ab0a9e63abdd45..6932e615d4b089c68b4d847649bd3adb0f70d543 100644 (file)
@@ -1818,6 +1818,7 @@ EXPORT_SYMBOL(ocelot_init);
 
 void ocelot_deinit(struct ocelot *ocelot)
 {
+       cancel_delayed_work(&ocelot->stats_work);
        destroy_workqueue(ocelot->stats_queue);
        mutex_destroy(&ocelot->stats_lock);
        ocelot_ace_deinit();
index 59487d446a098d6e620f09b6582c15f11c524162..b894bc0c9c1685c31d449fd61ab6466db5258c17 100644 (file)
@@ -13,12 +13,6 @@ struct ocelot_port_block {
        struct ocelot_port *port;
 };
 
-static u16 get_prio(u32 prio)
-{
-       /* prio starts from 0x1000 while the ids starts from 0 */
-       return prio >> 16;
-}
-
 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
                                      struct ocelot_ace_rule *rule)
 {
@@ -168,7 +162,7 @@ static int ocelot_flower_parse(struct flow_cls_offload *f,
        }
 
 finished_key_parsing:
-       ocelot_rule->prio = get_prio(f->common.prio);
+       ocelot_rule->prio = f->common.prio;
        ocelot_rule->id = f->cookie;
        return ocelot_flower_parse_action(f, ocelot_rule);
 }
@@ -218,7 +212,7 @@ static int ocelot_flower_destroy(struct flow_cls_offload *f,
        struct ocelot_ace_rule rule;
        int ret;
 
-       rule.prio = get_prio(f->common.prio);
+       rule.prio = f->common.prio;
        rule.port = port_block->port;
        rule.id = f->cookie;
 
@@ -236,7 +230,7 @@ static int ocelot_flower_stats_update(struct flow_cls_offload *f,
        struct ocelot_ace_rule rule;
        int ret;
 
-       rule.prio = get_prio(f->common.prio);
+       rule.prio = f->common.prio;
        rule.port = port_block->port;
        rule.id = f->cookie;
        ret = ocelot_ace_rule_stats_update(&rule);
index d8b7fba96d58ed109a4962e0128909f9ea283e50..337b0cbfd153ef6bdabcbd8f4e26a1b21bfb2b00 100644 (file)
@@ -3919,7 +3919,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * setup (if available). */
        status = myri10ge_request_irq(mgp);
        if (status != 0)
-               goto abort_with_firmware;
+               goto abort_with_slices;
        myri10ge_free_irq(mgp);
 
        /* Save configuration space to be restored if the
index 86e968cd5ffd3dc6ce9cc17ef29bffeb59ec5caa..124a43dc136a8a28ba1e4a971f6ded621cfaf7e6 100644 (file)
@@ -93,7 +93,7 @@ nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
                return -EOPNOTSUPP;
        }
 
-       if (flow->common.prio != (1 << 16)) {
+       if (flow->common.prio != 1) {
                NL_SET_ERR_MSG_MOD(extack, "unsupported offload: qos rate limit offload requires highest priority");
                return -EOPNOTSUPP;
        }
index d9cbe84ac6ade4105af2e9c93a2f847f944cf8f6..1b840ee4733969a4b61e74e98bf2bfcd3ad2aecb 100644 (file)
@@ -444,12 +444,12 @@ static u8 *nfp_vnic_get_sw_stats_strings(struct net_device *netdev, u8 *data)
        data = nfp_pr_et(data, "hw_rx_csum_complete");
        data = nfp_pr_et(data, "hw_rx_csum_err");
        data = nfp_pr_et(data, "rx_replace_buf_alloc_fail");
-       data = nfp_pr_et(data, "rx_tls_decrypted");
+       data = nfp_pr_et(data, "rx_tls_decrypted_packets");
        data = nfp_pr_et(data, "hw_tx_csum");
        data = nfp_pr_et(data, "hw_tx_inner_csum");
        data = nfp_pr_et(data, "tx_gather");
        data = nfp_pr_et(data, "tx_lso");
-       data = nfp_pr_et(data, "tx_tls_encrypted");
+       data = nfp_pr_et(data, "tx_tls_encrypted_packets");
        data = nfp_pr_et(data, "tx_tls_ooo");
        data = nfp_pr_et(data, "tx_tls_drop_no_sync_data");
 
index 70b1a03c0953e696a92f51769e1db6388a55cab7..01229190132d484ff7d44ccc8606960d4bb76171 100644 (file)
@@ -11,7 +11,7 @@ config NET_VENDOR_NI
 
          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about National Instrument devices.
+         the questions about National Instruments devices.
          If you say Y, you will be asked for your specific device in the
          following questions.
 
index 8161e308e64b0f16e8f527e84145ca9a208bf23f..ead3750b4489d1bf9f2678af74ee7adaec3bd5fc 100644 (file)
@@ -1,10 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
-# Packet engine device configuration
+# Packet Engines device configuration
 #
 
 config NET_VENDOR_PACKET_ENGINES
-       bool "Packet Engine devices"
+       bool "Packet Engines devices"
        default y
        depends on PCI
        ---help---
@@ -12,7 +12,7 @@ config NET_VENDOR_PACKET_ENGINES
 
          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about packet engine devices. If you say Y, you will
+         the questions about Packet Engines devices. If you say Y, you will
          be asked for your specific card in the following questions.
 
 if NET_VENDOR_PACKET_ENGINES
index 1553c9cfc254d6f8a17aa1f84e0a225515ebff4e..cf054b796d1112316f9cebe199a375b24415f725 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
-# Makefile for the Packet Engine network device drivers.
+# Makefile for the Packet Engines network device drivers.
 #
 
 obj-$(CONFIG_HAMACHI) += hamachi.o
index 4e8118a0865455d9ff68447f7c7507d6cc92a8ee..9f5113639eaf0cf2649769e3b2f481f19ff9fec1 100644 (file)
@@ -1093,7 +1093,7 @@ static int qed_int_deassertion(struct qed_hwfn  *p_hwfn,
                                                snprintf(bit_name, 30,
                                                         p_aeu->bit_name, num);
                                        else
-                                               strncpy(bit_name,
+                                               strlcpy(bit_name,
                                                        p_aeu->bit_name, 30);
 
                                        /* We now need to pass bitmask in its
index 17c64e43d6c311e22042a7fca381b26261090b26..158ac07389118278766ae3c9836a13d8f5307981 100644 (file)
@@ -442,7 +442,7 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn,
        /* Vendor specific information */
        dev->vendor_id = cdev->vendor_id;
        dev->vendor_part_id = cdev->device_id;
-       dev->hw_ver = 0;
+       dev->hw_ver = cdev->chip_rev;
        dev->fw_ver = (FW_MAJOR_VERSION << 24) | (FW_MINOR_VERSION << 16) |
                      (FW_REVISION_VERSION << 8) | (FW_ENGINEERING_VERSION);
 
index 60189923737a79f0735ffec15b96c3c110b579d6..21d38167f96180718fdcda68ed2433d73271b1bf 100644 (file)
@@ -206,9 +206,9 @@ rmnet_map_ipv4_ul_csum_header(void *iphdr,
        ul_header->csum_insert_offset = skb->csum_offset;
        ul_header->csum_enabled = 1;
        if (ip4h->protocol == IPPROTO_UDP)
-               ul_header->udp_ip4_ind = 1;
+               ul_header->udp_ind = 1;
        else
-               ul_header->udp_ip4_ind = 0;
+               ul_header->udp_ind = 0;
 
        /* Changing remaining fields to network order */
        hdr++;
@@ -239,6 +239,7 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
                              struct rmnet_map_ul_csum_header *ul_header,
                              struct sk_buff *skb)
 {
+       struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr;
        __be16 *hdr = (__be16 *)ul_header, offset;
 
        offset = htons((__force u16)(skb_transport_header(skb) -
@@ -246,7 +247,11 @@ rmnet_map_ipv6_ul_csum_header(void *ip6hdr,
        ul_header->csum_start_offset = offset;
        ul_header->csum_insert_offset = skb->csum_offset;
        ul_header->csum_enabled = 1;
-       ul_header->udp_ip4_ind = 0;
+
+       if (ip6h->nexthdr == IPPROTO_UDP)
+               ul_header->udp_ind = 1;
+       else
+               ul_header->udp_ind = 0;
 
        /* Changing remaining fields to network order */
        hdr++;
@@ -419,7 +424,7 @@ sw_csum:
        ul_header->csum_start_offset = 0;
        ul_header->csum_insert_offset = 0;
        ul_header->csum_enabled = 0;
-       ul_header->udp_ip4_ind = 0;
+       ul_header->udp_ind = 0;
 
        priv->stats.csum_sw++;
 }
index 6272115b28480a55b081bd2c52ec051791835786..e1dd6ea60d67050f2784a08d2ec2589eef040a35 100644 (file)
@@ -6136,10 +6136,7 @@ static int r8169_phy_connect(struct rtl8169_private *tp)
        if (ret)
                return ret;
 
-       if (tp->supports_gmii)
-               phy_remove_link_mode(phydev,
-                                    ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
-       else
+       if (!tp->supports_gmii)
                phy_set_max_speed(phydev, SPEED_100);
 
        phy_support_asym_pause(phydev);
@@ -6589,13 +6586,18 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
 {
        unsigned int flags;
 
-       if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+       switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
                rtl_unlock_config_regs(tp);
                RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
                rtl_lock_config_regs(tp);
+               /* fall through */
+       case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_24:
                flags = PCI_IRQ_LEGACY;
-       } else {
+               break;
+       default:
                flags = PCI_IRQ_ALL_TYPES;
+               break;
        }
 
        return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
index ef8f08931fe8b9d3cb75daee8a09c18aaa858f5f..6cacd5e893acacfd5da3bc16444de50acd89e764 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Renesas Ethernet AVB device driver
  *
- * Copyright (C) 2014-2015 Renesas Electronics Corporation
+ * Copyright (C) 2014-2019 Renesas Electronics Corporation
  * Copyright (C) 2015 Renesas Solutions Corp.
  * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
  *
@@ -513,7 +513,10 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
                        kfree(ts_skb);
                        if (tag == tfa_tag) {
                                skb_tstamp_tx(skb, &shhwtstamps);
+                               dev_consume_skb_any(skb);
                                break;
+                       } else {
+                               dev_kfree_skb_any(skb);
                        }
                }
                ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
@@ -1564,7 +1567,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                        }
                        goto unmap;
                }
-               ts_skb->skb = skb;
+               ts_skb->skb = skb_get(skb);
                ts_skb->tag = priv->ts_skb_tag++;
                priv->ts_skb_tag &= 0x3ff;
                list_add_tail(&ts_skb->list, &priv->ts_skb_list);
@@ -1693,6 +1696,7 @@ static int ravb_close(struct net_device *ndev)
        /* Clear the timestamp list */
        list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
                list_del(&ts_skb->list);
+               kfree_skb(ts_skb->skb);
                kfree(ts_skb);
        }
 
index 079f459c73a5d45a9802da81caf403c1c4e43d35..2c5d3f5b84dd6ef1096f3289b8c86ebc49b0348b 100644 (file)
@@ -2208,10 +2208,12 @@ static int rocker_router_fib_event(struct notifier_block *nb,
 
                        if (fen_info->fi->fib_nh_is_v6) {
                                NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
+                               kfree(fib_work);
                                return notifier_from_errno(-EINVAL);
                        }
                        if (fen_info->fi->nh) {
                                NL_SET_ERR_MSG_MOD(info->extack, "IPv4 route with nexthop objects is not supported");
+                               kfree(fib_work);
                                return notifier_from_errno(-EINVAL);
                        }
                }
index 027938017579130fd1072b0b3c0745a541933107..e92a178a76df0849600734c1193ee0cbdbc9ca19 100644 (file)
@@ -11,7 +11,7 @@ config NET_VENDOR_SAMSUNG
          say Y.
 
          Note that the answer to this question does not directly affect
-         the kernel: saying N will just case the configurator to skip all
+         the kernel: saying N will just cause the configurator to skip all
          the questions about Samsung chipsets. If you say Y, you will be asked
          for your specific chipset/driver in the following questions.
 
index bd14803545de30b7fb7c7a7ff0201227cdd39bdb..8d88e40834567fc23797515f55dbe0e08543622d 100644 (file)
@@ -712,6 +712,7 @@ static void smc911x_phy_detect(struct net_device *dev)
                                        /* Found an external PHY */
                                        break;
                        }
+                       /* Else, fall through */
                default:
                        /* Internal media only */
                        SMC_GET_PHY_ID1(lp, 1, id1);
index 01c2e2d83e76dc78eadbb6faef74ec620199d1a2..fc9954e4a7729e79b86313af8d916290006ba9c2 100644 (file)
@@ -85,6 +85,8 @@ static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
        u32 value;
 
        base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + base_register);
 
@@ -102,6 +104,8 @@ static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
        u32 value;
 
        base_register = (queue < 4) ? GMAC_TXQ_PRTY_MAP0 : GMAC_TXQ_PRTY_MAP1;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + base_register);
 
index 7f86dffb264d352f57019c581baedda9a798e285..3174b701aa903f6b07f6267dbc4fac64cfc1c818 100644 (file)
 #define XGMAC_CORE_INIT_RX             0
 #define XGMAC_PACKET_FILTER            0x00000008
 #define XGMAC_FILTER_RA                        BIT(31)
+#define XGMAC_FILTER_HPF               BIT(10)
 #define XGMAC_FILTER_PCF               BIT(7)
 #define XGMAC_FILTER_PM                        BIT(4)
 #define XGMAC_FILTER_HMC               BIT(2)
 #define XGMAC_FILTER_PR                        BIT(0)
 #define XGMAC_HASH_TABLE(x)            (0x00000010 + (x) * 4)
+#define XGMAC_MAX_HASH_TABLE           8
 #define XGMAC_RXQ_CTRL0                        0x000000a0
 #define XGMAC_RXQEN(x)                 GENMASK((x) * 2 + 1, (x) * 2)
 #define XGMAC_RXQEN_SHIFT(x)           ((x) * 2)
 #define XGMAC_MDIO_ADDR                        0x00000200
 #define XGMAC_MDIO_DATA                        0x00000204
 #define XGMAC_MDIO_C22P                        0x00000220
-#define XGMAC_ADDR0_HIGH               0x00000300
+#define XGMAC_ADDRx_HIGH(x)            (0x00000300 + (x) * 0x8)
+#define XGMAC_ADDR_MAX                 32
 #define XGMAC_AE                       BIT(31)
 #define XGMAC_DCS                      GENMASK(19, 16)
 #define XGMAC_DCS_SHIFT                        16
-#define XGMAC_ADDR0_LOW                        0x00000304
+#define XGMAC_ADDRx_LOW(x)             (0x00000304 + (x) * 0x8)
 #define XGMAC_ARP_ADDR                 0x00000c10
 #define XGMAC_TIMESTAMP_STATUS         0x00000d20
 #define XGMAC_TXTSC                    BIT(15)
index 0a32c96a7854e95eef3b7f0834249131760bd612..85c68b7ee8c6a557cb8a306d5bbb6ae633432c0b 100644 (file)
@@ -4,6 +4,8 @@
  * stmmac XGMAC support.
  */
 
+#include <linux/bitrev.h>
+#include <linux/crc32.h>
 #include "stmmac.h"
 #include "dwxgmac2.h"
 
@@ -106,6 +108,8 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
        u32 value, reg;
 
        reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + reg);
        value &= ~XGMAC_PSRQ(queue);
@@ -169,6 +173,8 @@ static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue,
        u32 value, reg;
 
        reg = (queue < 4) ? XGMAC_MTL_RXQ_DMA_MAP0 : XGMAC_MTL_RXQ_DMA_MAP1;
+       if (queue >= 4)
+               queue -= 4;
 
        value = readl(ioaddr + reg);
        value &= ~XGMAC_QxMDMACH(queue);
@@ -278,10 +284,10 @@ static void dwxgmac2_set_umac_addr(struct mac_device_info *hw,
        u32 value;
 
        value = (addr[5] << 8) | addr[4];
-       writel(value | XGMAC_AE, ioaddr + XGMAC_ADDR0_HIGH);
+       writel(value | XGMAC_AE, ioaddr + XGMAC_ADDRx_HIGH(reg_n));
 
        value = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
-       writel(value, ioaddr + XGMAC_ADDR0_LOW);
+       writel(value, ioaddr + XGMAC_ADDRx_LOW(reg_n));
 }
 
 static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
@@ -291,8 +297,8 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
        u32 hi_addr, lo_addr;
 
        /* Read the MAC address from the hardware */
-       hi_addr = readl(ioaddr + XGMAC_ADDR0_HIGH);
-       lo_addr = readl(ioaddr + XGMAC_ADDR0_LOW);
+       hi_addr = readl(ioaddr + XGMAC_ADDRx_HIGH(reg_n));
+       lo_addr = readl(ioaddr + XGMAC_ADDRx_LOW(reg_n));
 
        /* Extract the MAC address from the high and low words */
        addr[0] = lo_addr & 0xff;
@@ -303,19 +309,82 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
        addr[5] = (hi_addr >> 8) & 0xff;
 }
 
+static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
+                               int mcbitslog2)
+{
+       int numhashregs, regs;
+
+       switch (mcbitslog2) {
+       case 6:
+               numhashregs = 2;
+               break;
+       case 7:
+               numhashregs = 4;
+               break;
+       case 8:
+               numhashregs = 8;
+               break;
+       default:
+               return;
+       }
+
+       for (regs = 0; regs < numhashregs; regs++)
+               writel(mcfilterbits[regs], ioaddr + XGMAC_HASH_TABLE(regs));
+}
+
 static void dwxgmac2_set_filter(struct mac_device_info *hw,
                                struct net_device *dev)
 {
        void __iomem *ioaddr = (void __iomem *)dev->base_addr;
-       u32 value = XGMAC_FILTER_RA;
+       u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
+       int mcbitslog2 = hw->mcast_bits_log2;
+       u32 mc_filter[8];
+       int i;
+
+       value &= ~(XGMAC_FILTER_PR | XGMAC_FILTER_HMC | XGMAC_FILTER_PM);
+       value |= XGMAC_FILTER_HPF;
+
+       memset(mc_filter, 0, sizeof(mc_filter));
 
        if (dev->flags & IFF_PROMISC) {
-               value |= XGMAC_FILTER_PR | XGMAC_FILTER_PCF;
+               value |= XGMAC_FILTER_PR;
+               value |= XGMAC_FILTER_PCF;
        } else if ((dev->flags & IFF_ALLMULTI) ||
-                  (netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
+                  (netdev_mc_count(dev) > hw->multicast_filter_bins)) {
                value |= XGMAC_FILTER_PM;
-               writel(~0x0, ioaddr + XGMAC_HASH_TABLE(0));
-               writel(~0x0, ioaddr + XGMAC_HASH_TABLE(1));
+
+               for (i = 0; i < XGMAC_MAX_HASH_TABLE; i++)
+                       writel(~0x0, ioaddr + XGMAC_HASH_TABLE(i));
+       } else if (!netdev_mc_empty(dev)) {
+               struct netdev_hw_addr *ha;
+
+               value |= XGMAC_FILTER_HMC;
+
+               netdev_for_each_mc_addr(ha, dev) {
+                       int nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
+                                       (32 - mcbitslog2));
+                       mc_filter[nr >> 5] |= (1 << (nr & 0x1F));
+               }
+       }
+
+       dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2);
+
+       /* Handle multiple unicast addresses */
+       if (netdev_uc_count(dev) > XGMAC_ADDR_MAX) {
+               value |= XGMAC_FILTER_PR;
+       } else {
+               struct netdev_hw_addr *ha;
+               int reg = 1;
+
+               netdev_for_each_uc_addr(ha, dev) {
+                       dwxgmac2_set_umac_addr(hw, ha->addr, reg);
+                       reg++;
+               }
+
+               for ( ; reg < XGMAC_ADDR_MAX; reg++) {
+                       writel(0, ioaddr + XGMAC_ADDRx_HIGH(reg));
+                       writel(0, ioaddr + XGMAC_ADDRx_LOW(reg));
+               }
        }
 
        writel(value, ioaddr + XGMAC_PACKET_FILTER);
index c7c9e5f162e6de73f2534dc5f8d5b5a38222e743..fd54c7c8748548e279cc5293ea3df19d656c6366 100644 (file)
@@ -814,20 +814,15 @@ static void stmmac_validate(struct phylink_config *config,
        phylink_set(mac_supported, 10baseT_Full);
        phylink_set(mac_supported, 100baseT_Half);
        phylink_set(mac_supported, 100baseT_Full);
+       phylink_set(mac_supported, 1000baseT_Half);
+       phylink_set(mac_supported, 1000baseT_Full);
+       phylink_set(mac_supported, 1000baseKX_Full);
 
        phylink_set(mac_supported, Autoneg);
        phylink_set(mac_supported, Pause);
        phylink_set(mac_supported, Asym_Pause);
        phylink_set_port_modes(mac_supported);
 
-       if (priv->plat->has_gmac ||
-           priv->plat->has_gmac4 ||
-           priv->plat->has_xgmac) {
-               phylink_set(mac_supported, 1000baseT_Half);
-               phylink_set(mac_supported, 1000baseT_Full);
-               phylink_set(mac_supported, 1000baseKX_Full);
-       }
-
        /* Cut down 1G if asked to */
        if ((max_speed > 0) && (max_speed < 1000)) {
                phylink_set(mask, 1000baseT_Full);
@@ -1295,6 +1290,8 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
                          "(%s) dma_rx_phy=0x%08x\n", __func__,
                          (u32)rx_q->dma_rx_phy);
 
+               stmmac_clear_rx_descriptors(priv, queue);
+
                for (i = 0; i < DMA_RX_SIZE; i++) {
                        struct dma_desc *p;
 
@@ -1312,8 +1309,6 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
                rx_q->cur_rx = 0;
                rx_q->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
 
-               stmmac_clear_rx_descriptors(priv, queue);
-
                /* Setup the chained descriptor addresses */
                if (priv->mode == STMMAC_CHAIN_MODE) {
                        if (priv->extend_desc)
@@ -1555,9 +1550,8 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
                        goto err_dma;
                }
 
-               rx_q->buf_pool = kmalloc_array(DMA_RX_SIZE,
-                                              sizeof(*rx_q->buf_pool),
-                                              GFP_KERNEL);
+               rx_q->buf_pool = kcalloc(DMA_RX_SIZE, sizeof(*rx_q->buf_pool),
+                                        GFP_KERNEL);
                if (!rx_q->buf_pool)
                        goto err_dma;
 
@@ -1608,15 +1602,15 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                tx_q->queue_index = queue;
                tx_q->priv_data = priv;
 
-               tx_q->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE,
-                                                   sizeof(*tx_q->tx_skbuff_dma),
-                                                   GFP_KERNEL);
+               tx_q->tx_skbuff_dma = kcalloc(DMA_TX_SIZE,
+                                             sizeof(*tx_q->tx_skbuff_dma),
+                                             GFP_KERNEL);
                if (!tx_q->tx_skbuff_dma)
                        goto err_dma;
 
-               tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE,
-                                               sizeof(struct sk_buff *),
-                                               GFP_KERNEL);
+               tx_q->tx_skbuff = kcalloc(DMA_TX_SIZE,
+                                         sizeof(struct sk_buff *),
+                                         GFP_KERNEL);
                if (!tx_q->tx_skbuff)
                        goto err_dma;
 
@@ -3277,9 +3271,11 @@ static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q)
 static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
 {
        struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
-       int dirty = stmmac_rx_dirty(priv, queue);
+       int len, dirty = stmmac_rx_dirty(priv, queue);
        unsigned int entry = rx_q->dirty_rx;
 
+       len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
+
        while (dirty-- > 0) {
                struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry];
                struct dma_desc *p;
@@ -3297,6 +3293,13 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
                }
 
                buf->addr = page_pool_get_dma_addr(buf->page);
+
+               /* Sync whole allocation to device. This will invalidate old
+                * data.
+                */
+               dma_sync_single_for_device(priv->device, buf->addr, len,
+                                          DMA_FROM_DEVICE);
+
                stmmac_set_desc_addr(priv, p, buf->addr);
                stmmac_refill_desc3(priv, rx_q, p);
 
@@ -3431,8 +3434,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
                        skb_copy_to_linear_data(skb, page_address(buf->page),
                                                frame_len);
                        skb_put(skb, frame_len);
-                       dma_sync_single_for_device(priv->device, buf->addr,
-                                                  frame_len, DMA_FROM_DEVICE);
 
                        if (netif_msg_pktdata(priv)) {
                                netdev_dbg(priv->dev, "frame received (%dbytes)",
@@ -4319,8 +4320,9 @@ int stmmac_dvr_probe(struct device *device,
                                       NAPI_POLL_WEIGHT);
                }
                if (queue < priv->plat->tx_queues_to_use) {
-                       netif_napi_add(ndev, &ch->tx_napi, stmmac_napi_poll_tx,
-                                      NAPI_POLL_WEIGHT);
+                       netif_tx_napi_add(ndev, &ch->tx_napi,
+                                         stmmac_napi_poll_tx,
+                                         NAPI_POLL_WEIGHT);
                }
        }
 
index 73fc2524372e25269a3f4e39987ae65270054ef3..154daf4d10724e9928770319167c16fadc5a476a 100644 (file)
@@ -370,6 +370,13 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
                return ERR_PTR(-ENOMEM);
 
        *mac = of_get_mac_address(np);
+       if (IS_ERR(*mac)) {
+               if (PTR_ERR(*mac) == -EPROBE_DEFER)
+                       return ERR_CAST(*mac);
+
+               *mac = NULL;
+       }
+
        plat->interface = of_get_phy_mode(np);
 
        /* Some wrapper drivers still rely on phy_node. Let's save it while
index 58ea18af9813ab950b1252cde08d626abe61c30e..6c305b6ecad04a9077f15e6f063bc5aba6914561 100644 (file)
@@ -37,7 +37,7 @@ static struct stmmac_tc_entry *tc_find_entry(struct stmmac_priv *priv,
                entry = &priv->tc_entries[i];
                if (!entry->in_use && !first && free)
                        first = entry;
-               if (entry->handle == loc && !free)
+               if ((entry->handle == loc) && !free && !entry->is_frag)
                        dup = entry;
        }
 
@@ -94,7 +94,7 @@ static int tc_fill_entry(struct stmmac_priv *priv,
        struct stmmac_tc_entry *entry, *frag = NULL;
        struct tc_u32_sel *sel = cls->knode.sel;
        u32 off, data, mask, real_off, rem;
-       u32 prio = cls->common.prio;
+       u32 prio = cls->common.prio << 16;
        int ret;
 
        /* Only 1 match per entry */
index 5b196ebfed492e44b381f46b5eaa1d5d0d2e8f3e..0f346761a2b294ecd519a3e7ed8f5d389dcc91f3 100644 (file)
@@ -788,6 +788,7 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
                        /* fallthrough, if we release the descriptors
                         * brutally (then we don't care about
                         * SPIDER_NET_DESCR_CARDOWNED) */
+                       /* Fall through */
 
                case SPIDER_NET_DESCR_RESPONSE_ERROR:
                case SPIDER_NET_DESCR_PROTECTION_ERROR:
index 8479a440527b8902cfc6b1b5cd25ef34c6171e7b..12466a72cefceafa86830a1f68280f432da3ffb5 100644 (file)
@@ -1504,7 +1504,7 @@ tc35815_rx(struct net_device *dev, int limit)
                        pci_unmap_single(lp->pci_dev,
                                         lp->rx_skbs[cur_bd].skb_dma,
                                         RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-                       if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN)
+                       if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN != 0)
                                memmove(skb->data, skb->data - NET_IP_ALIGN,
                                        pkt_len);
                        data = skb_put(skb, pkt_len);
index 78a7de3fb622f4d98fae24768297caa9bcf1003c..c62f474b6d08eb74c159811c9ea32549845072e9 100644 (file)
@@ -371,9 +371,10 @@ tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift,
 static void tsi108_stat_carry(struct net_device *dev)
 {
        struct tsi108_prv_data *data = netdev_priv(dev);
+       unsigned long flags;
        u32 carry1, carry2;
 
-       spin_lock_irq(&data->misclock);
+       spin_lock_irqsave(&data->misclock, flags);
 
        carry1 = TSI_READ(TSI108_STAT_CARRY1);
        carry2 = TSI_READ(TSI108_STAT_CARRY2);
@@ -441,7 +442,7 @@ static void tsi108_stat_carry(struct net_device *dev)
                              TSI108_STAT_TXPAUSEDROP_CARRY,
                              &data->tx_pause_drop);
 
-       spin_unlock_irq(&data->misclock);
+       spin_unlock_irqrestore(&data->misclock, flags);
 }
 
 /* Read a stat counter atomically with respect to carries.
index 2f354ba029a6149154a66de43e3abc44139996e7..cd0a8f46e7c6c1438231e7f845e5dcc025adc456 100644 (file)
@@ -13,7 +13,7 @@ config NET_VENDOR_XSCALE
 
          Note that the answer to this question does not directly affect the
          kernel: saying N will just cause the configurator to skip all
-         the questions about XSacle IXP devices. If you say Y, you will be
+         the questions about XScale IXP devices. If you say Y, you will be
          asked for your specific card in the following questions.
 
 if NET_VENDOR_XSCALE
index daab2c07d891dc3d718c7122708e695ea553507b..9303aeb2595f412cefa9ddcaca09ff93f9a4ecd8 100644 (file)
@@ -500,8 +500,9 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
                                }
                                break;
                        }
+                       /* fall through */
 
-               default:  /* fall through */
+               default:
                        if (bc->hdlctx.calibrate <= 0)
                                return 0;
                        i = min_t(int, cnt, bc->hdlctx.calibrate);
index 3544e19915792df3e162b83983bdbf4647a42ab7..e8fce6d715ef069fe2e482b014b4d3f6e4f3e088 100644 (file)
@@ -1239,12 +1239,15 @@ static void netvsc_get_stats64(struct net_device *net,
                               struct rtnl_link_stats64 *t)
 {
        struct net_device_context *ndev_ctx = netdev_priv(net);
-       struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev);
+       struct netvsc_device *nvdev;
        struct netvsc_vf_pcpu_stats vf_tot;
        int i;
 
+       rcu_read_lock();
+
+       nvdev = rcu_dereference(ndev_ctx->nvdev);
        if (!nvdev)
-               return;
+               goto out;
 
        netdev_stats_to_stats64(t, &net->stats);
 
@@ -1283,6 +1286,8 @@ static void netvsc_get_stats64(struct net_device *net,
                t->rx_packets   += packets;
                t->multicast    += multicast;
        }
+out:
+       rcu_read_unlock();
 }
 
 static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
index c5c417a3c0ce71d46bf1c5e4dd77dfd261b26407..bcc40a2366248be1954f4ba7d67184009b58e548 100644 (file)
@@ -73,46 +73,47 @@ static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
        debugfs_remove_recursive(nsim_dev_port->ddir);
 }
 
+static struct net *nsim_devlink_net(struct devlink *devlink)
+{
+       return &init_net;
+}
+
 static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV4_FIB, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false);
 }
 
 static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV4_FIB_RULES, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false);
 }
 
 static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV6_FIB, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false);
 }
 
 static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv)
 {
-       struct nsim_dev *nsim_dev = priv;
+       struct net *net = priv;
 
-       return nsim_fib_get_val(nsim_dev->fib_data,
-                               NSIM_RESOURCE_IPV6_FIB_RULES, false);
+       return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false);
 }
 
 static int nsim_dev_resources_register(struct devlink *devlink)
 {
-       struct nsim_dev *nsim_dev = devlink_priv(devlink);
        struct devlink_resource_size_params params = {
                .size_max = (u64)-1,
                .size_granularity = 1,
                .unit = DEVLINK_RESOURCE_UNIT_ENTRY
        };
+       struct net *net = nsim_devlink_net(devlink);
        int err;
        u64 n;
 
@@ -126,8 +127,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                goto out;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV4_FIB, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV4_FIB,
                                        NSIM_RESOURCE_IPV4, &params);
@@ -136,8 +136,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                return err;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV4_FIB_RULES, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV4_FIB_RULES,
                                        NSIM_RESOURCE_IPV4, &params);
@@ -156,8 +155,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                goto out;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV6_FIB, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true);
        err = devlink_resource_register(devlink, "fib", n,
                                        NSIM_RESOURCE_IPV6_FIB,
                                        NSIM_RESOURCE_IPV6, &params);
@@ -166,8 +164,7 @@ static int nsim_dev_resources_register(struct devlink *devlink)
                return err;
        }
 
-       n = nsim_fib_get_val(nsim_dev->fib_data,
-                            NSIM_RESOURCE_IPV6_FIB_RULES, true);
+       n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true);
        err = devlink_resource_register(devlink, "fib-rules", n,
                                        NSIM_RESOURCE_IPV6_FIB_RULES,
                                        NSIM_RESOURCE_IPV6, &params);
@@ -179,19 +176,19 @@ static int nsim_dev_resources_register(struct devlink *devlink)
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV4_FIB,
                                          nsim_dev_ipv4_fib_resource_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV4_FIB_RULES,
                                          nsim_dev_ipv4_fib_rules_res_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV6_FIB,
                                          nsim_dev_ipv6_fib_resource_occ_get,
-                                         nsim_dev);
+                                         net);
        devlink_resource_occ_get_register(devlink,
                                          NSIM_RESOURCE_IPV6_FIB_RULES,
                                          nsim_dev_ipv6_fib_rules_res_occ_get,
-                                         nsim_dev);
+                                         net);
 out:
        return err;
 }
@@ -199,11 +196,11 @@ out:
 static int nsim_dev_reload(struct devlink *devlink,
                           struct netlink_ext_ack *extack)
 {
-       struct nsim_dev *nsim_dev = devlink_priv(devlink);
        enum nsim_resource_id res_ids[] = {
                NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES,
                NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES
        };
+       struct net *net = nsim_devlink_net(devlink);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(res_ids); ++i) {
@@ -212,8 +209,7 @@ static int nsim_dev_reload(struct devlink *devlink,
 
                err = devlink_resource_size_get(devlink, res_ids[i], &val);
                if (!err) {
-                       err = nsim_fib_set_max(nsim_dev->fib_data,
-                                              res_ids[i], val, extack);
+                       err = nsim_fib_set_max(net, res_ids[i], val, extack);
                        if (err)
                                return err;
                }
@@ -285,15 +281,9 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
        mutex_init(&nsim_dev->port_list_lock);
        nsim_dev->fw_update_status = true;
 
-       nsim_dev->fib_data = nsim_fib_create();
-       if (IS_ERR(nsim_dev->fib_data)) {
-               err = PTR_ERR(nsim_dev->fib_data);
-               goto err_devlink_free;
-       }
-
        err = nsim_dev_resources_register(devlink);
        if (err)
-               goto err_fib_destroy;
+               goto err_devlink_free;
 
        err = devlink_register(devlink, &nsim_bus_dev->dev);
        if (err)
@@ -315,8 +305,6 @@ err_dl_unregister:
        devlink_unregister(devlink);
 err_resources_unregister:
        devlink_resources_unregister(devlink, NULL);
-err_fib_destroy:
-       nsim_fib_destroy(nsim_dev->fib_data);
 err_devlink_free:
        devlink_free(devlink);
        return ERR_PTR(err);
@@ -330,7 +318,6 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
        nsim_dev_debugfs_exit(nsim_dev);
        devlink_unregister(devlink);
        devlink_resources_unregister(devlink, NULL);
-       nsim_fib_destroy(nsim_dev->fib_data);
        mutex_destroy(&nsim_dev->port_list_lock);
        devlink_free(devlink);
 }
index 8c57ba7477726650bb6c0b188a2c8ebb989b14d7..f61d094746c069bb7ac1c6db9eb77fe0820d2562 100644 (file)
@@ -18,6 +18,7 @@
 #include <net/ip_fib.h>
 #include <net/ip6_fib.h>
 #include <net/fib_rules.h>
+#include <net/netns/generic.h>
 
 #include "netdevsim.h"
 
@@ -32,14 +33,15 @@ struct nsim_per_fib_data {
 };
 
 struct nsim_fib_data {
-       struct notifier_block fib_nb;
        struct nsim_per_fib_data ipv4;
        struct nsim_per_fib_data ipv6;
 };
 
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, bool max)
+static unsigned int nsim_fib_net_id;
+
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max)
 {
+       struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
        struct nsim_fib_entry *entry;
 
        switch (res_id) {
@@ -62,10 +64,10 @@ u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
        return max ? entry->max : entry->num;
 }
 
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, u64 val,
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
                     struct netlink_ext_ack *extack)
 {
+       struct nsim_fib_data *fib_data = net_generic(net, nsim_fib_net_id);
        struct nsim_fib_entry *entry;
        int err = 0;
 
@@ -118,9 +120,9 @@ static int nsim_fib_rule_account(struct nsim_fib_entry *entry, bool add,
        return err;
 }
 
-static int nsim_fib_rule_event(struct nsim_fib_data *data,
-                              struct fib_notifier_info *info, bool add)
+static int nsim_fib_rule_event(struct fib_notifier_info *info, bool add)
 {
+       struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
        struct netlink_ext_ack *extack = info->extack;
        int err = 0;
 
@@ -155,9 +157,9 @@ static int nsim_fib_account(struct nsim_fib_entry *entry, bool add,
        return err;
 }
 
-static int nsim_fib_event(struct nsim_fib_data *data,
-                         struct fib_notifier_info *info, bool add)
+static int nsim_fib_event(struct fib_notifier_info *info, bool add)
 {
+       struct nsim_fib_data *data = net_generic(info->net, nsim_fib_net_id);
        struct netlink_ext_ack *extack = info->extack;
        int err = 0;
 
@@ -176,22 +178,18 @@ static int nsim_fib_event(struct nsim_fib_data *data,
 static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
                             void *ptr)
 {
-       struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
-                                                 fib_nb);
        struct fib_notifier_info *info = ptr;
        int err = 0;
 
        switch (event) {
        case FIB_EVENT_RULE_ADD: /* fall through */
        case FIB_EVENT_RULE_DEL:
-               err = nsim_fib_rule_event(data, info,
-                                         event == FIB_EVENT_RULE_ADD);
+               err = nsim_fib_rule_event(info, event == FIB_EVENT_RULE_ADD);
                break;
 
        case FIB_EVENT_ENTRY_ADD:  /* fall through */
        case FIB_EVENT_ENTRY_DEL:
-               err = nsim_fib_event(data, info,
-                                    event == FIB_EVENT_ENTRY_ADD);
+               err = nsim_fib_event(info, event == FIB_EVENT_ENTRY_ADD);
                break;
        }
 
@@ -201,23 +199,30 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event,
 /* inconsistent dump, trying again */
 static void nsim_fib_dump_inconsistent(struct notifier_block *nb)
 {
-       struct nsim_fib_data *data = container_of(nb, struct nsim_fib_data,
-                                                 fib_nb);
+       struct nsim_fib_data *data;
+       struct net *net;
+
+       rcu_read_lock();
+       for_each_net_rcu(net) {
+               data = net_generic(net, nsim_fib_net_id);
+
+               data->ipv4.fib.num = 0ULL;
+               data->ipv4.rules.num = 0ULL;
 
-       data->ipv4.fib.num = 0ULL;
-       data->ipv4.rules.num = 0ULL;
-       data->ipv6.fib.num = 0ULL;
-       data->ipv6.rules.num = 0ULL;
+               data->ipv6.fib.num = 0ULL;
+               data->ipv6.rules.num = 0ULL;
+       }
+       rcu_read_unlock();
 }
 
-struct nsim_fib_data *nsim_fib_create(void)
-{
-       struct nsim_fib_data *data;
-       int err;
+static struct notifier_block nsim_fib_nb = {
+       .notifier_call = nsim_fib_event_nb,
+};
 
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return ERR_PTR(-ENOMEM);
+/* Initialize per network namespace state */
+static int __net_init nsim_fib_netns_init(struct net *net)
+{
+       struct nsim_fib_data *data = net_generic(net, nsim_fib_net_id);
 
        data->ipv4.fib.max = (u64)-1;
        data->ipv4.rules.max = (u64)-1;
@@ -225,22 +230,37 @@ struct nsim_fib_data *nsim_fib_create(void)
        data->ipv6.fib.max = (u64)-1;
        data->ipv6.rules.max = (u64)-1;
 
-       data->fib_nb.notifier_call = nsim_fib_event_nb;
-       err = register_fib_notifier(&data->fib_nb, nsim_fib_dump_inconsistent);
-       if (err) {
-               pr_err("Failed to register fib notifier\n");
-               goto err_out;
-       }
+       return 0;
+}
 
-       return data;
+static struct pernet_operations nsim_fib_net_ops = {
+       .init = nsim_fib_netns_init,
+       .id   = &nsim_fib_net_id,
+       .size = sizeof(struct nsim_fib_data),
+};
 
-err_out:
-       kfree(data);
-       return ERR_PTR(err);
+void nsim_fib_exit(void)
+{
+       unregister_pernet_subsys(&nsim_fib_net_ops);
+       unregister_fib_notifier(&nsim_fib_nb);
 }
 
-void nsim_fib_destroy(struct nsim_fib_data *data)
+int nsim_fib_init(void)
 {
-       unregister_fib_notifier(&data->fib_nb);
-       kfree(data);
+       int err;
+
+       err = register_pernet_subsys(&nsim_fib_net_ops);
+       if (err < 0) {
+               pr_err("Failed to register pernet subsystem\n");
+               goto err_out;
+       }
+
+       err = register_fib_notifier(&nsim_fib_nb, nsim_fib_dump_inconsistent);
+       if (err < 0) {
+               pr_err("Failed to register fib notifier\n");
+               goto err_out;
+       }
+
+err_out:
+       return err;
 }
index 0740940f41b12949558b6150edec27917d3cfe3c..55f57f76d01bb014e8c79b93c739cb1da29460a5 100644 (file)
@@ -357,12 +357,18 @@ static int __init nsim_module_init(void)
        if (err)
                goto err_dev_exit;
 
-       err = rtnl_link_register(&nsim_link_ops);
+       err = nsim_fib_init();
        if (err)
                goto err_bus_exit;
 
+       err = rtnl_link_register(&nsim_link_ops);
+       if (err)
+               goto err_fib_exit;
+
        return 0;
 
+err_fib_exit:
+       nsim_fib_exit();
 err_bus_exit:
        nsim_bus_exit();
 err_dev_exit:
@@ -373,6 +379,7 @@ err_dev_exit:
 static void __exit nsim_module_exit(void)
 {
        rtnl_link_unregister(&nsim_link_ops);
+       nsim_fib_exit();
        nsim_bus_exit();
        nsim_dev_exit();
 }
index 79c05af2a7c0505d6f68eb1345d7629afa61d5b6..9404637d34b7ab30da70c32492abec2b1c07558b 100644 (file)
@@ -169,12 +169,10 @@ int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
 int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
                      unsigned int port_index);
 
-struct nsim_fib_data *nsim_fib_create(void);
-void nsim_fib_destroy(struct nsim_fib_data *fib_data);
-u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, bool max);
-int nsim_fib_set_max(struct nsim_fib_data *fib_data,
-                    enum nsim_resource_id res_id, u64 val,
+int nsim_fib_init(void);
+void nsim_fib_exit(void);
+u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max);
+int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val,
                     struct netlink_ext_ack *extack);
 
 #if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
index 222ccd9ecfcebc0bf92beb82e177fba7c3bfaea5..6ad8b1c63c3426c9f7a554eceb6033bab675be62 100644 (file)
@@ -257,36 +257,20 @@ static int at803x_config_init(struct phy_device *phydev)
         *   after HW reset: RX delay enabled and TX delay disabled
         *   after SW reset: RX delay enabled, while TX delay retains the
         *   value before reset.
-        *
-        * So let's first disable the RX and TX delays in PHY and enable
-        * them based on the mode selected (this also takes care of RGMII
-        * mode where we expect delays to be disabled)
         */
-
-       ret = at803x_disable_rx_delay(phydev);
-       if (ret < 0)
-               return ret;
-       ret = at803x_disable_tx_delay(phydev);
-       if (ret < 0)
-               return ret;
-
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-           phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
-               /* If RGMII_ID or RGMII_RXID are specified enable RX delay,
-                * otherwise keep it disabled
-                */
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
                ret = at803x_enable_rx_delay(phydev);
-               if (ret < 0)
-                       return ret;
-       }
+       else
+               ret = at803x_disable_rx_delay(phydev);
+       if (ret < 0)
+               return ret;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
-               /* If RGMII_ID or RGMII_TXID are specified enable TX delay,
-                * otherwise keep it disabled
-                */
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
                ret = at803x_enable_tx_delay(phydev);
-       }
+       else
+               ret = at803x_disable_tx_delay(phydev);
 
        return ret;
 }
index 3ffe46df249ee2a482b748ac66a79ff31141690a..7c5265fd2b94d31f03ce61ce0f9505310d434f7b 100644 (file)
@@ -216,8 +216,10 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np)
        if (IS_ERR(gpiod)) {
                if (PTR_ERR(gpiod) == -EPROBE_DEFER)
                        return gpiod;
-               pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
-                      fixed_link_node);
+
+               if (PTR_ERR(gpiod) != -ENOENT)
+                       pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
+                              fixed_link_node);
                gpiod = NULL;
        }
 
index 28676af97b42c275f6d2df4a285d3d6d391ec7f6..645d354ffb4852605f19782ff60815f517d72e40 100644 (file)
@@ -2226,8 +2226,8 @@ static int vsc8514_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc85xx_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
@@ -2251,8 +2251,8 @@ static int vsc8574_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc8584_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
@@ -2281,8 +2281,8 @@ static int vsc8584_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC8584_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc8584_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc8584_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
@@ -2311,8 +2311,8 @@ static int vsc85xx_probe(struct phy_device *phydev)
        vsc8531->supp_led_modes = VSC85XX_SUPP_LED_MODES;
        vsc8531->hw_stats = vsc85xx_hw_stats;
        vsc8531->nstats = ARRAY_SIZE(vsc85xx_hw_stats);
-       vsc8531->stats = devm_kmalloc_array(&phydev->mdio.dev, vsc8531->nstats,
-                                           sizeof(u64), GFP_KERNEL);
+       vsc8531->stats = devm_kcalloc(&phydev->mdio.dev, vsc8531->nstats,
+                                     sizeof(u64), GFP_KERNEL);
        if (!vsc8531->stats)
                return -ENOMEM;
 
index b9d4145781caa092625adb94214549a02b66fd50..58bb25e4af1066ab8d4cc624884e247e37c6c5a7 100644 (file)
@@ -219,6 +219,20 @@ int genphy_c45_read_link(struct phy_device *phydev)
        int val, devad;
        bool link = true;
 
+       if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
+               val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
+               if (val < 0)
+                       return val;
+
+               /* Autoneg is being started, therefore disregard current
+                * link status and report link as down.
+                */
+               if (val & MDIO_AN_CTRL1_RESTART) {
+                       phydev->link = 0;
+                       return 0;
+               }
+       }
+
        while (mmd_mask && link) {
                devad = __ffs(mmd_mask);
                mmd_mask &= ~BIT(devad);
index 6b5cb87f38661d70b4e2d1ea30eccbe2e7200f73..27ebc2c6c2d0c4eb111f39a5596f50d976ca4a1a 100644 (file)
@@ -1752,7 +1752,17 @@ EXPORT_SYMBOL(genphy_aneg_done);
  */
 int genphy_update_link(struct phy_device *phydev)
 {
-       int status;
+       int status = 0, bmcr;
+
+       bmcr = phy_read(phydev, MII_BMCR);
+       if (bmcr < 0)
+               return bmcr;
+
+       /* Autoneg is being started, therefore disregard BMSR value and
+        * report link as down.
+        */
+       if (bmcr & BMCR_ANRESTART)
+               goto done;
 
        /* The link state is latched low so that momentary link
         * drops can be detected. Do not double-read the status
@@ -1774,6 +1784,12 @@ done:
        phydev->link = status & BMSR_LSTATUS ? 1 : 0;
        phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
 
+       /* Consider the case that autoneg was started and "aneg complete"
+        * bit has been reset, but "link up" bit not yet.
+        */
+       if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
+               phydev->link = 0;
+
        return 0;
 }
 EXPORT_SYMBOL(genphy_update_link);
index b86a4b2116f8156af6c32f82a6e8df9bfaa441d0..59a94e07e7c55b88d860cac214603228c22f021d 100644 (file)
@@ -48,8 +48,9 @@ void phy_led_trigger_change_speed(struct phy_device *phy)
                if (!phy->last_triggered)
                        led_trigger_event(&phy->led_link_trigger->trigger,
                                          LED_FULL);
+               else
+                       led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
 
-               led_trigger_event(&phy->last_triggered->trigger, LED_OFF);
                led_trigger_event(&plt->trigger, LED_FULL);
                phy->last_triggered = plt;
        }
index 5d0af041b8f9f662d957d19353b05a8cb4bf4157..a45c5de96ab1c9688c0ed1eaa99f60fef3294230 100644 (file)
@@ -216,6 +216,8 @@ static int phylink_parse_fixedlink(struct phylink *pl,
                               pl->supported, true);
        linkmode_zero(pl->supported);
        phylink_set(pl->supported, MII);
+       phylink_set(pl->supported, Pause);
+       phylink_set(pl->supported, Asym_Pause);
        if (s) {
                __set_bit(s->bit, pl->supported);
        } else {
@@ -990,10 +992,10 @@ void phylink_start(struct phylink *pl)
        }
        if (pl->link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
                mod_timer(&pl->link_poll, jiffies + HZ);
-       if (pl->sfp_bus)
-               sfp_upstream_start(pl->sfp_bus);
        if (pl->phydev)
                phy_start(pl->phydev);
+       if (pl->sfp_bus)
+               sfp_upstream_start(pl->sfp_bus);
 }
 EXPORT_SYMBOL_GPL(phylink_start);
 
@@ -1010,10 +1012,10 @@ void phylink_stop(struct phylink *pl)
 {
        ASSERT_RTNL();
 
-       if (pl->phydev)
-               phy_stop(pl->phydev);
        if (pl->sfp_bus)
                sfp_upstream_stop(pl->sfp_bus);
+       if (pl->phydev)
+               phy_stop(pl->phydev);
        del_timer_sync(&pl->link_poll);
        if (pl->link_irq) {
                free_irq(pl->link_irq, pl);
index 1d902ecb4aa8b76dc14147841cf51ce12ae02127..a44dd3c8af632565043be1639efb99910e9afc25 100644 (file)
@@ -1115,6 +1115,9 @@ static const struct proto_ops pppoe_ops = {
        .recvmsg        = pppoe_recvmsg,
        .mmap           = sock_no_mmap,
        .ioctl          = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = pppox_compat_ioctl,
+#endif
 };
 
 static const struct pppox_proto pppoe_proto = {
index 5ef422a43d70b479e44991062cbdc03de9aa8951..08364f10a43fae46642f57225121bec00b70a0e0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/compat.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/net.h>
@@ -98,6 +99,18 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 EXPORT_SYMBOL(pppox_ioctl);
 
+#ifdef CONFIG_COMPAT
+int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       if (cmd == PPPOEIOCSFWD32)
+               cmd = PPPOEIOCSFWD;
+
+       return pppox_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
+}
+
+EXPORT_SYMBOL(pppox_compat_ioctl);
+#endif
+
 static int pppox_create(struct net *net, struct socket *sock, int protocol,
                        int kern)
 {
index a8e52c8e4128370ca5bc3f44e5be55881846f02f..734de7de03f7893158e1370056f5193f82b7bd54 100644 (file)
@@ -623,6 +623,9 @@ static const struct proto_ops pptp_ops = {
        .recvmsg    = sock_no_recvmsg,
        .mmap       = sock_no_mmap,
        .ioctl      = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = pppox_compat_ioctl,
+#endif
 };
 
 static const struct pppox_proto pppox_pptp_proto = {
index abfa0da9bbd28d8765867e2e4920cd4bf029a229..e8089def5a4671bad10efbde7b00297e4c37df69 100644 (file)
@@ -1004,6 +1004,8 @@ static void __team_compute_features(struct team *team)
 
        team->dev->vlan_features = vlan_features;
        team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+                                    NETIF_F_HW_VLAN_CTAG_TX |
+                                    NETIF_F_HW_VLAN_STAG_TX |
                                     NETIF_F_GSO_UDP_L4;
        team->dev->hard_header_len = max_hard_header_len;
 
index 3d443597bd0496fc99e181f1df29a7ca70191125..db16d7a13e00c197574b1f9f70044775648bbd72 100644 (file)
@@ -1599,7 +1599,8 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
        return true;
 }
 
-static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
+static struct sk_buff *__tun_build_skb(struct tun_file *tfile,
+                                      struct page_frag *alloc_frag, char *buf,
                                       int buflen, int len, int pad)
 {
        struct sk_buff *skb = build_skb(buf, buflen);
@@ -1609,6 +1610,7 @@ static struct sk_buff *__tun_build_skb(struct page_frag *alloc_frag, char *buf,
 
        skb_reserve(skb, pad);
        skb_put(skb, len);
+       skb_set_owner_w(skb, tfile->socket.sk);
 
        get_page(alloc_frag->page);
        alloc_frag->offset += buflen;
@@ -1686,7 +1688,8 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
         */
        if (hdr->gso_type || !xdp_prog) {
                *skb_xdp = 1;
-               return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
+               return __tun_build_skb(tfile, alloc_frag, buf, buflen, len,
+                                      pad);
        }
 
        *skb_xdp = 0;
@@ -1723,7 +1726,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
        rcu_read_unlock();
        local_bh_enable();
 
-       return __tun_build_skb(alloc_frag, buf, buflen, len, pad);
+       return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad);
 
 err_xdp:
        put_page(alloc_frag->page);
index 5519248a791ebefd9003ae6892894f2d95b96a03..32b08b18e12086f9634284b54a2f336994986092 100644 (file)
@@ -163,7 +163,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
        }
        if (!timeout) {
                dev_err(&udev->dev, "firmware not ready in time\n");
-               return -ETIMEDOUT;
+               ret = -ETIMEDOUT;
+               goto err;
        }
 
        /* enable ethernet mode (?) */
index d62b6706a5376a6f50834721ec32297ff3481bc7..fc5895f85cee2f8256661f37de0802054826d421 100644 (file)
@@ -113,16 +113,16 @@ kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
        status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_1),
                                         usb_buf, 24);
        if (status != 0)
-               return status;
+               goto out;
 
        memcpy(usb_buf, init_msg_2, 12);
        status = kalmia_send_init_packet(dev, usb_buf, ARRAY_SIZE(init_msg_2),
                                         usb_buf, 28);
        if (status != 0)
-               return status;
+               goto out;
 
        memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
-
+out:
        kfree(usb_buf);
        return status;
 }
index 3d92ea6fcc02be12c00083cdc71832745c8a70fb..f033fee225a11cc7c5b977d26f639042f7896524 100644 (file)
@@ -3792,7 +3792,7 @@ static int lan78xx_probe(struct usb_interface *intf,
        ret = register_netdev(netdev);
        if (ret != 0) {
                netif_err(dev, probe, netdev, "couldn't register the device\n");
-               goto out3;
+               goto out4;
        }
 
        usb_set_intfdata(intf, dev);
@@ -3807,12 +3807,14 @@ static int lan78xx_probe(struct usb_interface *intf,
 
        ret = lan78xx_phy_init(dev);
        if (ret < 0)
-               goto out4;
+               goto out5;
 
        return 0;
 
-out4:
+out5:
        unregister_netdev(netdev);
+out4:
+       usb_free_urb(dev->urb_intr);
 out3:
        lan78xx_unbind(dev, intf);
 out2:
index 6d25dea5ad4b2a956c7c0e4772e64c100c5bd5b1..f7d117d80cfbb81b7fad2e22dd13900290030dc9 100644 (file)
@@ -282,7 +282,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
 static int read_eprom_word(pegasus_t *pegasus, __u8 index, __u16 *retdata)
 {
        int i;
-       __u8 tmp;
+       __u8 tmp = 0;
        __le16 retdatai;
        int ret;
 
index 69e0a2acfcb05b140d5f953e7e4b8f663e9321dc..b6dc5d714b5e636c5b39fa199eb7fd64c1c125bd 100644 (file)
@@ -1295,6 +1295,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_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 39e0768d734db45f1bc8f873bc4e3036e0f4f087..0cc03a9ff5457922a581cbdf5d76d34186575ae6 100644 (file)
@@ -50,7 +50,7 @@
 #define PLA_TEREDO_WAKE_BASE   0xc0c4
 #define PLA_MAR                        0xcd00
 #define PLA_BACKUP             0xd000
-#define PAL_BDC_CR             0xd1a0
+#define PLA_BDC_CR             0xd1a0
 #define PLA_TEREDO_TIMER       0xd2cc
 #define PLA_REALWOW_TIMER      0xd2e8
 #define PLA_SUSPEND_FLAG       0xd38a
 #define TEREDO_RS_EVENT_MASK   0x00fe
 #define OOB_TEREDO_EN          0x0001
 
-/* PAL_BDC_CR */
+/* PLA_BDC_CR */
 #define ALDPS_PROXY_MODE       0x0001
 
 /* PLA_EFUSE_CMD */
@@ -3191,9 +3191,9 @@ static void r8152b_enter_oob(struct r8152 *tp)
 
        rtl_rx_vlan_en(tp, true);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
        ocp_data |= ALDPS_PROXY_MODE;
-       ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
@@ -3577,9 +3577,9 @@ static void r8153_enter_oob(struct r8152 *tp)
 
        rtl_rx_vlan_en(tp, true);
 
-       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
+       ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR);
        ocp_data |= ALDPS_PROXY_MODE;
-       ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data);
 
        ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
        ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
index a9ac3f37b904f00fdadbcf3ba077fe818475bc7a..e2e679a01b65a2570f8bcd88870929622f3b7264 100644 (file)
@@ -413,6 +413,7 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int
                case SDLA_RET_NO_BUFS:
                        if (cmd == SDLA_INFORMATION_WRITE)
                                break;
+                       /* Else, fall through */
 
                default: 
                        netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n",
index e9fc168bb734504e535be77067dd250a8197bffe..489cba9b284d1b3bf633853c2f1f5de57e1533c2 100644 (file)
@@ -351,13 +351,15 @@ int i2400m_barker_db_init(const char *_options)
                        }
                        result = i2400m_barker_db_add(barker);
                        if (result < 0)
-                               goto error_add;
+                               goto error_parse_add;
                }
                kfree(options_orig);
        }
        return 0;
 
+error_parse_add:
 error_parse:
+       kfree(options_orig);
 error_add:
        kfree(i2400m_barker_db);
        return result;
index d55312ef58c9c61e257a257b16af8ff74a7c80dc..9b0bb89599fc3325a61c4fe283bace44e73b1448 100644 (file)
@@ -776,7 +776,6 @@ struct iwl_rss_config_cmd {
        u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE];
 } __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */
 
-#define IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE 128
 #define IWL_MULTI_QUEUE_SYNC_SENDER_POS 0
 #define IWL_MULTI_QUEUE_SYNC_SENDER_MSK 0xf
 
@@ -812,10 +811,12 @@ struct iwl_rxq_sync_notification {
  *
  * @IWL_MVM_RXQ_EMPTY: empty sync notification
  * @IWL_MVM_RXQ_NOTIF_DEL_BA: notify RSS queues of delBA
+ * @IWL_MVM_RXQ_NSSN_SYNC: notify all the RSS queues with the new NSSN
  */
 enum iwl_mvm_rxq_notif_type {
        IWL_MVM_RXQ_EMPTY,
        IWL_MVM_RXQ_NOTIF_DEL_BA,
+       IWL_MVM_RXQ_NSSN_SYNC,
 };
 
 /**
index e411ac98290dc39b744c781b888969f79bd2cf21..4d81776f576dc370091126d1c706b1532f956909 100644 (file)
@@ -2438,17 +2438,19 @@ static void iwl_fw_dbg_info_apply(struct iwl_fw_runtime *fwrt,
 {
        u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
        u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
-       const char err_str[] =
-               "WRT: ext=%d. Invalid %s name length %d, expected %d\n";
 
        if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
-               IWL_WARN(fwrt, err_str, ext, "image", img_name_len,
+               IWL_WARN(fwrt,
+                        "WRT: ext=%d. Invalid image name length %d, expected %d\n",
+                        ext, img_name_len,
                         IWL_FW_INI_MAX_IMG_NAME_LEN);
                return;
        }
 
        if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
-               IWL_WARN(fwrt, err_str, ext, "debug cfg", dbg_cfg_name_len,
+               IWL_WARN(fwrt,
+                        "WRT: ext=%d. Invalid debug cfg name length %d, expected %d\n",
+                        ext, dbg_cfg_name_len,
                         IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
                return;
        }
@@ -2775,8 +2777,6 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
                struct iwl_ucode_tlv *tlv = iter;
                void *ini_tlv = (void *)tlv->data;
                u32 type = le32_to_cpu(tlv->type);
-               const char invalid_ap_str[] =
-                       "WRT: ext=%d. Invalid apply point %d for %s\n";
 
                switch (type) {
                case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
@@ -2786,8 +2786,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
                        struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv;
 
                        if (pnt != IWL_FW_INI_APPLY_EARLY) {
-                               IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
-                                       "buffer allocation");
+                               IWL_ERR(fwrt,
+                                       "WRT: ext=%d. Invalid apply point %d for buffer allocation\n",
+                                       ext, pnt);
                                goto next;
                        }
 
@@ -2797,8 +2798,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
                }
                case IWL_UCODE_TLV_TYPE_HCMD:
                        if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
-                               IWL_ERR(fwrt, invalid_ap_str, ext, pnt,
-                                       "host command");
+                               IWL_ERR(fwrt,
+                                       "WRT: ext=%d. Invalid apply point %d for host command\n",
+                                       ext, pnt);
                                goto next;
                        }
                        iwl_fw_dbg_send_hcmd(fwrt, tlv, ext);
index 57d09049e615ce1f3b1ab7c737f1d50be429f857..38672dd5aae962c8da529c7a4b4cd75a6b140c6f 100644 (file)
@@ -1640,6 +1640,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
        init_completion(&drv->request_firmware_complete);
        INIT_LIST_HEAD(&drv->list);
 
+       iwl_load_fw_dbg_tlv(drv->trans->dev, drv->trans);
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        /* Create the device debugfs entries. */
        drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
@@ -1660,8 +1662,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
 err_fw:
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        debugfs_remove_recursive(drv->dbgfs_drv);
-       iwl_fw_dbg_free(drv->trans);
 #endif
+       iwl_fw_dbg_free(drv->trans);
        kfree(drv);
 err:
        return ERR_PTR(ret);
index 1d608e9e91018447465672734570a38c515e3bf7..5de54d1559dda8e2fb62bf659b24abf9339e56cf 100644 (file)
@@ -755,7 +755,7 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
 
        for (i = 0; i < n_profiles; i++) {
                /* the tables start at element 3 */
-               static int pos = 3;
+               int pos = 3;
 
                /* The EWRD profiles officially go from 2 to 4, but we
                 * save them in sar_profiles[1-3] (because we don't
@@ -880,6 +880,22 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
        return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
 }
 
+static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
+{
+       /*
+        * The GEO_TX_POWER_LIMIT command is not supported on earlier
+        * firmware versions.  Unfortunately, we don't have a TLV API
+        * flag to rely on, so rely on the major version which is in
+        * the first byte of ucode_ver.  This was implemented
+        * initially on version 38 and then backported to 36, 29 and
+        * 17.
+        */
+       return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 36 ||
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 ||
+              IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17;
+}
+
 int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
 {
        struct iwl_geo_tx_power_profiles_resp *resp;
@@ -909,6 +925,9 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
                .data = { data },
        };
 
+       if (!iwl_mvm_sar_geo_support(mvm))
+               return -EOPNOTSUPP;
+
        ret = iwl_mvm_send_cmd(mvm, &cmd);
        if (ret) {
                IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
@@ -934,13 +953,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
        int ret, i, j;
        u16 cmd_wide_id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
 
-       /*
-        * This command is not supported on earlier firmware versions.
-        * Unfortunately, we don't have a TLV API flag to rely on, so
-        * rely on the major version which is in the first byte of
-        * ucode_ver.
-        */
-       if (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) < 41)
+       if (!iwl_mvm_sar_geo_support(mvm))
                return 0;
 
        ret = iwl_mvm_sar_get_wgds_table(mvm);
index 55cd49ccbf0b7a309286692cef45cc7bbddd4fa0..1c904b5226aa42d875ba503b725b33fec85e0ffd 100644 (file)
@@ -207,11 +207,11 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
        },
 };
 
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
-                              enum set_key_cmd cmd,
-                              struct ieee80211_vif *vif,
-                              struct ieee80211_sta *sta,
-                              struct ieee80211_key_conf *key);
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+                                enum set_key_cmd cmd,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta,
+                                struct ieee80211_key_conf *key);
 
 void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
 {
@@ -474,7 +474,19 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
        ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
        ieee80211_hw_set(hw, STA_MMPDU_TXQ);
-       ieee80211_hw_set(hw, TX_AMSDU);
+       /*
+        * On older devices, enabling TX A-MSDU occasionally leads to
+        * something getting messed up, the command read from the FIFO
+        * gets out of sync and isn't a TX command, so that we have an
+        * assert EDC.
+        *
+        * It's not clear where the bug is, but since we didn't used to
+        * support A-MSDU until moving the mac80211 iTXQs, just leave it
+        * for older devices. We also don't see this issue on any newer
+        * devices.
+        */
+       if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_9000)
+               ieee80211_hw_set(hw, TX_AMSDU);
        ieee80211_hw_set(hw, TX_FRAG_LIST);
 
        if (iwl_mvm_has_tlc_offload(mvm)) {
@@ -2726,7 +2738,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
 
                mvmvif->ap_early_keys[i] = NULL;
 
-               ret = iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
+               ret = __iwl_mvm_mac_set_key(hw, SET_KEY, vif, NULL, key);
                if (ret)
                        goto out_quota_failed;
        }
@@ -3494,11 +3506,11 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
        return ret;
 }
 
-static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
-                              enum set_key_cmd cmd,
-                              struct ieee80211_vif *vif,
-                              struct ieee80211_sta *sta,
-                              struct ieee80211_key_conf *key)
+static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+                                enum set_key_cmd cmd,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta,
+                                struct ieee80211_key_conf *key)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -3553,8 +3565,6 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
                        return -EOPNOTSUPP;
        }
 
-       mutex_lock(&mvm->mutex);
-
        switch (cmd) {
        case SET_KEY:
                if ((vif->type == NL80211_IFTYPE_ADHOC ||
@@ -3700,7 +3710,22 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
                ret = -EINVAL;
        }
 
+       return ret;
+}
+
+static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+                              enum set_key_cmd cmd,
+                              struct ieee80211_vif *vif,
+                              struct ieee80211_sta *sta,
+                              struct ieee80211_key_conf *key)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       int ret;
+
+       mutex_lock(&mvm->mutex);
+       ret = __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key);
        mutex_unlock(&mvm->mutex);
+
        return ret;
 }
 
@@ -5041,7 +5066,6 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
        u32 qmask = BIT(mvm->trans->num_rx_queues) - 1;
        int ret;
 
-       lockdep_assert_held(&mvm->mutex);
 
        if (!iwl_mvm_has_new_rx_api(mvm))
                return;
@@ -5052,13 +5076,15 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
                atomic_set(&mvm->queue_sync_counter,
                           mvm->trans->num_rx_queues);
 
-       ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif, size);
+       ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
+                                     size, !notif->sync);
        if (ret) {
                IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret);
                goto out;
        }
 
        if (notif->sync) {
+               lockdep_assert_held(&mvm->mutex);
                ret = wait_event_timeout(mvm->rx_sync_waitq,
                                         atomic_read(&mvm->queue_sync_counter) == 0 ||
                                         iwl_mvm_is_radio_killed(mvm),
index 48c77af54e9919017d4261a2ac80b10a41a900df..a263cc629d7551d05f8084e8770b1aec6ddfcae6 100644 (file)
@@ -1664,9 +1664,9 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
 void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue);
 int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
-                           const u8 *data, u32 count);
-void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-                           int queue);
+                           const u8 *data, u32 count, bool async);
+void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+                           struct iwl_rx_cmd_buffer *rxb, int queue);
 void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
 void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
                                   struct iwl_rx_cmd_buffer *rxb);
@@ -1813,7 +1813,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 
 /* rate scaling */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync);
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq);
 void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg);
 int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
 void rs_update_last_rssi(struct iwl_mvm *mvm,
index 719f793b3487ce28b949d9d4d80185503d2013b7..a9bb43a2f27b2c81e0a02e5e6ae5a7835a0563a2 100644 (file)
@@ -620,7 +620,7 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
        enum iwl_mcc_source src;
        char mcc[3];
        struct ieee80211_regdomain *regd;
-       u32 wgds_tbl_idx;
+       int wgds_tbl_idx;
 
        lockdep_assert_held(&mvm->mutex);
 
index d7d6f3398f86b4516198bc372261bca0b6ca9a1c..4888054dc3d87eb1c7f0a565dde24b1dec3bd305 100644 (file)
@@ -1088,7 +1088,7 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
        else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
                                         RX_QUEUES_NOTIFICATION)))
-               iwl_mvm_rx_queue_notif(mvm, rxb, 0);
+               iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0);
        else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
                iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
        else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
@@ -1812,7 +1812,7 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
                iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
        else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
                                         RX_QUEUES_NOTIFICATION)))
-               iwl_mvm_rx_queue_notif(mvm, rxb, queue);
+               iwl_mvm_rx_queue_notif(mvm, napi, rxb, queue);
        else if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
                iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue);
 }
index 8c9069f28a589c78c0df05c8c36f6fea3e2fa328..d3f04acfbacb9fa360388110423391f6032ea2ca 100644 (file)
@@ -1197,239 +1197,6 @@ static u8 rs_get_tid(struct ieee80211_hdr *hdr)
        return tid;
 }
 
-void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         int tid, struct ieee80211_tx_info *info, bool ndp)
-{
-       int legacy_success;
-       int retries;
-       int i;
-       struct iwl_lq_cmd *table;
-       u32 lq_hwrate;
-       struct rs_rate lq_rate, tx_resp_rate;
-       struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
-       u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
-       u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
-       u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
-       u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
-       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-       struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
-
-       /* Treat uninitialized rate scaling data same as non-existing. */
-       if (!lq_sta) {
-               IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
-               return;
-       } else if (!lq_sta->pers.drv) {
-               IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
-               return;
-       }
-
-       /* This packet was aggregated but doesn't carry status info */
-       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
-           !(info->flags & IEEE80211_TX_STAT_AMPDU))
-               return;
-
-       if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band,
-                                   &tx_resp_rate)) {
-               WARN_ON_ONCE(1);
-               return;
-       }
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-       /* Disable last tx check if we are debugging with fixed rate but
-        * update tx stats */
-       if (lq_sta->pers.dbg_fixed_rate) {
-               int index = tx_resp_rate.index;
-               enum rs_column column;
-               int attempts, success;
-
-               column = rs_get_column_from_rate(&tx_resp_rate);
-               if (WARN_ONCE(column == RS_COLUMN_INVALID,
-                             "Can't map rate 0x%x to column",
-                             tx_resp_hwrate))
-                       return;
-
-               if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-                       attempts = info->status.ampdu_len;
-                       success = info->status.ampdu_ack_len;
-               } else {
-                       attempts = info->status.rates[0].count;
-                       success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-               }
-
-               lq_sta->pers.tx_stats[column][index].total += attempts;
-               lq_sta->pers.tx_stats[column][index].success += success;
-
-               IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n",
-                              tx_resp_hwrate, success, attempts);
-               return;
-       }
-#endif
-
-       if (time_after(jiffies,
-                      (unsigned long)(lq_sta->last_tx +
-                                      (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
-               IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
-               iwl_mvm_rs_rate_init(mvm, sta, info->band, true);
-               return;
-       }
-       lq_sta->last_tx = jiffies;
-
-       /* Ignore this Tx frame response if its initial rate doesn't match
-        * that of latest Link Quality command.  There may be stragglers
-        * from a previous Link Quality command, but we're no longer interested
-        * in those; they're either from the "active" mode while we're trying
-        * to check "search" mode, or a prior "search" mode after we've moved
-        * to a new "search" mode (which might become the new "active" mode).
-        */
-       table = &lq_sta->lq;
-       lq_hwrate = le32_to_cpu(table->rs_table[0]);
-       if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) {
-               WARN_ON_ONCE(1);
-               return;
-       }
-
-       /* Here we actually compare this rate to the latest LQ command */
-       if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
-               IWL_DEBUG_RATE(mvm,
-                              "tx resp color 0x%x does not match 0x%x\n",
-                              lq_color, LQ_FLAG_COLOR_GET(table->flags));
-
-               /*
-                * Since rates mis-match, the last LQ command may have failed.
-                * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
-                * ... driver.
-                */
-               lq_sta->missed_rate_counter++;
-               if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {
-                       lq_sta->missed_rate_counter = 0;
-                       IWL_DEBUG_RATE(mvm,
-                                      "Too many rates mismatch. Send sync LQ. rs_state %d\n",
-                                      lq_sta->rs_state);
-                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
-               }
-               /* Regardless, ignore this status info for outdated rate */
-               return;
-       } else
-               /* Rate did match, so reset the missed_rate_counter */
-               lq_sta->missed_rate_counter = 0;
-
-       if (!lq_sta->search_better_tbl) {
-               curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-       } else {
-               curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       }
-
-       if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
-               IWL_DEBUG_RATE(mvm,
-                              "Neither active nor search matches tx rate\n");
-               tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
-               tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
-               rs_dump_rate(mvm, &lq_rate, "ACTUAL");
-
-               /*
-                * no matching table found, let's by-pass the data collection
-                * and continue to perform rate scale to find the rate table
-                */
-               rs_stay_in_table(lq_sta, true);
-               goto done;
-       }
-
-       /*
-        * Updating the frame history depends on whether packets were
-        * aggregated.
-        *
-        * For aggregation, all packets were transmitted at the same rate, the
-        * first index into rate scale table.
-        */
-       if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-               rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,
-                                   info->status.ampdu_len,
-                                   info->status.ampdu_ack_len,
-                                   reduced_txp);
-
-               /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
-                * it as a single frame loss as we don't want the success ratio
-                * to dip too quickly because a BA wasn't received.
-                * For TPC, there's no need for this optimisation since we want
-                * to recover very quickly from a bad power reduction and,
-                * therefore we'd like the success ratio to get an immediate hit
-                * when failing to get a BA, so we'd switch back to a lower or
-                * zero power reduction. When FW transmits agg with a rate
-                * different from the initial rate, it will not use reduced txp
-                * and will send BA notification twice (one empty with reduced
-                * txp equal to the value from LQ and one with reduced txp 0).
-                * We need to update counters for each txp level accordingly.
-                */
-               if (info->status.ampdu_ack_len == 0)
-                       info->status.ampdu_len = 1;
-
-               rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl, tx_resp_rate.index,
-                                   info->status.ampdu_len,
-                                   info->status.ampdu_ack_len);
-
-               /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
-                       lq_sta->total_success += info->status.ampdu_ack_len;
-                       lq_sta->total_failed += (info->status.ampdu_len -
-                                       info->status.ampdu_ack_len);
-               }
-       } else {
-               /* For legacy, update frame history with for each Tx retry. */
-               retries = info->status.rates[0].count - 1;
-               /* HW doesn't send more than 15 retries */
-               retries = min(retries, 15);
-
-               /* The last transmission may have been successful */
-               legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
-               /* Collect data for each rate used during failed TX attempts */
-               for (i = 0; i <= retries; ++i) {
-                       lq_hwrate = le32_to_cpu(table->rs_table[i]);
-                       if (rs_rate_from_ucode_rate(lq_hwrate, info->band,
-                                                   &lq_rate)) {
-                               WARN_ON_ONCE(1);
-                               return;
-                       }
-
-                       /*
-                        * Only collect stats if retried rate is in the same RS
-                        * table as active/search.
-                        */
-                       if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
-                               tmp_tbl = curr_tbl;
-                       else if (rs_rate_column_match(&lq_rate,
-                                                     &other_tbl->rate))
-                               tmp_tbl = other_tbl;
-                       else
-                               continue;
-
-                       rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
-                                           tx_resp_rate.index, 1,
-                                           i < retries ? 0 : legacy_success,
-                                           reduced_txp);
-                       rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
-                                           tx_resp_rate.index, 1,
-                                           i < retries ? 0 : legacy_success);
-               }
-
-               /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
-                       lq_sta->total_success += legacy_success;
-                       lq_sta->total_failed += retries + (1 - legacy_success);
-               }
-       }
-       /* The last TX rate is cached in lq_sta; it's set in if/else above */
-       lq_sta->last_rate_n_flags = lq_hwrate;
-       IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
-done:
-       /* See if there's a better rate or modulation mode to try. */
-       if (sta->supp_rates[info->band])
-               rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);
-}
-
 /*
  * mac80211 sends us Tx status
  */
@@ -1442,8 +1209,9 @@ static void rs_drv_mac80211_tx_status(void *mvm_r,
        struct iwl_op_mode *op_mode = mvm_r;
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
-       if (!iwl_mvm_sta_from_mac80211(sta)->vif)
+       if (!mvmsta->vif)
                return;
 
        if (!ieee80211_is_data(hdr->frame_control) ||
@@ -1584,6 +1352,18 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
        tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
 }
 
+/* rs uses two tables, one is active and the second is for searching better
+ * configuration. This function, according to the index of the currently
+ * active table returns the search table, which is located at the
+ * index complementary to 1 according to the active table (active = 1,
+ * search = 0 or active = 0, search = 1).
+ * Since lq_info is an arary of size 2, make sure index cannot be out of bounds.
+ */
+static inline u8 rs_search_tbl(u8 active_tbl)
+{
+       return (active_tbl ^ 1) & 1;
+}
+
 static s32 rs_get_best_rate(struct iwl_mvm *mvm,
                            struct iwl_lq_sta *lq_sta,
                            struct iwl_scale_tbl_info *tbl,     /* "search" */
@@ -1794,7 +1574,7 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
                               struct iwl_scale_tbl_info *tbl)
 {
        rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
-       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
+       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
 }
 
 static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
@@ -1931,9 +1711,9 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
                               struct ieee80211_sta *sta,
                               enum rs_column col_id)
 {
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
        struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+               &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
        struct rs_rate *rate = &search_tbl->rate;
        const struct rs_tx_column *column = &rs_tx_columns[col_id];
        const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
@@ -2341,7 +2121,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        if (!lq_sta->search_better_tbl)
                active_tbl = lq_sta->active_tbl;
        else
-               active_tbl = 1 - lq_sta->active_tbl;
+               active_tbl = rs_search_tbl(lq_sta->active_tbl);
 
        tbl = &(lq_sta->lq_info[active_tbl]);
        rate = &tbl->rate;
@@ -2565,7 +2345,7 @@ lq_update:
                /* If new "search" mode was selected, set up in uCode table */
                if (lq_sta->search_better_tbl) {
                        /* Access the "search" table, clear its history. */
-                       tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+                       tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
                        rs_rate_scale_clear_tbl_windows(mvm, tbl);
 
                        /* Use new "search" start rate */
@@ -2896,7 +2676,7 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,
 static void rs_initialize_lq(struct iwl_mvm *mvm,
                             struct ieee80211_sta *sta,
                             struct iwl_lq_sta *lq_sta,
-                            enum nl80211_band band, bool update)
+                            enum nl80211_band band)
 {
        struct iwl_scale_tbl_info *tbl;
        struct rs_rate *rate;
@@ -2908,7 +2688,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
        if (!lq_sta->search_better_tbl)
                active_tbl = lq_sta->active_tbl;
        else
-               active_tbl = 1 - lq_sta->active_tbl;
+               active_tbl = rs_search_tbl(lq_sta->active_tbl);
 
        tbl = &(lq_sta->lq_info[active_tbl]);
        rate = &tbl->rate;
@@ -2926,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
        rs_set_expected_tpt_table(lq_sta, tbl);
        rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
        /* TODO restore station should remember the lq cmd */
-       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, !update);
+       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
 }
 
 static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
@@ -3175,7 +2955,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
  * Called after adding a new station to initialize rate scaling
  */
 static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                            enum nl80211_band band, bool update)
+                            enum nl80211_band band)
 {
        int i, j;
        struct ieee80211_hw *hw = mvm->hw;
@@ -3186,6 +2966,8 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        struct ieee80211_supported_band *sband;
        unsigned long supp; /* must be unsigned long for for_each_set_bit */
 
+       lockdep_assert_held(&mvmsta->lq_sta.rs_drv.pers.lock);
+
        /* clear all non-persistent lq data */
        memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
 
@@ -3255,7 +3037,7 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        iwl_mvm_reset_frame_stats(mvm);
 #endif
-       rs_initialize_lq(mvm, sta, lq_sta, band, update);
+       rs_initialize_lq(mvm, sta, lq_sta, band);
 }
 
 static void rs_drv_rate_update(void *mvm_r,
@@ -3278,6 +3060,258 @@ static void rs_drv_rate_update(void *mvm_r,
        iwl_mvm_rs_rate_init(mvm, sta, sband->band, true);
 }
 
+static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
+                                  struct ieee80211_sta *sta,
+                                  int tid, struct ieee80211_tx_info *info,
+                                  bool ndp)
+{
+       int legacy_success;
+       int retries;
+       int i;
+       struct iwl_lq_cmd *table;
+       u32 lq_hwrate;
+       struct rs_rate lq_rate, tx_resp_rate;
+       struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+       u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
+       u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
+       u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
+       u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
+
+       /* Treat uninitialized rate scaling data same as non-existing. */
+       if (!lq_sta) {
+               IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
+               return;
+       } else if (!lq_sta->pers.drv) {
+               IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
+               return;
+       }
+
+       /* This packet was aggregated but doesn't carry status info */
+       if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+           !(info->flags & IEEE80211_TX_STAT_AMPDU))
+               return;
+
+       if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band,
+                                   &tx_resp_rate)) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       /* Disable last tx check if we are debugging with fixed rate but
+        * update tx stats
+        */
+       if (lq_sta->pers.dbg_fixed_rate) {
+               int index = tx_resp_rate.index;
+               enum rs_column column;
+               int attempts, success;
+
+               column = rs_get_column_from_rate(&tx_resp_rate);
+               if (WARN_ONCE(column == RS_COLUMN_INVALID,
+                             "Can't map rate 0x%x to column",
+                             tx_resp_hwrate))
+                       return;
+
+               if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+                       attempts = info->status.ampdu_len;
+                       success = info->status.ampdu_ack_len;
+               } else {
+                       attempts = info->status.rates[0].count;
+                       success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+               }
+
+               lq_sta->pers.tx_stats[column][index].total += attempts;
+               lq_sta->pers.tx_stats[column][index].success += success;
+
+               IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n",
+                              tx_resp_hwrate, success, attempts);
+               return;
+       }
+#endif
+
+       if (time_after(jiffies,
+                      (unsigned long)(lq_sta->last_tx +
+                                      (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) {
+               IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
+               /* reach here only in case of driver RS, call directly
+                * the unlocked version
+                */
+               rs_drv_rate_init(mvm, sta, info->band);
+               return;
+       }
+       lq_sta->last_tx = jiffies;
+
+       /* Ignore this Tx frame response if its initial rate doesn't match
+        * that of latest Link Quality command.  There may be stragglers
+        * from a previous Link Quality command, but we're no longer interested
+        * in those; they're either from the "active" mode while we're trying
+        * to check "search" mode, or a prior "search" mode after we've moved
+        * to a new "search" mode (which might become the new "active" mode).
+        */
+       table = &lq_sta->lq;
+       lq_hwrate = le32_to_cpu(table->rs_table[0]);
+       if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
+       /* Here we actually compare this rate to the latest LQ command */
+       if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
+               IWL_DEBUG_RATE(mvm,
+                              "tx resp color 0x%x does not match 0x%x\n",
+                              lq_color, LQ_FLAG_COLOR_GET(table->flags));
+
+               /* Since rates mis-match, the last LQ command may have failed.
+                * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
+                * ... driver.
+                */
+               lq_sta->missed_rate_counter++;
+               if (lq_sta->missed_rate_counter > IWL_MVM_RS_MISSED_RATE_MAX) {
+                       lq_sta->missed_rate_counter = 0;
+                       IWL_DEBUG_RATE(mvm,
+                                      "Too many rates mismatch. Send sync LQ. rs_state %d\n",
+                                      lq_sta->rs_state);
+                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq);
+               }
+               /* Regardless, ignore this status info for outdated rate */
+               return;
+       }
+
+       /* Rate did match, so reset the missed_rate_counter */
+       lq_sta->missed_rate_counter = 0;
+
+       if (!lq_sta->search_better_tbl) {
+               curr_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+               other_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+       } else {
+               curr_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+               other_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+       }
+
+       if (WARN_ON_ONCE(!rs_rate_column_match(&lq_rate, &curr_tbl->rate))) {
+               IWL_DEBUG_RATE(mvm,
+                              "Neither active nor search matches tx rate\n");
+               tmp_tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+               rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
+               tmp_tbl = &lq_sta->lq_info[rs_search_tbl(lq_sta->active_tbl)];
+               rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
+               rs_dump_rate(mvm, &lq_rate, "ACTUAL");
+
+               /* no matching table found, let's by-pass the data collection
+                * and continue to perform rate scale to find the rate table
+                */
+               rs_stay_in_table(lq_sta, true);
+               goto done;
+       }
+
+       /* Updating the frame history depends on whether packets were
+        * aggregated.
+        *
+        * For aggregation, all packets were transmitted at the same rate, the
+        * first index into rate scale table.
+        */
+       if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+               rs_collect_tpc_data(mvm, lq_sta, curr_tbl, tx_resp_rate.index,
+                                   info->status.ampdu_len,
+                                   info->status.ampdu_ack_len,
+                                   reduced_txp);
+
+               /* ampdu_ack_len = 0 marks no BA was received. For TLC, treat
+                * it as a single frame loss as we don't want the success ratio
+                * to dip too quickly because a BA wasn't received.
+                * For TPC, there's no need for this optimisation since we want
+                * to recover very quickly from a bad power reduction and,
+                * therefore we'd like the success ratio to get an immediate hit
+                * when failing to get a BA, so we'd switch back to a lower or
+                * zero power reduction. When FW transmits agg with a rate
+                * different from the initial rate, it will not use reduced txp
+                * and will send BA notification twice (one empty with reduced
+                * txp equal to the value from LQ and one with reduced txp 0).
+                * We need to update counters for each txp level accordingly.
+                */
+               if (info->status.ampdu_ack_len == 0)
+                       info->status.ampdu_len = 1;
+
+               rs_collect_tlc_data(mvm, mvmsta, tid, curr_tbl,
+                                   tx_resp_rate.index,
+                                   info->status.ampdu_len,
+                                   info->status.ampdu_ack_len);
+
+               /* Update success/fail counts if not searching for new mode */
+               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
+                       lq_sta->total_success += info->status.ampdu_ack_len;
+                       lq_sta->total_failed += (info->status.ampdu_len -
+                                       info->status.ampdu_ack_len);
+               }
+       } else {
+               /* For legacy, update frame history with for each Tx retry. */
+               retries = info->status.rates[0].count - 1;
+               /* HW doesn't send more than 15 retries */
+               retries = min(retries, 15);
+
+               /* The last transmission may have been successful */
+               legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+               /* Collect data for each rate used during failed TX attempts */
+               for (i = 0; i <= retries; ++i) {
+                       lq_hwrate = le32_to_cpu(table->rs_table[i]);
+                       if (rs_rate_from_ucode_rate(lq_hwrate, info->band,
+                                                   &lq_rate)) {
+                               WARN_ON_ONCE(1);
+                               return;
+                       }
+
+                       /* Only collect stats if retried rate is in the same RS
+                        * table as active/search.
+                        */
+                       if (rs_rate_column_match(&lq_rate, &curr_tbl->rate))
+                               tmp_tbl = curr_tbl;
+                       else if (rs_rate_column_match(&lq_rate,
+                                                     &other_tbl->rate))
+                               tmp_tbl = other_tbl;
+                       else
+                               continue;
+
+                       rs_collect_tpc_data(mvm, lq_sta, tmp_tbl,
+                                           tx_resp_rate.index, 1,
+                                           i < retries ? 0 : legacy_success,
+                                           reduced_txp);
+                       rs_collect_tlc_data(mvm, mvmsta, tid, tmp_tbl,
+                                           tx_resp_rate.index, 1,
+                                           i < retries ? 0 : legacy_success);
+               }
+
+               /* Update success/fail counts if not searching for new mode */
+               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
+                       lq_sta->total_success += legacy_success;
+                       lq_sta->total_failed += retries + (1 - legacy_success);
+               }
+       }
+       /* The last TX rate is cached in lq_sta; it's set in if/else above */
+       lq_sta->last_rate_n_flags = lq_hwrate;
+       IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
+done:
+       /* See if there's a better rate or modulation mode to try. */
+       if (sta->supp_rates[info->band])
+               rs_rate_scale_perform(mvm, sta, lq_sta, tid, ndp);
+}
+
+void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+                         int tid, struct ieee80211_tx_info *info, bool ndp)
+{
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+       /* If it's locked we are in middle of init flow
+        * just wait for next tx status to update the lq_sta data
+        */
+       if (!spin_trylock(&mvmsta->lq_sta.rs_drv.pers.lock))
+               return;
+
+       __iwl_mvm_rs_tx_status(mvm, sta, tid, info, ndp);
+       spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+}
+
 #ifdef CONFIG_MAC80211_DEBUGFS
 static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
                                            struct iwl_lq_cmd *lq_cmd,
@@ -3569,7 +3603,7 @@ static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
 
                bfersta_ss_params &= ~LQ_SS_BFER_ALLOWED;
                bfersta_lq_cmd->ss_params = cpu_to_le32(bfersta_ss_params);
-               iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd, false);
+               iwl_mvm_send_lq_cmd(mvm, bfersta_lq_cmd);
 
                ss_params |= LQ_SS_BFER_ALLOWED;
                IWL_DEBUG_RATE(mvm,
@@ -3735,7 +3769,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
 
        if (lq_sta->pers.dbg_fixed_rate) {
                rs_fill_lq_cmd(mvm, NULL, lq_sta, NULL);
-               iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false);
+               iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq);
        }
 }
 
@@ -4132,10 +4166,15 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
 void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                          enum nl80211_band band, bool update)
 {
-       if (iwl_mvm_has_tlc_offload(mvm))
+       if (iwl_mvm_has_tlc_offload(mvm)) {
                rs_fw_rate_init(mvm, sta, band, update);
-       else
-               rs_drv_rate_init(mvm, sta, band, update);
+       } else {
+               struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+               spin_lock(&mvmsta->lq_sta.rs_drv.pers.lock);
+               rs_drv_rate_init(mvm, sta, band);
+               spin_unlock(&mvmsta->lq_sta.rs_drv.pers.lock);
+       }
 }
 
 int iwl_mvm_rate_control_register(void)
@@ -4165,7 +4204,7 @@ static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
                        lq->flags &= ~LQ_FLAG_USE_RTS_MSK;
        }
 
-       return iwl_mvm_send_lq_cmd(mvm, lq, false);
+       return iwl_mvm_send_lq_cmd(mvm, lq);
 }
 
 /**
index f7eb60dbaf202460eaca0cf8695171357073996a..428642e666587d14e7d6d3c7a9f8713c4a8d6713 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  *
  * Contact Information:
  *  Intel Linux Wireless <linuxwifi@intel.com>
@@ -390,6 +390,7 @@ struct iwl_lq_sta {
                s8 last_rssi;
                struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
                struct iwl_mvm *drv;
+               spinlock_t lock; /* for races in reinit/update table */
        } pers;
 };
 
index 64f95050128770cae30a2871f1a3c717b95d7cf8..854edd7d7103b351fe69b23a085d3b2e6b9eb610 100644 (file)
@@ -463,20 +463,22 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
 }
 
 int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
-                           const u8 *data, u32 count)
+                           const u8 *data, u32 count, bool async)
 {
-       struct iwl_rxq_sync_cmd *cmd;
+       u8 buf[sizeof(struct iwl_rxq_sync_cmd) +
+              sizeof(struct iwl_mvm_rss_sync_notif)];
+       struct iwl_rxq_sync_cmd *cmd = (void *)buf;
        u32 data_size = sizeof(*cmd) + count;
        int ret;
 
-       /* should be DWORD aligned */
-       if (WARN_ON(count & 3 || count > IWL_MULTI_QUEUE_SYNC_MSG_MAX_SIZE))
+       /*
+        * size must be a multiple of DWORD
+        * Ensure we don't overflow buf
+        */
+       if (WARN_ON(count & 3 ||
+                   count > sizeof(struct iwl_mvm_rss_sync_notif)))
                return -EINVAL;
 
-       cmd = kzalloc(data_size, GFP_KERNEL);
-       if (!cmd)
-               return -ENOMEM;
-
        cmd->rxq_mask = cpu_to_le32(rxq_mask);
        cmd->count =  cpu_to_le32(count);
        cmd->flags = 0;
@@ -485,9 +487,8 @@ int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
        ret = iwl_mvm_send_cmd_pdu(mvm,
                                   WIDE_ID(DATA_PATH_GROUP,
                                           TRIGGER_RX_QUEUES_NOTIF_CMD),
-                                  0, data_size, cmd);
+                                  async ? CMD_ASYNC : 0, data_size, cmd);
 
-       kfree(cmd);
        return ret;
 }
 
@@ -503,14 +504,31 @@ static bool iwl_mvm_is_sn_less(u16 sn1, u16 sn2, u16 buffer_size)
               !ieee80211_sn_less(sn1, sn2 - buffer_size);
 }
 
+static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
+{
+       struct iwl_mvm_rss_sync_notif notif = {
+               .metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
+               .metadata.sync = 0,
+               .nssn_sync.baid = baid,
+               .nssn_sync.nssn = nssn,
+       };
+
+       iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
+}
+
 #define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10)
 
+enum iwl_mvm_release_flags {
+       IWL_MVM_RELEASE_SEND_RSS_SYNC = BIT(0),
+       IWL_MVM_RELEASE_FROM_RSS_SYNC = BIT(1),
+};
+
 static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
                                   struct ieee80211_sta *sta,
                                   struct napi_struct *napi,
                                   struct iwl_mvm_baid_data *baid_data,
                                   struct iwl_mvm_reorder_buffer *reorder_buf,
-                                  u16 nssn)
+                                  u16 nssn, u32 flags)
 {
        struct iwl_mvm_reorder_buf_entry *entries =
                &baid_data->entries[reorder_buf->queue *
@@ -519,6 +537,18 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
 
        lockdep_assert_held(&reorder_buf->lock);
 
+       /*
+        * We keep the NSSN not too far behind, if we are sync'ing it and it
+        * is more than 2048 ahead of us, it must be behind us. Discard it.
+        * This can happen if the queue that hit the 0 / 2048 seqno was lagging
+        * behind and this queue already processed packets. The next if
+        * would have caught cases where this queue would have processed less
+        * than 64 packets, but it may have processed more than 64 packets.
+        */
+       if ((flags & IWL_MVM_RELEASE_FROM_RSS_SYNC) &&
+           ieee80211_sn_less(nssn, ssn))
+               goto set_timer;
+
        /* ignore nssn smaller than head sn - this can happen due to timeout */
        if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
                goto set_timer;
@@ -529,6 +559,9 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
                struct sk_buff *skb;
 
                ssn = ieee80211_sn_inc(ssn);
+               if ((flags & IWL_MVM_RELEASE_SEND_RSS_SYNC) &&
+                   (ssn == 2048 || ssn == 0))
+                       iwl_mvm_sync_nssn(mvm, baid_data->baid, ssn);
 
                /*
                 * Empty the list. Will have more than one frame for A-MSDU.
@@ -615,7 +648,8 @@ void iwl_mvm_reorder_timer_expired(struct timer_list *t)
                             sta_id, sn);
                iwl_mvm_event_frame_timeout_callback(buf->mvm, mvmsta->vif,
                                                     sta, baid_data->tid);
-               iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data, buf, sn);
+               iwl_mvm_release_frames(buf->mvm, sta, NULL, baid_data,
+                                      buf, sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
                rcu_read_unlock();
        } else {
                /*
@@ -657,7 +691,8 @@ static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
        spin_lock_bh(&reorder_buf->lock);
        iwl_mvm_release_frames(mvm, sta, NULL, ba_data, reorder_buf,
                               ieee80211_sn_add(reorder_buf->head_sn,
-                                               reorder_buf->buf_size));
+                                               reorder_buf->buf_size),
+                              0);
        spin_unlock_bh(&reorder_buf->lock);
        del_timer_sync(&reorder_buf->reorder_timer);
 
@@ -665,8 +700,54 @@ out:
        rcu_read_unlock();
 }
 
-void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
-                           int queue)
+static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
+                                             struct napi_struct *napi,
+                                             u8 baid, u16 nssn, int queue,
+                                             u32 flags)
+{
+       struct ieee80211_sta *sta;
+       struct iwl_mvm_reorder_buffer *reorder_buf;
+       struct iwl_mvm_baid_data *ba_data;
+
+       IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
+                    baid, nssn);
+
+       if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
+                        baid >= ARRAY_SIZE(mvm->baid_map)))
+               return;
+
+       rcu_read_lock();
+
+       ba_data = rcu_dereference(mvm->baid_map[baid]);
+       if (WARN_ON_ONCE(!ba_data))
+               goto out;
+
+       sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
+       if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
+               goto out;
+
+       reorder_buf = &ba_data->reorder_buf[queue];
+
+       spin_lock_bh(&reorder_buf->lock);
+       iwl_mvm_release_frames(mvm, sta, napi, ba_data,
+                              reorder_buf, nssn, flags);
+       spin_unlock_bh(&reorder_buf->lock);
+
+out:
+       rcu_read_unlock();
+}
+
+static void iwl_mvm_nssn_sync(struct iwl_mvm *mvm,
+                             struct napi_struct *napi, int queue,
+                             const struct iwl_mvm_nssn_sync_data *data)
+{
+       iwl_mvm_release_frames_from_notif(mvm, napi, data->baid,
+                                         data->nssn, queue,
+                                         IWL_MVM_RELEASE_FROM_RSS_SYNC);
+}
+
+void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
+                           struct iwl_rx_cmd_buffer *rxb, int queue)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_rxq_sync_notification *notif;
@@ -687,6 +768,10 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
        case IWL_MVM_RXQ_NOTIF_DEL_BA:
                iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data);
                break;
+       case IWL_MVM_RXQ_NSSN_SYNC:
+               iwl_mvm_nssn_sync(mvm, napi, queue,
+                                 (void *)internal_notif->data);
+               break;
        default:
                WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
        }
@@ -785,7 +870,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
        }
 
        if (ieee80211_is_back_req(hdr->frame_control)) {
-               iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer, nssn);
+               iwl_mvm_release_frames(mvm, sta, napi, baid_data,
+                                      buffer, nssn, 0);
                goto drop;
        }
 
@@ -794,7 +880,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * If the SN is smaller than the NSSN it might need to first go into
         * the reorder buffer, in which case we just release up to it and the
         * rest of the function will take care of storing it and releasing up to
-        * the nssn
+        * the nssn.
+        * This should not happen. This queue has been lagging and it should
+        * have been updated by a IWL_MVM_RXQ_NSSN_SYNC notification. Be nice
+        * and update the other queues.
         */
        if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
                                buffer->buf_size) ||
@@ -802,7 +891,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
                u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
 
                iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer,
-                                      min_sn);
+                                      min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
        }
 
        /* drop any oudated packets */
@@ -813,8 +902,23 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
        if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) {
                if (iwl_mvm_is_sn_less(buffer->head_sn, nssn,
                                       buffer->buf_size) &&
-                  (!amsdu || last_subframe))
+                  (!amsdu || last_subframe)) {
+                       /*
+                        * If we crossed the 2048 or 0 SN, notify all the
+                        * queues. This is done in order to avoid having a
+                        * head_sn that lags behind for too long. When that
+                        * happens, we can get to a situation where the head_sn
+                        * is within the interval [nssn - buf_size : nssn]
+                        * which will make us think that the nssn is a packet
+                        * that we already freed because of the reordering
+                        * buffer and we will ignore it. So maintain the
+                        * head_sn somewhat updated across all the queues:
+                        * when it crosses 0 and 2048.
+                        */
+                       if (sn == 2048 || sn == 0)
+                               iwl_mvm_sync_nssn(mvm, baid, sn);
                        buffer->head_sn = nssn;
+               }
                /* No need to update AMSDU last SN - we are moving the head */
                spin_unlock_bh(&buffer->lock);
                return false;
@@ -829,8 +933,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * while technically there is no hole and we can move forward.
         */
        if (!buffer->num_stored && sn == buffer->head_sn) {
-               if (!amsdu || last_subframe)
+               if (!amsdu || last_subframe) {
+                       if (sn == 2048 || sn == 0)
+                               iwl_mvm_sync_nssn(mvm, baid, sn);
                        buffer->head_sn = ieee80211_sn_inc(buffer->head_sn);
+               }
                /* No need to update AMSDU last SN - we are moving the head */
                spin_unlock_bh(&buffer->lock);
                return false;
@@ -875,7 +982,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * release notification with up to date NSSN.
         */
        if (!amsdu || last_subframe)
-               iwl_mvm_release_frames(mvm, sta, napi, baid_data, buffer, nssn);
+               iwl_mvm_release_frames(mvm, sta, napi, baid_data,
+                                      buffer, nssn,
+                                      IWL_MVM_RELEASE_SEND_RSS_SYNC);
 
        spin_unlock_bh(&buffer->lock);
        return true;
@@ -1840,40 +1949,14 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
 out:
        rcu_read_unlock();
 }
+
 void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl_frame_release *release = (void *)pkt->data;
-       struct ieee80211_sta *sta;
-       struct iwl_mvm_reorder_buffer *reorder_buf;
-       struct iwl_mvm_baid_data *ba_data;
-
-       int baid = release->baid;
-
-       IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n",
-                    release->baid, le16_to_cpu(release->nssn));
 
-       if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID))
-               return;
-
-       rcu_read_lock();
-
-       ba_data = rcu_dereference(mvm->baid_map[baid]);
-       if (WARN_ON_ONCE(!ba_data))
-               goto out;
-
-       sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
-       if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
-               goto out;
-
-       reorder_buf = &ba_data->reorder_buf[queue];
-
-       spin_lock_bh(&reorder_buf->lock);
-       iwl_mvm_release_frames(mvm, sta, napi, ba_data, reorder_buf,
-                              le16_to_cpu(release->nssn));
-       spin_unlock_bh(&reorder_buf->lock);
-
-out:
-       rcu_read_unlock();
+       iwl_mvm_release_frames_from_notif(mvm, napi, release->baid,
+                                         le16_to_cpu(release->nssn),
+                                         queue, 0);
 }
index f545a737a92dfa8321b83ce00748c1833ec7c854..10f18536dd0d288884aca8068eded9b1bc193dcb 100644 (file)
@@ -1684,6 +1684,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
         */
        if (iwl_mvm_has_tlc_offload(mvm))
                iwl_mvm_rs_add_sta(mvm, mvm_sta);
+       else
+               spin_lock_init(&mvm_sta->lq_sta.rs_drv.pers.lock);
 
        iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant);
 
@@ -2421,7 +2423,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 
 static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
 {
-       struct iwl_mvm_delba_notif notif = {
+       struct iwl_mvm_rss_sync_notif notif = {
                .metadata.type = IWL_MVM_RXQ_NOTIF_DEL_BA,
                .metadata.sync = 1,
                .delba.baid = baid,
@@ -2972,7 +2974,7 @@ out:
        IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n",
                     sta->addr, tid);
 
-       return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq, false);
+       return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.rs_drv.lq);
 }
 
 static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
index 4487cc3e07c1ebc6a223d9b0af387ea52db57b27..8d70093847cb1d8f1fcd3ada15f03f2c620597fa 100644 (file)
@@ -343,9 +343,17 @@ struct iwl_mvm_delba_data {
        u32 baid;
 } __packed;
 
-struct iwl_mvm_delba_notif {
+struct iwl_mvm_nssn_sync_data {
+       u32 baid;
+       u32 nssn;
+} __packed;
+
+struct iwl_mvm_rss_sync_notif {
        struct iwl_mvm_internal_rxq_notif metadata;
-       struct iwl_mvm_delba_data delba;
+       union {
+               struct iwl_mvm_delba_data delba;
+               struct iwl_mvm_nssn_sync_data nssn_sync;
+       };
 } __packed;
 
 /**
index a3e5d88f1c07cf5123f1d100ea117bda189c0938..6ac114a393ccf361cac64a891579de27623e6d7e 100644 (file)
@@ -831,6 +831,7 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
        unsigned int tcp_payload_len;
        unsigned int mss = skb_shinfo(skb)->gso_size;
        bool ipv4 = (skb->protocol == htons(ETH_P_IP));
+       bool qos = ieee80211_is_data_qos(hdr->frame_control);
        u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
 
        skb_shinfo(skb)->gso_size = num_subframes * mss;
@@ -864,7 +865,7 @@ iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes,
                if (tcp_payload_len > mss) {
                        skb_shinfo(tmp)->gso_size = mss;
                } else {
-                       if (ieee80211_is_data_qos(hdr->frame_control)) {
+                       if (qos) {
                                u8 *qc;
 
                                if (ipv4)
index 9ecd5f09615a64a34f220dcad8775568b022cde5..b8e20a01c1923b6de62f7a52bf4e8060ded1c221 100644 (file)
@@ -653,12 +653,12 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
  * this case to clear the state indicating that station creation is in
  * progress.
  */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync)
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq)
 {
        struct iwl_host_cmd cmd = {
                .id = LQ_CMD,
                .len = { sizeof(struct iwl_lq_cmd), },
-               .flags = sync ? 0 : CMD_ASYNC,
+               .flags = CMD_ASYNC,
                .data = { lq, },
        };
 
index ea2a03d4bf55c66571cae63c4223625e9d920db7..de711c1160d316320bc8d92ec3f537e390bbd517 100644 (file)
@@ -604,10 +604,13 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x2526, 0x6010, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x6014, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0xE010, iwl9260_2ac_160_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0xE014, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)},
index fa4245d0d4a8f848163c930126cd088f2f5c46b1..2f0ba7ef53b8616a4bf4581b49106cf0094739ad 100644 (file)
@@ -435,6 +435,8 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
                                         DMA_TO_DEVICE);
        }
 
+       meta->tbs = 0;
+
        if (trans->cfg->use_tfh) {
                struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
 
index 519b4ee88c5c3af68141b6bb357917ca610a32af..772e54f0696fdf728254dbc966936a92ca4a209b 100644 (file)
@@ -3617,10 +3617,12 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
                hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
                                  cb->nlh->nlmsg_seq, &hwsim_genl_family,
                                  NLM_F_MULTI, HWSIM_CMD_GET_RADIO);
-               if (!hdr)
+               if (hdr) {
+                       genl_dump_check_consistent(cb, hdr);
+                       genlmsg_end(skb, hdr);
+               } else {
                        res = -EMSGSIZE;
-               genl_dump_check_consistent(cb, hdr);
-               genlmsg_end(skb, hdr);
+               }
        }
 
 done:
index 3e442c7f78827bf5ce91953af495a7a6cc73a977..095837fba300536c719285183061156f17082028 100644 (file)
@@ -124,6 +124,7 @@ enum {
 
 #define MWIFIEX_MAX_TOTAL_SCAN_TIME    (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
 
+#define WPA_GTK_OUI_OFFSET                             2
 #define RSN_GTK_OUI_OFFSET                             2
 
 #define MWIFIEX_OUI_NOT_PRESENT                        0
index 0d6d41727037a737ed224ca84b6bd370dc0a5b7b..21dda385f6c6816fed5732042b0b135c0e364b68 100644 (file)
@@ -181,7 +181,8 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
        u8 ret = MWIFIEX_OUI_NOT_PRESENT;
 
        if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
-               iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
+               iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
+                                           WPA_GTK_OUI_OFFSET);
                oui = &mwifiex_wpa_oui[cipher][0];
                ret = mwifiex_search_oui_in_ie(iebody, oui);
                if (ret)
index 1d9940d4e8c7d0b627d428589325c10012971af2..c9262ffeefe4cb3eb8a13dfdcc0b77801adc5876 100644 (file)
@@ -925,6 +925,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                        skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
                        nskb = xenvif_alloc_skb(0);
                        if (unlikely(nskb == NULL)) {
+                               skb_shinfo(skb)->nr_frags = 0;
                                kfree_skb(skb);
                                xenvif_tx_err(queue, &txreq, extra_count, idx);
                                if (net_ratelimit())
@@ -940,6 +941,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                        if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
                                /* Failure in xenvif_set_skb_gso is fatal. */
+                               skb_shinfo(skb)->nr_frags = 0;
                                kfree_skb(skb);
                                kfree_skb(nskb);
                                break;
index e65d027b91fafbbd752970cff0afdc9e8cfb0d7c..529be35ac1782a62e9f18b71905fa597ea52a222 100644 (file)
@@ -244,7 +244,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
        /* Reset possible fault of previous session */
        clear_bit(NFCMRVL_PHY_ERROR, &priv->flags);
 
-       if (priv->config.reset_n_io) {
+       if (gpio_is_valid(priv->config.reset_n_io)) {
                nfc_info(priv->dev, "reset the chip\n");
                gpio_set_value(priv->config.reset_n_io, 0);
                usleep_range(5000, 10000);
@@ -255,7 +255,7 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv)
 
 void nfcmrvl_chip_halt(struct nfcmrvl_private *priv)
 {
-       if (priv->config.reset_n_io)
+       if (gpio_is_valid(priv->config.reset_n_io))
                gpio_set_value(priv->config.reset_n_io, 0);
 }
 
index 9a22056e8d9eea921b59a588318be8c47b6b1046..e5a622ce4b9517d299170f20d35bde2bd5e003da 100644 (file)
@@ -26,7 +26,7 @@
 static unsigned int hci_muxed;
 static unsigned int flow_control;
 static unsigned int break_control;
-static unsigned int reset_n_io;
+static int reset_n_io = -EINVAL;
 
 /*
 ** NFCMRVL NCI OPS
@@ -231,5 +231,5 @@ MODULE_PARM_DESC(break_control, "Tell if UART driver must drive break signal.");
 module_param(hci_muxed, uint, 0);
 MODULE_PARM_DESC(hci_muxed, "Tell if transport is muxed in HCI one.");
 
-module_param(reset_n_io, uint, 0);
+module_param(reset_n_io, int, 0);
 MODULE_PARM_DESC(reset_n_io, "GPIO that is wired to RESET_N signal.");
index 945cc903d8f1123fd63a13c42564a3dfe7465a12..888e298f610b8ed7140c85c5d0355d55007b6cfc 100644 (file)
@@ -305,6 +305,7 @@ static int nfcmrvl_probe(struct usb_interface *intf,
 
        /* No configuration for USB */
        memset(&config, 0, sizeof(config));
+       config.reset_n_io = -EINVAL;
 
        nfc_info(&udev->dev, "intf %p id %p\n", intf, id);
 
index c3e10b6ab3a4d45203a67e36af1cf2d193a39028..f25f1ec5f9e97a10aebc1b308180cb84beb4133e 100644 (file)
@@ -333,6 +333,8 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev,
 
                transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
                                            skb->len - 2, GFP_KERNEL);
+               if (!transaction)
+                       return -ENOMEM;
 
                transaction->aid_len = skb->data[1];
                memcpy(transaction->aid, &skb->data[2], transaction->aid_len);
index 06fc542fd19876d16c0a6e8e39de654340cc2b5a..6586378cacb05ed6b80bcc8c9c350010f7e88905 100644 (file)
@@ -317,6 +317,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host,
 
                transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
                                                   skb->len - 2, GFP_KERNEL);
+               if (!transaction)
+                       return -ENOMEM;
 
                transaction->aid_len = skb->data[1];
                memcpy(transaction->aid, &skb->data[2],
index 9dddf133658fd9c086ac6c7cab49ae177536222d..0a5e884a920c0a6de68c1f842972d5dffab31694 100644 (file)
@@ -6,11 +6,6 @@
 #include <linux/msi.h>
 #include <linux/pci.h>
 
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION("0.1");
-MODULE_AUTHOR("Logan Gunthorpe <logang@deltatee.com>");
-MODULE_DESCRIPTION("NTB MSI Interrupt Library");
-
 struct ntb_msi {
        u64 base_addr;
        u64 end_addr;
index 8f3fbe5ca9379988b16c88c6e25cb45869f6a614..c258a1ce4b28aaa3d4f021f30213e80132d2a076 100644 (file)
@@ -1286,6 +1286,9 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
         */
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                mutex_lock(&ctrl->scan_lock);
+               mutex_lock(&ctrl->subsys->lock);
+               nvme_mpath_start_freeze(ctrl->subsys);
+               nvme_mpath_wait_freeze(ctrl->subsys);
                nvme_start_freeze(ctrl);
                nvme_wait_freeze(ctrl);
        }
@@ -1316,6 +1319,8 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
                nvme_update_formats(ctrl);
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                nvme_unfreeze(ctrl);
+               nvme_mpath_unfreeze(ctrl->subsys);
+               mutex_unlock(&ctrl->subsys->lock);
                mutex_unlock(&ctrl->scan_lock);
        }
        if (effects & NVME_CMD_EFFECTS_CCC)
@@ -1715,6 +1720,7 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
        if (ns->head->disk) {
                nvme_update_disk_info(ns->head->disk, ns, id);
                blk_queue_stack_limits(ns->head->disk->queue, ns->queue);
+               revalidate_disk(ns->head->disk);
        }
 #endif
 }
@@ -2487,6 +2493,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
                if (ret) {
                        dev_err(ctrl->device,
                                "failed to register subsystem device.\n");
+                       put_device(&subsys->dev);
                        goto out_unlock;
                }
                ida_init(&subsys->ns_ida);
@@ -2509,7 +2516,6 @@ out_put_subsystem:
        nvme_put_subsystem(subsys);
 out_unlock:
        mutex_unlock(&nvme_subsystems_lock);
-       put_device(&subsys->dev);
        return ret;
 }
 
@@ -3571,6 +3577,13 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
        struct nvme_ns *ns, *next;
        LIST_HEAD(ns_list);
 
+       /*
+        * make sure to requeue I/O to all namespaces as these
+        * might result from the scan itself and must complete
+        * for the scan_work to make progress
+        */
+       nvme_mpath_clear_ctrl_paths(ctrl);
+
        /* prevent racing with ns scanning */
        flush_work(&ctrl->scan_work);
 
index 4f0d0d12744e0e94dbc1e518ca0c1935648c1bac..888d4543894e7d74ea9f75a462df1ace4e3b0cec 100644 (file)
@@ -12,6 +12,36 @@ module_param(multipath, bool, 0444);
 MODULE_PARM_DESC(multipath,
        "turn on native support for multiple controllers per subsystem");
 
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
+{
+       struct nvme_ns_head *h;
+
+       lockdep_assert_held(&subsys->lock);
+       list_for_each_entry(h, &subsys->nsheads, entry)
+               if (h->disk)
+                       blk_mq_unfreeze_queue(h->disk->queue);
+}
+
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+{
+       struct nvme_ns_head *h;
+
+       lockdep_assert_held(&subsys->lock);
+       list_for_each_entry(h, &subsys->nsheads, entry)
+               if (h->disk)
+                       blk_mq_freeze_queue_wait(h->disk->queue);
+}
+
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+{
+       struct nvme_ns_head *h;
+
+       lockdep_assert_held(&subsys->lock);
+       list_for_each_entry(h, &subsys->nsheads, entry)
+               if (h->disk)
+                       blk_freeze_queue_start(h->disk->queue);
+}
+
 /*
  * If multipathing is enabled we need to always use the subsystem instance
  * number for numbering our devices to avoid conflicts between subsystems that
@@ -104,18 +134,34 @@ static const char *nvme_ana_state_names[] = {
        [NVME_ANA_CHANGE]               = "change",
 };
 
-void nvme_mpath_clear_current_path(struct nvme_ns *ns)
+bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
 {
        struct nvme_ns_head *head = ns->head;
+       bool changed = false;
        int node;
 
        if (!head)
-               return;
+               goto out;
 
        for_each_node(node) {
-               if (ns == rcu_access_pointer(head->current_path[node]))
+               if (ns == rcu_access_pointer(head->current_path[node])) {
                        rcu_assign_pointer(head->current_path[node], NULL);
+                       changed = true;
+               }
        }
+out:
+       return changed;
+}
+
+void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
+{
+       struct nvme_ns *ns;
+
+       mutex_lock(&ctrl->scan_lock);
+       list_for_each_entry(ns, &ctrl->namespaces, list)
+               if (nvme_mpath_clear_current_path(ns))
+                       kblockd_schedule_work(&ns->head->requeue_work);
+       mutex_unlock(&ctrl->scan_lock);
 }
 
 static bool nvme_path_is_disabled(struct nvme_ns *ns)
@@ -226,6 +272,24 @@ inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
        return ns;
 }
 
+static bool nvme_available_path(struct nvme_ns_head *head)
+{
+       struct nvme_ns *ns;
+
+       list_for_each_entry_rcu(ns, &head->list, siblings) {
+               switch (ns->ctrl->state) {
+               case NVME_CTRL_LIVE:
+               case NVME_CTRL_RESETTING:
+               case NVME_CTRL_CONNECTING:
+                       /* fallthru */
+                       return true;
+               default:
+                       break;
+               }
+       }
+       return false;
+}
+
 static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
                struct bio *bio)
 {
@@ -252,14 +316,14 @@ static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
                                      disk_devt(ns->head->disk),
                                      bio->bi_iter.bi_sector);
                ret = direct_make_request(bio);
-       } else if (!list_empty_careful(&head->list)) {
-               dev_warn_ratelimited(dev, "no path available - requeuing I/O\n");
+       } else if (nvme_available_path(head)) {
+               dev_warn_ratelimited(dev, "no usable path - requeuing I/O\n");
 
                spin_lock_irq(&head->requeue_lock);
                bio_list_add(&head->requeue_list, bio);
                spin_unlock_irq(&head->requeue_lock);
        } else {
-               dev_warn_ratelimited(dev, "no path - failing I/O\n");
+               dev_warn_ratelimited(dev, "no available path - failing I/O\n");
 
                bio->bi_status = BLK_STS_IOERR;
                bio_endio(bio);
index 26b563f9985b5a9bf4163a18646e9fee68a2ae17..778b3a0b6adb1f9866c4d7d1b0e2b5c08e277ea9 100644 (file)
@@ -490,6 +490,9 @@ static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
        return ctrl->ana_log_buf != NULL;
 }
 
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys);
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
 void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
                        struct nvme_ctrl *ctrl, int *flags);
 void nvme_failover_req(struct request *req);
@@ -500,7 +503,8 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head);
 int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
 void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
 void nvme_mpath_stop(struct nvme_ctrl *ctrl);
-void nvme_mpath_clear_current_path(struct nvme_ns *ns);
+bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
+void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl);
 struct nvme_ns *nvme_find_path(struct nvme_ns_head *head);
 
 static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
@@ -548,7 +552,11 @@ static inline void nvme_mpath_add_disk(struct nvme_ns *ns,
 static inline void nvme_mpath_remove_disk(struct nvme_ns_head *head)
 {
 }
-static inline void nvme_mpath_clear_current_path(struct nvme_ns *ns)
+static inline bool nvme_mpath_clear_current_path(struct nvme_ns *ns)
+{
+       return false;
+}
+static inline void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
 {
 }
 static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
@@ -568,6 +576,15 @@ static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
 static inline void nvme_mpath_stop(struct nvme_ctrl *ctrl)
 {
 }
+static inline void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
+{
+}
+static inline void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+{
+}
+static inline void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+{
+}
 #endif /* CONFIG_NVME_MULTIPATH */
 
 #ifdef CONFIG_NVM
index db160cee42ad178e02b11cc15bb0229a9417f118..6bd9b10339654b3d11aa3944f7a51ee264ffb8a2 100644 (file)
@@ -2695,7 +2695,7 @@ static void nvme_async_probe(void *data, async_cookie_t cookie)
 {
        struct nvme_dev *dev = data;
 
-       nvme_reset_ctrl_sync(&dev->ctrl);
+       flush_work(&dev->ctrl.reset_work);
        flush_work(&dev->ctrl.scan_work);
        nvme_put_ctrl(&dev->ctrl);
 }
@@ -2761,6 +2761,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
 
+       nvme_reset_ctrl(&dev->ctrl);
        nvme_get_ctrl(&dev->ctrl);
        async_schedule(nvme_async_probe, dev);
 
@@ -2846,7 +2847,7 @@ static int nvme_resume(struct device *dev)
        struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));
        struct nvme_ctrl *ctrl = &ndev->ctrl;
 
-       if (pm_resume_via_firmware() || !ctrl->npss ||
+       if (ndev->last_ps == U32_MAX ||
            nvme_set_power_state(ctrl, ndev->last_ps) != 0)
                nvme_reset_ctrl(ctrl);
        return 0;
@@ -2859,6 +2860,8 @@ static int nvme_suspend(struct device *dev)
        struct nvme_ctrl *ctrl = &ndev->ctrl;
        int ret = -EBUSY;
 
+       ndev->last_ps = U32_MAX;
+
        /*
         * The platform does not remove power for a kernel managed suspend so
         * use host managed nvme power settings for lowest idle power if
@@ -2866,8 +2869,14 @@ static int nvme_suspend(struct device *dev)
         * shutdown.  But if the firmware is involved after the suspend or the
         * device does not support any non-default power states, shut down the
         * device fully.
+        *
+        * If ASPM is not enabled for the device, shut down the device and allow
+        * the PCI bus layer to put it into D3 in order to take the PCIe link
+        * down, so as to allow the platform to achieve its minimum low-power
+        * state (which may not be possible if the link is up).
         */
-       if (pm_suspend_via_firmware() || !ctrl->npss) {
+       if (pm_suspend_via_firmware() || !ctrl->npss ||
+           !pcie_aspm_enabled(pdev)) {
                nvme_dev_disable(ndev, true);
                return 0;
        }
@@ -2880,7 +2889,6 @@ static int nvme_suspend(struct device *dev)
            ctrl->state != NVME_CTRL_ADMIN_ONLY)
                goto unfreeze;
 
-       ndev->last_ps = 0;
        ret = nvme_get_power_state(ctrl, &ndev->last_ps);
        if (ret < 0)
                goto unfreeze;
index a249db528d543dcad37e9b5162cc4b196a2f41e1..1a6449bc547b91ab7460b817fd6aada3ca5b5acd 100644 (file)
@@ -562,13 +562,17 @@ out_destroy_cm_id:
        return ret;
 }
 
+static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
+{
+       rdma_disconnect(queue->cm_id);
+       ib_drain_qp(queue->qp);
+}
+
 static void nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
 {
        if (!test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags))
                return;
-
-       rdma_disconnect(queue->cm_id);
-       ib_drain_qp(queue->qp);
+       __nvme_rdma_stop_queue(queue);
 }
 
 static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue)
@@ -607,11 +611,13 @@ static int nvme_rdma_start_queue(struct nvme_rdma_ctrl *ctrl, int idx)
        else
                ret = nvmf_connect_admin_queue(&ctrl->ctrl);
 
-       if (!ret)
+       if (!ret) {
                set_bit(NVME_RDMA_Q_LIVE, &queue->flags);
-       else
+       } else {
+               __nvme_rdma_stop_queue(queue);
                dev_info(ctrl->ctrl.device,
                        "failed to connect queue: %d ret=%d\n", idx, ret);
+       }
        return ret;
 }
 
index cd52b9f153766602036eb9e7322f845551fff855..98613a45bd3b408e343b8e89f9605475f1cb47b9 100644 (file)
@@ -675,6 +675,7 @@ static void nvmet_port_subsys_drop_link(struct config_item *parent,
 
 found:
        list_del(&p->entry);
+       nvmet_port_del_ctrls(port, subsys);
        nvmet_port_disc_changed(port, subsys);
 
        if (list_empty(&port->subsystems))
index dad0243c7c96cfd5f84d5e996b09dcc5fa78d07b..3a67e244e5685a35f65e24e322f85b9557bba37d 100644 (file)
@@ -46,6 +46,9 @@ inline u16 errno_to_nvme_status(struct nvmet_req *req, int errno)
        u16 status;
 
        switch (errno) {
+       case 0:
+               status = NVME_SC_SUCCESS;
+               break;
        case -ENOSPC:
                req->error_loc = offsetof(struct nvme_rw_command, length);
                status = NVME_SC_CAP_EXCEEDED | NVME_SC_DNR;
@@ -280,6 +283,18 @@ void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops)
 }
 EXPORT_SYMBOL_GPL(nvmet_unregister_transport);
 
+void nvmet_port_del_ctrls(struct nvmet_port *port, struct nvmet_subsys *subsys)
+{
+       struct nvmet_ctrl *ctrl;
+
+       mutex_lock(&subsys->lock);
+       list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+               if (ctrl->port == port)
+                       ctrl->ops->delete_ctrl(ctrl);
+       }
+       mutex_unlock(&subsys->lock);
+}
+
 int nvmet_enable_port(struct nvmet_port *port)
 {
        const struct nvmet_fabrics_ops *ops;
index b16dc3981c698749a1a5f85e7066e68c946dfed4..0940c5024a3456457a732c6ae97195e346fd097d 100644 (file)
@@ -654,6 +654,14 @@ static void nvme_loop_remove_port(struct nvmet_port *port)
        mutex_lock(&nvme_loop_ports_mutex);
        list_del_init(&port->entry);
        mutex_unlock(&nvme_loop_ports_mutex);
+
+       /*
+        * Ensure any ctrls that are in the process of being
+        * deleted are in fact deleted before we return
+        * and free the port. This is to prevent active
+        * ctrls from using a port after it's freed.
+        */
+       flush_workqueue(nvme_delete_wq);
 }
 
 static const struct nvmet_fabrics_ops nvme_loop_ops = {
index 6ee66c6107391899898f812a4b4347b284d6c333..c51f8dd01dc487a1395e3a3ff5350cf260046118 100644 (file)
@@ -418,6 +418,9 @@ void nvmet_port_send_ana_event(struct nvmet_port *port);
 int nvmet_register_transport(const struct nvmet_fabrics_ops *ops);
 void nvmet_unregister_transport(const struct nvmet_fabrics_ops *ops);
 
+void nvmet_port_del_ctrls(struct nvmet_port *port,
+                         struct nvmet_subsys *subsys);
+
 int nvmet_enable_port(struct nvmet_port *port);
 void nvmet_disable_port(struct nvmet_port *port);
 
index 6f303b91f6e70d7a438879cfcfe3294936aaa4e0..9e0c429cd08a263c917f66113425630f3902f235 100644 (file)
@@ -224,10 +224,17 @@ int nvmem_sysfs_setup_compat(struct nvmem_device *nvmem,
        if (!config->base_dev)
                return -EINVAL;
 
-       if (nvmem->read_only)
-               nvmem->eeprom = bin_attr_ro_root_nvmem;
-       else
-               nvmem->eeprom = bin_attr_rw_root_nvmem;
+       if (nvmem->read_only) {
+               if (config->root_only)
+                       nvmem->eeprom = bin_attr_ro_root_nvmem;
+               else
+                       nvmem->eeprom = bin_attr_ro_nvmem;
+       } else {
+               if (config->root_only)
+                       nvmem->eeprom = bin_attr_rw_root_nvmem;
+               else
+                       nvmem->eeprom = bin_attr_rw_nvmem;
+       }
        nvmem->eeprom.attr.name = "eeprom";
        nvmem->eeprom.size = nvmem->size;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
index 7f84bb4903caaf4d63847689972ff2c005cb9279..a296eaf52a5b23c377349b59688ffa62ec66db4d 100644 (file)
@@ -277,7 +277,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
  * of_irq_parse_one - Resolve an interrupt for a device
  * @device: the device whose interrupt is to be resolved
  * @index: index of the interrupt to resolve
- * @out_irq: structure of_irq filled by this function
+ * @out_irq: structure of_phandle_args filled by this function
  *
  * This function resolves an interrupt for a node by walking the interrupt tree,
  * finding which interrupt controller node it is attached to, and returning the
index c1b67dd7cd6eed61c75e9fe4234565dd9c329c5b..83c766233181096887f7d4a204214012b8223166 100644 (file)
@@ -206,16 +206,22 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
        for_each_child_of_node(local_fixups, child) {
 
                for_each_child_of_node(overlay, overlay_child)
-                       if (!node_name_cmp(child, overlay_child))
+                       if (!node_name_cmp(child, overlay_child)) {
+                               of_node_put(overlay_child);
                                break;
+                       }
 
-               if (!overlay_child)
+               if (!overlay_child) {
+                       of_node_put(child);
                        return -EINVAL;
+               }
 
                err = adjust_local_phandle_references(child, overlay_child,
                                phandle_delta);
-               if (err)
+               if (err) {
+                       of_node_put(child);
                        return err;
+               }
        }
 
        return 0;
index 29ed5ec1ac27bf1c1d0b2d4028123a992594a513..1b27b5af3d552f8622b075c80dd365561347ec6e 100644 (file)
@@ -1025,10 +1025,15 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
        if (state == PCI_D0) {
                pci_platform_power_transition(dev, PCI_D0);
                /*
-                * Mandatory power management transition delays are
-                * handled in the PCIe portdrv resume hooks.
+                * Mandatory power management transition delays, see
+                * PCI Express Base Specification Revision 2.0 Section
+                * 6.6.1: Conventional Reset.  Do not delay for
+                * devices powered on/off by corresponding bridge,
+                * because have already delayed for the bridge.
                 */
                if (dev->runtime_d3cold) {
+                       if (dev->d3cold_delay && !dev->imm_ready)
+                               msleep(dev->d3cold_delay);
                        /*
                         * When powering on a bridge from D3cold, the
                         * whole hierarchy may be powered on into
@@ -4602,16 +4607,14 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
 
        return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS);
 }
-
 /**
- * pcie_wait_for_link_delay - Wait until link is active or inactive
+ * pcie_wait_for_link - Wait until link is active or inactive
  * @pdev: Bridge device
  * @active: waiting for active or inactive?
- * @delay: Delay to wait after link has become active (in ms)
  *
  * Use this to wait till link becomes active or inactive.
  */
-bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay)
+bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
 {
        int timeout = 1000;
        bool ret;
@@ -4648,25 +4651,13 @@ bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay)
                timeout -= 10;
        }
        if (active && ret)
-               msleep(delay);
+               msleep(100);
        else if (ret != active)
                pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
                        active ? "set" : "cleared");
        return ret == active;
 }
 
-/**
- * pcie_wait_for_link - Wait until link is active or inactive
- * @pdev: Bridge device
- * @active: waiting for active or inactive?
- *
- * Use this to wait till link becomes active or inactive.
- */
-bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
-{
-       return pcie_wait_for_link_delay(pdev, active, 100);
-}
-
 void pci_reset_secondary_bus(struct pci_dev *dev)
 {
        u16 ctrl;
index 1be03a97cb92c1ce9486a4b6ea0f037f7c18067f..d22d1b80770198c5b3fa334b563efd90ae2e7e47 100644 (file)
@@ -497,7 +497,6 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
 void pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state,
                      u32 service);
 
-bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, int delay);
 bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
 #ifdef CONFIG_PCIEASPM
 void pcie_aspm_init_link_state(struct pci_dev *pdev);
index e44af7f4d37ff48c050daeaeab33326ec1a52067..464f8f92653f461e907e3a77062658e1a33a57ec 100644 (file)
@@ -1170,6 +1170,26 @@ static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp)
 module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
        NULL, 0644);
 
+/**
+ * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
+ * @pdev: Target device.
+ */
+bool pcie_aspm_enabled(struct pci_dev *pdev)
+{
+       struct pci_dev *bridge = pci_upstream_bridge(pdev);
+       bool ret;
+
+       if (!bridge)
+               return false;
+
+       mutex_lock(&aspm_lock);
+       ret = bridge->link_state ? !!bridge->link_state->aspm_enabled : false;
+       mutex_unlock(&aspm_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
+
 #ifdef CONFIG_PCIEASPM_DEBUG
 static ssize_t link_state_show(struct device *dev,
                struct device_attribute *attr,
index 308c3e0c4a34012ebda42d5e86d342c8a42edd68..1b330129089fea765919e7ae477298473edb843c 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
@@ -379,67 +378,6 @@ static int pm_iter(struct device *dev, void *data)
        return 0;
 }
 
-static int get_downstream_delay(struct pci_bus *bus)
-{
-       struct pci_dev *pdev;
-       int min_delay = 100;
-       int max_delay = 0;
-
-       list_for_each_entry(pdev, &bus->devices, bus_list) {
-               if (!pdev->imm_ready)
-                       min_delay = 0;
-               else if (pdev->d3cold_delay < min_delay)
-                       min_delay = pdev->d3cold_delay;
-               if (pdev->d3cold_delay > max_delay)
-                       max_delay = pdev->d3cold_delay;
-       }
-
-       return max(min_delay, max_delay);
-}
-
-/*
- * wait_for_downstream_link - Wait for downstream link to establish
- * @pdev: PCIe port whose downstream link is waited
- *
- * Handle delays according to PCIe 4.0 section 6.6.1 before configuration
- * access to the downstream component is permitted.
- *
- * This blocks PCI core resume of the hierarchy below this port until the
- * link is trained. Should be called before resuming port services to
- * prevent pciehp from starting to tear-down the hierarchy too soon.
- */
-static void wait_for_downstream_link(struct pci_dev *pdev)
-{
-       int delay;
-
-       if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
-           pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
-               return;
-
-       if (pci_dev_is_disconnected(pdev))
-               return;
-
-       if (!pdev->subordinate || list_empty(&pdev->subordinate->devices) ||
-           !pdev->bridge_d3)
-               return;
-
-       delay = get_downstream_delay(pdev->subordinate);
-       if (!delay)
-               return;
-
-       dev_dbg(&pdev->dev, "waiting downstream link for %d ms\n", delay);
-
-       /*
-        * If downstream port does not support speeds greater than 5 GT/s
-        * need to wait 100ms. For higher speeds (gen3) we need to wait
-        * first for the data link layer to become active.
-        */
-       if (pcie_get_speed_cap(pdev) <= PCIE_SPEED_5_0GT)
-               msleep(delay);
-       else
-               pcie_wait_for_link_delay(pdev, true, delay);
-}
-
 /**
  * pcie_port_device_suspend - suspend port services associated with a PCIe port
  * @dev: PCI Express port to handle
@@ -453,8 +391,6 @@ int pcie_port_device_suspend(struct device *dev)
 int pcie_port_device_resume_noirq(struct device *dev)
 {
        size_t off = offsetof(struct pcie_port_service_driver, resume_noirq);
-
-       wait_for_downstream_link(to_pci_dev(dev));
        return device_for_each_child(dev, &off, pm_iter);
 }
 
@@ -485,8 +421,6 @@ int pcie_port_device_runtime_suspend(struct device *dev)
 int pcie_port_device_runtime_resume(struct device *dev)
 {
        size_t off = offsetof(struct pcie_port_service_driver, runtime_resume);
-
-       wait_for_downstream_link(to_pci_dev(dev));
        return device_for_each_child(dev, &off, pm_iter);
 }
 #endif /* PM */
index eb6168e6ac434289aeecbf333b1d92f5b9060a84..590e594092f25f080314d08316dd26b2b2831f8b 100644 (file)
@@ -255,8 +255,10 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
        switch (state->Vcc) {
        case 50:
                ++v;
+               /* fall through */
        case 33:
                ++v;
+               /* fall through */
        case 0:
                break;
        default:
@@ -267,9 +269,11 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
        switch (state->Vpp) {
        case 12:
                ++p;
+               /* fall through */
        case 33:
        case 50:
                ++p;
+               /* fall through */
        case 0:
                break;
        default:
index 384396cbb22d21a00bf6f71f6fe7881bbfabf475..22256576b69a22a1b2d421ac44818e945d11e9ab 100644 (file)
@@ -2412,7 +2412,7 @@ static const struct aspeed_pin_config aspeed_g4_configs[] = {
        { PIN_CONFIG_INPUT_DEBOUNCE, { C14, B14 }, SCUA8, 27 },
 };
 
-static int aspeed_g4_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static int aspeed_g4_sig_expr_set(struct aspeed_pinmux_data *ctx,
                                  const struct aspeed_sig_expr *expr,
                                  bool enable)
 {
index 053101f795a29938ec059a395fcee3b498cbf757..ba6438ac4d72a0623da3abd65a03f57d326224b8 100644 (file)
@@ -2507,6 +2507,61 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
        { PIN_CONFIG_INPUT_DEBOUNCE, { A20, B19 }, SCUA8, 27 },
 };
 
+static struct regmap *aspeed_g5_acquire_regmap(struct aspeed_pinmux_data *ctx,
+                                              int ip)
+{
+       if (ip == ASPEED_IP_SCU) {
+               WARN(!ctx->maps[ip], "Missing SCU syscon!");
+               return ctx->maps[ip];
+       }
+
+       if (ip >= ASPEED_NR_PINMUX_IPS)
+               return ERR_PTR(-EINVAL);
+
+       if (likely(ctx->maps[ip]))
+               return ctx->maps[ip];
+
+       if (ip == ASPEED_IP_GFX) {
+               struct device_node *node;
+               struct regmap *map;
+
+               node = of_parse_phandle(ctx->dev->of_node,
+                                       "aspeed,external-nodes", 0);
+               if (node) {
+                       map = syscon_node_to_regmap(node);
+                       of_node_put(node);
+                       if (IS_ERR(map))
+                               return map;
+               } else
+                       return ERR_PTR(-ENODEV);
+
+               ctx->maps[ASPEED_IP_GFX] = map;
+               dev_dbg(ctx->dev, "Acquired GFX regmap");
+               return map;
+       }
+
+       if (ip == ASPEED_IP_LPC) {
+               struct device_node *node;
+               struct regmap *map;
+
+               node = of_parse_phandle(ctx->dev->of_node,
+                                       "aspeed,external-nodes", 1);
+               if (node) {
+                       map = syscon_node_to_regmap(node->parent);
+                       of_node_put(node);
+                       if (IS_ERR(map))
+                               return map;
+               } else
+                       map = ERR_PTR(-ENODEV);
+
+               ctx->maps[ASPEED_IP_LPC] = map;
+               dev_dbg(ctx->dev, "Acquired LPC regmap");
+               return map;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
 /**
  * Configure a pin's signal by applying an expression's descriptor state for
  * all descriptors in the expression.
@@ -2520,7 +2575,7 @@ static struct aspeed_pin_config aspeed_g5_configs[] = {
  * Return: 0 if the expression is configured as requested and a negative error
  * code otherwise
  */
-static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static int aspeed_g5_sig_expr_set(struct aspeed_pinmux_data *ctx,
                                  const struct aspeed_sig_expr *expr,
                                  bool enable)
 {
@@ -2531,9 +2586,15 @@ static int aspeed_g5_sig_expr_set(const struct aspeed_pinmux_data *ctx,
                const struct aspeed_sig_desc *desc = &expr->descs[i];
                u32 pattern = enable ? desc->enable : desc->disable;
                u32 val = (pattern << __ffs(desc->mask));
+               struct regmap *map;
 
-               if (!ctx->maps[desc->ip])
-                       return -ENODEV;
+               map = aspeed_g5_acquire_regmap(ctx, desc->ip);
+               if (IS_ERR(map)) {
+                       dev_err(ctx->dev,
+                               "Failed to acquire regmap for IP block %d\n",
+                               desc->ip);
+                       return PTR_ERR(map);
+               }
 
                /*
                 * Strap registers are configured in hardware or by early-boot
@@ -2641,34 +2702,11 @@ static struct pinctrl_desc aspeed_g5_pinctrl_desc = {
 static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
 {
        int i;
-       struct regmap *map;
-       struct device_node *node;
 
        for (i = 0; i < ARRAY_SIZE(aspeed_g5_pins); i++)
                aspeed_g5_pins[i].number = i;
 
-       node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 0);
-       map = syscon_node_to_regmap(node);
-       of_node_put(node);
-       if (IS_ERR(map)) {
-               dev_warn(&pdev->dev, "No GFX phandle found, some mux configurations may fail\n");
-               map = NULL;
-       }
-       aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_GFX] = map;
-
-       node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
-       if (node) {
-               map = syscon_node_to_regmap(node->parent);
-               if (IS_ERR(map)) {
-                       dev_warn(&pdev->dev, "LHC parent is not a syscon, some mux configurations may fail\n");
-                       map = NULL;
-               }
-       } else {
-               dev_warn(&pdev->dev, "No LHC phandle found, some mux configurations may fail\n");
-               map = NULL;
-       }
-       of_node_put(node);
-       aspeed_g5_pinctrl_data.pinmux.maps[ASPEED_IP_LPC] = map;
+       aspeed_g5_pinctrl_data.pinmux.dev = &pdev->dev;
 
        return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
                        &aspeed_g5_pinctrl_data);
index 535db3de490b73adbc122402ab6dc3da77be42d4..54933665b5f8b4fe7e321c377dddfeddbdcf85ba 100644 (file)
@@ -71,7 +71,7 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
+static int aspeed_sig_expr_enable(struct aspeed_pinmux_data *ctx,
                                  const struct aspeed_sig_expr *expr)
 {
        int ret;
@@ -86,7 +86,7 @@ static int aspeed_sig_expr_enable(const struct aspeed_pinmux_data *ctx,
        return 0;
 }
 
-static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
+static int aspeed_sig_expr_disable(struct aspeed_pinmux_data *ctx,
                                   const struct aspeed_sig_expr *expr)
 {
        int ret;
@@ -109,7 +109,7 @@ static int aspeed_sig_expr_disable(const struct aspeed_pinmux_data *ctx,
  *
  * Return: 0 if all expressions are disabled, otherwise a negative error code
  */
-static int aspeed_disable_sig(const struct aspeed_pinmux_data *ctx,
+static int aspeed_disable_sig(struct aspeed_pinmux_data *ctx,
                              const struct aspeed_sig_expr **exprs)
 {
        int ret = 0;
@@ -217,8 +217,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
 {
        int i;
        int ret;
-       const struct aspeed_pinctrl_data *pdata =
-               pinctrl_dev_get_drvdata(pctldev);
+       struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
        const struct aspeed_pin_group *pgroup = &pdata->pinmux.groups[group];
        const struct aspeed_pin_function *pfunc =
                &pdata->pinmux.functions[function];
@@ -306,8 +305,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
                               unsigned int offset)
 {
        int ret;
-       const struct aspeed_pinctrl_data *pdata =
-               pinctrl_dev_get_drvdata(pctldev);
+       struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
        const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
        const struct aspeed_sig_expr ***prios, **funcs, *expr;
 
index 5b0fe178ccf21042cbe7e6c76acf7bccde191d8c..839c01b7953f2b845f1e0db64f4269feb0bb2131 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "pinmux-aspeed.h"
 
-const char *const aspeed_pinmux_ips[] = {
+static const char *const aspeed_pinmux_ips[] = {
        [ASPEED_IP_SCU] = "SCU",
        [ASPEED_IP_GFX] = "GFX",
        [ASPEED_IP_LPC] = "LPC",
index 329d54d4866775b5f8e7a58ed5dd84ef34ee3f20..52d299b59ce2fe20bebe72a491f66ce59a0e567d 100644 (file)
@@ -702,11 +702,12 @@ struct aspeed_pin_function {
 struct aspeed_pinmux_data;
 
 struct aspeed_pinmux_ops {
-       int (*set)(const struct aspeed_pinmux_data *ctx,
+       int (*set)(struct aspeed_pinmux_data *ctx,
                   const struct aspeed_sig_expr *expr, bool enabled);
 };
 
 struct aspeed_pinmux_data {
+       struct device *dev;
        struct regmap *maps[ASPEED_NR_PINMUX_IPS];
 
        const struct aspeed_pinmux_ops *ops;
@@ -725,7 +726,7 @@ int aspeed_sig_expr_eval(const struct aspeed_pinmux_data *ctx,
                         const struct aspeed_sig_expr *expr,
                         bool enabled);
 
-static inline int aspeed_sig_expr_set(const struct aspeed_pinmux_data *ctx,
+static inline int aspeed_sig_expr_set(struct aspeed_pinmux_data *ctx,
                                      const struct aspeed_sig_expr *expr,
                                      bool enabled)
 {
index c3ab07ab31a96df3072b94240fc241558a0da925..8edfac17364e9141ba4fd7fed8d1a3e0f4df6d1a 100644 (file)
@@ -882,8 +882,11 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
                return of_pwm_get(dev, dev->of_node, con_id);
 
        /* then lookup via ACPI */
-       if (dev && is_acpi_node(dev->fwnode))
-               return acpi_pwm_get(dev->fwnode);
+       if (dev && is_acpi_node(dev->fwnode)) {
+               pwm = acpi_pwm_get(dev->fwnode);
+               if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT)
+                       return pwm;
+       }
 
        /*
         * We look up the provider in the static table typically provided by
index 1b4ee570b712f272363255472caa8fd13662d2d8..4a8a5373cb35142fca9662f8a91358bfd85935e0 100644 (file)
@@ -1704,6 +1704,7 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
                        grp->changed_side = 2;
                        break;
                }
+               /* Else, fall through */
        case MPCG_STATE_XID0IOWAIX:
        case MPCG_STATE_XID7INITW:
        case MPCG_STATE_XID7INITX:
index e02f295d38a9bf060ab2054b67a516713b90eb79..1534420a02433759ae836d904b18973367517be5 100644 (file)
@@ -357,6 +357,7 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
                /*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/
                if (callback)
                        grp->send_qllc_disc = 1;
+               /* Else, fall through */
        case MPCG_STATE_XID0IOWAIT:
                fsm_deltimer(&grp->timer);
                grp->outstanding_xid2 = 0;
@@ -1469,6 +1470,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
                if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) &&
                   (fsm_getstate(wch->fsm) == CH_XID0_PENDING))
                        break;
+               /* Else, fall through */
        default:
                fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
        }
@@ -2089,6 +2091,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
                        grp->estconnfunc = NULL;
                        break;
                }
+               /* Else, fall through */
        case MPCG_STATE_FLOWC:
        case MPCG_STATE_READY:
                grp->send_qllc_disc = 2;
index c7ee07ce3615d93a9d02b5a507ca0ef008a9698f..28db887d38edc809669b32fb146fcd8d64185f92 100644 (file)
@@ -629,6 +629,7 @@ struct qeth_seqno {
 struct qeth_reply {
        struct list_head list;
        struct completion received;
+       spinlock_t lock;
        int (*callback)(struct qeth_card *, struct qeth_reply *,
                unsigned long);
        u32 seqno;
index 4d0caeebc80210d3a130a2ec19574e0e1824b1bb..9c3310c4d61d670426bfa5a842b5f2c750119f04 100644 (file)
@@ -544,6 +544,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
        if (reply) {
                refcount_set(&reply->refcnt, 1);
                init_completion(&reply->received);
+               spin_lock_init(&reply->lock);
        }
        return reply;
 }
@@ -799,6 +800,13 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
 
        if (!reply->callback) {
                rc = 0;
+               goto no_callback;
+       }
+
+       spin_lock_irqsave(&reply->lock, flags);
+       if (reply->rc) {
+               /* Bail out when the requestor has already left: */
+               rc = reply->rc;
        } else {
                if (cmd) {
                        reply->offset = (u16)((char *)cmd - (char *)iob->data);
@@ -807,7 +815,9 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
                        rc = reply->callback(card, reply, (unsigned long)iob);
                }
        }
+       spin_unlock_irqrestore(&reply->lock, flags);
 
+no_callback:
        if (rc <= 0)
                qeth_notify_reply(reply, rc);
        qeth_put_reply(reply);
@@ -1749,6 +1759,16 @@ static int qeth_send_control_data(struct qeth_card *card,
                rc = (timeout == -ERESTARTSYS) ? -EINTR : -ETIME;
 
        qeth_dequeue_reply(card, reply);
+
+       if (reply_cb) {
+               /* Wait until the callback for a late reply has completed: */
+               spin_lock_irq(&reply->lock);
+               if (rc)
+                       /* Zap any callback that's still pending: */
+                       reply->rc = rc;
+               spin_unlock_irq(&reply->lock);
+       }
+
        if (!rc)
                rc = reply->rc;
        qeth_put_reply(reply);
index fd64bc3f406243cbcc311147a1b84a2ab91c4a72..cbead3d1b2fd2c4b47d6c2586fc4e123a5e41b13 100644 (file)
@@ -333,7 +333,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
                                card->osn_info.data_cb(skb);
                                break;
                        }
-                       /* else unknown */
+                       /* Else, fall through */
                default:
                        dev_kfree_skb_any(skb);
                        QETH_CARD_TEXT(card, 3, "inbunkno");
index aea4fd73c8627b1f6ddde32a07f73c0b3693b574..6c68c23036383406d65f328ba4bfeac88aa2521b 100644 (file)
@@ -603,6 +603,7 @@ static void fas216_handlesync(FAS216_Info *info, char *msg)
                msgqueue_flush(&info->scsi.msgs);
                msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
                info->scsi.phase = PHASE_MSGOUT_EXPECT;
+               /* fall through */
 
        case async:
                dev->period = info->ifcfg.asyncperiod / 4;
@@ -915,6 +916,7 @@ static void fas216_disconnect_intr(FAS216_Info *info)
                        fas216_done(info, DID_ABORT);
                        break;
                }
+               /* else, fall through */
 
        default:                                /* huh?                                 */
                printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
@@ -1411,6 +1413,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
        case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out     -> Status       */
        case STATE(STAT_STATUS, PHASE_DATAIN):  /* Data In      -> Status       */
                fas216_stoptransfer(info);
+               /* fall through */
+
        case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status       */
        case STATE(STAT_STATUS, PHASE_MSGOUT):  /* Message Out  -> Status       */
        case STATE(STAT_STATUS, PHASE_COMMAND): /* Command      -> Status       */
@@ -1422,6 +1426,8 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
        case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out     -> Message In   */
        case STATE(STAT_MESGIN, PHASE_DATAIN):  /* Data In      -> Message In   */
                fas216_stoptransfer(info);
+               /* fall through */
+
        case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command      -> Message In   */
        case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
        case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
@@ -1575,6 +1581,7 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned
                        fas216_message(info);
                        break;
                }
+               /* else, fall through */
 
        default:
                fas216_log(info, 0, "internal phase %s for function done?"
@@ -1957,6 +1964,7 @@ static void fas216_kick(FAS216_Info *info)
        switch (where_from) {
        case TYPE_QUEUE:
                fas216_allocate_tag(info, SCpnt);
+               /* fall through */
        case TYPE_OTHER:
                fas216_start_command(info, SCpnt);
                break;
index faf43b1d3dbef626610744daf4d3ecf6220489db..a7549ae32542738cce6a8c4011911f1462ff09d1 100644 (file)
@@ -10776,12 +10776,31 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors)
        /* This loop sets up all CPUs that are affinitized with a
         * irq vector assigned to the driver. All affinitized CPUs
         * will get a link to that vectors IRQ and EQ.
+        *
+        * NULL affinity mask handling:
+        * If irq count is greater than one, log an error message.
+        * If the null mask is received for the first irq, find the
+        * first present cpu, and assign the eq index to ensure at
+        * least one EQ is assigned.
         */
        for (idx = 0; idx <  phba->cfg_irq_chann; idx++) {
                /* Get a CPU mask for all CPUs affinitized to this vector */
                maskp = pci_irq_get_affinity(phba->pcidev, idx);
-               if (!maskp)
-                       continue;
+               if (!maskp) {
+                       if (phba->cfg_irq_chann > 1)
+                               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                               "3329 No affinity mask found "
+                                               "for vector %d (%d)\n",
+                                               idx, phba->cfg_irq_chann);
+                       if (!idx) {
+                               cpu = cpumask_first(cpu_present_mask);
+                               cpup = &phba->sli4_hba.cpu_map[cpu];
+                               cpup->eq = idx;
+                               cpup->irq = pci_irq_vector(phba->pcidev, idx);
+                               cpup->flag |= LPFC_CPU_FIRST_IRQ;
+                       }
+                       break;
+               }
 
                i = 0;
                /* Loop through all CPUs associated with vector idx */
index 3a01cfd70fdcdb45b8f6d149136b91421e82eaa1..f518273cfbe3cbcd4cc4ed0c462550a3c9e11d03 100644 (file)
@@ -4,7 +4,7 @@
 #
 
 menuconfig SOUNDWIRE
-       bool "SoundWire support"
+       tristate "SoundWire support"
        help
          SoundWire is a 2-Pin interface with data and clock line ratified
          by the MIPI Alliance. SoundWire is used for transporting data
@@ -17,17 +17,12 @@ if SOUNDWIRE
 
 comment "SoundWire Devices"
 
-config SOUNDWIRE_BUS
-       tristate
-       select REGMAP_SOUNDWIRE
-
 config SOUNDWIRE_CADENCE
        tristate
 
 config SOUNDWIRE_INTEL
        tristate "Intel SoundWire Master driver"
        select SOUNDWIRE_CADENCE
-       select SOUNDWIRE_BUS
        depends on X86 && ACPI && SND_SOC
        help
          SoundWire Intel Master driver.
index fd99a831b92a0baf3a15b4a42db8160034b1468e..45b7e50016539aaad4242a14a7292ff5c4d7b3a6 100644 (file)
@@ -5,7 +5,7 @@
 
 #Bus Objs
 soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o
-obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
+obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o
 
 #Cadence Objs
 soundwire-cadence-objs := cadence_master.o
index ff4badc9b3dec599e269cda5f1c39b9ef282b305..60e8bdee5c754b83f2170bad9757d5cc5c63aa9d 100644 (file)
@@ -81,8 +81,8 @@
 
 #define CDNS_MCP_INTSET                                0x4C
 
-#define CDNS_SDW_SLAVE_STAT                    0x50
-#define CDNS_MCP_SLAVE_STAT_MASK               BIT(1, 0)
+#define CDNS_MCP_SLAVE_STAT                    0x50
+#define CDNS_MCP_SLAVE_STAT_MASK               GENMASK(1, 0)
 
 #define CDNS_MCP_SLAVE_INTSTAT0                        0x54
 #define CDNS_MCP_SLAVE_INTSTAT1                        0x58
@@ -96,8 +96,8 @@
 #define CDNS_MCP_SLAVE_INTMASK0                        0x5C
 #define CDNS_MCP_SLAVE_INTMASK1                        0x60
 
-#define CDNS_MCP_SLAVE_INTMASK0_MASK           GENMASK(30, 0)
-#define CDNS_MCP_SLAVE_INTMASK1_MASK           GENMASK(16, 0)
+#define CDNS_MCP_SLAVE_INTMASK0_MASK           GENMASK(31, 0)
+#define CDNS_MCP_SLAVE_INTMASK1_MASK           GENMASK(15, 0)
 
 #define CDNS_MCP_PORT_INTSTAT                  0x64
 #define CDNS_MCP_PDI_STAT                      0x6C
index fd4995fb676eaa73aea38da72b7f219f9c67517e..f85ec5b16b65e3ed59880b029c33c930f036c781 100644 (file)
@@ -8,11 +8,14 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/sched/signal.h>
 
 #include "ion.h"
 
 static inline struct page *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
 {
+       if (fatal_signal_pending(current))
+               return NULL;
        return alloc_pages(pool->gfp_mask, pool->order);
 }
 
index 2edf3ee91300007c4dff503774bca1f2fe04b57b..caf4d4df4bd3044f68a6e26b0bc5145b20e150ef 100644 (file)
@@ -342,9 +342,9 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
                            unsigned int flags)
 {
-       int divider, base, prescale;
+       unsigned int divider, base, prescale;
 
-       /* This function needs improvment */
+       /* This function needs improvement */
        /* Don't know if divider==0 works. */
 
        for (prescale = 0; prescale < 16; prescale++) {
@@ -358,7 +358,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
                        divider = (*nanosec) / base;
                        break;
                case CMDF_ROUND_UP:
-                       divider = (*nanosec) / base;
+                       divider = DIV_ROUND_UP(*nanosec, base);
                        break;
                }
                if (divider < 65536) {
@@ -368,7 +368,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
        }
 
        prescale = 15;
-       base = timer_base * (1 << prescale);
+       base = timer_base * (prescale + 1);
        divider = 65535;
        *nanosec = divider * base;
        return (prescale << 16) | (divider);
index b6c6d66e4eb1b5eb8806f85cceee764f805e73b0..e2c7646588f8c9d5cee07e9514e677163cae4eea 100644 (file)
@@ -24,7 +24,7 @@
 
 static int init_display(struct fbtft_par *par)
 {
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        par->fbtftops.reset(par);
index d609a2b67db9b6cf56db1ace82b45e1a019e776c..fd32376700e288b944308c09b5718f0329dcfefd 100644 (file)
@@ -77,7 +77,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */
index b090e7ab6fdd60c5b4df0a7ef8568034eb4aff98..85e54a10ed72c4c9d866d59fac20a2f6e41e1527 100644 (file)
@@ -85,7 +85,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        bt &= 0x07;
index b3d0701880fe353cc46092be339d0e848c904387..5a129b1352cc8ec010ec027322ad1b662ceaf0c8 100644 (file)
@@ -29,7 +29,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        /* Initialization sequence from Lib_UTFT */
index bbf75f795234b06c96a246b009bd05015a06efbf..88a5b6925901d39456efd02f7816b567534cb627 100644 (file)
@@ -28,7 +28,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        write_reg(par, 0x00, 0x0001);
index 4cfe9f8535d0fedb2ce877fd347480e3b01fd733..37622c9462aa7da92d25d1016f0c1f68463a86cc 100644 (file)
@@ -81,7 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
        va_start(args, len);
 
        *buf = (u8)va_arg(args, unsigned int);
-       if (!par->gpio.dc)
+       if (par->gpio.dc)
                gpiod_set_value(par->gpio.dc, 0);
        ret = par->fbtftops.write(par, par->buf, sizeof(u8));
        if (ret < 0) {
@@ -104,7 +104,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
                        return;
                }
        }
-       if (!par->gpio.dc)
+       if (par->gpio.dc)
                gpiod_set_value(par->gpio.dc, 1);
        va_end(args);
 }
index 564a38e3444062b7d049470f23abbbd5a375b71c..c77832ae5e5ba5cffea8cf37915530d29eae745b 100644 (file)
@@ -26,7 +26,7 @@ static int init_display(struct fbtft_par *par)
 {
        par->fbtftops.reset(par);
 
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        /* Initialization sequence from Lib_UTFT */
index 2ea814d0dca5d45679866540ec7c3a7e57fde45a..63c65dd67b175ca9b28c4121115bac4c001b0cdb 100644 (file)
@@ -135,7 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
        remain = len / 2;
        vmem16 = (u16 *)(par->info->screen_buffer + offset);
 
-       if (!par->gpio.dc)
+       if (par->gpio.dc)
                gpiod_set_value(par->gpio.dc, 1);
 
        /* non buffered write */
index 7cbc1bdd2d8a7ef6c2ca4f6b47fe02797c488e87..cf5700a2ea6688d6e73e07151fe40b5d4e6af7e8 100644 (file)
@@ -76,21 +76,18 @@ static int fbtft_request_one_gpio(struct fbtft_par *par,
                                  struct gpio_desc **gpiop)
 {
        struct device *dev = par->info->device;
-       struct device_node *node = dev->of_node;
        int ret = 0;
 
-       if (of_find_property(node, name, NULL)) {
-               *gpiop = devm_gpiod_get_index(dev, dev->driver->name, index,
-                                             GPIOD_OUT_HIGH);
-               if (IS_ERR(*gpiop)) {
-                       ret = PTR_ERR(*gpiop);
-                       dev_err(dev,
-                               "Failed to request %s GPIO:%d\n", name, ret);
-                       return ret;
-               }
-               fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
-                             __func__, name);
+       *gpiop = devm_gpiod_get_index_optional(dev, name, index,
+                                              GPIOD_OUT_HIGH);
+       if (IS_ERR(*gpiop)) {
+               ret = PTR_ERR(*gpiop);
+               dev_err(dev,
+                       "Failed to request %s GPIO: %d\n", name, ret);
+               return ret;
        }
+       fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
+                     __func__, name);
 
        return ret;
 }
@@ -103,34 +100,34 @@ static int fbtft_request_gpios_dt(struct fbtft_par *par)
        if (!par->info->device->of_node)
                return -EINVAL;
 
-       ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset);
+       ret = fbtft_request_one_gpio(par, "reset", 0, &par->gpio.reset);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc);
+       ret = fbtft_request_one_gpio(par, "dc", 0, &par->gpio.dc);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd);
+       ret = fbtft_request_one_gpio(par, "rd", 0, &par->gpio.rd);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr);
+       ret = fbtft_request_one_gpio(par, "wr", 0, &par->gpio.wr);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs);
+       ret = fbtft_request_one_gpio(par, "cs", 0, &par->gpio.cs);
        if (ret)
                return ret;
-       ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch);
+       ret = fbtft_request_one_gpio(par, "latch", 0, &par->gpio.latch);
        if (ret)
                return ret;
        for (i = 0; i < 16; i++) {
-               ret = fbtft_request_one_gpio(par, "db-gpios", i,
+               ret = fbtft_request_one_gpio(par, "db", i,
                                             &par->gpio.db[i]);
                if (ret)
                        return ret;
-               ret = fbtft_request_one_gpio(par, "led-gpios", i,
+               ret = fbtft_request_one_gpio(par, "led", i,
                                             &par->gpio.led[i]);
                if (ret)
                        return ret;
-               ret = fbtft_request_one_gpio(par, "aux-gpios", i,
+               ret = fbtft_request_one_gpio(par, "aux", i,
                                             &par->gpio.aux[i]);
                if (ret)
                        return ret;
@@ -234,9 +231,9 @@ static void fbtft_reset(struct fbtft_par *par)
        if (!par->gpio.reset)
                return;
        fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
-       gpiod_set_value_cansleep(par->gpio.reset, 0);
-       usleep_range(20, 40);
        gpiod_set_value_cansleep(par->gpio.reset, 1);
+       usleep_range(20, 40);
+       gpiod_set_value_cansleep(par->gpio.reset, 0);
        msleep(120);
 }
 
@@ -921,7 +918,7 @@ static int fbtft_init_display_dt(struct fbtft_par *par)
                return -EINVAL;
 
        par->fbtftops.reset(par);
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        while (p) {
@@ -1012,7 +1009,7 @@ int fbtft_init_display(struct fbtft_par *par)
        }
 
        par->fbtftops.reset(par);
-       if (!par->gpio.cs)
+       if (par->gpio.cs)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        i = 0;
index 2be45ee9d061747ad3a2a98f31ba67d9f6214827..464648ee20368627fd0d8a2f98df24888d186df4 100644 (file)
@@ -532,7 +532,7 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr,
                break;
        case ATTR_KERNEL_HIB_SIMPLE_PAGE_TABLE_SIZE:
                ret = scnprintf(buf, PAGE_SIZE, "%u\n",
-                               gasket_page_table_num_entries(
+                               gasket_page_table_num_simple_entries(
                                        gasket_dev->page_table[0]));
                break;
        case ATTR_KERNEL_HIB_NUM_ACTIVE_PAGES:
index 9d4f1dab0968dd04d5ed75daf42f240dfe00c71c..40dd573e73c3d4318ab54911951907f5ecaf9f3d 100644 (file)
@@ -1750,7 +1750,8 @@ static int visornic_poll(struct napi_struct *napi, int budget)
 }
 
 /* poll_for_irq        - checks the status of the response queue
- * @v: Void pointer to the visronic devdata struct.
+ * @t: pointer to the 'struct timer_list' from which we can retrieve the
+ *     the visornic devdata struct.
  *
  * Main function of the vnic_incoming thread. Periodically check the response
  * queue and drain it if needed.
index d72fdd333050cd45042237942f794a41f9d7ffa9..736eedef23b69e5d9670b8a701adb06513ec4f46 100644 (file)
@@ -1969,6 +1969,7 @@ void wilc_deinit_host_int(struct net_device *net)
 
        priv->p2p_listen_state = false;
 
+       flush_workqueue(vif->wilc->hif_workqueue);
        mutex_destroy(&priv->scan_req_lock);
        ret = wilc_deinit(vif);
 
index bfe5e9e034ecf86b3de80476eb90a44a0d228359..c7d51b51898f675917e74e0ff362cad5eb1b9cbe 100644 (file)
@@ -277,10 +277,14 @@ static void kgdboc_pre_exp_handler(void)
        /* Increment the module count when the debugger is active */
        if (!kgdb_connected)
                try_module_get(THIS_MODULE);
+
+       atomic_inc(&ignore_console_lock_warning);
 }
 
 static void kgdboc_post_exp_handler(void)
 {
+       atomic_dec(&ignore_console_lock_warning);
+
        /* decrement the module count when the debugger detaches */
        if (!kgdb_connected)
                module_put(THIS_MODULE);
index b5abfe89190cf28070d05c75bd3703b54d06a6b2..df8812c306407168b66ff2307ee172899d0e5492 100644 (file)
@@ -454,9 +454,11 @@ err_clk:
        imx_disable_unprepare_clks(dev);
 disable_hsic_regulator:
        if (data->hsic_pad_regulator)
-               ret = regulator_disable(data->hsic_pad_regulator);
+               /* don't overwrite original ret (cf. EPROBE_DEFER) */
+               regulator_disable(data->hsic_pad_regulator);
        if (pdata.flags & CI_HDRC_PMQOS)
                pm_qos_remove_request(&data->pm_qos_req);
+       data->ci_pdev = NULL;
        return ret;
 }
 
@@ -469,14 +471,17 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
                pm_runtime_disable(&pdev->dev);
                pm_runtime_put_noidle(&pdev->dev);
        }
-       ci_hdrc_remove_device(data->ci_pdev);
+       if (data->ci_pdev)
+               ci_hdrc_remove_device(data->ci_pdev);
        if (data->override_phy_control)
                usb_phy_shutdown(data->phy);
-       imx_disable_unprepare_clks(&pdev->dev);
-       if (data->plat_data->flags & CI_HDRC_PMQOS)
-               pm_qos_remove_request(&data->pm_qos_req);
-       if (data->hsic_pad_regulator)
-               regulator_disable(data->hsic_pad_regulator);
+       if (data->ci_pdev) {
+               imx_disable_unprepare_clks(&pdev->dev);
+               if (data->plat_data->flags & CI_HDRC_PMQOS)
+                       pm_qos_remove_request(&data->pm_qos_req);
+               if (data->hsic_pad_regulator)
+                       regulator_disable(data->hsic_pad_regulator);
+       }
 
        return 0;
 }
index 183b41753c98298236ea0690cd119e231d1ae5f3..62f4fb9b362f14533c86ba324588158517787019 100644 (file)
@@ -1301,10 +1301,6 @@ made_compressed_probe:
        tty_port_init(&acm->port);
        acm->port.ops = &acm_port_ops;
 
-       minor = acm_alloc_minor(acm);
-       if (minor < 0)
-               goto alloc_fail1;
-
        ctrlsize = usb_endpoint_maxp(epctrl);
        readsize = usb_endpoint_maxp(epread) *
                                (quirks == SINGLE_RX_URB ? 1 : 2);
@@ -1312,6 +1308,13 @@ made_compressed_probe:
        acm->writesize = usb_endpoint_maxp(epwrite) * 20;
        acm->control = control_interface;
        acm->data = data_interface;
+
+       usb_get_intf(acm->control); /* undone in destruct() */
+
+       minor = acm_alloc_minor(acm);
+       if (minor < 0)
+               goto alloc_fail1;
+
        acm->minor = minor;
        acm->dev = usb_dev;
        if (h.usb_cdc_acm_descriptor)
@@ -1458,7 +1461,6 @@ skip_countries:
        usb_driver_claim_interface(&acm_driver, data_interface, acm);
        usb_set_intfdata(data_interface, acm);
 
-       usb_get_intf(control_interface);
        tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
                        &control_interface->dev);
        if (IS_ERR(tty_dev)) {
index 1359b78a624e6b56dcbea6bcf19c3be1960b3848..6cf22c27f2d24e3eb74f631cd2adb07e8c685ce6 100644 (file)
@@ -66,9 +66,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
        char            name[16];
        int             i, size;
 
-       if (!IS_ENABLED(CONFIG_HAS_DMA) ||
-           (!is_device_dma_capable(hcd->self.sysdev) &&
-            !hcd->localmem_pool))
+       if (hcd->localmem_pool || !hcd_uses_dma(hcd))
                return 0;
 
        for (i = 0; i < HCD_BUFFER_POOLS; i++) {
@@ -129,8 +127,7 @@ void *hcd_buffer_alloc(
                return gen_pool_dma_alloc(hcd->localmem_pool, size, dma);
 
        /* some USB hosts just use PIO */
-       if (!IS_ENABLED(CONFIG_HAS_DMA) ||
-           !is_device_dma_capable(bus->sysdev)) {
+       if (!hcd_uses_dma(hcd)) {
                *dma = ~(dma_addr_t) 0;
                return kmalloc(size, mem_flags);
        }
@@ -160,8 +157,7 @@ void hcd_buffer_free(
                return;
        }
 
-       if (!IS_ENABLED(CONFIG_HAS_DMA) ||
-           !is_device_dma_capable(bus->sysdev)) {
+       if (!hcd_uses_dma(hcd)) {
                kfree(addr);
                return;
        }
index b265ab5405f9ae4b20a49945fc60c787751771fc..9063ede411ae73e9ceffe7430ad578f6c7283878 100644 (file)
@@ -1812,8 +1812,6 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
        return 0;
 
  error:
-       if (as && as->usbm)
-               dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count);
        kfree(isopkt);
        kfree(dr);
        if (as)
index 65de6f73b6725200d8ec5cb2301b7a557cdf8a9c..558890ada0e5bdcf8c573af0cc5be59c52c99ef1 100644 (file)
@@ -193,9 +193,10 @@ int usb_register_dev(struct usb_interface *intf,
                intf->minor = minor;
                break;
        }
-       up_write(&minor_rwsem);
-       if (intf->minor < 0)
+       if (intf->minor < 0) {
+               up_write(&minor_rwsem);
                return -EXFULL;
+       }
 
        /* create a usb class device for this usb interface */
        snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
@@ -203,12 +204,11 @@ int usb_register_dev(struct usb_interface *intf,
                                      MKDEV(USB_MAJOR, minor), class_driver,
                                      "%s", kbasename(name));
        if (IS_ERR(intf->usb_dev)) {
-               down_write(&minor_rwsem);
                usb_minors[minor] = NULL;
                intf->minor = -1;
-               up_write(&minor_rwsem);
                retval = PTR_ERR(intf->usb_dev);
        }
+       up_write(&minor_rwsem);
        return retval;
 }
 EXPORT_SYMBOL_GPL(usb_register_dev);
@@ -234,12 +234,12 @@ void usb_deregister_dev(struct usb_interface *intf,
                return;
 
        dev_dbg(&intf->dev, "removing %d minor\n", intf->minor);
+       device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
 
        down_write(&minor_rwsem);
        usb_minors[intf->minor] = NULL;
        up_write(&minor_rwsem);
 
-       device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
        intf->usb_dev = NULL;
        intf->minor = -1;
        destroy_usb_class();
index 9320787ac2e648cb7a8c319b8b56f2e95623ff9b..8592c0344fe81f1458cacf1eaf55bfa516049121 100644 (file)
@@ -103,11 +103,6 @@ static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
 /* wait queue for synchronous unlinks */
 DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
 
-static inline int is_root_hub(struct usb_device *udev)
-{
-       return (udev->parent == NULL);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -880,101 +875,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 }
 
 
-
-/*
- * Show & store the current value of authorized_default
- */
-static ssize_t authorized_default_show(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
-{
-       struct usb_device *rh_usb_dev = to_usb_device(dev);
-       struct usb_bus *usb_bus = rh_usb_dev->bus;
-       struct usb_hcd *hcd;
-
-       hcd = bus_to_hcd(usb_bus);
-       return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
-}
-
-static ssize_t authorized_default_store(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t size)
-{
-       ssize_t result;
-       unsigned val;
-       struct usb_device *rh_usb_dev = to_usb_device(dev);
-       struct usb_bus *usb_bus = rh_usb_dev->bus;
-       struct usb_hcd *hcd;
-
-       hcd = bus_to_hcd(usb_bus);
-       result = sscanf(buf, "%u\n", &val);
-       if (result == 1) {
-               hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
-                       val : USB_DEVICE_AUTHORIZE_ALL;
-               result = size;
-       } else {
-               result = -EINVAL;
-       }
-       return result;
-}
-static DEVICE_ATTR_RW(authorized_default);
-
-/*
- * interface_authorized_default_show - show default authorization status
- * for USB interfaces
- *
- * note: interface_authorized_default is the default value
- *       for initializing the authorized attribute of interfaces
- */
-static ssize_t interface_authorized_default_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct usb_device *usb_dev = to_usb_device(dev);
-       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
-
-       return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
-}
-
-/*
- * interface_authorized_default_store - store default authorization status
- * for USB interfaces
- *
- * note: interface_authorized_default is the default value
- *       for initializing the authorized attribute of interfaces
- */
-static ssize_t interface_authorized_default_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct usb_device *usb_dev = to_usb_device(dev);
-       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
-       int rc = count;
-       bool val;
-
-       if (strtobool(buf, &val) != 0)
-               return -EINVAL;
-
-       if (val)
-               set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
-       else
-               clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
-
-       return rc;
-}
-static DEVICE_ATTR_RW(interface_authorized_default);
-
-/* Group all the USB bus attributes */
-static struct attribute *usb_bus_attrs[] = {
-               &dev_attr_authorized_default.attr,
-               &dev_attr_interface_authorized_default.attr,
-               NULL,
-};
-
-static const struct attribute_group usb_bus_attr_group = {
-       .name = NULL,   /* we want them in the same directory */
-       .attrs = usb_bus_attrs,
-};
-
-
-
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -1512,7 +1412,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
        if (usb_endpoint_xfer_control(&urb->ep->desc)) {
                if (hcd->self.uses_pio_for_control)
                        return ret;
-               if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+               if (hcd_uses_dma(hcd)) {
                        if (is_vmalloc_addr(urb->setup_packet)) {
                                WARN_ONCE(1, "setup packet is not dma capable\n");
                                return -EAGAIN;
@@ -1546,7 +1446,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
        dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
        if (urb->transfer_buffer_length != 0
            && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-               if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) {
+               if (hcd_uses_dma(hcd)) {
                        if (urb->num_sgs) {
                                int n;
 
@@ -2894,32 +2794,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
        if (retval != 0)
                goto err_register_root_hub;
 
-       retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
-       if (retval < 0) {
-               printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",
-                      retval);
-               goto error_create_attr_group;
-       }
        if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
                usb_hcd_poll_rh_status(hcd);
 
        return retval;
 
-error_create_attr_group:
-       clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
-       if (HC_IS_RUNNING(hcd->state))
-               hcd->state = HC_STATE_QUIESCING;
-       spin_lock_irq(&hcd_root_hub_lock);
-       hcd->rh_registered = 0;
-       spin_unlock_irq(&hcd_root_hub_lock);
-
-#ifdef CONFIG_PM
-       cancel_work_sync(&hcd->wakeup_work);
-#endif
-       cancel_work_sync(&hcd->died_work);
-       mutex_lock(&usb_bus_idr_lock);
-       usb_disconnect(&rhdev);         /* Sets rhdev to NULL */
-       mutex_unlock(&usb_bus_idr_lock);
 err_register_root_hub:
        hcd->rh_pollable = 0;
        clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
@@ -2963,8 +2842,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
 
        usb_get_dev(rhdev);
-       sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
-
        clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
        if (HC_IS_RUNNING (hcd->state))
                hcd->state = HC_STATE_QUIESCING;
index e844bb7b5676a4525724d25883231af474cdd8e0..5adf489428aad5dd422121678fc86a3b2da8c71e 100644 (file)
@@ -2218,14 +2218,14 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
                                (struct usb_cdc_dmm_desc *)buffer;
                        break;
                case USB_CDC_MDLM_TYPE:
-                       if (elength < sizeof(struct usb_cdc_mdlm_desc *))
+                       if (elength < sizeof(struct usb_cdc_mdlm_desc))
                                goto next_desc;
                        if (desc)
                                return -EINVAL;
                        desc = (struct usb_cdc_mdlm_desc *)buffer;
                        break;
                case USB_CDC_MDLM_DETAIL_TYPE:
-                       if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *))
+                       if (elength < sizeof(struct usb_cdc_mdlm_detail_desc))
                                goto next_desc;
                        if (detail)
                                return -EINVAL;
index 7e88fdfe3cf5c7c23ba7e9878904a8e72db7686c..f19694e69f5c3eda9f58ba317a81b43096d8228d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/quirks.h>
 #include <linux/of.h>
 #include "usb.h"
@@ -922,6 +923,116 @@ static struct bin_attribute dev_bin_attr_descriptors = {
        .size = 18 + 65535,     /* dev descr + max-size raw descriptor */
 };
 
+/*
+ * Show & store the current value of authorized_default
+ */
+static ssize_t authorized_default_show(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       struct usb_device *rh_usb_dev = to_usb_device(dev);
+       struct usb_bus *usb_bus = rh_usb_dev->bus;
+       struct usb_hcd *hcd;
+
+       hcd = bus_to_hcd(usb_bus);
+       return snprintf(buf, PAGE_SIZE, "%u\n", hcd->dev_policy);
+}
+
+static ssize_t authorized_default_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t size)
+{
+       ssize_t result;
+       unsigned int val;
+       struct usb_device *rh_usb_dev = to_usb_device(dev);
+       struct usb_bus *usb_bus = rh_usb_dev->bus;
+       struct usb_hcd *hcd;
+
+       hcd = bus_to_hcd(usb_bus);
+       result = sscanf(buf, "%u\n", &val);
+       if (result == 1) {
+               hcd->dev_policy = val <= USB_DEVICE_AUTHORIZE_INTERNAL ?
+                       val : USB_DEVICE_AUTHORIZE_ALL;
+               result = size;
+       } else {
+               result = -EINVAL;
+       }
+       return result;
+}
+static DEVICE_ATTR_RW(authorized_default);
+
+/*
+ * interface_authorized_default_show - show default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ *       for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct usb_device *usb_dev = to_usb_device(dev);
+       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+
+       return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
+}
+
+/*
+ * interface_authorized_default_store - store default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ *       for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct usb_device *usb_dev = to_usb_device(dev);
+       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+       int rc = count;
+       bool val;
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       if (val)
+               set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+       else
+               clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
+       return rc;
+}
+static DEVICE_ATTR_RW(interface_authorized_default);
+
+/* Group all the USB bus attributes */
+static struct attribute *usb_bus_attrs[] = {
+               &dev_attr_authorized_default.attr,
+               &dev_attr_interface_authorized_default.attr,
+               NULL,
+};
+
+static const struct attribute_group usb_bus_attr_group = {
+       .name = NULL,   /* we want them in the same directory */
+       .attrs = usb_bus_attrs,
+};
+
+
+static int add_default_authorized_attributes(struct device *dev)
+{
+       int rc = 0;
+
+       if (is_usb_device(dev))
+               rc = sysfs_create_group(&dev->kobj, &usb_bus_attr_group);
+
+       return rc;
+}
+
+static void remove_default_authorized_attributes(struct device *dev)
+{
+       if (is_usb_device(dev)) {
+               sysfs_remove_group(&dev->kobj, &usb_bus_attr_group);
+       }
+}
+
 int usb_create_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
@@ -938,7 +1049,14 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
        retval = add_power_attributes(dev);
        if (retval)
                goto error;
+
+       if (is_root_hub(udev)) {
+               retval = add_default_authorized_attributes(dev);
+               if (retval)
+                       goto error;
+       }
        return retval;
+
 error:
        usb_remove_sysfs_dev_files(udev);
        return retval;
@@ -948,6 +1066,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
 
+       if (is_root_hub(udev))
+               remove_default_authorized_attributes(dev);
+
        remove_power_attributes(dev);
        remove_persist_attributes(dev);
        device_remove_bin_file(dev, &dev_bin_attr_descriptors);
index bd8d01f85a1371dffa8f32e522ecaa4ae5e8e23e..0c9fde5ad0524b50f1789803dbd00fa8adec4713 100644 (file)
@@ -153,6 +153,11 @@ static inline int is_usb_port(const struct device *dev)
        return dev->type == &usb_port_device_type;
 }
 
+static inline int is_root_hub(struct usb_device *udev)
+{
+       return (udev->parent == NULL);
+}
+
 /* Do the same for device drivers and interface drivers. */
 
 static inline int is_usb_device_driver(struct device_driver *drv)
index ee144ff8af5b1195f08ce0466d0586231f3d0dd3..111787a137eead0bd65e554bc2a9705ad39dbcc9 100644 (file)
@@ -4608,7 +4608,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 
        buf = urb->transfer_buffer;
 
-       if (hcd->self.uses_dma) {
+       if (hcd_uses_dma(hcd)) {
                if (!buf && (urb->transfer_dma & 3)) {
                        dev_err(hsotg->dev,
                                "%s: unaligned transfer with no transfer_buffer",
index 9118b42c70b6312659eafd76f72b97434147ac2c..76883ff4f5bb6f7c4a157716c76354a01f20afc0 100644 (file)
@@ -1976,6 +1976,7 @@ void composite_disconnect(struct usb_gadget *gadget)
         * disconnect callbacks?
         */
        spin_lock_irqsave(&cdev->lock, flags);
+       cdev->suspended = 0;
        if (cdev->config)
                reset_config(cdev);
        if (cdev->driver->disconnect)
index 29cc5693e05cc55dafbd7c00cc57b8476c7cbc41..7c96c4665178e4c60ccc66f7153b29b1d1f4316d 100644 (file)
@@ -261,7 +261,7 @@ struct fsg_common;
 struct fsg_common {
        struct usb_gadget       *gadget;
        struct usb_composite_dev *cdev;
-       struct fsg_dev          *fsg, *new_fsg;
+       struct fsg_dev          *fsg;
        wait_queue_head_t       io_wait;
        wait_queue_head_t       fsg_wait;
 
@@ -290,6 +290,7 @@ struct fsg_common {
        unsigned int            bulk_out_maxpacket;
        enum fsg_state          state;          /* For exception handling */
        unsigned int            exception_req_tag;
+       void                    *exception_arg;
 
        enum data_direction     data_dir;
        u32                     data_size;
@@ -391,7 +392,8 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
 
 /* These routines may be called in process context or in_irq */
 
-static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+static void __raise_exception(struct fsg_common *common, enum fsg_state new_state,
+                             void *arg)
 {
        unsigned long           flags;
 
@@ -404,6 +406,7 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
        if (common->state <= new_state) {
                common->exception_req_tag = common->ep0_req_tag;
                common->state = new_state;
+               common->exception_arg = arg;
                if (common->thread_task)
                        send_sig_info(SIGUSR1, SEND_SIG_PRIV,
                                      common->thread_task);
@@ -411,6 +414,10 @@ static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
        spin_unlock_irqrestore(&common->lock, flags);
 }
 
+static void raise_exception(struct fsg_common *common, enum fsg_state new_state)
+{
+       __raise_exception(common, new_state, NULL);
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -2285,16 +2292,16 @@ reset:
 static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->new_fsg = fsg;
-       raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+
+       __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, fsg);
        return USB_GADGET_DELAYED_STATUS;
 }
 
 static void fsg_disable(struct usb_function *f)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
-       fsg->common->new_fsg = NULL;
-       raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+
+       __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL);
 }
 
 
@@ -2307,6 +2314,7 @@ static void handle_exception(struct fsg_common *common)
        enum fsg_state          old_state;
        struct fsg_lun          *curlun;
        unsigned int            exception_req_tag;
+       struct fsg_dev          *new_fsg;
 
        /*
         * Clear the existing signals.  Anything but SIGUSR1 is converted
@@ -2360,6 +2368,7 @@ static void handle_exception(struct fsg_common *common)
        common->next_buffhd_to_fill = &common->buffhds[0];
        common->next_buffhd_to_drain = &common->buffhds[0];
        exception_req_tag = common->exception_req_tag;
+       new_fsg = common->exception_arg;
        old_state = common->state;
        common->state = FSG_STATE_NORMAL;
 
@@ -2413,8 +2422,8 @@ static void handle_exception(struct fsg_common *common)
                break;
 
        case FSG_STATE_CONFIG_CHANGE:
-               do_set_interface(common, common->new_fsg);
-               if (common->new_fsg)
+               do_set_interface(common, new_fsg);
+               if (new_fsg)
                        usb_composite_setup_continue(common->cdev);
                break;
 
@@ -2989,8 +2998,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
 
        DBG(fsg, "unbind\n");
        if (fsg->common->fsg == fsg) {
-               fsg->common->new_fsg = NULL;
-               raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+               __raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE, NULL);
                /* FIXME: make interruptible or killable somehow? */
                wait_event(common->fsg_wait, common->fsg != fsg);
        }
index 87062d22134da38d22dce196f28461ce22d4a0da..1f4c3fbd1df8b37d1d2f8cd82470171be2ae9985 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/sys_soc.h>
 #include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
@@ -2450,9 +2451,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
        if (usb3->forced_b_device)
                return -EBUSY;
 
-       if (!strncmp(buf, "host", strlen("host")))
+       if (sysfs_streq(buf, "host"))
                new_mode_is_host = true;
-       else if (!strncmp(buf, "peripheral", strlen("peripheral")))
+       else if (sysfs_streq(buf, "peripheral"))
                new_mode_is_host = false;
        else
                return -EINVAL;
index 77cc36efae9500ea94f7109f5d7abed19812275a..0dbfa5c107035df3e0158a1af07a271c600a2df6 100644 (file)
@@ -1629,6 +1629,10 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        /* see what we found out */
                        temp = check_reset_complete(fotg210, wIndex, status_reg,
                                        fotg210_readl(fotg210, status_reg));
+
+                       /* restart schedule */
+                       fotg210->command |= CMD_RUN;
+                       fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
                }
 
                if (!(temp & (PORT_RESUME|PORT_RESET))) {
index 671bce18782c5a788ad1af896ab9066fd4078839..8616c52849c6d2a8f6ac30dd887be966b3cf9eab 100644 (file)
@@ -238,10 +238,15 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd)
         * pointers. So, this driver clears the AC64 bit of xhci->hcc_params
         * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in
         * xhci_gen_setup().
+        *
+        * And, since the firmware/internal CPU control the USBSTS.STS_HALT
+        * and the process speed is down when the roothub port enters U3,
+        * long delay for the handshake of STS_HALT is neeed in xhci_suspend().
         */
        if (xhci_rcar_is_gen2(hcd->self.controller) ||
-                       xhci_rcar_is_gen3(hcd->self.controller))
-               xhci->quirks |= XHCI_NO_64BIT_SUPPORT;
+                       xhci_rcar_is_gen3(hcd->self.controller)) {
+               xhci->quirks |= XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND;
+       }
 
        if (!xhci_rcar_wait_for_pll_active(hcd))
                return -ETIMEDOUT;
index 248cd7a8b163b60044ea390d75bfc2544c813aa0..03d1e552769bf9d1a7471e8c17d36765eb0225f6 100644 (file)
@@ -3089,8 +3089,18 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
                return;
        udev = (struct usb_device *) host_ep->hcpriv;
        vdev = xhci->devs[udev->slot_id];
+
+       /*
+        * vdev may be lost due to xHC restore error and re-initialization
+        * during S3/S4 resume. A new vdev will be allocated later by
+        * xhci_discover_or_reset_device()
+        */
+       if (!udev->slot_id || !vdev)
+               return;
        ep_index = xhci_get_endpoint_index(&host_ep->desc);
        ep = &vdev->eps[ep_index];
+       if (!ep)
+               return;
 
        /* Bail out if toggle is already being cleared by a endpoint reset */
        if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
index ba05dd80a020fb553752ff2b80e04a20b862c26f..f5bed9f29e5621521b4ea754ed76a5442744492d 100644 (file)
@@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface)
        dev = usb_get_intfdata(interface);
        mutex_lock(&iowarrior_open_disc_lock);
        usb_set_intfdata(interface, NULL);
+       /* prevent device read, write and ioctl */
+       dev->present = 0;
 
        minor = dev->minor;
+       mutex_unlock(&iowarrior_open_disc_lock);
+       /* give back our minor - this will call close() locks need to be dropped at this point*/
 
-       /* give back our minor */
        usb_deregister_dev(interface, &iowarrior_class);
 
        mutex_lock(&dev->mutex);
 
        /* prevent device read, write and ioctl */
-       dev->present = 0;
 
        mutex_unlock(&dev->mutex);
-       mutex_unlock(&iowarrior_open_disc_lock);
 
        if (dev->opened) {
                /* There is a process that holds a filedescriptor to the device ,
index 27e9c78a791e25fc444728da708b63ca421f9983..a32d61a79ab8af6170b00578e7cc066138f66c53 100644 (file)
@@ -51,6 +51,7 @@ struct rio_usb_data {
         char *obuf, *ibuf;              /* transfer buffers */
         char bulk_in_ep, bulk_out_ep;   /* Endpoint assignments */
         wait_queue_head_t wait_q;       /* for timeouts */
+       struct mutex lock;          /* general race avoidance */
 };
 
 static DEFINE_MUTEX(rio500_mutex);
@@ -62,8 +63,10 @@ static int open_rio(struct inode *inode, struct file *file)
 
        /* against disconnect() */
        mutex_lock(&rio500_mutex);
+       mutex_lock(&(rio->lock));
 
        if (rio->isopen || !rio->present) {
+               mutex_unlock(&(rio->lock));
                mutex_unlock(&rio500_mutex);
                return -EBUSY;
        }
@@ -71,6 +74,7 @@ static int open_rio(struct inode *inode, struct file *file)
 
        init_waitqueue_head(&rio->wait_q);
 
+       mutex_unlock(&(rio->lock));
 
        dev_info(&rio->rio_dev->dev, "Rio opened.\n");
        mutex_unlock(&rio500_mutex);
@@ -84,6 +88,7 @@ static int close_rio(struct inode *inode, struct file *file)
 
        /* against disconnect() */
        mutex_lock(&rio500_mutex);
+       mutex_lock(&(rio->lock));
 
        rio->isopen = 0;
        if (!rio->present) {
@@ -95,6 +100,7 @@ static int close_rio(struct inode *inode, struct file *file)
        } else {
                dev_info(&rio->rio_dev->dev, "Rio closed.\n");
        }
+       mutex_unlock(&(rio->lock));
        mutex_unlock(&rio500_mutex);
        return 0;
 }
@@ -109,7 +115,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
        int retries;
        int retval=0;
 
-       mutex_lock(&rio500_mutex);
+       mutex_lock(&(rio->lock));
         /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
                retval = -ENODEV;
@@ -253,7 +259,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
 
 
 err_out:
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
        return retval;
 }
 
@@ -273,12 +279,12 @@ write_rio(struct file *file, const char __user *buffer,
        int errn = 0;
        int intr;
 
-       intr = mutex_lock_interruptible(&rio500_mutex);
+       intr = mutex_lock_interruptible(&(rio->lock));
        if (intr)
                return -EINTR;
         /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
-               mutex_unlock(&rio500_mutex);
+               mutex_unlock(&(rio->lock));
                return -ENODEV;
        }
 
@@ -301,7 +307,7 @@ write_rio(struct file *file, const char __user *buffer,
                                goto error;
                        }
                        if (signal_pending(current)) {
-                               mutex_unlock(&rio500_mutex);
+                               mutex_unlock(&(rio->lock));
                                return bytes_written ? bytes_written : -EINTR;
                        }
 
@@ -339,12 +345,12 @@ write_rio(struct file *file, const char __user *buffer,
                buffer += copy_size;
        } while (count > 0);
 
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
 
        return bytes_written ? bytes_written : -EIO;
 
 error:
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
        return errn;
 }
 
@@ -361,12 +367,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
        char *ibuf;
        int intr;
 
-       intr = mutex_lock_interruptible(&rio500_mutex);
+       intr = mutex_lock_interruptible(&(rio->lock));
        if (intr)
                return -EINTR;
        /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
-               mutex_unlock(&rio500_mutex);
+               mutex_unlock(&(rio->lock));
                return -ENODEV;
        }
 
@@ -377,11 +383,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
 
        while (count > 0) {
                if (signal_pending(current)) {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        return read_count ? read_count : -EINTR;
                }
                if (!rio->rio_dev) {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        return -ENODEV;
                }
                this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
@@ -399,7 +405,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
                        count = this_read = partial;
                } else if (result == -ETIMEDOUT || result == 15) {      /* FIXME: 15 ??? */
                        if (!maxretry--) {
-                               mutex_unlock(&rio500_mutex);
+                               mutex_unlock(&(rio->lock));
                                dev_err(&rio->rio_dev->dev,
                                        "read_rio: maxretry timeout\n");
                                return -ETIME;
@@ -409,19 +415,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
                        finish_wait(&rio->wait_q, &wait);
                        continue;
                } else if (result != -EREMOTEIO) {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        dev_err(&rio->rio_dev->dev,
                                "Read Whoops - result:%d partial:%u this_read:%u\n",
                                result, partial, this_read);
                        return -EIO;
                } else {
-                       mutex_unlock(&rio500_mutex);
+                       mutex_unlock(&(rio->lock));
                        return (0);
                }
 
                if (this_read) {
                        if (copy_to_user(buffer, ibuf, this_read)) {
-                               mutex_unlock(&rio500_mutex);
+                               mutex_unlock(&(rio->lock));
                                return -EFAULT;
                        }
                        count -= this_read;
@@ -429,7 +435,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
                        buffer += this_read;
                }
        }
-       mutex_unlock(&rio500_mutex);
+       mutex_unlock(&(rio->lock));
        return read_count;
 }
 
@@ -494,6 +500,8 @@ static int probe_rio(struct usb_interface *intf,
        }
        dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
 
+       mutex_init(&(rio->lock));
+
        usb_set_intfdata (intf, rio);
        rio->present = 1;
 bail_out:
@@ -511,10 +519,12 @@ static void disconnect_rio(struct usb_interface *intf)
        if (rio) {
                usb_deregister_dev(intf, &usb_rio_class);
 
+               mutex_lock(&(rio->lock));
                if (rio->isopen) {
                        rio->isopen = 0;
                        /* better let it finish - the release will do whats needed */
                        rio->rio_dev = NULL;
+                       mutex_unlock(&(rio->lock));
                        mutex_unlock(&rio500_mutex);
                        return;
                }
@@ -524,6 +534,7 @@ static void disconnect_rio(struct usb_interface *intf)
                dev_info(&intf->dev, "USB Rio disconnected.\n");
 
                rio->present = 0;
+               mutex_unlock(&(rio->lock));
        }
        mutex_unlock(&rio500_mutex);
 }
index 7b306aa22d2589518d696111cb2750bdc3bed4c0..6715a128e6c8b29bd52cb6c132b5eb0ecd459209 100644 (file)
@@ -92,7 +92,6 @@ static void yurex_delete(struct kref *kref)
 
        dev_dbg(&dev->interface->dev, "%s\n", __func__);
 
-       usb_put_dev(dev->udev);
        if (dev->cntl_urb) {
                usb_kill_urb(dev->cntl_urb);
                kfree(dev->cntl_req);
@@ -108,6 +107,7 @@ static void yurex_delete(struct kref *kref)
                                dev->int_buffer, dev->urb->transfer_dma);
                usb_free_urb(dev->urb);
        }
+       usb_put_dev(dev->udev);
        kfree(dev);
 }
 
index c1582fbd1150326e070603fc537f2f283e59b365..38e920ac7f82092f996279c0918c88538f932175 100644 (file)
@@ -968,6 +968,11 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) },
 
+       /* Motorola devices */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x2a70, 0xff, 0xff, 0xff) },    /* mdm6600 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x2e0a, 0xff, 0xff, 0xff) },    /* mdm9600 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x4281, 0x0a, 0x00, 0xfc) },    /* mdm ram dl */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x900e, 0xff, 0xff, 0xff) },    /* mdm qc dl */
 
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
@@ -1549,6 +1554,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff),  /* Telewell TW-LTE 4G v2 */
          .driver_info = RSVD(2) },
        { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) },    /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0x00, 0x00) }, /* ZTE MF871A */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
@@ -1952,11 +1958,15 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) },
        { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff),                     /* D-Link DWM-222 */
          .driver_info = RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e3d, 0xff),                     /* D-Link DWM-222 A2 */
+         .driver_info = RSVD(4) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) },    /* D-Link DWM-152/C1 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) },    /* D-Link DWM-156/C1 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) },    /* D-Link DWM-156/A3 */
        { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff),                     /* Olicard 600 */
          .driver_info = RSVD(4) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2060, 0xff),                     /* BroadMobi BM818 */
+         .driver_info = RSVD(4) },
        { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) },                   /* OLICARD300 - MT6225 */
        { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
        { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
index fba32d84e5787f2f0b47a94d7c61e0b16747e190..15abe1d9958fdb402f9025248b3836b995c3313b 100644 (file)
@@ -379,7 +379,8 @@ static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
                        return SNK_UNATTACHED;
                else if (port->try_role == TYPEC_SOURCE)
                        return SRC_UNATTACHED;
-               else if (port->tcpc->config->default_role == TYPEC_SINK)
+               else if (port->tcpc->config &&
+                        port->tcpc->config->default_role == TYPEC_SINK)
                        return SNK_UNATTACHED;
                /* Fall through to return SRC_UNATTACHED */
        } else if (port->port_type == TYPEC_PORT_SNK) {
@@ -586,7 +587,20 @@ static void tcpm_debugfs_init(struct tcpm_port *port)
 
 static void tcpm_debugfs_exit(struct tcpm_port *port)
 {
+       int i;
+
+       mutex_lock(&port->logbuffer_lock);
+       for (i = 0; i < LOG_BUFFER_ENTRIES; i++) {
+               kfree(port->logbuffer[i]);
+               port->logbuffer[i] = NULL;
+       }
+       mutex_unlock(&port->logbuffer_lock);
+
        debugfs_remove(port->dentry);
+       if (list_empty(&rootdir->d_subdirs)) {
+               debugfs_remove(rootdir);
+               rootdir = NULL;
+       }
 }
 
 #else
@@ -1095,7 +1109,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
                        break;
                case CMD_ATTENTION:
                        /* Attention command does not have response */
-                       typec_altmode_attention(adev, p[1]);
+                       if (adev)
+                               typec_altmode_attention(adev, p[1]);
                        return 0;
                default:
                        break;
@@ -1147,20 +1162,26 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
                        }
                        break;
                case CMD_ENTER_MODE:
-                       typec_altmode_update_active(pdev, true);
-
-                       if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
-                               response[0] = VDO(adev->svid, 1, CMD_EXIT_MODE);
-                               response[0] |= VDO_OPOS(adev->mode);
-                               return 1;
+                       if (adev && pdev) {
+                               typec_altmode_update_active(pdev, true);
+
+                               if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) {
+                                       response[0] = VDO(adev->svid, 1,
+                                                         CMD_EXIT_MODE);
+                                       response[0] |= VDO_OPOS(adev->mode);
+                                       return 1;
+                               }
                        }
                        return 0;
                case CMD_EXIT_MODE:
-                       typec_altmode_update_active(pdev, false);
+                       if (adev && pdev) {
+                               typec_altmode_update_active(pdev, false);
 
-                       /* Back to USB Operation */
-                       WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB,
-                                                    NULL));
+                               /* Back to USB Operation */
+                               WARN_ON(typec_altmode_notify(adev,
+                                                            TYPEC_STATE_USB,
+                                                            NULL));
+                       }
                        break;
                default:
                        break;
@@ -1170,8 +1191,10 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
                switch (cmd) {
                case CMD_ENTER_MODE:
                        /* Back to USB Operation */
-                       WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB,
-                                                    NULL));
+                       if (adev)
+                               WARN_ON(typec_altmode_notify(adev,
+                                                            TYPEC_STATE_USB,
+                                                            NULL));
                        break;
                default:
                        break;
@@ -1182,7 +1205,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
        }
 
        /* Informing the alternate mode drivers about everything */
-       typec_altmode_vdm(adev, p[0], &p[1], cnt);
+       if (adev)
+               typec_altmode_vdm(adev, p[0], &p[1], cnt);
 
        return rlen;
 }
@@ -4114,7 +4138,7 @@ static int tcpm_try_role(const struct typec_capability *cap, int role)
        mutex_lock(&port->lock);
        if (tcpc->try_role)
                ret = tcpc->try_role(tcpc, role);
-       if (!ret && !tcpc->config->try_role_hw)
+       if (!ret && (!tcpc->config || !tcpc->config->try_role_hw))
                port->try_role = role;
        port->try_src_count = 0;
        port->try_snk_count = 0;
@@ -4701,7 +4725,7 @@ static int tcpm_copy_caps(struct tcpm_port *port,
        port->typec_caps.prefer_role = tcfg->default_role;
        port->typec_caps.type = tcfg->type;
        port->typec_caps.data = tcfg->data;
-       port->self_powered = port->tcpc->config->self_powered;
+       port->self_powered = tcfg->self_powered;
 
        return 0;
 }
index f7a79a23ebedc02898102d287114ffafbb4b8ccc..8e9f8fba55af999f1b1c3c73bfd68919518e42e5 100644 (file)
@@ -1018,7 +1018,7 @@ release_fw:
  ******************************************************************************/
 static int ccg_fw_update(struct ucsi_ccg *uc, enum enum_flash_mode flash_mode)
 {
-       int err;
+       int err = 0;
 
        while (flash_mode != FLASH_NOT_NEEDED) {
                err = do_flash(uc, flash_mode);
index 90eca64e3144398a3c44472eb1a2c7e81d18d2b5..702cca59bda192a730f73648b5edd3b1b55ab533 100644 (file)
@@ -447,6 +447,7 @@ static int set_color_mode(struct omapfb_plane_struct *plane,
                return 0;
        case 12:
                var->bits_per_pixel = 16;
+               /* fall through */
        case 16:
                if (plane->fbdev->panel->bpp == 12)
                        plane->color_mode = OMAPFB_COLOR_RGB444;
@@ -1534,20 +1535,27 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
        case OMAPFB_ACTIVE:
                for (i = 0; i < fbdev->mem_desc.region_cnt; i++)
                        unregister_framebuffer(fbdev->fb_info[i]);
+               /* fall through */
        case 7:
                omapfb_unregister_sysfs(fbdev);
+               /* fall through */
        case 6:
                if (fbdev->panel->disable)
                        fbdev->panel->disable(fbdev->panel);
+               /* fall through */
        case 5:
                omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
+               /* fall through */
        case 4:
                planes_cleanup(fbdev);
+               /* fall through */
        case 3:
                ctrl_cleanup(fbdev);
+               /* fall through */
        case 2:
                if (fbdev->panel->cleanup)
                        fbdev->panel->cleanup(fbdev->panel);
+               /* fall through */
        case 1:
                dev_set_drvdata(fbdev->dev, NULL);
                kfree(fbdev);
index b9b2d06b387965eb206e1f08c6ffad7129b4f707..668a1c704f28063602b87a90713522d593be80d6 100644 (file)
@@ -235,6 +235,7 @@ static long ar7_wdt_ioctl(struct file *file,
                ar7_wdt_update_margin(new_margin);
                ar7_wdt_kick(1);
                spin_unlock(&wdt_lock);
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                if (put_user(margin, (int *)arg))
index 1b2cf5b95a89d301a14e8413bc1fcb2c47b17110..c3c93e00b32050947d6bd0a592915ba2a8fb4f03 100644 (file)
@@ -651,7 +651,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        return -EINVAL;
 
                pcwd_keepalive();
-               /* Fall */
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                return put_user(heartbeat, argp);
index 41a2a11535a6a8939cd48c0d7c3239b2ba889dc0..b35f7be20c00d08b12b7ef234d6c5f2214717aca 100644 (file)
@@ -134,7 +134,7 @@ static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        return -EINVAL;
                riowd_timeout = (new_margin + 59) / 60;
                riowd_writereg(p, riowd_timeout, WDTO_INDEX);
-               /* Fall */
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                return put_user(riowd_timeout * 60, (int __user *)argp);
index 5a6ced7a7e8f80a95ebc0ecba3e70c793caea701..202fc8d8ca5fa573385279ca14c6d7557784c71c 100644 (file)
@@ -202,6 +202,7 @@ static long sbwdog_ioctl(struct file *file, unsigned int cmd,
                timeout = time;
                sbwdog_set(user_dog, timeout);
                sbwdog_pet(user_dog);
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                /*
index efd7996694de6c994a282c2bc65a84a1db299e62..46268309ee9b86825eb5cc1a6155e4ca08430de1 100644 (file)
@@ -186,6 +186,7 @@ static long scx200_wdt_ioctl(struct file *file, unsigned int cmd,
                margin = new_margin;
                scx200_wdt_update_margin();
                scx200_wdt_ping();
+               /* Fall through */
        case WDIOC_GETTIMEOUT:
                if (put_user(margin, p))
                        return -EFAULT;
index 0650100fad001e1c337f7f9839e1dd82dc8945df..7d278b37e083d2bb4b8d5f0401593554e0e94a5b 100644 (file)
@@ -389,7 +389,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                if (wdt_set_heartbeat(new_heartbeat))
                        return -EINVAL;
                wdt_ping();
-               /* Fall */
+               /* Fall through */
        case WDIOC_GETTIMEOUT:
                return put_user(heartbeat, p);
        default:
index 567005d7598e244c70c3d923fb22e08ac61daff4..5c52c73e183993c6ce7713362bbcfd331e12d76a 100644 (file)
@@ -398,7 +398,7 @@ static long wdt977_ioctl(struct file *file, unsigned int cmd,
                        return -EINVAL;
 
                wdt977_keepalive();
-               /* Fall */
+               /* Fall through */
 
        case WDIOC_GETTIMEOUT:
                return put_user(timeout, uarg.i);
index 4f1b6f466ff510d2899ae6f225ff5e0234875f15..b86195e4dc6cd657485eb01f62d103b4e06f7008 100644 (file)
@@ -505,18 +505,14 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
        struct afs_call *call = container_of(work, struct afs_call, work);
        struct afs_uuid *r = call->request;
 
-       struct {
-               __be32  match;
-       } reply;
-
        _enter("");
 
        if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
-               reply.match = htonl(0);
+               afs_send_empty_reply(call);
        else
-               reply.match = htonl(1);
+               rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
+                                       1, 1, "K-1");
 
-       afs_send_simple_reply(call, &reply, sizeof(reply));
        afs_put_call(call);
        _leave("");
 }
index e640d67274be2b06e64a83dd967670d72a1cbed4..81207dc3c9977892ece421851666eadf8e818321 100644 (file)
@@ -440,7 +440,7 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
  * iterate through the data blob that lists the contents of an AFS directory
  */
 static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
-                          struct key *key)
+                          struct key *key, afs_dataversion_t *_dir_version)
 {
        struct afs_vnode *dvnode = AFS_FS_I(dir);
        struct afs_xdr_dir_page *dbuf;
@@ -460,6 +460,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
        req = afs_read_dir(dvnode, key);
        if (IS_ERR(req))
                return PTR_ERR(req);
+       *_dir_version = req->data_version;
 
        /* round the file position up to the next entry boundary */
        ctx->pos += sizeof(union afs_xdr_dirent) - 1;
@@ -514,7 +515,10 @@ out:
  */
 static int afs_readdir(struct file *file, struct dir_context *ctx)
 {
-       return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file));
+       afs_dataversion_t dir_version;
+
+       return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
+                              &dir_version);
 }
 
 /*
@@ -555,7 +559,8 @@ static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
  * - just returns the FID the dentry name maps to if found
  */
 static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
-                            struct afs_fid *fid, struct key *key)
+                            struct afs_fid *fid, struct key *key,
+                            afs_dataversion_t *_dir_version)
 {
        struct afs_super_info *as = dir->i_sb->s_fs_info;
        struct afs_lookup_one_cookie cookie = {
@@ -568,7 +573,7 @@ static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
        _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
 
        /* search the directory */
-       ret = afs_dir_iterate(dir, &cookie.ctx, key);
+       ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
        if (ret < 0) {
                _leave(" = %d [iter]", ret);
                return ret;
@@ -642,6 +647,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
        struct afs_server *server;
        struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
        struct inode *inode = NULL, *ti;
+       afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
        int ret, i;
 
        _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
@@ -669,12 +675,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
                cookie->fids[i].vid = as->volume->vid;
 
        /* search the directory */
-       ret = afs_dir_iterate(dir, &cookie->ctx, key);
+       ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
        if (ret < 0) {
                inode = ERR_PTR(ret);
                goto out;
        }
 
+       dentry->d_fsdata = (void *)(unsigned long)data_version;
+
        inode = ERR_PTR(-ENOENT);
        if (!cookie->found)
                goto out;
@@ -968,7 +976,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        struct dentry *parent;
        struct inode *inode;
        struct key *key;
-       long dir_version, de_version;
+       afs_dataversion_t dir_version;
+       long de_version;
        int ret;
 
        if (flags & LOOKUP_RCU)
@@ -1014,20 +1023,20 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
         * on a 32-bit system, we only have 32 bits in the dentry to store the
         * version.
         */
-       dir_version = (long)dir->status.data_version;
+       dir_version = dir->status.data_version;
        de_version = (long)dentry->d_fsdata;
-       if (de_version == dir_version)
-               goto out_valid;
+       if (de_version == (long)dir_version)
+               goto out_valid_noupdate;
 
-       dir_version = (long)dir->invalid_before;
-       if (de_version - dir_version >= 0)
+       dir_version = dir->invalid_before;
+       if (de_version - (long)dir_version >= 0)
                goto out_valid;
 
        _debug("dir modified");
        afs_stat_v(dir, n_reval);
 
        /* search the directory for this vnode */
-       ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key);
+       ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
        switch (ret) {
        case 0:
                /* the filename maps to something */
@@ -1080,7 +1089,8 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        }
 
 out_valid:
-       dentry->d_fsdata = (void *)dir_version;
+       dentry->d_fsdata = (void *)(unsigned long)dir_version;
+out_valid_noupdate:
        dput(parent);
        key_put(key);
        _leave(" = 1 [valid]");
@@ -1185,6 +1195,20 @@ static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
        iget_data->cb_s_break = fc->cbi->server->cb_s_break;
 }
 
+/*
+ * Note that a dentry got changed.  We need to set d_fsdata to the data version
+ * number derived from the result of the operation.  It doesn't matter if
+ * d_fsdata goes backwards as we'll just revalidate.
+ */
+static void afs_update_dentry_version(struct afs_fs_cursor *fc,
+                                     struct dentry *dentry,
+                                     struct afs_status_cb *scb)
+{
+       if (fc->ac.error == 0)
+               dentry->d_fsdata =
+                       (void *)(unsigned long)scb->status.data_version;
+}
+
 /*
  * create a directory on an AFS filesystem
  */
@@ -1227,6 +1251,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
                afs_check_for_remote_deletion(&fc, dvnode);
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, &scb[0]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
@@ -1319,6 +1344,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
 
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, scb);
+               afs_update_dentry_version(&fc, dentry, scb);
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0) {
                        afs_dir_remove_subdir(dentry);
@@ -1458,6 +1484,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
                                        &data_version, &scb[0]);
                afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
                                        &data_version_2, &scb[1]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                ret = afs_end_vnode_operation(&fc);
                if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
                        ret = afs_dir_remove_link(dvnode, dentry, key);
@@ -1526,6 +1553,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                afs_check_for_remote_deletion(&fc, dvnode);
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, &scb[0]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
@@ -1607,6 +1635,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
                afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
                                        NULL, &scb[1]);
                ihold(&vnode->vfs_inode);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                d_instantiate(dentry, &vnode->vfs_inode);
 
                mutex_unlock(&vnode->io_lock);
@@ -1686,6 +1715,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
                afs_check_for_remote_deletion(&fc, dvnode);
                afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
                                        &data_version, &scb[0]);
+               afs_update_dentry_version(&fc, dentry, &scb[0]);
                afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
@@ -1791,6 +1821,17 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                }
        }
 
+       /* This bit is potentially nasty as there's a potential race with
+        * afs_d_revalidate{,_rcu}().  We have to change d_fsdata on the dentry
+        * to reflect it's new parent's new data_version after the op, but
+        * d_revalidate may see old_dentry between the op having taken place
+        * and the version being updated.
+        *
+        * So drop the old_dentry for now to make other threads go through
+        * lookup instead - which we hold a lock against.
+        */
+       d_drop(old_dentry);
+
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
                afs_dataversion_t orig_data_version;
@@ -1802,9 +1843,9 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (orig_dvnode != new_dvnode) {
                        if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
                                afs_end_vnode_operation(&fc);
-                               goto error_rehash;
+                               goto error_rehash_old;
                        }
-                       new_data_version = new_dvnode->status.data_version;
+                       new_data_version = new_dvnode->status.data_version + 1;
                } else {
                        new_data_version = orig_data_version;
                        new_scb = &scb[0];
@@ -1827,7 +1868,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                }
                ret = afs_end_vnode_operation(&fc);
                if (ret < 0)
-                       goto error_rehash;
+                       goto error_rehash_old;
        }
 
        if (ret == 0) {
@@ -1853,10 +1894,26 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                drop_nlink(new_inode);
                        spin_unlock(&new_inode->i_lock);
                }
+
+               /* Now we can update d_fsdata on the dentries to reflect their
+                * new parent's data_version.
+                *
+                * Note that if we ever implement RENAME_EXCHANGE, we'll have
+                * to update both dentries with opposing dir versions.
+                */
+               if (new_dvnode != orig_dvnode) {
+                       afs_update_dentry_version(&fc, old_dentry, &scb[1]);
+                       afs_update_dentry_version(&fc, new_dentry, &scb[1]);
+               } else {
+                       afs_update_dentry_version(&fc, old_dentry, &scb[0]);
+                       afs_update_dentry_version(&fc, new_dentry, &scb[0]);
+               }
                d_move(old_dentry, new_dentry);
                goto error_tmp;
        }
 
+error_rehash_old:
+       d_rehash(new_dentry);
 error_rehash:
        if (rehash)
                d_rehash(rehash);
index 56b69576274d5b64cae3be2192f01838f201507d..dd3c55c9101c4e8475eca6a66e789a5f991d845d 100644 (file)
@@ -191,11 +191,13 @@ void afs_put_read(struct afs_read *req)
        int i;
 
        if (refcount_dec_and_test(&req->usage)) {
-               for (i = 0; i < req->nr_pages; i++)
-                       if (req->pages[i])
-                               put_page(req->pages[i]);
-               if (req->pages != req->array)
-                       kfree(req->pages);
+               if (req->pages) {
+                       for (i = 0; i < req->nr_pages; i++)
+                               if (req->pages[i])
+                                       put_page(req->pages[i]);
+                       if (req->pages != req->array)
+                               kfree(req->pages);
+               }
                kfree(req);
        }
 }
index d7e0fd3c00df9e8ee52b97d272ffc6ae71effa8c..cfb0ac4bd039e672c14110ce8ad4eccb16706103 100644 (file)
@@ -56,23 +56,24 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call)
                struct afs_uuid__xdr *xdr;
                struct afs_uuid *uuid;
                int j;
+               int n = entry->nr_servers;
 
                tmp = ntohl(uvldb->serverFlags[i]);
                if (tmp & AFS_VLSF_DONTUSE ||
                    (new_only && !(tmp & AFS_VLSF_NEWREPSITE)))
                        continue;
                if (tmp & AFS_VLSF_RWVOL) {
-                       entry->fs_mask[i] |= AFS_VOL_VTM_RW;
+                       entry->fs_mask[n] |= AFS_VOL_VTM_RW;
                        if (vlflags & AFS_VLF_BACKEXISTS)
-                               entry->fs_mask[i] |= AFS_VOL_VTM_BAK;
+                               entry->fs_mask[n] |= AFS_VOL_VTM_BAK;
                }
                if (tmp & AFS_VLSF_ROVOL)
-                       entry->fs_mask[i] |= AFS_VOL_VTM_RO;
-               if (!entry->fs_mask[i])
+                       entry->fs_mask[n] |= AFS_VOL_VTM_RO;
+               if (!entry->fs_mask[n])
                        continue;
 
                xdr = &uvldb->serverNumber[i];
-               uuid = (struct afs_uuid *)&entry->fs_server[i];
+               uuid = (struct afs_uuid *)&entry->fs_server[n];
                uuid->time_low                  = xdr->time_low;
                uuid->time_mid                  = htons(ntohl(xdr->time_mid));
                uuid->time_hi_and_version       = htons(ntohl(xdr->time_hi_and_version));
index a6f7c892cb4a390f9d6357263cfc17fa8c2db9aa..677cb364d33f0e43e65d25349fdcdce651a6ca5e 100644 (file)
@@ -345,24 +345,15 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        struct bio *bio;
        bool is_poll = (iocb->ki_flags & IOCB_HIPRI) != 0;
        bool is_read = (iov_iter_rw(iter) == READ), is_sync;
-       bool nowait = (iocb->ki_flags & IOCB_NOWAIT) != 0;
        loff_t pos = iocb->ki_pos;
        blk_qc_t qc = BLK_QC_T_NONE;
-       gfp_t gfp;
-       ssize_t ret;
+       int ret = 0;
 
        if ((pos | iov_iter_alignment(iter)) &
            (bdev_logical_block_size(bdev) - 1))
                return -EINVAL;
 
-       if (nowait)
-               gfp = GFP_NOWAIT;
-       else
-               gfp = GFP_KERNEL;
-
-       bio = bio_alloc_bioset(gfp, nr_pages, &blkdev_dio_pool);
-       if (!bio)
-               return -EAGAIN;
+       bio = bio_alloc_bioset(GFP_KERNEL, nr_pages, &blkdev_dio_pool);
 
        dio = container_of(bio, struct blkdev_dio, bio);
        dio->is_sync = is_sync = is_sync_kiocb(iocb);
@@ -384,10 +375,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        if (!is_poll)
                blk_start_plug(&plug);
 
-       ret = 0;
        for (;;) {
-               int err;
-
                bio_set_dev(bio, bdev);
                bio->bi_iter.bi_sector = pos >> 9;
                bio->bi_write_hint = iocb->ki_hint;
@@ -395,10 +383,8 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                bio->bi_end_io = blkdev_bio_end_io;
                bio->bi_ioprio = iocb->ki_ioprio;
 
-               err = bio_iov_iter_get_pages(bio, iter);
-               if (unlikely(err)) {
-                       if (!ret)
-                               ret = err;
+               ret = bio_iov_iter_get_pages(bio, iter);
+               if (unlikely(ret)) {
                        bio->bi_status = BLK_STS_IOERR;
                        bio_endio(bio);
                        break;
@@ -413,14 +399,6 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                        task_io_account_write(bio->bi_iter.bi_size);
                }
 
-               /*
-                * Tell underlying layer to not block for resource shortage.
-                * And if we would have blocked, return error inline instead
-                * of through the bio->bi_end_io() callback.
-                */
-               if (nowait)
-                       bio->bi_opf |= (REQ_NOWAIT | REQ_NOWAIT_INLINE);
-
                dio->size += bio->bi_iter.bi_size;
                pos += bio->bi_iter.bi_size;
 
@@ -434,12 +412,6 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                        }
 
                        qc = submit_bio(bio);
-                       if (qc == BLK_QC_T_EAGAIN) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               goto error;
-                       }
-                       ret = dio->size;
 
                        if (polled)
                                WRITE_ONCE(iocb->ki_cookie, qc);
@@ -460,20 +432,8 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                        atomic_inc(&dio->ref);
                }
 
-               qc = submit_bio(bio);
-               if (qc == BLK_QC_T_EAGAIN) {
-                       if (!ret)
-                               ret = -EAGAIN;
-                       goto error;
-               }
-               ret = dio->size;
-
-               bio = bio_alloc(gfp, nr_pages);
-               if (!bio) {
-                       if (!ret)
-                               ret = -EAGAIN;
-                       goto error;
-               }
+               submit_bio(bio);
+               bio = bio_alloc(GFP_KERNEL, nr_pages);
        }
 
        if (!is_poll)
@@ -493,16 +453,13 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        }
        __set_current_state(TASK_RUNNING);
 
-out:
        if (!ret)
                ret = blk_status_to_errno(dio->bio.bi_status);
+       if (likely(!ret))
+               ret = dio->size;
 
        bio_put(&dio->bio);
        return ret;
-error:
-       if (!is_poll)
-               blk_finish_plug(&plug);
-       goto out;
 }
 
 static ssize_t
@@ -1754,7 +1711,10 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
 
                /* finish claiming */
                mutex_lock(&bdev->bd_mutex);
-               bd_finish_claiming(bdev, whole, holder);
+               if (!res)
+                       bd_finish_claiming(bdev, whole, holder);
+               else
+                       bd_abort_claiming(bdev, whole, holder);
                /*
                 * Block event polling for write claims if requested.  Any
                 * write holder makes the write_holder state stick until
index 299e11e6c554c00034df2e3941543434f00d911b..94660063a1628989108b5e15c5b1682e616b2dd3 100644 (file)
@@ -401,7 +401,6 @@ struct btrfs_dev_replace {
 struct raid_kobject {
        u64 flags;
        struct kobject kobj;
-       struct list_head list;
 };
 
 /*
@@ -915,8 +914,6 @@ struct btrfs_fs_info {
        u32 thread_pool_size;
 
        struct kobject *space_info_kobj;
-       struct list_head pending_raid_kobjs;
-       spinlock_t pending_raid_kobjs_lock; /* uncontended */
 
        u64 total_pinned;
 
@@ -2698,7 +2695,6 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr);
 int btrfs_make_block_group(struct btrfs_trans_handle *trans,
                           u64 bytes_used, u64 type, u64 chunk_offset,
                           u64 size);
-void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info);
 struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
                                struct btrfs_fs_info *fs_info,
                                const u64 chunk_offset);
index 5f7ee70b3d1a0fd26f620901b62d1d12b468ec3a..97beb351a10cdc0117bc41b5dade4d01eb916093 100644 (file)
@@ -2683,8 +2683,6 @@ int open_ctree(struct super_block *sb,
        INIT_LIST_HEAD(&fs_info->delayed_iputs);
        INIT_LIST_HEAD(&fs_info->delalloc_roots);
        INIT_LIST_HEAD(&fs_info->caching_block_groups);
-       INIT_LIST_HEAD(&fs_info->pending_raid_kobjs);
-       spin_lock_init(&fs_info->pending_raid_kobjs_lock);
        spin_lock_init(&fs_info->delalloc_root_lock);
        spin_lock_init(&fs_info->trans_lock);
        spin_lock_init(&fs_info->fs_roots_radix_lock);
index d3b58e388535e704d7f0c4c961c2f068f19d1856..8b7eb22d508a597b3bcc97f018c096f6d251e715 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/sched/signal.h>
 #include <linux/pagemap.h>
 #include <linux/writeback.h>
@@ -7888,33 +7889,6 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
        return 0;
 }
 
-/* link_block_group will queue up kobjects to add when we're reclaim-safe */
-void btrfs_add_raid_kobjects(struct btrfs_fs_info *fs_info)
-{
-       struct btrfs_space_info *space_info;
-       struct raid_kobject *rkobj;
-       LIST_HEAD(list);
-       int ret = 0;
-
-       spin_lock(&fs_info->pending_raid_kobjs_lock);
-       list_splice_init(&fs_info->pending_raid_kobjs, &list);
-       spin_unlock(&fs_info->pending_raid_kobjs_lock);
-
-       list_for_each_entry(rkobj, &list, list) {
-               space_info = btrfs_find_space_info(fs_info, rkobj->flags);
-
-               ret = kobject_add(&rkobj->kobj, &space_info->kobj,
-                               "%s", btrfs_bg_type_to_raid_name(rkobj->flags));
-               if (ret) {
-                       kobject_put(&rkobj->kobj);
-                       break;
-               }
-       }
-       if (ret)
-               btrfs_warn(fs_info,
-                          "failed to add kobject for block cache, ignoring");
-}
-
 static void link_block_group(struct btrfs_block_group_cache *cache)
 {
        struct btrfs_space_info *space_info = cache->space_info;
@@ -7929,18 +7903,36 @@ static void link_block_group(struct btrfs_block_group_cache *cache)
        up_write(&space_info->groups_sem);
 
        if (first) {
-               struct raid_kobject *rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS);
+               struct raid_kobject *rkobj;
+               unsigned int nofs_flag;
+               int ret;
+
+               /*
+                * Setup a NOFS context because kobject_add(), deep in its call
+                * chain, does GFP_KERNEL allocations, and we are often called
+                * in a context where if reclaim is triggered we can deadlock
+                * (we are either holding a transaction handle or some lock
+                * required for a transaction commit).
+                */
+               nofs_flag = memalloc_nofs_save();
+               rkobj = kzalloc(sizeof(*rkobj), GFP_KERNEL);
                if (!rkobj) {
+                       memalloc_nofs_restore(nofs_flag);
                        btrfs_warn(cache->fs_info,
                                "couldn't alloc memory for raid level kobject");
                        return;
                }
                rkobj->flags = cache->flags;
                kobject_init(&rkobj->kobj, &btrfs_raid_ktype);
-
-               spin_lock(&fs_info->pending_raid_kobjs_lock);
-               list_add_tail(&rkobj->list, &fs_info->pending_raid_kobjs);
-               spin_unlock(&fs_info->pending_raid_kobjs_lock);
+               ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s",
+                                 btrfs_bg_type_to_raid_name(rkobj->flags));
+               memalloc_nofs_restore(nofs_flag);
+               if (ret) {
+                       kobject_put(&rkobj->kobj);
+                       btrfs_warn(fs_info,
+                          "failed to add kobject for block cache, ignoring");
+                       return;
+               }
                space_info->block_group_kobjs[index] = &rkobj->kobj;
        }
 }
@@ -8206,7 +8198,6 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                        inc_block_group_ro(cache, 1);
        }
 
-       btrfs_add_raid_kobjects(info);
        btrfs_init_global_block_rsv(info);
        ret = check_chunk_block_group_mappings(info);
 error:
@@ -8975,6 +8966,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
        struct btrfs_device *device;
        struct list_head *devices;
        u64 group_trimmed;
+       u64 range_end = U64_MAX;
        u64 start;
        u64 end;
        u64 trimmed = 0;
@@ -8984,16 +8976,23 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
        int dev_ret = 0;
        int ret = 0;
 
+       /*
+        * Check range overflow if range->len is set.
+        * The default range->len is U64_MAX.
+        */
+       if (range->len != U64_MAX &&
+           check_add_overflow(range->start, range->len, &range_end))
+               return -EINVAL;
+
        cache = btrfs_lookup_first_block_group(fs_info, range->start);
        for (; cache; cache = next_block_group(cache)) {
-               if (cache->key.objectid >= (range->start + range->len)) {
+               if (cache->key.objectid >= range_end) {
                        btrfs_put_block_group(cache);
                        break;
                }
 
                start = max(range->start, cache->key.objectid);
-               end = min(range->start + range->len,
-                               cache->key.objectid + cache->key.offset);
+               end = min(range_end, cache->key.objectid + cache->key.offset);
 
                if (end - start >= range->minlen) {
                        if (!block_group_cache_done(cache)) {
index d74b74ca07afd00d9302954408a8b87b04c0b09f..a447d3ec48d506b848e1ab228fc0ce55fb0f87c7 100644 (file)
@@ -3087,16 +3087,6 @@ static int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
        if (ret)
                return ret;
 
-       /*
-        * We add the kobjects here (and after forcing data chunk creation)
-        * since relocation is the only place we'll create chunks of a new
-        * type at runtime.  The only place where we'll remove the last
-        * chunk of a type is the call immediately below this one.  Even
-        * so, we're protected against races with the cleaner thread since
-        * we're covered by the delete_unused_bgs_mutex.
-        */
-       btrfs_add_raid_kobjects(fs_info);
-
        trans = btrfs_start_trans_remove_block_group(root->fs_info,
                                                     chunk_offset);
        if (IS_ERR(trans)) {
@@ -3223,9 +3213,6 @@ static int btrfs_may_alloc_data_chunk(struct btrfs_fs_info *fs_info,
                        btrfs_end_transaction(trans);
                        if (ret < 0)
                                return ret;
-
-                       btrfs_add_raid_kobjects(fs_info);
-
                        return 1;
                }
        }
index a4830ced0f9899c35c89609b2ea25330a06693bd..1795e80cbdf7b246c12f4bbdf758b14a1999d96a 100644 (file)
@@ -1113,6 +1113,7 @@ cifs_demultiplex_thread(void *p)
                mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
 
        set_freezable();
+       allow_kernel_signal(SIGKILL);
        while (server->tcpStatus != CifsExiting) {
                if (try_to_freeze())
                        continue;
index a5bc1b671c126579a7161853ad0ef352e01f8c39..64a5864127be9154fead53d4188a15d3f7ddaf17 100644 (file)
@@ -3489,7 +3489,15 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
 static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
                                   unsigned int buflen)
 {
-       sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
+       void *addr;
+       /*
+        * VMAP_STACK (at least) puts stack into the vmalloc address space
+        */
+       if (is_vmalloc_addr(buf))
+               addr = vmalloc_to_page(buf);
+       else
+               addr = virt_to_page(buf);
+       sg_set_page(sg, addr, buflen, offset_in_page(buf));
 }
 
 /* Assumes the first rqst has a transform header as the first iov.
@@ -4070,7 +4078,6 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
 {
        int ret, length;
        char *buf = server->smallbuf;
-       char *tmpbuf;
        struct smb2_sync_hdr *shdr;
        unsigned int pdu_length = server->pdu_size;
        unsigned int buf_size;
@@ -4100,18 +4107,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
                return length;
 
        next_is_large = server->large_buf;
- one_more:
+one_more:
        shdr = (struct smb2_sync_hdr *)buf;
        if (shdr->NextCommand) {
-               if (next_is_large) {
-                       tmpbuf = server->bigbuf;
+               if (next_is_large)
                        next_buffer = (char *)cifs_buf_get();
-               } else {
-                       tmpbuf = server->smallbuf;
+               else
                        next_buffer = (char *)cifs_small_buf_get();
-               }
                memcpy(next_buffer,
-                      tmpbuf + le32_to_cpu(shdr->NextCommand),
+                      buf + le32_to_cpu(shdr->NextCommand),
                       pdu_length - le32_to_cpu(shdr->NextCommand));
        }
 
@@ -4140,12 +4144,21 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
                pdu_length -= le32_to_cpu(shdr->NextCommand);
                server->large_buf = next_is_large;
                if (next_is_large)
-                       server->bigbuf = next_buffer;
+                       server->bigbuf = buf = next_buffer;
                else
-                       server->smallbuf = next_buffer;
-
-               buf += le32_to_cpu(shdr->NextCommand);
+                       server->smallbuf = buf = next_buffer;
                goto one_more;
+       } else if (ret != 0) {
+               /*
+                * ret != 0 here means that we didn't get to handle_mid() thus
+                * server->smallbuf and server->bigbuf are still valid. We need
+                * to free next_buffer because it is not going to be used
+                * anywhere.
+                */
+               if (next_is_large)
+                       free_rsp_buf(CIFS_LARGE_BUFFER, next_buffer);
+               else
+                       free_rsp_buf(CIFS_SMALL_BUFFER, next_buffer);
        }
 
        return ret;
index c8cd7b6cdda2a5c93b0c6a5cf374d6b29291726e..31e4a1b0b1704b90e9ed8f0cdb123477933fb369 100644 (file)
@@ -252,7 +252,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
        if (tcon == NULL)
                return 0;
 
-       if (smb2_command == SMB2_TREE_CONNECT)
+       if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
                return 0;
 
        if (tcon->tidStatus == CifsExiting) {
@@ -1196,7 +1196,12 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
        else
                req->SecurityMode = 0;
 
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
+#else
        req->Capabilities = 0;
+#endif /* DFS_UPCALL */
+
        req->Channel = 0; /* MBZ */
 
        sess_data->iov[0].iov_base = (char *)req;
index 6e30949d9f7794a584c1503fe8dbf7a51d0e83b7..a7ec2d3dff9282bf6e8fbc2c29e2f8e0301efb39 100644 (file)
@@ -638,9 +638,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN)
 COMPATIBLE_IOCTL(PPPIOCATTCHAN)
 COMPATIBLE_IOCTL(PPPIOCGCHAN)
 COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
-/* PPPOX */
-COMPATIBLE_IOCTL(PPPOEIOCSFWD)
-COMPATIBLE_IOCTL(PPPOEIOCDFWD)
 /* Big A */
 /* sparc only */
 /* Big Q for sound/OSS */
index b64964ef44f62b8ad3a261396d16809d2667e274..6bf81f931de39e48bc2983a1c901b1a6643443f8 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -600,7 +600,7 @@ struct page *dax_layout_busy_page(struct address_space *mapping)
         * guaranteed to either see new references or prevent new
         * references from being established.
         */
-       unmap_mapping_range(mapping, 0, 0, 1);
+       unmap_mapping_range(mapping, 0, 0, 0);
 
        xas_lock_irq(&xas);
        xas_for_each(&xas, entry, ULONG_MAX) {
index 4df26ef2b2b15689bcfa058b8997bc0da3f99a67..4f8b5fd6c81fdeafccff2ffbf4409ada329b7d00 100644 (file)
@@ -390,6 +390,19 @@ static int fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, int h)
        return mp->mp_aheight - x - 1;
 }
 
+static sector_t metapath_to_block(struct gfs2_sbd *sdp, struct metapath *mp)
+{
+       sector_t factor = 1, block = 0;
+       int hgt;
+
+       for (hgt = mp->mp_fheight - 1; hgt >= 0; hgt--) {
+               if (hgt < mp->mp_aheight)
+                       block += mp->mp_list[hgt] * factor;
+               factor *= sdp->sd_inptrs;
+       }
+       return block;
+}
+
 static void release_metapath(struct metapath *mp)
 {
        int i;
@@ -430,60 +443,84 @@ static inline unsigned int gfs2_extent_length(struct buffer_head *bh, __be64 *pt
        return ptr - first;
 }
 
-typedef const __be64 *(*gfs2_metadata_walker)(
-               struct metapath *mp,
-               const __be64 *start, const __be64 *end,
-               u64 factor, void *data);
+enum walker_status { WALK_STOP, WALK_FOLLOW, WALK_CONTINUE };
 
-#define WALK_STOP ((__be64 *)0)
-#define WALK_NEXT ((__be64 *)1)
+/*
+ * gfs2_metadata_walker - walk an indirect block
+ * @mp: Metapath to indirect block
+ * @ptrs: Number of pointers to look at
+ *
+ * When returning WALK_FOLLOW, the walker must update @mp to point at the right
+ * indirect block to follow.
+ */
+typedef enum walker_status (*gfs2_metadata_walker)(struct metapath *mp,
+                                                  unsigned int ptrs);
 
-static int gfs2_walk_metadata(struct inode *inode, sector_t lblock,
-               u64 len, struct metapath *mp, gfs2_metadata_walker walker,
-               void *data)
+/*
+ * gfs2_walk_metadata - walk a tree of indirect blocks
+ * @inode: The inode
+ * @mp: Starting point of walk
+ * @max_len: Maximum number of blocks to walk
+ * @walker: Called during the walk
+ *
+ * Returns 1 if the walk was stopped by @walker, 0 if we went past @max_len or
+ * past the end of metadata, and a negative error code otherwise.
+ */
+
+static int gfs2_walk_metadata(struct inode *inode, struct metapath *mp,
+               u64 max_len, gfs2_metadata_walker walker)
 {
-       struct metapath clone;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
-       const __be64 *start, *end, *ptr;
        u64 factor = 1;
        unsigned int hgt;
-       int ret = 0;
+       int ret;
 
-       for (hgt = ip->i_height - 1; hgt >= mp->mp_aheight; hgt--)
+       /*
+        * The walk starts in the lowest allocated indirect block, which may be
+        * before the position indicated by @mp.  Adjust @max_len accordingly
+        * to avoid a short walk.
+        */
+       for (hgt = mp->mp_fheight - 1; hgt >= mp->mp_aheight; hgt--) {
+               max_len += mp->mp_list[hgt] * factor;
+               mp->mp_list[hgt] = 0;
                factor *= sdp->sd_inptrs;
+       }
 
        for (;;) {
-               u64 step;
+               u16 start = mp->mp_list[hgt];
+               enum walker_status status;
+               unsigned int ptrs;
+               u64 len;
 
                /* Walk indirect block. */
-               start = metapointer(hgt, mp);
-               end = metaend(hgt, mp);
-
-               step = (end - start) * factor;
-               if (step > len)
-                       end = start + DIV_ROUND_UP_ULL(len, factor);
-
-               ptr = walker(mp, start, end, factor, data);
-               if (ptr == WALK_STOP)
+               ptrs = (hgt >= 1 ? sdp->sd_inptrs : sdp->sd_diptrs) - start;
+               len = ptrs * factor;
+               if (len > max_len)
+                       ptrs = DIV_ROUND_UP_ULL(max_len, factor);
+               status = walker(mp, ptrs);
+               switch (status) {
+               case WALK_STOP:
+                       return 1;
+               case WALK_FOLLOW:
+                       BUG_ON(mp->mp_aheight == mp->mp_fheight);
+                       ptrs = mp->mp_list[hgt] - start;
+                       len = ptrs * factor;
                        break;
-               if (step >= len)
+               case WALK_CONTINUE:
                        break;
-               len -= step;
-               if (ptr != WALK_NEXT) {
-                       BUG_ON(!*ptr);
-                       mp->mp_list[hgt] += ptr - start;
-                       goto fill_up_metapath;
                }
+               if (len >= max_len)
+                       break;
+               max_len -= len;
+               if (status == WALK_FOLLOW)
+                       goto fill_up_metapath;
 
 lower_metapath:
                /* Decrease height of metapath. */
-               if (mp != &clone) {
-                       clone_metapath(&clone, mp);
-                       mp = &clone;
-               }
                brelse(mp->mp_bh[hgt]);
                mp->mp_bh[hgt] = NULL;
+               mp->mp_list[hgt] = 0;
                if (!hgt)
                        break;
                hgt--;
@@ -491,10 +528,7 @@ lower_metapath:
 
                /* Advance in metadata tree. */
                (mp->mp_list[hgt])++;
-               start = metapointer(hgt, mp);
-               end = metaend(hgt, mp);
-               if (start >= end) {
-                       mp->mp_list[hgt] = 0;
+               if (mp->mp_list[hgt] >= sdp->sd_inptrs) {
                        if (!hgt)
                                break;
                        goto lower_metapath;
@@ -502,44 +536,36 @@ lower_metapath:
 
 fill_up_metapath:
                /* Increase height of metapath. */
-               if (mp != &clone) {
-                       clone_metapath(&clone, mp);
-                       mp = &clone;
-               }
                ret = fillup_metapath(ip, mp, ip->i_height - 1);
                if (ret < 0)
-                       break;
+                       return ret;
                hgt += ret;
                for (; ret; ret--)
                        do_div(factor, sdp->sd_inptrs);
                mp->mp_aheight = hgt + 1;
        }
-       if (mp == &clone)
-               release_metapath(mp);
-       return ret;
+       return 0;
 }
 
-struct gfs2_hole_walker_args {
-       u64 blocks;
-};
-
-static const __be64 *gfs2_hole_walker(struct metapath *mp,
-               const __be64 *start, const __be64 *end,
-               u64 factor, void *data)
+static enum walker_status gfs2_hole_walker(struct metapath *mp,
+                                          unsigned int ptrs)
 {
-       struct gfs2_hole_walker_args *args = data;
-       const __be64 *ptr;
+       const __be64 *start, *ptr, *end;
+       unsigned int hgt;
+
+       hgt = mp->mp_aheight - 1;
+       start = metapointer(hgt, mp);
+       end = start + ptrs;
 
        for (ptr = start; ptr < end; ptr++) {
                if (*ptr) {
-                       args->blocks += (ptr - start) * factor;
+                       mp->mp_list[hgt] += ptr - start;
                        if (mp->mp_aheight == mp->mp_fheight)
                                return WALK_STOP;
-                       return ptr;  /* increase height */
+                       return WALK_FOLLOW;
                }
        }
-       args->blocks += (end - start) * factor;
-       return WALK_NEXT;
+       return WALK_CONTINUE;
 }
 
 /**
@@ -557,12 +583,24 @@ static const __be64 *gfs2_hole_walker(struct metapath *mp,
 static int gfs2_hole_size(struct inode *inode, sector_t lblock, u64 len,
                          struct metapath *mp, struct iomap *iomap)
 {
-       struct gfs2_hole_walker_args args = { };
-       int ret = 0;
+       struct metapath clone;
+       u64 hole_size;
+       int ret;
 
-       ret = gfs2_walk_metadata(inode, lblock, len, mp, gfs2_hole_walker, &args);
-       if (!ret)
-               iomap->length = args.blocks << inode->i_blkbits;
+       clone_metapath(&clone, mp);
+       ret = gfs2_walk_metadata(inode, &clone, len, gfs2_hole_walker);
+       if (ret < 0)
+               goto out;
+
+       if (ret == 1)
+               hole_size = metapath_to_block(GFS2_SB(inode), &clone) - lblock;
+       else
+               hole_size = len;
+       iomap->length = hole_size << inode->i_blkbits;
+       ret = 0;
+
+out:
+       release_metapath(&clone);
        return ret;
 }
 
index d542f1cf4428ed79af62c76273d32885490f72ff..24bbe3cb7ad45e72b1cfca18c3084795d0be6a8c 100644 (file)
@@ -1097,10 +1097,8 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw,
 
                        iter->bvec = bvec + seg_skip;
                        iter->nr_segs -= seg_skip;
-                       iter->count -= (seg_skip << PAGE_SHIFT);
+                       iter->count -= bvec->bv_len + offset;
                        iter->iov_offset = offset & ~PAGE_MASK;
-                       if (iter->iov_offset)
-                               iter->count -= iter->iov_offset;
                }
        }
 
@@ -2025,6 +2023,15 @@ static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
 {
        int ret;
 
+       ret = io_req_defer(ctx, req, s->sqe);
+       if (ret) {
+               if (ret != -EIOCBQUEUED) {
+                       io_free_req(req);
+                       io_cqring_add_event(ctx, s->sqe->user_data, ret);
+               }
+               return 0;
+       }
+
        ret = __io_submit_sqe(ctx, req, s, true);
        if (ret == -EAGAIN && !(req->flags & REQ_F_NOWAIT)) {
                struct io_uring_sqe *sqe_copy;
@@ -2097,13 +2104,6 @@ err:
                return;
        }
 
-       ret = io_req_defer(ctx, req, s->sqe);
-       if (ret) {
-               if (ret != -EIOCBQUEUED)
-                       goto err_req;
-               return;
-       }
-
        /*
         * If we already have a head request, queue this one for async
         * submittal once the head completes. If we don't have a head but
index 0ff3facf81dac61fe99c6eff078e0a23b000d2e4..071b90a45933a4b95c176e8042a29130e07a71f1 100644 (file)
@@ -153,7 +153,7 @@ again:
                /* Block nfs4_proc_unlck */
                mutex_lock(&sp->so_delegreturn_mutex);
                seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
-               err = nfs4_open_delegation_recall(ctx, state, stateid, type);
+               err = nfs4_open_delegation_recall(ctx, state, stateid);
                if (!err)
                        err = nfs_delegation_claim_locks(state, stateid);
                if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -1046,6 +1046,22 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
        nfs4_schedule_state_manager(clp);
 }
 
+static void
+nfs_delegation_test_free_expired(struct inode *inode,
+               nfs4_stateid *stateid,
+               const struct cred *cred)
+{
+       struct nfs_server *server = NFS_SERVER(inode);
+       const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;
+       int status;
+
+       if (!cred)
+               return;
+       status = ops->test_and_free_expired(server, stateid, cred);
+       if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
+               nfs_remove_bad_delegation(inode, stateid);
+}
+
 /**
  * nfs_reap_expired_delegations - reap expired delegations
  * @clp: nfs_client to process
@@ -1057,7 +1073,6 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp)
  */
 void nfs_reap_expired_delegations(struct nfs_client *clp)
 {
-       const struct nfs4_minor_version_ops *ops = clp->cl_mvops;
        struct nfs_delegation *delegation;
        struct nfs_server *server;
        struct inode *inode;
@@ -1088,11 +1103,7 @@ restart:
                        nfs4_stateid_copy(&stateid, &delegation->stateid);
                        clear_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
                        rcu_read_unlock();
-                       if (cred != NULL &&
-                           ops->test_and_free_expired(server, &stateid, cred) < 0) {
-                               nfs_revoke_delegation(inode, &stateid);
-                               nfs_inode_find_state_and_recover(inode, &stateid);
-                       }
+                       nfs_delegation_test_free_expired(inode, &stateid, cred);
                        put_cred(cred);
                        if (nfs4_server_rebooted(clp)) {
                                nfs_inode_mark_test_expired_delegation(server,inode);
index 5799777df5ec860d8eaee84d2ca495b31ea31d09..9eb87ae4c98276632ab799e5b66487df9cdcd3e4 100644 (file)
@@ -63,7 +63,7 @@ void nfs_reap_expired_delegations(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync);
-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
 bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
 bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
index 53507aa96b0b63df96dc504abd7dc952c50d00d8..3800ab6f08fa8f91465f6a881a89098cd413eafa 100644 (file)
@@ -114,6 +114,10 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
        struct rb_node **p, *parent;
        int diff;
 
+       nfss->fscache_key = NULL;
+       nfss->fscache = NULL;
+       if (!(nfss->options & NFS_OPTION_FSCACHE))
+               return;
        if (!uniq) {
                uniq = "";
                ulen = 1;
@@ -226,10 +230,11 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
 void nfs_fscache_init_inode(struct inode *inode)
 {
        struct nfs_fscache_inode_auxdata auxdata;
+       struct nfs_server *nfss = NFS_SERVER(inode);
        struct nfs_inode *nfsi = NFS_I(inode);
 
        nfsi->fscache = NULL;
-       if (!S_ISREG(inode->i_mode))
+       if (!(nfss->fscache && S_ISREG(inode->i_mode)))
                return;
 
        memset(&auxdata, 0, sizeof(auxdata));
index 25a75e40d91d983f1ce7124ccef80d8ddff9050d..ad041cfbf9ec0fe616441dc653225c30f0983ca8 100644 (file)
@@ -182,7 +182,7 @@ static inline void nfs_fscache_wait_on_invalidate(struct inode *inode)
  */
 static inline const char *nfs_server_fscache_state(struct nfs_server *server)
 {
-       if (server->fscache && (server->options & NFS_OPTION_FSCACHE))
+       if (server->fscache)
                return "yes";
        return "no ";
 }
index d778dad9a75eb1263f05e241026a2b8216241c0a..3564da1ba8a1c78d82463628c3084e0586441be9 100644 (file)
@@ -465,7 +465,8 @@ static inline void nfs4_schedule_session_recovery(struct nfs4_session *session,
 
 extern struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *, const struct cred *, gfp_t);
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
-extern void nfs4_purge_state_owners(struct nfs_server *);
+extern void nfs4_purge_state_owners(struct nfs_server *, struct list_head *);
+extern void nfs4_free_state_owners(struct list_head *head);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct nfs4_state *, fmode_t);
index 616393a01c062ba99c79dd202166ef63691ece19..da6204025a2db09987791599b0bdbdcd0fc9953f 100644 (file)
@@ -758,9 +758,12 @@ out:
 
 static void nfs4_destroy_server(struct nfs_server *server)
 {
+       LIST_HEAD(freeme);
+
        nfs_server_return_all_delegations(server);
        unset_pnfs_layoutdriver(server);
-       nfs4_purge_state_owners(server);
+       nfs4_purge_state_owners(server, &freeme);
+       nfs4_free_state_owners(&freeme);
 }
 
 /*
index 39896afc6edf548aad9fb21cbcfce8b377074b7d..1406858bae6c95187c1190d3bb3b64bc5f317c58 100644 (file)
@@ -1683,6 +1683,14 @@ static void nfs_state_set_open_stateid(struct nfs4_state *state,
        write_sequnlock(&state->seqlock);
 }
 
+static void nfs_state_clear_open_state_flags(struct nfs4_state *state)
+{
+       clear_bit(NFS_O_RDWR_STATE, &state->flags);
+       clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+       clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+       clear_bit(NFS_OPEN_STATE, &state->flags);
+}
+
 static void nfs_state_set_delegation(struct nfs4_state *state,
                const nfs4_stateid *deleg_stateid,
                fmode_t fmode)
@@ -1907,8 +1915,9 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
        if (data->o_res.delegation_type != 0)
                nfs4_opendata_check_deleg(data, state);
 update:
-       update_open_stateid(state, &data->o_res.stateid, NULL,
-                           data->o_arg.fmode);
+       if (!update_open_stateid(state, &data->o_res.stateid,
+                               NULL, data->o_arg.fmode))
+               return ERR_PTR(-EAGAIN);
        refcount_inc(&state->count);
 
        return state;
@@ -1973,8 +1982,11 @@ _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
 
        if (data->o_res.delegation_type != 0)
                nfs4_opendata_check_deleg(data, state);
-       update_open_stateid(state, &data->o_res.stateid, NULL,
-                       data->o_arg.fmode);
+       if (!update_open_stateid(state, &data->o_res.stateid,
+                               NULL, data->o_arg.fmode)) {
+               nfs4_put_open_state(state);
+               state = ERR_PTR(-EAGAIN);
+       }
 out:
        nfs_release_seqid(data->o_arg.seqid);
        return state;
@@ -2074,13 +2086,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
 {
        int ret;
 
-       /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
-       clear_bit(NFS_O_RDWR_STATE, &state->flags);
-       clear_bit(NFS_O_WRONLY_STATE, &state->flags);
-       clear_bit(NFS_O_RDONLY_STATE, &state->flags);
        /* memory barrier prior to reading state->n_* */
-       clear_bit(NFS_DELEGATED_STATE, &state->flags);
-       clear_bit(NFS_OPEN_STATE, &state->flags);
        smp_rmb();
        ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
        if (ret != 0)
@@ -2156,6 +2162,8 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
        ctx = nfs4_state_find_open_context(state);
        if (IS_ERR(ctx))
                return -EAGAIN;
+       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+       nfs_state_clear_open_state_flags(state);
        ret = nfs4_do_open_reclaim(ctx, state);
        put_nfs_open_context(ctx);
        return ret;
@@ -2171,18 +2179,17 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
                case -ENOENT:
                case -EAGAIN:
                case -ESTALE:
+               case -ETIMEDOUT:
                        break;
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
                case -NFS4ERR_BAD_HIGH_SLOT:
                case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                case -NFS4ERR_DEADSESSION:
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
                        nfs4_schedule_session_recovery(server->nfs_client->cl_session, err);
                        return -EAGAIN;
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_STALE_STATEID:
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
                        /* Don't recall a delegation if it was lost */
                        nfs4_schedule_lease_recovery(server->nfs_client);
                        return -EAGAIN;
@@ -2203,7 +2210,6 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
                        return -EAGAIN;
                case -NFS4ERR_DELAY:
                case -NFS4ERR_GRACE:
-                       set_bit(NFS_DELEGATED_STATE, &state->flags);
                        ssleep(1);
                        return -EAGAIN;
                case -ENOMEM:
@@ -2219,8 +2225,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
 }
 
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
-               struct nfs4_state *state, const nfs4_stateid *stateid,
-               fmode_t type)
+               struct nfs4_state *state, const nfs4_stateid *stateid)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_opendata *opendata;
@@ -2231,20 +2236,23 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
        if (IS_ERR(opendata))
                return PTR_ERR(opendata);
        nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
-       nfs_state_clear_delegation(state);
-       switch (type & (FMODE_READ|FMODE_WRITE)) {
-       case FMODE_READ|FMODE_WRITE:
-       case FMODE_WRITE:
+       if (!test_bit(NFS_O_RDWR_STATE, &state->flags)) {
                err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
                if (err)
-                       break;
+                       goto out;
+       }
+       if (!test_bit(NFS_O_WRONLY_STATE, &state->flags)) {
                err = nfs4_open_recover_helper(opendata, FMODE_WRITE);
                if (err)
-                       break;
-               /* Fall through */
-       case FMODE_READ:
+                       goto out;
+       }
+       if (!test_bit(NFS_O_RDONLY_STATE, &state->flags)) {
                err = nfs4_open_recover_helper(opendata, FMODE_READ);
+               if (err)
+                       goto out;
        }
+       nfs_state_clear_delegation(state);
+out:
        nfs4_opendata_put(opendata);
        return nfs4_handle_delegation_recall_error(server, state, stateid, NULL, err);
 }
@@ -2492,6 +2500,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data,
        if (!ctx) {
                nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1);
                data->is_recover = true;
+               task_setup_data.flags |= RPC_TASK_TIMEOUT;
        } else {
                nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0);
                pnfs_lgopen_prepare(data, ctx);
@@ -2698,6 +2707,7 @@ static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
 {
        /* NFSv4.0 doesn't allow for delegation recovery on open expire */
        nfs40_clear_delegation_stateid(state);
+       nfs_state_clear_open_state_flags(state);
        return nfs4_open_expired(sp, state);
 }
 
@@ -2740,13 +2750,13 @@ out_free:
        return -NFS4ERR_EXPIRED;
 }
 
-static void nfs41_check_delegation_stateid(struct nfs4_state *state)
+static int nfs41_check_delegation_stateid(struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        nfs4_stateid stateid;
        struct nfs_delegation *delegation;
        const struct cred *cred = NULL;
-       int status;
+       int status, ret = NFS_OK;
 
        /* Get the delegation credential for use by test/free_stateid */
        rcu_read_lock();
@@ -2754,20 +2764,15 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
        if (delegation == NULL) {
                rcu_read_unlock();
                nfs_state_clear_delegation(state);
-               return;
+               return NFS_OK;
        }
 
        nfs4_stateid_copy(&stateid, &delegation->stateid);
-       if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
-               rcu_read_unlock();
-               nfs_state_clear_delegation(state);
-               return;
-       }
 
        if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
                                &delegation->flags)) {
                rcu_read_unlock();
-               return;
+               return NFS_OK;
        }
 
        if (delegation->cred)
@@ -2777,9 +2782,24 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
        trace_nfs4_test_delegation_stateid(state, NULL, status);
        if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID)
                nfs_finish_clear_delegation_stateid(state, &stateid);
+       else
+               ret = status;
 
-       if (delegation->cred)
-               put_cred(cred);
+       put_cred(cred);
+       return ret;
+}
+
+static void nfs41_delegation_recover_stateid(struct nfs4_state *state)
+{
+       nfs4_stateid tmp;
+
+       if (test_bit(NFS_DELEGATED_STATE, &state->flags) &&
+           nfs4_copy_delegation_stateid(state->inode, state->state,
+                               &tmp, NULL) &&
+           nfs4_stateid_match_other(&state->stateid, &tmp))
+               nfs_state_set_delegation(state, &tmp, state->state);
+       else
+               nfs_state_clear_delegation(state);
 }
 
 /**
@@ -2849,21 +2869,12 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
        const struct cred *cred = state->owner->so_cred;
        int status;
 
-       if (test_bit(NFS_OPEN_STATE, &state->flags) == 0) {
-               if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)  {
-                       if (nfs4_have_delegation(state->inode, state->state))
-                               return NFS_OK;
-                       return -NFS4ERR_OPENMODE;
-               }
+       if (test_bit(NFS_OPEN_STATE, &state->flags) == 0)
                return -NFS4ERR_BAD_STATEID;
-       }
        status = nfs41_test_and_free_expired_stateid(server, stateid, cred);
        trace_nfs4_test_open_stateid(state, NULL, status);
        if (status == -NFS4ERR_EXPIRED || status == -NFS4ERR_BAD_STATEID) {
-               clear_bit(NFS_O_RDONLY_STATE, &state->flags);
-               clear_bit(NFS_O_WRONLY_STATE, &state->flags);
-               clear_bit(NFS_O_RDWR_STATE, &state->flags);
-               clear_bit(NFS_OPEN_STATE, &state->flags);
+               nfs_state_clear_open_state_flags(state);
                stateid->type = NFS4_INVALID_STATEID_TYPE;
                return status;
        }
@@ -2876,7 +2887,11 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
 {
        int status;
 
-       nfs41_check_delegation_stateid(state);
+       status = nfs41_check_delegation_stateid(state);
+       if (status != NFS_OK)
+               return status;
+       nfs41_delegation_recover_stateid(state);
+
        status = nfs41_check_expired_locks(state);
        if (status != NFS_OK)
                return status;
@@ -3201,7 +3216,7 @@ static int _nfs4_do_setattr(struct inode *inode,
 
        if (nfs4_copy_delegation_stateid(inode, FMODE_WRITE, &arg->stateid, &delegation_cred)) {
                /* Use that stateid */
-       } else if (ctx != NULL) {
+       } else if (ctx != NULL && ctx->state) {
                struct nfs_lock_context *l_ctx;
                if (!nfs4_valid_open_stateid(ctx->state))
                        return -EBADF;
index 9afd051a487605f8fe043ded2b4e0e25dcfd51bb..cad4e064b328747e29fdc20578c53f28bf438607 100644 (file)
@@ -624,24 +624,39 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 /**
  * nfs4_purge_state_owners - Release all cached state owners
  * @server: nfs_server with cached state owners to release
+ * @head: resulting list of state owners
  *
  * Called at umount time.  Remaining state owners will be on
  * the LRU with ref count of zero.
+ * Note that the state owners are not freed, but are added
+ * to the list @head, which can later be used as an argument
+ * to nfs4_free_state_owners.
  */
-void nfs4_purge_state_owners(struct nfs_server *server)
+void nfs4_purge_state_owners(struct nfs_server *server, struct list_head *head)
 {
        struct nfs_client *clp = server->nfs_client;
        struct nfs4_state_owner *sp, *tmp;
-       LIST_HEAD(doomed);
 
        spin_lock(&clp->cl_lock);
        list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) {
-               list_move(&sp->so_lru, &doomed);
+               list_move(&sp->so_lru, head);
                nfs4_remove_state_owner_locked(sp);
        }
        spin_unlock(&clp->cl_lock);
+}
 
-       list_for_each_entry_safe(sp, tmp, &doomed, so_lru) {
+/**
+ * nfs4_purge_state_owners - Release all cached state owners
+ * @head: resulting list of state owners
+ *
+ * Frees a list of state owners that was generated by
+ * nfs4_purge_state_owners
+ */
+void nfs4_free_state_owners(struct list_head *head)
+{
+       struct nfs4_state_owner *sp, *tmp;
+
+       list_for_each_entry_safe(sp, tmp, head, so_lru) {
                list_del(&sp->so_lru);
                nfs4_free_state_owner(sp);
        }
@@ -1463,7 +1478,7 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
                nfs4_schedule_state_manager(clp);
 }
 
-static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
+static void nfs4_state_mark_open_context_bad(struct nfs4_state *state, int err)
 {
        struct inode *inode = state->inode;
        struct nfs_inode *nfsi = NFS_I(inode);
@@ -1474,6 +1489,8 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
                if (ctx->state != state)
                        continue;
                set_bit(NFS_CONTEXT_BAD, &ctx->flags);
+               pr_warn("NFSv4: state recovery failed for open file %pd2, "
+                               "error = %d\n", ctx->dentry, err);
        }
        rcu_read_unlock();
 }
@@ -1481,7 +1498,7 @@ static void nfs4_state_mark_open_context_bad(struct nfs4_state *state)
 static void nfs4_state_mark_recovery_failed(struct nfs4_state *state, int error)
 {
        set_bit(NFS_STATE_RECOVERY_FAILED, &state->flags);
-       nfs4_state_mark_open_context_bad(state);
+       nfs4_state_mark_open_context_bad(state, error);
 }
 
 
@@ -1512,6 +1529,7 @@ restart:
                switch (status) {
                case 0:
                        break;
+               case -ETIMEDOUT:
                case -ESTALE:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
@@ -1605,6 +1623,7 @@ static int __nfs4_reclaim_open_state(struct nfs4_state_owner *sp, struct nfs4_st
 static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs4_state_recovery_ops *ops)
 {
        struct nfs4_state *state;
+       unsigned int loop = 0;
        int status = 0;
 
        /* Note: we rely on the sp->so_states list being ordered 
@@ -1631,8 +1650,10 @@ restart:
 
                switch (status) {
                default:
-                       if (status >= 0)
+                       if (status >= 0) {
+                               loop = 0;
                                break;
+                       }
                        printk(KERN_ERR "NFS: %s: unhandled error %d\n", __func__, status);
                        /* Fall through */
                case -ENOENT:
@@ -1646,6 +1667,10 @@ restart:
                        break;
                case -EAGAIN:
                        ssleep(1);
+                       if (loop++ < 10) {
+                               set_bit(ops->state_flag_bit, &state->flags);
+                               break;
+                       }
                        /* Fall through */
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
@@ -1658,11 +1683,13 @@ restart:
                case -NFS4ERR_EXPIRED:
                case -NFS4ERR_NO_GRACE:
                        nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state);
+                       /* Fall through */
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
                case -NFS4ERR_BAD_HIGH_SLOT:
                case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               case -ETIMEDOUT:
                        goto out_err;
                }
                nfs4_put_open_state(state);
@@ -1856,12 +1883,13 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
        struct nfs4_state_owner *sp;
        struct nfs_server *server;
        struct rb_node *pos;
+       LIST_HEAD(freeme);
        int status = 0;
 
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-               nfs4_purge_state_owners(server);
+               nfs4_purge_state_owners(server, &freeme);
                spin_lock(&clp->cl_lock);
                for (pos = rb_first(&server->state_owners);
                     pos != NULL;
@@ -1890,6 +1918,7 @@ restart:
                spin_unlock(&clp->cl_lock);
        }
        rcu_read_unlock();
+       nfs4_free_state_owners(&freeme);
        return 0;
 }
 
@@ -1945,7 +1974,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status)
                return -EPERM;
        case -EACCES:
        case -NFS4ERR_DELAY:
-       case -ETIMEDOUT:
        case -EAGAIN:
                ssleep(1);
                break;
@@ -2574,7 +2602,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                }
 
                /* Now recover expired state... */
-               if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
+               if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
                        section = "reclaim nograce";
                        status = nfs4_do_reclaim(clp,
                                clp->cl_mvops->nograce_recovery_ops);
@@ -2582,6 +2610,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                                continue;
                        if (status < 0)
                                goto out_error;
+                       clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
                }
 
                nfs4_end_drain_session(clp);
index 75bd5b552ba47acf7a680b22cbe3c1d3b569e050..4525d5acae3868c04440da5d51db0128ed2644bc 100644 (file)
@@ -1903,12 +1903,6 @@ lookup_again:
                goto out_unlock;
        }
 
-       if (!nfs4_valid_open_stateid(ctx->state)) {
-               trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
-                               PNFS_UPDATE_LAYOUT_INVALID_OPEN);
-               goto out_unlock;
-       }
-
        /*
         * Choose a stateid for the LAYOUTGET. If we don't have a layout
         * stateid, or it has been invalidated, then we must use the open
@@ -1939,6 +1933,7 @@ lookup_again:
                                        iomode == IOMODE_RW ? FMODE_WRITE : FMODE_READ,
                                        NULL, &stateid, NULL);
                if (status != 0) {
+                       lseg = ERR_PTR(status);
                        trace_pnfs_update_layout(ino, pos, count,
                                        iomode, lo, lseg,
                                        PNFS_UPDATE_LAYOUT_INVALID_OPEN);
index 628631e2e34fe630f6e24a814f43551d93484135..703f595dce90c1bfb8dfad1ca589221cc7f6f0b5 100644 (file)
@@ -2260,6 +2260,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
            data->acdirmin != nfss->acdirmin / HZ ||
            data->acdirmax != nfss->acdirmax / HZ ||
            data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
+           (data->options & NFS_OPTION_FSCACHE) != (nfss->options & NFS_OPTION_FSCACHE) ||
            data->nfs_server.port != nfss->port ||
            data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
            !rpc_cmp_addr((struct sockaddr *)&data->nfs_server.address,
index 04f09689cd6d5bfb23b9757b7cb01fd1af180924..1600034a929bb1c89df6ce7134ecaad994bd1491 100644 (file)
@@ -119,6 +119,7 @@ static int traverse(struct seq_file *m, loff_t offset)
                }
                if (seq_has_overflowed(m))
                        goto Eoverflow;
+               p = m->op->next(m, p, &m->index);
                if (pos + m->count > offset) {
                        m->from = offset - pos;
                        m->count -= m->from;
@@ -126,7 +127,6 @@ static int traverse(struct seq_file *m, loff_t offset)
                }
                pos += m->count;
                m->count = 0;
-               p = m->op->next(m, p, &m->index);
                if (pos == offset)
                        break;
        }
index baf0b72c0a37deddd4936556a985cb020bf5ff4d..07aad70f39319f46b670dfef948f3b49d16f786a 100644 (file)
@@ -3835,15 +3835,28 @@ xfs_bmapi_read(
        XFS_STATS_INC(mp, xs_blk_mapr);
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
+       if (!ifp) {
+               /* No CoW fork?  Return a hole. */
+               if (whichfork == XFS_COW_FORK) {
+                       mval->br_startoff = bno;
+                       mval->br_startblock = HOLESTARTBLOCK;
+                       mval->br_blockcount = len;
+                       mval->br_state = XFS_EXT_NORM;
+                       *nmap = 1;
+                       return 0;
+               }
 
-       /* No CoW fork?  Return a hole. */
-       if (whichfork == XFS_COW_FORK && !ifp) {
-               mval->br_startoff = bno;
-               mval->br_startblock = HOLESTARTBLOCK;
-               mval->br_blockcount = len;
-               mval->br_state = XFS_EXT_NORM;
-               *nmap = 1;
-               return 0;
+               /*
+                * A missing attr ifork implies that the inode says we're in
+                * extents or btree format but failed to pass the inode fork
+                * verifier while trying to load it.  Treat that as a file
+                * corruption too.
+                */
+#ifdef DEBUG
+               xfs_alert(mp, "%s: inode %llu missing fork %d",
+                               __func__, ip->i_ino, whichfork);
+#endif /* DEBUG */
+               return -EFSCORRUPTED;
        }
 
        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
index d1c77fd0815da89cca4882c7bd4c19efac357745..0bf56e94bfe93cb00a87a92e3112346ca21ec7ca 100644 (file)
@@ -487,10 +487,8 @@ xfs_da3_split(
        ASSERT(state->path.active == 0);
        oldblk = &state->path.blk[0];
        error = xfs_da3_root_split(state, oldblk, addblk);
-       if (error) {
-               addblk->bp = NULL;
-               return error;   /* GROT: dir is inconsistent */
-       }
+       if (error)
+               goto out;
 
        /*
         * Update pointers to the node which used to be block 0 and just got
@@ -505,7 +503,10 @@ xfs_da3_split(
         */
        node = oldblk->bp->b_addr;
        if (node->hdr.info.forw) {
-               ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno);
+               if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
+                       error = -EFSCORRUPTED;
+                       goto out;
+               }
                node = addblk->bp->b_addr;
                node->hdr.info.back = cpu_to_be32(oldblk->blkno);
                xfs_trans_log_buf(state->args->trans, addblk->bp,
@@ -514,15 +515,19 @@ xfs_da3_split(
        }
        node = oldblk->bp->b_addr;
        if (node->hdr.info.back) {
-               ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno);
+               if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
+                       error = -EFSCORRUPTED;
+                       goto out;
+               }
                node = addblk->bp->b_addr;
                node->hdr.info.forw = cpu_to_be32(oldblk->blkno);
                xfs_trans_log_buf(state->args->trans, addblk->bp,
                                  XFS_DA_LOGRANGE(node, &node->hdr.info,
                                  sizeof(node->hdr.info)));
        }
+out:
        addblk->bp = NULL;
-       return 0;
+       return error;
 }
 
 /*
index afcc6642690a8d85aebab8849321b01c50016b98..1fc44efc344df9ebfd22597b57447e3b77cfb836 100644 (file)
@@ -741,7 +741,8 @@ xfs_dir2_leafn_lookup_for_entry(
        ents = dp->d_ops->leaf_ents_p(leaf);
 
        xfs_dir3_leaf_check(dp, bp);
-       ASSERT(leafhdr.count > 0);
+       if (leafhdr.count <= 0)
+               return -EFSCORRUPTED;
 
        /*
         * Look up the hash value in the leaf entries.
index 00e9f5c388d366031fd8c5b713655a718c0a9287..7fc3c1ad36bcd0e490058c78f39e5883505da1c6 100644 (file)
@@ -429,10 +429,7 @@ xfs_log_reserve(
 
        ASSERT(*ticp == NULL);
        tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent,
-                               KM_SLEEP | KM_MAYFAIL);
-       if (!tic)
-               return -ENOMEM;
-
+                               KM_SLEEP);
        *ticp = tic;
 
        xlog_grant_push_ail(log, tic->t_cnt ? tic->t_unit_res * tic->t_cnt
index bb6cb347018c07cda6a0cd90570938dd4ac5d2d1..f6947da70d715fc7fdd6d67fd7845ac0d1d4b23f 100644 (file)
 
 #define p4d_alloc(mm, pgd, address)    (pgd)
 #define p4d_offset(pgd, start)         (pgd)
-#define p4d_none(p4d)                  0
-#define p4d_bad(p4d)                   0
-#define p4d_present(p4d)               1
+
+#ifndef __ASSEMBLY__
+static inline int p4d_none(p4d_t p4d)
+{
+       return 0;
+}
+
+static inline int p4d_bad(p4d_t p4d)
+{
+       return 0;
+}
+
+static inline int p4d_present(p4d_t p4d)
+{
+       return 1;
+}
+#endif
+
 #define p4d_ERROR(p4d)                 do { } while (0)
 #define p4d_clear(p4d)                 pgd_clear(p4d)
 #define p4d_val(p4d)                   pgd_val(p4d)
index 16c769a7f979e387f58d65e094f9531213ad1f8b..6db030439e29c287ece08ab5353080fcfe0de39f 100644 (file)
@@ -34,6 +34,7 @@ struct kvm_pmu {
 u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
 void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
 u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
+void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);
 void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val);
@@ -71,6 +72,7 @@ static inline u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
 {
        return 0;
 }
+static inline void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
 static inline void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val) {}
index 46bbc949c20a0c8bfd89f24665b7b5c169e4d4ea..7a30524a80ee8793b446d745c225c5864f50cdc7 100644 (file)
@@ -350,6 +350,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 void kvm_vgic_load(struct kvm_vcpu *vcpu);
 void kvm_vgic_put(struct kvm_vcpu *vcpu);
+void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)   (!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)    ((k)->arch.vgic.initialized)
index 1b1fa1557e68aefe5cf5df252485d398b8a38e35..feff3fe4467ec97ce92aa7e6b5b13ef05012bb47 100644 (file)
@@ -311,7 +311,6 @@ enum req_flag_bits {
        __REQ_RAHEAD,           /* read ahead, can fail anytime */
        __REQ_BACKGROUND,       /* background IO */
        __REQ_NOWAIT,           /* Don't wait if request will block */
-       __REQ_NOWAIT_INLINE,    /* Return would-block error inline */
        /*
         * When a shared kthread needs to issue a bio for a cgroup, doing
         * so synchronously can lead to priority inversions as the kthread
@@ -346,7 +345,6 @@ enum req_flag_bits {
 #define REQ_RAHEAD             (1ULL << __REQ_RAHEAD)
 #define REQ_BACKGROUND         (1ULL << __REQ_BACKGROUND)
 #define REQ_NOWAIT             (1ULL << __REQ_NOWAIT)
-#define REQ_NOWAIT_INLINE      (1ULL << __REQ_NOWAIT_INLINE)
 #define REQ_CGROUP_PUNT                (1ULL << __REQ_CGROUP_PUNT)
 
 #define REQ_NOUNMAP            (1ULL << __REQ_NOUNMAP)
@@ -420,13 +418,12 @@ static inline int op_stat_group(unsigned int op)
 
 typedef unsigned int blk_qc_t;
 #define BLK_QC_T_NONE          -1U
-#define BLK_QC_T_EAGAIN                -2U
 #define BLK_QC_T_SHIFT         16
 #define BLK_QC_T_INTERNAL      (1U << 31)
 
 static inline bool blk_qc_t_valid(blk_qc_t cookie)
 {
-       return cookie != BLK_QC_T_NONE && cookie != BLK_QC_T_EAGAIN;
+       return cookie != BLK_QC_T_NONE;
 }
 
 static inline unsigned int blk_qc_t_to_queue_num(blk_qc_t cookie)
index 55cb455cfcb067f2ccdbdc84d6d2ba9c78deaaf8..a5dfbaf2470d7cbf31f8b339b469f0c85fbaea9d 100644 (file)
@@ -170,6 +170,8 @@ struct ccp_aes_engine {
        enum ccp_aes_mode mode;
        enum ccp_aes_action action;
 
+       u32 authsize;
+
        struct scatterlist *key;
        u32 key_len;            /* In bytes */
 
index d3a0fbfff2bb0931dddd8fd0d65ab544bc8f76b0..9fa4b3f88c397a790ce3d0d8a7042d5cea3107bd 100644 (file)
@@ -272,62 +272,6 @@ dim_update_sample_with_comps(u16 event_ctr, u64 packets, u64 bytes, u64 comps,
 
 /* Net DIM */
 
-/*
- * Net DIM profiles:
- *        There are different set of profiles for each CQ period mode.
- *        There are different set of profiles for RX/TX CQs.
- *        Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
- */
-#define NET_DIM_PARAMS_NUM_PROFILES 5
-#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
-#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
-#define NET_DIM_DEF_PROFILE_CQE 1
-#define NET_DIM_DEF_PROFILE_EQE 1
-
-#define NET_DIM_RX_EQE_PROFILES { \
-       {1,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {8,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {64,  NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-       {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
-}
-
-#define NET_DIM_RX_CQE_PROFILES { \
-       {2,  256},             \
-       {8,  128},             \
-       {16, 64},              \
-       {32, 64},              \
-       {64, 64}               \
-}
-
-#define NET_DIM_TX_EQE_PROFILES { \
-       {1,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {8,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {32,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {64,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
-       {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}   \
-}
-
-#define NET_DIM_TX_CQE_PROFILES { \
-       {5,  128},  \
-       {8,  64},  \
-       {16, 32},  \
-       {32, 32},  \
-       {64, 32}   \
-}
-
-static const struct dim_cq_moder
-rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
-       NET_DIM_RX_EQE_PROFILES,
-       NET_DIM_RX_CQE_PROFILES,
-};
-
-static const struct dim_cq_moder
-tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
-       NET_DIM_TX_EQE_PROFILES,
-       NET_DIM_TX_CQE_PROFILES,
-};
-
 /**
  *     net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile
  *     @cq_period_mode: CQ period mode
index 3813211a9aadef0e2dc2f96267faf914cad2987d..0bff3d7fac92c95e324928a0aadc48e6d4ffd35f 100644 (file)
@@ -42,13 +42,18 @@ void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
                dma_addr_t dma_addr, unsigned long attrs);
 long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr,
                dma_addr_t dma_addr);
-
-#ifdef CONFIG_ARCH_HAS_DMA_MMAP_PGPROT
 pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
                unsigned long attrs);
+
+#ifdef CONFIG_MMU
+pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs);
 #else
-# define arch_dma_mmap_pgprot(dev, prot, attrs)        pgprot_noncached(prot)
-#endif
+static inline pgprot_t dma_pgprot(struct device *dev, pgprot_t prot,
+               unsigned long attrs)
+{
+       return prot;    /* no protection bits supported without page tables */
+}
+#endif /* CONFIG_MMU */
 
 #ifdef CONFIG_DMA_NONCOHERENT_CACHE_SYNC
 void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
index ff65d22cf336935c9406930496dc8a8f57a0cbd0..92c6e31fb008ee80073e310797e27d0e72d428c2 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <net/sch_generic.h>
 
+#include <asm/byteorder.h>
 #include <uapi/linux/filter.h>
 #include <uapi/linux/bpf.h>
 
@@ -747,6 +748,18 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
        return size <= size_default && (size & (size - 1)) == 0;
 }
 
+static inline u8
+bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default)
+{
+       u8 load_off = off & (size_default - 1);
+
+#ifdef __LITTLE_ENDIAN
+       return load_off * 8;
+#else
+       return (size_default - (load_off + size)) * 8;
+#endif
+}
+
 #define bpf_ctx_wide_access_ok(off, size, type, field)                 \
        (size == sizeof(__u64) &&                                       \
        off >= offsetof(type, field) &&                                 \
index fb07b503dc453ddfe16c5f0f959d46be01ad55ba..f33881688f42b2d6605d4f868546fbc06b1cd778 100644 (file)
@@ -510,22 +510,18 @@ alloc_pages(gfp_t gfp_mask, unsigned int order)
 }
 extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
                        struct vm_area_struct *vma, unsigned long addr,
-                       int node, bool hugepage);
-#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
-       alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true)
+                       int node);
 #else
 #define alloc_pages(gfp_mask, order) \
                alloc_pages_node(numa_node_id(), gfp_mask, order)
-#define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\
-       alloc_pages(gfp_mask, order)
-#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
+#define alloc_pages_vma(gfp_mask, order, vma, addr, node)\
        alloc_pages(gfp_mask, order)
 #endif
 #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
 #define alloc_page_vma(gfp_mask, vma, addr)                    \
-       alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false)
+       alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id())
 #define alloc_page_vma_node(gfp_mask, vma, addr, node)         \
-       alloc_pages_vma(gfp_mask, 0, vma, addr, node, false)
+       alloc_pages_vma(gfp_mask, 0, vma, addr, node)
 
 extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 extern unsigned long get_zeroed_page(gfp_t gfp_mask);
index 8b728750a62580c6ed05fe93fc5aada94e145ac1..69e813bcb947ef59c1fc23e541a938d5c179d197 100644 (file)
@@ -80,6 +80,9 @@ extern int register_pppox_proto(int proto_num, const struct pppox_proto *pp);
 extern void unregister_pppox_proto(int proto_num);
 extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
 extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+extern int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+
+#define PPPOEIOCSFWD32    _IOW(0xB1 ,0, compat_size_t)
 
 /* PPPoX socket states */
 enum {
index b4f5403383fc9be106fad4cde572909df920c00c..9661416a9bb473da8bb329477b548a22fce4eaae 100644 (file)
@@ -41,11 +41,11 @@ struct rmnet_map_ul_csum_header {
        __be16 csum_start_offset;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        u16 csum_insert_offset:14;
-       u16 udp_ip4_ind:1;
+       u16 udp_ind:1;
        u16 csum_enabled:1;
 #elif defined (__BIG_ENDIAN_BITFIELD)
        u16 csum_enabled:1;
-       u16 udp_ip4_ind:1;
+       u16 udp_ind:1;
        u16 csum_insert_offset:14;
 #else
 #error "Please fix <asm/byteorder.h>"
index 91f391cd272e094d3d74683f08ac226fe8e1ce20..50028338a4cc081dc0f9dfcda8394804962dc1de 100644 (file)
@@ -94,11 +94,11 @@ struct keyring_index_key {
        union {
                struct {
 #ifdef __LITTLE_ENDIAN /* Put desc_len at the LSB of x */
-                       u     desc_len;
-                       char    desc[sizeof(long) - 1]; /* First few chars of description */
+                       u16     desc_len;
+                       char    desc[sizeof(long) - 2]; /* First few chars of description */
 #else
-                       char    desc[sizeof(long) - 1]; /* First few chars of description */
-                       u     desc_len;
+                       char    desc[sizeof(long) - 2]; /* First few chars of description */
+                       u16     desc_len;
 #endif
                };
                unsigned long x;
index 5c5b5867024cd80b69b96f29721faa6871c64dc5..fcb46b3374c60967993cf6123172c35a7cac4277 100644 (file)
@@ -861,8 +861,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
 
-bool kvm_arch_has_vcpu_debugfs(void);
-int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu);
+#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS
+void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu);
+#endif
 
 int kvm_arch_hardware_enable(void);
 void kvm_arch_hardware_disable(void);
@@ -872,6 +873,7 @@ int kvm_arch_check_processor_compat(void);
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
+bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 /*
index 44c41462be334dac8edbc365c293d7014bed29e9..2cd4359cb38cb4fa44d8099b89cee0811eee22ff 100644 (file)
@@ -668,6 +668,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
 
 void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
                        int val);
+void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);
 
 static inline void mod_lruvec_state(struct lruvec *lruvec,
                                    enum node_stat_item idx, int val)
@@ -1072,6 +1073,14 @@ static inline void mod_lruvec_page_state(struct page *page,
        mod_node_page_state(page_pgdat(page), idx, val);
 }
 
+static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx,
+                                          int val)
+{
+       struct page *page = virt_to_head_page(p);
+
+       __mod_node_page_state(page_pgdat(page), idx, val);
+}
+
 static inline
 unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
                                            gfp_t gfp_mask,
@@ -1159,6 +1168,16 @@ static inline void __dec_lruvec_page_state(struct page *page,
        __mod_lruvec_page_state(page, idx, -1);
 }
 
+static inline void __inc_lruvec_slab_state(void *p, enum node_stat_item idx)
+{
+       __mod_lruvec_slab_state(p, idx, 1);
+}
+
+static inline void __dec_lruvec_slab_state(void *p, enum node_stat_item idx)
+{
+       __mod_lruvec_slab_state(p, idx, -1);
+}
+
 /* idx can be of type enum memcg_stat_item or node_stat_item */
 static inline void inc_memcg_state(struct mem_cgroup *memcg,
                                   int idx)
index 5228c62af41659bb7d5ae0e7db00969b9f16ef73..bac395f1d00a0f9691b12ec6841f2401a10ca4fc 100644 (file)
@@ -139,6 +139,8 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
 struct mempolicy *get_task_policy(struct task_struct *p);
 struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
                unsigned long addr);
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+                                               unsigned long addr);
 bool vma_policy_mof(struct vm_area_struct *vma);
 
 extern void numa_default_policy(void);
index ce9839c8bc1a6ca539628f078fc8bf7471a84ce7..c2f056b5766df377a02414c5081134b12688efa6 100644 (file)
@@ -446,11 +446,11 @@ enum {
 };
 
 enum {
-       MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x20,
+       MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x1,
 };
 
 enum {
-       MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x20,
+       MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x1,
 };
 
 enum {
index 04a569568eacb738bcc52a9389f96eb4fcafdd7f..f049af3f3cd838c85d87e02d5e13f5a39d1ffec0 100644 (file)
@@ -220,6 +220,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler,
 
 struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
 void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
+u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse);
 int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
index b3d5752657d9893fbc83bdaf577d872ed9bde5a4..b8b570c30b5ed967bd5acc38fe2e3f4a6c7025fa 100644 (file)
@@ -5975,10 +5975,12 @@ struct mlx5_ifc_modify_cq_in_bits {
 
        struct mlx5_ifc_cqc_bits cq_context;
 
-       u8         reserved_at_280[0x40];
+       u8         reserved_at_280[0x60];
 
        u8         cq_umem_valid[0x1];
-       u8         reserved_at_2c1[0x5bf];
+       u8         reserved_at_2e1[0x1f];
+
+       u8         reserved_at_300[0x580];
 
        u8         pas[0][0x40];
 };
@@ -10052,9 +10054,8 @@ struct mlx5_ifc_tls_static_params_bits {
 };
 
 struct mlx5_ifc_tls_progress_params_bits {
-       u8         valid[0x1];
-       u8         reserved_at_1[0x7];
-       u8         pd[0x18];
+       u8         reserved_at_0[0x8];
+       u8         tisn[0x18];
 
        u8         next_record_tcp_sn[0x20];
 
index 3a37a89eb7a7c363c4ac795b8ed782e657e3c6fe..6a7a1083b6fb796d89d47beba775b3dd57255c3f 100644 (file)
@@ -159,7 +159,16 @@ struct page {
                        /** @pgmap: Points to the hosting device page map. */
                        struct dev_pagemap *pgmap;
                        void *zone_device_data;
-                       unsigned long _zd_pad_1;        /* uses mapping */
+                       /*
+                        * ZONE_DEVICE private pages are counted as being
+                        * mapped so the next 3 words hold the mapping, index,
+                        * and private fields from the source anonymous or
+                        * page cache page while the page is migrated to device
+                        * private memory.
+                        * ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also
+                        * use the mapping, index, and private fields when
+                        * pmem backed DAX files are mapped.
+                        */
                };
 
                /** @rcu_head: You can use this to free a page by RCU. */
index 9e700d9f9f287d0db0bf770cd5c4ee2a564db94c..82e4cd1b7ac3cb50346492a27163da53bb206e2c 100644 (file)
@@ -1567,8 +1567,10 @@ extern bool pcie_ports_native;
 
 #ifdef CONFIG_PCIEASPM
 bool pcie_aspm_support_enabled(void);
+bool pcie_aspm_enabled(struct pci_dev *pdev);
 #else
 static inline bool pcie_aspm_support_enabled(void) { return false; }
+static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
 #endif
 
 #ifdef CONFIG_PCIEAER
index b5d99482d3fe18e5f9c2eceb606a75458ae7e969..1a5f88316b081463a4e76bb8b48aa312f75162d5 100644 (file)
@@ -282,6 +282,9 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
 extern void exit_signals(struct task_struct *tsk);
 extern void kernel_sigaction(int, __sighandler_t);
 
+#define SIG_KTHREAD ((__force __sighandler_t)2)
+#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3)
+
 static inline void allow_signal(int sig)
 {
        /*
@@ -289,7 +292,17 @@ static inline void allow_signal(int sig)
         * know it'll be handled, so that they don't get converted to
         * SIGKILL or just silently dropped.
         */
-       kernel_sigaction(sig, (__force __sighandler_t)2);
+       kernel_sigaction(sig, SIG_KTHREAD);
+}
+
+static inline void allow_kernel_signal(int sig)
+{
+       /*
+        * Kernel threads handle their own signals. Let the signal code
+        * know signals sent by the kernel will be handled, so that they
+        * don't get silently dropped.
+        */
+       kernel_sigaction(sig, SIG_KTHREAD_KERNEL);
 }
 
 static inline void disallow_signal(int sig)
index d8af86d995d6fe0b7fe8afc3a21d7d8faac2d7ce..ba5583522d249444361314dc12ef63d5e6d5e79a 100644 (file)
@@ -1374,6 +1374,14 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
        to->l4_hash = from->l4_hash;
 };
 
+static inline void skb_copy_decrypted(struct sk_buff *to,
+                                     const struct sk_buff *from)
+{
+#ifdef CONFIG_TLS_DEVICE
+       to->decrypted = from->decrypted;
+#endif
+}
+
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
index 50ced8aba9dbf6c2cd4a0a1ef1598bdd58822821..e4b3fb4bb77c7004d9164c6ba85f3be37eea741f 100644 (file)
@@ -354,7 +354,13 @@ static inline void sk_psock_restore_proto(struct sock *sk,
        sk->sk_write_space = psock->saved_write_space;
 
        if (psock->sk_proto) {
-               sk->sk_prot = psock->sk_proto;
+               struct inet_connection_sock *icsk = inet_csk(sk);
+               bool has_ulp = !!icsk->icsk_ulp_data;
+
+               if (has_ulp)
+                       tcp_update_ulp(sk, psock->sk_proto);
+               else
+                       sk->sk_prot = psock->sk_proto;
                psock->sk_proto = NULL;
        }
 }
index 97523818cb14e0676cdc22c6b748f5b643ddc9ec..fc0bed59fc84ef8e6631d3c275853d52a46f84aa 100644 (file)
@@ -292,6 +292,9 @@ struct ucred {
 #define MSG_BATCH      0x40000 /* sendmmsg(): more messages coming */
 #define MSG_EOF         MSG_FIN
 #define MSG_NO_SHARED_FRAGS 0x80000 /* sendpage() internal : page frags are not shared */
+#define MSG_SENDPAGE_DECRYPTED 0x100000 /* sendpage() internal : page may carry
+                                         * plain text and require encryption
+                                         */
 
 #define MSG_ZEROCOPY   0x4000000       /* Use user data in kernel path */
 #define MSG_FASTOPEN   0x20000000      /* Send data in TCP SYN */
index 83d35d993e8c91cda28eb4f6f0ff222750a4a1db..e87826e23d593026f4d2fb2432f418f716585b67 100644 (file)
@@ -1457,7 +1457,7 @@ typedef void (*usb_complete_t)(struct urb *);
  * field rather than determining a dma address themselves.
  *
  * Note that transfer_buffer must still be set if the controller
- * does not support DMA (as indicated by bus.uses_dma) and when talking
+ * does not support DMA (as indicated by hcd_uses_dma()) and when talking
  * to root hub. If you have to trasfer between highmem zone and the device
  * on such controller, create a bounce buffer or bail out with an error.
  * If transfer_buffer cannot be set (is in highmem) and the controller is DMA
index bab27ccc8ff564eb70d364746e1fc317c0fd3fb2..a20e7815d814cb1fd6f84c91730d8584f8381fe4 100644 (file)
@@ -422,6 +422,9 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
        return hcd->high_prio_bh.completing_ep == ep;
 }
 
+#define hcd_uses_dma(hcd) \
+       (IS_ENABLED(CONFIG_HAS_DMA) && (hcd)->self.uses_dma)
+
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
 extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
                int status);
diff --git a/include/misc/charlcd.h b/include/misc/charlcd.h
deleted file mode 100644 (file)
index 8cf6c18..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Character LCD driver for Linux
- *
- * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
- * Copyright (C) 2016-2017 Glider bvba
- */
-
-struct charlcd {
-       const struct charlcd_ops *ops;
-       const unsigned char *char_conv; /* Optional */
-
-       int ifwidth;                    /* 4-bit or 8-bit (default) */
-       int height;
-       int width;
-       int bwidth;                     /* Default set by charlcd_alloc() */
-       int hwidth;                     /* Default set by charlcd_alloc() */
-
-       void *drvdata;                  /* Set by charlcd_alloc() */
-};
-
-struct charlcd_ops {
-       /* Required */
-       void (*write_cmd)(struct charlcd *lcd, int cmd);
-       void (*write_data)(struct charlcd *lcd, int data);
-
-       /* Optional */
-       void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
-       void (*clear_fast)(struct charlcd *lcd);
-       void (*backlight)(struct charlcd *lcd, int on);
-};
-
-struct charlcd *charlcd_alloc(unsigned int drvdata_size);
-void charlcd_free(struct charlcd *lcd);
-
-int charlcd_register(struct charlcd *lcd);
-int charlcd_unregister(struct charlcd *lcd);
-
-void charlcd_poke(struct charlcd *lcd);
index ded574b32c2089c2140397a30d985ff7c1c550f0..ffc95b382eb56cac8b32ec2c022eb3a9e19159ad 100644 (file)
@@ -278,6 +278,7 @@ struct hci_dev {
        __u16           conn_info_min_age;
        __u16           conn_info_max_age;
        __u16           auth_payload_timeout;
+       __u8            min_enc_key_size;
        __u8            ssp_debug_mode;
        __u8            hw_error_code;
        __u32           clock;
index 45850a8391d95d50e608ca36d1dfb3554582b4f8..26e2ad2c702786781d326f01c7bb824775a82d37 100644 (file)
@@ -7320,6 +7320,21 @@ void cfg80211_pmsr_complete(struct wireless_dev *wdev,
                            struct cfg80211_pmsr_request *req,
                            gfp_t gfp);
 
+/**
+ * cfg80211_iftype_allowed - check whether the interface can be allowed
+ * @wiphy: the wiphy
+ * @iftype: interface type
+ * @is_4addr: use_4addr flag, must be '0' when check_swif is '1'
+ * @check_swif: check iftype against software interfaces
+ *
+ * Check whether the interface is allowed to operate; additionally, this API
+ * can be used to check iftype against the software interfaces when
+ * check_swif is '1'.
+ */
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+                            bool is_4addr, u8 check_swif);
+
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
index 010f26b31c89b375f4cabf6572d51f0383c93f0e..bac79e817776c6e65ed37f5b5c6af61a5df59ec0 100644 (file)
@@ -171,7 +171,7 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
 void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
                              struct sk_buff *parent);
 void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
-                           void *reasm_data);
+                           void *reasm_data, bool try_coalesce);
 struct sk_buff *inet_frag_pull_head(struct inet_frag_queue *q);
 
 #endif
index 4a9da951a794efbf9183c0a2e3d3ca94ec88f9d5..cb668bc2692db22e4639fcd3e95b21ed55f00410 100644 (file)
@@ -61,7 +61,6 @@ struct net {
        spinlock_t              rules_mod_lock;
 
        u32                     hash_mix;
-       atomic64_t              cookie_gen;
 
        struct list_head        list;           /* list of network namespaces */
        struct list_head        exit_list;      /* To linked to call pernet exit
index 9b624566b82d3028cd5210a183308e8571ade2e5..475d6f28ca677a8b40c106fa08af86971226000e 100644 (file)
@@ -421,8 +421,7 @@ struct nft_set {
        unsigned char                   *udata;
        /* runtime data below here */
        const struct nft_set_ops        *ops ____cacheline_aligned;
-       u16                             flags:13,
-                                       bound:1,
+       u16                             flags:14,
                                        genmask:2;
        u8                              klen;
        u8                              dlen;
@@ -1348,12 +1347,15 @@ struct nft_trans_rule {
 struct nft_trans_set {
        struct nft_set                  *set;
        u32                             set_id;
+       bool                            bound;
 };
 
 #define nft_trans_set(trans)   \
        (((struct nft_trans_set *)trans->data)->set)
 #define nft_trans_set_id(trans)        \
        (((struct nft_trans_set *)trans->data)->set_id)
+#define nft_trans_set_bound(trans)     \
+       (((struct nft_trans_set *)trans->data)->bound)
 
 struct nft_trans_chain {
        bool                            update;
@@ -1384,12 +1386,15 @@ struct nft_trans_table {
 struct nft_trans_elem {
        struct nft_set                  *set;
        struct nft_set_elem             elem;
+       bool                            bound;
 };
 
 #define nft_trans_elem_set(trans)      \
        (((struct nft_trans_elem *)trans->data)->set)
 #define nft_trans_elem(trans)  \
        (((struct nft_trans_elem *)trans->data)->elem)
+#define nft_trans_elem_set_bound(trans)        \
+       (((struct nft_trans_elem *)trans->data)->bound)
 
 struct nft_trans_obj {
        struct nft_object               *obj;
index 3196663a10e30e24880f571fb59a30e2e2cabfb7..c8b9dec376f56599a7403718727b0674681fbcdb 100644 (file)
@@ -73,4 +73,6 @@ int nft_flow_rule_offload_commit(struct net *net);
        (__reg)->key            = __key;                                \
        memset(&(__reg)->mask, 0xff, (__reg)->len);
 
+int nft_chain_offload_priority(struct nft_base_chain *basechain);
+
 #endif
index e4650e5b64a1db760a220fba3b7d4ad50eb54b17..b140c8f1be22d2e9943d7d98ae9e7db3c076f20b 100644 (file)
@@ -684,9 +684,8 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
                              const struct nla_policy *policy,
                              struct netlink_ext_ack *extack)
 {
-       return __nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
-                          nlmsg_attrlen(nlh, hdrlen), policy,
-                          NL_VALIDATE_STRICT, extack);
+       return __nlmsg_parse(nlh, hdrlen, tb, maxtype, policy,
+                            NL_VALIDATE_STRICT, extack);
 }
 
 /**
index e429809ca90d84b167749195126b0c8004d5223c..98be18ef1ed3400739120e354ba1c5082bc94770 100644 (file)
@@ -646,7 +646,7 @@ tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common,
 {
        cls_common->chain_index = tp->chain->index;
        cls_common->protocol = tp->protocol;
-       cls_common->prio = tp->prio;
+       cls_common->prio = tp->prio >> 16;
        if (tc_skip_sw(flags) || flags & TCA_CLS_FLAGS_VERBOSE)
                cls_common->extack = extack;
 }
index 228db3998e46e42156fec16e78f5e627669a9687..2c53f1a1d905409247b1bdafdfaf99d86e430cd0 100644 (file)
@@ -2482,6 +2482,7 @@ static inline bool sk_fullsock(const struct sock *sk)
 
 /* Checks if this SKB belongs to an HW offloaded socket
  * and whether any SW fallbacks are required based on dev.
+ * Check decrypted mark in case skb_orphan() cleared socket.
  */
 static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
                                                   struct net_device *dev)
@@ -2489,8 +2490,15 @@ static inline struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
 #ifdef CONFIG_SOCK_VALIDATE_XMIT
        struct sock *sk = skb->sk;
 
-       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb)
+       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) {
                skb = sk->sk_validate_xmit_skb(sk, dev, skb);
+#ifdef CONFIG_TLS_DEVICE
+       } else if (unlikely(skb->decrypted)) {
+               pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n");
+               kfree_skb(skb);
+               skb = NULL;
+#endif
+       }
 #endif
 
        return skb;
index 8b9ef366426256ee83943f9da05bd1c301ffbf23..cfdc7cb82cad02b12167a168d2cce13def02f0c0 100644 (file)
@@ -54,7 +54,7 @@ static inline u64 tcf_police_rate_bytes_ps(const struct tc_action *act)
        struct tcf_police *police = to_police(act);
        struct tcf_police_params *params;
 
-       params = rcu_dereference_bh(police->params);
+       params = rcu_dereference_bh_rtnl(police->params);
        return params->rate.rate_bytes_ps;
 }
 
@@ -63,7 +63,7 @@ static inline s64 tcf_police_tcfp_burst(const struct tc_action *act)
        struct tcf_police *police = to_police(act);
        struct tcf_police_params *params;
 
-       params = rcu_dereference_bh(police->params);
+       params = rcu_dereference_bh_rtnl(police->params);
        return params->tcfp_burst;
 }
 
index 0a559d4b6f0f019a872e2afad578fc3cd3d02b1b..b4fce0fae645690207be3b4cd289cf27f8578f03 100644 (file)
@@ -44,7 +44,7 @@ static inline int tcf_sample_trunc_size(const struct tc_action *a)
 static inline struct psample_group *
 tcf_sample_psample_group(const struct tc_action *a)
 {
-       return rcu_dereference(to_sample(a)->psample_group);
+       return rcu_dereference_rtnl(to_sample(a)->psample_group);
 }
 
 #endif /* __NET_TC_SAMPLE_H */
index e5cf514ba118e688ce3b3da66f696abd47e1d10f..81e8ade1e6e415779e1a18b39bd2695c9b871152 100644 (file)
@@ -2108,6 +2108,8 @@ struct tcp_ulp_ops {
 
        /* initialize ulp */
        int (*init)(struct sock *sk);
+       /* update ulp */
+       void (*update)(struct sock *sk, struct proto *p);
        /* cleanup ulp */
        void (*release)(struct sock *sk);
 
@@ -2119,6 +2121,7 @@ void tcp_unregister_ulp(struct tcp_ulp_ops *type);
 int tcp_set_ulp(struct sock *sk, const char *name);
 void tcp_get_available_ulp(char *buf, size_t len);
 void tcp_cleanup_ulp(struct sock *sk);
+void tcp_update_ulp(struct sock *sk, struct proto *p);
 
 #define MODULE_ALIAS_TCP_ULP(name)                             \
        __MODULE_INFO(alias, alias_userspace, name);            \
index 584609174fe007fbaea67da225363e2b91047c3b..41b2d41bb1b81a67731fc064c9dffa33b1c439e9 100644 (file)
@@ -107,9 +107,7 @@ struct tls_device {
 enum {
        TLS_BASE,
        TLS_SW,
-#ifdef CONFIG_TLS_DEVICE
        TLS_HW,
-#endif
        TLS_HW_RECORD,
        TLS_NUM_CONFIG,
 };
@@ -162,6 +160,7 @@ struct tls_sw_context_tx {
        int async_capable;
 
 #define BIT_TX_SCHEDULED       0
+#define BIT_TX_CLOSING         1
        unsigned long tx_bitmask;
 };
 
@@ -272,6 +271,8 @@ struct tls_context {
        unsigned long flags;
 
        /* cache cold stuff */
+       struct proto *sk_proto;
+
        void (*sk_destruct)(struct sock *sk);
        void (*sk_proto_close)(struct sock *sk, long timeout);
 
@@ -355,13 +356,17 @@ int tls_sk_attach(struct sock *sk, int optname, char __user *optval,
                  unsigned int optlen);
 
 int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx);
+void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx);
+void tls_sw_strparser_done(struct tls_context *tls_ctx);
 int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
 int tls_sw_sendpage(struct sock *sk, struct page *page,
                    int offset, size_t size, int flags);
-void tls_sw_close(struct sock *sk, long timeout);
-void tls_sw_free_resources_tx(struct sock *sk);
+void tls_sw_cancel_work_tx(struct tls_context *tls_ctx);
+void tls_sw_release_resources_tx(struct sock *sk);
+void tls_sw_free_ctx_tx(struct tls_context *tls_ctx);
 void tls_sw_free_resources_rx(struct sock *sk);
 void tls_sw_release_resources_rx(struct sock *sk);
+void tls_sw_free_ctx_rx(struct tls_context *tls_ctx);
 int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
                   int nonblock, int flags, int *addr_len);
 bool tls_sw_stream_read(const struct sock *sk);
index 954563ee22779741d86d20885a7c4a08abb502cb..985a5f583de4c7f10cf161267cd554999dad4bf8 100644 (file)
@@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
 {
        struct device *dev = simple_priv_to_dev(priv);
 
+       /* dai might be NULL */
+       if (!dai)
+               return;
+
        if (dai->name)
                dev_dbg(dev, "%s dai name = %s\n",
                        name, dai->name);
index cc1d060cbf133e92460cf91f24c35babccbd9248..fa06b528c73c51d14f757be9328470d987e1945f 100644 (file)
@@ -498,10 +498,10 @@ rxrpc_tx_points;
 #define E_(a, b)       { a, b }
 
 TRACE_EVENT(rxrpc_local,
-           TP_PROTO(struct rxrpc_local *local, enum rxrpc_local_trace op,
+           TP_PROTO(unsigned int local_debug_id, enum rxrpc_local_trace op,
                     int usage, const void *where),
 
-           TP_ARGS(local, op, usage, where),
+           TP_ARGS(local_debug_id, op, usage, where),
 
            TP_STRUCT__entry(
                    __field(unsigned int,       local           )
@@ -511,7 +511,7 @@ TRACE_EVENT(rxrpc_local,
                             ),
 
            TP_fast_assign(
-                   __entry->local = local->debug_id;
+                   __entry->local = local_debug_id;
                    __entry->op = op;
                    __entry->usage = usage;
                    __entry->where = where;
index fa1c753dcdbc7f170a65dbaa8b01683de5e6e942..a5aa7d3ac6a116a7a8d3c08d840c37a70e42e7a4 100644 (file)
@@ -1466,8 +1466,8 @@ union bpf_attr {
  *             If no cookie has been set yet, generate a new cookie. Once
  *             generated, the socket cookie remains stable for the life of the
  *             socket. This helper can be useful for monitoring per socket
- *             networking traffic statistics as it provides a unique socket
- *             identifier per namespace.
+ *             networking traffic statistics as it provides a global socket
+ *             identifier that can be assumed unique.
  *     Return
  *             A 8-byte long non-decreasing number on success, or 0 if the
  *             socket field is missing inside *skb*.
index 070d1bc7e725df318d2297ae671f2a34f8dd5089..20917c59f39c9a2a27bf1b62e907d5e2a31f88a6 100644 (file)
@@ -410,21 +410,6 @@ struct kfd_ioctl_unmap_memory_from_gpu_args {
        __u32 n_success;                /* to/from KFD */
 };
 
-/* Allocate GWS for specific queue
- *
- * @gpu_id:      device identifier
- * @queue_id:    queue's id that GWS is allocated for
- * @num_gws:     how many GWS to allocate
- * @first_gws:   index of the first GWS allocated.
- *               only support contiguous GWS allocation
- */
-struct kfd_ioctl_alloc_queue_gws_args {
-       __u32 gpu_id;           /* to KFD */
-       __u32 queue_id;         /* to KFD */
-       __u32 num_gws;          /* to KFD */
-       __u32 first_gws;        /* from KFD */
-};
-
 struct kfd_ioctl_get_dmabuf_info_args {
        __u64 size;             /* from KFD */
        __u64 metadata_ptr;     /* to KFD */
@@ -544,10 +529,7 @@ enum kfd_mmio_remap {
 #define AMDKFD_IOC_IMPORT_DMABUF               \
                AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args)
 
-#define AMDKFD_IOC_ALLOC_QUEUE_GWS             \
-               AMDKFD_IOWR(0x1E, struct kfd_ioctl_alloc_queue_gws_args)
-
 #define AMDKFD_COMMAND_START           0x01
-#define AMDKFD_COMMAND_END             0x1F
+#define AMDKFD_COMMAND_END             0x1E
 
 #endif
index 2312f0ec07b2791ffaece0a95eebaefa727f14be..323f0dfc2a4e2403ca50b13fc46b74f4d44a779c 100644 (file)
@@ -1,4 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef _UAPI_XT_CONNLABEL_H
+#define _UAPI_XT_CONNLABEL_H
+
 #include <linux/types.h>
 
 #define XT_CONNLABEL_MAXBIT 127
@@ -11,3 +15,5 @@ struct xt_connlabel_mtinfo {
        __u16 bit;
        __u16 options;
 };
+
+#endif /* _UAPI_XT_CONNLABEL_H */
index 8eb96021709c8c3ed15f53e7295a6c92dfe77010..c3409c8ec0ddd10de38c1a1e7742dff563ec8b71 100644 (file)
@@ -6,17 +6,24 @@
  * Desired design of maximum size and alignment (see RFC2553)
  */
 #define _K_SS_MAXSIZE  128     /* Implementation specific max size */
-#define _K_SS_ALIGNSIZE        (__alignof__ (struct sockaddr *))
-                               /* Implementation specific desired alignment */
 
 typedef unsigned short __kernel_sa_family_t;
 
+/*
+ * The definition uses anonymous union and struct in order to control the
+ * default alignment.
+ */
 struct __kernel_sockaddr_storage {
-       __kernel_sa_family_t    ss_family;              /* address family */
-       /* Following field(s) are implementation specific */
-       char            __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
+       union {
+               struct {
+                       __kernel_sa_family_t    ss_family; /* address family */
+                       /* Following field(s) are implementation specific */
+                       char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
                                /* space to achieve desired size, */
                                /* _SS_MAXSIZE value minus size of ss_family */
-} __attribute__ ((aligned(_K_SS_ALIGNSIZE)));  /* force desired alignment */
+               };
+               void *__align; /* implementation specific desired alignment */
+       };
+};
 
 #endif /* _UAPI_LINUX_SOCKET_H */
index 7de68f1dc707f0d55805e3fafa3c97a363d06e0b..af735f55b2911208077ad70d2e83e750125001e0 100644 (file)
@@ -180,6 +180,7 @@ struct siw_cqe {
  * to control CQ arming.
  */
 struct siw_cq_ctrl {
-       __aligned_u64 notify;
+       __u32 flags;
+       __u32 pad;
 };
 #endif
index 1afca973eb0972ee127e75bbac9fbb142ab6faed..e9f697467a8611ad7441d5f1219913bc2de7a97c 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __INCLUDE_UAPI_SOF_FW_H__
 #define __INCLUDE_UAPI_SOF_FW_H__
 
+#include <linux/types.h>
+
 #define SND_SOF_FW_SIG_SIZE    4
 #define SND_SOF_FW_ABI         1
 #define SND_SOF_FW_SIG         "Reef"
@@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type {
 
 struct snd_sof_blk_hdr {
        enum snd_sof_fw_blk_type type;
-       uint32_t size;          /* bytes minus this header */
-       uint32_t offset;        /* offset from base */
+       __u32 size;             /* bytes minus this header */
+       __u32 offset;           /* offset from base */
 } __packed;
 
 /*
@@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type {
 
 struct snd_sof_mod_hdr {
        enum snd_sof_fw_mod_type type;
-       uint32_t size;          /* bytes minus this header */
-       uint32_t num_blocks;    /* number of blocks */
+       __u32 size;             /* bytes minus this header */
+       __u32 num_blocks;       /* number of blocks */
 } __packed;
 
 /*
@@ -70,9 +72,9 @@ struct snd_sof_mod_hdr {
  */
 struct snd_sof_fw_header {
        unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
-       uint32_t file_size;     /* size of file minus this header */
-       uint32_t num_modules;   /* number of modules */
-       uint32_t abi;           /* version of header format */
+       __u32 file_size;        /* size of file minus this header */
+       __u32 num_modules;      /* number of modules */
+       __u32 abi;              /* version of header format */
 } __packed;
 
 #endif
index 7868990b0d6f34a9bf3613b98281fde8792ec0b3..5f4518e7a972347c121784b8bc7d9194201267fa 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
 #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
 
+#include <linux/types.h>
+
 /*
  * Header for all non IPC ABI data.
  *
  * Used by any bespoke component data structures or binary blobs.
  */
 struct sof_abi_hdr {
-       uint32_t magic;         /**< 'S', 'O', 'F', '\0' */
-       uint32_t type;          /**< component specific type */
-       uint32_t size;          /**< size in bytes of data excl. this struct */
-       uint32_t abi;           /**< SOF ABI version */
-       uint32_t reserved[4];   /**< reserved for future use */
-       uint32_t data[0];       /**< Component data - opaque to core */
+       __u32 magic;            /**< 'S', 'O', 'F', '\0' */
+       __u32 type;             /**< component specific type */
+       __u32 size;             /**< size in bytes of data excl. this struct */
+       __u32 abi;              /**< SOF ABI version */
+       __u32 reserved[4];      /**< reserved for future use */
+       __u32 data[0];          /**< Component data - opaque to core */
 }  __packed;
 
 #endif
index 5900cbb966b17adb04538e887b2f2eff658ba823..c84d83f86141f82913bd540be1fcd87bd04613f6 100644 (file)
@@ -8616,8 +8616,8 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
                }
 
                if (is_narrower_load && size < target_size) {
-                       u8 shift = (off & (size_default - 1)) * 8;
-
+                       u8 shift = bpf_ctx_narrow_load_shift(off, size,
+                                                            size_default);
                        if (ctx_field_size <= 4) {
                                if (shift)
                                        insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH,
index b062425ccf8da3d6a6c79d539297e30ebd70050d..c09ea4c995e104b2ed0dd62b5ab010d4b255dc91 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * kernel/configs.c
  * Echo the kernel .config file used to build the kernel
@@ -6,21 +7,6 @@
  * Copyright (C) 2002 Randy Dunlap <rdunlap@xenotime.net>
  * Copyright (C) 2002 Al Stone <ahs3@fc.hp.com>
  * Copyright (C) 2002 Hewlett-Packard Company
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>
index 59bdceea3737a4a095555723f4a7b79fda15c048..795c9b095d7573a79df1d4eeef00a10dca6a2ee4 100644 (file)
@@ -47,9 +47,6 @@ u64 dma_direct_get_required_mask(struct device *dev)
 {
        u64 max_dma = phys_to_dma_direct(dev, (max_pfn - 1) << PAGE_SHIFT);
 
-       if (dev->bus_dma_mask && dev->bus_dma_mask < max_dma)
-               max_dma = dev->bus_dma_mask;
-
        return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
 }
 
@@ -130,10 +127,12 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
        if (!page)
                return NULL;
 
-       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+       if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+           !force_dma_unencrypted(dev)) {
                /* remove any dirty cache lines on the kernel alias */
                if (!PageHighMem(page))
                        arch_dma_prep_coherent(page, size);
+               *dma_handle = phys_to_dma(dev, page_to_phys(page));
                /* return the page pointer as the opaque cookie */
                return page;
        }
@@ -178,7 +177,8 @@ void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
 {
        unsigned int page_order = get_order(size);
 
-       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+       if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+           !force_dma_unencrypted(dev)) {
                /* cpu_addr is a struct page cookie, not a kernel address */
                __dma_direct_free_pages(dev, size, cpu_addr);
                return;
index b945239621d86255d6a259a9a2911c9a393e0b11..b0038ca3aa92b2e9d4a7976a08237deb2c2c7531 100644 (file)
@@ -150,6 +150,23 @@ int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt,
 }
 EXPORT_SYMBOL(dma_get_sgtable_attrs);
 
+#ifdef CONFIG_MMU
+/*
+ * Return the page attributes used for mapping dma_alloc_* memory, either in
+ * kernel space if remapping is needed, or to userspace through dma_mmap_*.
+ */
+pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs)
+{
+       if (dev_is_dma_coherent(dev) ||
+           (IS_ENABLED(CONFIG_DMA_NONCOHERENT_CACHE_SYNC) &&
+             (attrs & DMA_ATTR_NON_CONSISTENT)))
+               return prot;
+       if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_MMAP_PGPROT))
+               return arch_dma_mmap_pgprot(dev, prot, attrs);
+       return pgprot_noncached(prot);
+}
+#endif /* CONFIG_MMU */
+
 /*
  * Create userspace mapping for the DMA-coherent memory.
  */
@@ -164,7 +181,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
        unsigned long pfn;
        int ret = -ENXIO;
 
-       vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
+       vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
 
        if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
                return ret;
index a594aec07882d9a0ad4d482d00afb81e4daa3189..ffe78f0b2fe47c442330ee8de67cb11e230b0ae0 100644 (file)
@@ -218,7 +218,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 
        /* create a coherent mapping */
        ret = dma_common_contiguous_remap(page, size, VM_USERMAP,
-                       arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs),
+                       dma_pgprot(dev, PAGE_KERNEL, attrs),
                        __builtin_return_address(0));
        if (!ret) {
                __dma_direct_free_pages(dev, size, page);
index 4352b08ae48dec41f3ec678cd6938fc2e8bb2b3a..6fef48033f9686997bc455d79e2a76899746fc93 100644 (file)
@@ -251,11 +251,9 @@ irq_create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
         * Determine the number of vectors which need interrupt affinities
         * assigned. If the pre/post request exhausts the available vectors
         * then nothing to do here except for invoking the calc_sets()
-        * callback so the device driver can adjust to the situation. If there
-        * is only a single vector, then managing the queue is pointless as
-        * well.
+        * callback so the device driver can adjust to the situation.
         */
-       if (nvecs > 1 && nvecs > affd->pre_vectors + affd->post_vectors)
+       if (nvecs > affd->pre_vectors + affd->post_vectors)
                affvecs = nvecs - affd->pre_vectors - affd->post_vectors;
        else
                affvecs = 0;
index 636ca6f88c8ee275efd664c553609c5121a5cb3f..867b4bb6d4beb541d1d9eb087711d1e52a446416 100644 (file)
@@ -40,6 +40,7 @@ struct sugov_policy {
        struct task_struct      *thread;
        bool                    work_in_progress;
 
+       bool                    limits_changed;
        bool                    need_freq_update;
 };
 
@@ -89,8 +90,11 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
            !cpufreq_this_cpu_can_update(sg_policy->policy))
                return false;
 
-       if (unlikely(sg_policy->need_freq_update))
+       if (unlikely(sg_policy->limits_changed)) {
+               sg_policy->limits_changed = false;
+               sg_policy->need_freq_update = true;
                return true;
+       }
 
        delta_ns = time - sg_policy->last_freq_update_time;
 
@@ -437,7 +441,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
 static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy)
 {
        if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
-               sg_policy->need_freq_update = true;
+               sg_policy->limits_changed = true;
 }
 
 static void sugov_update_single(struct update_util_data *hook, u64 time,
@@ -457,7 +461,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
        if (!sugov_should_update_freq(sg_policy, time))
                return;
 
-       busy = sugov_cpu_is_busy(sg_cpu);
+       /* Limits may have changed, don't skip frequency update */
+       busy = !sg_policy->need_freq_update && sugov_cpu_is_busy(sg_cpu);
 
        util = sugov_get_util(sg_cpu);
        max = sg_cpu->max;
@@ -831,6 +836,7 @@ static int sugov_start(struct cpufreq_policy *policy)
        sg_policy->last_freq_update_time        = 0;
        sg_policy->next_freq                    = 0;
        sg_policy->work_in_progress             = false;
+       sg_policy->limits_changed               = false;
        sg_policy->need_freq_update             = false;
        sg_policy->cached_raw_freq              = 0;
 
@@ -879,7 +885,7 @@ static void sugov_limits(struct cpufreq_policy *policy)
                mutex_unlock(&sg_policy->work_lock);
        }
 
-       sg_policy->need_freq_update = true;
+       sg_policy->limits_changed = true;
 }
 
 struct cpufreq_governor schedutil_gov = {
index ef5b9f6b1d421bbd3e88e5300fa8f0ceeb448cbd..46122edd8552c9abd7acb3cf665332d91746ed7d 100644 (file)
@@ -2088,17 +2088,13 @@ retry:
        }
 
        deactivate_task(rq, next_task, 0);
-       sub_running_bw(&next_task->dl, &rq->dl);
-       sub_rq_bw(&next_task->dl, &rq->dl);
        set_task_cpu(next_task, later_rq->cpu);
-       add_rq_bw(&next_task->dl, &later_rq->dl);
 
        /*
         * Update the later_rq clock here, because the clock is used
         * by the cpufreq_update_util() inside __add_running_bw().
         */
        update_rq_clock(later_rq);
-       add_running_bw(&next_task->dl, &later_rq->dl);
        activate_task(later_rq, next_task, ENQUEUE_NOCLOCK);
        ret = 1;
 
@@ -2186,11 +2182,7 @@ static void pull_dl_task(struct rq *this_rq)
                        resched = true;
 
                        deactivate_task(src_rq, p, 0);
-                       sub_running_bw(&p->dl, &src_rq->dl);
-                       sub_rq_bw(&p->dl, &src_rq->dl);
                        set_task_cpu(p, this_cpu);
-                       add_rq_bw(&p->dl, &this_rq->dl);
-                       add_running_bw(&p->dl, &this_rq->dl);
                        activate_task(this_rq, p, 0);
                        dmin = p->dl.deadline;
 
index 7acc632c3b82bebceeff2cfdc06eb652096f912b..23fbbcc414d5d739507ac1f8ecb5757c87a9ce55 100644 (file)
@@ -1051,7 +1051,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
 
        if (!rcu_access_pointer(group->poll_kworker)) {
                struct sched_param param = {
-                       .sched_priority = MAX_RT_PRIO - 1,
+                       .sched_priority = 1,
                };
                struct kthread_worker *kworker;
 
@@ -1061,7 +1061,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
                        mutex_unlock(&group->trigger_lock);
                        return ERR_CAST(kworker);
                }
-               sched_setscheduler(kworker->task, SCHED_FIFO, &param);
+               sched_setscheduler_nocheck(kworker->task, SCHED_FIFO, &param);
                kthread_init_delayed_work(&group->poll_work,
                                psi_poll_work);
                rcu_assign_pointer(group->poll_kworker, kworker);
index e667be6907d71333c44546cd43ebfdde6c9eab3c..534fec266a334b299846034e878c271619fe5c71 100644 (file)
@@ -90,6 +90,11 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
            handler == SIG_DFL && !(force && sig_kernel_only(sig)))
                return true;
 
+       /* Only allow kernel generated signals to this kthread */
+       if (unlikely((t->flags & PF_KTHREAD) &&
+                    (handler == SIG_KTHREAD_KERNEL) && !force))
+               return true;
+
        return sig_handler_ignored(handler, sig);
 }
 
index 439d641ec79648439999bcb9a93a11cece9c4566..38045d6d05381ebb89d73369b0c60766505ef9be 100644 (file)
@@ -74,8 +74,8 @@ void dim_calc_stats(struct dim_sample *start, struct dim_sample *end,
                                        delta_us);
        curr_stats->cpms = DIV_ROUND_UP(ncomps * USEC_PER_MSEC, delta_us);
        if (curr_stats->epms != 0)
-               curr_stats->cpe_ratio =
-                               (curr_stats->cpms * 100) / curr_stats->epms;
+               curr_stats->cpe_ratio = DIV_ROUND_DOWN_ULL(
+                       curr_stats->cpms * 100, curr_stats->epms);
        else
                curr_stats->cpe_ratio = 0;
 
index 5bcc902c53888d8feb90957d0e90e5ad91e562fc..a4db51c2126633c35c3f0ee789022a3562596b80 100644 (file)
@@ -5,6 +5,62 @@
 
 #include <linux/dim.h>
 
+/*
+ * Net DIM profiles:
+ *        There are different set of profiles for each CQ period mode.
+ *        There are different set of profiles for RX/TX CQs.
+ *        Each profile size must be of NET_DIM_PARAMS_NUM_PROFILES
+ */
+#define NET_DIM_PARAMS_NUM_PROFILES 5
+#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256
+#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128
+#define NET_DIM_DEF_PROFILE_CQE 1
+#define NET_DIM_DEF_PROFILE_EQE 1
+
+#define NET_DIM_RX_EQE_PROFILES { \
+       {1,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {8,   NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {64,  NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+       {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \
+}
+
+#define NET_DIM_RX_CQE_PROFILES { \
+       {2,  256},             \
+       {8,  128},             \
+       {16, 64},              \
+       {32, 64},              \
+       {64, 64}               \
+}
+
+#define NET_DIM_TX_EQE_PROFILES { \
+       {1,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {8,   NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {32,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {64,  NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE},  \
+       {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}   \
+}
+
+#define NET_DIM_TX_CQE_PROFILES { \
+       {5,  128},  \
+       {8,  64},  \
+       {16, 32},  \
+       {32, 32},  \
+       {64, 32}   \
+}
+
+static const struct dim_cq_moder
+rx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+       NET_DIM_RX_EQE_PROFILES,
+       NET_DIM_RX_CQE_PROFILES,
+};
+
+static const struct dim_cq_moder
+tx_profile[DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = {
+       NET_DIM_TX_EQE_PROFILES,
+       NET_DIM_TX_CQE_PROFILES,
+};
+
 struct dim_cq_moder
 net_dim_get_rx_moderation(u8 cq_period_mode, int ix)
 {
index 1334ede667a82aa1d5701526836c7f54487e9996..738065f765abd4dda88a9f762736f9a1108cb6fd 100644 (file)
@@ -644,30 +644,40 @@ release:
  *         available
  * never: never stall for any thp allocation
  */
-static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma)
+static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma, unsigned long addr)
 {
        const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
+       gfp_t this_node = 0;
+
+#ifdef CONFIG_NUMA
+       struct mempolicy *pol;
+       /*
+        * __GFP_THISNODE is used only when __GFP_DIRECT_RECLAIM is not
+        * specified, to express a general desire to stay on the current
+        * node for optimistic allocation attempts. If the defrag mode
+        * and/or madvise hint requires the direct reclaim then we prefer
+        * to fallback to other node rather than node reclaim because that
+        * can lead to excessive reclaim even though there is free memory
+        * on other nodes. We expect that NUMA preferences are specified
+        * by memory policies.
+        */
+       pol = get_vma_policy(vma, addr);
+       if (pol->mode != MPOL_BIND)
+               this_node = __GFP_THISNODE;
+       mpol_cond_put(pol);
+#endif
 
-       /* Always do synchronous compaction */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
                return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
-
-       /* Kick kcompactd and fail quickly */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
-
-       /* Synchronous compaction if madvised, otherwise kick kcompactd */
+               return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM | this_node;
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT |
-                       (vma_madvised ? __GFP_DIRECT_RECLAIM :
-                                       __GFP_KSWAPD_RECLAIM);
-
-       /* Only do synchronous compaction if madvised */
+               return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+                                                            __GFP_KSWAPD_RECLAIM | this_node);
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT |
-                      (vma_madvised ? __GFP_DIRECT_RECLAIM : 0);
-
-       return GFP_TRANSHUGE_LIGHT;
+               return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
+                                                            this_node);
+       return GFP_TRANSHUGE_LIGHT | this_node;
 }
 
 /* Caller must hold page table lock. */
@@ -739,8 +749,8 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
                        pte_free(vma->vm_mm, pgtable);
                return ret;
        }
-       gfp = alloc_hugepage_direct_gfpmask(vma);
-       page = alloc_hugepage_vma(gfp, vma, haddr, HPAGE_PMD_ORDER);
+       gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
+       page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, vma, haddr, numa_node_id());
        if (unlikely(!page)) {
                count_vm_event(THP_FAULT_FALLBACK);
                return VM_FAULT_FALLBACK;
@@ -1347,8 +1357,9 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
 alloc:
        if (__transparent_hugepage_enabled(vma) &&
            !transparent_hugepage_debug_cow()) {
-               huge_gfp = alloc_hugepage_direct_gfpmask(vma);
-               new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER);
+               huge_gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
+               new_page = alloc_pages_vma(huge_gfp, HPAGE_PMD_ORDER, vma,
+                               haddr, numa_node_id());
        } else
                new_page = NULL;
 
index ede7e7f5d1ab2fec113507b5dabe78a7cdad8256..6d7296dd11b83503a511986814ba5d1f2a84b26b 100644 (file)
@@ -3856,6 +3856,25 @@ retry:
 
                page = alloc_huge_page(vma, haddr, 0);
                if (IS_ERR(page)) {
+                       /*
+                        * Returning error will result in faulting task being
+                        * sent SIGBUS.  The hugetlb fault mutex prevents two
+                        * tasks from racing to fault in the same page which
+                        * could result in false unable to allocate errors.
+                        * Page migration does not take the fault mutex, but
+                        * does a clear then write of pte's under page table
+                        * lock.  Page fault code could race with migration,
+                        * notice the clear pte and try to allocate a page
+                        * here.  Before returning error, get ptl and make
+                        * sure there really is no pte entry.
+                        */
+                       ptl = huge_pte_lock(h, mm, ptep);
+                       if (!huge_pte_none(huge_ptep_get(ptep))) {
+                               ret = 0;
+                               spin_unlock(ptl);
+                               goto out;
+                       }
+                       spin_unlock(ptl);
                        ret = vmf_error(PTR_ERR(page));
                        goto out;
                }
index 6e9e8cca663e477d328584ac3142d8234d8e3e05..f6e602918dac84a96fe16a8e2c202505256bcb8d 100644 (file)
@@ -1966,6 +1966,7 @@ static void kmemleak_disable(void)
 
        /* stop any memory operation tracing */
        kmemleak_enabled = 0;
+       kmemleak_early_log = 0;
 
        /* check whether it is too early for a kernel thread */
        if (kmemleak_initialized)
@@ -2009,7 +2010,6 @@ void __init kmemleak_init(void)
 
 #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
        if (!kmemleak_skip_disable) {
-               kmemleak_early_log = 0;
                kmemleak_disable();
                return;
        }
index cdbb7a84cb6e186242afeebb32f4c5c7fb2d0639..6f5c0c517c497dbddad9016ef2d1993e4e1bcf05 100644 (file)
@@ -768,6 +768,26 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
        __this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
 }
 
+void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
+{
+       struct page *page = virt_to_head_page(p);
+       pg_data_t *pgdat = page_pgdat(page);
+       struct mem_cgroup *memcg;
+       struct lruvec *lruvec;
+
+       rcu_read_lock();
+       memcg = memcg_from_slab_page(page);
+
+       /* Untracked pages have no memcg, no lruvec. Update only the node */
+       if (!memcg || memcg == root_mem_cgroup) {
+               __mod_node_page_state(pgdat, idx, val);
+       } else {
+               lruvec = mem_cgroup_lruvec(pgdat, memcg);
+               __mod_lruvec_state(lruvec, idx, val);
+       }
+       rcu_read_unlock();
+}
+
 /**
  * __count_memcg_events - account VM events in a cgroup
  * @memcg: the memory cgroup
@@ -1130,26 +1150,45 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
                css_put(&prev->css);
 }
 
-static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+static void __invalidate_reclaim_iterators(struct mem_cgroup *from,
+                                       struct mem_cgroup *dead_memcg)
 {
-       struct mem_cgroup *memcg = dead_memcg;
        struct mem_cgroup_reclaim_iter *iter;
        struct mem_cgroup_per_node *mz;
        int nid;
        int i;
 
-       for (; memcg; memcg = parent_mem_cgroup(memcg)) {
-               for_each_node(nid) {
-                       mz = mem_cgroup_nodeinfo(memcg, nid);
-                       for (i = 0; i <= DEF_PRIORITY; i++) {
-                               iter = &mz->iter[i];
-                               cmpxchg(&iter->position,
-                                       dead_memcg, NULL);
-                       }
+       for_each_node(nid) {
+               mz = mem_cgroup_nodeinfo(from, nid);
+               for (i = 0; i <= DEF_PRIORITY; i++) {
+                       iter = &mz->iter[i];
+                       cmpxchg(&iter->position,
+                               dead_memcg, NULL);
                }
        }
 }
 
+static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+{
+       struct mem_cgroup *memcg = dead_memcg;
+       struct mem_cgroup *last;
+
+       do {
+               __invalidate_reclaim_iterators(memcg, dead_memcg);
+               last = memcg;
+       } while ((memcg = parent_mem_cgroup(memcg)));
+
+       /*
+        * When cgruop1 non-hierarchy mode is used,
+        * parent_mem_cgroup() does not walk all the way up to the
+        * cgroup root (root_mem_cgroup). So we have to handle
+        * dead_memcg from cgroup root separately.
+        */
+       if (last != root_mem_cgroup)
+               __invalidate_reclaim_iterators(root_mem_cgroup,
+                                               dead_memcg);
+}
+
 /**
  * mem_cgroup_scan_tasks - iterate over tasks of a memory cgroup hierarchy
  * @memcg: hierarchy root
index f48693f75b37a0ece6ba8bf9c7ebb9a25ce3a7fd..65e0874fce1736a65f8ced74f2a94d3e23d718c9 100644 (file)
@@ -403,7 +403,7 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = {
        },
 };
 
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
                                unsigned long flags);
 
 struct queue_pages {
@@ -429,11 +429,14 @@ static inline bool queue_pages_required(struct page *page,
 }
 
 /*
- * queue_pages_pmd() has three possible return values:
- * 1 - pages are placed on the right node or queued successfully.
- * 0 - THP was split.
- * -EIO - is migration entry or MPOL_MF_STRICT was specified and an existing
- *        page was already on a node that does not follow the policy.
+ * queue_pages_pmd() has four possible return values:
+ * 0 - pages are placed on the right node or queued successfully.
+ * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ *     specified.
+ * 2 - THP was split.
+ * -EIO - is migration entry or only MPOL_MF_STRICT was specified and an
+ *        existing page was already on a node that does not follow the
+ *        policy.
  */
 static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
                                unsigned long end, struct mm_walk *walk)
@@ -451,23 +454,20 @@ static int queue_pages_pmd(pmd_t *pmd, spinlock_t *ptl, unsigned long addr,
        if (is_huge_zero_page(page)) {
                spin_unlock(ptl);
                __split_huge_pmd(walk->vma, pmd, addr, false, NULL);
+               ret = 2;
                goto out;
        }
-       if (!queue_pages_required(page, qp)) {
-               ret = 1;
+       if (!queue_pages_required(page, qp))
                goto unlock;
-       }
 
-       ret = 1;
        flags = qp->flags;
        /* go to thp migration */
        if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-               if (!vma_migratable(walk->vma)) {
-                       ret = -EIO;
+               if (!vma_migratable(walk->vma) ||
+                   migrate_page_add(page, qp->pagelist, flags)) {
+                       ret = 1;
                        goto unlock;
                }
-
-               migrate_page_add(page, qp->pagelist, flags);
        } else
                ret = -EIO;
 unlock:
@@ -479,6 +479,13 @@ out:
 /*
  * Scan through pages checking if pages follow certain conditions,
  * and move them to the pagelist if they do.
+ *
+ * queue_pages_pte_range() has three possible return values:
+ * 0 - pages are placed on the right node or queued successfully.
+ * 1 - there is unmovable page, and MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ *     specified.
+ * -EIO - only MPOL_MF_STRICT was specified and an existing page was already
+ *        on a node that does not follow the policy.
  */
 static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
                        unsigned long end, struct mm_walk *walk)
@@ -488,17 +495,17 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
        struct queue_pages *qp = walk->private;
        unsigned long flags = qp->flags;
        int ret;
+       bool has_unmovable = false;
        pte_t *pte;
        spinlock_t *ptl;
 
        ptl = pmd_trans_huge_lock(pmd, vma);
        if (ptl) {
                ret = queue_pages_pmd(pmd, ptl, addr, end, walk);
-               if (ret > 0)
-                       return 0;
-               else if (ret < 0)
+               if (ret != 2)
                        return ret;
        }
+       /* THP was split, fall through to pte walk */
 
        if (pmd_trans_unstable(pmd))
                return 0;
@@ -519,14 +526,28 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
                if (!queue_pages_required(page, qp))
                        continue;
                if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-                       if (!vma_migratable(vma))
+                       /* MPOL_MF_STRICT must be specified if we get here */
+                       if (!vma_migratable(vma)) {
+                               has_unmovable = true;
                                break;
-                       migrate_page_add(page, qp->pagelist, flags);
+                       }
+
+                       /*
+                        * Do not abort immediately since there may be
+                        * temporary off LRU pages in the range.  Still
+                        * need migrate other LRU pages.
+                        */
+                       if (migrate_page_add(page, qp->pagelist, flags))
+                               has_unmovable = true;
                } else
                        break;
        }
        pte_unmap_unlock(pte - 1, ptl);
        cond_resched();
+
+       if (has_unmovable)
+               return 1;
+
        return addr != end ? -EIO : 0;
 }
 
@@ -639,7 +660,13 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
  *
  * If pages found in a given range are on a set of nodes (determined by
  * @nodes and @flags,) it's isolated and queued to the pagelist which is
- * passed via @private.)
+ * passed via @private.
+ *
+ * queue_pages_range() has three possible return values:
+ * 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
+ *     specified.
+ * 0 - queue pages successfully or no misplaced page.
+ * -EIO - there is misplaced page and only MPOL_MF_STRICT was specified.
  */
 static int
 queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
@@ -940,7 +967,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
 /*
  * page migration, thp tail pages can be passed.
  */
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
                                unsigned long flags)
 {
        struct page *head = compound_head(page);
@@ -953,8 +980,19 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
                        mod_node_page_state(page_pgdat(head),
                                NR_ISOLATED_ANON + page_is_file_cache(head),
                                hpage_nr_pages(head));
+               } else if (flags & MPOL_MF_STRICT) {
+                       /*
+                        * Non-movable page may reach here.  And, there may be
+                        * temporary off LRU pages or non-LRU movable pages.
+                        * Treat them as unmovable pages since they can't be
+                        * isolated, so they can't be moved at the moment.  It
+                        * should return -EIO for this case too.
+                        */
+                       return -EIO;
                }
        }
+
+       return 0;
 }
 
 /* page allocation callback for NUMA node migration */
@@ -1142,8 +1180,8 @@ static struct page *new_page(struct page *page, unsigned long start)
        } else if (PageTransHuge(page)) {
                struct page *thp;
 
-               thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
-                                        HPAGE_PMD_ORDER);
+               thp = alloc_pages_vma(GFP_TRANSHUGE, HPAGE_PMD_ORDER, vma,
+                               address, numa_node_id());
                if (!thp)
                        return NULL;
                prep_transhuge_page(thp);
@@ -1157,9 +1195,10 @@ static struct page *new_page(struct page *page, unsigned long start)
 }
 #else
 
-static void migrate_page_add(struct page *page, struct list_head *pagelist,
+static int migrate_page_add(struct page *page, struct list_head *pagelist,
                                unsigned long flags)
 {
+       return -EIO;
 }
 
 int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
@@ -1182,6 +1221,7 @@ static long do_mbind(unsigned long start, unsigned long len,
        struct mempolicy *new;
        unsigned long end;
        int err;
+       int ret;
        LIST_HEAD(pagelist);
 
        if (flags & ~(unsigned long)MPOL_MF_VALID)
@@ -1243,10 +1283,15 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (err)
                goto mpol_out;
 
-       err = queue_pages_range(mm, start, end, nmask,
+       ret = queue_pages_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
-       if (!err)
-               err = mbind_range(mm, start, end, new);
+
+       if (ret < 0) {
+               err = -EIO;
+               goto up_out;
+       }
+
+       err = mbind_range(mm, start, end, new);
 
        if (!err) {
                int nr_failed = 0;
@@ -1259,13 +1304,14 @@ static long do_mbind(unsigned long start, unsigned long len,
                                putback_movable_pages(&pagelist);
                }
 
-               if (nr_failed && (flags & MPOL_MF_STRICT))
+               if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT)))
                        err = -EIO;
        } else
                putback_movable_pages(&pagelist);
 
+up_out:
        up_write(&mm->mmap_sem);
- mpol_out:
+mpol_out:
        mpol_put(new);
        return err;
 }
@@ -1688,7 +1734,7 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
  * freeing by another task.  It is the caller's responsibility to free the
  * extra reference for shared policies.
  */
-static struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
                                                unsigned long addr)
 {
        struct mempolicy *pol = __get_vma_policy(vma, addr);
@@ -2037,7 +2083,6 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
  *     @vma:  Pointer to VMA or NULL if not available.
  *     @addr: Virtual Address of the allocation. Must be inside the VMA.
  *     @node: Which node to prefer for allocation (modulo policy).
- *     @hugepage: for hugepages try only the preferred node if possible
  *
  *     This function allocates a page from the kernel page pool and applies
  *     a NUMA policy associated with the VMA or the current process.
@@ -2048,7 +2093,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
  */
 struct page *
 alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
-               unsigned long addr, int node, bool hugepage)
+               unsigned long addr, int node)
 {
        struct mempolicy *pol;
        struct page *page;
@@ -2066,31 +2111,6 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
                goto out;
        }
 
-       if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
-               int hpage_node = node;
-
-               /*
-                * For hugepage allocation and non-interleave policy which
-                * allows the current node (or other explicitly preferred
-                * node) we only try to allocate from the current/preferred
-                * node and don't fall back to other nodes, as the cost of
-                * remote accesses would likely offset THP benefits.
-                *
-                * If the policy is interleave, or does not allow the current
-                * node in its nodemask, we allocate the standard way.
-                */
-               if (pol->mode == MPOL_PREFERRED && !(pol->flags & MPOL_F_LOCAL))
-                       hpage_node = pol->v.preferred_node;
-
-               nmask = policy_nodemask(gfp, pol);
-               if (!nmask || node_isset(hpage_node, *nmask)) {
-                       mpol_cond_put(pol);
-                       page = __alloc_pages_node(hpage_node,
-                                               gfp | __GFP_THISNODE, order);
-                       goto out;
-               }
-       }
-
        nmask = policy_nodemask(gfp, pol);
        preferred_nid = policy_node(gfp, pol, node);
        page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask);
index 6ee03a816d67a889729e834b8c614675ac4cf94c..ed70c4e8e52a505f431fdeefaf209694a4b03093 100644 (file)
@@ -91,6 +91,12 @@ static void dev_pagemap_cleanup(struct dev_pagemap *pgmap)
                wait_for_completion(&pgmap->done);
                percpu_ref_exit(pgmap->ref);
        }
+       /*
+        * Undo the pgmap ref assignment for the internal case as the
+        * caller may re-enable the same pgmap.
+        */
+       if (pgmap->ref == &pgmap->internal_ref)
+               pgmap->ref = NULL;
 }
 
 static void devm_memremap_pages_release(void *data)
@@ -397,6 +403,30 @@ void __put_devmap_managed_page(struct page *page)
 
                mem_cgroup_uncharge(page);
 
+               /*
+                * When a device_private page is freed, the page->mapping field
+                * may still contain a (stale) mapping value. For example, the
+                * lower bits of page->mapping may still identify the page as
+                * an anonymous page. Ultimately, this entire field is just
+                * stale and wrong, and it will cause errors if not cleared.
+                * One example is:
+                *
+                *  migrate_vma_pages()
+                *    migrate_vma_insert_page()
+                *      page_add_new_anon_rmap()
+                *        __page_set_anon_rmap()
+                *          ...checks page->mapping, via PageAnon(page) call,
+                *            and incorrectly concludes that the page is an
+                *            anonymous page. Therefore, it incorrectly,
+                *            silently fails to set up the new anon rmap.
+                *
+                * For other types of ZONE_DEVICE pages, migration is either
+                * handled differently or not done at all, so there is no need
+                * to clear page->mapping.
+                */
+               if (is_device_private_page(page))
+                       page->mapping = NULL;
+
                page->pgmap->ops->page_free(page);
        } else if (!count)
                __put_page(page);
index e5dfe2ae6b0d5dfc4a0b38c58c8e2c762b0b7696..003377e2423232614525ae2e6cbdda9695aca75b 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1475,7 +1475,15 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                        /*
                         * No need to invalidate here it will synchronize on
                         * against the special swap migration pte.
+                        *
+                        * The assignment to subpage above was computed from a
+                        * swap PTE which results in an invalid pointer.
+                        * Since only PAGE_SIZE pages can currently be
+                        * migrated, just set it to page. This will need to be
+                        * changed when hugepage migrations to device private
+                        * memory are supported.
                         */
+                       subpage = page;
                        goto discard;
                }
 
index 626d8c74b973f173d3062ee118580b649d35073a..2bed4761f2795695b2e970c304f8985aeacef9f6 100644 (file)
@@ -1466,7 +1466,7 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
 
        shmem_pseudo_vma_init(&pvma, info, hindex);
        page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN,
-                       HPAGE_PMD_ORDER, &pvma, 0, numa_node_id(), true);
+                       HPAGE_PMD_ORDER, &pvma, 0, numa_node_id());
        shmem_pseudo_vma_destroy(&pvma);
        if (page)
                prep_transhuge_page(page);
index 2a09796edef8d53d257dedada5b1a40bc21b4c16..98e924864554c5dbbd4804f51af20639eb413694 100644 (file)
@@ -147,7 +147,7 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n,
                                       bool to_user)
 {
        /* Reject if object wraps past end of memory. */
-       if (ptr + n < ptr)
+       if (ptr + (n - 1) < ptr)
                usercopy_abort("wrapped address", NULL, to_user, 0, ptr + n);
 
        /* Reject if NULL or ZERO-allocation. */
index e0fc963acc41eb33c843886cab669844abc6b16b..7ba11e12a11f33b38a007a038bbfc7dee2fe48b3 100644 (file)
@@ -3278,10 +3278,20 @@ retry:
                if (va == NULL)
                        goto overflow;
 
+               /*
+                * If required width exeeds current VA block, move
+                * base downwards and then recheck.
+                */
+               if (base + end > va->va_end) {
+                       base = pvm_determine_end_from_reverse(&va, align) - end;
+                       term_area = area;
+                       continue;
+               }
+
                /*
                 * If this VA does not fit, move base downwards and recheck.
                 */
-               if (base + start < va->va_start || base + end > va->va_end) {
+               if (base + start < va->va_start) {
                        va = node_to_va(rb_prev(&va->rb_node));
                        base = pvm_determine_end_from_reverse(&va, align) - end;
                        term_area = area;
index dbdc46a84f63089de614a2807ef62a70f7c14968..c77d1e3761a7f191f5e274b281a9ca132b64fc6f 100644 (file)
@@ -88,9 +88,6 @@ struct scan_control {
        /* Can pages be swapped as part of reclaim? */
        unsigned int may_swap:1;
 
-       /* e.g. boosted watermark reclaim leaves slabs alone */
-       unsigned int may_shrinkslab:1;
-
        /*
         * Cgroups are not reclaimed below their configured memory.low,
         * unless we threaten to OOM. If any cgroups are skipped due to
@@ -2714,10 +2711,8 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc)
                        shrink_node_memcg(pgdat, memcg, sc, &lru_pages);
                        node_lru_pages += lru_pages;
 
-                       if (sc->may_shrinkslab) {
-                               shrink_slab(sc->gfp_mask, pgdat->node_id,
-                                   memcg, sc->priority);
-                       }
+                       shrink_slab(sc->gfp_mask, pgdat->node_id, memcg,
+                                       sc->priority);
 
                        /* Record the group's reclaim efficiency */
                        vmpressure(sc->gfp_mask, memcg, false,
@@ -3194,7 +3189,6 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = 1,
-               .may_shrinkslab = 1,
        };
 
        /*
@@ -3238,7 +3232,6 @@ unsigned long mem_cgroup_shrink_node(struct mem_cgroup *memcg,
                .may_unmap = 1,
                .reclaim_idx = MAX_NR_ZONES - 1,
                .may_swap = !noswap,
-               .may_shrinkslab = 1,
        };
        unsigned long lru_pages;
 
@@ -3286,7 +3279,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                .may_writepage = !laptop_mode,
                .may_unmap = 1,
                .may_swap = may_swap,
-               .may_shrinkslab = 1,
        };
 
        set_task_reclaim_state(current, &sc.reclaim_state);
@@ -3598,7 +3590,6 @@ restart:
                 */
                sc.may_writepage = !laptop_mode && !nr_boost_reclaim;
                sc.may_swap = !nr_boost_reclaim;
-               sc.may_shrinkslab = !nr_boost_reclaim;
 
                /*
                 * Do some background aging of the anon list, to give
index e0b4edcb88c8c63dd307b0648ad34e3a27ce0ee8..c963831d354f8058447888c049c41178fe9a4d55 100644 (file)
@@ -380,14 +380,12 @@ void workingset_update_node(struct xa_node *node)
        if (node->count && node->count == node->nr_values) {
                if (list_empty(&node->private_list)) {
                        list_lru_add(&shadow_nodes, &node->private_list);
-                       __inc_lruvec_page_state(virt_to_page(node),
-                                               WORKINGSET_NODES);
+                       __inc_lruvec_slab_state(node, WORKINGSET_NODES);
                }
        } else {
                if (!list_empty(&node->private_list)) {
                        list_lru_del(&shadow_nodes, &node->private_list);
-                       __dec_lruvec_page_state(virt_to_page(node),
-                                               WORKINGSET_NODES);
+                       __dec_lruvec_slab_state(node, WORKINGSET_NODES);
                }
        }
 }
@@ -480,7 +478,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
        }
 
        list_lru_isolate(lru, item);
-       __dec_lruvec_page_state(virt_to_page(node), WORKINGSET_NODES);
+       __dec_lruvec_slab_state(node, WORKINGSET_NODES);
 
        spin_unlock(lru_lock);
 
@@ -503,7 +501,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
         * shadow entries we were tracking ...
         */
        xas_store(&xas, NULL);
-       __inc_lruvec_page_state(virt_to_page(node), WORKINGSET_NODERECLAIM);
+       __inc_lruvec_slab_state(node, WORKINGSET_NODERECLAIM);
 
 out_invalid:
        xa_unlock_irq(&mapping->i_pages);
index 1a029a7432ee56635f9dcde8f4c5ad2b1e2984ed..ed19d98c9dcd1641c5e66d27d586e93f43fadce1 100644 (file)
@@ -817,9 +817,19 @@ out:
 static void z3fold_destroy_pool(struct z3fold_pool *pool)
 {
        kmem_cache_destroy(pool->c_handle);
-       z3fold_unregister_migration(pool);
-       destroy_workqueue(pool->release_wq);
+
+       /*
+        * We need to destroy pool->compact_wq before pool->release_wq,
+        * as any pending work on pool->compact_wq will call
+        * queue_work(pool->release_wq, &pool->work).
+        *
+        * There are still outstanding pages until both workqueues are drained,
+        * so we cannot unregister migration until then.
+        */
+
        destroy_workqueue(pool->compact_wq);
+       destroy_workqueue(pool->release_wq);
+       z3fold_unregister_migration(pool);
        kfree(pool);
 }
 
index 67d7f83009ae1e0c1fc8e9e694d3d33a9f93d7d5..1d5bdf3a4b65526c7c4b90283d97366e10ba19c3 100644 (file)
@@ -2303,7 +2303,7 @@ __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
 
        while (bucket_tmp < hash->size) {
                if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
-                                                  *bucket, &idx_tmp))
+                                                  bucket_tmp, &idx_tmp))
                        break;
 
                bucket_tmp++;
@@ -2420,8 +2420,10 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
        batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
        batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
        batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
-       batadv_mcast_want_rtr4_update(bat_priv, orig, BATADV_NO_FLAGS);
-       batadv_mcast_want_rtr6_update(bat_priv, orig, BATADV_NO_FLAGS);
+       batadv_mcast_want_rtr4_update(bat_priv, orig,
+                                     BATADV_MCAST_WANT_NO_RTR4);
+       batadv_mcast_want_rtr6_update(bat_priv, orig,
+                                     BATADV_MCAST_WANT_NO_RTR6);
 
        spin_unlock_bh(&orig->mcast_handler_lock);
 }
index b9585e7d9d2e9492b0d495ae58b8da9029bce6b7..04bc79359a1736b28e83f0eb88828ceefd430f25 100644 (file)
@@ -3202,6 +3202,7 @@ struct hci_dev *hci_alloc_dev(void)
        hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
        hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
        hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
+       hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE;
 
        mutex_init(&hdev->lock);
        mutex_init(&hdev->req_lock);
index bb67f4a5479a2c79d724956c883d80e2a0c93345..402e2cc54044acc3ec7243915a177affdb004c14 100644 (file)
@@ -433,6 +433,35 @@ static int auto_accept_delay_set(void *data, u64 val)
        return 0;
 }
 
+static int min_encrypt_key_size_set(void *data, u64 val)
+{
+       struct hci_dev *hdev = data;
+
+       if (val < 1 || val > 16)
+               return -EINVAL;
+
+       hci_dev_lock(hdev);
+       hdev->min_enc_key_size = val;
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+static int min_encrypt_key_size_get(void *data, u64 *val)
+{
+       struct hci_dev *hdev = data;
+
+       hci_dev_lock(hdev);
+       *val = hdev->min_enc_key_size;
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops,
+                       min_encrypt_key_size_get,
+                       min_encrypt_key_size_set, "%llu\n");
+
 static int auto_accept_delay_get(void *data, u64 *val)
 {
        struct hci_dev *hdev = data;
@@ -545,6 +574,8 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev)
        if (lmp_ssp_capable(hdev)) {
                debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
                                    hdev, &ssp_debug_mode_fops);
+               debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs,
+                                   hdev, &min_encrypt_key_size_fops);
                debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
                                    hdev, &auto_accept_delay_fops);
        }
index 5abd423b55fa9c3839eb37d412c16a8735f901a5..8d889969ae7edaf2acf653098aaae0d98618776b 100644 (file)
@@ -101,6 +101,7 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
 {
        struct sk_buff *skb;
        struct sock *sk = sock->sk;
+       int ret;
 
        BT_DBG("session %p data %p size %d", session, data, size);
 
@@ -114,13 +115,17 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock,
        }
 
        skb_put_u8(skb, hdr);
-       if (data && size > 0)
+       if (data && size > 0) {
                skb_put_data(skb, data, size);
+               ret = size;
+       } else {
+               ret = 0;
+       }
 
        skb_queue_tail(transmit, skb);
        wake_up_interruptible(sk_sleep(sk));
 
-       return 0;
+       return ret;
 }
 
 static int hidp_send_ctrl_message(struct hidp_session *session,
index cc506fe99b4d7e092eefd90f9ea41bce9297dfca..dfc1edb168b78b2ed43575cdd6087c45b75a0f82 100644 (file)
@@ -1361,7 +1361,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
         * actually encrypted before enforcing a key size.
         */
        return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
-               hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE);
+               hcon->enc_key_size >= hcon->hdev->min_enc_key_size);
 }
 
 static void l2cap_do_start(struct l2cap_chan *chan)
index d164f63a4345c5667e5190f92900d79d3d8806d8..8a8f9e5f264f2a70b246094fa7c31f1be8c0deef 100644 (file)
@@ -37,12 +37,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
        int err;
 
        if (dev->priv_flags & IFF_EBRIDGE) {
+               err = br_vlan_bridge_event(dev, event, ptr);
+               if (err)
+                       return notifier_from_errno(err);
+
                if (event == NETDEV_REGISTER) {
                        /* register of bridge completed, add sysfs entries */
                        br_sysfs_addbr(dev);
                        return NOTIFY_DONE;
                }
-               br_vlan_bridge_event(dev, event, ptr);
        }
 
        /* not a port of a bridge */
index 3d8deac2353d045964c52981a1eaac96d6f23025..f8cac3702712028ef596ce994c7b872cc4e353d1 100644 (file)
@@ -1388,6 +1388,9 @@ br_multicast_leave_group(struct net_bridge *br,
                        if (!br_port_group_equal(p, port, src))
                                continue;
 
+                       if (p->flags & MDB_PG_FLAGS_PERMANENT)
+                               break;
+
                        rcu_assign_pointer(*pp, p->next);
                        hlist_del_init(&p->mglist);
                        del_timer(&p->timer);
index e8cf03b43b7d6c5225f6be08d285a2cbe0307fa2..646504db0220eaadf112a14a82a56f5223d264fa 100644 (file)
@@ -894,8 +894,8 @@ int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
 void br_vlan_get_stats(const struct net_bridge_vlan *v,
                       struct br_vlan_stats *stats);
 void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
-                         void *ptr);
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
+                        void *ptr);
 
 static inline struct net_bridge_vlan_group *br_vlan_group(
                                        const struct net_bridge *br)
@@ -1085,9 +1085,10 @@ static inline void br_vlan_port_event(struct net_bridge_port *p,
 {
 }
 
-static inline void br_vlan_bridge_event(struct net_device *dev,
-                                       unsigned long event, void *ptr)
+static inline int br_vlan_bridge_event(struct net_device *dev,
+                                      unsigned long event, void *ptr)
 {
+       return 0;
 }
 #endif
 
index 021cc9f66804d6db567d7a139d6e68ab10798665..f5b2aeebbfe98d82a084c78be2747a14ebcbc938 100644 (file)
@@ -1053,7 +1053,6 @@ int br_vlan_init(struct net_bridge *br)
 {
        struct net_bridge_vlan_group *vg;
        int ret = -ENOMEM;
-       bool changed;
 
        vg = kzalloc(sizeof(*vg), GFP_KERNEL);
        if (!vg)
@@ -1068,17 +1067,10 @@ int br_vlan_init(struct net_bridge *br)
        br->vlan_proto = htons(ETH_P_8021Q);
        br->default_pvid = 1;
        rcu_assign_pointer(br->vlgrp, vg);
-       ret = br_vlan_add(br, 1,
-                         BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED |
-                         BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
-       if (ret)
-               goto err_vlan_add;
 
 out:
        return ret;
 
-err_vlan_add:
-       vlan_tunnel_deinit(vg);
 err_tunnel_init:
        rhashtable_destroy(&vg->vlan_hash);
 err_rhtbl:
@@ -1464,13 +1456,23 @@ static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid)
 }
 
 /* Must be protected by RTNL. */
-void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
-                         void *ptr)
+int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr)
 {
        struct netdev_notifier_changeupper_info *info;
-       struct net_bridge *br;
+       struct net_bridge *br = netdev_priv(dev);
+       bool changed;
+       int ret = 0;
 
        switch (event) {
+       case NETDEV_REGISTER:
+               ret = br_vlan_add(br, br->default_pvid,
+                                 BRIDGE_VLAN_INFO_PVID |
+                                 BRIDGE_VLAN_INFO_UNTAGGED |
+                                 BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL);
+               break;
+       case NETDEV_UNREGISTER:
+               br_vlan_delete(br, br->default_pvid);
+               break;
        case NETDEV_CHANGEUPPER:
                info = ptr;
                br_vlan_upper_change(dev, info->upper_dev, info->linking);
@@ -1478,12 +1480,13 @@ void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
 
        case NETDEV_CHANGE:
        case NETDEV_UP:
-               br = netdev_priv(dev);
                if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING))
-                       return;
+                       break;
                br_vlan_link_state_change(dev, br);
                break;
        }
+
+       return ret;
 }
 
 /* Must be protected by RTNL. */
index 963dfdc1482724c07ad95a0fc17750c90cbfc964..c8177a89f52c362e70e4bb617db78bb000613bd8 100644 (file)
@@ -1770,20 +1770,28 @@ static int compat_calc_entry(const struct ebt_entry *e,
        return 0;
 }
 
+static int ebt_compat_init_offsets(unsigned int number)
+{
+       if (number > INT_MAX)
+               return -EINVAL;
+
+       /* also count the base chain policies */
+       number += NF_BR_NUMHOOKS;
+
+       return xt_compat_init_offsets(NFPROTO_BRIDGE, number);
+}
 
 static int compat_table_info(const struct ebt_table_info *info,
                             struct compat_ebt_replace *newinfo)
 {
        unsigned int size = info->entries_size;
        const void *entries = info->entries;
+       int ret;
 
        newinfo->entries_size = size;
-       if (info->nentries) {
-               int ret = xt_compat_init_offsets(NFPROTO_BRIDGE,
-                                                info->nentries);
-               if (ret)
-                       return ret;
-       }
+       ret = ebt_compat_init_offsets(info->nentries);
+       if (ret)
+               return ret;
 
        return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
                                                        entries, newinfo);
@@ -2234,11 +2242,9 @@ static int compat_do_replace(struct net *net, void __user *user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
-       if (tmp.nentries) {
-               ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
-               if (ret < 0)
-                       goto out_unlock;
-       }
+       ret = ebt_compat_init_offsets(tmp.nentries);
+       if (ret < 0)
+               goto out_unlock;
 
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
@@ -2261,8 +2267,10 @@ static int compat_do_replace(struct net *net, void __user *user,
        state.buf_kern_len = size64;
 
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
-       if (WARN_ON(ret < 0))
+       if (WARN_ON(ret < 0)) {
+               vfree(entries_tmp);
                goto out_unlock;
+       }
 
        vfree(entries_tmp);
        tmp.entries_size = size64;
index bed66f536b34535c38e72cd5de4ea0fb6aaf2780..1804e867f7151c77284f15b3681e72728c73cc5b 100644 (file)
@@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
        switch (priv->key) {
        case NFT_META_BRI_IIFNAME:
                br_dev = nft_meta_get_bridge(in);
-               if (!br_dev)
-                       goto err;
                break;
        case NFT_META_BRI_OIFNAME:
                br_dev = nft_meta_get_bridge(out);
-               if (!br_dev)
-                       goto err;
                break;
        case NFT_META_BRI_IIFPVID: {
                u16 p_pvid;
@@ -61,13 +57,11 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
                return;
        }
        default:
-               goto out;
+               return nft_meta_get_eval(expr, regs, pkt);
        }
 
-       strncpy((char *)dest, br_dev->name, IFNAMSIZ);
+       strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ);
        return;
-out:
-       return nft_meta_get_eval(expr, regs, pkt);
 err:
        regs->verdict.code = NFT_BREAK;
 }
index 5275ddf580bc7d64139e323eca15e276357bfdd1..72711053ebe66ce8231fbb79d9c37f682071be64 100644 (file)
@@ -1046,32 +1046,50 @@ static __init int cgw_module_init(void)
        pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
                max_hops);
 
-       register_pernet_subsys(&cangw_pernet_ops);
+       ret = register_pernet_subsys(&cangw_pernet_ops);
+       if (ret)
+               return ret;
+
+       ret = -ENOMEM;
        cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
                                      0, 0, NULL);
-
        if (!cgw_cache)
-               return -ENOMEM;
+               goto out_cache_create;
 
        /* set notifier */
        notifier.notifier_call = cgw_notifier;
-       register_netdevice_notifier(&notifier);
+       ret = register_netdevice_notifier(&notifier);
+       if (ret)
+               goto out_register_notifier;
 
        ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_GETROUTE,
                                   NULL, cgw_dump_jobs, 0);
-       if (ret) {
-               unregister_netdevice_notifier(&notifier);
-               kmem_cache_destroy(cgw_cache);
-               return -ENOBUFS;
-       }
-
-       /* Only the first call to rtnl_register_module can fail */
-       rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE,
-                            cgw_create_job, NULL, 0);
-       rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE,
-                            cgw_remove_job, NULL, 0);
+       if (ret)
+               goto out_rtnl_register1;
+
+       ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE,
+                                  cgw_create_job, NULL, 0);
+       if (ret)
+               goto out_rtnl_register2;
+       ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE,
+                                  cgw_remove_job, NULL, 0);
+       if (ret)
+               goto out_rtnl_register3;
 
        return 0;
+
+out_rtnl_register3:
+       rtnl_unregister(PF_CAN, RTM_NEWROUTE);
+out_rtnl_register2:
+       rtnl_unregister(PF_CAN, RTM_GETROUTE);
+out_rtnl_register1:
+       unregister_netdevice_notifier(&notifier);
+out_register_notifier:
+       kmem_cache_destroy(cgw_cache);
+out_cache_create:
+       unregister_pernet_subsys(&cangw_pernet_ops);
+
+       return ret;
 }
 
 static __exit void cgw_module_exit(void)
index fc676b2610e3c1e7e236b62d4984647bc0e71916..0891f499c1bb7cdb85490a681b21895f2206bcba 100644 (file)
@@ -4374,12 +4374,17 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
 
        act = bpf_prog_run_xdp(xdp_prog, xdp);
 
+       /* check if bpf_xdp_adjust_head was used */
        off = xdp->data - orig_data;
-       if (off > 0)
-               __skb_pull(skb, off);
-       else if (off < 0)
-               __skb_push(skb, -off);
-       skb->mac_header += off;
+       if (off) {
+               if (off > 0)
+                       __skb_pull(skb, off);
+               else if (off < 0)
+                       __skb_push(skb, -off);
+
+               skb->mac_header += off;
+               skb_reset_network_header(skb);
+       }
 
        /* check if bpf_xdp_adjust_tail was used. it can only "shrink"
         * pckt.
@@ -9701,6 +9706,8 @@ static void __net_exit default_device_exit(struct net *net)
 
                /* Push remaining network devices to init_net */
                snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex);
+               if (__dev_get_by_name(&init_net, fb_name))
+                       snprintf(fb_name, IFNAMSIZ, "dev%%d");
                err = dev_change_net_namespace(dev, &init_net, fb_name);
                if (err) {
                        pr_emerg("%s: failed to move %s to init_net: %d\n",
index 4e2a79b2fd77f36ba2a31e9e43af1abc1207766e..7878f918b8c057b7b90ca0afcf2d5773cfb55e15 100644 (file)
@@ -7455,12 +7455,12 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct __sk_buff, gso_segs):
                /* si->dst_reg = skb_shinfo(SKB); */
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
-               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
-                                     si->dst_reg, si->src_reg,
-                                     offsetof(struct sk_buff, head));
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
                                      BPF_REG_AX, si->src_reg,
                                      offsetof(struct sk_buff, end));
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct sk_buff, head));
                *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
 #else
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
index 93bffaad21354d4a255a973d03bc7bcdf9477432..6832eeb4b785464f873d073f5cd3b41fdf956034 100644 (file)
@@ -585,12 +585,12 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy);
 
 void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
 {
-       rcu_assign_sk_user_data(sk, NULL);
        sk_psock_cork_free(psock);
        sk_psock_zap_ingress(psock);
-       sk_psock_restore_proto(sk, psock);
 
        write_lock_bh(&sk->sk_callback_lock);
+       sk_psock_restore_proto(sk, psock);
+       rcu_assign_sk_user_data(sk, NULL);
        if (psock->progs.skb_parser)
                sk_psock_stop_strp(sk, psock);
        write_unlock_bh(&sk->sk_callback_lock);
index d57b0cc995a0cea45d82bf73d8149aae9f7b2e17..6d08553f885cdb44ed3e53c2231abb7f48bf309c 100644 (file)
@@ -1992,6 +1992,19 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
 }
 EXPORT_SYMBOL(skb_set_owner_w);
 
+static bool can_skb_orphan_partial(const struct sk_buff *skb)
+{
+#ifdef CONFIG_TLS_DEVICE
+       /* Drivers depend on in-order delivery for crypto offload,
+        * partial orphan breaks out-of-order-OK logic.
+        */
+       if (skb->decrypted)
+               return false;
+#endif
+       return (skb->destructor == sock_wfree ||
+               (IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree));
+}
+
 /* This helper is used by netem, as it can hold packets in its
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
@@ -2003,11 +2016,7 @@ void skb_orphan_partial(struct sk_buff *skb)
        if (skb_is_tcp_pure_ack(skb))
                return;
 
-       if (skb->destructor == sock_wfree
-#ifdef CONFIG_INET
-           || skb->destructor == tcp_wfree
-#endif
-               ) {
+       if (can_skb_orphan_partial(skb)) {
                struct sock *sk = skb->sk;
 
                if (refcount_inc_not_zero(&sk->sk_refcnt)) {
index 3312a5849a974e372a49164abca8f7067a2ed7e7..c13ffbd33d8d6ad4f591571325aaee321df5b242 100644 (file)
@@ -19,6 +19,7 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
 static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
 static DEFINE_MUTEX(sock_diag_table_mutex);
 static struct workqueue_struct *broadcast_wq;
+static atomic64_t cookie_gen;
 
 u64 sock_gen_cookie(struct sock *sk)
 {
@@ -27,7 +28,7 @@ u64 sock_gen_cookie(struct sock *sk)
 
                if (res)
                        return res;
-               res = atomic64_inc_return(&sock_net(sk)->cookie_gen);
+               res = atomic64_inc_return(&cookie_gen);
                atomic64_cmpxchg(&sk->sk_cookie, 0, res);
        }
 }
index 52d4faeee18b0cecc8432ee71db16efb852b8644..1330a7442e5b1e54d80d0b675f7356742bcdfbec 100644 (file)
@@ -247,6 +247,8 @@ static void sock_map_free(struct bpf_map *map)
        raw_spin_unlock_bh(&stab->lock);
        rcu_read_unlock();
 
+       synchronize_rcu();
+
        bpf_map_area_free(stab->sks);
        kfree(stab);
 }
@@ -276,16 +278,20 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
                             struct sock **psk)
 {
        struct sock *sk;
+       int err = 0;
 
        raw_spin_lock_bh(&stab->lock);
        sk = *psk;
        if (!sk_test || sk_test == sk)
-               *psk = NULL;
+               sk = xchg(psk, NULL);
+
+       if (likely(sk))
+               sock_map_unref(sk, psk);
+       else
+               err = -EINVAL;
+
        raw_spin_unlock_bh(&stab->lock);
-       if (unlikely(!sk))
-               return -EINVAL;
-       sock_map_unref(sk, psk);
-       return 0;
+       return err;
 }
 
 static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk,
@@ -328,6 +334,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
                                  struct sock *sk, u64 flags)
 {
        struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
+       struct inet_connection_sock *icsk = inet_csk(sk);
        struct sk_psock_link *link;
        struct sk_psock *psock;
        struct sock *osk;
@@ -338,6 +345,8 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
                return -EINVAL;
        if (unlikely(idx >= map->max_entries))
                return -E2BIG;
+       if (unlikely(icsk->icsk_ulp_data))
+               return -EINVAL;
 
        link = sk_psock_init_link();
        if (!link)
index 4ec5b7f85d51ea2274b69e0ae68fa824fac2edde..09d9286b27ccb9fb215f3bafb0511d49dfaa1062 100644 (file)
@@ -153,6 +153,9 @@ static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
 {
        int port;
 
+       if (!ds->ops->port_mdb_add)
+               return;
+
        for_each_set_bit(port, bitmap, ds->num_ports)
                ds->ops->port_mdb_add(ds, port, mdb);
 }
index 26363d72d25b35377bf844466b10e2844cbb70f6..47ee88163a9daede6494af72025d2f86974d167b 100644 (file)
@@ -165,6 +165,7 @@ static struct sk_buff
                                            "Expected meta frame, is %12llx "
                                            "in the DSA master multicast filter?\n",
                                            SJA1105_META_DMAC);
+                       kfree_skb(sp->data->stampable_skb);
                }
 
                /* Hold a reference to avoid dsa_switch_rcv
@@ -211,17 +212,8 @@ static struct sk_buff
                 * for further processing up the network stack.
                 */
                kfree_skb(skb);
-
-               skb = skb_copy(stampable_skb, GFP_ATOMIC);
-               if (!skb) {
-                       dev_err_ratelimited(dp->ds->dev,
-                                           "Failed to copy stampable skb\n");
-                       spin_unlock(&sp->data->meta_lock);
-                       return NULL;
-               }
+               skb = stampable_skb;
                sja1105_transfer_meta(skb, meta);
-               /* The cached copy will be freed now */
-               skb_unref(stampable_skb);
 
                spin_unlock(&sp->data->meta_lock);
        }
index e4aba5d485be6a59c639a23b75172f5015c4280f..bbe9b3b2d3959fef28d1d94a0bcc0a71077d607d 100644 (file)
@@ -170,7 +170,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *skb,
        reasm_data = inet_frag_reasm_prepare(&fq->q, skb, prev_tail);
        if (!reasm_data)
                goto out_oom;
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
 
        skb->dev = ldev;
        skb->tstamp = fq->q.stamp;
index d666756be5f18404ce8e85a95e9f09636d5f2694..10d31733297d7358b55b45d64bc447039365df1d 100644 (file)
@@ -331,7 +331,7 @@ struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key)
        prev = rhashtable_lookup(&fqdir->rhashtable, key, fqdir->f->rhash_params);
        if (!prev)
                fq = inet_frag_create(fqdir, key, &prev);
-       if (prev && !IS_ERR(prev)) {
+       if (!IS_ERR_OR_NULL(prev)) {
                fq = prev;
                if (!refcount_inc_not_zero(&fq->refcnt))
                        fq = NULL;
@@ -475,11 +475,12 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
 EXPORT_SYMBOL(inet_frag_reasm_prepare);
 
 void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
-                           void *reasm_data)
+                           void *reasm_data, bool try_coalesce)
 {
        struct sk_buff **nextp = (struct sk_buff **)reasm_data;
        struct rb_node *rbn;
        struct sk_buff *fp;
+       int sum_truesize;
 
        skb_push(head, head->data - skb_network_header(head));
 
@@ -487,25 +488,41 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
        fp = FRAG_CB(head)->next_frag;
        rbn = rb_next(&head->rbnode);
        rb_erase(&head->rbnode, &q->rb_fragments);
+
+       sum_truesize = head->truesize;
        while (rbn || fp) {
                /* fp points to the next sk_buff in the current run;
                 * rbn points to the next run.
                 */
                /* Go through the current run. */
                while (fp) {
-                       *nextp = fp;
-                       nextp = &fp->next;
-                       fp->prev = NULL;
-                       memset(&fp->rbnode, 0, sizeof(fp->rbnode));
-                       fp->sk = NULL;
-                       head->data_len += fp->len;
-                       head->len += fp->len;
+                       struct sk_buff *next_frag = FRAG_CB(fp)->next_frag;
+                       bool stolen;
+                       int delta;
+
+                       sum_truesize += fp->truesize;
                        if (head->ip_summed != fp->ip_summed)
                                head->ip_summed = CHECKSUM_NONE;
                        else if (head->ip_summed == CHECKSUM_COMPLETE)
                                head->csum = csum_add(head->csum, fp->csum);
-                       head->truesize += fp->truesize;
-                       fp = FRAG_CB(fp)->next_frag;
+
+                       if (try_coalesce && skb_try_coalesce(head, fp, &stolen,
+                                                            &delta)) {
+                               kfree_skb_partial(fp, stolen);
+                       } else {
+                               fp->prev = NULL;
+                               memset(&fp->rbnode, 0, sizeof(fp->rbnode));
+                               fp->sk = NULL;
+
+                               head->data_len += fp->len;
+                               head->len += fp->len;
+                               head->truesize += fp->truesize;
+
+                               *nextp = fp;
+                               nextp = &fp->next;
+                       }
+
+                       fp = next_frag;
                }
                /* Move to the next run. */
                if (rbn) {
@@ -516,7 +533,7 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
                        rbn = rbnext;
                }
        }
-       sub_frag_mem_limit(q->fqdir, head->truesize);
+       sub_frag_mem_limit(q->fqdir, sum_truesize);
 
        *nextp = NULL;
        skb_mark_not_on_list(head);
index 4385eb9e781ffc017a65d166ddf12c11fc901c0e..cfeb8890f94ee95b2246ba98beb338a33fc45d1d 100644 (file)
@@ -393,6 +393,11 @@ err:
        return err;
 }
 
+static bool ip_frag_coalesce_ok(const struct ipq *qp)
+{
+       return qp->q.key.v4.user == IP_DEFRAG_LOCAL_DELIVER;
+}
+
 /* Build a new IP datagram from all its fragments. */
 static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
                         struct sk_buff *prev_tail, struct net_device *dev)
@@ -421,7 +426,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
        if (len > 65535)
                goto out_oversize;
 
-       inet_frag_reasm_finish(&qp->q, skb, reasm_data);
+       inet_frag_reasm_finish(&qp->q, skb, reasm_data,
+                              ip_frag_coalesce_ok(qp));
 
        skb->dev = dev;
        IPCB(skb)->frag_max_size = max(qp->max_df_size, qp->q.max_size);
index 43adfc1641bacac2df882970e1eafca318896041..2f01cf6fa0deffb6f86a4db89b0aa8b951d0f352 100644 (file)
@@ -275,6 +275,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb,
        const struct iphdr  *tiph = &tunnel->parms.iph;
        u8 ipproto;
 
+       if (!pskb_inet_may_pull(skb))
+               goto tx_error;
+
        switch (skb->protocol) {
        case htons(ETH_P_IP):
                ipproto = IPPROTO_IPIP;
index 776905899ac06bcbaa7ece1f580303478e736d56..77b485d60b9d0e00edc4e2f0d6c5bb3a9460b23b 100644 (file)
@@ -984,6 +984,9 @@ new_segment:
                        if (!skb)
                                goto wait_for_memory;
 
+#ifdef CONFIG_TLS_DEVICE
+                       skb->decrypted = !!(flags & MSG_SENDPAGE_DECRYPTED);
+#endif
                        skb_entail(sk, skb);
                        copy = size_goal;
                }
index 3d1e1540138440a0c0f6a65aabd888626ad0e384..8a56e09cfb0ed3ebf03795ae4b5d1eb3f04221ba 100644 (file)
@@ -398,10 +398,14 @@ more_data:
 static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 {
        struct sk_msg tmp, *msg_tx = NULL;
-       int flags = msg->msg_flags | MSG_NO_SHARED_FRAGS;
        int copied = 0, err = 0;
        struct sk_psock *psock;
        long timeo;
+       int flags;
+
+       /* Don't let internal do_tcp_sendpages() flags through */
+       flags = (msg->msg_flags & ~MSG_SENDPAGE_DECRYPTED);
+       flags |= MSG_NO_SHARED_FRAGS;
 
        psock = sk_psock_get(sk);
        if (unlikely(!psock))
index 6e4afc48d7bba7cded4d3fe38f32ab02328f9e05..979520e46e33c16ba2237cb36ef7b4dab94f6546 100644 (file)
@@ -1320,6 +1320,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        buff = sk_stream_alloc_skb(sk, nsize, gfp, true);
        if (!buff)
                return -ENOMEM; /* We'll just try again later. */
+       skb_copy_decrypted(buff, skb);
 
        sk->sk_wmem_queued += buff->truesize;
        sk_mem_charge(sk, buff->truesize);
@@ -1874,6 +1875,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len,
        buff = sk_stream_alloc_skb(sk, 0, gfp, true);
        if (unlikely(!buff))
                return -ENOMEM;
+       skb_copy_decrypted(buff, skb);
 
        sk->sk_wmem_queued += buff->truesize;
        sk_mem_charge(sk, buff->truesize);
@@ -2143,6 +2145,7 @@ static int tcp_mtu_probe(struct sock *sk)
        sk_mem_charge(sk, nskb->truesize);
 
        skb = tcp_send_head(sk);
+       skb_copy_decrypted(nskb, skb);
 
        TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
        TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
index 3d8a1d8354719378ef157e36dbe21c57af9a4b7c..4849edb62d52964c61ef2d0601c16baa662e196d 100644 (file)
@@ -96,6 +96,19 @@ void tcp_get_available_ulp(char *buf, size_t maxlen)
        rcu_read_unlock();
 }
 
+void tcp_update_ulp(struct sock *sk, struct proto *proto)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+
+       if (!icsk->icsk_ulp_ops) {
+               sk->sk_prot = proto;
+               return;
+       }
+
+       if (icsk->icsk_ulp_ops->update)
+               icsk->icsk_ulp_ops->update(sk, proto);
+}
+
 void tcp_cleanup_ulp(struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
index c2049c72f3e533a7077674ca6dac43b527eb8b7f..dd2d0b96326074d3255eee91891938dc1d948483 100644 (file)
@@ -660,12 +660,13 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
                                    struct flowi6 *fl6, __u8 *dsfield,
                                    int *encap_limit)
 {
-       struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+       struct ipv6hdr *ipv6h;
        struct ip6_tnl *t = netdev_priv(dev);
        __u16 offset;
 
        offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
        /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+       ipv6h = ipv6_hdr(skb);
 
        if (offset > 0) {
                struct ipv6_tlv_tnl_enc_lim *tel;
index 3134fbb65d7f268d2b8785b3feb622a36c2d15c3..754a484d35df6eb03b82593cbb66a78718e30326 100644 (file)
@@ -1278,12 +1278,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+       dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
 
        if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
                return -1;
 
-       dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
-
        skb_set_inner_ipproto(skb, IPPROTO_IPIP);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1367,12 +1366,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+       dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
 
        if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
                return -1;
 
-       dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
-
        skb_set_inner_ipproto(skb, IPPROTO_IPV6);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
index 0f82c150543b75f42c35f0199244a3a8cf5dd3f7..fed9666a2f7da13cd2d686b71a1454401a18b7b4 100644 (file)
@@ -348,7 +348,7 @@ static int nf_ct_frag6_reasm(struct frag_queue *fq, struct sk_buff *skb,
 
        skb_reset_transport_header(skb);
 
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, false);
 
        skb->ignore_df = 1;
        skb->dev = dev;
index ca05b16f1bb95d4122a79fa9759011fd204f3e6f..1f5d4d196dccee12ee979f305b1b904864ff246e 100644 (file)
@@ -282,7 +282,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
 
        skb_reset_transport_header(skb);
 
-       inet_frag_reasm_finish(&fq->q, skb, reasm_data);
+       inet_frag_reasm_finish(&fq->q, skb, reasm_data, true);
 
        skb->dev = dev;
        ipv6_hdr(skb)->payload_len = htons(payload_len);
index e49fec767a10af5f6f03983f10cdf9d9f626ed3e..fd059e08785abb0d06320da870ffe8dd9499f8f9 100644 (file)
@@ -1951,7 +1951,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
                nexthop_for_each_fib6_nh(from->nh, fib6_nh_find_match, &arg);
 
                if (!arg.match)
-                       return;
+                       goto unlock;
                fib6_nh = arg.match;
        } else {
                fib6_nh = from->fib6_nh;
index 09e1694b6d341a5f1cf81e49643f9267ac4033c4..ebb62a4ebe30d3bd6347f72711b23655cddc00c5 100644 (file)
@@ -512,7 +512,9 @@ static void iucv_sock_close(struct sock *sk)
                        sk->sk_state = IUCV_DISCONN;
                        sk->sk_state_change(sk);
                }
-       case IUCV_DISCONN:   /* fall through */
+               /* fall through */
+
+       case IUCV_DISCONN:
                sk->sk_state = IUCV_CLOSING;
                sk->sk_state_change(sk);
 
@@ -525,8 +527,9 @@ static void iucv_sock_close(struct sock *sk)
                                        iucv_sock_in_state(sk, IUCV_CLOSED, 0),
                                        timeo);
                }
+               /* fall through */
 
-       case IUCV_CLOSING:   /* fall through */
+       case IUCV_CLOSING:
                sk->sk_state = IUCV_CLOSED;
                sk->sk_state_change(sk);
 
@@ -535,8 +538,9 @@ static void iucv_sock_close(struct sock *sk)
 
                skb_queue_purge(&iucv->send_skb_q);
                skb_queue_purge(&iucv->backlog_skb_q);
+               /* fall through */
 
-       default:   /* fall through */
+       default:
                iucv_sever_path(sk, 1);
        }
 
@@ -2247,10 +2251,10 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
                        kfree_skb(skb);
                        break;
                }
-               /* fall through and receive non-zero length data */
+               /* fall through and receive non-zero length data */
        case (AF_IUCV_FLAG_SHT):
                /* shutdown request */
-               /* fall through and receive zero length data */
+               /* fall through and receive zero length data */
        case 0:
                /* plain data frame */
                IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
index 1d0e5904dedf0bd180f2cd56400ac0da2038c0dd..c54cb59593ef8133c74bd30b771eb020573a27e2 100644 (file)
@@ -1681,6 +1681,9 @@ static const struct proto_ops pppol2tp_ops = {
        .recvmsg        = pppol2tp_recvmsg,
        .mmap           = sock_no_mmap,
        .ioctl          = pppox_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = pppox_compat_ioctl,
+#endif
 };
 
 static const struct pppox_proto pppol2tp_proto = {
index 06aac0aaae646cda1f3bca4aab7363922225be58..8dc6580e17871c4f8095079b226d18e1a41d51a5 100644 (file)
@@ -1222,7 +1222,6 @@ static void ieee80211_if_setup(struct net_device *dev)
 static void ieee80211_if_setup_no_queue(struct net_device *dev)
 {
        ieee80211_if_setup(dev);
-       dev->features |= NETIF_F_LLTX;
        dev->priv_flags |= IFF_NO_QUEUE;
 }
 
index a99ad032530946fd8c5d82cfd799ba598284e10d..4c888dc9bd8133eb0025ae919aa98ab002904740 100644 (file)
@@ -2042,6 +2042,16 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
                ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
        }
 
+       /* WMM specification requires all 4 ACIs. */
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               if (params[ac].cw_min == 0) {
+                       sdata_info(sdata,
+                                  "AP has invalid WMM params (missing AC %d), using defaults\n",
+                                  ac);
+                       return false;
+               }
+       }
+
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                mlme_dbg(sdata,
                         "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
index 1b224fa27367fbf4ce7cc7385eb27f8051081704..ad1e58184c4e4581dd111c506f0fe19a72aa6810 100644 (file)
@@ -3796,9 +3796,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        }
 
        /* Always allow software iftypes */
-       if (local->hw.wiphy->software_iftypes & BIT(iftype) ||
-           (iftype == NL80211_IFTYPE_AP_VLAN &&
-            local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) {
+       if (cfg80211_iftype_allowed(local->hw.wiphy, iftype, 0, 1)) {
                if (radar_detect)
                        return -EINVAL;
                return 0;
@@ -3833,7 +3831,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 
                if (sdata_iter == sdata ||
                    !ieee80211_sdata_running(sdata_iter) ||
-                   local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
+                   cfg80211_iftype_allowed(local->hw.wiphy,
+                                           wdev_iter->iftype, 0, 1))
                        continue;
 
                params.iftype_num[wdev_iter->iftype]++;
index ca7ac4a25ada2f1527175f03d204d90bedfea7ba..1d4e63326e68c1fe68d2e8542c8bbb4b29b2d859 100644 (file)
@@ -226,7 +226,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 
        e.id = ip_to_id(map, ip);
 
-       if (opt->flags & IPSET_DIM_ONE_SRC)
+       if (opt->flags & IPSET_DIM_TWO_SRC)
                ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
index 2e151856ad9992f1ec338f8fd6bed53b98c30be4..e64d5f9a89dd331e48ddf38af1c9978d2507a958 100644 (file)
@@ -1161,7 +1161,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl,
                return -ENOENT;
 
        write_lock_bh(&ip_set_ref_lock);
-       if (set->ref != 0) {
+       if (set->ref != 0 || set->ref_netlink != 0) {
                ret = -IPSET_ERR_REFERENCED;
                goto out;
        }
index faf59b6a998fecf50c191321d5605d5c5b460dc4..24d8f4df4230ca573098fbcdc83baadfd855e094 100644 (file)
@@ -89,15 +89,11 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-        /* MAC can be src only */
-       if (!(opt->flags & IPSET_DIM_TWO_SRC))
-               return 0;
-
        if (skb_mac_header(skb) < skb->head ||
            (skb_mac_header(skb) + ETH_HLEN) > skb->data)
                return -EINVAL;
 
-       if (opt->flags & IPSET_DIM_ONE_SRC)
+       if (opt->flags & IPSET_DIM_TWO_SRC)
                ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
index a542761e90d1fc269efbce6e4222da4b562b1c8e..81a8ef42b88d3893a210bea4f03b6eb4cbf04f99 100644 (file)
@@ -453,13 +453,12 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
  * table location, we assume id gets exposed to userspace.
  *
  * Following nf_conn items do not change throughout lifetime
- * of the nf_conn after it has been committed to main hash table:
+ * of the nf_conn:
  *
  * 1. nf_conn address
- * 2. nf_conn->ext address
- * 3. nf_conn->master address (normally NULL)
- * 4. tuple
- * 5. the associated net namespace
+ * 2. nf_conn->master address (normally NULL)
+ * 3. the associated net namespace
+ * 4. the original direction tuple
  */
 u32 nf_ct_get_id(const struct nf_conn *ct)
 {
@@ -469,9 +468,10 @@ u32 nf_ct_get_id(const struct nf_conn *ct)
        net_get_random_once(&ct_id_seed, sizeof(ct_id_seed));
 
        a = (unsigned long)ct;
-       b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct));
-       c = (unsigned long)ct->ext;
-       d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash),
+       b = (unsigned long)ct->master;
+       c = (unsigned long)nf_ct_net(ct);
+       d = (unsigned long)siphash(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                  sizeof(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple),
                                   &ct_id_seed);
 #ifdef CONFIG_64BIT
        return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed);
index e3d797252a981cdc7e3362be0e157c6db1d429a1..80a8f9ae4c93118d651f6b27f97f1f89bda77cfe 100644 (file)
@@ -111,15 +111,16 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
 #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT        (120 * HZ)
 #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT        (30 * HZ)
 
-static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
+{
+       return (__s32)(timeout - (u32)jiffies);
+}
+
+static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
 {
        const struct nf_conntrack_l4proto *l4proto;
+       int l4num = nf_ct_protonum(ct);
        unsigned int timeout;
-       int l4num;
-
-       l4num = nf_ct_protonum(ct);
-       if (l4num == IPPROTO_TCP)
-               flow_offload_fixup_tcp(&ct->proto.tcp);
 
        l4proto = nf_ct_l4proto_find(l4num);
        if (!l4proto)
@@ -132,7 +133,20 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)
        else
                return;
 
-       ct->timeout = nfct_time_stamp + timeout;
+       if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
+               ct->timeout = nfct_time_stamp + timeout;
+}
+
+static void flow_offload_fixup_ct_state(struct nf_conn *ct)
+{
+       if (nf_ct_protonum(ct) == IPPROTO_TCP)
+               flow_offload_fixup_tcp(&ct->proto.tcp);
+}
+
+static void flow_offload_fixup_ct(struct nf_conn *ct)
+{
+       flow_offload_fixup_ct_state(ct);
+       flow_offload_fixup_ct_timeout(ct);
 }
 
 void flow_offload_free(struct flow_offload *flow)
@@ -208,6 +222,11 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 }
 EXPORT_SYMBOL_GPL(flow_offload_add);
 
+static inline bool nf_flow_has_expired(const struct flow_offload *flow)
+{
+       return nf_flow_timeout_delta(flow->timeout) <= 0;
+}
+
 static void flow_offload_del(struct nf_flowtable *flow_table,
                             struct flow_offload *flow)
 {
@@ -223,6 +242,11 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
        e = container_of(flow, struct flow_offload_entry, flow);
        clear_bit(IPS_OFFLOAD_BIT, &e->ct->status);
 
+       if (nf_flow_has_expired(flow))
+               flow_offload_fixup_ct(e->ct);
+       else if (flow->flags & FLOW_OFFLOAD_TEARDOWN)
+               flow_offload_fixup_ct_timeout(e->ct);
+
        flow_offload_free(flow);
 }
 
@@ -298,11 +322,6 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
        return err;
 }
 
-static inline bool nf_flow_has_expired(const struct flow_offload *flow)
-{
-       return (__s32)(flow->timeout - (u32)jiffies) <= 0;
-}
-
 static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
 {
        struct nf_flowtable *flow_table = data;
index cdfc33517e85b5e0542195b019898bbe8efbcfa8..d68c801dd614bc3e40ec8741981a4d9b6cc1b997 100644 (file)
@@ -214,6 +214,25 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
        return true;
 }
 
+static int nf_flow_offload_dst_check(struct dst_entry *dst)
+{
+       if (unlikely(dst_xfrm(dst)))
+               return dst_check(dst, 0) ? 0 : -1;
+
+       return 0;
+}
+
+static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+                                     const struct nf_hook_state *state,
+                                     struct dst_entry *dst)
+{
+       skb_orphan(skb);
+       skb_dst_set_noref(skb, dst);
+       skb->tstamp = 0;
+       dst_output(state->net, state->sk, skb);
+       return NF_STOLEN;
+}
+
 unsigned int
 nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
                        const struct nf_hook_state *state)
@@ -254,6 +273,11 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
                return NF_ACCEPT;
 
+       if (nf_flow_offload_dst_check(&rt->dst)) {
+               flow_offload_teardown(flow);
+               return NF_ACCEPT;
+       }
+
        if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
                return NF_DROP;
 
@@ -261,6 +285,13 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        iph = ip_hdr(skb);
        ip_decrease_ttl(iph);
 
+       if (unlikely(dst_xfrm(&rt->dst))) {
+               memset(skb->cb, 0, sizeof(struct inet_skb_parm));
+               IPCB(skb)->iif = skb->dev->ifindex;
+               IPCB(skb)->flags = IPSKB_FORWARDED;
+               return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+       }
+
        skb->dev = outdev;
        nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
        skb_dst_set_noref(skb, &rt->dst);
@@ -467,6 +498,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
                                sizeof(*ip6h)))
                return NF_ACCEPT;
 
+       if (nf_flow_offload_dst_check(&rt->dst)) {
+               flow_offload_teardown(flow);
+               return NF_ACCEPT;
+       }
+
        if (skb_try_make_writable(skb, sizeof(*ip6h)))
                return NF_DROP;
 
@@ -477,6 +513,13 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
        ip6h = ipv6_hdr(skb);
        ip6h->hop_limit--;
 
+       if (unlikely(dst_xfrm(&rt->dst))) {
+               memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+               IP6CB(skb)->iif = skb->dev->ifindex;
+               IP6CB(skb)->flags = IP6SKB_FORWARDED;
+               return nf_flow_xmit_xfrm(skb, state, &rt->dst);
+       }
+
        skb->dev = outdev;
        nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
        skb_dst_set_noref(skb, &rt->dst);
index 605a7cfe7ca79ef316fa091bd913fd3827e61deb..d47469f824a10a8628c165cedef587a49528c725 100644 (file)
@@ -138,9 +138,14 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
                return;
 
        list_for_each_entry_reverse(trans, &net->nft.commit_list, list) {
-               if (trans->msg_type == NFT_MSG_NEWSET &&
-                   nft_trans_set(trans) == set) {
-                       set->bound = true;
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWSET:
+                       if (nft_trans_set(trans) == set)
+                               nft_trans_set_bound(trans) = true;
+                       break;
+               case NFT_MSG_NEWSETELEM:
+                       if (nft_trans_elem_set(trans) == set)
+                               nft_trans_elem_set_bound(trans) = true;
                        break;
                }
        }
@@ -1662,6 +1667,10 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
 
                chain->flags |= NFT_BASE_CHAIN | flags;
                basechain->policy = NF_ACCEPT;
+               if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
+                   nft_chain_offload_priority(basechain) < 0)
+                       return -EOPNOTSUPP;
+
                flow_block_init(&basechain->flow_block);
        } else {
                chain = kzalloc(sizeof(*chain), GFP_KERNEL);
@@ -6906,7 +6915,7 @@ static int __nf_tables_abort(struct net *net)
                        break;
                case NFT_MSG_NEWSET:
                        trans->ctx.table->use--;
-                       if (nft_trans_set(trans)->bound) {
+                       if (nft_trans_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
                        }
@@ -6918,7 +6927,7 @@ static int __nf_tables_abort(struct net *net)
                        nft_trans_destroy(trans);
                        break;
                case NFT_MSG_NEWSETELEM:
-                       if (nft_trans_elem_set(trans)->bound) {
+                       if (nft_trans_elem_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
                        }
index 64f5fd5f240e262cdb3382b244018899088fc0b8..c0d18c1d77ac05e0c9b1f98a33f2e18616bc3add 100644 (file)
@@ -103,10 +103,11 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
 }
 
 static void nft_flow_offload_common_init(struct flow_cls_common_offload *common,
-                                        __be16 proto,
-                                       struct netlink_ext_ack *extack)
+                                        __be16 proto, int priority,
+                                        struct netlink_ext_ack *extack)
 {
        common->protocol = proto;
+       common->prio = priority;
        common->extack = extack;
 }
 
@@ -124,6 +125,15 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
        return 0;
 }
 
+int nft_chain_offload_priority(struct nft_base_chain *basechain)
+{
+       if (basechain->ops.priority <= 0 ||
+           basechain->ops.priority > USHRT_MAX)
+               return -1;
+
+       return 0;
+}
+
 static int nft_flow_offload_rule(struct nft_trans *trans,
                                 enum flow_cls_command command)
 {
@@ -142,7 +152,8 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
        if (flow)
                proto = flow->proto;
 
-       nft_flow_offload_common_init(&cls_flow.common, proto, &extack);
+       nft_flow_offload_common_init(&cls_flow.common, proto,
+                                    basechain->ops.priority, &extack);
        cls_flow.command = command;
        cls_flow.cookie = (unsigned long) rule;
        if (flow)
index aa5f571d43619a4dc21f7036986228e78b640066..060a4ed46d5e6fca0196b3c874c9758999d84e0a 100644 (file)
@@ -72,11 +72,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 {
        struct nft_flow_offload *priv = nft_expr_priv(expr);
        struct nf_flowtable *flowtable = &priv->flowtable->data;
+       struct tcphdr _tcph, *tcph = NULL;
        enum ip_conntrack_info ctinfo;
        struct nf_flow_route route;
        struct flow_offload *flow;
        enum ip_conntrack_dir dir;
-       bool is_tcp = false;
        struct nf_conn *ct;
        int ret;
 
@@ -89,7 +89,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 
        switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
        case IPPROTO_TCP:
-               is_tcp = true;
+               tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff,
+                                         sizeof(_tcph), &_tcph);
+               if (unlikely(!tcph || tcph->fin || tcph->rst))
+                       goto out;
                break;
        case IPPROTO_UDP:
                break;
@@ -115,7 +118,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
        if (!flow)
                goto err_flow_alloc;
 
-       if (is_tcp) {
+       if (tcph) {
                ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
                ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
        }
index f1b1d948c07b431ea2bb6fe1ca5a024e4a1bc539..f69afb9ff3cbe04a5b36d9aef3964fb2e6962926 100644 (file)
@@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr,
                *dest = skb->mark;
                break;
        case NFT_META_IIF:
-               if (in == NULL)
-                       goto err;
-               *dest = in->ifindex;
+               *dest = in ? in->ifindex : 0;
                break;
        case NFT_META_OIF:
-               if (out == NULL)
-                       goto err;
-               *dest = out->ifindex;
+               *dest = out ? out->ifindex : 0;
                break;
        case NFT_META_IIFNAME:
-               if (in == NULL)
-                       goto err;
-               strncpy((char *)dest, in->name, IFNAMSIZ);
+               strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
                break;
        case NFT_META_OIFNAME:
-               if (out == NULL)
-                       goto err;
-               strncpy((char *)dest, out->name, IFNAMSIZ);
+               strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
                break;
        case NFT_META_IIFTYPE:
                if (in == NULL)
index 96740d389377170b90a5d3d2dba3482bd293eb9a..c4f54ad2b98afb44002415ce1daf2afef646d8c0 100644 (file)
@@ -967,6 +967,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 
        window = skb->data[20];
 
+       sock_hold(make);
        skb->sk             = make;
        skb->destructor     = sock_efree;
        make->sk_state      = TCP_ESTABLISHED;
index 892287d06c1768d3f16b029859f344c560984ff1..d01410e520979dd4a05336568f80dd6e0362bd93 100644 (file)
@@ -1047,7 +1047,7 @@ error:
 }
 
 /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */
-static struct sw_flow_actions *get_flow_actions(struct net *net,
+static noinline_for_stack struct sw_flow_actions *get_flow_actions(struct net *net,
                                                const struct nlattr *a,
                                                const struct sw_flow_key *key,
                                                const struct sw_flow_mask *mask,
@@ -1081,12 +1081,13 @@ static struct sw_flow_actions *get_flow_actions(struct net *net,
  * we should not to return match object with dangling reference
  * to mask.
  * */
-static int ovs_nla_init_match_and_action(struct net *net,
-                                        struct sw_flow_match *match,
-                                        struct sw_flow_key *key,
-                                        struct nlattr **a,
-                                        struct sw_flow_actions **acts,
-                                        bool log)
+static noinline_for_stack int
+ovs_nla_init_match_and_action(struct net *net,
+                             struct sw_flow_match *match,
+                             struct sw_flow_key *key,
+                             struct nlattr **a,
+                             struct sw_flow_actions **acts,
+                             bool log)
 {
        struct sw_flow_mask mask;
        int error = 0;
index 8d54f3047768d2272cbd28a7bcda33df800aa589..e2742b006d255f598fc98953dbb823f615d2bf9a 100644 (file)
@@ -2618,6 +2618,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
+       /* packet_sendmsg() check on tx_ring.pg_vec was lockless,
+        * we need to confirm it under protection of pg_vec_lock.
+        */
+       if (unlikely(!po->tx_ring.pg_vec)) {
+               err = -EBUSY;
+               goto out;
+       }
        if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
index ff74c4bbb9fc883f4107432c11a47f3d6f840137..9986d6065c4d1f357f021700351866d0ebe4f8a2 100644 (file)
@@ -105,7 +105,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                break;
 
        case RDMA_CM_EVENT_ESTABLISHED:
-               trans->cm_connect_complete(conn, event);
+               if (conn)
+                       trans->cm_connect_complete(conn, event);
                break;
 
        case RDMA_CM_EVENT_REJECTED:
@@ -137,6 +138,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                break;
 
        case RDMA_CM_EVENT_DISCONNECTED:
+               if (!conn)
+                       break;
                rdsdebug("DISCONNECT event - dropping connection "
                         "%pI6c->%pI6c\n", &conn->c_laddr,
                         &conn->c_faddr);
index d09eaf1535441fbea8f1b8b6cbba052f2a23d159..0dbbfd1b648759a7d9e729188521861d8accfe8f 100644 (file)
@@ -193,7 +193,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
 
 service_in_use:
        write_unlock(&local->services_lock);
-       rxrpc_put_local(local);
+       rxrpc_unuse_local(local);
        ret = -EADDRINUSE;
 error_unlock:
        release_sock(&rx->sk);
@@ -402,7 +402,7 @@ EXPORT_SYMBOL(rxrpc_kernel_check_life);
  */
 void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call)
 {
-       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                          rxrpc_propose_ack_ping_for_check_life);
        rxrpc_send_ack_packet(call, true, NULL);
 }
@@ -901,7 +901,7 @@ static int rxrpc_release_sock(struct sock *sk)
        rxrpc_queue_work(&rxnet->service_conn_reaper);
        rxrpc_queue_work(&rxnet->client_conn_reaper);
 
-       rxrpc_put_local(rx->local);
+       rxrpc_unuse_local(rx->local);
        rx->local = NULL;
        key_put(rx->key);
        rx->key = NULL;
index 80335b4ee4fd6c2b1ae39bed5b9089e35c292b84..145335611af66b1e6fcd261cc532be0a72aaa6ae 100644 (file)
@@ -254,7 +254,8 @@ struct rxrpc_security {
  */
 struct rxrpc_local {
        struct rcu_head         rcu;
-       atomic_t                usage;
+       atomic_t                active_users;   /* Number of users of the local endpoint */
+       atomic_t                usage;          /* Number of references to the structure */
        struct rxrpc_net        *rxnet;         /* The network ns in which this resides */
        struct list_head        link;
        struct socket           *socket;        /* my UDP socket */
@@ -649,7 +650,6 @@ struct rxrpc_call {
 
        /* receive-phase ACK management */
        u8                      ackr_reason;    /* reason to ACK */
-       u16                     ackr_skew;      /* skew on packet being ACK'd */
        rxrpc_serial_t          ackr_serial;    /* serial of packet being ACK'd */
        rxrpc_serial_t          ackr_first_seq; /* first sequence number received */
        rxrpc_seq_t             ackr_prev_seq;  /* previous sequence number received */
@@ -743,7 +743,7 @@ int rxrpc_reject_call(struct rxrpc_sock *);
 /*
  * call_event.c
  */
-void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
+void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool, bool,
                       enum rxrpc_propose_ack_trace);
 void rxrpc_process_call(struct work_struct *);
 
@@ -1002,6 +1002,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc
 struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *);
 struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *);
 void rxrpc_put_local(struct rxrpc_local *);
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *);
+void rxrpc_unuse_local(struct rxrpc_local *);
 void rxrpc_queue_local(struct rxrpc_local *);
 void rxrpc_destroy_all_locals(struct rxrpc_net *);
 
@@ -1061,6 +1063,7 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *);
 struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *);
 struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *);
 void rxrpc_put_peer(struct rxrpc_peer *);
+void rxrpc_put_peer_locked(struct rxrpc_peer *);
 
 /*
  * proc.c
index bc2adeb3acb9c9a54728cd9419c66186c22e4906..c767679bfa5db842c3ad94c33f011a4d5854bff2 100644 (file)
@@ -43,8 +43,7 @@ static void rxrpc_propose_ping(struct rxrpc_call *call,
  * propose an ACK be sent
  */
 static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
-                               u16 skew, u32 serial, bool immediate,
-                               bool background,
+                               u32 serial, bool immediate, bool background,
                                enum rxrpc_propose_ack_trace why)
 {
        enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use;
@@ -69,14 +68,12 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
                if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) {
                        outcome = rxrpc_propose_ack_update;
                        call->ackr_serial = serial;
-                       call->ackr_skew = skew;
                }
                if (!immediate)
                        goto trace;
        } else if (prior > rxrpc_ack_priority[call->ackr_reason]) {
                call->ackr_reason = ack_reason;
                call->ackr_serial = serial;
-               call->ackr_skew = skew;
        } else {
                outcome = rxrpc_propose_ack_subsume;
        }
@@ -137,11 +134,11 @@ trace:
  * propose an ACK be sent, locking the call structure
  */
 void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
-                      u16 skew, u32 serial, bool immediate, bool background,
+                      u32 serial, bool immediate, bool background,
                       enum rxrpc_propose_ack_trace why)
 {
        spin_lock_bh(&call->lock);
-       __rxrpc_propose_ACK(call, ack_reason, skew, serial,
+       __rxrpc_propose_ACK(call, ack_reason, serial,
                            immediate, background, why);
        spin_unlock_bh(&call->lock);
 }
@@ -239,7 +236,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
                ack_ts = ktime_sub(now, call->acks_latest_ts);
                if (ktime_to_ns(ack_ts) < call->peer->rtt)
                        goto out;
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                                  rxrpc_propose_ack_ping_for_lost_ack);
                rxrpc_send_ack_packet(call, true, NULL);
                goto out;
@@ -372,7 +369,7 @@ recheck_state:
        if (time_after_eq(now, t)) {
                trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now);
                cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET);
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true,
                                  rxrpc_propose_ack_ping_for_keepalive);
                set_bit(RXRPC_CALL_EV_PING, &call->events);
        }
@@ -407,7 +404,7 @@ recheck_state:
        send_ack = NULL;
        if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) {
                call->acks_lost_top = call->tx_top;
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false,
                                  rxrpc_propose_ack_ping_for_lost_ack);
                send_ack = &call->acks_lost_ping;
        }
index 5bd6f1546e5c6d1cbcdb30881675ceefab01c5b3..dd47d465d1d3e7de3bcf72dc76611621bb2c0e6a 100644 (file)
@@ -196,15 +196,14 @@ send_extra_data:
  * Ping the other end to fill our RTT cache and to retrieve the rwind
  * and MTU parameters.
  */
-static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb,
-                           int skew)
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        ktime_t now = skb->tstamp;
 
        if (call->peer->rtt_usage < 3 ||
            ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
                                  true, true,
                                  rxrpc_propose_ack_ping_for_params);
 }
@@ -419,8 +418,7 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
 /*
  * Process a DATA packet, adding the packet to the Rx ring.
  */
-static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
-                            u16 skew)
+static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        enum rxrpc_call_state state;
@@ -600,11 +598,11 @@ skip:
 
 ack:
        if (ack)
-               rxrpc_propose_ACK(call, ack, skew, ack_serial,
+               rxrpc_propose_ACK(call, ack, ack_serial,
                                  immediate_ack, true,
                                  rxrpc_propose_ack_input_data);
        else
-               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, skew, serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
                                  false, true,
                                  rxrpc_propose_ack_input_data);
 
@@ -822,8 +820,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks,
  * soft-ACK means that the packet may be discarded and retransmission
  * requested.  A phase is complete when all packets are hard-ACK'd.
  */
-static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
-                           u16 skew)
+static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
 {
        struct rxrpc_ack_summary summary = { 0 };
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -867,11 +864,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
        if (buf.ack.reason == RXRPC_ACK_PING) {
                _proto("Rx ACK %%%u PING Request", sp->hdr.serial);
                rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
-                                 skew, sp->hdr.serial, true, true,
+                                 sp->hdr.serial, true, true,
                                  rxrpc_propose_ack_respond_to_ping);
        } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
                rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED,
-                                 skew, sp->hdr.serial, true, true,
+                                 sp->hdr.serial, true, true,
                                  rxrpc_propose_ack_respond_to_ack);
        }
 
@@ -948,7 +945,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
            RXRPC_TX_ANNO_LAST &&
            summary.nr_acks == call->tx_top - hard_ack &&
            rxrpc_is_client_call(call))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial,
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
                                  false, true,
                                  rxrpc_propose_ack_ping_for_lost_reply);
 
@@ -1004,7 +1001,7 @@ static void rxrpc_input_abort(struct rxrpc_call *call, struct sk_buff *skb)
  * Process an incoming call packet.
  */
 static void rxrpc_input_call_packet(struct rxrpc_call *call,
-                                   struct sk_buff *skb, u16 skew)
+                                   struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        unsigned long timo;
@@ -1023,11 +1020,11 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
 
        switch (sp->hdr.type) {
        case RXRPC_PACKET_TYPE_DATA:
-               rxrpc_input_data(call, skb, skew);
+               rxrpc_input_data(call, skb);
                break;
 
        case RXRPC_PACKET_TYPE_ACK:
-               rxrpc_input_ack(call, skb, skew);
+               rxrpc_input_ack(call, skb);
                break;
 
        case RXRPC_PACKET_TYPE_BUSY:
@@ -1108,8 +1105,12 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
 {
        _enter("%p,%p", local, skb);
 
-       skb_queue_tail(&local->event_queue, skb);
-       rxrpc_queue_local(local);
+       if (rxrpc_get_local_maybe(local)) {
+               skb_queue_tail(&local->event_queue, skb);
+               rxrpc_queue_local(local);
+       } else {
+               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       }
 }
 
 /*
@@ -1119,8 +1120,12 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
 {
        CHECK_SLAB_OKAY(&local->usage);
 
-       skb_queue_tail(&local->reject_queue, skb);
-       rxrpc_queue_local(local);
+       if (rxrpc_get_local_maybe(local)) {
+               skb_queue_tail(&local->reject_queue, skb);
+               rxrpc_queue_local(local);
+       } else {
+               rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+       }
 }
 
 /*
@@ -1173,7 +1178,6 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
        struct rxrpc_peer *peer = NULL;
        struct rxrpc_sock *rx = NULL;
        unsigned int channel;
-       int skew = 0;
 
        _enter("%p", udp_sk);
 
@@ -1301,15 +1305,8 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                        goto out;
                }
 
-               /* Note the serial number skew here */
-               skew = (int)sp->hdr.serial - (int)conn->hi_serial;
-               if (skew >= 0) {
-                       if (skew > 0)
-                               conn->hi_serial = sp->hdr.serial;
-               } else {
-                       skew = -skew;
-                       skew = min(skew, 65535);
-               }
+               if ((int)sp->hdr.serial - (int)conn->hi_serial > 0)
+                       conn->hi_serial = sp->hdr.serial;
 
                /* Call-bound packets are routed by connection channel. */
                channel = sp->hdr.cid & RXRPC_CHANNELMASK;
@@ -1372,11 +1369,11 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                call = rxrpc_new_incoming_call(local, rx, skb);
                if (!call)
                        goto reject_packet;
-               rxrpc_send_ping(call, skb, skew);
+               rxrpc_send_ping(call, skb);
                mutex_unlock(&call->user_mutex);
        }
 
-       rxrpc_input_call_packet(call, skb, skew);
+       rxrpc_input_call_packet(call, skb);
        goto discard;
 
 discard:
index b1c71bad510b7c0200b2efed2a1652ecf254ca67..72a6e12a9304f8dbade52afcbca1019f5e28b1b5 100644 (file)
@@ -79,6 +79,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
        local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL);
        if (local) {
                atomic_set(&local->usage, 1);
+               atomic_set(&local->active_users, 1);
                local->rxnet = rxnet;
                INIT_LIST_HEAD(&local->link);
                INIT_WORK(&local->processor, rxrpc_local_processor);
@@ -92,7 +93,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
                local->debug_id = atomic_inc_return(&rxrpc_debug_id);
                memcpy(&local->srx, srx, sizeof(*srx));
                local->srx.srx_service = 0;
-               trace_rxrpc_local(local, rxrpc_local_new, 1, NULL);
+               trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, NULL);
        }
 
        _leave(" = %p", local);
@@ -266,11 +267,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
                 * bind the transport socket may still fail if we're attempting
                 * to use a local address that the dying object is still using.
                 */
-               if (!rxrpc_get_local_maybe(local)) {
-                       cursor = cursor->next;
-                       list_del_init(&local->link);
+               if (!rxrpc_use_local(local))
                        break;
-               }
 
                age = "old";
                goto found;
@@ -284,7 +282,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
        if (ret < 0)
                goto sock_error;
 
-       list_add_tail(&local->link, cursor);
+       if (cursor != &rxnet->local_endpoints)
+               list_replace_init(cursor, &local->link);
+       else
+               list_add_tail(&local->link, cursor);
        age = "new";
 
 found:
@@ -320,7 +321,7 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local)
        int n;
 
        n = atomic_inc_return(&local->usage);
-       trace_rxrpc_local(local, rxrpc_local_got, n, here);
+       trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here);
        return local;
 }
 
@@ -334,7 +335,8 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
        if (local) {
                int n = atomic_fetch_add_unless(&local->usage, 1, 0);
                if (n > 0)
-                       trace_rxrpc_local(local, rxrpc_local_got, n + 1, here);
+                       trace_rxrpc_local(local->debug_id, rxrpc_local_got,
+                                         n + 1, here);
                else
                        local = NULL;
        }
@@ -342,24 +344,18 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local)
 }
 
 /*
- * Queue a local endpoint.
+ * Queue a local endpoint and pass the caller's reference to the work item.
  */
 void rxrpc_queue_local(struct rxrpc_local *local)
 {
        const void *here = __builtin_return_address(0);
+       unsigned int debug_id = local->debug_id;
+       int n = atomic_read(&local->usage);
 
        if (rxrpc_queue_work(&local->processor))
-               trace_rxrpc_local(local, rxrpc_local_queued,
-                                 atomic_read(&local->usage), here);
-}
-
-/*
- * A local endpoint reached its end of life.
- */
-static void __rxrpc_put_local(struct rxrpc_local *local)
-{
-       _enter("%d", local->debug_id);
-       rxrpc_queue_work(&local->processor);
+               trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here);
+       else
+               rxrpc_put_local(local);
 }
 
 /*
@@ -372,10 +368,47 @@ void rxrpc_put_local(struct rxrpc_local *local)
 
        if (local) {
                n = atomic_dec_return(&local->usage);
-               trace_rxrpc_local(local, rxrpc_local_put, n, here);
+               trace_rxrpc_local(local->debug_id, rxrpc_local_put, n, here);
 
                if (n == 0)
-                       __rxrpc_put_local(local);
+                       call_rcu(&local->rcu, rxrpc_local_rcu);
+       }
+}
+
+/*
+ * Start using a local endpoint.
+ */
+struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local)
+{
+       unsigned int au;
+
+       local = rxrpc_get_local_maybe(local);
+       if (!local)
+               return NULL;
+
+       au = atomic_fetch_add_unless(&local->active_users, 1, 0);
+       if (au == 0) {
+               rxrpc_put_local(local);
+               return NULL;
+       }
+
+       return local;
+}
+
+/*
+ * Cease using a local endpoint.  Once the number of active users reaches 0, we
+ * start the closure of the transport in the work processor.
+ */
+void rxrpc_unuse_local(struct rxrpc_local *local)
+{
+       unsigned int au;
+
+       if (local) {
+               au = atomic_dec_return(&local->active_users);
+               if (au == 0)
+                       rxrpc_queue_local(local);
+               else
+                       rxrpc_put_local(local);
        }
 }
 
@@ -393,16 +426,6 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
 
        _enter("%d", local->debug_id);
 
-       /* We can get a race between an incoming call packet queueing the
-        * processor again and the work processor starting the destruction
-        * process which will shut down the UDP socket.
-        */
-       if (local->dead) {
-               _leave(" [already dead]");
-               return;
-       }
-       local->dead = true;
-
        mutex_lock(&rxnet->local_mutex);
        list_del_init(&local->link);
        mutex_unlock(&rxnet->local_mutex);
@@ -422,13 +445,11 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
         */
        rxrpc_purge_queue(&local->reject_queue);
        rxrpc_purge_queue(&local->event_queue);
-
-       _debug("rcu local %d", local->debug_id);
-       call_rcu(&local->rcu, rxrpc_local_rcu);
 }
 
 /*
- * Process events on an endpoint
+ * Process events on an endpoint.  The work item carries a ref which
+ * we must release.
  */
 static void rxrpc_local_processor(struct work_struct *work)
 {
@@ -436,13 +457,15 @@ static void rxrpc_local_processor(struct work_struct *work)
                container_of(work, struct rxrpc_local, processor);
        bool again;
 
-       trace_rxrpc_local(local, rxrpc_local_processing,
+       trace_rxrpc_local(local->debug_id, rxrpc_local_processing,
                          atomic_read(&local->usage), NULL);
 
        do {
                again = false;
-               if (atomic_read(&local->usage) == 0)
-                       return rxrpc_local_destroyer(local);
+               if (atomic_read(&local->active_users) == 0) {
+                       rxrpc_local_destroyer(local);
+                       break;
+               }
 
                if (!skb_queue_empty(&local->reject_queue)) {
                        rxrpc_reject_packets(local);
@@ -454,6 +477,8 @@ static void rxrpc_local_processor(struct work_struct *work)
                        again = true;
                }
        } while (again);
+
+       rxrpc_put_local(local);
 }
 
 /*
index 948e3fe249ec905208dc6966e7ff56f994ae0bac..369e516c4bdfdf3656a3f38b783ddcc70c92a5d3 100644 (file)
@@ -87,7 +87,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
        *_top = top;
 
        pkt->ack.bufferSpace    = htons(8);
-       pkt->ack.maxSkew        = htons(call->ackr_skew);
+       pkt->ack.maxSkew        = htons(0);
        pkt->ack.firstPacket    = htonl(hard_ack + 1);
        pkt->ack.previousPacket = htonl(call->ackr_prev_seq);
        pkt->ack.serial         = htonl(serial);
@@ -228,7 +228,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
                        if (ping)
                                clear_bit(RXRPC_CALL_PINGING, &call->flags);
                        rxrpc_propose_ACK(call, pkt->ack.reason,
-                                         ntohs(pkt->ack.maxSkew),
                                          ntohl(pkt->ack.serial),
                                          false, true,
                                          rxrpc_propose_ack_retry_tx);
index 9f2f45c09e58353d11e1b8abc9345209a92dc726..7666ec72d37e5e5e8971ca288749738ba324c64a 100644 (file)
@@ -378,7 +378,7 @@ static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net *rxnet,
                spin_lock_bh(&rxnet->peer_hash_lock);
                list_add_tail(&peer->keepalive_link,
                              &rxnet->peer_keepalive[slot & mask]);
-               rxrpc_put_peer(peer);
+               rxrpc_put_peer_locked(peer);
        }
 
        spin_unlock_bh(&rxnet->peer_hash_lock);
index 9d3ce81cf8ae899cd38c92a493b700d4d152f50a..9c3ac96f71cbf8202ccdeca3af388ad8a2ae08b3 100644 (file)
@@ -436,6 +436,24 @@ void rxrpc_put_peer(struct rxrpc_peer *peer)
        }
 }
 
+/*
+ * Drop a ref on a peer record where the caller already holds the
+ * peer_hash_lock.
+ */
+void rxrpc_put_peer_locked(struct rxrpc_peer *peer)
+{
+       const void *here = __builtin_return_address(0);
+       int n;
+
+       n = atomic_dec_return(&peer->usage);
+       trace_rxrpc_peer(peer, rxrpc_peer_put, n, here);
+       if (n == 0) {
+               hash_del_rcu(&peer->hash_link);
+               list_del_init(&peer->keepalive_link);
+               kfree_rcu(peer, rcu);
+       }
+}
+
 /*
  * Make sure all peer records have been discarded.
  */
index 5abf46cf9e6c4fa0e0271a2acdb32e24b6385870..9a7e1bc9791d7913e64e664ed08e4c17267b4331 100644 (file)
@@ -141,7 +141,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
        ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
 
        if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
-               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, false, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial, false, true,
                                  rxrpc_propose_ack_terminal_ack);
                //rxrpc_send_ack_packet(call, false, NULL);
        }
@@ -159,7 +159,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
                call->state = RXRPC_CALL_SERVER_ACK_REQUEST;
                call->expect_req_by = jiffies + MAX_JIFFY_OFFSET;
                write_unlock_bh(&call->state_lock);
-               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, false, true,
+               rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false, true,
                                  rxrpc_propose_ack_processing_op);
                break;
        default:
@@ -212,7 +212,7 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
                if (after_eq(hard_ack, call->ackr_consumed + 2) ||
                    after_eq(top, call->ackr_seen + 2) ||
                    (hard_ack == top && after(hard_ack, call->ackr_consumed)))
-                       rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
+                       rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial,
                                          true, true,
                                          rxrpc_propose_ack_rotate_rx);
                if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
index 5d3f33ce6d4100070dd348edc2018167fce921d3..bae14438f86918a8ccf1e2df82071d3a9dba7f18 100644 (file)
@@ -226,6 +226,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
                        rxrpc_set_call_completion(call,
                                                  RXRPC_CALL_LOCAL_ERROR,
                                                  0, ret);
+                       rxrpc_notify_socket(call);
                        goto out;
                }
                _debug("need instant resend %d", ret);
index 8126b26f125e019e3b5a16b632e2f7414498bfe4..fd1f7e799e23e04337eaee35aef5dfb03d43563e 100644 (file)
@@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        struct tcf_bpf *prog;
        bool is_bpf, is_ebpf;
        int ret, res = 0;
+       u32 index;
 
        if (!nla)
                return -EINVAL;
@@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
-
-       ret = tcf_idr_check_alloc(tn, &parm->index, act, bind);
+       index = parm->index;
+       ret = tcf_idr_check_alloc(tn, &index, act, bind);
        if (!ret) {
-               ret = tcf_idr_create(tn, parm->index, est, act,
+               ret = tcf_idr_create(tn, index, est, act,
                                     &act_bpf_ops, bind, true);
                if (ret < 0) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
index ce36b0f7e1dc15379319858d5e5891d3417ca061..32ac04d77a455a845e61d89ec9d646d3e886b155 100644 (file)
@@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
        struct tcf_connmark_info *ci;
        struct tc_connmark *parm;
        int ret = 0, err;
+       u32 index;
 
        if (!nla)
                return -EINVAL;
@@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_CONNMARK_PARMS]);
-
-       ret = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       ret = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!ret) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_connmark_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
index 621fb22ce2a9297f6cab5fd1d675cc2fdd63aa73..9b9288267a545627474a9909018f6a3e9f625930 100644 (file)
@@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
        struct tc_csum *parm;
        struct tcf_csum *p;
        int ret = 0, err;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
        if (tb[TCA_CSUM_PARMS] == NULL)
                return -EINVAL;
        parm = nla_data(tb[TCA_CSUM_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_csum_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index b501ce0cf11675c04c7840cb1d8d0b3ad5029498..33a1a7406e87feb2735f9acde1b9a76f7304bec5 100644 (file)
@@ -666,6 +666,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
        struct tc_ct *parm;
        struct tcf_ct *c;
        int err, res = 0;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed");
@@ -681,16 +682,16 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
        parm = nla_data(tb[TCA_CT_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
 
        if (!err) {
-               err = tcf_idr_create(tn, parm->index, est, a,
+               err = tcf_idr_create(tn, index, est, a,
                                     &act_ct_ops, bind, true);
                if (err) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return err;
                }
                res = ACT_P_CREATED;
index 10eb2bb998617b38a71764aa307f024a7436f018..06ef74b74911cea631af5f12d8dba6fb9c13cf46 100644 (file)
@@ -157,10 +157,10 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
                           struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
+       u32 dscpmask = 0, dscpstatemask, index;
        struct nlattr *tb[TCA_CTINFO_MAX + 1];
        struct tcf_ctinfo_params *cp_new;
        struct tcf_chain *goto_ch = NULL;
-       u32 dscpmask = 0, dscpstatemask;
        struct tc_ctinfo *actparm;
        struct tcf_ctinfo *ci;
        u8 dscpmaskshift;
@@ -206,12 +206,13 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
        }
 
        /* done the validation:now to the actual action allocation */
-       err = tcf_idr_check_alloc(tn, &actparm->index, a, bind);
+       index = actparm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, actparm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_ctinfo_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, actparm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index b2380c5284e6f5fbcdbb6a5f9a8e9f6b0ddc7394..8f0140c6ca58b6b0c6645f48b4f093c21c471dd6 100644 (file)
@@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        struct tc_gact *parm;
        struct tcf_gact *gact;
        int ret = 0;
+       u32 index;
        int err;
 #ifdef CONFIG_GACT_PROB
        struct tc_gact_p *p_parm = NULL;
@@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        if (tb[TCA_GACT_PARMS] == NULL)
                return -EINVAL;
        parm = nla_data(tb[TCA_GACT_PARMS]);
+       index = parm->index;
 
 #ifndef CONFIG_GACT_PROB
        if (tb[TCA_GACT_PROB] != NULL)
@@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        }
 #endif
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_gact_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index 41d5398dd2f2ee79bc9fc203df86846bdce0f3a7..92ee853d43e6c5f71d4ed635cc0043eb761358a9 100644 (file)
@@ -479,8 +479,14 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        u8 *saddr = NULL;
        bool exists = false;
        int ret = 0;
+       u32 index;
        int err;
 
+       if (!nla) {
+               NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be passed");
+               return -EINVAL;
+       }
+
        err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy,
                                          NULL);
        if (err < 0)
@@ -502,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        if (!p)
                return -ENOMEM;
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0) {
                kfree(p);
                return err;
@@ -514,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops,
+               ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
                                     bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        kfree(p);
                        return ret;
                }
index 055faa298c8e90f5c9029735fa411d06308f5d10..be3f88dfc37eb735a7f76728c525fad88d22c83a 100644 (file)
@@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        struct net_device *dev;
        bool exists = false;
        int ret, err;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed");
@@ -118,8 +119,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
        parm = nla_data(tb[TCA_MIRRED_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -136,21 +137,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
                return -EINVAL;
        }
 
        if (!exists) {
                if (!parm->ifindex) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
                        return -EINVAL;
                }
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_mirred_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index ca2597ce4ac9d9296e7c76ec2d9851310bf38004..0f299e3b618cbae1f4794cd8e7230437d974ead9 100644 (file)
@@ -138,6 +138,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
        struct tcf_mpls *m;
        int ret = 0, err;
        u8 mpls_ttl = 0;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes");
@@ -153,6 +154,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
        parm = nla_data(tb[TCA_MPLS_PARMS]);
+       index = parm->index;
 
        /* Verify parameters against action type. */
        switch (parm->m_action) {
@@ -209,7 +211,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -217,10 +219,10 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_mpls_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
index 45923ebb7a4fa3c103111b128274058ea088bee5..7b858c11b1b5ffd34f57706ee5631229b45f65a3 100644 (file)
@@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        struct tc_nat *parm;
        int ret = 0, err;
        struct tcf_nat *p;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        if (tb[TCA_NAT_PARMS] == NULL)
                return -EINVAL;
        parm = nla_data(tb[TCA_NAT_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_nat_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index 45e9d6bfddb3df539d9b76e7cc72e8e5e6b71e8a..17360c6faeaac184a59ef82fa2e909885b83fa84 100644 (file)
@@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        struct tcf_pedit *p;
        int ret = 0, err;
        int ksize;
+       u32 index;
 
        if (!nla) {
                NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed");
@@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        if (IS_ERR(keys_ex))
                return PTR_ERR(keys_ex);
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
                if (!parm->nkeys) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
                        ret = -EINVAL;
                        goto out_free;
                }
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_pedit_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        goto out_free;
                }
                ret = ACT_P_CREATED;
index a065f62fa79c04e10442d870e6bb29523d216f36..49cec3e64a4d5b15b781151715347cccff1833ca 100644 (file)
@@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        struct tc_action_net *tn = net_generic(net, police_net_id);
        struct tcf_police_params *new;
        bool exists = false;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_POLICE_TBF]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, NULL, a,
+               ret = tcf_idr_create(tn, index, NULL, a,
                                     &act_police_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index 274d7a0c0e25c91186b5513715f7b87534d6476d..595308d60133d4428d385d34429d692af3f8c747 100644 (file)
@@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
        struct tc_action_net *tn = net_generic(net, sample_net_id);
        struct nlattr *tb[TCA_SAMPLE_MAX + 1];
        struct psample_group *psample_group;
+       u32 psample_group_num, rate, index;
        struct tcf_chain *goto_ch = NULL;
-       u32 psample_group_num, rate;
        struct tc_sample *parm;
        struct tcf_sample *s;
        bool exists = false;
@@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_SAMPLE_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_sample_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
                ret = ACT_P_CREATED;
index f28ddbabff7604373bd9374fa283c07f9b3c01ed..33aefa25b545e4032c0058b633aaaf74a88cf70e 100644 (file)
@@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        struct tcf_defact *d;
        bool exists = false;
        int ret = 0, err;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
 
        parm = nla_data(tb[TCA_DEF_PARMS]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_simp_ops, bind, false);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
index 215a06705cef71d501faa5ecb3a97fbb2f51bfe7..37dced00b63d16de7797c34ff0c10ed4812fe0b4 100644 (file)
@@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        u16 *queue_mapping = NULL, *ptype = NULL;
        bool exists = false;
        int ret = 0, err;
+       u32 index;
 
        if (nla == NULL)
                return -EINVAL;
@@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        }
 
        parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
-
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_skbedit_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -306,6 +307,17 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
        return tcf_idr_search(tn, a, index);
 }
 
+static size_t tcf_skbedit_get_fill_size(const struct tc_action *act)
+{
+       return nla_total_size(sizeof(struct tc_skbedit))
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_PRIORITY */
+               + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING */
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MARK */
+               + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_PTYPE */
+               + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MASK */
+               + nla_total_size_64bit(sizeof(u64)); /* TCA_SKBEDIT_FLAGS */
+}
+
 static struct tc_action_ops act_skbedit_ops = {
        .kind           =       "skbedit",
        .id             =       TCA_ID_SKBEDIT,
@@ -315,6 +327,7 @@ static struct tc_action_ops act_skbedit_ops = {
        .init           =       tcf_skbedit_init,
        .cleanup        =       tcf_skbedit_cleanup,
        .walk           =       tcf_skbedit_walker,
+       .get_fill_size  =       tcf_skbedit_get_fill_size,
        .lookup         =       tcf_skbedit_search,
        .size           =       sizeof(struct tcf_skbedit),
 };
index 4f07706eff07ec7790c3bee295b893f1f2e6f720..7da3518e18efb709f81d9435d6fe66411b8a270a 100644 (file)
@@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        struct tcf_skbmod_params *p, *p_old;
        struct tcf_chain *goto_ch = NULL;
        struct tc_skbmod *parm;
+       u32 lflags = 0, index;
        struct tcf_skbmod *d;
        bool exists = false;
        u8 *daddr = NULL;
        u8 *saddr = NULL;
        u16 eth_type = 0;
-       u32 lflags = 0;
        int ret = 0, err;
 
        if (!nla)
@@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        }
 
        parm = nla_data(tb[TCA_SKBMOD_PARMS]);
+       index = parm->index;
        if (parm->flags & SKBMOD_F_SWAPMAC)
                lflags = SKBMOD_F_SWAPMAC;
 
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_skbmod_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
index 10dffda1d5cc4d9d0236efaf713502a6367c1f92..6d0debdc9b972631ee2f53a1745e8fe0d8d5d126 100644 (file)
@@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        __be16 flags = 0;
        u8 tos, ttl;
        int ret = 0;
+       u32 index;
        int err;
 
        if (!nla) {
@@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        }
 
        parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_tunnel_key_ops, bind, true);
                if (ret) {
                        NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
@@ -403,7 +405,7 @@ err_out:
        if (exists)
                tcf_idr_release(*a, bind);
        else
-               tcf_idr_cleanup(tn, parm->index);
+               tcf_idr_cleanup(tn, index);
        return ret;
 }
 
index 9269d350fb8aa0ae525cd89fa8d855b9be280731..a3c9eea1ee8ac720311a8c88994a08a4a01d2bcb 100644 (file)
@@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        u8 push_prio = 0;
        bool exists = false;
        int ret = 0, err;
+       u32 index;
 
        if (!nla)
                return -EINVAL;
@@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        if (!tb[TCA_VLAN_PARMS])
                return -EINVAL;
        parm = nla_data(tb[TCA_VLAN_PARMS]);
-       err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+       index = parm->index;
+       err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0)
                return err;
        exists = err;
@@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                        if (exists)
                                tcf_idr_release(*a, bind);
                        else
-                               tcf_idr_cleanup(tn, parm->index);
+                               tcf_idr_cleanup(tn, index);
                        return -EINVAL;
                }
                push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
@@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                        if (exists)
                                tcf_idr_release(*a, bind);
                        else
-                               tcf_idr_cleanup(tn, parm->index);
+                               tcf_idr_cleanup(tn, index);
                        return -ERANGE;
                }
 
@@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                                if (exists)
                                        tcf_idr_release(*a, bind);
                                else
-                                       tcf_idr_cleanup(tn, parm->index);
+                                       tcf_idr_cleanup(tn, index);
                                return -EPROTONOSUPPORT;
                        }
                } else {
@@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                if (exists)
                        tcf_idr_release(*a, bind);
                else
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                return -EINVAL;
        }
        action = parm->v_action;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, parm->index, est, a,
+               ret = tcf_idr_create(tn, index, est, a,
                                     &act_vlan_ops, bind, true);
                if (ret) {
-                       tcf_idr_cleanup(tn, parm->index);
+                       tcf_idr_cleanup(tn, index);
                        return ret;
                }
 
@@ -306,6 +308,14 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
        return tcf_idr_search(tn, a, index);
 }
 
+static size_t tcf_vlan_get_fill_size(const struct tc_action *act)
+{
+       return nla_total_size(sizeof(struct tc_vlan))
+               + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_ID */
+               + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_PROTOCOL */
+               + nla_total_size(sizeof(u8)); /* TCA_VLAN_PUSH_VLAN_PRIORITY */
+}
+
 static struct tc_action_ops act_vlan_ops = {
        .kind           =       "vlan",
        .id             =       TCA_ID_VLAN,
@@ -315,6 +325,7 @@ static struct tc_action_ops act_vlan_ops = {
        .init           =       tcf_vlan_init,
        .cleanup        =       tcf_vlan_cleanup,
        .walk           =       tcf_vlan_walker,
+       .get_fill_size  =       tcf_vlan_get_fill_size,
        .lookup         =       tcf_vlan_search,
        .size           =       sizeof(struct tcf_vlan),
 };
index 25ef172c23dfa31d05729c76a58ade3bb4967d5e..30169b3adbbb064c51b6006755d56446570f974c 100644 (file)
@@ -71,10 +71,10 @@ static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx)
        struct Qdisc *sch = ctx;
        struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
 
-       if (skb)
+       if (skb) {
                sch->qstats.backlog -= qdisc_pkt_len(skb);
-
-       prefetch(&skb->end); /* we'll need skb_shinfo() */
+               prefetch(&skb->end); /* we'll need skb_shinfo() */
+       }
        return skb;
 }
 
index c39db507ba3f42234c14e4e24184909509b9e2e7..e25d414ae12fdd9a7c4b8ea1903293e36e4ae12a 100644 (file)
@@ -1195,7 +1195,8 @@ unlock:
        spin_unlock_bh(qdisc_lock(sch));
 
 free_sched:
-       kfree(new_admin);
+       if (new_admin)
+               call_rcu(&new_admin->rcu, taprio_free_sched_cb);
 
        return err;
 }
index a554d6d15d1b6fe490ab62dd4bb1abbc96b923ab..1cf5bb5b73c412cadf1b3d7240bb8c200edb77a5 100644 (file)
@@ -546,7 +546,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands,
         */
        if (net->sctp.pf_enable &&
           (transport->state == SCTP_ACTIVE) &&
-          (asoc->pf_retrans < transport->pathmaxrxt) &&
+          (transport->error_count < transport->pathmaxrxt) &&
           (transport->error_count > asoc->pf_retrans)) {
 
                sctp_assoc_control_transport(asoc, transport,
index aa80cda3658116b94081f4700c28b8cb03fd2de6..9d1f83b10c0a6c5ab0ca2736c8a9f8491e44c310 100644 (file)
@@ -985,7 +985,7 @@ static int sctp_setsockopt_bindx(struct sock *sk,
                return -EINVAL;
 
        kaddrs = memdup_user(addrs, addrs_size);
-       if (unlikely(IS_ERR(kaddrs)))
+       if (IS_ERR(kaddrs))
                return PTR_ERR(kaddrs);
 
        /* Walk through the addrs buffer and count the number of addresses. */
@@ -1315,7 +1315,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
                return -EINVAL;
 
        kaddrs = memdup_user(addrs, addrs_size);
-       if (unlikely(IS_ERR(kaddrs)))
+       if (IS_ERR(kaddrs))
                return PTR_ERR(kaddrs);
 
        /* Allow security module to validate connectx addresses. */
index 25946604af85c09917e63e5c4a8d7d6fa2caebc4..e83cdaa2ab765c1ce20392b5ba2d91573f39ff14 100644 (file)
@@ -316,6 +316,7 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
                nstr_list[i] = htons(str_list[i]);
 
        if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) {
+               kfree(nstr_list);
                retval = -EAGAIN;
                goto out;
        }
index 302e355f2ebc39c49ebbe7d617cbc488f66f83c6..5b932583e4076feacb786d315bc4d6181fd9a17b 100644 (file)
@@ -263,7 +263,7 @@ static int smc_bind(struct socket *sock, struct sockaddr *uaddr,
 
        /* Check if socket is already active */
        rc = -EINVAL;
-       if (sk->sk_state != SMC_INIT)
+       if (sk->sk_state != SMC_INIT || smc->connect_nonblock)
                goto out_rel;
 
        smc->clcsock->sk->sk_reuse = sk->sk_reuse;
@@ -1390,7 +1390,8 @@ static int smc_listen(struct socket *sock, int backlog)
        lock_sock(sk);
 
        rc = -EINVAL;
-       if ((sk->sk_state != SMC_INIT) && (sk->sk_state != SMC_LISTEN))
+       if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) ||
+           smc->connect_nonblock)
                goto out;
 
        rc = 0;
@@ -1518,7 +1519,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                goto out;
 
        if (msg->msg_flags & MSG_FASTOPEN) {
-               if (sk->sk_state == SMC_INIT) {
+               if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) {
                        smc_switch_to_fallback(smc);
                        smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
                } else {
@@ -1732,14 +1733,18 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
                }
                break;
        case TCP_NODELAY:
-               if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
+               if (sk->sk_state != SMC_INIT &&
+                   sk->sk_state != SMC_LISTEN &&
+                   sk->sk_state != SMC_CLOSED) {
                        if (val && !smc->use_fallback)
                                mod_delayed_work(system_wq, &smc->conn.tx_work,
                                                 0);
                }
                break;
        case TCP_CORK:
-               if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) {
+               if (sk->sk_state != SMC_INIT &&
+                   sk->sk_state != SMC_LISTEN &&
+                   sk->sk_state != SMC_CLOSED) {
                        if (!val && !smc->use_fallback)
                                mod_delayed_work(system_wq, &smc->conn.tx_work,
                                                 0);
index b88d48d009130985db69993bc115c8cae80a71a9..0f1eaed1bd1b310833443cfb930e57d85dfa51a9 100644 (file)
@@ -75,6 +75,7 @@ void tipc_set_node_addr(struct net *net, u32 addr)
                tipc_set_node_id(net, node_id);
        }
        tn->trial_addr = addr;
+       tn->addr_trial_end = jiffies;
        pr_info("32-bit node address hash set to %x\n", addr);
 }
 
index 66d3a07bc5711ff404332e2224d139ad71daaaee..c2c5c53cad22e26e156bfe13b70fa369a32ee620 100644 (file)
@@ -106,8 +106,6 @@ struct tipc_stats {
  * @transmitq: queue for sent, non-acked messages
  * @backlogq: queue for messages waiting to be sent
  * @snt_nxt: next sequence number to use for outbound messages
- * @prev_from: sequence number of most previous retransmission request
- * @stale_limit: time when repeated identical retransmits must force link reset
  * @ackers: # of peers that needs to ack each packet before it can be released
  * @acked: # last packet acked by a certain peer. Used for broadcast.
  * @rcv_nxt: next sequence number to expect for inbound messages
@@ -164,9 +162,7 @@ struct tipc_link {
                u16 limit;
        } backlog[5];
        u16 snd_nxt;
-       u16 prev_from;
        u16 window;
-       unsigned long stale_limit;
 
        /* Reception */
        u16 rcv_nxt;
@@ -1044,47 +1040,53 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
  * link_retransmit_failure() - Detect repeated retransmit failures
  * @l: tipc link sender
  * @r: tipc link receiver (= l in case of unicast)
- * @from: seqno of the 1st packet in retransmit request
  * @rc: returned code
  *
  * Return: true if the repeated retransmit failures happens, otherwise
  * false
  */
 static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r,
-                                   u16 from, int *rc)
+                                   int *rc)
 {
        struct sk_buff *skb = skb_peek(&l->transmq);
        struct tipc_msg *hdr;
 
        if (!skb)
                return false;
-       hdr = buf_msg(skb);
 
-       /* Detect repeated retransmit failures on same packet */
-       if (r->prev_from != from) {
-               r->prev_from = from;
-               r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance);
-       } else if (time_after(jiffies, r->stale_limit)) {
-               pr_warn("Retransmission failure on link <%s>\n", l->name);
-               link_print(l, "State of link ");
-               pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
-                       msg_user(hdr), msg_type(hdr), msg_size(hdr),
-                       msg_errcode(hdr));
-               pr_info("sqno %u, prev: %x, src: %x\n",
-                       msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr));
-
-               trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
-               trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
-               trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+       if (!TIPC_SKB_CB(skb)->retr_cnt)
+               return false;
 
-               if (link_is_bc_sndlink(l))
-                       *rc = TIPC_LINK_DOWN_EVT;
+       if (!time_after(jiffies, TIPC_SKB_CB(skb)->retr_stamp +
+                       msecs_to_jiffies(r->tolerance)))
+               return false;
+
+       hdr = buf_msg(skb);
+       if (link_is_bc_sndlink(l) && !less(r->acked, msg_seqno(hdr)))
+               return false;
 
+       pr_warn("Retransmission failure on link <%s>\n", l->name);
+       link_print(l, "State of link ");
+       pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n",
+               msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr));
+       pr_info("sqno %u, prev: %x, dest: %x\n",
+               msg_seqno(hdr), msg_prevnode(hdr), msg_destnode(hdr));
+       pr_info("retr_stamp %d, retr_cnt %d\n",
+               jiffies_to_msecs(TIPC_SKB_CB(skb)->retr_stamp),
+               TIPC_SKB_CB(skb)->retr_cnt);
+
+       trace_tipc_list_dump(&l->transmq, true, "retrans failure!");
+       trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!");
+       trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!");
+
+       if (link_is_bc_sndlink(l)) {
+               r->state = LINK_RESET;
+               *rc = TIPC_LINK_DOWN_EVT;
+       } else {
                *rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
-               return true;
        }
 
-       return false;
+       return true;
 }
 
 /* tipc_link_bc_retrans() - retransmit zero or more packets
@@ -1110,7 +1112,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
 
        trace_tipc_link_retrans(r, from, to, &l->transmq);
 
-       if (link_retransmit_failure(l, r, from, &rc))
+       if (link_retransmit_failure(l, r, &rc))
                return rc;
 
        skb_queue_walk(&l->transmq, skb) {
@@ -1119,11 +1121,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
                        continue;
                if (more(msg_seqno(hdr), to))
                        break;
-               if (link_is_bc_sndlink(l)) {
-                       if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
-                               continue;
-                       TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
-               }
+
+               if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
+                       continue;
+               TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM;
                _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC);
                if (!_skb)
                        return 0;
@@ -1133,6 +1134,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r,
                _skb->priority = TC_PRIO_CONTROL;
                __skb_queue_tail(xmitq, _skb);
                l->stats.retransmitted++;
+
+               /* Increase actual retrans counter & mark first time */
+               if (!TIPC_SKB_CB(skb)->retr_cnt++)
+                       TIPC_SKB_CB(skb)->retr_stamp = jiffies;
        }
        return 0;
 }
@@ -1357,12 +1362,10 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap,
        struct tipc_msg *hdr;
        u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
        u16 ack = l->rcv_nxt - 1;
+       bool passed = false;
        u16 seqno, n = 0;
        int rc = 0;
 
-       if (gap && link_retransmit_failure(l, l, acked + 1, &rc))
-               return rc;
-
        skb_queue_walk_safe(&l->transmq, skb, tmp) {
                seqno = buf_seqno(skb);
 
@@ -1372,12 +1375,17 @@ next_gap_ack:
                        __skb_unlink(skb, &l->transmq);
                        kfree_skb(skb);
                } else if (less_eq(seqno, acked + gap)) {
-                       /* retransmit skb */
+                       /* First, check if repeated retrans failures occurs? */
+                       if (!passed && link_retransmit_failure(l, l, &rc))
+                               return rc;
+                       passed = true;
+
+                       /* retransmit skb if unrestricted*/
                        if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
                                continue;
                        TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
-
-                       _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
+                       _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE,
+                                          GFP_ATOMIC);
                        if (!_skb)
                                continue;
                        hdr = buf_msg(_skb);
@@ -1386,6 +1394,10 @@ next_gap_ack:
                        _skb->priority = TC_PRIO_CONTROL;
                        __skb_queue_tail(xmitq, _skb);
                        l->stats.retransmitted++;
+
+                       /* Increase actual retrans counter & mark first time */
+                       if (!TIPC_SKB_CB(skb)->retr_cnt++)
+                               TIPC_SKB_CB(skb)->retr_stamp = jiffies;
                } else {
                        /* retry with Gap ACK blocks if any */
                        if (!ga || n >= ga->gack_cnt)
@@ -2577,7 +2589,7 @@ int tipc_link_dump(struct tipc_link *l, u16 dqueues, char *buf)
        i += scnprintf(buf + i, sz - i, " %x", l->peer_caps);
        i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt);
        i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt);
-       i += scnprintf(buf + i, sz - i, " %u", l->prev_from);
+       i += scnprintf(buf + i, sz - i, " %u", 0);
        i += scnprintf(buf + i, sz - i, " %u", 0);
        i += scnprintf(buf + i, sz - i, " %u", l->acked);
 
index da509f0eb9ca48d70ef012418e2e3326d9e83563..d7ebc9e955f6a35fe6b6ac058a48c30c6218fbdc 100644 (file)
@@ -102,13 +102,15 @@ struct plist;
 #define TIPC_MEDIA_INFO_OFFSET 5
 
 struct tipc_skb_cb {
-       u32 bytes_read;
-       u32 orig_member;
        struct sk_buff *tail;
        unsigned long nxt_retr;
-       bool validated;
+       unsigned long retr_stamp;
+       u32 bytes_read;
+       u32 orig_member;
        u16 chain_imp;
        u16 ackers;
+       u16 retr_cnt;
+       bool validated;
 };
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
index d86030ef1232a33af7e2da036bc5592c4d5c0021..e135d4e11231995c952d4adbe69d7b42a63adc27 100644 (file)
@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
        int rep_type;
        int rep_size;
        int req_type;
+       int req_size;
        struct net *net;
        struct sk_buff *rep;
        struct tlv_desc *req;
@@ -257,7 +258,8 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
        int err;
        struct sk_buff *arg;
 
-       if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
+       if (msg->req_type && (!msg->req_size ||
+                             !TLV_CHECK_TYPE(msg->req, msg->req_type)))
                return -EINVAL;
 
        msg->rep = tipc_tlv_alloc(msg->rep_size);
@@ -354,7 +356,8 @@ static int tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
 {
        int err;
 
-       if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type))
+       if (msg->req_type && (!msg->req_size ||
+                             !TLV_CHECK_TYPE(msg->req, msg->req_type)))
                return -EINVAL;
 
        err = __tipc_nl_compat_doit(cmd, msg);
@@ -1278,8 +1281,8 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
                goto send;
        }
 
-       len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-       if (!len || !TLV_OK(msg.req, len)) {
+       msg.req_size = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
+       if (msg.req_size && !TLV_OK(msg.req, msg.req_size)) {
                msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
                err = -EOPNOTSUPP;
                goto send;
index dd8537f988c4004a5c50e004f1654db5c4e548b6..83ae41d7e5548077778c805e6c3367cdbf674313 100644 (file)
@@ -485,9 +485,8 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
                tsk_set_unreturnable(tsk, true);
                if (sock->type == SOCK_DGRAM)
                        tsk_set_unreliable(tsk, true);
-               __skb_queue_head_init(&tsk->mc_method.deferredq);
        }
-
+       __skb_queue_head_init(&tsk->mc_method.deferredq);
        trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " ");
        return 0;
 }
index 7c0b2b778703f7080c28d4919084390d4da05e7c..43922d86e5109f9b19dab68be4c950e7440ad7e8 100644 (file)
@@ -373,9 +373,9 @@ static int tls_push_data(struct sock *sk,
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_prot_info *prot = &tls_ctx->prot_info;
        struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
-       int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
        int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
        struct tls_record_info *record = ctx->open_record;
+       int tls_push_record_flags;
        struct page_frag *pfrag;
        size_t orig_size = size;
        u32 max_open_record_len;
@@ -390,6 +390,9 @@ static int tls_push_data(struct sock *sk,
        if (sk->sk_err)
                return -sk->sk_err;
 
+       flags |= MSG_SENDPAGE_DECRYPTED;
+       tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
+
        timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
        if (tls_is_partially_sent_record(tls_ctx)) {
                rc = tls_push_partial_record(sk, tls_ctx, flags);
@@ -576,7 +579,9 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
                gfp_t sk_allocation = sk->sk_allocation;
 
                sk->sk_allocation = GFP_ATOMIC;
-               tls_push_partial_record(sk, ctx, MSG_DONTWAIT | MSG_NOSIGNAL);
+               tls_push_partial_record(sk, ctx,
+                                       MSG_DONTWAIT | MSG_NOSIGNAL |
+                                       MSG_SENDPAGE_DECRYPTED);
                sk->sk_allocation = sk_allocation;
        }
 }
index 4674e57e66b0533fc5faf5ae930c0aad85eb8b77..43252a801c3f6db298d30926aa15453b42aa1644 100644 (file)
@@ -261,24 +261,9 @@ void tls_ctx_free(struct tls_context *ctx)
        kfree(ctx);
 }
 
-static void tls_sk_proto_close(struct sock *sk, long timeout)
+static void tls_sk_proto_cleanup(struct sock *sk,
+                                struct tls_context *ctx, long timeo)
 {
-       struct tls_context *ctx = tls_get_ctx(sk);
-       long timeo = sock_sndtimeo(sk, 0);
-       void (*sk_proto_close)(struct sock *sk, long timeout);
-       bool free_ctx = false;
-
-       lock_sock(sk);
-       sk_proto_close = ctx->sk_proto_close;
-
-       if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD)
-               goto skip_tx_cleanup;
-
-       if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) {
-               free_ctx = true;
-               goto skip_tx_cleanup;
-       }
-
        if (unlikely(sk->sk_write_pending) &&
            !wait_on_pending_writer(sk, &timeo))
                tls_handle_open_record(sk, 0);
@@ -287,7 +272,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
        if (ctx->tx_conf == TLS_SW) {
                kfree(ctx->tx.rec_seq);
                kfree(ctx->tx.iv);
-               tls_sw_free_resources_tx(sk);
+               tls_sw_release_resources_tx(sk);
 #ifdef CONFIG_TLS_DEVICE
        } else if (ctx->tx_conf == TLS_HW) {
                tls_device_free_resources_tx(sk);
@@ -295,26 +280,46 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
        }
 
        if (ctx->rx_conf == TLS_SW)
-               tls_sw_free_resources_rx(sk);
+               tls_sw_release_resources_rx(sk);
 
 #ifdef CONFIG_TLS_DEVICE
        if (ctx->rx_conf == TLS_HW)
                tls_device_offload_cleanup_rx(sk);
-
-       if (ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW) {
-#else
-       {
 #endif
-               tls_ctx_free(ctx);
-               ctx = NULL;
-       }
+}
 
-skip_tx_cleanup:
+static void tls_sk_proto_close(struct sock *sk, long timeout)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct tls_context *ctx = tls_get_ctx(sk);
+       long timeo = sock_sndtimeo(sk, 0);
+       bool free_ctx;
+
+       if (ctx->tx_conf == TLS_SW)
+               tls_sw_cancel_work_tx(ctx);
+
+       lock_sock(sk);
+       free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW;
+
+       if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE)
+               tls_sk_proto_cleanup(sk, ctx, timeo);
+
+       write_lock_bh(&sk->sk_callback_lock);
+       if (free_ctx)
+               icsk->icsk_ulp_data = NULL;
+       sk->sk_prot = ctx->sk_proto;
+       if (sk->sk_write_space == tls_write_space)
+               sk->sk_write_space = ctx->sk_write_space;
+       write_unlock_bh(&sk->sk_callback_lock);
        release_sock(sk);
-       sk_proto_close(sk, timeout);
-       /* free ctx for TLS_HW_RECORD, used by tcp_set_state
-        * for sk->sk_prot->unhash [tls_hw_unhash]
-        */
+       if (ctx->tx_conf == TLS_SW)
+               tls_sw_free_ctx_tx(ctx);
+       if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW)
+               tls_sw_strparser_done(ctx);
+       if (ctx->rx_conf == TLS_SW)
+               tls_sw_free_ctx_rx(ctx);
+       ctx->sk_proto_close(sk, timeout);
+
        if (free_ctx)
                tls_ctx_free(ctx);
 }
@@ -526,6 +531,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
                {
 #endif
                        rc = tls_set_sw_offload(sk, ctx, 1);
+                       if (rc)
+                               goto err_crypto_info;
                        conf = TLS_SW;
                }
        } else {
@@ -537,13 +544,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval,
                {
 #endif
                        rc = tls_set_sw_offload(sk, ctx, 0);
+                       if (rc)
+                               goto err_crypto_info;
                        conf = TLS_SW;
                }
+               tls_sw_strparser_arm(sk, ctx);
        }
 
-       if (rc)
-               goto err_crypto_info;
-
        if (tx)
                ctx->tx_conf = conf;
        else
@@ -607,6 +614,7 @@ static struct tls_context *create_ctx(struct sock *sk)
        ctx->setsockopt = sk->sk_prot->setsockopt;
        ctx->getsockopt = sk->sk_prot->getsockopt;
        ctx->sk_proto_close = sk->sk_prot->close;
+       ctx->unhash = sk->sk_prot->unhash;
        return ctx;
 }
 
@@ -764,7 +772,6 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG],
        prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base;
        prot[TLS_HW_RECORD][TLS_HW_RECORD].hash         = tls_hw_hash;
        prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash       = tls_hw_unhash;
-       prot[TLS_HW_RECORD][TLS_HW_RECORD].close        = tls_sk_proto_close;
 }
 
 static int tls_init(struct sock *sk)
@@ -773,7 +780,7 @@ static int tls_init(struct sock *sk)
        int rc = 0;
 
        if (tls_hw_prot(sk))
-               goto out;
+               return 0;
 
        /* The TLS ulp is currently supported only for TCP sockets
         * in ESTABLISHED state.
@@ -784,21 +791,38 @@ static int tls_init(struct sock *sk)
        if (sk->sk_state != TCP_ESTABLISHED)
                return -ENOTSUPP;
 
+       tls_build_proto(sk);
+
        /* allocate tls context */
+       write_lock_bh(&sk->sk_callback_lock);
        ctx = create_ctx(sk);
        if (!ctx) {
                rc = -ENOMEM;
                goto out;
        }
 
-       tls_build_proto(sk);
        ctx->tx_conf = TLS_BASE;
        ctx->rx_conf = TLS_BASE;
+       ctx->sk_proto = sk->sk_prot;
        update_sk_prot(sk, ctx);
 out:
+       write_unlock_bh(&sk->sk_callback_lock);
        return rc;
 }
 
+static void tls_update(struct sock *sk, struct proto *p)
+{
+       struct tls_context *ctx;
+
+       ctx = tls_get_ctx(sk);
+       if (likely(ctx)) {
+               ctx->sk_proto_close = p->close;
+               ctx->sk_proto = p;
+       } else {
+               sk->sk_prot = p;
+       }
+}
+
 void tls_register_device(struct tls_device *device)
 {
        spin_lock_bh(&device_spinlock);
@@ -819,6 +843,7 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = {
        .name                   = "tls",
        .owner                  = THIS_MODULE,
        .init                   = tls_init,
+       .update                 = tls_update,
 };
 
 static int __init tls_register(void)
index 53b4ad94e74ab0aecb964ce0ed482c9277654d47..91d21b048a9b245804ba800d7e9dbc1b5c07a868 100644 (file)
@@ -2054,7 +2054,16 @@ static void tls_data_ready(struct sock *sk)
        }
 }
 
-void tls_sw_free_resources_tx(struct sock *sk)
+void tls_sw_cancel_work_tx(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+
+       set_bit(BIT_TX_CLOSING, &ctx->tx_bitmask);
+       set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask);
+       cancel_delayed_work_sync(&ctx->tx_work.work);
+}
+
+void tls_sw_release_resources_tx(struct sock *sk)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
@@ -2065,11 +2074,6 @@ void tls_sw_free_resources_tx(struct sock *sk)
        if (atomic_read(&ctx->encrypt_pending))
                crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
 
-       release_sock(sk);
-       cancel_delayed_work_sync(&ctx->tx_work.work);
-       lock_sock(sk);
-
-       /* Tx whatever records we can transmit and abandon the rest */
        tls_tx_records(sk, -1);
 
        /* Free up un-sent records in tx_list. First, free
@@ -2092,6 +2096,11 @@ void tls_sw_free_resources_tx(struct sock *sk)
 
        crypto_free_aead(ctx->aead_send);
        tls_free_open_rec(sk);
+}
+
+void tls_sw_free_ctx_tx(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
 
        kfree(ctx);
 }
@@ -2110,25 +2119,40 @@ void tls_sw_release_resources_rx(struct sock *sk)
                skb_queue_purge(&ctx->rx_list);
                crypto_free_aead(ctx->aead_recv);
                strp_stop(&ctx->strp);
-               write_lock_bh(&sk->sk_callback_lock);
-               sk->sk_data_ready = ctx->saved_data_ready;
-               write_unlock_bh(&sk->sk_callback_lock);
-               release_sock(sk);
-               strp_done(&ctx->strp);
-               lock_sock(sk);
+               /* If tls_sw_strparser_arm() was not called (cleanup paths)
+                * we still want to strp_stop(), but sk->sk_data_ready was
+                * never swapped.
+                */
+               if (ctx->saved_data_ready) {
+                       write_lock_bh(&sk->sk_callback_lock);
+                       sk->sk_data_ready = ctx->saved_data_ready;
+                       write_unlock_bh(&sk->sk_callback_lock);
+               }
        }
 }
 
-void tls_sw_free_resources_rx(struct sock *sk)
+void tls_sw_strparser_done(struct tls_context *tls_ctx)
 {
-       struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
 
-       tls_sw_release_resources_rx(sk);
+       strp_done(&ctx->strp);
+}
+
+void tls_sw_free_ctx_rx(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
 
        kfree(ctx);
 }
 
+void tls_sw_free_resources_rx(struct sock *sk)
+{
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+
+       tls_sw_release_resources_rx(sk);
+       tls_sw_free_ctx_rx(tls_ctx);
+}
+
 /* The work handler to transmitt the encrypted records in tx_list */
 static void tx_work_handler(struct work_struct *work)
 {
@@ -2137,11 +2161,17 @@ static void tx_work_handler(struct work_struct *work)
                                               struct tx_work, work);
        struct sock *sk = tx_work->sk;
        struct tls_context *tls_ctx = tls_get_ctx(sk);
-       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+       struct tls_sw_context_tx *ctx;
 
-       if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
+       if (unlikely(!tls_ctx))
                return;
 
+       ctx = tls_sw_ctx_tx(tls_ctx);
+       if (test_bit(BIT_TX_CLOSING, &ctx->tx_bitmask))
+               return;
+
+       if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
+               return;
        lock_sock(sk);
        tls_tx_records(sk, -1);
        release_sock(sk);
@@ -2160,6 +2190,18 @@ void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)
        }
 }
 
+void tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(tls_ctx);
+
+       write_lock_bh(&sk->sk_callback_lock);
+       rx_ctx->saved_data_ready = sk->sk_data_ready;
+       sk->sk_data_ready = tls_data_ready;
+       write_unlock_bh(&sk->sk_callback_lock);
+
+       strp_check_rcv(&rx_ctx->strp);
+}
+
 int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
@@ -2357,13 +2399,6 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
                cb.parse_msg = tls_read_size;
 
                strp_init(&sw_ctx_rx->strp, sk, &cb);
-
-               write_lock_bh(&sk->sk_callback_lock);
-               sw_ctx_rx->saved_data_ready = sk->sk_data_ready;
-               sk->sk_data_ready = tls_data_ready;
-               write_unlock_bh(&sk->sk_callback_lock);
-
-               strp_check_rcv(&sw_ctx_rx->strp);
        }
 
        goto out;
index f2084e3f7aa4f2157fc7a76dbdfbb31a46c8edb8..9d864ebeb7b32acaca6c207279b829e09ac6c60b 100644 (file)
@@ -312,6 +312,11 @@ static void hvs_close_connection(struct vmbus_channel *chan)
        lock_sock(sk);
        hvs_do_close_lock_held(vsock_sk(sk), true);
        release_sock(sk);
+
+       /* Release the refcnt for the channel that's opened in
+        * hvs_open_connection().
+        */
+       sock_put(sk);
 }
 
 static void hvs_open_connection(struct vmbus_channel *chan)
@@ -407,6 +412,9 @@ static void hvs_open_connection(struct vmbus_channel *chan)
        }
 
        set_per_channel_state(chan, conn_from_host ? new : sk);
+
+       /* This reference will be dropped by hvs_close_connection(). */
+       sock_hold(conn_from_host ? new : sk);
        vmbus_set_chn_rescind_callback(chan, hvs_close_connection);
 
        /* Set the pending send size to max packet size to always get
index 45d9afcff6d5f060c0f60fecd15a7acb42731fc2..32b3c719fdfce2487321d29a10b03c0cebad17f8 100644 (file)
@@ -1410,10 +1410,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                }
                break;
        case NETDEV_PRE_UP:
-               if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) &&
-                   !(wdev->iftype == NL80211_IFTYPE_AP_VLAN &&
-                     rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP &&
-                     wdev->use_4addr))
+               if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype,
+                                            wdev->use_4addr, 0))
                        return notifier_from_errno(-EOPNOTSUPP);
 
                if (rfkill_blocked(rdev->rfkill))
index fc83dd179c1a8b64b622a0646840fe70a06c3b2f..fd05ae1437a9f4aaca9a8d2f07f00565cff7817f 100644 (file)
@@ -3484,9 +3484,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                        return err;
        }
 
-       if (!(rdev->wiphy.interface_modes & (1 << type)) &&
-           !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr &&
-             rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP))
+       if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
                return -EOPNOTSUPP;
 
        err = nl80211_parse_mon_options(rdev, type, info, &params);
index 1c39d6a2e85011aff8a4991473fdec387c93bdac..d0e35b7b9e3502790cb6812f12824ff3826e7610 100644 (file)
@@ -1697,7 +1697,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
        for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
                num_interfaces += params->iftype_num[iftype];
                if (params->iftype_num[iftype] > 0 &&
-                   !(wiphy->software_iftypes & BIT(iftype)))
+                   !cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
                        used_iftypes |= BIT(iftype);
        }
 
@@ -1719,7 +1719,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
                        return -ENOMEM;
 
                for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
-                       if (wiphy->software_iftypes & BIT(iftype))
+                       if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
                                continue;
                        for (j = 0; j < c->n_limits; j++) {
                                all_iftypes |= limits[j].types;
@@ -2072,3 +2072,26 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
        return max_vht_nss;
 }
 EXPORT_SYMBOL(ieee80211_get_vht_max_nss);
+
+bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
+                            bool is_4addr, u8 check_swif)
+
+{
+       bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN;
+
+       switch (check_swif) {
+       case 0:
+               if (is_vlan && is_4addr)
+                       return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+               return wiphy->interface_modes & BIT(iftype);
+       case 1:
+               if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan)
+                       return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
+               return wiphy->software_iftypes & BIT(iftype);
+       default:
+               break;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL(cfg80211_iftype_allowed);
index 85571e90191fc35fad9aca49cda400ae75b9751d..bfeab44f81d077b5ac76bd1bf117ec148d010c79 100644 (file)
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
 
        if (argc != 2) {
                printf(
-                       "Sintax:  %s fbdev\n"
+                       "Syntax:  %s fbdev\n"
                        "Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
                return -1;
        }
index 0d434d0afc0bc81262afebdd069a1ccb30da9787..2f66ed388d1c33962126c015530147b2f677cef8 100644 (file)
@@ -52,6 +52,13 @@ ifndef obj
 $(warning kbuild: Makefile.build is included improperly)
 endif
 
+ifeq ($(MAKECMDGOALS)$(need-modorder),)
+ifneq ($(obj-m),)
+$(warning $(patsubst %.o,'%.ko',$(obj-m)) will not be built even though obj-m is specified.)
+$(warning You cannot use subdir-y/m to visit a module Makefile. Use obj-y/m instead.)
+endif
+endif
+
 # ===========================================================================
 
 ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -487,7 +494,9 @@ targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
 
 PHONY += $(subdir-ym)
 $(subdir-ym):
-       $(Q)$(MAKE) $(build)=$@ need-builtin=$(if $(findstring $@,$(subdir-obj-y)),1)
+       $(Q)$(MAKE) $(build)=$@ \
+       need-builtin=$(if $(filter $@/built-in.a, $(subdir-obj-y)),1) \
+       need-modorder=$(if $(need-modorder),$(if $(filter $@/modules.order, $(modorder)),1))
 
 # Add FORCE to the prequisites of a target to force it to be always rebuilt.
 # ---------------------------------------------------------------------------
index 92ed02d7cd5e4a2321985c7b4cafd482b736bb87..26e6574ecd08d4e0e189a35524aff1c704fb0e24 100644 (file)
@@ -85,10 +85,8 @@ endif
 
 include scripts/Makefile.lib
 
-modorder := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order
-
 # find all modules listed in modules.order
-modules := $(sort $(shell cat $(modorder)))
+modules := $(sort $(shell cat $(MODORDER)))
 
 # Stop after building .o files if NOFINAL is set. Makes compile tests quicker
 __modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules))
@@ -98,7 +96,7 @@ MODPOST += $(subst -i,-n,$(filter -i,$(MAKEFLAGS))) -s -T - $(wildcard vmlinux)
 
 # We can go over command line length here, so be careful.
 quiet_cmd_modpost = MODPOST $(words $(modules)) modules
-      cmd_modpost = sed 's/ko$$/o/' $(modorder) | $(MODPOST)
+      cmd_modpost = sed 's/ko$$/o/' $(MODORDER) | $(MODPOST)
 
 PHONY += modules-modpost
 modules-modpost:
index 988120e0fd67a073ed750a2469b92ff7f2d2662d..0f78d94abc351145b9607c17909e3ce14634e2e9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 // Check if refcount_t type and API should be used
 // instead of atomic_t type when dealing with refcounters
 //
index 9a94672e7adccff05901782c47a2473185e05831..ade69913106540e4e1918b88654a8914f3bbe29d 100644 (file)
@@ -1228,24 +1228,11 @@ hashalg_fail:
 
 static int __init init_digests(void)
 {
-       u8 digest[TPM_MAX_DIGEST_SIZE];
-       int ret;
-       int i;
-
-       ret = tpm_get_random(chip, digest, TPM_MAX_DIGEST_SIZE);
-       if (ret < 0)
-               return ret;
-       if (ret < TPM_MAX_DIGEST_SIZE)
-               return -EFAULT;
-
        digests = kcalloc(chip->nr_allocated_banks, sizeof(*digests),
                          GFP_KERNEL);
        if (!digests)
                return -ENOMEM;
 
-       for (i = 0; i < chip->nr_allocated_banks; i++)
-               memcpy(digests[i].digest, digest, TPM_MAX_DIGEST_SIZE);
-
        return 0;
 }
 
index 0d35359d25cd8643e5c5ab23fd00af6add754d73..0ecafd0c672271d08d844fe09c78c63fd5fccddf 100644 (file)
@@ -37,7 +37,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
        packets_per_page = PAGE_SIZE / packet_size;
        if (WARN_ON(!packets_per_page)) {
                err = -EINVAL;
-               goto error;
+               goto err_packets;
        }
        pages = DIV_ROUND_UP(count, packets_per_page);
 
index c8d1b4316245f3ac02ca0b25bbe6f63b66eceb02..48d863736b3c32ed7da2d29ab73da0b741b08fdc 100644 (file)
@@ -598,11 +598,9 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        }
        runtime->private_data = azx_dev;
 
-       if (chip->gts_present)
-               azx_pcm_hw.info = azx_pcm_hw.info |
-                       SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
-
        runtime->hw = azx_pcm_hw;
+       if (chip->gts_present)
+               runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME;
        runtime->hw.channels_min = hinfo->channels_min;
        runtime->hw.channels_max = hinfo->channels_max;
        runtime->hw.formats = hinfo->formats;
@@ -615,6 +613,13 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                                     20,
                                     178000000);
 
+       /* by some reason, the playback stream stalls on PulseAudio with
+        * tsched=1 when a capture stream triggers.  Until we figure out the
+        * real cause, disable tsched mode by telling the PCM info flag.
+        */
+       if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND)
+               runtime->hw.info |= SNDRV_PCM_INFO_BATCH;
+
        if (chip->align_buffer_size)
                /* constrain buffer sizes to be multiple of 128
                   bytes. This is more efficient in terms of memory
index baa15374fbcb4a38301fa7d5a5197a04ecb66e1b..f2a6df5e6bcb72cf222e40efda3bc2adabe66146 100644 (file)
@@ -31,7 +31,7 @@
 /* 14 unused */
 #define AZX_DCAPS_CTX_WORKAROUND (1 << 15)     /* X-Fi workaround */
 #define AZX_DCAPS_POSFIX_LPIB  (1 << 16)       /* Use LPIB as default */
-/* 17 unused */
+#define AZX_DCAPS_AMD_WORKAROUND (1 << 17)     /* AMD-specific workaround */
 #define AZX_DCAPS_NO_64BIT     (1 << 18)       /* No 64bit address */
 #define AZX_DCAPS_SYNC_WRITE   (1 << 19)       /* sync each cmd write */
 #define AZX_DCAPS_OLD_SSYNC    (1 << 20)       /* Old SSYNC reg for ICH */
index 485edaba0037e5d6a477d2eb0e8b62f75fe06858..5bf24fb819d28f12cb00012dd73aa65db65c60cc 100644 (file)
@@ -6051,6 +6051,24 @@ void snd_hda_gen_free(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_free);
 
+/**
+ * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
+ * @codec: the HDA codec
+ *
+ * This can be put as patch_ops reboot_notify function.
+ */
+void snd_hda_gen_reboot_notify(struct hda_codec *codec)
+{
+       /* Make the codec enter D3 to avoid spurious noises from the internal
+        * speaker during (and after) reboot
+        */
+       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+       snd_hda_codec_write(codec, codec->core.afg, 0,
+                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+       msleep(10);
+}
+EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
+
 #ifdef CONFIG_PM
 /**
  * snd_hda_gen_check_power_status - check the loopback power save state
@@ -6078,6 +6096,7 @@ static const struct hda_codec_ops generic_patch_ops = {
        .init = snd_hda_gen_init,
        .free = snd_hda_gen_free,
        .unsol_event = snd_hda_jack_unsol_event,
+       .reboot_notify = snd_hda_gen_reboot_notify,
 #ifdef CONFIG_PM
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
@@ -6100,7 +6119,7 @@ static int snd_hda_parse_generic_codec(struct hda_codec *codec)
 
        err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
        if (err < 0)
-               return err;
+               goto error;
 
        err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
        if (err < 0)
index 35a670a71c423097e8d65e19b283fe4118aea35f..5f199dcb0d188eb62ff84fac843e6a94bb027e57 100644 (file)
@@ -332,6 +332,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                                  struct auto_pin_cfg *cfg);
 int snd_hda_gen_build_controls(struct hda_codec *codec);
 int snd_hda_gen_build_pcms(struct hda_codec *codec);
+void snd_hda_gen_reboot_notify(struct hda_codec *codec);
 
 /* standard jack event callbacks */
 void snd_hda_gen_hp_automute(struct hda_codec *codec,
index 1e14d7270adf6d70474283bf92cb9ed441e7fe76..99fc0917339bbef2e0911b7119ddf89072923999 100644 (file)
@@ -64,6 +64,7 @@ enum {
        POS_FIX_VIACOMBO,
        POS_FIX_COMBO,
        POS_FIX_SKL,
+       POS_FIX_FIFO,
 };
 
 /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -135,7 +136,7 @@ module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 module_param_array(position_fix, int, NULL, 0444);
 MODULE_PARM_DESC(position_fix, "DMA pointer read method."
-                "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+).");
+                "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO).");
 module_param_array(bdl_pos_adj, int, NULL, 0644);
 MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
 module_param_array(probe_mask, int, NULL, 0444);
@@ -332,6 +333,11 @@ enum {
 #define AZX_DCAPS_PRESET_ATI_HDMI_NS \
        (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF)
 
+/* quirks for AMD SB */
+#define AZX_DCAPS_PRESET_AMD_SB \
+       (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_AMD_WORKAROUND |\
+        AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME)
+
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
        (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
@@ -841,6 +847,49 @@ static unsigned int azx_via_get_position(struct azx *chip,
        return bound_pos + mod_dma_pos;
 }
 
+#define AMD_FIFO_SIZE  32
+
+/* get the current DMA position with FIFO size correction */
+static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev)
+{
+       struct snd_pcm_substream *substream = azx_dev->core.substream;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       unsigned int pos, delay;
+
+       pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
+       if (!runtime)
+               return pos;
+
+       runtime->delay = AMD_FIFO_SIZE;
+       delay = frames_to_bytes(runtime, AMD_FIFO_SIZE);
+       if (azx_dev->insufficient) {
+               if (pos < delay) {
+                       delay = pos;
+                       runtime->delay = bytes_to_frames(runtime, pos);
+               } else {
+                       azx_dev->insufficient = 0;
+               }
+       }
+
+       /* correct the DMA position for capture stream */
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+               if (pos < delay)
+                       pos += azx_dev->core.bufsize;
+               pos -= delay;
+       }
+
+       return pos;
+}
+
+static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev,
+                                  unsigned int pos)
+{
+       struct snd_pcm_substream *substream = azx_dev->core.substream;
+
+       /* just read back the calculated value in the above */
+       return substream->runtime->delay;
+}
+
 static unsigned int azx_skl_get_dpib_pos(struct azx *chip,
                                         struct azx_dev *azx_dev)
 {
@@ -1417,6 +1466,7 @@ static int check_position_fix(struct azx *chip, int fix)
        case POS_FIX_VIACOMBO:
        case POS_FIX_COMBO:
        case POS_FIX_SKL:
+       case POS_FIX_FIFO:
                return fix;
        }
 
@@ -1433,6 +1483,10 @@ static int check_position_fix(struct azx *chip, int fix)
                dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n");
                return POS_FIX_VIACOMBO;
        }
+       if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) {
+               dev_dbg(chip->card->dev, "Using FIFO position fix\n");
+               return POS_FIX_FIFO;
+       }
        if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
                dev_dbg(chip->card->dev, "Using LPIB position fix\n");
                return POS_FIX_LPIB;
@@ -1453,6 +1507,7 @@ static void assign_position_fix(struct azx *chip, int fix)
                [POS_FIX_VIACOMBO] = azx_via_get_position,
                [POS_FIX_COMBO] = azx_get_pos_lpib,
                [POS_FIX_SKL] = azx_get_pos_skl,
+               [POS_FIX_FIFO] = azx_get_pos_fifo,
        };
 
        chip->get_position[0] = chip->get_position[1] = callbacks[fix];
@@ -1467,6 +1522,9 @@ static void assign_position_fix(struct azx *chip, int fix)
                        azx_get_delay_from_lpib;
        }
 
+       if (fix == POS_FIX_FIFO)
+               chip->get_delay[0] = chip->get_delay[1] =
+                       azx_get_delay_from_fifo;
 }
 
 /*
@@ -2447,6 +2505,12 @@ static const struct pci_device_id azx_ids[] = {
        /* AMD Hudson */
        { PCI_DEVICE(0x1022, 0x780d),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
+       /* AMD, X370 & co */
+       { PCI_DEVICE(0x1022, 0x1457),
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
+       /* AMD, X570 & co */
+       { PCI_DEVICE(0x1022, 0x1487),
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB },
        /* AMD Stoney */
        { PCI_DEVICE(0x1022, 0x157a),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
index f299f137eaea2b5b1c4871008928e31d966573c9..14298ef45b21bdf71db7dc864542ea8a7213331f 100644 (file)
@@ -163,23 +163,10 @@ static void cx_auto_reboot_notify(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
 
-       switch (codec->core.vendor_id) {
-       case 0x14f12008: /* CX8200 */
-       case 0x14f150f2: /* CX20722 */
-       case 0x14f150f4: /* CX20724 */
-               break;
-       default:
-               return;
-       }
-
        /* Turn the problematic codec into D3 to avoid spurious noises
           from the internal speaker during (and after) reboot */
        cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
-
-       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
-       snd_hda_codec_write(codec, codec->core.afg, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-       msleep(10);
+       snd_hda_gen_reboot_notify(codec);
 }
 
 static void cx_auto_free(struct hda_codec *codec)
index de224cbea7a077b000ba95b9eed6eb1571a1510f..e333b3e30e316034420b1dd4e24e031d18812b3d 100644 (file)
@@ -869,15 +869,6 @@ static void alc_reboot_notify(struct hda_codec *codec)
                alc_shutup(codec);
 }
 
-/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
-static void alc_d3_at_reboot(struct hda_codec *codec)
-{
-       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
-       snd_hda_codec_write(codec, codec->core.afg, 0,
-                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-       msleep(10);
-}
-
 #define alc_free       snd_hda_gen_free
 
 #ifdef CONFIG_PM
@@ -5152,7 +5143,7 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
+               spec->reboot_notify = snd_hda_gen_reboot_notify; /* reduce noise */
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
                codec->power_save_node = 0; /* avoid click noises */
                snd_hda_apply_pincfgs(codec, pincfgs);
@@ -6987,6 +6978,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
index a4ade6bb5bebea57f499f3d113eff5eec14ada1d..bc4dfafdfcd12757f76e4f78ee12b3ebb89acd62 100644 (file)
@@ -31,8 +31,8 @@ struct i2s_stream_instance {
        u16 num_pages;
        u16 channels;
        u32 xfer_resolution;
-       struct page *pg;
        u64 bytescount;
+       dma_addr_t dma_addr;
        void __iomem *acp3x_base;
 };
 
@@ -211,9 +211,8 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
 static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 {
        u16 page_idx;
-       u64 addr;
        u32 low, high, val, acp_fifo_addr;
-       struct page *pg = rtd->pg;
+       dma_addr_t addr = rtd->dma_addr;
 
        /* 8 scratch registers used to map one 64 bit address */
        if (direction == SNDRV_PCM_STREAM_PLAYBACK)
@@ -229,7 +228,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 
        for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
                /* Load the low address of page int ACP SRAM through SRBM */
-               addr = page_to_phys(pg);
                low = lower_32_bits(addr);
                high = upper_32_bits(addr);
 
@@ -239,7 +237,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
                                + 4);
                /* Move to next physically contiguos page */
                val += 8;
-               pg++;
+               addr += PAGE_SIZE;
        }
 
        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -341,7 +339,6 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
 {
        int status;
        u64 size;
-       struct page *pg;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct i2s_stream_instance *rtd = runtime->private_data;
 
@@ -354,9 +351,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
                return status;
 
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
-       pg = virt_to_page(substream->dma_buffer.area);
-       if (pg) {
-               rtd->pg = pg;
+       if (substream->dma_buffer.area) {
+               rtd->dma_addr = substream->dma_buffer.addr;
                rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
                config_acp3x_dma(rtd, substream->stream);
                status = 0;
@@ -385,9 +381,11 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
 
 static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
+                                                                   DRV_NAME);
+       struct device *parent = component->dev->parent;
        snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
-                                             rtd->pcm->card->dev,
-                                             MIN_BUFFER, MAX_BUFFER);
+                                             parent, MIN_BUFFER, MAX_BUFFER);
        return 0;
 }
 
index 6203f54d9f25831553ab670b81586e9c65ba14f0..5b049fcdba2013ee0398653bbf1f1ef8710620b9 100644 (file)
@@ -47,6 +47,7 @@ struct cs42xx8_priv {
        unsigned long sysclk;
        u32 tx_channels;
        struct gpio_desc *gpiod_reset;
+       u32 rate[2];
 };
 
 /* -127.5dB to 0dB with step of 0.5dB */
@@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
 };
 
 struct cs42xx8_ratios {
-       unsigned int ratio;
-       unsigned char speed;
-       unsigned char mclk;
+       unsigned int mfreq;
+       unsigned int min_mclk;
+       unsigned int max_mclk;
+       unsigned int ratio[3];
 };
 
+/*
+ * According to reference mannual, define the cs42xx8_ratio struct
+ * MFreq2 | MFreq1 | MFreq0 |     Description     | SSM | DSM | QSM |
+ * 0      | 0      | 0      |1.029MHz to 12.8MHz  | 256 | 128 |  64 |
+ * 0      | 0      | 1      |1.536MHz to 19.2MHz  | 384 | 192 |  96 |
+ * 0      | 1      | 0      |2.048MHz to 25.6MHz  | 512 | 256 | 128 |
+ * 0      | 1      | 1      |3.072MHz to 38.4MHz  | 768 | 384 | 192 |
+ * 1      | x      | x      |4.096MHz to 51.2MHz  |1024 | 512 | 256 |
+ */
 static const struct cs42xx8_ratios cs42xx8_ratios[] = {
-       { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
-       { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
-       { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
-       { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
-       { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
-       { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
-       { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
-       { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
-       { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
+       { 0, 1029000, 12800000, {256, 128, 64} },
+       { 2, 1536000, 19200000, {384, 192, 96} },
+       { 4, 2048000, 25600000, {512, 256, 128} },
+       { 6, 3072000, 38400000, {768, 384, 192} },
+       { 8, 4096000, 51200000, {1024, 512, 256} },
 };
 
 static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_component *component = dai->component;
        struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-       u32 ratio = cs42xx8->sysclk / params_rate(params);
-       u32 i, fm, val, mask;
+       u32 ratio[2];
+       u32 rate[2];
+       u32 fm[2];
+       u32 i, val, mask;
+       bool condition1, condition2;
 
        if (tx)
                cs42xx8->tx_channels = params_channels(params);
 
+       rate[tx]  = params_rate(params);
+       rate[!tx] = cs42xx8->rate[!tx];
+
+       ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0;
+       ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0;
+
+       /* Get functional mode for tx and rx according to rate */
+       for (i = 0; i < 2; i++) {
+               if (cs42xx8->slave_mode) {
+                       fm[i] = CS42XX8_FM_AUTO;
+               } else {
+                       if (rate[i] < 50000) {
+                               fm[i] = CS42XX8_FM_SINGLE;
+                       } else if (rate[i] > 50000 && rate[i] < 100000) {
+                               fm[i] = CS42XX8_FM_DOUBLE;
+                       } else if (rate[i] > 100000 && rate[i] < 200000) {
+                               fm[i] = CS42XX8_FM_QUAD;
+                       } else {
+                               dev_err(component->dev,
+                                       "unsupported sample rate\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
        for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
-               if (cs42xx8_ratios[i].ratio == ratio)
+               /* Is the ratio[tx] valid ? */
+               condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ?
+                       (cs42xx8_ratios[i].ratio[0] == ratio[tx] ||
+                       cs42xx8_ratios[i].ratio[1] == ratio[tx] ||
+                       cs42xx8_ratios[i].ratio[2] == ratio[tx]) :
+                       (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) &&
+                       cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
+                       cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk;
+
+               if (!ratio[tx])
+                       condition1 = true;
+
+               /* Is the ratio[!tx] valid ? */
+               condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ?
+                       (cs42xx8_ratios[i].ratio[0] == ratio[!tx] ||
+                       cs42xx8_ratios[i].ratio[1] == ratio[!tx] ||
+                       cs42xx8_ratios[i].ratio[2] == ratio[!tx]) :
+                       (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx]));
+
+               if (!ratio[!tx])
+                       condition2 = true;
+
+               /*
+                * Both ratio[tx] and ratio[!tx] is valid, then we get
+                * a proper MFreq.
+                */
+               if (condition1 && condition2)
                        break;
        }
 
@@ -273,15 +334,31 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       mask = CS42XX8_FUNCMOD_MFREQ_MASK;
-       val = cs42xx8_ratios[i].mclk;
+       cs42xx8->rate[tx] = params_rate(params);
 
-       fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
+       mask = CS42XX8_FUNCMOD_MFREQ_MASK;
+       val = cs42xx8_ratios[i].mfreq;
 
        regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
                           CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
-                          CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
+                          CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val);
+
+       return 0;
+}
+
+static int cs42xx8_hw_free(struct snd_pcm_substream *substream,
+                          struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
+       /* Clear stored rate */
+       cs42xx8->rate[tx] = 0;
+
+       regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
+                          CS42XX8_FUNCMOD_xC_FM_MASK(tx),
+                          CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO));
        return 0;
 }
 
@@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
        .set_fmt        = cs42xx8_set_dai_fmt,
        .set_sysclk     = cs42xx8_set_dai_sysclk,
        .hw_params      = cs42xx8_hw_params,
+       .hw_free        = cs42xx8_hw_free,
        .digital_mute   = cs42xx8_digital_mute,
 };
 
index 6f0e28f903bfb1963de5248bbd7d63a2534dcb2c..16313b973eaa41b26694bd154626b0329575d31c 100644 (file)
 #include <sound/soc-dapm.h>
 
 struct max98357a_priv {
-       struct delayed_work enable_sdmode_work;
        struct gpio_desc *sdmode;
        unsigned int sdmode_delay;
 };
 
-static void max98357a_enable_sdmode_work(struct work_struct *work)
-{
-       struct max98357a_priv *max98357a =
-       container_of(work, struct max98357a_priv,
-                       enable_sdmode_work.work);
-
-       gpiod_set_value(max98357a->sdmode, 1);
-}
-
 static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
                int cmd, struct snd_soc_dai *dai)
 {
@@ -46,14 +36,12 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               queue_delayed_work(system_power_efficient_wq,
-                               &max98357a->enable_sdmode_work,
-                               msecs_to_jiffies(max98357a->sdmode_delay));
+               mdelay(max98357a->sdmode_delay);
+               gpiod_set_value(max98357a->sdmode, 1);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               cancel_delayed_work_sync(&max98357a->enable_sdmode_work);
                gpiod_set_value(max98357a->sdmode, 0);
                break;
        }
@@ -112,30 +100,25 @@ static int max98357a_platform_probe(struct platform_device *pdev)
        int ret;
 
        max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL);
-
        if (!max98357a)
                return -ENOMEM;
 
        max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev,
                                "sdmode", GPIOD_OUT_LOW);
-
        if (IS_ERR(max98357a->sdmode))
                return PTR_ERR(max98357a->sdmode);
 
        ret = device_property_read_u32(&pdev->dev, "sdmode-delay",
                                        &max98357a->sdmode_delay);
-
        if (ret) {
                max98357a->sdmode_delay = 0;
                dev_dbg(&pdev->dev,
-                       "no optional property 'sdmode-delay' found, default: no delay\n");
+                       "no optional property 'sdmode-delay' found, "
+                       "default: no delay\n");
        }
 
        dev_set_drvdata(&pdev->dev, max98357a);
 
-       INIT_DELAYED_WORK(&max98357a->enable_sdmode_work,
-                               max98357a_enable_sdmode_work);
-
        return devm_snd_soc_register_component(&pdev->dev,
                        &max98357a_component_driver,
                        &max98357a_dai_driver, 1);
index 528695cd6a1ca7fef5e2812d86fbe283f677b34e..8c601a3ebc27e123693dff0a3bf682cf0ce47be2 100644 (file)
@@ -267,6 +267,12 @@ static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
        case 48000:
                sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
                break;
+       case 88200:
+               sampling_rate = MAX98373_PCM_SR_SET1_SR_88200;
+               break;
+       case 96000:
+               sampling_rate = MAX98373_PCM_SR_SET1_SR_96000;
+               break;
        default:
                dev_err(component->dev, "rate %d not supported\n",
                        params_rate(params));
index f6a37aa02f2665ea67dda2dcc4441763765b9f76..a59e51355a84ddba7ef8fc24695f4401459d56d3 100644 (file)
 #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0)
 #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0)
 #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0)
+#define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0)
+#define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0)
 
 /* MAX98373_R2028_PCM_SR_SETUP_2 */
 #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4)
index cdc8314882bc8a8ced49109e55449522d87285d9..abcdeb92220147ec38a3e70d2aff2be27a015bfc 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PCM3060 I2C driver
 //
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
 
 #include <linux/i2c.h>
 #include <linux/module.h>
@@ -56,5 +56,5 @@ static struct i2c_driver pcm3060_i2c_driver = {
 module_i2c_driver(pcm3060_i2c_driver);
 
 MODULE_DESCRIPTION("PCM3060 I2C driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
 MODULE_LICENSE("GPL v2");
index f6f19fa80932b4920dcf6bf69bab60bd48429ead..3b79734b832bd36926359a230c2031a824b9d66b 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PCM3060 SPI driver
 //
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
 
 #include <linux/module.h>
 #include <linux/spi/spi.h>
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = {
 module_spi_driver(pcm3060_spi_driver);
 
 MODULE_DESCRIPTION("PCM3060 SPI driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
 MODULE_LICENSE("GPL v2");
index 32b26f1c22829d5ccb68537b50566ed797fec745..b2358069cf9b12269b0b8cb78050b8af2f1a6fa8 100644 (file)
@@ -2,7 +2,7 @@
 //
 // PCM3060 codec driver
 //
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
 
 #include <linux/module.h>
 #include <sound/pcm_params.h>
@@ -342,5 +342,5 @@ int pcm3060_probe(struct device *dev)
 EXPORT_SYMBOL(pcm3060_probe);
 
 MODULE_DESCRIPTION("PCM3060 codec driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
+MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
 MODULE_LICENSE("GPL v2");
index 75931c9a9d85027b34d848de9758efb131fcd690..18d51e5dac2cb5f2b7a71f21229282edb52e14e3 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * PCM3060 codec driver
  *
- * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
+ * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
  */
 
 #ifndef _SND_SOC_PCM3060_H
index 5605b660f4bfd4059ca7de8b85899dc78b498f43..0a6ff13d76e136fd6b3e130899ee75b81e09fa16 100644 (file)
@@ -39,7 +39,7 @@ static const struct reg_sequence init_list[] = {
        { RT1011_POWER_9, 0xa840 },
 
        { RT1011_ADC_SET_5, 0x0a20 },
-       { RT1011_DAC_SET_2, 0xa232 },
+       { RT1011_DAC_SET_2, 0xa032 },
        { RT1011_ADC_SET_1, 0x2925 },
 
        { RT1011_SPK_PRO_DC_DET_1, 0xb00c },
@@ -1917,7 +1917,7 @@ static int rt1011_set_bias_level(struct snd_soc_component *component,
                snd_soc_component_write(component,
                        RT1011_SYSTEM_RESET_2, 0x0000);
                snd_soc_component_write(component,
-                       RT1011_SYSTEM_RESET_3, 0x0000);
+                       RT1011_SYSTEM_RESET_3, 0x0001);
                snd_soc_component_write(component,
                        RT1011_SYSTEM_RESET_1, 0x003f);
                snd_soc_component_write(component,
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 30a4e8399ec38eef1de4ac8e26118c59f77894d9..288df245b2f07e16d42329a8da6cdb50b0a8fcd5 100644 (file)
@@ -63,6 +63,7 @@ static int graph_get_dai_id(struct device_node *ep)
        struct device_node *endpoint;
        struct of_endpoint info;
        int i, id;
+       const u32 *reg;
        int ret;
 
        /* use driver specified DAI ID if exist */
@@ -83,8 +84,9 @@ static int graph_get_dai_id(struct device_node *ep)
                        return info.id;
 
                node = of_get_parent(ep);
+               reg = of_get_property(node, "reg", NULL);
                of_node_put(node);
-               if (of_get_property(node, "reg", NULL))
+               if (reg)
                        return info.port;
        }
        node = of_graph_get_port_parent(ep);
@@ -208,10 +210,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        dev_dbg(dev, "link_of DPCM (%pOF)\n", ep);
 
-       of_node_put(ports);
-       of_node_put(port);
-       of_node_put(node);
-
        if (li->cpu) {
                int is_single_links = 0;
 
@@ -229,17 +227,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links);
                if (ret)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "fe.%s",
                                                   cpus->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                /* card->num_links includes Codec */
                asoc_simple_canonicalize_cpu(dai_link, is_single_links);
@@ -263,17 +261,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_codec(ep, dai_link);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "be.%s",
                                                   codecs->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                /* check "prefix" from top node */
                snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -293,19 +291,23 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        ret = asoc_simple_parse_tdm(ep, dai);
        if (ret)
-               return ret;
+               goto out_put_node;
 
        ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep,
                                       NULL, &dai_link->dai_fmt);
        if (ret < 0)
-               return ret;
+               goto out_put_node;
 
        dai_link->dpcm_playback         = 1;
        dai_link->dpcm_capture          = 1;
        dai_link->ops                   = &graph_ops;
        dai_link->init                  = asoc_simple_dai_init;
 
-       return 0;
+out_put_node:
+       of_node_put(ports);
+       of_node_put(port);
+       of_node_put(node);
+       return ret;
 }
 
 static int graph_dai_link_of(struct asoc_simple_priv *priv,
index ac8678fe55ffc3a5e2dbf0322850f7d817728e27..556b1a789629d221a972d161b3c7efa6d8813717 100644 (file)
@@ -349,6 +349,13 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link)
        /* Assumes platform == cpu */
        if (!dai_link->platforms->of_node)
                dai_link->platforms->of_node = dai_link->cpus->of_node;
+
+       /*
+        * DPCM BE can be no platform.
+        * Alloced memory will be waste, but not leak.
+        */
+       if (!dai_link->platforms->of_node)
+               dai_link->num_platforms = 0;
 }
 EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform);
 
index e5cde0d5e63c991b37878c88787fed8262484bb1..ef849151ba563fd549f0b48e47eb7c5ddbecde95 100644 (file)
@@ -124,8 +124,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        li->link++;
 
-       of_node_put(node);
-
        /* For single DAI link & old style of DT node */
        if (is_top)
                prefix = PREFIX;
@@ -147,17 +145,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links);
                if (ret)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "fe.%s",
                                                   cpus->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                asoc_simple_canonicalize_cpu(dai_link, is_single_links);
        } else {
@@ -180,17 +178,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
                ret = asoc_simple_parse_codec(np, dai_link);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                ret = asoc_simple_set_dailink_name(dev, dai_link,
                                                   "be.%s",
                                                   codecs->dai_name);
                if (ret < 0)
-                       return ret;
+                       goto out_put_node;
 
                /* check "prefix" from top node */
                snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -208,19 +206,21 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        ret = asoc_simple_parse_tdm(np, dai);
        if (ret)
-               return ret;
+               goto out_put_node;
 
        ret = asoc_simple_parse_daifmt(dev, node, codec,
                                       prefix, &dai_link->dai_fmt);
        if (ret < 0)
-               return ret;
+               goto out_put_node;
 
        dai_link->dpcm_playback         = 1;
        dai_link->dpcm_capture          = 1;
        dai_link->ops                   = &simple_ops;
        dai_link->init                  = asoc_simple_dai_init;
 
-       return 0;
+out_put_node:
+       of_node_put(node);
+       return ret;
 }
 
 static int simple_dai_link_of(struct asoc_simple_priv *priv,
@@ -364,8 +364,6 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
                        goto error;
                }
 
-               of_node_put(codec);
-
                /* get convert-xxx property */
                memset(&adata, 0, sizeof(adata));
                for_each_child_of_node(node, np)
@@ -387,11 +385,13 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
                                ret = func_noml(priv, np, codec, li, is_top);
 
                        if (ret < 0) {
+                               of_node_put(codec);
                                of_node_put(np);
                                goto error;
                        }
                }
 
+               of_node_put(codec);
                node = of_get_next_child(top, node);
        } while (!is_top && node);
 
index fac09be3cadea272bc1e25fbd9b667f10c188eb1..46612331f5ea7aa21bbf9e70b9945113cab67e5d 100644 (file)
@@ -437,6 +437,14 @@ static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
 
 /* Please keep this list alphabetically sorted */
 static const struct dmi_system_id byt_cht_es8316_quirk_table[] = {
+       {       /* Irbis NB41 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "NB41"),
+               },
+               .driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN2_MAP
+                                       | BYT_CHT_ES8316_JD_INVERTED),
+       },
        {       /* Teclast X98 Plus II */
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
index 229e395868684ebe6efe6aac220e2e489da3673c..4a5adae1d785d60ca5e6b679cae3debf3f85b388 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
+ * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index b94b482ac34f8a1249799f222179be72e8f129ac..1cc801ba92ebbbcfa52f2c34648f0cd9706f2b4f 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-byt-match.c - tables and support for BYT ACPI enumeration.
+ * soc-acpi-intel-byt-match.c - tables and support for BYT ACPI enumeration.
  *
  * Copyright (c) 2017, Intel Corporation.
  */
index b7f11f6be1cf063045716a4cec33a2b17881185f..d0fb43c2b9f68639a6319f40b912501d71f4c004 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-cht-match.c - tables and support for CHT ACPI enumeration.
+ * soc-acpi-intel-cht-match.c - tables and support for CHT ACPI enumeration.
  *
  * Copyright (c) 2017, Intel Corporation.
  */
index c36c0aa4f683250a18085d8adeb28779ec86099d..771b0ef21051e5c1fa68fa3e958fabf2bbd03a42 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
+ * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 616eb09e78a01abf2e83e2615882eaaa0621f4e1..60dea358fa041bbc7c66e428718a1d6a1e8141df 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-glk-match.c - tables and support for GLK ACPI enumeration.
+ * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 68ae43f7b4b2880468198eab3d0c90719b95122d..cc972d2ac6915672114cbf11111fc58104256d15 100644 (file)
@@ -2,7 +2,7 @@
 // Copyright (c) 2018, Intel Corporation.
 
 /*
- * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
+ * soc-acpi-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
  *
  */
 
index d27853e7a3696fc52dc40caccec729e49a8384c6..34eb0baaa951787c0c338233a7254d9ad408be09 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * soc-apci-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
+ * soc-acpi-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
  *
  * Copyright (c) 2017, Intel Corporation.
  */
index 0b430b9b3673681cdf25c2f85ee07b9954e2eda4..38977669b576539035a4edbafcd34924eed3dd64 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-icl-match.c - tables and support for ICL ACPI enumeration.
+ * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 4b331058e8070af6f86f5ff6f37a64c5273ac1a4..e200baa11011871c7ab8f6b2b5c816d54cf8f25c 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
+ * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index 0c9c0edd35b34d93949863f171555ebbda095534..42fa40a8d9326784fe66fb3324aca00cbabfdfd7 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * soc-apci-intel-skl-match.c - tables and support for SKL ACPI enumeration.
+ * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration.
  *
  * Copyright (c) 2018, Intel Corporation.
  *
index f60a71990f662acd40ea1e5cd22bc43464a4eba7..ac75838bbfabe9ec24974571a6761e5fa63ed5d7 100644 (file)
@@ -150,17 +150,17 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)
 
        link = data->dai_link;
 
-       dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
-       if (!dlc)
-               return ERR_PTR(-ENOMEM);
+       for_each_child_of_node(node, np) {
+               dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
+               if (!dlc)
+                       return ERR_PTR(-ENOMEM);
 
-       link->cpus      = &dlc[0];
-       link->platforms = &dlc[1];
+               link->cpus      = &dlc[0];
+               link->platforms = &dlc[1];
 
-       link->num_cpus          = 1;
-       link->num_platforms     = 1;
+               link->num_cpus          = 1;
+               link->num_platforms     = 1;
 
-       for_each_child_of_node(node, np) {
                cpu = of_get_child_by_name(np, "cpu");
                codec = of_get_child_by_name(np, "codec");
 
index 0a34d0eb8dba919e81a5e18cbb8b0c43884161a7..88ebaf6e1880a3aafea7f1dd7a7614aef3e700ee 100644 (file)
@@ -326,7 +326,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
                val |= I2S_CHN_4;
                break;
        case 2:
-       case 1:
                val |= I2S_CHN_2;
                break;
        default:
@@ -459,7 +458,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
        },
        .capture = {
                .stream_name = "Capture",
-               .channels_min = 1,
+               .channels_min = 2,
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_8000_192000,
                .formats = (SNDRV_PCM_FMTBIT_S8 |
@@ -659,7 +658,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
        }
 
        if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
-               if (val >= 1 && val <= 8)
+               if (val >= 2 && val <= 8)
                        soc_dai->capture.channels_max = val;
        }
 
index c5fc24675a330531e5cbc27ca4e34c3ab729354e..782e534d4c0dd0c3d35024bda96320a562672027 100644 (file)
@@ -61,6 +61,37 @@ static const struct snd_kcontrol_new rk_mc_controls[] = {
        SOC_DAPM_PIN_SWITCH("Speaker"),
 };
 
+static int rk_jack_event(struct notifier_block *nb, unsigned long event,
+                        void *data)
+{
+       struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
+       struct snd_soc_dapm_context *dapm = &jack->card->dapm;
+
+       if (event & SND_JACK_MICROPHONE)
+               snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
+       else
+               snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+
+       snd_soc_dapm_sync(dapm);
+
+       return 0;
+}
+
+static struct notifier_block rk_jack_nb = {
+       .notifier_call = rk_jack_event,
+};
+
+static int rk_init(struct snd_soc_pcm_runtime *runtime)
+{
+       /*
+        * The jack has already been created in the rk_98090_headset_init()
+        * function.
+        */
+       snd_soc_jack_notifier_register(&headset_jack, &rk_jack_nb);
+
+       return 0;
+}
+
 static int rk_aif1_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -119,6 +150,7 @@ SND_SOC_DAILINK_DEFS(hifi,
 static struct snd_soc_dai_link rk_dailink = {
        .name = "max98090",
        .stream_name = "Audio",
+       .init = rk_init,
        .ops = &rk_aif1_ops,
        /* set max98090 as slave */
        .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
index dfb6e460e7eb625879885ac0bcf71201c0a6b6b5..f0f5fa9c27d32a464e85a6aebd7fa3b8ad79bfb9 100644 (file)
@@ -284,9 +284,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
        }
 
        of_node_put(cpu);
-       of_node_put(codec);
        if (ret < 0)
-               return ret;
+               goto err_put_node;
 
        ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link);
        if (ret < 0)
@@ -309,7 +308,6 @@ static int odroid_audio_probe(struct platform_device *pdev)
                ret = PTR_ERR(priv->clk_i2s_bus);
                goto err_put_sclk;
        }
-       of_node_put(cpu_dai);
 
        ret = devm_snd_soc_register_card(dev, card);
        if (ret < 0) {
@@ -317,6 +315,8 @@ static int odroid_audio_probe(struct platform_device *pdev)
                goto err_put_clk_i2s;
        }
 
+       of_node_put(cpu_dai);
+       of_node_put(codec);
        return 0;
 
 err_put_clk_i2s:
@@ -326,6 +326,8 @@ err_put_sclk:
 err_put_cpu_dai:
        of_node_put(cpu_dai);
        snd_soc_of_put_dai_link_codecs(codec_link);
+err_put_node:
+       of_node_put(codec);
        return ret;
 }
 
index fd6eaae6c0ed37e38da9fd8a66c5a621047cc20d..44f899b970c2a399bb3cf9b97ce4a93d9264f140 100644 (file)
@@ -1515,8 +1515,11 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
                }
        }
 
-       if (dai_link->dai_fmt)
-               snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+       if (dai_link->dai_fmt) {
+               ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+               if (ret)
+                       return ret;
+       }
 
        ret = soc_post_component_init(rtd, dai_link->name);
        if (ret)
index f013b24c050a17376ff7fe8237624adef1c5406e..2790c00735f3abaa4582fd95854b7134780ae869 100644 (file)
@@ -1157,8 +1157,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
                list_add_tail(&widget->work_list, list);
 
        if (custom_stop_condition && custom_stop_condition(widget, dir)) {
-               widget->endpoints[dir] = 1;
-               return widget->endpoints[dir];
+               list = NULL;
+               custom_stop_condition = NULL;
        }
 
        if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) {
@@ -1195,8 +1195,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
  *
  * Optionally, can be supplied with a function acting as a stopping condition.
  * This function takes the dapm widget currently being examined and the walk
- * direction as an arguments, it should return true if the walk should be
- * stopped and false otherwise.
+ * direction as an arguments, it should return true if widgets from that point
+ * in the graph onwards should not be added to the widget list.
  */
 static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
        struct list_head *list,
@@ -3706,6 +3706,8 @@ request_failed:
                dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
                        w->name, ret);
 
+       kfree_const(w->sname);
+       kfree(w);
        return ERR_PTR(ret);
 }
 
index f2b392998f20dea89b89a3062b948d584f670ae8..ffd8d43945374c65328e9d787bfe78e3ec2b124d 100644 (file)
@@ -101,8 +101,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
                /*
                 * This interrupt is not shared so no need to return IRQ_NONE.
                 */
-               dev_err_ratelimited(sdev->dev,
-                                   "error: nothing to do in IRQ thread\n");
+               dev_dbg_ratelimited(sdev->dev,
+                                   "nothing to do in IPC IRQ thread\n");
        }
 
        /* re-enable IPC interrupt */
index 50244b82600c017a9fe63f3dcb94edff4285ba86..2ecba91f5219d609f214b6697cd72e7758f21ec2 100644 (file)
@@ -224,8 +224,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
                /*
                 * This interrupt is not shared so no need to return IRQ_NONE.
                 */
-               dev_err_ratelimited(sdev->dev,
-                                   "error: nothing to do in IRQ thread\n");
+               dev_dbg_ratelimited(sdev->dev,
+                                   "nothing to do in IPC IRQ thread\n");
        }
 
        /* re-enable IPC interrupt */
index 9b2232908b6528a6adc10bf82bb9682d4e7c004c..7fa5c61169db00f103e7658020e60610534c4c84 100644 (file)
@@ -1002,8 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
        .field_rxchanmap        = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31),
        .field_txchansel        = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2),
        .field_rxchansel        = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2),
-       .get_sr                 = sun8i_i2s_get_sr_wss,
-       .get_wss                = sun8i_i2s_get_sr_wss,
+       .get_sr                 = sun4i_i2s_get_sr,
+       .get_wss                = sun4i_i2s_get_wss,
 };
 
 static int sun4i_i2s_init_regmap_fields(struct device *dev,
index ac59b509ead51de648b09cf8819131e1d13be9d2..bc7bf15ed7a44544b875dc35a4ce4ca73b406c03 100644 (file)
@@ -195,7 +195,7 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
 {
        u32 bit;
 
-       for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) {
+       for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AMUTE) {
                if (enable)
                        mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
                else
@@ -223,6 +223,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
        if (mcasp_is_synchronous(mcasp)) {
                mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
                mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+               mcasp_set_clk_pdir(mcasp, true);
        }
 
        /* Activate serializer(s) */
@@ -1256,6 +1257,28 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params,
+                                           struct snd_pcm_hw_rule *rule)
+{
+       struct davinci_mcasp_ruledata *rd = rule->private;
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_mask nfmt;
+       int i, slot_width;
+
+       snd_mask_none(&nfmt);
+       slot_width = rd->mcasp->slot_width;
+
+       for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+               if (snd_mask_test(fmt, i)) {
+                       if (snd_pcm_format_width(i) <= slot_width) {
+                               snd_mask_set(&nfmt, i);
+                       }
+               }
+       }
+
+       return snd_mask_refine(fmt, &nfmt);
+}
+
 static const unsigned int davinci_mcasp_dai_rates[] = {
        8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
        88200, 96000, 176400, 192000,
@@ -1377,7 +1400,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
        struct davinci_mcasp_ruledata *ruledata =
                                        &mcasp->ruledata[substream->stream];
        u32 max_channels = 0;
-       int i, dir;
+       int i, dir, ret;
        int tdm_slots = mcasp->tdm_slots;
 
        /* Do not allow more then one stream per direction */
@@ -1406,6 +1429,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                        max_channels++;
        }
        ruledata->serializers = max_channels;
+       ruledata->mcasp = mcasp;
        max_channels *= tdm_slots;
        /*
         * If the already active stream has less channels than the calculated
@@ -1431,20 +1455,22 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                                   0, SNDRV_PCM_HW_PARAM_CHANNELS,
                                   &mcasp->chconstr[substream->stream]);
 
-       if (mcasp->slot_width)
-               snd_pcm_hw_constraint_minmax(substream->runtime,
-                                            SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-                                            8, mcasp->slot_width);
+       if (mcasp->slot_width) {
+               /* Only allow formats require <= slot_width bits on the bus */
+               ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_FORMAT,
+                                         davinci_mcasp_hw_rule_slot_width,
+                                         ruledata,
+                                         SNDRV_PCM_HW_PARAM_FORMAT, -1);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * If we rely on implicit BCLK divider setting we should
         * set constraints based on what we can provide.
         */
        if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
-               int ret;
-
-               ruledata->mcasp = mcasp;
-
                ret = snd_pcm_hw_rule_add(substream->runtime, 0,
                                          SNDRV_PCM_HW_PARAM_RATE,
                                          davinci_mcasp_hw_rule_rate,
index b730d97c4de6aca7c44ecedd2ee33fe1ada913b5..90d118cd91641cf9f0471324a02b8a3ac40e17a2 100644 (file)
@@ -275,7 +275,8 @@ retry:
                                goto retry;
                        }
                        spin_unlock(&sound_loader_lock);
-                       return -EBUSY;
+                       r = -EBUSY;
+                       goto fail;
                }
        }
 
index 14fc1e1d5d132486db21a6874ea1b6e82f011b04..c406497c5919be31f4722a22a60ab65192706c5c 100644 (file)
@@ -600,14 +600,13 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
                ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
                                    hiface_pcm_out_urb_handler);
                if (ret < 0)
-                       return ret;
+                       goto error;
        }
 
        ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
        if (ret < 0) {
-               kfree(rt);
                dev_err(&chip->dev->dev, "Cannot create pcm instance\n");
-               return ret;
+               goto error;
        }
 
        pcm->private_data = rt;
@@ -620,4 +619,10 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
 
        chip->pcm = rt;
        return 0;
+
+error:
+       for (i = 0; i < PCM_N_URBS; i++)
+               kfree(rt->out_urbs[i].buffer);
+       kfree(rt);
+       return ret;
 }
index 7498b5191b68e4cf0368599998160ec0eb17f29d..b5927c3d5bc0b0657360ef8aa923c0aa344422bb 100644 (file)
@@ -68,6 +68,7 @@ struct mixer_build {
        unsigned char *buffer;
        unsigned int buflen;
        DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
+       DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
        struct usb_audio_term oterm;
        const struct usbmix_name_map *map;
        const struct usbmix_selector_map *selector_map;
@@ -744,6 +745,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
                return -EINVAL;
        if (!desc->bNrInPins)
                return -EINVAL;
+       if (desc->bLength < sizeof(*desc) + desc->bNrInPins)
+               return -EINVAL;
 
        switch (state->mixer->protocol) {
        case UAC_VERSION_1:
@@ -773,16 +776,25 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
  * parse the source unit recursively until it reaches to a terminal
  * or a branched unit.
  */
-static int check_input_term(struct mixer_build *state, int id,
+static int __check_input_term(struct mixer_build *state, int id,
                            struct usb_audio_term *term)
 {
        int protocol = state->mixer->protocol;
        int err;
        void *p1;
+       unsigned char *hdr;
 
        memset(term, 0, sizeof(*term));
-       while ((p1 = find_audio_control_unit(state, id)) != NULL) {
-               unsigned char *hdr = p1;
+       for (;;) {
+               /* a loop in the terminal chain? */
+               if (test_and_set_bit(id, state->termbitmap))
+                       return -EINVAL;
+
+               p1 = find_audio_control_unit(state, id);
+               if (!p1)
+                       break;
+
+               hdr = p1;
                term->id = id;
 
                if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
@@ -800,7 +812,7 @@ static int check_input_term(struct mixer_build *state, int id,
 
                                        /* call recursively to verify that the
                                         * referenced clock entity is valid */
-                                       err = check_input_term(state, d->bCSourceID, term);
+                                       err = __check_input_term(state, d->bCSourceID, term);
                                        if (err < 0)
                                                return err;
 
@@ -834,7 +846,7 @@ static int check_input_term(struct mixer_build *state, int id,
                        case UAC2_CLOCK_SELECTOR: {
                                struct uac_selector_unit_descriptor *d = p1;
                                /* call recursively to retrieve the channel info */
-                               err = check_input_term(state, d->baSourceID[0], term);
+                               err = __check_input_term(state, d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
                                term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
@@ -897,7 +909,7 @@ static int check_input_term(struct mixer_build *state, int id,
 
                                /* call recursively to verify that the
                                 * referenced clock entity is valid */
-                               err = check_input_term(state, d->bCSourceID, term);
+                               err = __check_input_term(state, d->bCSourceID, term);
                                if (err < 0)
                                        return err;
 
@@ -948,7 +960,7 @@ static int check_input_term(struct mixer_build *state, int id,
                        case UAC3_CLOCK_SELECTOR: {
                                struct uac_selector_unit_descriptor *d = p1;
                                /* call recursively to retrieve the channel info */
-                               err = check_input_term(state, d->baSourceID[0], term);
+                               err = __check_input_term(state, d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
                                term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
@@ -964,7 +976,7 @@ static int check_input_term(struct mixer_build *state, int id,
                                        return -EINVAL;
 
                                /* call recursively to retrieve the channel info */
-                               err = check_input_term(state, d->baSourceID[0], term);
+                               err = __check_input_term(state, d->baSourceID[0], term);
                                if (err < 0)
                                        return err;
 
@@ -982,6 +994,15 @@ static int check_input_term(struct mixer_build *state, int id,
        return -ENODEV;
 }
 
+
+static int check_input_term(struct mixer_build *state, int id,
+                           struct usb_audio_term *term)
+{
+       memset(term, 0, sizeof(*term));
+       memset(state->termbitmap, 0, sizeof(state->termbitmap));
+       return __check_input_term(state, id, term);
+}
+
 /*
  * Feature Unit
  */
index 7ee9d17d0143a1e17670871980034bfda28c3112..e852c7fd61097e566215fd87f8a298351057de04 100644 (file)
@@ -1043,6 +1043,7 @@ found_clock:
 
                pd = kzalloc(sizeof(*pd), GFP_KERNEL);
                if (!pd) {
+                       kfree(fp->chmap);
                        kfree(fp->rate_table);
                        kfree(fp);
                        return NULL;
index 5215e0870bcbaf84e97db8c241260989ed74318f..6a71324be6283eccb0d816a72dd61f66b4527de6 100644 (file)
@@ -204,7 +204,11 @@ int do_pin_fd(int fd, const char *name)
        if (err)
                return err;
 
-       return bpf_obj_pin(fd, name);
+       err = bpf_obj_pin(fd, name);
+       if (err)
+               p_err("can't pin the object (%s): %s", name, strerror(errno));
+
+       return err;
 }
 
 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
@@ -237,7 +241,7 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
 
        fd = get_fd_by_id(id);
        if (fd < 0) {
-               p_err("can't get prog by id (%u): %s", id, strerror(errno));
+               p_err("can't open object by id (%u): %s", id, strerror(errno));
                return -1;
        }
 
index c38686c4465646d495745cfa769a4b6d693829dd..2f2a3c7df3de89d3fdbabfae6bb43ef43fbf006f 100755 (executable)
@@ -13,7 +13,7 @@
 #      the script prints the string "Disabled" to stdout.
 #
 # Each Distro is expected to implement this script in a distro specific
-# fashion. For instance on Distros that ship with Network Manager enabled,
+# fashion. For instance, on Distros that ship with Network Manager enabled,
 # this script can be based on the Network Manager APIs for retrieving DHCP
 # information.
 
index d7e06fe0270eefb29343b82ce4971765c2a981d5..f5597503c771d0790a4750f06b78c0e5edf38df8 100644 (file)
@@ -700,7 +700,7 @@ static void kvp_get_ipconfig_info(char *if_name,
 
 
        /*
-        * Gather the DNS  state.
+        * Gather the DNS state.
         * Since there is no standard way to get this information
         * across various distributions of interest; we just invoke
         * an external script that needs to be ported across distros
@@ -1051,7 +1051,7 @@ static int parse_ip_val_buffer(char *in_buf, int *offset,
        char *start;
 
        /*
-        * in_buf has sequence of characters that are seperated by
+        * in_buf has sequence of characters that are separated by
         * the character ';'. The last sequence does not have the
         * terminating ";" character.
         */
@@ -1386,6 +1386,8 @@ int main(int argc, char *argv[])
                        daemonize = 0;
                        break;
                case 'h':
+                       print_usage(argv);
+                       exit(0);
                default:
                        print_usage(argv);
                        exit(EXIT_FAILURE);
@@ -1490,7 +1492,7 @@ int main(int argc, char *argv[])
                case KVP_OP_GET_IP_INFO:
                        kvp_ip_val = &hv_msg->body.kvp_ip_val;
 
-                       error =  kvp_mac_to_ip(kvp_ip_val);
+                       error = kvp_mac_to_ip(kvp_ip_val);
 
                        if (error)
                                hv_msg->error = error;
index 7ed9f85ef9085103e3d31f86390317fa62102bc9..d10fe35b7f259d4928816626d72d7986fde6dcba 100755 (executable)
@@ -12,7 +12,7 @@
 # be used to configure the interface.
 #
 # Each Distro is expected to implement this script in a distro specific
-# fashion. For instance on Distros that ship with Network Manager enabled,
+# fashion. For instance, on Distros that ship with Network Manager enabled,
 # this script can be based on the Network Manager APIs for configuring the
 # interface.
 #
index efe1e34dd91b40c0a117432b38122087e22f76c8..92902a88f671de94db15303b3e3dda45bbba4894 100644 (file)
@@ -42,7 +42,7 @@ static int vss_do_freeze(char *dir, unsigned int cmd)
         * If a partition is mounted more than once, only the first
         * FREEZE/THAW can succeed and the later ones will get
         * EBUSY/EINVAL respectively: there could be 2 cases:
-        * 1) a user may mount the same partition to differnt directories
+        * 1) a user may mount the same partition to different directories
         *  by mistake or on purpose;
         * 2) The subvolume of btrfs appears to have the same partition
         * mounted more than once.
@@ -218,6 +218,8 @@ int main(int argc, char *argv[])
                        daemonize = 0;
                        break;
                case 'h':
+                       print_usage(argv);
+                       exit(0);
                default:
                        print_usage(argv);
                        exit(EXIT_FAILURE);
index 55e7374bade0d5c581fbee36e3183b77b057858d..099f2c44dbed26e9b6fb8fa9e242fe8ed24ce825 100644 (file)
@@ -4,10 +4,10 @@
 import os
 from optparse import OptionParser
 
+help_msg = "print verbose messages. Try -vv, -vvv for  more verbose messages"
 parser = OptionParser()
-parser.add_option("-v", "--verbose", dest="verbose",
-                  help="print verbose messages. Try -vv, -vvv for \
-                       more verbose messages", action="count")
+parser.add_option(
+       "-v", "--verbose", dest="verbose", help=help_msg, action="count")
 
 (options, args) = parser.parse_args()
 
@@ -21,27 +21,28 @@ if not os.path.isdir(vmbus_sys_path):
        exit(-1)
 
 vmbus_dev_dict = {
-       '{0e0b6031-5213-4934-818b-38d90ced39db}' : '[Operating system shutdown]',
-       '{9527e630-d0ae-497b-adce-e80ab0175caf}' : '[Time Synchronization]',
-       '{57164f39-9115-4e78-ab55-382f3bd5422d}' : '[Heartbeat]',
-       '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}' : '[Data Exchange]',
-       '{35fa2e29-ea23-4236-96ae-3a6ebacba440}' : '[Backup (volume checkpoint)]',
-       '{34d14be3-dee4-41c8-9ae7-6b174977c192}' : '[Guest services]',
-       '{525074dc-8985-46e2-8057-a307dc18a502}' : '[Dynamic Memory]',
-       '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}' : 'Synthetic mouse',
-       '{f912ad6d-2b17-48ea-bd65-f927a61c7684}' : 'Synthetic keyboard',
-       '{da0a7802-e377-4aac-8e77-0558eb1073f8}' : 'Synthetic framebuffer adapter',
-       '{f8615163-df3e-46c5-913f-f2d2f965ed0e}' : 'Synthetic network adapter',
-       '{32412632-86cb-44a2-9b5c-50d1417354f5}' : 'Synthetic IDE Controller',
-       '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
-       '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
-       '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
-       '{44c4f61d-4444-4400-9d52-802e27ede19f}' : 'PCI Express pass-through',
-       '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
-       '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
-       '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
+       '{0e0b6031-5213-4934-818b-38d90ced39db}': '[Operating system shutdown]',
+       '{9527e630-d0ae-497b-adce-e80ab0175caf}': '[Time Synchronization]',
+       '{57164f39-9115-4e78-ab55-382f3bd5422d}': '[Heartbeat]',
+       '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}': '[Data Exchange]',
+       '{35fa2e29-ea23-4236-96ae-3a6ebacba440}': '[Backup (volume checkpoint)]',
+       '{34d14be3-dee4-41c8-9ae7-6b174977c192}': '[Guest services]',
+       '{525074dc-8985-46e2-8057-a307dc18a502}': '[Dynamic Memory]',
+       '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}': 'Synthetic mouse',
+       '{f912ad6d-2b17-48ea-bd65-f927a61c7684}': 'Synthetic keyboard',
+       '{da0a7802-e377-4aac-8e77-0558eb1073f8}': 'Synthetic framebuffer adapter',
+       '{f8615163-df3e-46c5-913f-f2d2f965ed0e}': 'Synthetic network adapter',
+       '{32412632-86cb-44a2-9b5c-50d1417354f5}': 'Synthetic IDE Controller',
+       '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}': 'Synthetic SCSI Controller',
+       '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}': 'Synthetic fiber channel adapter',
+       '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}': 'Synthetic RDMA adapter',
+       '{44c4f61d-4444-4400-9d52-802e27ede19f}': 'PCI Express pass-through',
+       '{276aacf4-ac15-426c-98dd-7521ad3f01fe}': '[Reserved system device]',
+       '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}': '[Reserved system device]',
+       '{3375baf4-9e15-4b30-b765-67acb10d607b}': '[Reserved system device]',
 }
 
+
 def get_vmbus_dev_attr(dev_name, attr):
        try:
                f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
@@ -52,6 +53,7 @@ def get_vmbus_dev_attr(dev_name, attr):
 
        return lines
 
+
 class VMBus_Dev:
        pass
 
@@ -66,12 +68,13 @@ for f in os.listdir(vmbus_sys_path):
 
        chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
        chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
-       chn_vp_mapping = sorted(chn_vp_mapping,
-               key = lambda c : int(c.split(':')[0]))
+       chn_vp_mapping = sorted(
+               chn_vp_mapping, key=lambda c: int(c.split(':')[0]))
 
-       chn_vp_mapping = ['\tRel_ID=%s, target_cpu=%s' %
-                               (c.split(':')[0], c.split(':')[1])
-                                       for c in chn_vp_mapping]
+       chn_vp_mapping = [
+               '\tRel_ID=%s, target_cpu=%s' %
+               (c.split(':')[0], c.split(':')[1]) for c in chn_vp_mapping
+       ]
        d = VMBus_Dev()
        d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
        d.vmbus_id = vmbus_id
@@ -85,7 +88,7 @@ for f in os.listdir(vmbus_sys_path):
        vmbus_dev_list.append(d)
 
 
-vmbus_dev_list  = sorted(vmbus_dev_list, key = lambda d : int(d.vmbus_id))
+vmbus_dev_list = sorted(vmbus_dev_list, key=lambda d: int(d.vmbus_id))
 
 format0 = '%2s: %s'
 format1 = '%2s: Class_ID = %s - %s\n%s'
@@ -95,9 +98,15 @@ for d in vmbus_dev_list:
        if verbose == 0:
                print(('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc))
        elif verbose == 1:
-               print (('VMBUS ID ' + format1) %        \
-                       (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping))
+               print(
+                       ('VMBUS ID ' + format1) %
+                       (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
+               )
        else:
-               print (('VMBUS ID ' + format2) % \
-                       (d.vmbus_id, d.class_id, d.dev_desc, \
-                       d.device_id, d.sysfs_path, d.chn_vp_mapping))
+               print(
+                       ('VMBUS ID ' + format2) %
+                       (
+                               d.vmbus_id, d.class_id, d.dev_desc,
+                               d.device_id, d.sysfs_path, d.chn_vp_mapping
+                       )
+               )
index 4e455018da65f76126719936d8b0672331a3b51e..a5aa7d3ac6a116a7a8d3c08d840c37a70e42e7a4 100644 (file)
@@ -1466,8 +1466,8 @@ union bpf_attr {
  *             If no cookie has been set yet, generate a new cookie. Once
  *             generated, the socket cookie remains stable for the life of the
  *             socket. This helper can be useful for monitoring per socket
- *             networking traffic statistics as it provides a unique socket
- *             identifier per namespace.
+ *             networking traffic statistics as it provides a global socket
+ *             identifier that can be assumed unique.
  *     Return
  *             A 8-byte long non-decreasing number on success, or 0 if the
  *             socket field is missing inside *skb*.
@@ -1571,8 +1571,11 @@ union bpf_attr {
  *             but this is only implemented for native XDP (with driver
  *             support) as of this writing).
  *
- *             All values for *flags* are reserved for future usage, and must
- *             be left at zero.
+ *             The lower two bits of *flags* are used as the return code if
+ *             the map lookup fails. This is so that the return value can be
+ *             one of the XDP program return codes up to XDP_TX, as chosen by
+ *             the caller. Any higher bits in the *flags* argument must be
+ *             unset.
  *
  *             When used to redirect packets to net devices, this helper
  *             provides a high performance increase over **bpf_redirect**\ ().
index 467224feb43b0fa56b5720aa0ff693ad42ce6b32..d821107f55f90ff5c823d4ff1c19432268132a84 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 /* Copyright (c) 2018 Facebook */
 
+#include <endian.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -419,9 +420,9 @@ done:
 
 static bool btf_check_endianness(const GElf_Ehdr *ehdr)
 {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
        return ehdr->e_ident[EI_DATA] == ELFDATA2LSB;
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#elif __BYTE_ORDER == __BIG_ENDIAN
        return ehdr->e_ident[EI_DATA] == ELFDATA2MSB;
 #else
 # error "Unrecognized __BYTE_ORDER__"
index 794dd5064ae8a01d9628c3baade0605a24fa4f44..2b57d7ea78363a7c36da5540d67ff985a5e40963 100644 (file)
@@ -20,6 +20,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
+#include <endian.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <asm/unistd.h>
@@ -181,7 +182,6 @@ struct bpf_program {
        bpf_program_clear_priv_t clear_priv;
 
        enum bpf_attach_type expected_attach_type;
-       int btf_fd;
        void *func_info;
        __u32 func_info_rec_size;
        __u32 func_info_cnt;
@@ -312,7 +312,6 @@ void bpf_program__unload(struct bpf_program *prog)
        prog->instances.nr = -1;
        zfree(&prog->instances.fds);
 
-       zclose(prog->btf_fd);
        zfree(&prog->func_info);
        zfree(&prog->line_info);
 }
@@ -391,7 +390,6 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx,
        prog->instances.fds = NULL;
        prog->instances.nr = -1;
        prog->type = BPF_PROG_TYPE_UNSPEC;
-       prog->btf_fd = -1;
 
        return 0;
 errout:
@@ -612,10 +610,10 @@ errout:
 
 static int bpf_object__check_endianness(struct bpf_object *obj)
 {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
        if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
                return 0;
-#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#elif __BYTE_ORDER == __BIG_ENDIAN
        if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
                return 0;
 #else
@@ -1377,8 +1375,13 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj)
                if (!has_datasec && kind == BTF_KIND_VAR) {
                        /* replace VAR with INT */
                        t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0);
-                       t->size = sizeof(int);
-                       *(int *)(t+1) = BTF_INT_ENC(0, 0, 32);
+                       /*
+                        * using size = 1 is the safest choice, 4 will be too
+                        * big and cause kernel BTF validation failure if
+                        * original variable took less than 4 bytes
+                        */
+                       t->size = 1;
+                       *(int *)(t+1) = BTF_INT_ENC(0, 0, 8);
                } else if (!has_datasec && kind == BTF_KIND_DATASEC) {
                        /* replace DATASEC with STRUCT */
                        struct btf_var_secinfo *v = (void *)(t + 1);
@@ -1500,6 +1503,12 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
                           BTF_ELF_SEC, err);
                btf__free(obj->btf);
                obj->btf = NULL;
+               /* btf_ext can't exist without btf, so free it as well */
+               if (obj->btf_ext) {
+                       btf_ext__free(obj->btf_ext);
+                       obj->btf_ext = NULL;
+               }
+
                if (bpf_object__is_btf_mandatory(obj))
                        return err;
        }
@@ -2276,9 +2285,6 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj,
                prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext);
        }
 
-       if (!insn_offset)
-               prog->btf_fd = btf__fd(obj->btf);
-
        return 0;
 }
 
@@ -2451,7 +2457,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        char *cp, errmsg[STRERR_BUFSIZE];
        int log_buf_size = BPF_LOG_BUF_SIZE;
        char *log_buf;
-       int ret;
+       int btf_fd, ret;
 
        if (!insns || !insns_cnt)
                return -EINVAL;
@@ -2466,7 +2472,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        load_attr.license = license;
        load_attr.kern_version = kern_version;
        load_attr.prog_ifindex = prog->prog_ifindex;
-       load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0;
+       /* if .BTF.ext was loaded, kernel supports associated BTF for prog */
+       if (prog->obj->btf_ext)
+               btf_fd = bpf_object__btf_fd(prog->obj);
+       else
+               btf_fd = -1;
+       load_attr.prog_btf_fd = btf_fd >= 0 ? btf_fd : 0;
        load_attr.func_info = prog->func_info;
        load_attr.func_info_rec_size = prog->func_info_rec_size;
        load_attr.func_info_cnt = prog->func_info_cnt;
@@ -4507,13 +4518,13 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt,
                                     const struct perf_buffer_opts *opts)
 {
        struct perf_buffer_params p = {};
-       struct perf_event_attr attr = {
-               .config = PERF_COUNT_SW_BPF_OUTPUT,
-               .type = PERF_TYPE_SOFTWARE,
-               .sample_type = PERF_SAMPLE_RAW,
-               .sample_period = 1,
-               .wakeup_events = 1,
-       };
+       struct perf_event_attr attr = { 0, };
+
+       attr.config = PERF_COUNT_SW_BPF_OUTPUT,
+       attr.type = PERF_TYPE_SOFTWARE;
+       attr.sample_type = PERF_SAMPLE_RAW;
+       attr.sample_period = 1;
+       attr.wakeup_events = 1;
 
        p.attr = &attr;
        p.sample_cb = opts ? opts->sample_cb : NULL;
@@ -4988,13 +4999,15 @@ int libbpf_num_possible_cpus(void)
        static const char *fcpu = "/sys/devices/system/cpu/possible";
        int len = 0, n = 0, il = 0, ir = 0;
        unsigned int start = 0, end = 0;
+       int tmp_cpus = 0;
        static int cpus;
        char buf[128];
        int error = 0;
        int fd = -1;
 
-       if (cpus > 0)
-               return cpus;
+       tmp_cpus = READ_ONCE(cpus);
+       if (tmp_cpus > 0)
+               return tmp_cpus;
 
        fd = open(fcpu, O_RDONLY);
        if (fd < 0) {
@@ -5017,7 +5030,7 @@ int libbpf_num_possible_cpus(void)
        }
        buf[len] = '\0';
 
-       for (ir = 0, cpus = 0; ir <= len; ir++) {
+       for (ir = 0, tmp_cpus = 0; ir <= len; ir++) {
                /* Each sub string separated by ',' has format \d+-\d+ or \d+ */
                if (buf[ir] == ',' || buf[ir] == '\0') {
                        buf[ir] = '\0';
@@ -5029,13 +5042,15 @@ int libbpf_num_possible_cpus(void)
                        } else if (n == 1) {
                                end = start;
                        }
-                       cpus += end - start + 1;
+                       tmp_cpus += end - start + 1;
                        il = ir + 1;
                }
        }
-       if (cpus <= 0) {
-               pr_warning("Invalid #CPUs %d from %s\n", cpus, fcpu);
+       if (tmp_cpus <= 0) {
+               pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu);
                return -EINVAL;
        }
-       return cpus;
+
+       WRITE_ONCE(cpus, tmp_cpus);
+       return tmp_cpus;
 }
index 5007b5d4fd2c51186a554fb03893dcabd7bef381..680e63066cf39c7f3bd06cdf645b05065060728e 100644 (file)
@@ -317,17 +317,16 @@ static int xsk_load_xdp_prog(struct xsk_socket *xsk)
 
 static int xsk_get_max_queues(struct xsk_socket *xsk)
 {
-       struct ethtool_channels channels;
-       struct ifreq ifr;
+       struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS };
+       struct ifreq ifr = {};
        int fd, err, ret;
 
        fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0)
                return -errno;
 
-       channels.cmd = ETHTOOL_GCHANNELS;
        ifr.ifr_data = (void *)&channels;
-       strncpy(ifr.ifr_name, xsk->ifname, IFNAMSIZ - 1);
+       memcpy(ifr.ifr_name, xsk->ifname, IFNAMSIZ - 1);
        ifr.ifr_name[IFNAMSIZ - 1] = '\0';
        err = ioctl(fd, SIOCETHTOOL, &ifr);
        if (err && errno != EOPNOTSUPP) {
@@ -335,7 +334,7 @@ static int xsk_get_max_queues(struct xsk_socket *xsk)
                goto out;
        }
 
-       if (channels.max_combined == 0 || errno == EOPNOTSUPP)
+       if (err || channels.max_combined == 0)
                /* If the device says it has no channels, then all traffic
                 * is sent to a single stream, so max queues = 1.
                 */
@@ -517,7 +516,7 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
                err = -errno;
                goto out_socket;
        }
-       strncpy(xsk->ifname, ifname, IFNAMSIZ - 1);
+       memcpy(xsk->ifname, ifname, IFNAMSIZ - 1);
        xsk->ifname[IFNAMSIZ - 1] = '\0';
 
        err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
index 6d148a40551ceda23b590184e92cf632dc705f01..adc5a7e44b98223e6350908a417862541ef57513 100644 (file)
@@ -242,7 +242,7 @@ $(OUTPUT)doc.dep : $(wildcard *.txt) build-docdep.perl
        $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
        mv $@+ $@
 
--include $(OUPTUT)doc.dep
+-include $(OUTPUT)doc.dep
 
 _cmds_txt = cmds-ancillaryinterrogators.txt \
        cmds-ancillarymanipulators.txt \
index a19690a17291ebb52a9f0bccf97a356f4af6ade0..c8c86a0c9b793d6f5173d9bc2fa7bb60f7d23f6e 100644 (file)
@@ -6,8 +6,9 @@
 #include "machine.h"
 #include "api/fs/fs.h"
 #include "debug.h"
+#include "symbol.h"
 
-int arch__fix_module_text_start(u64 *start, const char *name)
+int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
 {
        u64 m_start = *start;
        char path[PATH_MAX];
@@ -17,7 +18,35 @@ int arch__fix_module_text_start(u64 *start, const char *name)
        if (sysfs__read_ull(path, (unsigned long long *)start) < 0) {
                pr_debug2("Using module %s start:%#lx\n", path, m_start);
                *start = m_start;
+       } else {
+               /* Successful read of the modules segment text start address.
+                * Calculate difference between module start address
+                * in memory and module text segment start address.
+                * For example module load address is 0x3ff8011b000
+                * (from /proc/modules) and module text segment start
+                * address is 0x3ff8011b870 (from file above).
+                *
+                * Adjust the module size and subtract the GOT table
+                * size located at the beginning of the module.
+                */
+               *size -= (*start - m_start);
        }
 
        return 0;
 }
+
+/* On s390 kernel text segment start is located at very low memory addresses,
+ * for example 0x10000. Modules are located at very high memory addresses,
+ * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment
+ * and beginning of first module's text segment is very big.
+ * Therefore do not fill this gap and do not assign it to the kernel dso map.
+ */
+void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+{
+       if (strchr(p->name, '[') == NULL && strchr(c->name, '['))
+               /* Last kernel symbol mapped to end of page */
+               p->end = roundup(p->end, page_size);
+       else
+               p->end = c->start;
+       pr_debug4("%s sym:%s end:%#lx\n", __func__, p->name, p->end);
+}
index a640ca7aaadaf5c170703a711d91a3fc072e01e5..513cb2f2fa32e08e3d4b531b4709d53b28c4b07a 100644 (file)
@@ -379,8 +379,10 @@ static u8 *alloc_data(ssize_t bytes0, int map_flags,
 
        /* Allocate and initialize all memory on CPU#0: */
        if (init_cpu0) {
-               orig_mask = bind_to_node(0);
-               bind_to_memnode(0);
+               int node = numa_node_of_cpu(0);
+
+               orig_mask = bind_to_node(node);
+               bind_to_memnode(node);
        }
 
        bytes = bytes0 + HPSIZE;
index 66d5a6658daf542489d5eed878b9ed0e1035498a..01931281040563358793d74151233c8989df1082 100644 (file)
@@ -173,7 +173,7 @@ static int set_tracing_cpumask(struct cpu_map *cpumap)
        int last_cpu;
 
        last_cpu = cpu_map__cpu(cpumap, cpumap->nr - 1);
-       mask_size = (last_cpu + 3) / 4 + 1;
+       mask_size = last_cpu / 4 + 2; /* one more byte for EOS */
        mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
 
        cpumask = malloc(mask_size);
index 1a91a197cafb02124b9ca20cda355b7195c51fcd..d413761621b09673e5063a308e544e07c799da67 100644 (file)
@@ -453,6 +453,7 @@ static struct fixed {
        { "inst_retired.any_p", "event=0xc0" },
        { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" },
        { "cpu_clk_unhalted.thread", "event=0x3c" },
+       { "cpu_clk_unhalted.core", "event=0x3c" },
        { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" },
        { NULL, NULL},
 };
index f80c51d5356555a7789f952a1d99985a9f552ac3..d227d74b28f812040159fa6b99148abf9d821480 100644 (file)
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
-#include "../string2.h"
-#include "../config.h"
-#include "../../perf.h"
+#include "../util/util.h"
+#include "../util/string2.h"
+#include "../util/config.h"
+#include "../perf.h"
 #include "libslang.h"
 #include "ui.h"
 #include "util.h"
@@ -14,7 +15,7 @@
 #include "browser.h"
 #include "helpline.h"
 #include "keysyms.h"
-#include "../color.h"
+#include "../util/color.h"
 #include <linux/ctype.h>
 #include <linux/zalloc.h>
 
index bc134b82829d64a55c61663bbfeadac09e14d6df..5a24dd3ce4db9bd13b5637481574cf0bd9b00f87 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
-#include "../cache.h"
+#include "../../util/cache.h"
 #include "../progress.h"
 #include "../libslang.h"
 #include "../ui.h"
index ac9ad2330f930d78fe499d38bdc80937d71bdd3c..163536720149baf525f8d1ce1a978868574f281b 100644 (file)
@@ -1122,7 +1122,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
                goto out;
 
        (*rawp)[0] = tmp;
-       *rawp = skip_spaces(*rawp);
+       *rawp = strim(*rawp);
 
        return 0;
 
index 3acfbe34ebafb53ea806a108e825a7c621164a7d..39cce66b4ebcca3aa071ba59ec43b2830ab83d79 100644 (file)
@@ -751,7 +751,10 @@ size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
        unsigned char *bitmap;
        int last_cpu = cpu_map__cpu(map, map->nr - 1);
 
-       bitmap = zalloc((last_cpu + 7) / 8);
+       if (buf == NULL)
+               return 0;
+
+       bitmap = zalloc(last_cpu / 8 + 1);
        if (bitmap == NULL) {
                buf[0] = '\0';
                return 0;
index cf826eca3aafd7e65379c8caa001bf43e685881b..83b2fbbeeb900e713e733e054392a1eb45efac61 100644 (file)
@@ -1378,6 +1378,7 @@ static int machine__set_modules_path(struct machine *machine)
        return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
 }
 int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
+                               u64 *size __maybe_unused,
                                const char *name __maybe_unused)
 {
        return 0;
@@ -1389,7 +1390,7 @@ static int machine__create_module(void *arg, const char *name, u64 start,
        struct machine *machine = arg;
        struct map *map;
 
-       if (arch__fix_module_text_start(&start, name) < 0)
+       if (arch__fix_module_text_start(&start, &size, name) < 0)
                return -1;
 
        map = machine__findnew_module_map(machine, start, name);
index f70ab98a7bde5d3c4422db17ba082d54e7ffb556..7aa38da26427008eb7dc7a46c7ed16c9932c631c 100644 (file)
@@ -222,7 +222,7 @@ struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
 
 struct map *machine__findnew_module_map(struct machine *machine, u64 start,
                                        const char *filename);
-int arch__fix_module_text_start(u64 *start, const char *name);
+int arch__fix_module_text_start(u64 *start, u64 *size, const char *name);
 
 int machine__load_kallsyms(struct machine *machine, const char *filename);
 
index 173f3378aaa0696a8497881a0b6b98928c1f10a2..4efde7879474cc63e32c4cbbd180495f7da72b5b 100644 (file)
@@ -92,6 +92,11 @@ static int prefix_underscores_count(const char *str)
        return tail - str;
 }
 
+void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
+{
+       p->end = c->start;
+}
+
 const char * __weak arch__normalize_symbol_name(const char *name)
 {
        return name;
@@ -218,7 +223,7 @@ void symbols__fixup_end(struct rb_root_cached *symbols)
                curr = rb_entry(nd, struct symbol, rb_node);
 
                if (prev->end == prev->start && prev->end != curr->start)
-                       prev->end = curr->start;
+                       arch__symbols__fixup_end(prev, curr);
        }
 
        /* Last entry */
index 12755b42ea93c86f6069ccfc93df581803d6ac60..183f630cb5f1b47b1fc7aaaf105814d6df0cb01c 100644 (file)
@@ -288,6 +288,7 @@ const char *arch__normalize_symbol_name(const char *name);
 #define SYMBOL_A 0
 #define SYMBOL_B 1
 
+void arch__symbols__fixup_end(struct symbol *p, struct symbol *c);
 int arch__compare_symbol_names(const char *namea, const char *nameb);
 int arch__compare_symbol_names_n(const char *namea, const char *nameb,
                                 unsigned int n);
index 873ab505ca8071fdf38e2eb8b091e19553f165fc..590793cc51424c163b99e5e35f58b2609f206d70 100644 (file)
@@ -214,14 +214,24 @@ struct comm *thread__comm(const struct thread *thread)
 
 struct comm *thread__exec_comm(const struct thread *thread)
 {
-       struct comm *comm, *last = NULL;
+       struct comm *comm, *last = NULL, *second_last = NULL;
 
        list_for_each_entry(comm, &thread->comm_list, list) {
                if (comm->exec)
                        return comm;
+               second_last = last;
                last = comm;
        }
 
+       /*
+        * 'last' with no start time might be the parent's comm of a synthesized
+        * thread (created by processing a synthesized fork event). For a main
+        * thread, that is very probably wrong. Prefer a later comm to avoid
+        * that case.
+        */
+       if (second_last && !last->start && thread->pid_ == thread->tid)
+               return second_last;
+
        return last;
 }
 
index 11c9c62c33620790f6ff72cba3369721f13fdc4e..c085964e1d05a2d85e589be8565b025e9dda4665 100644 (file)
@@ -57,7 +57,8 @@ TEST_PROGS := test_kmod.sh \
        test_lirc_mode2.sh \
        test_skb_cgroup_id.sh \
        test_flow_dissector.sh \
-       test_xdp_vlan.sh \
+       test_xdp_vlan_mode_generic.sh \
+       test_xdp_vlan_mode_native.sh \
        test_lwt_ip_encap.sh \
        test_tcp_check_syncookie.sh \
        test_tc_tunnel.sh \
index 5aeaa284fc47493decf0fc55b31de7c8a734ac6d..a680628204108b41d0c046a5371cec9f2cfedc0b 100644 (file)
@@ -41,8 +41,7 @@ int sendmsg_v6_prog(struct bpf_sock_addr *ctx)
        }
 
        /* Rewrite destination. */
-       if ((ctx->user_ip6[0] & 0xFFFF) == bpf_htons(0xFACE) &&
-            ctx->user_ip6[0] >> 16 == bpf_htons(0xB00C)) {
+       if (ctx->user_ip6[0] == bpf_htonl(0xFACEB00C)) {
                ctx->user_ip6[0] = bpf_htonl(DST_REWRITE_IP6_0);
                ctx->user_ip6[1] = bpf_htonl(DST_REWRITE_IP6_1);
                ctx->user_ip6[2] = bpf_htonl(DST_REWRITE_IP6_2);
index 51a3a31d1aac47b0e95e27b9ce3cc28d29b94d09..bb8b0da91686f0e14105b7c22bb40a7e762f937f 100755 (executable)
@@ -1,6 +1,14 @@
 #!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Author: Jesper Dangaard Brouer <hawk@kernel.org>
 
-TESTNAME=xdp_vlan
+# Allow wrapper scripts to name test
+if [ -z "$TESTNAME" ]; then
+    TESTNAME=xdp_vlan
+fi
+
+# Default XDP mode
+XDP_MODE=xdpgeneric
 
 usage() {
   echo "Testing XDP + TC eBPF VLAN manipulations: $TESTNAME"
@@ -9,9 +17,23 @@ usage() {
   echo "  -v | --verbose : Verbose"
   echo "  --flush        : Flush before starting (e.g. after --interactive)"
   echo "  --interactive  : Keep netns setup running after test-run"
+  echo "  --mode=XXX     : Choose XDP mode (xdp | xdpgeneric | xdpdrv)"
   echo ""
 }
 
+valid_xdp_mode()
+{
+       local mode=$1
+
+       case "$mode" in
+               xdpgeneric | xdpdrv | xdp)
+                       return 0
+                       ;;
+               *)
+                       return 1
+       esac
+}
+
 cleanup()
 {
        local status=$?
@@ -37,7 +59,7 @@ cleanup()
 
 # Using external program "getopt" to get --long-options
 OPTIONS=$(getopt -o hvfi: \
-    --long verbose,flush,help,interactive,debug -- "$@")
+    --long verbose,flush,help,interactive,debug,mode: -- "$@")
 if (( $? != 0 )); then
     usage
     echo "selftests: $TESTNAME [FAILED] Error calling getopt, unknown option?"
@@ -60,6 +82,11 @@ while true; do
                cleanup
                shift
                ;;
+           --mode )
+               shift
+               XDP_MODE=$1
+               shift
+               ;;
            -- )
                shift
                break
@@ -81,8 +108,14 @@ if [ "$EUID" -ne 0 ]; then
        exit 1
 fi
 
-ip link set dev lo xdp off 2>/dev/null > /dev/null
-if [ $? -ne 0 ];then
+valid_xdp_mode $XDP_MODE
+if [ $? -ne 0 ]; then
+       echo "selftests: $TESTNAME [FAILED] unknown XDP mode ($XDP_MODE)"
+       exit 1
+fi
+
+ip link set dev lo xdpgeneric off 2>/dev/null > /dev/null
+if [ $? -ne 0 ]; then
        echo "selftests: $TESTNAME [SKIP] need ip xdp support"
        exit 0
 fi
@@ -155,7 +188,7 @@ ip netns exec ns2 ip link set lo up
 # At this point, the hosts cannot reach each-other,
 # because ns2 are using VLAN tags on the packets.
 
-ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Okay ping fails"'
+ip netns exec ns2 sh -c 'ping -W 1 -c 1 100.64.41.1 || echo "Success: First ping must fail"'
 
 
 # Now we can use the test_xdp_vlan.c program to pop/push these VLAN tags
@@ -166,7 +199,7 @@ export FILE=test_xdp_vlan.o
 
 # First test: Remove VLAN by setting VLAN ID 0, using "xdp_vlan_change"
 export XDP_PROG=xdp_vlan_change
-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
 
 # In ns1: egress use TC to add back VLAN tag 4011
 #  (del cmd)
@@ -177,8 +210,8 @@ ip netns exec ns1 tc filter add dev $DEVNS1 egress \
   prio 1 handle 1 bpf da obj $FILE sec tc_vlan_push
 
 # Now the namespaces can reach each-other, test with ping:
-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
+ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
 
 # Second test: Replace xdp prog, that fully remove vlan header
 #
@@ -187,9 +220,9 @@ ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
 # ETH_P_8021Q indication, and this cause overwriting of our changes.
 #
 export XDP_PROG=xdp_vlan_remove_outer2
-ip netns exec ns1 ip link set $DEVNS1 xdp off
-ip netns exec ns1 ip link set $DEVNS1 xdp object $FILE section $XDP_PROG
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE off
+ip netns exec ns1 ip link set $DEVNS1 $XDP_MODE object $FILE section $XDP_PROG
 
 # Now the namespaces should still be able reach each-other, test with ping:
-ip netns exec ns2 ping -W 2 -c 3 $IPADDR1
-ip netns exec ns1 ping -W 2 -c 3 $IPADDR2
+ip netns exec ns2 ping -i 0.2 -W 2 -c 2 $IPADDR1
+ip netns exec ns1 ping -i 0.2 -W 2 -c 2 $IPADDR2
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh b/tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh
new file mode 100755 (executable)
index 0000000..c515326
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Exit on failure
+set -e
+
+# Wrapper script to test generic-XDP
+export TESTNAME=xdp_vlan_mode_generic
+./test_xdp_vlan.sh --mode=xdpgeneric
diff --git a/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh b/tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh
new file mode 100755 (executable)
index 0000000..5cf7ce1
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Exit on failure
+set -e
+
+# Wrapper script to test native-XDP
+export TESTNAME=xdp_vlan_mode_native
+./test_xdp_vlan.sh --mode=xdpdrv
index b0fda2877119c4af08277bd0f329f238c193313c..d438193804b212ffa80c94be47e8c1aca392181e 100644 (file)
        .result = ACCEPT,
        .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
 },
+{
+       "read gso_segs from CGROUP_SKB",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
+                   offsetof(struct __sk_buff, gso_segs)),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
+},
 {
        "write gso_segs from CGROUP_SKB",
        .insns = {
index 5e980a5ab69deb857291889abb616d92507c852c..1fc4e61e9f9f0ba84b5d3329d1168446162d3cf1 100644 (file)
        .errstr = "loop detected",
        .prog_type = BPF_PROG_TYPE_TRACEPOINT,
 },
+{
+       "not-taken loop with back jump to 1st insn",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 123),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, -2),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .retval = 123,
+},
+{
+       "taken loop with back jump to 1st insn",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_1, 10),
+       BPF_MOV64_IMM(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
+       BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, -3),
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .retval = 55,
+},
index 41266af0d3dc8b37268ec0a2500ec88391ae82c1..b35da375530afb1a3d2166aeac07c49f4cff11a7 100644 (file)
@@ -1,7 +1,7 @@
+/s390x/sync_regs_test
 /x86_64/cr4_cpuid_sync_test
 /x86_64/evmcs_test
 /x86_64/hyperv_cpuid
-/x86_64/kvm_create_max_vcpus
 /x86_64/mmio_warning_test
 /x86_64/platform_info_test
 /x86_64/set_sregs_test
@@ -13,3 +13,4 @@
 /x86_64/vmx_tsc_adjust_test
 /clear_dirty_log_test
 /dirty_log_test
+/kvm_create_max_vcpus
diff --git a/tools/testing/selftests/kvm/config b/tools/testing/selftests/kvm/config
new file mode 100644 (file)
index 0000000..63ed533
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_KVM=y
+CONFIG_KVM_INTEL=y
+CONFIG_KVM_AMD=y
index 4ce0bc1612f5495444d72f678d6368d54e6a10c1..c7cced739c34bcada309cae1ce7607af04637887 100644 (file)
@@ -17,7 +17,7 @@ tcp_inq
 tls
 txring_overwrite
 ip_defrag
+ipv6_flowlabel
+ipv6_flowlabel_mgr
 so_txtime
-flowlabel
-flowlabel_mgr
 tcp_fastopen_backup_key
index cca2baa03fb81b12f393a1df566dbe0494cabe27..a8d8e8b3dc819f3abc90060eaa0d312632c2145f 100755 (executable)
@@ -93,18 +93,10 @@ sw1_create()
        ip route add vrf v$ol1 192.0.2.16/28 \
           nexthop dev g1a \
           nexthop dev g1b
-
-       tc qdisc add dev $ul1 clsact
-       tc filter add dev $ul1 egress pref 111 prot ipv4 \
-          flower dst_ip 192.0.2.66 action pass
-       tc filter add dev $ul1 egress pref 222 prot ipv4 \
-          flower dst_ip 192.0.2.82 action pass
 }
 
 sw1_destroy()
 {
-       tc qdisc del dev $ul1 clsact
-
        ip route del vrf v$ol1 192.0.2.16/28
 
        ip route del vrf v$ol1 192.0.2.82/32 via 192.0.2.146
@@ -139,10 +131,18 @@ sw2_create()
        ip route add vrf v$ol2 192.0.2.0/28 \
           nexthop dev g2a \
           nexthop dev g2b
+
+       tc qdisc add dev $ul2 clsact
+       tc filter add dev $ul2 ingress pref 111 prot 802.1Q \
+          flower vlan_id 111 action pass
+       tc filter add dev $ul2 ingress pref 222 prot 802.1Q \
+          flower vlan_id 222 action pass
 }
 
 sw2_destroy()
 {
+       tc qdisc del dev $ul2 clsact
+
        ip route del vrf v$ol2 192.0.2.0/28
 
        ip route del vrf v$ol2 192.0.2.81/32 via 192.0.2.145
@@ -187,12 +187,16 @@ setup_prepare()
        sw1_create
        sw2_create
        h2_create
+
+       forwarding_enable
 }
 
 cleanup()
 {
        pre_cleanup
 
+       forwarding_restore
+
        h2_destroy
        sw2_destroy
        sw1_destroy
@@ -211,15 +215,15 @@ multipath4_test()
           nexthop dev g1a weight $weight1 \
           nexthop dev g1b weight $weight2
 
-       local t0_111=$(tc_rule_stats_get $ul1 111 egress)
-       local t0_222=$(tc_rule_stats_get $ul1 222 egress)
+       local t0_111=$(tc_rule_stats_get $ul2 111 ingress)
+       local t0_222=$(tc_rule_stats_get $ul2 222 ingress)
 
        ip vrf exec v$h1 \
           $MZ $h1 -q -p 64 -A 192.0.2.1 -B 192.0.2.18 \
               -d 1msec -t udp "sp=1024,dp=0-32768"
 
-       local t1_111=$(tc_rule_stats_get $ul1 111 egress)
-       local t1_222=$(tc_rule_stats_get $ul1 222 egress)
+       local t1_111=$(tc_rule_stats_get $ul2 111 ingress)
+       local t1_222=$(tc_rule_stats_get $ul2 222 ingress)
 
        local d111=$((t1_111 - t0_111))
        local d222=$((t1_222 - t0_222))
index 41476399e184f9cbb13f4541918e80fea4f18cbf..f6e65674b83cec86c215605048a81e63e0d7c20d 100755 (executable)
@@ -30,7 +30,7 @@ do_test() {
        ip netns exec "${NETNS}" ./tcp_fastopen_backup_key "$1"
        val=$(ip netns exec "${NETNS}" nstat -az | \
                grep TcpExtTCPFastOpenPassiveFail | awk '{print $2}')
-       if [ $val -ne 0 ]; then
+       if [ "$val" != 0 ]; then
                echo "FAIL: TcpExtTCPFastOpenPassiveFail non-zero"
                return 1
        fi
index 090fff9dbc48f11a28ccba2444e80a3ac806a683..4c285b6e1db8c1713b70e6be5092b780bb5e0d6a 100644 (file)
 #define TLS_PAYLOAD_MAX_LEN 16384
 #define SOL_TLS 282
 
+#ifndef ENOTSUPP
+#define ENOTSUPP 524
+#endif
+
+FIXTURE(tls_basic)
+{
+       int fd, cfd;
+       bool notls;
+};
+
+FIXTURE_SETUP(tls_basic)
+{
+       struct sockaddr_in addr;
+       socklen_t len;
+       int sfd, ret;
+
+       self->notls = false;
+       len = sizeof(addr);
+
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr.sin_port = 0;
+
+       self->fd = socket(AF_INET, SOCK_STREAM, 0);
+       sfd = socket(AF_INET, SOCK_STREAM, 0);
+
+       ret = bind(sfd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+       ret = listen(sfd, 10);
+       ASSERT_EQ(ret, 0);
+
+       ret = getsockname(sfd, &addr, &len);
+       ASSERT_EQ(ret, 0);
+
+       ret = connect(self->fd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+
+       self->cfd = accept(sfd, &addr, &len);
+       ASSERT_GE(self->cfd, 0);
+
+       close(sfd);
+
+       ret = setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       if (ret != 0) {
+               ASSERT_EQ(errno, ENOENT);
+               self->notls = true;
+               printf("Failure setting TCP_ULP, testing without tls\n");
+               return;
+       }
+
+       ret = setsockopt(self->cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       ASSERT_EQ(ret, 0);
+}
+
+FIXTURE_TEARDOWN(tls_basic)
+{
+       close(self->fd);
+       close(self->cfd);
+}
+
+/* Send some data through with ULP but no keys */
+TEST_F(tls_basic, base_base)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+
+       ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+};
+
 FIXTURE(tls)
 {
        int fd, cfd;
@@ -165,6 +239,16 @@ TEST_F(tls, msg_more)
        EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
 }
 
+TEST_F(tls, msg_more_unsent)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
+       EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_DONTWAIT), -1);
+}
+
 TEST_F(tls, sendmsg_single)
 {
        struct msghdr msg;
@@ -610,6 +694,42 @@ TEST_F(tls, recv_lowat)
        EXPECT_EQ(memcmp(send_mem, recv_mem + 10, 5), 0);
 }
 
+TEST_F(tls, bidir)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+       int ret;
+
+       if (!self->notls) {
+               struct tls12_crypto_info_aes_gcm_128 tls12;
+
+               memset(&tls12, 0, sizeof(tls12));
+               tls12.info.version = TLS_1_3_VERSION;
+               tls12.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+
+               ret = setsockopt(self->fd, SOL_TLS, TLS_RX, &tls12,
+                                sizeof(tls12));
+               ASSERT_EQ(ret, 0);
+
+               ret = setsockopt(self->cfd, SOL_TLS, TLS_TX, &tls12,
+                                sizeof(tls12));
+               ASSERT_EQ(ret, 0);
+       }
+
+       ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+
+       memset(buf, 0, sizeof(buf));
+
+       EXPECT_EQ(send(self->cfd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->fd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+};
+
 TEST_F(tls, pollin)
 {
        char const *test_str = "test_poll";
@@ -837,6 +957,109 @@ TEST_F(tls, control_msg)
        EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
 }
 
+TEST_F(tls, shutdown)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+       char buf[10];
+
+       ASSERT_EQ(strlen(test_str) + 1, send_len);
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+       EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+       EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+
+       shutdown(self->fd, SHUT_RDWR);
+       shutdown(self->cfd, SHUT_RDWR);
+}
+
+TEST_F(tls, shutdown_unsent)
+{
+       char const *test_str = "test_read";
+       int send_len = 10;
+
+       EXPECT_EQ(send(self->fd, test_str, send_len, MSG_MORE), send_len);
+
+       shutdown(self->fd, SHUT_RDWR);
+       shutdown(self->cfd, SHUT_RDWR);
+}
+
+TEST_F(tls, shutdown_reuse)
+{
+       struct sockaddr_in addr;
+       int ret;
+
+       shutdown(self->fd, SHUT_RDWR);
+       shutdown(self->cfd, SHUT_RDWR);
+       close(self->cfd);
+
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr.sin_port = 0;
+
+       ret = bind(self->fd, &addr, sizeof(addr));
+       EXPECT_EQ(ret, 0);
+       ret = listen(self->fd, 10);
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EINVAL);
+
+       ret = connect(self->fd, &addr, sizeof(addr));
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EISCONN);
+}
+
+TEST(non_established) {
+       struct tls12_crypto_info_aes_gcm_256 tls12;
+       struct sockaddr_in addr;
+       int sfd, ret, fd;
+       socklen_t len;
+
+       len = sizeof(addr);
+
+       memset(&tls12, 0, sizeof(tls12));
+       tls12.info.version = TLS_1_2_VERSION;
+       tls12.info.cipher_type = TLS_CIPHER_AES_GCM_256;
+
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       addr.sin_port = 0;
+
+       fd = socket(AF_INET, SOCK_STREAM, 0);
+       sfd = socket(AF_INET, SOCK_STREAM, 0);
+
+       ret = bind(sfd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+       ret = listen(sfd, 10);
+       ASSERT_EQ(ret, 0);
+
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       EXPECT_EQ(ret, -1);
+       /* TLS ULP not supported */
+       if (errno == ENOENT)
+               return;
+       EXPECT_EQ(errno, ENOTSUPP);
+
+       ret = setsockopt(sfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, ENOTSUPP);
+
+       ret = getsockname(sfd, &addr, &len);
+       ASSERT_EQ(ret, 0);
+
+       ret = connect(fd, &addr, sizeof(addr));
+       ASSERT_EQ(ret, 0);
+
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       ASSERT_EQ(ret, 0);
+
+       ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
+       EXPECT_EQ(ret, -1);
+       EXPECT_EQ(errno, EEXIST);
+
+       close(fd);
+       close(sfd);
+}
+
 TEST(keysizes) {
        struct tls12_crypto_info_aes_gcm_256 tls12;
        struct sockaddr_in addr;
index fe52488a6f729b5a78eaf6dfa10230acb7abe957..16571ac1dab40267fc2141f924839aa671784d1d 100755 (executable)
@@ -321,4 +321,52 @@ else
        ip netns exec nsr1 nft list ruleset
 fi
 
+KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1)
+KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1)
+SPI1=$RANDOM
+SPI2=$RANDOM
+
+if [ $SPI1 -eq $SPI2 ]; then
+       SPI2=$((SPI2+1))
+fi
+
+do_esp() {
+    local ns=$1
+    local me=$2
+    local remote=$3
+    local lnet=$4
+    local rnet=$5
+    local spi_out=$6
+    local spi_in=$7
+
+    ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in  enc aes $KEY_AES  auth sha1 $KEY_SHA mode tunnel sel src $rnet dst $lnet
+    ip -net $ns xfrm state add src $me  dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
+
+    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
+    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow
+    # to fwd decrypted packets after esp processing:
+    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 1 action allow
+
+}
+
+do_esp nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
+
+do_esp nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
+
+ip netns exec nsr1 nft delete table ip nat
+
+# restore default routes
+ip -net ns2 route del 192.168.10.1 via 10.0.2.1
+ip -net ns2 route add default via 10.0.2.1
+ip -net ns2 route add default via dead:2::1
+
+test_tcp_forwarding ns1 ns2
+if [ $? -eq 0 ] ;then
+       echo "PASS: ipsec tunnel mode for ns1/ns2"
+else
+       echo "FAIL: ipsec tunnel mode for ns1/ns2"
+       ip netns exec nsr1 nft list ruleset 1>&2
+       ip netns exec nsr1 cat /proc/net/xfrm_stat 1>&2
+fi
+
 exit $ret
index bf5ebf59c2d4b9ce18f3f4900c42afcd0f7b7985..9cdd2e31ac2c5bff88be689b6b95ec822ef22e66 100644 (file)
         "teardown": [
             "$TC actions flush action skbedit"
         ]
+    },
+    {
+        "id": "630c",
+        "name": "Add batch of 32 skbedit actions with all parameters and cookie",
+        "category": [
+            "actions",
+            "skbedit"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action skbedit",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action skbedit",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action skbedit"
+        ]
+    },
+    {
+        "id": "706d",
+        "name": "Delete batch of 32 skbedit actions with all parameters",
+        "category": [
+            "actions",
+            "skbedit"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action skbedit",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit queue_mapping 2 priority 10 mark 7/0xaabbccdd ptype host inheritdsfield index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action skbedit index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action skbedit",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
     }
 ]
index cc7c7d75800809115bc22d62dbcd4c646a7f35d3..6503b1ce091f824dabbc3f25ddef6059cc6bce1f 100644 (file)
         "teardown": [
             "$TC actions flush action vlan"
         ]
+    },
+    {
+        "id": "294e",
+        "name": "Add batch of 32 vlan push actions with cookie",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan push protocol 802.1q id 4094 priority 7 pipe index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action vlan"
+        ]
+    },
+    {
+        "id": "56f7",
+        "name": "Delete batch of 32 vlan push actions",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan push protocol 802.1q id 4094 priority 7 pipe index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
+    },
+    {
+        "id": "759f",
+        "name": "Add batch of 32 vlan pop actions with cookie",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ]
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan pop continue index \\$i cookie aabbccddeeff112233445566778800a1 \\\"; args=\"\\$args\\$cmd\"; done && $TC actions add \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "32",
+        "teardown": [
+            "$TC actions flush action vlan"
+        ]
+    },
+    {
+        "id": "c84a",
+        "name": "Delete batch of 32 vlan pop actions",
+        "category": [
+            "actions",
+            "vlan"
+        ],
+        "setup": [
+            [
+                "$TC actions flush action vlan",
+                0,
+                1,
+                255
+            ],
+            "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan pop index \\$i \\\"; args=\\\"\\$args\\$cmd\\\"; done && $TC actions add \\$args\""
+        ],
+        "cmdUnderTest": "bash -c \"for i in \\`seq 1 32\\`; do cmd=\\\"action vlan index \\$i \\\"; args=\"\\$args\\$cmd\"; done && $TC actions del \\$args\"",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action vlan",
+        "matchPattern": "^[ \t]+index [0-9]+ ref",
+        "matchCount": "0",
+        "teardown": []
     }
 ]
index acc43242a3101cbae075e6a589cc5450027b40e9..35a069815baf1a4f970e9707460d677cc0e11907 100644 (file)
@@ -144,11 +144,6 @@ out_fail_alloc:
        return ret;
 }
 
-bool kvm_arch_has_vcpu_debugfs(void)
-{
-       return false;
-}
-
 int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
        return 0;
@@ -323,6 +318,17 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
 {
+       /*
+        * If we're about to block (most likely because we've just hit a
+        * WFI), we need to sync back the state of the GIC CPU interface
+        * so that we have the lastest PMR and group enables. This ensures
+        * that kvm_arch_vcpu_runnable has up-to-date data to decide
+        * whether we have pending interrupts.
+        */
+       preempt_disable();
+       kvm_vgic_vmcr_sync(vcpu);
+       preempt_enable();
+
        kvm_vgic_v4_enable_doorbell(vcpu);
 }
 
@@ -340,6 +346,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        /* Set up the timer */
        kvm_timer_vcpu_init(vcpu);
 
+       kvm_pmu_vcpu_init(vcpu);
+
        kvm_arm_reset_debug_ptr(vcpu);
 
        return kvm_vgic_vcpu_init(vcpu);
index 254c5f190a3d660507f22e10799b36eddd160b8b..ccf1fde9836c1e2a5ae041899a0e7675e8837cc2 100644 (file)
@@ -349,8 +349,10 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
        case 7:
                cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
                cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
+               /* Fall through */
        case 6:
                cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
+               /* Fall through */
        default:
                cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
        }
@@ -359,8 +361,10 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
        case 7:
                cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
                cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
+               /* Fall through */
        case 6:
                cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
+               /* Fall through */
        default:
                cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
        }
@@ -382,8 +386,10 @@ void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
        case 7:
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
+               /* Fall through */
        case 6:
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
+               /* Fall through */
        default:
                __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
        }
@@ -392,8 +398,10 @@ void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
        case 7:
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
+               /* Fall through */
        case 6:
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
+               /* Fall through */
        default:
                __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
        }
index 3dd8238ed2462eeeb04e5c7cfa2735e3782d02bd..362a01886bab9ef64ca89b61de1ff93ddf26e1bb 100644 (file)
@@ -214,6 +214,20 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
        kvm_pmu_release_perf_event(pmc);
 }
 
+/**
+ * kvm_pmu_vcpu_init - assign pmu counter idx for cpu
+ * @vcpu: The vcpu pointer
+ *
+ */
+void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       int i;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
+               pmu->pmc[i].idx = i;
+}
+
 /**
  * kvm_pmu_vcpu_reset - reset pmu state for cpu
  * @vcpu: The vcpu pointer
@@ -224,10 +238,8 @@ void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
        int i;
        struct kvm_pmu *pmu = &vcpu->arch.pmu;
 
-       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
                kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]);
-               pmu->pmc[i].idx = i;
-       }
 
        bitmap_zero(vcpu->arch.pmu.chained, ARMV8_PMU_MAX_COUNTER_PAIRS);
 }
index 3ba7278fb533be5acdba3c339358039eb6b472e0..44efc2ff863f4b903075d55476e4374862c619dd 100644 (file)
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               if (vgic_irq_is_mapped_level(irq)) {
+                       bool was_high = irq->line_level;
+
+                       /*
+                        * We need to update the state of the interrupt because
+                        * the guest might have changed the state of the device
+                        * while the interrupt was disabled at the VGIC level.
+                        */
+                       irq->line_level = vgic_get_phys_line_level(irq);
+                       /*
+                        * Deactivate the physical interrupt so the GIC will let
+                        * us know when it is asserted again.
+                        */
+                       if (!irq->active && was_high && !irq->line_level)
+                               vgic_irq_set_phys_active(irq, false);
+               }
                irq->enabled = true;
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
index 6dd5ad706c927190152eb979dc2498b75d03a809..96aab77d04718a00164abd251566aaa8e2167b48 100644 (file)
@@ -484,10 +484,17 @@ void vgic_v2_load(struct kvm_vcpu *vcpu)
                       kvm_vgic_global_state.vctrl_base + GICH_APR);
 }
 
-void vgic_v2_put(struct kvm_vcpu *vcpu)
+void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu)
 {
        struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 
        cpu_if->vgic_vmcr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VMCR);
+}
+
+void vgic_v2_put(struct kvm_vcpu *vcpu)
+{
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+
+       vgic_v2_vmcr_sync(vcpu);
        cpu_if->vgic_apr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_APR);
 }
index c2c9ce009f6381556cf71f520c680af78fae4525..0c653a1e5215280f4076db92fdb1db61b7b01386 100644 (file)
@@ -662,12 +662,17 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
                __vgic_v3_activate_traps(vcpu);
 }
 
-void vgic_v3_put(struct kvm_vcpu *vcpu)
+void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 
        if (likely(cpu_if->vgic_sre))
                cpu_if->vgic_vmcr = kvm_call_hyp_ret(__vgic_v3_read_vmcr);
+}
+
+void vgic_v3_put(struct kvm_vcpu *vcpu)
+{
+       vgic_v3_vmcr_sync(vcpu);
 
        kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
 
index 04786c8ec77ed8e4a48b085c029ba2d03a008d4a..13d4b38a94ec4b81af13cd739497ae6db9640a55 100644 (file)
@@ -919,6 +919,17 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu)
                vgic_v3_put(vcpu);
 }
 
+void kvm_vgic_vmcr_sync(struct kvm_vcpu *vcpu)
+{
+       if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
+               return;
+
+       if (kvm_vgic_global_state.type == VGIC_V2)
+               vgic_v2_vmcr_sync(vcpu);
+       else
+               vgic_v3_vmcr_sync(vcpu);
+}
+
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
index 3b7525deec80e7b1e23eff1c60d971428f1d73ab..797e05004d807a1041b4711488913f78f98636bb 100644 (file)
@@ -193,6 +193,7 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 void vgic_v2_init_lrs(void);
 void vgic_v2_load(struct kvm_vcpu *vcpu);
 void vgic_v2_put(struct kvm_vcpu *vcpu);
+void vgic_v2_vmcr_sync(struct kvm_vcpu *vcpu);
 
 void vgic_v2_save_state(struct kvm_vcpu *vcpu);
 void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
@@ -223,6 +224,7 @@ bool vgic_v3_check_base(struct kvm *kvm);
 
 void vgic_v3_load(struct kvm_vcpu *vcpu);
 void vgic_v3_put(struct kvm_vcpu *vcpu);
+void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu);
 
 bool vgic_has_its(struct kvm *kvm);
 int kvm_vgic_register_its_device(void);
index 887f3b0c2b602d4cd4f81ebf137b8c04e112077c..c6a91b044d8d62d00a259590927b83d58b853394 100644 (file)
@@ -1855,8 +1855,7 @@ void kvm_set_pfn_dirty(kvm_pfn_t pfn)
        if (!kvm_is_reserved_pfn(pfn)) {
                struct page *page = pfn_to_page(pfn);
 
-               if (!PageReserved(page))
-                       SetPageDirty(page);
+               SetPageDirty(page);
        }
 }
 EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
@@ -2477,6 +2476,29 @@ static bool kvm_vcpu_eligible_for_directed_yield(struct kvm_vcpu *vcpu)
 #endif
 }
 
+/*
+ * Unlike kvm_arch_vcpu_runnable, this function is called outside
+ * a vcpu_load/vcpu_put pair.  However, for most architectures
+ * kvm_arch_vcpu_runnable does not require vcpu_load.
+ */
+bool __weak kvm_arch_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       return kvm_arch_vcpu_runnable(vcpu);
+}
+
+static bool vcpu_dy_runnable(struct kvm_vcpu *vcpu)
+{
+       if (kvm_arch_dy_runnable(vcpu))
+               return true;
+
+#ifdef CONFIG_KVM_ASYNC_PF
+       if (!list_empty_careful(&vcpu->async_pf.done))
+               return true;
+#endif
+
+       return false;
+}
+
 void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
 {
        struct kvm *kvm = me->kvm;
@@ -2506,9 +2528,10 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
                                continue;
                        if (vcpu == me)
                                continue;
-                       if (swait_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
+                       if (swait_active(&vcpu->wq) && !vcpu_dy_runnable(vcpu))
                                continue;
-                       if (yield_to_kernel_mode && !kvm_arch_vcpu_in_kernel(vcpu))
+                       if (READ_ONCE(vcpu->preempted) && yield_to_kernel_mode &&
+                               !kvm_arch_vcpu_in_kernel(vcpu))
                                continue;
                        if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
                                continue;
@@ -2591,30 +2614,20 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)
        return anon_inode_getfd(name, &kvm_vcpu_fops, vcpu, O_RDWR | O_CLOEXEC);
 }
 
-static int kvm_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
+static void kvm_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
 {
+#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS
        char dir_name[ITOA_MAX_LEN * 2];
-       int ret;
-
-       if (!kvm_arch_has_vcpu_debugfs())
-               return 0;
 
        if (!debugfs_initialized())
-               return 0;
+               return;
 
        snprintf(dir_name, sizeof(dir_name), "vcpu%d", vcpu->vcpu_id);
        vcpu->debugfs_dentry = debugfs_create_dir(dir_name,
-                                                               vcpu->kvm->debugfs_dentry);
-       if (!vcpu->debugfs_dentry)
-               return -ENOMEM;
-
-       ret = kvm_arch_create_vcpu_debugfs(vcpu);
-       if (ret < 0) {
-               debugfs_remove_recursive(vcpu->debugfs_dentry);
-               return ret;
-       }
+                                                 vcpu->kvm->debugfs_dentry);
 
-       return 0;
+       kvm_arch_create_vcpu_debugfs(vcpu);
+#endif
 }
 
 /*
@@ -2649,9 +2662,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        if (r)
                goto vcpu_destroy;
 
-       r = kvm_create_vcpu_debugfs(vcpu);
-       if (r)
-               goto vcpu_destroy;
+       kvm_create_vcpu_debugfs(vcpu);
 
        mutex_lock(&kvm->lock);
        if (kvm_get_vcpu_by_id(kvm, id)) {
@@ -4205,7 +4216,7 @@ static void kvm_sched_in(struct preempt_notifier *pn, int cpu)
 {
        struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
 
-       vcpu->preempted = false;
+       WRITE_ONCE(vcpu->preempted, false);
        WRITE_ONCE(vcpu->ready, false);
 
        kvm_arch_sched_in(vcpu, cpu);
@@ -4219,7 +4230,7 @@ static void kvm_sched_out(struct preempt_notifier *pn,
        struct kvm_vcpu *vcpu = preempt_notifier_to_vcpu(pn);
 
        if (current->state == TASK_RUNNING) {
-               vcpu->preempted = true;
+               WRITE_ONCE(vcpu->preempted, true);
                WRITE_ONCE(vcpu->ready, true);
        }
        kvm_arch_vcpu_put(vcpu);