Merge tag 'mmc-v5.9-rc4-4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Oct 2020 17:10:52 +0000 (10:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Oct 2020 17:10:52 +0000 (10:10 -0700)
Pull MMC fix from Ulf Hansson:
 "Assign a proper discard granularity rather than incorrectly set it to
  zero"

* tag 'mmc-v5.9-rc4-4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: core: don't set limits.discard_granularity as 0

957 files changed:
.mailmap
Documentation/admin-guide/cgroup-v2.rst
Documentation/admin-guide/device-mapper/dm-crypt.rst
Documentation/admin-guide/dynamic-debug-howto.rst
Documentation/admin-guide/pm/cpuidle.rst
Documentation/bpf/ringbuf.rst
Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml
Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.yaml
Documentation/devicetree/bindings/dma/xilinx/xlnx,zynqmp-dpdma.yaml
Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
Documentation/devicetree/bindings/media/i2c/imx274.txt [deleted file]
Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/net/renesas,ravb.txt
Documentation/devicetree/bindings/spi/brcm,spi-bcm-qspi.txt
Documentation/driver-api/dma-buf.rst
Documentation/features/debug/debug-vm-pgtable/arch-support.txt
Documentation/kbuild/llvm.rst
Documentation/networking/ethtool-netlink.rst
Documentation/userspace-api/media/v4l/buffer.rst
Documentation/userspace-api/media/v4l/vidioc-create-bufs.rst
Documentation/userspace-api/media/v4l/vidioc-reqbufs.rst
Documentation/virt/kvm/api.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/at91-sama5d2_icp.dts
arch/arm/boot/dts/bcm-hr2.dtsi
arch/arm/boot/dts/bcm-nsp.dtsi
arch/arm/boot/dts/bcm2835-rpi.dtsi
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/imx6q-logicpd.dts
arch/arm/boot/dts/imx6q-prtwd2.dts
arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
arch/arm/boot/dts/imx6sx-pinfunc.h
arch/arm/boot/dts/imx7d-zii-rmu2.dts
arch/arm/boot/dts/imx7ulp.dtsi
arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi
arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi
arch/arm/boot/dts/ls1021a.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/socfpga_arria10.dtsi
arch/arm/boot/dts/vfxxx.dtsi
arch/arm/configs/integrator_defconfig
arch/arm/mach-imx/cpuidle-imx6q.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/xen/enlighten.c
arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
arch/arm64/boot/dts/freescale/Makefile
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/xilinx/zynqmp.dtsi
arch/arm64/configs/defconfig
arch/arm64/crypto/aes-neonbs-core.S
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kernel/acpi.c
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/paravirt.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/nvhe/tlb.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pvtime.c
arch/arm64/kvm/trace_arm.h
arch/arm64/kvm/trace_handle_exit.h
arch/arm64/net/bpf_jit_comp.c
arch/ia64/include/asm/acpi.h
arch/ia64/mm/init.c
arch/mips/Kconfig
arch/mips/bcm47xx/setup.c
arch/mips/include/asm/cpu-type.h
arch/mips/kvm/mips.c
arch/mips/loongson2ef/Platform
arch/mips/loongson64/cop2-ex.c
arch/mips/sni/a20r.c
arch/openrisc/include/asm/uaccess.h
arch/openrisc/kernel/setup.c
arch/openrisc/mm/cache.c
arch/powerpc/Kconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/powerpc/include/asm/book3s/64/mmu.h
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/vdso32/Makefile
arch/powerpc/kernel/vdso32/vdso32.lds.S
arch/powerpc/kernel/vdso64/Makefile
arch/powerpc/kernel/vdso64/vdso64.lds.S
arch/powerpc/mm/book3s64/radix_pgtable.c
arch/powerpc/mm/init_64.c
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/riscv/Kconfig
arch/riscv/boot/dts/kendryte/k210.dtsi
arch/riscv/include/asm/clint.h [new file with mode: 0644]
arch/riscv/include/asm/ftrace.h
arch/riscv/include/asm/stackprotector.h
arch/riscv/include/asm/timex.h
arch/riscv/kernel/ftrace.c
arch/riscv/mm/init.c
arch/s390/include/asm/pgtable.h
arch/s390/kernel/entry.h
arch/s390/kernel/idle.c
arch/s390/kernel/pgm_check.S
arch/s390/kernel/setup.c
arch/s390/mm/fault.c
arch/s390/pci/pci.c
arch/s390/pci/pci_event.c
arch/sh/include/asm/smp.h
arch/sh/kernel/entry-common.S
arch/sh/kernel/ptrace_32.c
arch/x86/boot/compressed/Makefile
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/entry/common.c
arch/x86/entry/entry_64.S
arch/x86/include/asm/acpi.h
arch/x86/include/asm/frame.h
arch/x86/include/asm/idtentry.h
arch/x86/include/asm/irq_stack.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/irq.c
arch/x86/kernel/irq_64.c
arch/x86/kernel/kvm.c
arch/x86/kernel/process.c
arch/x86/kvm/emulate.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/nested.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/lib/usercopy_64.c
block/bfq-iosched.c
block/bio.c
block/blk-mq-sched.h
block/blk-mq.c
block/blk-settings.c
block/partitions/core.c
block/partitions/ibm.c
block/scsi_ioctl.c
drivers/acpi/processor_idle.c
drivers/atm/eni.c
drivers/base/core.c
drivers/base/firmware_loader/firmware.h
drivers/base/firmware_loader/main.c
drivers/base/node.c
drivers/base/regmap/internal.h
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap.c
drivers/block/drbd/drbd_main.c
drivers/block/rbd.c
drivers/clk/bcm/Kconfig
drivers/clk/davinci/pll.c
drivers/clk/qcom/lpasscorecc-sc7180.c
drivers/clk/rockchip/clk-rk3228.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/socfpga/clk-s10.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra210-emc.c
drivers/clk/versatile/clk-impd1.c
drivers/clocksource/h8300_timer8.c
drivers/clocksource/timer-clint.c
drivers/clocksource/timer-gx6605s.c
drivers/clocksource/timer-ti-dm-systimer.c
drivers/counter/microchip-tcb-capture.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle-psci.c
drivers/cpuidle/cpuidle-pseries.c
drivers/cpuidle/cpuidle.c
drivers/dax/super.c
drivers/devfreq/devfreq.c
drivers/devfreq/tegra30-devfreq.c
drivers/dma-buf/dma-buf.c
drivers/dma-buf/dma-fence-chain.c
drivers/dma/dmatest.c
drivers/edac/ghes_edac.c
drivers/firmware/efi/efibc.c
drivers/firmware/efi/embedded-firmware.c
drivers/gpio/gpio-amd-fch.c
drivers/gpio/gpio-aspeed-sgpio.c
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-siox.c
drivers/gpio/gpio-sprd.c
drivers/gpio/gpio-tc3589x.c
drivers/gpio/gpiolib-cdev.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn30/Makefile
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.h
drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_default.h
drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h
drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h
drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_3_0_0_sh_mask.h
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gem/i915_gem_object.h
drivers/gpu/drm/i915/gem/i915_gem_pages.c
drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_sw_fence.c
drivers/gpu/drm/i915/selftests/mock_gem_device.c
drivers/gpu/drm/ingenic/ingenic-drm-drv.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/msm/adreno/a2xx_gpu.c
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
drivers/gpu/drm/msm/adreno/a4xx_gpu.c
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/adreno/a5xx_gpu.h
drivers/gpu/drm/msm/adreno/a5xx_preempt.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_ringbuffer.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
drivers/gpu/drm/sun4i/sun8i_csc.h
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/tve200/tve200_display.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/virtio/virtgpu_display.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
drivers/gpu/drm/vmwgfx/vmwgfx_thp.c
drivers/gpu/drm/xlnx/Kconfig
drivers/hv/channel_mgmt.c
drivers/hv/vmbus_drv.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-npcm7xx.c
drivers/i2c/i2c-core-base.c
drivers/iio/accel/bmc150-accel-core.c
drivers/iio/accel/kxsd9.c
drivers/iio/accel/mma7455_core.c
drivers/iio/accel/mma8452.c
drivers/iio/adc/Kconfig
drivers/iio/adc/ad7124.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/max1118.c
drivers/iio/adc/mcp3422.c
drivers/iio/adc/meson_saradc.c
drivers/iio/adc/qcom-spmi-adc5.c
drivers/iio/adc/ti-adc081c.c
drivers/iio/adc/ti-adc084s021.c
drivers/iio/adc/ti-ads1015.c
drivers/iio/chemical/ccs811.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/light/ltr501.c
drivers/iio/light/max44000.c
drivers/iio/magnetometer/ak8975.c
drivers/iio/proximity/mb1232.c
drivers/infiniband/core/cache.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/cq.c
drivers/infiniband/core/device.c
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
drivers/infiniband/hw/bnxt_re/qplib_sp.c
drivers/infiniband/hw/bnxt_re/qplib_sp.h
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/sw/rxe/rxe.c
drivers/infiniband/sw/rxe/rxe.h
drivers/infiniband/sw/rxe/rxe_mr.c
drivers/infiniband/sw/rxe/rxe_sysfs.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
drivers/infiniband/ulp/rtrs/rtrs-srv.c
drivers/input/mouse/trackpoint.c
drivers/input/mouse/trackpoint.h
drivers/input/serio/i8042-x86ia64io.h
drivers/interconnect/core.c
drivers/interconnect/qcom/bcm-voter.c
drivers/iommu/amd/init.c
drivers/iommu/amd/iommu.c
drivers/iommu/exynos-iommu.c
drivers/iommu/intel/iommu.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/media/cec/core/cec-adap.c
drivers/media/common/videobuf2/videobuf2-core.c
drivers/media/common/videobuf2/videobuf2-dma-contig.c
drivers/media/common/videobuf2/videobuf2-dma-sg.c
drivers/media/common/videobuf2/videobuf2-v4l2.c
drivers/media/dvb-core/dvb_vb2.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/misc/eeprom/at24.c
drivers/misc/habanalabs/common/debugfs.c
drivers/misc/habanalabs/include/gaudi/gaudi_masks.h
drivers/mtd/spi-nor/core.c
drivers/mtd/spi-nor/core.h
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/ocelot/seville_vsc9953.c
drivers/net/dsa/rtl8366.c
drivers/net/ethernet/3com/typhoon.h
drivers/net/ethernet/aquantia/atlantic/Makefile
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/freescale/dpaa2/dpmac-cmd.h
drivers/net/ethernet/freescale/dpaa2/dpni-cmd.h
drivers/net/ethernet/freescale/enetc/enetc_pf.c
drivers/net/ethernet/freescale/xgmac_mdio.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/huawei/hinic/Kconfig
drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
drivers/net/ethernet/huawei/hinic/hinic_main.c
drivers/net/ethernet/huawei/hinic/hinic_port.c
drivers/net/ethernet/huawei/hinic/hinic_rx.c
drivers/net/ethernet/huawei/hinic/hinic_sriov.c
drivers/net/ethernet/huawei/hinic/hinic_tx.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_common.c
drivers/net/ethernet/intel/ice/ice_fw_update.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_lib.h
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/lantiq_xrx200.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/octeontx2/af/mbox.c
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.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_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_net.c
drivers/net/ethernet/mscc/ocelot_vsc7514.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qede/qede_filter.c
drivers/net/ethernet/qlogic/qede/qede_main.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/sfc/ef100.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/geneve.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/adf7242.c
drivers/net/ieee802154/ca8210.c
drivers/net/ipa/ipa_table.c
drivers/net/macsec.c
drivers/net/phy/Kconfig
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/realtek.c
drivers/net/team/team.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/pegasus.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/rndis_host.c
drivers/net/usb/rtl8150.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_ppp.c
drivers/net/wan/lapbether.c
drivers/net/wan/x25_asy.c
drivers/net/wireguard/noise.c
drivers/net/wireguard/peerlookup.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
drivers/net/wireless/marvell/mwifiex/fw.h
drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
drivers/net/wireless/mediatek/mt76/mt7615/init.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/quantenna/qtnfmac/core.c
drivers/net/wireless/ti/wlcore/cmd.h
drivers/net/wireless/ti/wlcore/main.c
drivers/nvme/host/Kconfig
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/fc.c
drivers/nvme/host/hwmon.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/passthru.c
drivers/pci/controller/pcie-rockchip-host.c
drivers/phy/qualcomm/phy-qcom-ipq806x-usb.c
drivers/phy/qualcomm/phy-qcom-qmp.c
drivers/phy/qualcomm/phy-qcom-qmp.h
drivers/phy/ti/phy-am654-serdes.c
drivers/phy/ti/phy-omap-usb2.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
drivers/pinctrl/mvebu/pinctrl-armada-xp.c
drivers/pinctrl/qcom/pinctrl-sm8250.c
drivers/platform/olpc/olpc-ec.c
drivers/platform/x86/Kconfig
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/intel_pmc_core_pltdrv.c
drivers/platform/x86/mlx-platform.c
drivers/platform/x86/pcengines-apuv2.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/powercap/intel_rapl_common.c
drivers/rapidio/Kconfig
drivers/regulator/axp20x-regulator.c
drivers/regulator/core.c
drivers/regulator/cros-ec-regulator.c
drivers/regulator/fixed.c
drivers/regulator/pwm-regulator.c
drivers/s390/block/dasd_fba.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/libfc/fc_disc.c
drivers/scsi/libiscsi_tcp.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sd_zbc.c
drivers/soundwire/bus.c
drivers/soundwire/stream.c
drivers/spi/spi-bcm-qspi.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-cadence-quadspi.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-loopback-test.c
drivers/spi/spi-stm32.c
drivers/spi/spi.c
drivers/staging/greybus/audio_helper.c
drivers/staging/greybus/audio_topology.c
drivers/staging/wlan-ng/hfa384x_usb.c
drivers/staging/wlan-ng/prism2usb.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_login.h
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/target_core_transport.c
drivers/thunderbolt/eeprom.c
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/tunnel.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/serial_core.c
drivers/usb/class/usblp.c
drivers/usb/core/driver.c
drivers/usb/core/message.c
drivers/usb/core/quirks.c
drivers/usb/core/sysfs.c
drivers/usb/dwc3/dwc3-meson-g12a.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/storage/uas.c
drivers/usb/typec/mux/intel_pmc_mux.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi_acpi.c
drivers/usb/usbip/stub_dev.c
drivers/vdpa/Kconfig
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vhost/iotlb.c
drivers/vhost/vdpa.c
drivers/vhost/vhost.c
drivers/video/console/Kconfig
drivers/video/console/newport_con.c
drivers/video/console/vgacon.c
drivers/video/fbdev/Kconfig
drivers/video/fbdev/Makefile
drivers/video/fbdev/amba-clcd.c [new file with mode: 0644]
drivers/video/fbdev/core/bitblit.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbcon.h
drivers/video/fbdev/core/fbcon_ccw.c
drivers/video/fbdev/core/fbcon_cw.c
drivers/video/fbdev/core/fbcon_rotate.c
drivers/video/fbdev/core/fbcon_ud.c
drivers/video/fbdev/core/tileblit.c
drivers/video/fbdev/vga16fb.c
drivers/xen/events/events_base.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/write.c
fs/autofs/waitq.c
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/ioctl.c
fs/btrfs/print-tree.c
fs/btrfs/sysfs.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/cifs/inode.c
fs/debugfs/file.c
fs/eventpoll.c
fs/exfat/cache.c
fs/exfat/exfat_fs.h
fs/exfat/inode.c
fs/exfat/namei.c
fs/exfat/super.c
fs/f2fs/data.c
fs/f2fs/node.c
fs/f2fs/segment.c
fs/fs-writeback.c
fs/fuse/file.c
fs/io_uring.c
fs/nfs/dir.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4proc.c
fs/pipe.c
fs/read_write.c
fs/splice.c
fs/vboxsf/super.c
include/asm-generic/vmlinux.lds.h
include/drm/drm_dsc.h
include/linux/acpi.h
include/linux/amba/clcd-regs.h [new file with mode: 0644]
include/linux/amba/clcd.h [new file with mode: 0644]
include/linux/blk_types.h
include/linux/blkdev.h
include/linux/cpuhotplug.h
include/linux/cpuidle.h
include/linux/dax.h
include/linux/device.h
include/linux/dynamic_debug.h
include/linux/efi_embedded_fw.h
include/linux/font.h
include/linux/fs_parser.h
include/linux/ftrace.h
include/linux/i2c-algo-pca.h
include/linux/kprobes.h
include/linux/kvm_host.h
include/linux/mlx5/driver.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/net.h
include/linux/netdev_features.h
include/linux/netdevice.h
include/linux/nfs_xdr.h
include/linux/node.h
include/linux/percpu-rwsem.h
include/linux/pgtable.h
include/linux/pipe_fs_i.h
include/linux/platform_data/gpio/gpio-amd-fch.h
include/linux/powercap.h
include/linux/qed/qed_if.h
include/linux/serial_core.h
include/linux/skbuff.h
include/linux/stackleak.h
include/linux/vmstat.h
include/linux/wait.h
include/media/videobuf2-core.h
include/net/act_api.h
include/net/flow.h
include/net/genetlink.h
include/net/ip.h
include/net/netlink.h
include/net/netns/nftables.h
include/net/sctp/structs.h
include/net/vxlan.h
include/net/xfrm.h
include/soc/mscc/ocelot.h
include/soc/mscc/ocelot_ana.h
include/sound/soc.h
include/uapi/linux/ethtool_netlink.h
include/uapi/linux/kvm.h
include/uapi/linux/rxrpc.h
include/uapi/linux/snmp.h
include/uapi/linux/videodev2.h
include/xen/arm/page.h
init/main.c
kernel/bpf/hashtab.c
kernel/bpf/inode.c
kernel/bpf/sysfs_btf.c
kernel/bpf/verifier.c
kernel/entry/common.c
kernel/fork.c
kernel/gcov/Kconfig
kernel/gcov/gcc_4_7.c
kernel/kprobes.c
kernel/locking/lockdep.c
kernel/locking/lockdep_internals.h
kernel/locking/percpu-rwsem.c
kernel/padata.c
kernel/rcu/tasks.h
kernel/rcu/tree.c
kernel/seccomp.c
kernel/stackleak.c
kernel/sysctl.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_output.c
kernel/trace/trace_preemptirq.c
kernel/umh.c
lib/Kconfig.debug
lib/bootconfig.c
lib/dynamic_debug.c
lib/fonts/font_10x18.c
lib/fonts/font_6x10.c
lib/fonts/font_6x11.c
lib/fonts/font_7x14.c
lib/fonts/font_8x16.c
lib/fonts/font_8x8.c
lib/fonts/font_acorn_8x8.c
lib/fonts/font_mini_4x6.c
lib/fonts/font_pearl_8x8.c
lib/fonts/font_sun12x22.c
lib/fonts/font_sun8x16.c
lib/fonts/font_ter16x32.c
lib/kobject.c
lib/memregion.c
lib/random32.c
lib/string.c
lib/test_firmware.c
lib/test_rhashtable.c
mm/filemap.c
mm/gup.c
mm/huge_memory.c
mm/ksm.c
mm/madvise.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mlock.c
mm/page_alloc.c
mm/page_isolation.c
mm/percpu.c
mm/shmem.c
mm/slab.c
mm/slub.c
mm/swap.c
mm/swapfile.c
mm/vmscan.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/multicast.c
net/batman-adv/multicast.h
net/batman-adv/routing.c
net/batman-adv/soft-interface.c
net/bridge/br_arp_nd_proxy.c
net/bridge/br_fdb.c
net/bridge/br_netlink.c
net/bridge/br_vlan.c
net/ceph/messenger.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/dst.c
net/core/fib_rules.c
net/core/filter.c
net/core/net_namespace.c
net/core/skbuff.c
net/dcb/dcbnl.c
net/dsa/slave.c
net/dsa/tag_ocelot.c
net/ethtool/netlink.c
net/ethtool/tunnels.c
net/hsr/hsr_netlink.c
net/ipv4/fib_frontend.c
net/ipv4/inet_diag.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ip_vti.c
net/ipv4/proc.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv6/Kconfig
net/ipv6/ip6_fib.c
net/ipv6/route.c
net/mac80211/airtime.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/util.c
net/mac80211/vht.c
net/mac802154/tx.c
net/mptcp/options.c
net/mptcp/pm_netlink.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_meta.c
net/netlink/genetlink.c
net/netlink/policy.c
net/openvswitch/conntrack.c
net/qrtr/ns.c
net/qrtr/qrtr.c
net/rxrpc/ar-internal.h
net/rxrpc/call_accept.c
net/rxrpc/call_object.c
net/rxrpc/conn_event.c
net/rxrpc/key.c
net/rxrpc/recvmsg.c
net/rxrpc/sendmsg.c
net/sched/act_api.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_gate.c
net/sched/act_ife.c
net/sched/act_ipt.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/cls_flower.c
net/sched/sch_generic.c
net/sched/sch_taprio.c
net/sctp/auth.c
net/sctp/socket.c
net/socket.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/verbs.c
net/switchdev/switchdev.c
net/tipc/group.c
net/tipc/link.c
net/tipc/msg.c
net/tipc/socket.c
net/tls/tls_sw.c
net/wireless/Kconfig
net/wireless/nl80211.c
net/wireless/util.c
net/xdp/xdp_umem.c
net/xdp/xsk.c
net/xfrm/espintcp.c
net/xfrm/xfrm_interface.c
net/xfrm/xfrm_state.c
scripts/dtc/Makefile
scripts/kallsyms.c
scripts/kconfig/lkc.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/qconf.cc
scripts/spelling.txt
scripts/tags.sh
security/device_cgroup.c
sound/pci/asihpi/hpioctl.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/max98373-sdw.c
sound/soc/codecs/pcm3168a.c
sound/soc/codecs/rt1308-sdw.c
sound/soc/codecs/rt700-sdw.c
sound/soc/codecs/rt711-sdw.c
sound/soc/codecs/rt715-sdw.c
sound/soc/codecs/tlv320adcx140.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.h
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/skl_hda_dsp_generic.c
sound/soc/intel/boards/sof_maxim_common.c
sound/soc/intel/haswell/sst-haswell-dsp.c
sound/soc/meson/axg-toddr.c
sound/soc/qcom/apq8016_sbc.c
sound/soc/qcom/apq8096.c
sound/soc/qcom/common.c
sound/soc/qcom/sdm845.c
sound/soc/qcom/storm.c
sound/soc/soc-core.c
sound/soc/soc-dai.c
sound/soc/soc-pcm.c
sound/soc/ti/ams-delta.c
sound/usb/mixer_maps.c
sound/usb/quirks.c
tools/bootconfig/test-bootconfig.sh
tools/bpf/Makefile
tools/bpf/bpftool/Makefile
tools/bpf/resolve_btfids/Makefile
tools/include/uapi/linux/in.h
tools/include/uapi/linux/kvm.h
tools/io_uring/io_uring-bench.c
tools/lib/bpf/Makefile
tools/lib/bpf/btf.c
tools/lib/bpf/libbpf.c
tools/objtool/check.c
tools/perf/bench/sched-messaging.c
tools/perf/pmu-events/arch/x86/amdzen1/core.json
tools/perf/pmu-events/arch/x86/amdzen2/core.json
tools/perf/tests/attr/README
tools/perf/tests/attr/test-record-group2 [new file with mode: 0644]
tools/perf/tests/bp_signal.c
tools/perf/tests/parse-metric.c
tools/perf/tests/pmu-events.c
tools/perf/tests/pmu.c
tools/perf/util/evlist.c
tools/perf/util/evsel.c
tools/perf/util/metricgroup.c
tools/perf/util/parse-events.c
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/record.c
tools/perf/util/stat-shadow.c
tools/testing/selftests/bpf/progs/bpf_iter_bpf_hash_map.c
tools/testing/selftests/kvm/x86_64/debug_regs.c
tools/testing/selftests/net/rtnetlink.sh
tools/testing/selftests/powerpc/mm/prot_sao.c
tools/testing/selftests/timers/Makefile
tools/testing/selftests/timers/settings [new file with mode: 0644]
tools/testing/selftests/vm/map_hugetlb.c
virt/kvm/kvm_main.c

index 332c783..a780211 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -169,6 +169,10 @@ Juha Yrjola <juha.yrjola@solidboot.com>
 Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
 Kamil Konieczny <k.konieczny@samsung.com> <k.konieczny@partner.samsung.com>
 Kay Sievers <kay.sievers@vrfy.org>
+Kees Cook <keescook@chromium.org> <kees.cook@canonical.com>
+Kees Cook <keescook@chromium.org> <keescook@google.com>
+Kees Cook <keescook@chromium.org> <kees@outflux.net>
+Kees Cook <keescook@chromium.org> <kees@ubuntu.com>
 Kenneth W Chen <kenneth.w.chen@intel.com>
 Konstantin Khlebnikov <koct9i@gmail.com> <khlebnikov@yandex-team.ru>
 Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
@@ -308,6 +312,7 @@ Tony Luck <tony.luck@intel.com>
 TripleX Chung <xxx.phy@gmail.com> <triplex@zh-kernel.org>
 TripleX Chung <xxx.phy@gmail.com> <zhongyu@18mail.cn>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
+Tycho Andersen <tycho@tycho.pizza> <tycho@tycho.ws>
 Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
 Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
index 6be4378..baa07b3 100644 (file)
@@ -1324,15 +1324,26 @@ PAGE_SIZE multiple when read back.
          pgmajfault
                Number of major page faults incurred
 
-         workingset_refault
-               Number of refaults of previously evicted pages
+         workingset_refault_anon
+               Number of refaults of previously evicted anonymous pages.
 
-         workingset_activate
-               Number of refaulted pages that were immediately activated
+         workingset_refault_file
+               Number of refaults of previously evicted file pages.
 
-         workingset_restore
-               Number of restored pages which have been detected as an active
-               workingset before they got reclaimed.
+         workingset_activate_anon
+               Number of refaulted anonymous pages that were immediately
+               activated.
+
+         workingset_activate_file
+               Number of refaulted file pages that were immediately activated.
+
+         workingset_restore_anon
+               Number of restored anonymous pages which have been detected as
+               an active workingset before they got reclaimed.
+
+         workingset_restore_file
+               Number of restored file pages which have been detected as an
+               active workingset before they got reclaimed.
 
          workingset_nodereclaim
                Number of times a shadow node has been reclaimed
index 8f4a3f8..bc28a95 100644 (file)
@@ -67,7 +67,7 @@ Parameters::
     the value passed in <key_size>.
 
 <key_type>
-    Either 'logon' or 'user' kernel key type.
+    Either 'logon', 'user' or 'encrypted' kernel key type.
 
 <key_description>
     The kernel keyring key description crypt target should look for
@@ -121,6 +121,14 @@ submit_from_crypt_cpus
     thread because it benefits CFQ to have writes submitted using the
     same context.
 
+no_read_workqueue
+    Bypass dm-crypt internal workqueue and process read requests synchronously.
+
+no_write_workqueue
+    Bypass dm-crypt internal workqueue and process write requests synchronously.
+    This option is automatically enabled for host-managed zoned block devices
+    (e.g. host-managed SMR hard-disks).
+
 integrity:<bytes>:<type>
     The device requires additional <bytes> metadata per-sector stored
     in per-bio integrity structure. This metadata must by provided
index e5a8def..6c04aea 100644 (file)
@@ -156,7 +156,6 @@ against.  Possible keywords are:::
   ``line-range`` cannot contain space, e.g.
   "1-30" is valid range but "1 - 30" is not.
 
-  ``module=foo`` combined keyword=value form is interchangably accepted
 
 The meanings of each keyword are:
 
index a96a423..6ebe163 100644 (file)
@@ -690,7 +690,7 @@ which of the two parameters is added to the kernel command line.  In the
 instruction of the CPUs (which, as a rule, suspends the execution of the program
 and causes the hardware to attempt to enter the shallowest available idle state)
 for this purpose, and if ``idle=poll`` is used, idle CPUs will execute a
-more or less ``lightweight'' sequence of instructions in a tight loop.  [Note
+more or less "lightweight" sequence of instructions in a tight loop.  [Note
 that using ``idle=poll`` is somewhat drastic in many cases, as preventing idle
 CPUs from saving almost any energy at all may not be the only effect of it.
 For example, on Intel hardware it effectively prevents CPUs from using
index 75f943f..6a615cd 100644 (file)
@@ -182,9 +182,6 @@ in the order of reservations, but only after all previous records where
 already committed. It is thus possible for slow producers to temporarily hold
 off submitted records, that were reserved later.
 
-Reservation/commit/consumer protocol is verified by litmus tests in
-Documentation/litmus_tests/bpf-rb/_.
-
 One interesting implementation bit, that significantly simplifies (and thus
 speeds up as well) implementation of both producers and consumers is how data
 area is mapped twice contiguously back-to-back in the virtual memory. This
@@ -200,7 +197,7 @@ a self-pacing notifications of new data being availability.
 being available after commit only if consumer has already caught up right up to
 the record being committed. If not, consumer still has to catch up and thus
 will see new data anyways without needing an extra poll notification.
-Benchmarks (see tools/testing/selftests/bpf/benchs/bench_ringbuf.c_) show that
+Benchmarks (see tools/testing/selftests/bpf/benchs/bench_ringbufs.c) show that
 this allows to achieve a very high throughput without having to resort to
 tricks like "notify only every Nth sample", which are necessary with perf
 buffer. For extreme cases, when BPF program wants more manual control of
index 17e4f20..6834f5e 100644 (file)
@@ -23,7 +23,7 @@ properties:
   compatible:
     items:
       - const: raspberrypi,bcm2835-firmware
-      - const: simple-bus
+      - const: simple-mfd
 
   mboxes:
     $ref: '/schemas/types.yaml#/definitions/phandle'
@@ -57,7 +57,7 @@ required:
 examples:
   - |
     firmware {
-        compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+        compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
         mboxes = <&mailbox>;
 
         firmware_clocks: clocks {
index 85ef69f..1465c9e 100644 (file)
@@ -67,7 +67,7 @@ examples:
 
     main_crypto: crypto@4e00000 {
         compatible = "ti,j721-sa2ul";
-        reg = <0x0 0x4e00000 0x0 0x1200>;
+        reg = <0x4e00000 0x1200>;
         power-domains = <&k3_pds 264 TI_SCI_PD_EXCLUSIVE>;
         dmas = <&main_udmap 0xc000>, <&main_udmap 0x4000>,
                <&main_udmap 0x4001>;
index 52a939c..7b9d468 100644 (file)
@@ -145,10 +145,10 @@ examples:
 
     display@fd4a0000 {
         compatible = "xlnx,zynqmp-dpsub-1.7";
-        reg = <0x0 0xfd4a0000 0x0 0x1000>,
-              <0x0 0xfd4aa000 0x0 0x1000>,
-              <0x0 0xfd4ab000 0x0 0x1000>,
-              <0x0 0xfd4ac000 0x0 0x1000>;
+        reg = <0xfd4a0000 0x1000>,
+              <0xfd4aa000 0x1000>,
+              <0xfd4ab000 0x1000>,
+              <0xfd4ac000 0x1000>;
         reg-names = "dp", "blend", "av_buf", "aud";
         interrupts = <0 119 4>;
         interrupt-parent = <&gic>;
index 5de510f..2a595b1 100644 (file)
@@ -57,7 +57,7 @@ examples:
 
     dma: dma-controller@fd4c0000 {
       compatible = "xlnx,zynqmp-dpdma";
-      reg = <0x0 0xfd4c0000 0x0 0x1000>;
+      reg = <0xfd4c0000 0x1000>;
       interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
       interrupt-parent = <&gic>;
       clocks = <&dpdma_clk>;
index d4d8391..be329ea 100644 (file)
@@ -20,8 +20,9 @@ Required properties:
 - gpio-controller : Marks the device node as a GPIO controller
 - interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
 - interrupt-controller : Mark the GPIO controller as an interrupt-controller
-- ngpios : number of GPIO lines, see gpio.txt
-  (should be multiple of 8, up to 80 pins)
+- ngpios : number of *hardware* GPIO lines, see gpio.txt. This will expose
+  2 software GPIOs per hardware GPIO: one for hardware input, one for hardware
+  output. Up to 80 pins, must be a multiple of 8.
 - clocks : A phandle to the APB clock for SGPM clock division
 - bus-frequency : SGPM CLK frequency
 
index 24ad144..fe7fa25 100644 (file)
@@ -30,7 +30,7 @@ properties:
     const: 0
 
 patternProperties:
-  "^multi-led[0-9a-f]$":
+  "^multi-led@[0-9a-b]$":
     type: object
     allOf:
       - $ref: leds-class-multicolor.yaml#
diff --git a/Documentation/devicetree/bindings/media/i2c/imx274.txt b/Documentation/devicetree/bindings/media/i2c/imx274.txt
deleted file mode 100644 (file)
index 0727079..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-* Sony 1/2.5-Inch 8.51Mp CMOS Digital Image Sensor
-
-The Sony imx274 is a 1/2.5-inch CMOS active pixel digital image sensor with
-an active array size of 3864H x 2202V. It is programmable through I2C
-interface. The I2C address is fixed to 0x1a as per sensor data sheet.
-Image data is sent through MIPI CSI-2, which is configured as 4 lanes
-at 1440 Mbps.
-
-
-Required Properties:
-- compatible: value should be "sony,imx274" for imx274 sensor
-- reg: I2C bus address of the device
-
-Optional Properties:
-- reset-gpios: Sensor reset GPIO
-- clocks: Reference to the input clock.
-- clock-names: Should be "inck".
-- VANA-supply: Sensor 2.8v analog supply.
-- VDIG-supply: Sensor 1.8v digital core supply.
-- VDDL-supply: Sensor digital IO 1.2v supply.
-
-The imx274 device node should contain one 'port' child node with
-an 'endpoint' subnode. For further reading on port node refer to
-Documentation/devicetree/bindings/media/video-interfaces.txt.
-
-Example:
-       sensor@1a {
-               compatible = "sony,imx274";
-               reg = <0x1a>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               reset-gpios = <&gpio_sensor 0 0>;
-               port {
-                       sensor_out: endpoint {
-                               remote-endpoint = <&csiss_in>;
-                       };
-               };
-       };
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
new file mode 100644 (file)
index 0000000..f697e1a
--- /dev/null
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/sony,imx274.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sony 1/2.5-Inch 8.51MP CMOS Digital Image Sensor
+
+maintainers:
+  - Leon Luo <leonl@leopardimaging.com>
+
+description: |
+  The Sony IMX274 is a 1/2.5-inch CMOS active pixel digital image sensor with an
+  active array size of 3864H x 2202V. It is programmable through I2C interface.
+  Image data is sent through MIPI CSI-2, which is configured as 4 lanes at 1440
+  Mbps.
+
+properties:
+  compatible:
+    const: sony,imx274
+
+  reg:
+    const: 0x1a
+
+  reset-gpios:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: inck
+
+  vana-supply:
+    description: Sensor 2.8 V analog supply.
+    maxItems: 1
+
+  vdig-supply:
+    description: Sensor 1.8 V digital core supply.
+    maxItems: 1
+
+  vddl-supply:
+    description: Sensor digital IO 1.2 V supply.
+    maxItems: 1
+
+  port:
+    type: object
+    description: Output video port. See ../video-interfaces.txt.
+
+required:
+  - compatible
+  - reg
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c0 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        imx274: camera-sensor@1a {
+            compatible = "sony,imx274";
+            reg = <0x1a>;
+            reset-gpios = <&gpio_sensor 0 0>;
+
+            port {
+                sensor_out: endpoint {
+                    remote-endpoint = <&csiss_in>;
+                };
+            };
+        };
+    };
+
+...
index 032b76f..9119f1c 100644 (file)
@@ -21,6 +21,7 @@ Required properties:
       - "renesas,etheravb-r8a774a1" for the R8A774A1 SoC.
       - "renesas,etheravb-r8a774b1" for the R8A774B1 SoC.
       - "renesas,etheravb-r8a774c0" for the R8A774C0 SoC.
+      - "renesas,etheravb-r8a774e1" for the R8A774E1 SoC.
       - "renesas,etheravb-r8a7795" for the R8A7795 SoC.
       - "renesas,etheravb-r8a7796" for the R8A77960 SoC.
       - "renesas,etheravb-r8a77961" for the R8A77961 SoC.
index f5e518d..62d4ed2 100644 (file)
@@ -23,8 +23,8 @@ Required properties:
 
 - compatible:
     Must be one of :
-    "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-qspi" : MSPI+BSPI on BRCMSTB SoCs
-    "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI
+    "brcm,spi-brcmstb-qspi", "brcm,spi-bcm-qspi" : MSPI+BSPI on BRCMSTB SoCs
+    "brcm,spi-brcmstb-mspi", "brcm,spi-bcm-qspi" : Second Instance of MSPI
                                                   BRCMSTB  SoCs
     "brcm,spi-bcm7425-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI
                                                                            BRCMSTB  SoCs
@@ -36,8 +36,8 @@ Required properties:
                                                                            BRCMSTB  SoCs
     "brcm,spi-bcm7278-qspi", "brcm,spi-bcm-qspi", "brcm,spi-brcmstb-mspi" : Second Instance of MSPI
                                                                            BRCMSTB  SoCs
-    "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi"     : MSPI+BSPI on Cygnus, NSP
-    "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi"     : NS2 SoCs
+    "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"     : MSPI+BSPI on Cygnus, NSP
+    "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi"     : NS2 SoCs
 
 - reg:
     Define the bases and ranges of the associated I/O address spaces.
@@ -86,7 +86,7 @@ BRCMSTB SoC Example:
     spi@f03e3400 {
                #address-cells = <0x1>;
                #size-cells = <0x0>;
-               compatible = "brcm,spi-brcmstb-qspi", "brcm,spi-brcmstb-qspi";
+               compatible = "brcm,spi-brcmstb-qspi", "brcm,spi-bcm-qspi";
                reg = <0xf03e0920 0x4 0xf03e3400 0x188 0xf03e3200 0x50>;
                reg-names = "cs_reg", "mspi", "bspi";
                interrupts = <0x6 0x5 0x4 0x3 0x2 0x1 0x0>;
@@ -149,7 +149,7 @@ BRCMSTB SoC Example:
                #address-cells = <1>;
                #size-cells = <0>;
                clocks = <&upg_fixed>;
-               compatible = "brcm,spi-brcmstb-qspi", "brcm,spi-brcmstb-mspi";
+               compatible = "brcm,spi-brcmstb-mspi", "brcm,spi-bcm-qspi";
                reg = <0xf0416000 0x180>;
                reg-names = "mspi";
                interrupts = <0x14>;
@@ -160,7 +160,7 @@ BRCMSTB SoC Example:
 iProc SoC Example:
 
     qspi: spi@18027200 {
-       compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+       compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
        reg = <0x18027200 0x184>,
              <0x18027000 0x124>,
              <0x1811c408 0x004>,
@@ -191,7 +191,7 @@ iProc SoC Example:
  NS2 SoC Example:
 
               qspi: spi@66470200 {
-                      compatible = "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi";
+                      compatible = "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi";
                       reg = <0x66470200 0x184>,
                             <0x66470000 0x124>,
                             <0x67017408 0x004>,
index 100bfd2..13ea0cc 100644 (file)
@@ -179,7 +179,7 @@ DMA Fence uABI/Sync File
    :internal:
 
 Indefinite DMA Fences
-~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~
 
 At various times &dma_fence with an indefinite time until dma_fence_wait()
 finishes have been proposed. Examples include:
index 53da483..1c49723 100644 (file)
@@ -22,7 +22,7 @@
     |       nios2: | TODO |
     |    openrisc: | TODO |
     |      parisc: | TODO |
-    |     powerpc: |  ok  |
+    |     powerpc: | TODO |
     |       riscv: |  ok  |
     |        s390: |  ok  |
     |          sh: | TODO |
index 334df75..dae90c2 100644 (file)
@@ -39,10 +39,10 @@ which can help simplify cross compiling. ::
        ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make CC=clang
 
 ``CROSS_COMPILE`` is not used to prefix the Clang compiler binary, instead
-``CROSS_COMPILE`` is used to set a command line flag: ``--target <triple>``. For
+``CROSS_COMPILE`` is used to set a command line flag: ``--target=<triple>``. For
 example: ::
 
-       clang --target aarch64-linux-gnu foo.c
+       clang --target=aarch64-linux-gnu foo.c
 
 LLVM Utilities
 --------------
index d53bcb3..b5a7988 100644 (file)
@@ -206,6 +206,7 @@ Userspace to kernel:
   ``ETHTOOL_MSG_TSINFO_GET``           get timestamping info
   ``ETHTOOL_MSG_CABLE_TEST_ACT``        action start cable test
   ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT``    action start raw TDR cable test
+  ``ETHTOOL_MSG_TUNNEL_INFO_GET``       get tunnel offload info
   ===================================== ================================
 
 Kernel to userspace:
@@ -239,6 +240,7 @@ Kernel to userspace:
   ``ETHTOOL_MSG_TSINFO_GET_REPLY``     timestamping info
   ``ETHTOOL_MSG_CABLE_TEST_NTF``        Cable test results
   ``ETHTOOL_MSG_CABLE_TEST_TDR_NTF``    Cable test TDR results
+  ``ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY`` tunnel offload info
   ===================================== =================================
 
 ``GET`` requests are sent by userspace applications to retrieve device
@@ -1363,4 +1365,5 @@ are netlink only.
   ``ETHTOOL_SFECPARAM``               n/a
   n/a                                 ''ETHTOOL_MSG_CABLE_TEST_ACT''
   n/a                                 ''ETHTOOL_MSG_CABLE_TEST_TDR_ACT''
+  n/a                                 ``ETHTOOL_MSG_TUNNEL_INFO_GET``
   =================================== =====================================
index 57e752a..2044ed1 100644 (file)
@@ -701,23 +701,6 @@ Memory Consistency Flags
     :stub-columns: 0
     :widths:       3 1 4
 
-    * .. _`V4L2-FLAG-MEMORY-NON-CONSISTENT`:
-
-      - ``V4L2_FLAG_MEMORY_NON_CONSISTENT``
-      - 0x00000001
-      - A buffer is allocated either in consistent (it will be automatically
-       coherent between the CPU and the bus) or non-consistent memory. The
-       latter can provide performance gains, for instance the CPU cache
-       sync/flush operations can be avoided if the buffer is accessed by the
-       corresponding device only and the CPU does not read/write to/from that
-       buffer. However, this requires extra care from the driver -- it must
-       guarantee memory consistency by issuing a cache flush/sync when
-       consistency is needed. If this flag is set V4L2 will attempt to
-       allocate the buffer in non-consistent memory. The flag takes effect
-       only if the buffer is used for :ref:`memory mapping <mmap>` I/O and the
-       queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS
-       <V4L2-BUF-CAP-SUPPORTS-MMAP-CACHE-HINTS>` capability.
-
 .. c:type:: v4l2_memory
 
 enum v4l2_memory
index f2a7028..12cf6b4 100644 (file)
@@ -120,13 +120,9 @@ than the number requested.
        If you want to just query the capabilities without making any
        other changes, then set ``count`` to 0, ``memory`` to
        ``V4L2_MEMORY_MMAP`` and ``format.type`` to the buffer type.
-    * - __u32
-      - ``flags``
-      - Specifies additional buffer management attributes.
-       See :ref:`memory-flags`.
 
     * - __u32
-      - ``reserved``\ [6]
+      - ``reserved``\ [7]
       - A place holder for future extensions. Drivers and applications
        must set the array to zero.
 
index 75d894d..0e3e2fd 100644 (file)
@@ -112,17 +112,10 @@ aborting or finishing any DMA in progress, an implicit
        ``V4L2_MEMORY_MMAP`` and ``type`` set to the buffer type. This will
        free any previously allocated buffers, so this is typically something
        that will be done at the start of the application.
-    * - union {
-      - (anonymous)
-    * - __u32
-      - ``flags``
-      - Specifies additional buffer management attributes.
-       See :ref:`memory-flags`.
     * - __u32
       - ``reserved``\ [1]
-      - Kept for backwards compatibility. Use ``flags`` instead.
-    * - }
-      -
+      - A place holder for future extensions. Drivers and applications
+       must set the array to zero.
 
 .. tabularcolumns:: |p{6.1cm}|p{2.2cm}|p{8.7cm}|
 
@@ -169,7 +162,6 @@ aborting or finishing any DMA in progress, an implicit
       - This capability is set by the driver to indicate that the queue supports
         cache and memory management hints. However, it's only valid when the
         queue is used for :ref:`memory mapping <mmap>` streaming I/O. See
-        :ref:`V4L2_FLAG_MEMORY_NON_CONSISTENT <V4L2-FLAG-MEMORY-NON-CONSISTENT>`,
         :ref:`V4L2_BUF_FLAG_NO_CACHE_INVALIDATE <V4L2-BUF-FLAG-NO-CACHE-INVALIDATE>` and
         :ref:`V4L2_BUF_FLAG_NO_CACHE_CLEAN <V4L2-BUF-FLAG-NO-CACHE-CLEAN>`.
 
index eb3a131..51191b5 100644 (file)
@@ -6130,7 +6130,7 @@ HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx.
 8.21 KVM_CAP_HYPERV_DIRECT_TLBFLUSH
 -----------------------------------
 
-:Architecture: x86
+:Architectures: x86
 
 This capability indicates that KVM running on top of Hyper-V hypervisor
 enables Direct TLB flush for its guests meaning that TLB flush
@@ -6143,19 +6143,53 @@ in CPUID and only exposes Hyper-V identification. In this case, guest
 thinks it's running on Hyper-V and only use Hyper-V hypercalls.
 
 8.22 KVM_CAP_S390_VCPU_RESETS
+-----------------------------
 
-Architectures: s390
+:Architectures: s390
 
 This capability indicates that the KVM_S390_NORMAL_RESET and
 KVM_S390_CLEAR_RESET ioctls are available.
 
 8.23 KVM_CAP_S390_PROTECTED
+---------------------------
 
-Architecture: s390
-
+:Architectures: s390
 
 This capability indicates that the Ultravisor has been initialized and
 KVM can therefore start protected VMs.
 This capability governs the KVM_S390_PV_COMMAND ioctl and the
 KVM_MP_STATE_LOAD MP_STATE. KVM_SET_MP_STATE can fail for protected
 guests when the state change is invalid.
+
+8.24 KVM_CAP_STEAL_TIME
+-----------------------
+
+:Architectures: arm64, x86
+
+This capability indicates that KVM supports steal time accounting.
+When steal time accounting is supported it may be enabled with
+architecture-specific interfaces.  This capability and the architecture-
+specific interfaces must be consistent, i.e. if one says the feature
+is supported, than the other should as well and vice versa.  For arm64
+see Documentation/virt/kvm/devices/vcpu.rst "KVM_ARM_VCPU_PVTIME_CTRL".
+For x86 see Documentation/virt/kvm/msr.rst "MSR_KVM_STEAL_TIME".
+
+8.25 KVM_CAP_S390_DIAG318
+-------------------------
+
+:Architectures: s390
+
+This capability enables a guest to set information about its control program
+(i.e. guest kernel type and version). The information is helpful during
+system/firmware service events, providing additional data about the guest
+environments running on the machine.
+
+The information is associated with the DIAGNOSE 0x318 instruction, which sets
+an 8-byte value consisting of a one-byte Control Program Name Code (CPNC) and
+a 7-byte Control Program Version Code (CPVC). The CPNC determines what
+environment the control program is running in (e.g. Linux, z/VM...), and the
+CPVC is used for information specific to OS (e.g. Linux version, Linux
+distribution...)
+
+If this capability is available, then the CPNC and CPVC can be synchronized
+between KVM and userspace via the sync regs mechanism (KVM_SYNC_DIAG318).
index b5cfab0..9a54806 100644 (file)
@@ -1460,6 +1460,11 @@ S:       Odd Fixes
 F:     drivers/amba/
 F:     include/linux/amba/bus.h
 
+ARM PRIMECELL CLCD PL110 DRIVER
+M:     Russell King <linux@armlinux.org.uk>
+S:     Odd Fixes
+F:     drivers/video/fbdev/amba-clcd.*
+
 ARM PRIMECELL KMI PL050 DRIVER
 M:     Russell King <linux@armlinux.org.uk>
 S:     Odd Fixes
@@ -4408,12 +4413,6 @@ T:       git git://git.infradead.org/users/hch/configfs.git
 F:     fs/configfs/
 F:     include/linux/configfs.h
 
-CONNECTOR
-M:     Evgeniy Polyakov <zbr@ioremap.net>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/connector/
-
 CONSOLE SUBSYSTEM
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 S:     Supported
@@ -6180,7 +6179,7 @@ F:        Documentation/devicetree/bindings/edac/aspeed-sdram-edac.txt
 F:     drivers/edac/aspeed_edac.c
 
 EDAC-BLUEFIELD
-M:     Shravan Kumar Ramani <sramani@nvidia.com>
+M:     Shravan Kumar Ramani <shravankr@nvidia.com>
 S:     Supported
 F:     drivers/edac/bluefield_edac.c
 
@@ -6901,6 +6900,14 @@ L:       linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/dma/fsldma.*
 
+FREESCALE DSPI DRIVER
+M:     Vladimir Oltean <olteanv@gmail.com>
+L:     linux-spi@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+F:     drivers/spi/spi-fsl-dspi.c
+F:     include/linux/spi/spi-fsl-dspi.h
+
 FREESCALE ENETC ETHERNET DRIVERS
 M:     Claudiu Manoil <claudiu.manoil@nxp.com>
 L:     netdev@vger.kernel.org
@@ -8321,8 +8328,9 @@ S:        Supported
 F:     drivers/pci/hotplug/rpaphp*
 
 IBM Power SRIOV Virtual NIC Device Driver
-M:     Thomas Falcon <tlfalcon@linux.ibm.com>
-M:     John Allen <jallen@linux.ibm.com>
+M:     Dany Madden <drt@linux.ibm.com>
+M:     Lijun Pan <ljp@linux.ibm.com>
+M:     Sukadev Bhattiprolu <sukadev@linux.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/ibm/ibmvnic.*
@@ -8336,7 +8344,7 @@ F:        arch/powerpc/platforms/powernv/copy-paste.h
 F:     arch/powerpc/platforms/powernv/vas*
 
 IBM Power Virtual Ethernet Device Driver
-M:     Thomas Falcon <tlfalcon@linux.ibm.com>
+M:     Cristobal Forno <cforno12@linux.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/ibm/ibmveth.*
@@ -8749,7 +8757,8 @@ F:        include/drm/i915*
 F:     include/uapi/drm/i915_drm.h
 
 INTEL ETHERNET DRIVERS
-M:     Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+M:     Jesse Brandeburg <jesse.brandeburg@intel.com>
+M:     Tony Nguyen <anthony.l.nguyen@intel.com>
 L:     intel-wired-lan@lists.osuosl.org (moderated for non-subscribers)
 S:     Supported
 W:     http://www.intel.com/support/feedback.htm
@@ -9243,7 +9252,7 @@ F:        drivers/firmware/iscsi_ibft*
 
 ISCSI EXTENSIONS FOR RDMA (ISER) INITIATOR
 M:     Sagi Grimberg <sagi@grimberg.me>
-M:     Max Gurtovoy <maxg@nvidia.com>
+M:     Max Gurtovoy <mgurtovoy@nvidia.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 W:     http://www.openfabrics.org
@@ -9792,7 +9801,7 @@ F:        drivers/scsi/53c700*
 
 LEAKING_ADDRESSES
 M:     Tobin C. Harding <me@tobin.cc>
-M:     Tycho Andersen <tycho@tycho.ws>
+M:     Tycho Andersen <tycho@tycho.pizza>
 L:     kernel-hardening@lists.openwall.com
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tobin/leaks.git
@@ -11034,6 +11043,7 @@ F:      drivers/char/hw_random/mtk-rng.c
 
 MEDIATEK SWITCH DRIVER
 M:     Sean Wang <sean.wang@mediatek.com>
+M:     Landen Chao <Landen.Chao@mediatek.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/dsa/mt7530.*
@@ -12047,6 +12057,7 @@ Q:      http://patchwork.ozlabs.org/project/netdev/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 F:     Documentation/devicetree/bindings/net/
+F:     drivers/connector/
 F:     drivers/net/
 F:     include/linux/etherdevice.h
 F:     include/linux/fcdevice.h
@@ -12072,6 +12083,7 @@ NETWORKING [DSA]
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Vivien Didelot <vivien.didelot@gmail.com>
 M:     Florian Fainelli <f.fainelli@gmail.com>
+M:     Vladimir Oltean <olteanv@gmail.com>
 S:     Maintained
 F:     Documentation/devicetree/bindings/net/dsa/
 F:     drivers/net/dsa/
@@ -13177,6 +13189,7 @@ F:      drivers/firmware/pcdp.*
 
 PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
 M:     Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+M:     Pali Rohár <pali@kernel.org>
 L:     linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -15569,6 +15582,7 @@ F:      include/uapi/linux/sed*
 SECURITY CONTACT
 M:     Security Officers <security@kernel.org>
 S:     Supported
+F:     Documentation/admin-guide/security-bugs.rst
 
 SECURITY SUBSYSTEM
 M:     James Morris <jmorris@namei.org>
@@ -16148,7 +16162,7 @@ M:      Leon Luo <leonl@leopardimaging.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
 T:     git git://linuxtv.org/media_tree.git
-F:     Documentation/devicetree/bindings/media/i2c/imx274.txt
+F:     Documentation/devicetree/bindings/media/i2c/sony,imx274.yaml
 F:     drivers/media/i2c/imx274.c
 
 SONY IMX290 SENSOR DRIVER
@@ -18275,7 +18289,8 @@ F:      drivers/gpu/vga/vga_switcheroo.c
 F:     include/linux/vga_switcheroo.h
 
 VIA RHINE NETWORK DRIVER
-S:     Orphan
+S:     Maintained
+M:     Kevin Brace <kevinbrace@bracecomputerlab.com>
 F:     drivers/net/ethernet/via/via-rhine.c
 
 VIA SD/MMC CARD CONTROLLER DRIVER
@@ -18880,10 +18895,10 @@ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/mm
 F:     arch/x86/mm/
 
 X86 PLATFORM DRIVERS
-M:     Darren Hart <dvhart@infradead.org>
-M:     Andy Shevchenko <andy@infradead.org>
+M:     Hans de Goede <hdegoede@redhat.com>
+M:     Mark Gross <mgross@linux.intel.com>
 L:     platform-driver-x86@vger.kernel.org
-S:     Odd Fixes
+S:     Maintained
 T:     git git://git.infradead.org/linux-platform-drivers-x86.git
 F:     drivers/platform/olpc/
 F:     drivers/platform/x86/
index ec2330c..f84d7e4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc8
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -882,10 +882,6 @@ KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
 LDFLAGS_vmlinux += --gc-sections
 endif
 
-ifdef CONFIG_LIVEPATCH
-KBUILD_CFLAGS += $(call cc-option, -flive-patching=inline-clone)
-endif
-
 ifdef CONFIG_SHADOW_CALL_STACK
 CC_FLAGS_SCS   := -fsanitize=shadow-call-stack
 KBUILD_CFLAGS  += $(CC_FLAGS_SCS)
index 8d19925..6783cf1 100644 (file)
                switch0: ksz8563@0 {
                        compatible = "microchip,ksz8563";
                        reg = <0>;
-                       phy-mode = "mii";
                        reset-gpios = <&pioA PIN_PD4 GPIO_ACTIVE_LOW>;
 
                        spi-max-frequency = <500000>;
                                        reg = <2>;
                                        label = "cpu";
                                        ethernet = <&macb0>;
+                                       phy-mode = "mii";
                                        fixed-link {
                                                speed = <100>;
                                                full-duplex;
index cbebed5..e8df458 100644 (file)
                };
 
                qspi: spi@27200 {
-                       compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+                       compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
                        reg = <0x027200 0x184>,
                              <0x027000 0x124>,
                              <0x11c408 0x004>,
index 0346ea6..c846fa3 100644 (file)
                };
 
                qspi: spi@27200 {
-                       compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+                       compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
                        reg = <0x027200 0x184>,
                              <0x027000 0x124>,
                              <0x11c408 0x004>,
index f7ae5a4..d94357b 100644 (file)
@@ -13,7 +13,7 @@
 
        soc {
                firmware: firmware {
-                       compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
+                       compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
                        #address-cells = <1>;
                        #size-cells = <1>;
 
index 2d9b4dd..0016720 100644 (file)
        };
 
        spi@18029200 {
-               compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+               compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
                reg = <0x18029200 0x184>,
                      <0x18029000 0x124>,
                      <0x1811b408 0x004>,
index 7a3d1d3..8f94364 100644 (file)
@@ -13,7 +13,7 @@
 
        backlight: backlight-lvds {
                compatible = "pwm-backlight";
-               pwms = <&pwm3 0 20000>;
+               pwms = <&pwm3 0 20000 0>;
                brightness-levels = <0 4 8 16 32 64 128 255>;
                default-brightness-level = <6>;
                power-supply = <&reg_lcd>;
index dffafbc..349959d 100644 (file)
@@ -30,7 +30,7 @@
        };
 
        /* PRTWD2 rev 1 bitbang I2C for Ethernet Switch */
-       i2c@4 {
+       i2c {
                compatible = "i2c-gpio";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_i2c4>;
index 7705285..4d01c33 100644 (file)
@@ -22,8 +22,6 @@
 
        gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
 
                user-pb {
                        label = "user_pb";
index 0b02c7e..f4dc462 100644 (file)
 #define MX6SX_PAD_QSPI1B_DQS__SIM_M_HADDR_15                      0x01B0 0x04F8 0x0000 0x7 0x0
 #define MX6SX_PAD_QSPI1B_SCLK__QSPI1_B_SCLK                       0x01B4 0x04FC 0x0000 0x0 0x0
 #define MX6SX_PAD_QSPI1B_SCLK__UART3_DCE_RX                       0x01B4 0x04FC 0x0840 0x1 0x4
-#define MX6SX_PAD_QSPI1B_SCLK__UART3_DTE_TX                       0x01B4 0x04FC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__UART3_DTE_TX                       0x01B4 0x04FC 0x0000 0x1 0x0
 #define MX6SX_PAD_QSPI1B_SCLK__ECSPI3_SCLK                        0x01B4 0x04FC 0x0730 0x2 0x1
 #define MX6SX_PAD_QSPI1B_SCLK__ESAI_RX_HF_CLK                     0x01B4 0x04FC 0x0780 0x3 0x2
 #define MX6SX_PAD_QSPI1B_SCLK__CSI1_DATA_16                       0x01B4 0x04FC 0x06DC 0x4 0x1
index e5e20b0..7cb6153 100644 (file)
@@ -58,7 +58,7 @@
                          <&clks IMX7D_ENET1_TIME_ROOT_CLK>;
        assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
        assigned-clock-rates = <0>, <100000000>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-handle = <&fec1_phy>;
        status = "okay";
 
index 3674396..b7ea37a 100644 (file)
                        clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
                                 <&pcc3 IMX7ULP_CLK_PCTLC>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc1 0 0 32>;
+                       gpio-ranges = <&iomuxc1 0 0 20>;
                };
 
                gpio_ptd: gpio@40af0000 {
                        clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
                                 <&pcc3 IMX7ULP_CLK_PCTLD>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc1 0 32 32>;
+                       gpio-ranges = <&iomuxc1 0 32 12>;
                };
 
                gpio_pte: gpio@40b00000 {
                        clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
                                 <&pcc3 IMX7ULP_CLK_PCTLE>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc1 0 64 32>;
+                       gpio-ranges = <&iomuxc1 0 64 16>;
                };
 
                gpio_ptf: gpio@40b10000 {
                        clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
                                 <&pcc3 IMX7ULP_CLK_PCTLF>;
                        clock-names = "gpio", "port";
-                       gpio-ranges = <&iomuxc1 0 96 32>;
+                       gpio-ranges = <&iomuxc1 0 96 20>;
                };
        };
 
index 100396f..395e05f 100644 (file)
@@ -51,6 +51,8 @@
 
 &mcbsp2 {
        status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcbsp2_pins>;
 };
 
 &charger {
                regulator-max-microvolt = <3300000>;
        };
 
-       lcd0: display@0 {
-               compatible = "panel-dpi";
-               label = "28";
-               status = "okay";
-               /* default-on; */
+       lcd0: display {
+               /* This isn't the exact LCD, but the timings meet spec */
+               compatible = "logicpd,type28";
                pinctrl-names = "default";
                pinctrl-0 = <&lcd_enable_pin>;
-               enable-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;    /* gpio155, lcd INI */
+               backlight = <&bl>;
+               enable-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;
                port {
                        lcd_in: endpoint {
                                remote-endpoint = <&dpi_out>;
                        };
                };
-
-               panel-timing {
-                       clock-frequency = <9000000>;
-                       hactive = <480>;
-                       vactive = <272>;
-                       hfront-porch = <3>;
-                       hback-porch = <2>;
-                       hsync-len = <42>;
-                       vback-porch = <3>;
-                       vfront-porch = <2>;
-                       vsync-len = <11>;
-                       hsync-active = <1>;
-                       vsync-active = <1>;
-                       de-active = <1>;
-                       pixelclk-active = <0>;
-               };
        };
 
        bl: backlight {
index 381f0e8..b0f6613 100644 (file)
@@ -81,6 +81,8 @@
 };
 
 &mcbsp2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcbsp2_pins>;
        status = "okay";
 };
 
index 069af9a..827373e 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0x0 0x1550000 0x0 0x10000>,
-                             <0x0 0x40000000 0x0 0x40000000>;
+                             <0x0 0x40000000 0x0 0x20000000>;
                        reg-names = "QuadSPI", "QuadSPI-memory";
                        interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
                        clock-names = "qspi_en", "qspi";
index 5da9cff..a82c962 100644 (file)
                                        };
                                };
 
-                               target-module@5000 {
+                               target-module@4000 {
                                        compatible = "ti,sysc-omap2", "ti,sysc";
-                                       reg = <0x5000 0x4>,
-                                             <0x5010 0x4>,
-                                             <0x5014 0x4>;
+                                       reg = <0x4000 0x4>,
+                                             <0x4010 0x4>,
+                                             <0x4014 0x4>;
                                        reg-names = "rev", "sysc", "syss";
                                        ti,sysc-sidle = <SYSC_IDLE_FORCE>,
                                                        <SYSC_IDLE_NO>,
                                        ti,syss-mask = <1>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
-                                       ranges = <0 0x5000 0x1000>;
+                                       ranges = <0 0x4000 0x1000>;
 
                                        dsi1: encoder@0 {
                                                compatible = "ti,omap5-dsi";
                                                reg-names = "proto", "phy", "pll";
                                                interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
                                                status = "disabled";
-                                               clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>;
-                                               clock-names = "fck";
+                                               clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>,
+                                                        <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>;
+                                               clock-names = "fck", "sys_clk";
                                        };
                                };
 
                                                reg-names = "proto", "phy", "pll";
                                                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
                                                status = "disabled";
-                                               clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>;
-                                               clock-names = "fck";
+                                               clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>,
+                                                        <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>;
+                                               clock-names = "fck", "sys_clk";
                                        };
                                };
 
index fc4abef..0013ec3 100644 (file)
                timer3: timer3@ffd00100 {
                        compatible = "snps,dw-apb-timer";
                        interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>;
-                       reg = <0xffd01000 0x100>;
+                       reg = <0xffd00100 0x100>;
                        clocks = <&l4_sys_free_clk>;
                        clock-names = "timer";
                        resets = <&rst L4SYSTIMER1_RESET>;
index 0fe03aa..2259d11 100644 (file)
                        };
 
                        ocotp: ocotp@400a5000 {
-                               compatible = "fsl,vf610-ocotp";
+                               compatible = "fsl,vf610-ocotp", "syscon";
                                reg = <0x400a5000 0x1000>;
                                clocks = <&clks VF610_CLK_OCOTP>;
                        };
index a9755c5..b06e537 100644 (file)
@@ -1,13 +1,11 @@
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_MULTI_V4T=y
 CONFIG_ARCH_MULTI_V5=y
 # CONFIG_ARCH_MULTI_V7 is not set
@@ -15,19 +13,17 @@ CONFIG_ARCH_INTEGRATOR=y
 CONFIG_ARCH_INTEGRATOR_AP=y
 CONFIG_INTEGRATOR_IMPD1=y
 CONFIG_ARCH_INTEGRATOR_CP=y
-CONFIG_PCI=y
-CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_ATAGS is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_CPUFREQ_DT=y
-CONFIG_CMA=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -37,6 +33,7 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
+CONFIG_PCI=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
@@ -52,9 +49,12 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_NETDEVICES=y
 CONFIG_E100=y
 CONFIG_SMC91X=y
+CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_DRM=y
+CONFIG_DRM_DISPLAY_CONNECTOR=y
 CONFIG_DRM_SIMPLE_BRIDGE=y
 CONFIG_DRM_PL111=y
 CONFIG_FB_MODE_HELPERS=y
index 24dd5bb..094337d 100644 (file)
@@ -24,7 +24,9 @@ static int imx6q_enter_wait(struct cpuidle_device *dev,
                imx6_set_lpm(WAIT_UNCLOCKED);
        raw_spin_unlock(&cpuidle_lock);
 
+       rcu_idle_enter();
        cpu_do_idle();
+       rcu_idle_exit();
 
        raw_spin_lock(&cpuidle_lock);
        if (num_idle_cpus-- == num_online_cpus())
@@ -44,7 +46,7 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
                {
                        .exit_latency = 50,
                        .target_residency = 75,
-                       .flags = CPUIDLE_FLAG_TIMER_STOP,
+                       .flags = CPUIDLE_FLAG_TIMER_STOP | CPUIDLE_FLAG_RCU_IDLE,
                        .enter = imx6q_enter_wait,
                        .name = "WAIT",
                        .desc = "Clock off",
index 54aff33..bfa5e1b 100644 (file)
@@ -74,7 +74,7 @@ static struct powerdomain *_get_pwrdm(struct device *dev)
                return pwrdm;
 
        clk = of_clk_get(dev->of_node->parent, 0);
-       if (!clk) {
+       if (IS_ERR(clk)) {
                dev_err(dev, "no fck found\n");
                return NULL;
        }
index e93145d..a6ab368 100644 (file)
@@ -150,7 +150,7 @@ static int xen_starting_cpu(unsigned int cpu)
        pr_info("Xen: initializing cpu%d\n", cpu);
        vcpup = per_cpu_ptr(xen_vcpu_info, cpu);
 
-       info.mfn = virt_to_gfn(vcpup);
+       info.mfn = percpu_to_gfn(vcpup);
        info.offset = xen_offset_in_page(vcpup);
 
        err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, xen_vcpu_nr(cpu),
index 15f7b0e..3980206 100644 (file)
                };
 
                qspi: spi@66470200 {
-                       compatible = "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi";
+                       compatible = "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi";
                        reg = <0x66470200 0x184>,
                                <0x66470000 0x124>,
                                <0x67017408 0x004>,
index a39f0a1..903c0eb 100644 (file)
@@ -28,6 +28,7 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-honeycomb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
 
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-beacon-kit.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mn-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mn-ddr4-evk.dtb
index 9de2aa1..a5154f1 100644 (file)
                                reg = <0x30bd0000 0x10000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MP_CLK_SDMA1_ROOT>,
-                                        <&clk IMX8MP_CLK_SDMA1_ROOT>;
+                                        <&clk IMX8MP_CLK_AHB>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
index f70435c..561fa79 100644 (file)
                        tmu: tmu@30260000 {
                                compatible = "fsl,imx8mq-tmu";
                                reg = <0x30260000 0x10000>;
-                               interrupt = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MQ_CLK_TMU_ROOT>;
                                little-endian;
                                fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>;
index 9174ddc..3ec99f1 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <dt-bindings/power/xlnx-zynqmp-power.h>
+#include <dt-bindings/reset/xlnx-zynqmp-resets.h>
 
 / {
        compatible = "xlnx,zynqmp";
                        };
                };
 
+               psgtr: phy@fd400000 {
+                       compatible = "xlnx,zynqmp-psgtr-v1.1";
+                       status = "disabled";
+                       reg = <0x0 0xfd400000 0x0 0x40000>,
+                             <0x0 0xfd3d0000 0x0 0x1000>;
+                       reg-names = "serdes", "siou";
+                       #phy-cells = <4>;
+               };
+
                rtc: rtc@ffa60000 {
                        compatible = "xlnx,zynqmp-rtc";
                        status = "disabled";
                        power-domains = <&zynqmp_firmware PD_SD_1>;
                };
 
-               smmu: smmu@fd800000 {
+               smmu: iommu@fd800000 {
                        compatible = "arm,mmu-500";
                        reg = <0x0 0xfd800000 0x0 0x20000>;
                        status = "disabled";
index e0f3382..6d04b95 100644 (file)
@@ -724,6 +724,17 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_USB_RENESAS_USB3=m
 CONFIG_USB_TEGRA_XUDC=m
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_TYPEC=m
 CONFIG_TYPEC_TCPM=m
 CONFIG_TYPEC_FUSB302=m
@@ -914,6 +925,7 @@ CONFIG_ARCH_TEGRA_194_SOC=y
 CONFIG_ARCH_K3_AM6_SOC=y
 CONFIG_ARCH_K3_J721E_SOC=y
 CONFIG_TI_SCI_PM_DOMAINS=y
+CONFIG_EXTCON_PTN5150=m
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_EXTCON_USBC_CROS_EC=y
 CONFIG_IIO=y
index b357164..63a52ad 100644 (file)
@@ -788,7 +788,7 @@ SYM_FUNC_START_LOCAL(__xts_crypt8)
 
 0:     mov             bskey, x21
        mov             rounds, x22
-       br              x7
+       br              x16
 SYM_FUNC_END(__xts_crypt8)
 
        .macro          __xts_crypt, do8, o0, o1, o2, o3, o4, o5, o6, o7
@@ -806,7 +806,7 @@ SYM_FUNC_END(__xts_crypt8)
        uzp1            v30.4s, v30.4s, v25.4s
        ld1             {v25.16b}, [x24]
 
-99:    adr             x7, \do8
+99:    adr             x16, \do8
        bl              __xts_crypt8
 
        ldp             q16, q17, [sp, #.Lframe_local_offset]
index 49a55be..1cc5f5f 100644 (file)
@@ -298,15 +298,15 @@ static __always_inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
        return (kvm_vcpu_get_esr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
 }
 
-static __always_inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_abt_iss1tw(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_S1PTW);
 }
 
+/* Always check for S1PTW *before* using this. */
 static __always_inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
 {
-       return !!(kvm_vcpu_get_esr(vcpu) & ESR_ELx_WNR) ||
-               kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */
+       return kvm_vcpu_get_esr(vcpu) & ESR_ELx_WNR;
 }
 
 static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
@@ -335,6 +335,11 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
 }
 
+static inline bool kvm_vcpu_trap_is_exec_fault(const struct kvm_vcpu *vcpu)
+{
+       return kvm_vcpu_trap_is_iabt(vcpu) && !kvm_vcpu_abt_iss1tw(vcpu);
+}
+
 static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC;
@@ -372,6 +377,9 @@ static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
 
 static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
 {
+       if (kvm_vcpu_abt_iss1tw(vcpu))
+               return true;
+
        if (kvm_vcpu_trap_is_iabt(vcpu))
                return false;
 
index e52c927..905c2b8 100644 (file)
@@ -368,7 +368,6 @@ struct kvm_vcpu_arch {
 
        /* Guest PV state */
        struct {
-               u64 steal;
                u64 last_steal;
                gpa_t base;
        } steal;
@@ -544,6 +543,7 @@ long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
 gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu);
 void kvm_update_stolen_time(struct kvm_vcpu *vcpu);
 
+bool kvm_arm_pvtime_supported(void);
 int kvm_arm_pvtime_set_attr(struct kvm_vcpu *vcpu,
                            struct kvm_device_attr *attr);
 int kvm_arm_pvtime_get_attr(struct kvm_vcpu *vcpu,
index a85174d..cada0b8 100644 (file)
@@ -298,8 +298,21 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
                case EFI_BOOT_SERVICES_DATA:
                case EFI_CONVENTIONAL_MEMORY:
                case EFI_PERSISTENT_MEMORY:
-                       pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
-                       return NULL;
+                       if (memblock_is_map_memory(phys) ||
+                           !memblock_is_region_memory(phys, size)) {
+                               pr_warn(FW_BUG "requested region covers kernel memory @ %pa\n", &phys);
+                               return NULL;
+                       }
+                       /*
+                        * Mapping kernel memory is permitted if the region in
+                        * question is covered by a single memblock with the
+                        * NOMAP attribute set: this enables the use of ACPI
+                        * table overrides passed via initramfs, which are
+                        * reserved in memory using arch_reserve_mem_area()
+                        * below. As this particular use case only requires
+                        * read access, fall through to the R/O mapping case.
+                        */
+                       fallthrough;
 
                case EFI_RUNTIME_SERVICES_CODE:
                        /*
@@ -388,3 +401,8 @@ int apei_claim_sea(struct pt_regs *regs)
 
        return err;
 }
+
+void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
+{
+       memblock_mark_nomap(addr, size);
+}
index c332d49..560ba69 100644 (file)
@@ -910,8 +910,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .desc = "ARM erratum 1418040",
                .capability = ARM64_WORKAROUND_1418040,
                ERRATA_MIDR_RANGE_LIST(erratum_1418040_list),
-               .type = (ARM64_CPUCAP_SCOPE_LOCAL_CPU |
-                        ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU),
+               /*
+                * We need to allow affected CPUs to come in late, but
+                * also need the non-affected CPUs to be able to come
+                * in at any point in time. Wonderful.
+                */
+               .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
        },
 #endif
 #ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT
index 295d664..c07d7a0 100644 (file)
@@ -50,16 +50,19 @@ static u64 pv_steal_clock(int cpu)
        struct pv_time_stolen_time_region *reg;
 
        reg = per_cpu_ptr(&stolen_time_region, cpu);
-       if (!reg->kaddr) {
-               pr_warn_once("stolen time enabled but not configured for cpu %d\n",
-                            cpu);
+
+       /*
+        * paravirt_steal_clock() may be called before the CPU
+        * online notification callback runs. Until the callback
+        * has run we just return zero.
+        */
+       if (!reg->kaddr)
                return 0;
-       }
 
        return le64_to_cpu(READ_ONCE(reg->kaddr->stolen_time));
 }
 
-static int stolen_time_dying_cpu(unsigned int cpu)
+static int stolen_time_cpu_down_prepare(unsigned int cpu)
 {
        struct pv_time_stolen_time_region *reg;
 
@@ -73,7 +76,7 @@ static int stolen_time_dying_cpu(unsigned int cpu)
        return 0;
 }
 
-static int init_stolen_time_cpu(unsigned int cpu)
+static int stolen_time_cpu_online(unsigned int cpu)
 {
        struct pv_time_stolen_time_region *reg;
        struct arm_smccc_res res;
@@ -103,19 +106,20 @@ static int init_stolen_time_cpu(unsigned int cpu)
        return 0;
 }
 
-static int pv_time_init_stolen_time(void)
+static int __init pv_time_init_stolen_time(void)
 {
        int ret;
 
-       ret = cpuhp_setup_state(CPUHP_AP_ARM_KVMPV_STARTING,
-                               "hypervisor/arm/pvtime:starting",
-                               init_stolen_time_cpu, stolen_time_dying_cpu);
+       ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+                               "hypervisor/arm/pvtime:online",
+                               stolen_time_cpu_online,
+                               stolen_time_cpu_down_prepare);
        if (ret < 0)
                return ret;
        return 0;
 }
 
-static bool has_pv_steal_clock(void)
+static bool __init has_pv_steal_clock(void)
 {
        struct arm_smccc_res res;
 
index 46dc3d7..b588c3b 100644 (file)
@@ -206,6 +206,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                 */
                r = 1;
                break;
+       case KVM_CAP_STEAL_TIME:
+               r = kvm_arm_pvtime_supported();
+               break;
        default:
                r = kvm_arch_vm_ioctl_check_extension(kvm, ext);
                break;
index 5b6b8fa..0261308 100644 (file)
@@ -449,7 +449,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
                        kvm_vcpu_trap_get_fault_type(vcpu) == FSC_FAULT &&
                        kvm_vcpu_dabt_isvalid(vcpu) &&
                        !kvm_vcpu_abt_issea(vcpu) &&
-                       !kvm_vcpu_dabt_iss1tw(vcpu);
+                       !kvm_vcpu_abt_iss1tw(vcpu);
 
                if (valid) {
                        int ret = __vgic_v2_perform_cpuif_access(vcpu);
index 69eae60..b15d65a 100644 (file)
@@ -31,7 +31,14 @@ static void __tlb_switch_to_guest(struct kvm_s2_mmu *mmu,
                isb();
        }
 
+       /*
+        * __load_guest_stage2() includes an ISB only when the AT
+        * workaround is applied. Take care of the opposite condition,
+        * ensuring that we always have an ISB, but not two ISBs back
+        * to back.
+        */
        __load_guest_stage2(mmu);
+       asm(ALTERNATIVE("isb", "nop", ARM64_WORKAROUND_SPECULATIVE_AT));
 }
 
 static void __tlb_switch_to_host(struct tlb_inv_context *cxt)
index ba00bcc..3d26b47 100644 (file)
@@ -1849,7 +1849,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
        struct kvm_s2_mmu *mmu = vcpu->arch.hw_mmu;
 
        write_fault = kvm_is_write_fault(vcpu);
-       exec_fault = kvm_vcpu_trap_is_iabt(vcpu);
+       exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu);
        VM_BUG_ON(write_fault && exec_fault);
 
        if (fault_status == FSC_PERM && !write_fault && !exec_fault) {
@@ -1877,6 +1877,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
            !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) {
                force_pte = true;
                vma_pagesize = PAGE_SIZE;
+               vma_shift = PAGE_SHIFT;
        }
 
        /*
@@ -1970,7 +1971,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                (fault_status == FSC_PERM &&
                 stage2_is_exec(mmu, fault_ipa, vma_pagesize));
 
-       if (vma_pagesize == PUD_SIZE) {
+       /*
+        * If PUD_SIZE == PMD_SIZE, there is no real PUD level, and
+        * all we have is a 2-level page table. Trying to map a PUD in
+        * this case would be fatally wrong.
+        */
+       if (PUD_SIZE != PMD_SIZE && vma_pagesize == PUD_SIZE) {
                pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
 
                new_pud = kvm_pud_mkhuge(new_pud);
@@ -2125,7 +2131,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
                        goto out;
                }
 
-               if (kvm_vcpu_dabt_iss1tw(vcpu)) {
+               if (kvm_vcpu_abt_iss1tw(vcpu)) {
                        kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
                        ret = 1;
                        goto out_unlock;
index f7b52ce..920ac43 100644 (file)
 void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = vcpu->kvm;
-       u64 steal;
-       __le64 steal_le;
-       u64 offset;
-       int idx;
        u64 base = vcpu->arch.steal.base;
+       u64 last_steal = vcpu->arch.steal.last_steal;
+       u64 offset = offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
+       u64 steal = 0;
+       int idx;
 
        if (base == GPA_INVALID)
                return;
 
-       /* Let's do the local bookkeeping */
-       steal = vcpu->arch.steal.steal;
-       steal += current->sched_info.run_delay - vcpu->arch.steal.last_steal;
-       vcpu->arch.steal.last_steal = current->sched_info.run_delay;
-       vcpu->arch.steal.steal = steal;
-
-       steal_le = cpu_to_le64(steal);
        idx = srcu_read_lock(&kvm->srcu);
-       offset = offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
-       kvm_put_guest(kvm, base + offset, steal_le, u64);
+       if (!kvm_get_guest(kvm, base + offset, steal)) {
+               steal = le64_to_cpu(steal);
+               vcpu->arch.steal.last_steal = READ_ONCE(current->sched_info.run_delay);
+               steal += vcpu->arch.steal.last_steal - last_steal;
+               kvm_put_guest(kvm, base + offset, cpu_to_le64(steal));
+       }
        srcu_read_unlock(&kvm->srcu, idx);
 }
 
@@ -43,7 +40,8 @@ long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
        switch (feature) {
        case ARM_SMCCC_HV_PV_TIME_FEATURES:
        case ARM_SMCCC_HV_PV_TIME_ST:
-               val = SMCCC_RET_SUCCESS;
+               if (vcpu->arch.steal.base != GPA_INVALID)
+                       val = SMCCC_RET_SUCCESS;
                break;
        }
 
@@ -64,7 +62,6 @@ gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
         * Start counting stolen time from the time the guest requests
         * the feature enabled.
         */
-       vcpu->arch.steal.steal = 0;
        vcpu->arch.steal.last_steal = current->sched_info.run_delay;
 
        idx = srcu_read_lock(&kvm->srcu);
@@ -74,7 +71,7 @@ gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
        return base;
 }
 
-static bool kvm_arm_pvtime_supported(void)
+bool kvm_arm_pvtime_supported(void)
 {
        return !!sched_info_on();
 }
index 4691053..ff04443 100644 (file)
@@ -23,7 +23,7 @@ TRACE_EVENT(kvm_entry,
                __entry->vcpu_pc                = vcpu_pc;
        ),
 
-       TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
+       TP_printk("PC: 0x%016lx", __entry->vcpu_pc)
 );
 
 TRACE_EVENT(kvm_exit,
@@ -42,7 +42,7 @@ TRACE_EVENT(kvm_exit,
                __entry->vcpu_pc                = vcpu_pc;
        ),
 
-       TP_printk("%s: HSR_EC: 0x%04x (%s), PC: 0x%08lx",
+       TP_printk("%s: HSR_EC: 0x%04x (%s), PC: 0x%016lx",
                  __print_symbolic(__entry->ret, kvm_arm_exception_type),
                  __entry->esr_ec,
                  __print_symbolic(__entry->esr_ec, kvm_arm_exception_class),
@@ -69,7 +69,7 @@ TRACE_EVENT(kvm_guest_fault,
                __entry->ipa                    = ipa;
        ),
 
-       TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#08lx",
+       TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#016lx",
                  __entry->ipa, __entry->hsr,
                  __entry->hxfar, __entry->vcpu_pc)
 );
@@ -131,7 +131,7 @@ TRACE_EVENT(kvm_mmio_emulate,
                __entry->cpsr                   = cpsr;
        ),
 
-       TP_printk("Emulate MMIO at: 0x%08lx (instr: %08lx, cpsr: %08lx)",
+       TP_printk("Emulate MMIO at: 0x%016lx (instr: %08lx, cpsr: %08lx)",
                  __entry->vcpu_pc, __entry->instr, __entry->cpsr)
 );
 
@@ -149,7 +149,7 @@ TRACE_EVENT(kvm_unmap_hva_range,
                __entry->end            = end;
        ),
 
-       TP_printk("mmu notifier unmap range: %#08lx -- %#08lx",
+       TP_printk("mmu notifier unmap range: %#016lx -- %#016lx",
                  __entry->start, __entry->end)
 );
 
@@ -165,7 +165,7 @@ TRACE_EVENT(kvm_set_spte_hva,
                __entry->hva            = hva;
        ),
 
-       TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva)
+       TP_printk("mmu notifier set pte hva: %#016lx", __entry->hva)
 );
 
 TRACE_EVENT(kvm_age_hva,
@@ -182,7 +182,7 @@ TRACE_EVENT(kvm_age_hva,
                __entry->end            = end;
        ),
 
-       TP_printk("mmu notifier age hva: %#08lx -- %#08lx",
+       TP_printk("mmu notifier age hva: %#016lx -- %#016lx",
                  __entry->start, __entry->end)
 );
 
@@ -198,7 +198,7 @@ TRACE_EVENT(kvm_test_age_hva,
                __entry->hva            = hva;
        ),
 
-       TP_printk("mmu notifier test age hva: %#08lx", __entry->hva)
+       TP_printk("mmu notifier test age hva: %#016lx", __entry->hva)
 );
 
 TRACE_EVENT(kvm_set_way_flush,
index 2c56d1e..8d78acc 100644 (file)
@@ -22,7 +22,7 @@ TRACE_EVENT(kvm_wfx_arm64,
                __entry->is_wfe  = is_wfe;
        ),
 
-       TP_printk("guest executed wf%c at: 0x%08lx",
+       TP_printk("guest executed wf%c at: 0x%016lx",
                  __entry->is_wfe ? 'e' : 'i', __entry->vcpu_pc)
 );
 
@@ -42,7 +42,7 @@ TRACE_EVENT(kvm_hvc_arm64,
                __entry->imm = imm;
        ),
 
-       TP_printk("HVC at 0x%08lx (r0: 0x%08lx, imm: 0x%lx)",
+       TP_printk("HVC at 0x%016lx (r0: 0x%016lx, imm: 0x%lx)",
                  __entry->vcpu_pc, __entry->r0, __entry->imm)
 );
 
@@ -135,7 +135,7 @@ TRACE_EVENT(trap_reg,
                __entry->write_value = write_value;
        ),
 
-       TP_printk("%s %s reg %d (0x%08llx)", __entry->fn,  __entry->is_write?"write to":"read from", __entry->reg, __entry->write_value)
+       TP_printk("%s %s reg %d (0x%016llx)", __entry->fn,  __entry->is_write?"write to":"read from", __entry->reg, __entry->write_value)
 );
 
 TRACE_EVENT(kvm_handle_sys_reg,
index f8912e4..ef9f1d5 100644 (file)
@@ -143,14 +143,17 @@ static inline void emit_addr_mov_i64(const int reg, const u64 val,
        }
 }
 
-static inline int bpf2a64_offset(int bpf_to, int bpf_from,
+static inline int bpf2a64_offset(int bpf_insn, int off,
                                 const struct jit_ctx *ctx)
 {
-       int to = ctx->offset[bpf_to];
-       /* -1 to account for the Branch instruction */
-       int from = ctx->offset[bpf_from] - 1;
-
-       return to - from;
+       /* BPF JMP offset is relative to the next instruction */
+       bpf_insn++;
+       /*
+        * Whereas arm64 branch instructions encode the offset
+        * from the branch itself, so we must subtract 1 from the
+        * instruction offset.
+        */
+       return ctx->offset[bpf_insn + off] - (ctx->offset[bpf_insn] - 1);
 }
 
 static void jit_fill_hole(void *area, unsigned int size)
@@ -642,7 +645,7 @@ emit_bswap_uxt:
 
        /* JUMP off */
        case BPF_JMP | BPF_JA:
-               jmp_offset = bpf2a64_offset(i + off, i, ctx);
+               jmp_offset = bpf2a64_offset(i, off, ctx);
                check_imm26(jmp_offset);
                emit(A64_B(jmp_offset), ctx);
                break;
@@ -669,7 +672,7 @@ emit_bswap_uxt:
        case BPF_JMP32 | BPF_JSLE | BPF_X:
                emit(A64_CMP(is64, dst, src), ctx);
 emit_cond_jmp:
-               jmp_offset = bpf2a64_offset(i + off, i, ctx);
+               jmp_offset = bpf2a64_offset(i, off, ctx);
                check_imm19(jmp_offset);
                switch (BPF_OP(code)) {
                case BPF_JEQ:
@@ -908,10 +911,21 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass)
        const struct bpf_prog *prog = ctx->prog;
        int i;
 
+       /*
+        * - offset[0] offset of the end of prologue,
+        *   start of the 1st instruction.
+        * - offset[1] - offset of the end of 1st instruction,
+        *   start of the 2nd instruction
+        * [....]
+        * - offset[3] - offset of the end of 3rd instruction,
+        *   start of 4th instruction
+        */
        for (i = 0; i < prog->len; i++) {
                const struct bpf_insn *insn = &prog->insnsi[i];
                int ret;
 
+               if (ctx->image == NULL)
+                       ctx->offset[i] = ctx->idx;
                ret = build_insn(insn, ctx, extra_pass);
                if (ret > 0) {
                        i++;
@@ -919,11 +933,16 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass)
                                ctx->offset[i] = ctx->idx;
                        continue;
                }
-               if (ctx->image == NULL)
-                       ctx->offset[i] = ctx->idx;
                if (ret)
                        return ret;
        }
+       /*
+        * offset is allocated with prog->len + 1 so fill in
+        * the last element with the offset after the last
+        * instruction (end of program)
+        */
+       if (ctx->image == NULL)
+               ctx->offset[i] = ctx->idx;
 
        return 0;
 }
@@ -1002,7 +1021,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        memset(&ctx, 0, sizeof(ctx));
        ctx.prog = prog;
 
-       ctx.offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
+       ctx.offset = kcalloc(prog->len + 1, sizeof(int), GFP_KERNEL);
        if (ctx.offset == NULL) {
                prog = orig_prog;
                goto out_off;
@@ -1089,7 +1108,7 @@ skip_init_ctx:
        prog->jited_len = prog_size;
 
        if (!prog->is_func || extra_pass) {
-               bpf_prog_fill_jited_linfo(prog, ctx.offset);
+               bpf_prog_fill_jited_linfo(prog, ctx.offset + 1);
 out_off:
                kfree(ctx.offset);
                kfree(jit_data);
index b66ba90..87927eb 100644 (file)
@@ -74,8 +74,6 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)
        buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
 }
 
-#define acpi_unlazy_tlb(x)
-
 #ifdef CONFIG_ACPI_NUMA
 extern cpumask_t early_cpu_possible_map;
 #define for_each_possible_early_cpu(cpu)  \
index 0b3fb4c..8e7b8c6 100644 (file)
@@ -538,7 +538,7 @@ virtual_memmap_init(u64 start, u64 end, void *arg)
        if (map_start < map_end)
                memmap_init_zone((unsigned long)(map_end - map_start),
                                 args->nid, args->zone, page_to_pfn(map_start),
-                                MEMMAP_EARLY, NULL);
+                                MEMINIT_EARLY, NULL);
        return 0;
 }
 
@@ -547,8 +547,8 @@ memmap_init (unsigned long size, int nid, unsigned long zone,
             unsigned long start_pfn)
 {
        if (!vmem_map) {
-               memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY,
-                               NULL);
+               memmap_init_zone(size, nid, zone, start_pfn,
+                                MEMINIT_EARLY, NULL);
        } else {
                struct page *start;
                struct memmap_init_callback_data args;
index c95fa3a..8f32829 100644 (file)
@@ -877,6 +877,7 @@ config SNI_RM
        select I8253
        select I8259
        select ISA
+       select MIPS_L1_CACHE_SHIFT_6
        select SWAP_IO_SPACE if CPU_BIG_ENDIAN
        select SYS_HAS_CPU_R4X00
        select SYS_HAS_CPU_R5000
index 82627c2..01427bd 100644 (file)
@@ -148,7 +148,7 @@ void __init plat_mem_setup(void)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
 
-       if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K)) {
+       if (c->cputype == CPU_74K) {
                pr_info("Using bcma bus\n");
 #ifdef CONFIG_BCM47XX_BCMA
                bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
index 75a7a38..3288cef 100644 (file)
@@ -47,6 +47,7 @@ static inline int __pure __get_cpu_type(const int cpu_type)
        case CPU_34K:
        case CPU_1004K:
        case CPU_74K:
+       case CPU_1074K:
        case CPU_M14KC:
        case CPU_M14KEC:
        case CPU_INTERAPTIV:
index 7de85d2..0c50ac4 100644 (file)
@@ -137,6 +137,8 @@ extern void kvm_init_loongson_ipi(struct kvm *kvm);
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        switch (type) {
+       case KVM_VM_MIPS_AUTO:
+               break;
 #ifdef CONFIG_KVM_MIPS_VZ
        case KVM_VM_MIPS_VZ:
 #else
index 4ab55f1..ae023b9 100644 (file)
@@ -44,6 +44,10 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
   endif
 endif
 
+# Some -march= flags enable MMI instructions, and GCC complains about that
+# support being enabled alongside -msoft-float. Thus explicitly disable MMI.
+cflags-y += $(call cc-option,-mno-loongson-mmi)
+
 #
 # Loongson Machines' Support
 #
index f130f62..00055d4 100644 (file)
@@ -95,10 +95,8 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
                        if (res)
                                goto fault;
 
-                       set_fpr64(current->thread.fpu.fpr,
-                               insn.loongson3_lswc2_format.rt, value);
-                       set_fpr64(current->thread.fpu.fpr,
-                               insn.loongson3_lswc2_format.rq, value_next);
+                       set_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rt], 0, value);
+                       set_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rq], 0, value_next);
                        compute_return_epc(regs);
                        own_fpu(1);
                }
@@ -130,15 +128,13 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
                                goto sigbus;
 
                        lose_fpu(1);
-                       value_next = get_fpr64(current->thread.fpu.fpr,
-                                       insn.loongson3_lswc2_format.rq);
+                       value_next = get_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rq], 0);
 
                        StoreDW(addr + 8, value_next, res);
                        if (res)
                                goto fault;
 
-                       value = get_fpr64(current->thread.fpu.fpr,
-                                       insn.loongson3_lswc2_format.rt);
+                       value = get_fpr64(&current->thread.fpu.fpr[insn.loongson3_lswc2_format.rt], 0);
 
                        StoreDW(addr, value, res);
                        if (res)
@@ -204,8 +200,7 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
                        if (res)
                                goto fault;
 
-                       set_fpr64(current->thread.fpu.fpr,
-                                       insn.loongson3_lsdc2_format.rt, value);
+                       set_fpr64(&current->thread.fpu.fpr[insn.loongson3_lsdc2_format.rt], 0, value);
                        compute_return_epc(regs);
                        own_fpu(1);
 
@@ -221,8 +216,7 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
                        if (res)
                                goto fault;
 
-                       set_fpr64(current->thread.fpu.fpr,
-                                       insn.loongson3_lsdc2_format.rt, value);
+                       set_fpr64(&current->thread.fpu.fpr[insn.loongson3_lsdc2_format.rt], 0, value);
                        compute_return_epc(regs);
                        own_fpu(1);
                        break;
@@ -286,8 +280,7 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
                                goto sigbus;
 
                        lose_fpu(1);
-                       value = get_fpr64(current->thread.fpu.fpr,
-                                       insn.loongson3_lsdc2_format.rt);
+                       value = get_fpr64(&current->thread.fpu.fpr[insn.loongson3_lsdc2_format.rt], 0);
 
                        StoreW(addr, value, res);
                        if (res)
@@ -305,8 +298,7 @@ static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
                                goto sigbus;
 
                        lose_fpu(1);
-                       value = get_fpr64(current->thread.fpu.fpr,
-                                       insn.loongson3_lsdc2_format.rt);
+                       value = get_fpr64(&current->thread.fpu.fpr[insn.loongson3_lsdc2_format.rt], 0);
 
                        StoreDW(addr, value, res);
                        if (res)
index b09dc84..eeeec18 100644 (file)
@@ -143,7 +143,10 @@ static struct platform_device sc26xx_pdev = {
        },
 };
 
-static u32 a20r_ack_hwint(void)
+/*
+ * Trigger chipset to update CPU's CAUSE IP field
+ */
+static u32 a20r_update_cause_ip(void)
 {
        u32 status = read_c0_status();
 
@@ -205,12 +208,14 @@ static void a20r_hwint(void)
        int irq;
 
        clear_c0_status(IE_IRQ0);
-       status = a20r_ack_hwint();
+       status = a20r_update_cause_ip();
        cause = read_c0_cause();
 
        irq = ffs(((cause & status) >> 8) & 0xf8);
        if (likely(irq > 0))
                do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
+
+       a20r_update_cause_ip();
        set_c0_status(IE_IRQ0);
 }
 
index f039021..120f500 100644 (file)
@@ -165,19 +165,19 @@ struct __large_struct {
 
 #define __get_user_nocheck(x, ptr, size)                       \
 ({                                                             \
-       long __gu_err, __gu_val;                                \
-       __get_user_size(__gu_val, (ptr), (size), __gu_err);     \
-       (x) = (__force __typeof__(*(ptr)))__gu_val;             \
+       long __gu_err;                                          \
+       __get_user_size((x), (ptr), (size), __gu_err);          \
        __gu_err;                                               \
 })
 
 #define __get_user_check(x, ptr, size)                                 \
 ({                                                                     \
-       long __gu_err = -EFAULT, __gu_val = 0;                          \
+       long __gu_err = -EFAULT;                                        \
        const __typeof__(*(ptr)) __user *__gu_addr = (ptr);             \
-       if (access_ok(__gu_addr, size))                 \
-               __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
-       (x) = (__force __typeof__(*(ptr)))__gu_val;                     \
+       if (access_ok(__gu_addr, size))                                 \
+               __get_user_size((x), __gu_addr, (size), __gu_err);      \
+       else                                                            \
+               (x) = (__typeof__(*(ptr))) 0;                           \
        __gu_err;                                                       \
 })
 
@@ -191,11 +191,13 @@ do {                                                                      \
        case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break;         \
        case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break;         \
        case 8: __get_user_asm2(x, ptr, retval); break;                 \
-       default: (x) = __get_user_bad();                                \
+       default: (x) = (__typeof__(*(ptr)))__get_user_bad();            \
        }                                                               \
 } while (0)
 
 #define __get_user_asm(x, addr, err, op)               \
+{                                                      \
+       unsigned long __gu_tmp;                         \
        __asm__ __volatile__(                           \
                "1:     "op" %1,0(%2)\n"                \
                "2:\n"                                  \
@@ -209,10 +211,14 @@ do {                                                                      \
                "       .align 2\n"                     \
                "       .long 1b,3b\n"                  \
                ".previous"                             \
-               : "=r"(err), "=r"(x)                    \
-               : "r"(addr), "i"(-EFAULT), "0"(err))
+               : "=r"(err), "=r"(__gu_tmp)             \
+               : "r"(addr), "i"(-EFAULT), "0"(err));   \
+       (x) = (__typeof__(*(addr)))__gu_tmp;            \
+}
 
 #define __get_user_asm2(x, addr, err)                  \
+{                                                      \
+       unsigned long long __gu_tmp;                    \
        __asm__ __volatile__(                           \
                "1:     l.lwz %1,0(%2)\n"               \
                "2:     l.lwz %H1,4(%2)\n"              \
@@ -229,8 +235,11 @@ do {                                                                       \
                "       .long 1b,4b\n"                  \
                "       .long 2b,4b\n"                  \
                ".previous"                             \
-               : "=r"(err), "=&r"(x)                   \
-               : "r"(addr), "i"(-EFAULT), "0"(err))
+               : "=r"(err), "=&r"(__gu_tmp)            \
+               : "r"(addr), "i"(-EFAULT), "0"(err));   \
+       (x) = (__typeof__(*(addr)))(                    \
+               (__typeof__((x)-(x)))__gu_tmp);         \
+}
 
 /* more complex routines */
 
index b18e775..13c87f1 100644 (file)
@@ -80,6 +80,16 @@ static void __init setup_memory(void)
         */
        memblock_reserve(__pa(_stext), _end - _stext);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       /* Then reserve the initrd, if any */
+       if (initrd_start && (initrd_end > initrd_start)) {
+               unsigned long aligned_start = ALIGN_DOWN(initrd_start, PAGE_SIZE);
+               unsigned long aligned_end = ALIGN(initrd_end, PAGE_SIZE);
+
+               memblock_reserve(__pa(aligned_start), aligned_end - aligned_start);
+       }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
        early_init_fdt_reserve_self();
        early_init_fdt_scan_reserved_mem();
 
index 08f56af..534a52e 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-static void cache_loop(struct page *page, const unsigned int reg)
+static __always_inline void cache_loop(struct page *page, const unsigned int reg)
 {
        unsigned long paddr = page_to_pfn(page) << PAGE_SHIFT;
        unsigned long line = paddr & ~(L1_CACHE_BYTES - 1);
index 65bed1f..787e829 100644 (file)
@@ -116,7 +116,6 @@ config PPC
        #
        select ARCH_32BIT_OFF_T if PPC32
        select ARCH_HAS_DEBUG_VIRTUAL
-       select ARCH_HAS_DEBUG_VM_PGTABLE
        select ARCH_HAS_DEVMEM_IS_ALLOWED
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
index af9af03..15ed8d0 100644 (file)
@@ -108,7 +108,6 @@ CONFIG_FB_NVIDIA=y
 CONFIG_FB_NVIDIA_I2C=y
 CONFIG_FB_RADEON=y
 # CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
index 5e6f92b..66e9a0f 100644 (file)
@@ -743,7 +743,6 @@ CONFIG_FB_TRIDENT=m
 CONFIG_FB_SM501=m
 CONFIG_FB_IBM_GXT4500=y
 CONFIG_LCD_PLATFORM=m
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
index 55442d4..b392384 100644 (file)
@@ -239,14 +239,14 @@ static inline void early_init_mmu_secondary(void)
 
 extern void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                         phys_addr_t first_memblock_size);
-extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
-                                        phys_addr_t first_memblock_size);
 static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                              phys_addr_t first_memblock_size)
 {
-       if (early_radix_enabled())
-               return radix__setup_initial_memory_limit(first_memblock_base,
-                                                  first_memblock_size);
+       /*
+        * Hash has more strict restrictions. At this point we don't
+        * know which translations we will pick. Hence go with hash
+        * restrictions.
+        */
        return hash__setup_initial_memory_limit(first_memblock_base,
                                           first_memblock_size);
 }
index 569fecd..9053fc9 100644 (file)
@@ -120,7 +120,8 @@ u64 dma_iommu_get_required_mask(struct device *dev)
        if (!tbl)
                return 0;
 
-       mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+       mask = 1ULL << (fls_long(tbl->it_offset + tbl->it_size) +
+                       tbl->it_page_shift - 1);
        mask += mask - 1;
 
        return mask;
index 87ab115..e147bbd 100644 (file)
@@ -50,7 +50,7 @@ $(obj-vdso32): %.o: %.S FORCE
 
 # actual build commands
 quiet_cmd_vdso32ld = VDSO32L $@
-      cmd_vdso32ld = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ $(call cc-ldoption, -Wl$(comma)--orphan-handling=warn) -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
+      cmd_vdso32ld = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
 quiet_cmd_vdso32as = VDSO32A $@
       cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) -c -o $@ $<
 
index 4c98546..5206c2e 100644 (file)
@@ -111,7 +111,6 @@ SECTIONS
                *(.note.GNU-stack)
                *(.data .data.* .gnu.linkonce.d.* .sdata*)
                *(.bss .sbss .dynbss .dynsbss)
-               *(.glink .iplt .plt .rela*)
        }
 }
 
index 38c317f..32ebb35 100644 (file)
@@ -34,7 +34,7 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
 
 # actual build commands
 quiet_cmd_vdso64ld = VDSO64L $@
-      cmd_vdso64ld = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) $(call cc-ldoption, -Wl$(comma)--orphan-handling=warn)
+      cmd_vdso64ld = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
 
 # install commands for the unstripped file
 quiet_cmd_vdso_install = INSTALL $@
index 4e3a8d4..256fb97 100644 (file)
@@ -30,7 +30,7 @@ SECTIONS
        . = ALIGN(16);
        .text           : {
                *(.text .stub .text.* .gnu.linkonce.t.* __ftr_alt_*)
-               *(.sfpr)
+               *(.sfpr .glink)
        }                                               :text
        PROVIDE(__etext = .);
        PROVIDE(_etext = .);
@@ -111,7 +111,6 @@ SECTIONS
                *(.branch_lt)
                *(.data .data.* .gnu.linkonce.d.* .sdata*)
                *(.bss .sbss .dynbss .dynsbss)
-               *(.glink .iplt .plt .rela*)
        }
 }
 
index 28c7849..d5f0c10 100644 (file)
@@ -734,21 +734,6 @@ void radix__mmu_cleanup_all(void)
        }
 }
 
-void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
-                               phys_addr_t first_memblock_size)
-{
-       /*
-        * We don't currently support the first MEMBLOCK not mapping 0
-        * physical on those processors
-        */
-       BUG_ON(first_memblock_base != 0);
-
-       /*
-        * Radix mode is not limited by RMA / VRMA addressing.
-        */
-       ppc64_rma_size = ULONG_MAX;
-}
-
 #ifdef CONFIG_MEMORY_HOTPLUG
 static void free_pte_table(pte_t *pte_start, pmd_t *pmd)
 {
index 02e127f..8459056 100644 (file)
@@ -433,9 +433,16 @@ void __init mmu_early_init_devtree(void)
        if (!(mfmsr() & MSR_HV))
                early_check_vec5();
 
-       if (early_radix_enabled())
+       if (early_radix_enabled()) {
                radix__early_init_devtree();
-       else
+               /*
+                * We have finalized the translation we are going to use by now.
+                * Radix mode is not limited by RMA / VRMA addressing.
+                * Hence don't limit memblock allocations.
+                */
+               ppc64_rma_size = ULONG_MAX;
+               memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
+       } else
                hash__early_init_devtree();
 }
 #endif /* CONFIG_PPC_BOOK3S_64 */
index 78d61f9..e809cb5 100644 (file)
@@ -475,7 +475,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                case BPF_JMP | BPF_JSET | BPF_K:
                case BPF_JMP | BPF_JSET | BPF_X:
                        true_cond = COND_NE;
-                       fallthrough;
                cond_branch:
                        /* same targets, can avoid doing the test :) */
                        if (filter[i].jt == filter[i].jf) {
index f439f0d..a88a707 100644 (file)
@@ -822,7 +822,7 @@ free_stats:
        kfree(stats);
        return rc ? rc : seq_buf_used(&s);
 }
-DEVICE_ATTR_RO(perf_stats);
+DEVICE_ATTR_ADMIN_RO(perf_stats);
 
 static ssize_t flags_show(struct device *dev,
                          struct device_attribute *attr, char *buf)
index df18372..7766e12 100644 (file)
@@ -32,6 +32,7 @@ config RISCV
        select ARCH_WANT_FRAME_POINTERS
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
        select CLONE_BACKWARDS
+       select CLINT_TIMER if !MMU
        select COMMON_CLK
        select EDAC_SUPPORT
        select GENERIC_ARCH_TOPOLOGY if SMP
index c1df56c..d2d0ff6 100644 (file)
                        #clock-cells = <1>;
                };
 
-               clint0: interrupt-controller@2000000 {
+               clint0: clint@2000000 {
+                       #interrupt-cells = <1>;
                        compatible = "riscv,clint0";
                        reg = <0x2000000 0xC000>;
-                       interrupts-extended = <&cpu0_intc 3>,  <&cpu1_intc 3>;
+                       interrupts-extended =  <&cpu0_intc 3 &cpu0_intc 7
+                                               &cpu1_intc 3 &cpu1_intc 7>;
                        clocks = <&sysctl K210_CLK_ACLK>;
                };
 
diff --git a/arch/riscv/include/asm/clint.h b/arch/riscv/include/asm/clint.h
new file mode 100644 (file)
index 0000000..0789fd3
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Google, Inc
+ */
+
+#ifndef _ASM_RISCV_CLINT_H
+#define _ASM_RISCV_CLINT_H
+
+#include <linux/types.h>
+#include <asm/mmio.h>
+
+#ifdef CONFIG_RISCV_M_MODE
+/*
+ * This lives in the CLINT driver, but is accessed directly by timex.h to avoid
+ * any overhead when accessing the MMIO timer.
+ *
+ * The ISA defines mtime as a 64-bit memory-mapped register that increments at
+ * a constant frequency, but it doesn't define some other constraints we depend
+ * on (most notably ordering constraints, but also some simpler stuff like the
+ * memory layout).  Thus, this is called "clint_time_val" instead of something
+ * like "riscv_mtime", to signify that these non-ISA assumptions must hold.
+ */
+extern u64 __iomem *clint_time_val;
+#endif
+
+#endif
index ace8a6e..845002c 100644 (file)
@@ -66,6 +66,13 @@ do {                                                                 \
  * Let auipc+jalr be the basic *mcount unit*, so we make it 8 bytes here.
  */
 #define MCOUNT_INSN_SIZE 8
+
+#ifndef __ASSEMBLY__
+struct dyn_ftrace;
+int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
+#define ftrace_init_nop ftrace_init_nop
+#endif
+
 #endif
 
 #endif /* _ASM_RISCV_FTRACE_H */
index d95f7b2..5962f88 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/random.h>
 #include <linux/version.h>
-#include <asm/timex.h>
 
 extern unsigned long __stack_chk_guard;
 
@@ -18,12 +17,9 @@ extern unsigned long __stack_chk_guard;
 static __always_inline void boot_init_stack_canary(void)
 {
        unsigned long canary;
-       unsigned long tsc;
 
        /* Try to get a semi random initial value. */
        get_random_bytes(&canary, sizeof(canary));
-       tsc = get_cycles();
-       canary += tsc + (tsc << BITS_PER_LONG/2);
        canary ^= LINUX_VERSION_CODE;
        canary &= CANARY_MASK;
 
index a3fb85d..ab10490 100644 (file)
 
 typedef unsigned long cycles_t;
 
+#ifdef CONFIG_RISCV_M_MODE
+
+#include <asm/clint.h>
+
+#ifdef CONFIG_64BIT
+static inline cycles_t get_cycles(void)
+{
+       return readq_relaxed(clint_time_val);
+}
+#else /* !CONFIG_64BIT */
+static inline u32 get_cycles(void)
+{
+       return readl_relaxed(((u32 *)clint_time_val));
+}
+#define get_cycles get_cycles
+
+static inline u32 get_cycles_hi(void)
+{
+       return readl_relaxed(((u32 *)clint_time_val) + 1);
+}
+#define get_cycles_hi get_cycles_hi
+#endif /* CONFIG_64BIT */
+
+/*
+ * Much like MIPS, we may not have a viable counter to use at an early point
+ * in the boot process. Unfortunately we don't have a fallback, so instead
+ * we just return 0.
+ */
+static inline unsigned long random_get_entropy(void)
+{
+       if (unlikely(clint_time_val == NULL))
+               return 0;
+       return get_cycles();
+}
+#define random_get_entropy()   random_get_entropy()
+
+#else /* CONFIG_RISCV_M_MODE */
+
 static inline cycles_t get_cycles(void)
 {
        return csr_read(CSR_TIME);
@@ -41,6 +79,8 @@ static inline u64 get_cycles64(void)
 }
 #endif /* CONFIG_64BIT */
 
+#endif /* !CONFIG_RISCV_M_MODE */
+
 #define ARCH_HAS_READ_CURRENT_TIMER
 static inline int read_current_timer(unsigned long *timer_val)
 {
index 2ff63d0..99e12fa 100644 (file)
@@ -97,6 +97,25 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
        return __ftrace_modify_call(rec->ip, addr, false);
 }
 
+
+/*
+ * This is called early on, and isn't wrapped by
+ * ftrace_arch_code_modify_{prepare,post_process}() and therefor doesn't hold
+ * text_mutex, which triggers a lockdep failure.  SMP isn't running so we could
+ * just directly poke the text, but it's simpler to just take the lock
+ * ourselves.
+ */
+int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
+{
+       int out;
+
+       ftrace_arch_code_modify_prepare();
+       out = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
+       ftrace_arch_code_modify_post_process();
+
+       return out;
+}
+
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
        int ret = __ftrace_modify_call((unsigned long)&ftrace_call,
index 787c75f..ca03762 100644 (file)
@@ -226,12 +226,11 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
 
        ptep = &fixmap_pte[pte_index(addr)];
 
-       if (pgprot_val(prot)) {
+       if (pgprot_val(prot))
                set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
-       } else {
+       else
                pte_clear(&init_mm, addr, ptep);
-               local_flush_tlb_page(addr);
-       }
+       local_flush_tlb_page(addr);
 }
 
 static pte_t *__init get_pte_virt(phys_addr_t pa)
index 7eb01a5..b55561c 100644 (file)
@@ -1260,26 +1260,44 @@ static inline pgd_t *pgd_offset_raw(pgd_t *pgd, unsigned long address)
 
 #define pgd_offset(mm, address) pgd_offset_raw(READ_ONCE((mm)->pgd), address)
 
-static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
+static inline p4d_t *p4d_offset_lockless(pgd_t *pgdp, pgd_t pgd, unsigned long address)
 {
-       if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R1)
-               return (p4d_t *) pgd_deref(*pgd) + p4d_index(address);
-       return (p4d_t *) pgd;
+       if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R1)
+               return (p4d_t *) pgd_deref(pgd) + p4d_index(address);
+       return (p4d_t *) pgdp;
 }
+#define p4d_offset_lockless p4d_offset_lockless
 
-static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
+static inline p4d_t *p4d_offset(pgd_t *pgdp, unsigned long address)
 {
-       if ((p4d_val(*p4d) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R2)
-               return (pud_t *) p4d_deref(*p4d) + pud_index(address);
-       return (pud_t *) p4d;
+       return p4d_offset_lockless(pgdp, *pgdp, address);
+}
+
+static inline pud_t *pud_offset_lockless(p4d_t *p4dp, p4d_t p4d, unsigned long address)
+{
+       if ((p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R2)
+               return (pud_t *) p4d_deref(p4d) + pud_index(address);
+       return (pud_t *) p4dp;
+}
+#define pud_offset_lockless pud_offset_lockless
+
+static inline pud_t *pud_offset(p4d_t *p4dp, unsigned long address)
+{
+       return pud_offset_lockless(p4dp, *p4dp, address);
 }
 #define pud_offset pud_offset
 
-static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
+static inline pmd_t *pmd_offset_lockless(pud_t *pudp, pud_t pud, unsigned long address)
+{
+       if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R3)
+               return (pmd_t *) pud_deref(pud) + pmd_index(address);
+       return (pmd_t *) pudp;
+}
+#define pmd_offset_lockless pmd_offset_lockless
+
+static inline pmd_t *pmd_offset(pud_t *pudp, unsigned long address)
 {
-       if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R3)
-               return (pmd_t *) pud_deref(*pud) + pmd_index(address);
-       return (pmd_t *) pud;
+       return pmd_offset_lockless(pudp, *pudp, address);
 }
 #define pmd_offset pmd_offset
 
index faca269..a44ddc2 100644 (file)
@@ -26,6 +26,7 @@ void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
 void do_secure_storage_access(struct pt_regs *regs);
 void do_non_secure_storage_access(struct pt_regs *regs);
+void do_secure_storage_violation(struct pt_regs *regs);
 
 void addressing_exception(struct pt_regs *regs);
 void data_exception(struct pt_regs *regs);
index c73f506..f7f1e64 100644 (file)
@@ -39,14 +39,13 @@ void enabled_wait(void)
        local_irq_restore(flags);
 
        /* Account time spent with enabled wait psw loaded as idle time. */
-       /* XXX seqcount has tracepoints that require RCU */
-       write_seqcount_begin(&idle->seqcount);
+       raw_write_seqcount_begin(&idle->seqcount);
        idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
        idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
        idle->idle_time += idle_time;
        idle->idle_count++;
        account_idle_time(cputime_to_nsecs(idle_time));
-       write_seqcount_end(&idle->seqcount);
+       raw_write_seqcount_end(&idle->seqcount);
 }
 NOKPROBE_SYMBOL(enabled_wait);
 
index 2c27907..9a92638 100644 (file)
@@ -80,7 +80,7 @@ PGM_CHECK(do_dat_exception)           /* 3b */
 PGM_CHECK_DEFAULT                      /* 3c */
 PGM_CHECK(do_secure_storage_access)    /* 3d */
 PGM_CHECK(do_non_secure_storage_access)        /* 3e */
-PGM_CHECK_DEFAULT                      /* 3f */
+PGM_CHECK(do_secure_storage_violation) /* 3f */
 PGM_CHECK(monitor_event_exception)     /* 40 */
 PGM_CHECK_DEFAULT                      /* 41 */
 PGM_CHECK_DEFAULT                      /* 42 */
index e600f69..c2c1b4e 100644 (file)
@@ -619,7 +619,7 @@ static struct notifier_block kdump_mem_nb = {
 /*
  * Make sure that the area behind memory_end is protected
  */
-static void reserve_memory_end(void)
+static void __init reserve_memory_end(void)
 {
        if (memory_end_set)
                memblock_reserve(memory_end, ULONG_MAX);
@@ -628,7 +628,7 @@ static void reserve_memory_end(void)
 /*
  * Make sure that oldmem, where the dump is stored, is protected
  */
-static void reserve_oldmem(void)
+static void __init reserve_oldmem(void)
 {
 #ifdef CONFIG_CRASH_DUMP
        if (OLDMEM_BASE)
@@ -640,7 +640,7 @@ static void reserve_oldmem(void)
 /*
  * Make sure that oldmem, where the dump is stored, is protected
  */
-static void remove_oldmem(void)
+static void __init remove_oldmem(void)
 {
 #ifdef CONFIG_CRASH_DUMP
        if (OLDMEM_BASE)
index 4c8c063..996884d 100644 (file)
@@ -859,6 +859,21 @@ void do_non_secure_storage_access(struct pt_regs *regs)
 }
 NOKPROBE_SYMBOL(do_non_secure_storage_access);
 
+void do_secure_storage_violation(struct pt_regs *regs)
+{
+       /*
+        * Either KVM messed up the secure guest mapping or the same
+        * page is mapped into multiple secure guests.
+        *
+        * This exception is only triggered when a guest 2 is running
+        * and can therefore never occur in kernel context.
+        */
+       printk_ratelimited(KERN_WARNING
+                          "Secure storage violation in task: %s, pid %d\n",
+                          current->comm, current->pid);
+       send_sig(SIGSEGV, current, 0);
+}
+
 #else
 void do_secure_storage_access(struct pt_regs *regs)
 {
@@ -869,4 +884,9 @@ void do_non_secure_storage_access(struct pt_regs *regs)
 {
        default_trap_handler(regs);
 }
+
+void do_secure_storage_violation(struct pt_regs *regs)
+{
+       default_trap_handler(regs);
+}
 #endif
index 4b62d6b..1804230 100644 (file)
@@ -668,6 +668,10 @@ EXPORT_SYMBOL_GPL(zpci_enable_device);
 int zpci_disable_device(struct zpci_dev *zdev)
 {
        zpci_dma_exit_device(zdev);
+       /*
+        * The zPCI function may already be disabled by the platform, this is
+        * detected in clp_disable_fh() which becomes a no-op.
+        */
        return clp_disable_fh(zdev);
 }
 EXPORT_SYMBOL_GPL(zpci_disable_device);
index 9a3a291..d9ae745 100644 (file)
@@ -143,6 +143,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                        zpci_remove_device(zdev);
                }
 
+               zdev->fh = ccdf->fh;
+               zpci_disable_device(zdev);
                zdev->state = ZPCI_FN_STATE_STANDBY;
                if (!clp_get_state(ccdf->fid, &state) &&
                    state == ZPCI_FN_STATE_RESERVED) {
index 1a0d7cf..100bf24 100644 (file)
@@ -8,7 +8,6 @@
 
 #ifdef CONFIG_SMP
 
-#include <linux/spinlock.h>
 #include <linux/atomic.h>
 #include <asm/current.h>
 #include <asm/percpu.h>
index ad96310..91ab260 100644 (file)
@@ -370,7 +370,6 @@ syscall_trace_entry:
         nop
        cmp/eq  #-1, r0
        bt      syscall_exit
-       mov.l   r0, @(OFF_R0,r15)       ! Save return value
        !                       Reload R0-R4 from kernel stack, where the
        !                       parent may have modified them using
        !                       ptrace(POKEUSR).  (Note that R0-R2 are
index b05bf92..5281685 100644 (file)
@@ -455,16 +455,11 @@ long arch_ptrace(struct task_struct *child, long request,
 
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       long ret = 0;
-
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-           tracehook_report_syscall_entry(regs))
-               /*
-                * Tracing decided this syscall should not happen.
-                * We'll return a bogus call number to get an ENOSYS
-                * error, but leave the original number in regs->regs[0].
-                */
-               ret = -1L;
+           tracehook_report_syscall_entry(regs)) {
+               regs->regs[0] = -ENOSYS;
+               return -1;
+       }
 
        if (secure_computing() == -1)
                return -1;
@@ -475,7 +470,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
        audit_syscall_entry(regs->regs[3], regs->regs[4], regs->regs[5],
                            regs->regs[6], regs->regs[7]);
 
-       return ret ?: regs->regs[0];
+       return 0;
 }
 
 asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
index 3962f59..ff7894f 100644 (file)
@@ -43,6 +43,8 @@ KBUILD_CFLAGS += -Wno-pointer-sign
 KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
 KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 KBUILD_CFLAGS += -D__DISABLE_EXPORTS
+# Disable relocation relaxation in case the link is not PIE.
+KBUILD_CFLAGS += $(call as-option,-Wa$(comma)-mrelax-relocations=no)
 
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
index d7577fe..7821079 100644 (file)
@@ -19,6 +19,7 @@ CONFIG_CGROUP_CPUACCT=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
+# CONFIG_64BIT is not set
 CONFIG_SMP=y
 CONFIG_X86_GENERIC=y
 CONFIG_HPET_TIMER=y
@@ -186,7 +187,6 @@ CONFIG_DRM_I915=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_EFI=y
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
index f856001..9936528 100644 (file)
@@ -181,7 +181,6 @@ CONFIG_DRM_I915=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_EFI=y
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
index 2f84c7c..870efee 100644 (file)
@@ -299,7 +299,7 @@ __visible noinstr void xen_pv_evtchn_do_upcall(struct pt_regs *regs)
        old_regs = set_irq_regs(regs);
 
        instrumentation_begin();
-       run_on_irqstack_cond(__xen_pv_evtchn_do_upcall, NULL, regs);
+       run_on_irqstack_cond(__xen_pv_evtchn_do_upcall, regs);
        instrumentation_begin();
 
        set_irq_regs(old_regs);
index 70dea93..d977079 100644 (file)
@@ -682,6 +682,8 @@ SYM_CODE_END(.Lbad_gs)
  * rdx: Function argument (can be NULL if none)
  */
 SYM_FUNC_START(asm_call_on_stack)
+SYM_INNER_LABEL(asm_call_sysvec_on_stack, SYM_L_GLOBAL)
+SYM_INNER_LABEL(asm_call_irq_on_stack, SYM_L_GLOBAL)
        /*
         * Save the frame pointer unconditionally. This allows the ORC
         * unwinder to handle the stack switch.
index ca09764..6d2df1e 100644 (file)
@@ -159,8 +159,6 @@ static inline u64 x86_default_get_root_pointer(void)
 extern int x86_acpi_numa_init(void);
 #endif /* CONFIG_ACPI_NUMA */
 
-#define acpi_unlazy_tlb(x)     leave_mm(x)
-
 #ifdef CONFIG_ACPI_APEI
 static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
 {
index 296b346..fb42659 100644 (file)
 #define FRAME_END "pop %" _ASM_BP "\n"
 
 #ifdef CONFIG_X86_64
+
 #define ENCODE_FRAME_POINTER                   \
        "lea 1(%rsp), %rbp\n\t"
+
+static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
+{
+       return (unsigned long)regs + 1;
+}
+
 #else /* !CONFIG_X86_64 */
+
 #define ENCODE_FRAME_POINTER                   \
        "movl %esp, %ebp\n\t"                   \
        "andl $0x7fffffff, %ebp\n\t"
+
+static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
+{
+       return (unsigned long)regs & 0x7fffffff;
+}
+
 #endif /* CONFIG_X86_64 */
 
 #endif /* __ASSEMBLY__ */
 
 #define ENCODE_FRAME_POINTER
 
+static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
+{
+       return 0;
+}
+
 #endif
 
 #define FRAME_BEGIN
index a433661..a063864 100644 (file)
@@ -242,7 +242,7 @@ __visible noinstr void func(struct pt_regs *regs)                   \
        instrumentation_begin();                                        \
        irq_enter_rcu();                                                \
        kvm_set_cpu_l1tf_flush_l1d();                                   \
-       run_on_irqstack_cond(__##func, regs, regs);                     \
+       run_sysvec_on_irqstack_cond(__##func, regs);                    \
        irq_exit_rcu();                                                 \
        instrumentation_end();                                          \
        irqentry_exit(regs, state);                                     \
index 4ae66f0..7758169 100644 (file)
@@ -12,20 +12,50 @@ static __always_inline bool irqstack_active(void)
        return __this_cpu_read(irq_count) != -1;
 }
 
-void asm_call_on_stack(void *sp, void *func, void *arg);
+void asm_call_on_stack(void *sp, void (*func)(void), void *arg);
+void asm_call_sysvec_on_stack(void *sp, void (*func)(struct pt_regs *regs),
+                             struct pt_regs *regs);
+void asm_call_irq_on_stack(void *sp, void (*func)(struct irq_desc *desc),
+                          struct irq_desc *desc);
 
-static __always_inline void __run_on_irqstack(void *func, void *arg)
+static __always_inline void __run_on_irqstack(void (*func)(void))
 {
        void *tos = __this_cpu_read(hardirq_stack_ptr);
 
        __this_cpu_add(irq_count, 1);
-       asm_call_on_stack(tos - 8, func, arg);
+       asm_call_on_stack(tos - 8, func, NULL);
+       __this_cpu_sub(irq_count, 1);
+}
+
+static __always_inline void
+__run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
+                        struct pt_regs *regs)
+{
+       void *tos = __this_cpu_read(hardirq_stack_ptr);
+
+       __this_cpu_add(irq_count, 1);
+       asm_call_sysvec_on_stack(tos - 8, func, regs);
+       __this_cpu_sub(irq_count, 1);
+}
+
+static __always_inline void
+__run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
+                     struct irq_desc *desc)
+{
+       void *tos = __this_cpu_read(hardirq_stack_ptr);
+
+       __this_cpu_add(irq_count, 1);
+       asm_call_irq_on_stack(tos - 8, func, desc);
        __this_cpu_sub(irq_count, 1);
 }
 
 #else /* CONFIG_X86_64 */
 static inline bool irqstack_active(void) { return false; }
-static inline void __run_on_irqstack(void *func, void *arg) { }
+static inline void __run_on_irqstack(void (*func)(void)) { }
+static inline void __run_sysvec_on_irqstack(void (*func)(struct pt_regs *regs),
+                                           struct pt_regs *regs) { }
+static inline void __run_irq_on_irqstack(void (*func)(struct irq_desc *desc),
+                                        struct irq_desc *desc) { }
 #endif /* !CONFIG_X86_64 */
 
 static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs)
@@ -37,17 +67,40 @@ static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs)
        return !user_mode(regs) && !irqstack_active();
 }
 
-static __always_inline void run_on_irqstack_cond(void *func, void *arg,
+
+static __always_inline void run_on_irqstack_cond(void (*func)(void),
                                                 struct pt_regs *regs)
 {
-       void (*__func)(void *arg) = func;
+       lockdep_assert_irqs_disabled();
+
+       if (irq_needs_irq_stack(regs))
+               __run_on_irqstack(func);
+       else
+               func();
+}
+
+static __always_inline void
+run_sysvec_on_irqstack_cond(void (*func)(struct pt_regs *regs),
+                           struct pt_regs *regs)
+{
+       lockdep_assert_irqs_disabled();
 
+       if (irq_needs_irq_stack(regs))
+               __run_sysvec_on_irqstack(func, regs);
+       else
+               func(regs);
+}
+
+static __always_inline void
+run_irq_on_irqstack_cond(void (*func)(struct irq_desc *desc), struct irq_desc *desc,
+                        struct pt_regs *regs)
+{
        lockdep_assert_irqs_disabled();
 
        if (irq_needs_irq_stack(regs))
-               __run_on_irqstack(__func, arg);
+               __run_irq_on_irqstack(func, desc);
        else
-               __func(arg);
+               func(desc);
 }
 
 #endif
index 779a89e..21f9c7f 100644 (file)
@@ -2243,6 +2243,7 @@ static inline void __init check_timer(void)
        legacy_pic->init(0);
        legacy_pic->make_irq(0);
        apic_write(APIC_LVT0, APIC_DM_EXTINT);
+       legacy_pic->unmask(0);
 
        unlock_ExtINT_logic();
 
index 1810602..c5dd503 100644 (file)
@@ -227,7 +227,7 @@ static __always_inline void handle_irq(struct irq_desc *desc,
                                       struct pt_regs *regs)
 {
        if (IS_ENABLED(CONFIG_X86_64))
-               run_on_irqstack_cond(desc->handle_irq, desc, regs);
+               run_irq_on_irqstack_cond(desc->handle_irq, desc, regs);
        else
                __handle_irq(desc, regs);
 }
index 1b4fe93..440eed5 100644 (file)
@@ -74,5 +74,5 @@ int irq_init_percpu_irqstack(unsigned int cpu)
 
 void do_softirq_own_stack(void)
 {
-       run_on_irqstack_cond(__do_softirq, NULL, NULL);
+       run_on_irqstack_cond(__do_softirq, NULL);
 }
index 08320b0..9663ba3 100644 (file)
@@ -270,9 +270,8 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_asyncpf_interrupt)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
        u32 token;
-       irqentry_state_t state;
 
-       state = irqentry_enter(regs);
+       ack_APIC_irq();
 
        inc_irq_stat(irq_hv_callback_count);
 
@@ -283,7 +282,6 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_asyncpf_interrupt)
                wrmsrl(MSR_KVM_ASYNC_PF_ACK, 1);
        }
 
-       irqentry_exit(regs, state);
        set_irq_regs(old_regs);
 }
 
index 13ce616..ba4593a 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/spec-ctrl.h>
 #include <asm/io_bitmap.h>
 #include <asm/proto.h>
+#include <asm/frame.h>
 
 #include "process.h"
 
@@ -133,7 +134,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
        fork_frame = container_of(childregs, struct fork_frame, regs);
        frame = &fork_frame->frame;
 
-       frame->bp = 0;
+       frame->bp = encode_frame_pointer(childregs);
        frame->ret_addr = (unsigned long) ret_from_fork;
        p->thread.sp = (unsigned long) fork_frame;
        p->thread.io_bitmap = NULL;
index 5299ef5..2f6510d 100644 (file)
@@ -2505,9 +2505,14 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt,
                *reg_write(ctxt, i) = GET_SMSTATE(u32, smstate, 0x7fd0 + i * 4);
 
        val = GET_SMSTATE(u32, smstate, 0x7fcc);
-       ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1);
+
+       if (ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1))
+               return X86EMUL_UNHANDLEABLE;
+
        val = GET_SMSTATE(u32, smstate, 0x7fc8);
-       ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1);
+
+       if (ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1))
+               return X86EMUL_UNHANDLEABLE;
 
        selector =                 GET_SMSTATE(u32, smstate, 0x7fc4);
        set_desc_base(&desc,       GET_SMSTATE(u32, smstate, 0x7f64));
@@ -2560,16 +2565,23 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt,
        ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7f70) | X86_EFLAGS_FIXED;
 
        val = GET_SMSTATE(u32, smstate, 0x7f68);
-       ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1);
+
+       if (ctxt->ops->set_dr(ctxt, 6, (val & DR6_VOLATILE) | DR6_FIXED_1))
+               return X86EMUL_UNHANDLEABLE;
+
        val = GET_SMSTATE(u32, smstate, 0x7f60);
-       ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1);
+
+       if (ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1))
+               return X86EMUL_UNHANDLEABLE;
 
        cr0 =                       GET_SMSTATE(u64, smstate, 0x7f58);
        cr3 =                       GET_SMSTATE(u64, smstate, 0x7f50);
        cr4 =                       GET_SMSTATE(u64, smstate, 0x7f48);
        ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smstate, 0x7f00));
        val =                       GET_SMSTATE(u64, smstate, 0x7ed0);
-       ctxt->ops->set_msr(ctxt, MSR_EFER, val & ~EFER_LMA);
+
+       if (ctxt->ops->set_msr(ctxt, MSR_EFER, val & ~EFER_LMA))
+               return X86EMUL_UNHANDLEABLE;
 
        selector =                  GET_SMSTATE(u32, smstate, 0x7e90);
        rsm_set_desc_flags(&desc,   GET_SMSTATE(u32, smstate, 0x7e92) << 8);
index 43fdb0c..71aa3da 100644 (file)
@@ -2469,7 +2469,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                }
 
                if (sp->unsync_children)
-                       kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
+                       kvm_make_request(KVM_REQ_MMU_SYNC, vcpu);
 
                __clear_sp_write_flooding_count(sp);
 
index fb68467..e90bc43 100644 (file)
@@ -586,7 +586,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
        svm->vcpu.arch.mp_state = KVM_MP_STATE_RUNNABLE;
 
        /* Give the current vmcb to the guest */
-       svm_set_gif(svm, false);
 
        nested_vmcb->save.es     = vmcb->save.es;
        nested_vmcb->save.cs     = vmcb->save.cs;
@@ -632,6 +631,9 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
        /* Restore the original control entries */
        copy_vmcb_control_area(&vmcb->control, &hsave->control);
 
+       /* On vmexit the  GIF is set to false */
+       svm_set_gif(svm, false);
+
        svm->vmcb->control.tsc_offset = svm->vcpu.arch.tsc_offset =
                svm->vcpu.arch.l1_tsc_offset;
 
@@ -1132,6 +1134,9 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
        load_nested_vmcb_control(svm, &ctl);
        nested_prepare_vmcb_control(svm);
 
+       if (!nested_svm_vmrun_msrpm(svm))
+               return -EINVAL;
+
 out_set_gif:
        svm_set_gif(svm, !!(kvm_state->flags & KVM_STATE_NESTED_GIF_SET));
        return 0;
index 402dc42..7bf7bf7 100644 (file)
@@ -1106,6 +1106,7 @@ void sev_vm_destroy(struct kvm *kvm)
                list_for_each_safe(pos, q, head) {
                        __unregister_enc_region_locked(kvm,
                                list_entry(pos, struct enc_region, list));
+                       cond_resched();
                }
        }
 
index 0194336..91ea74a 100644 (file)
@@ -2183,6 +2183,12 @@ static int iret_interception(struct vcpu_svm *svm)
        return 1;
 }
 
+static int invd_interception(struct vcpu_svm *svm)
+{
+       /* Treat an INVD instruction as a NOP and just skip it. */
+       return kvm_skip_emulated_instruction(&svm->vcpu);
+}
+
 static int invlpg_interception(struct vcpu_svm *svm)
 {
        if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
@@ -2774,7 +2780,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_RDPMC]                        = rdpmc_interception,
        [SVM_EXIT_CPUID]                        = cpuid_interception,
        [SVM_EXIT_IRET]                         = iret_interception,
-       [SVM_EXIT_INVD]                         = emulate_on_interception,
+       [SVM_EXIT_INVD]                         = invd_interception,
        [SVM_EXIT_PAUSE]                        = pause_interception,
        [SVM_EXIT_HLT]                          = halt_interception,
        [SVM_EXIT_INVLPG]                       = invlpg_interception,
@@ -2938,8 +2944,6 @@ static int handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
        if (npt_enabled)
                vcpu->arch.cr3 = svm->vmcb->save.cr3;
 
-       svm_complete_interrupts(svm);
-
        if (is_guest_mode(vcpu)) {
                int vmexit;
 
@@ -3504,7 +3508,6 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
        stgi();
 
        /* Any pending NMI will happen here */
-       exit_fastpath = svm_exit_handlers_fastpath(vcpu);
 
        if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
                kvm_after_interrupt(&svm->vcpu);
@@ -3518,6 +3521,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
        }
 
        svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
+       vmcb_mark_all_clean(svm->vmcb);
 
        /* if exit due to PF check for async PF */
        if (svm->vmcb->control.exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR)
@@ -3537,7 +3541,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
                     SVM_EXIT_EXCP_BASE + MC_VECTOR))
                svm_handle_mce(svm);
 
-       vmcb_mark_all_clean(svm->vmcb);
+       svm_complete_interrupts(svm);
+       exit_fastpath = svm_exit_handlers_fastpath(vcpu);
        return exit_fastpath;
 }
 
@@ -3900,21 +3905,28 @@ static int svm_pre_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
 static int svm_pre_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
-       struct vmcb *nested_vmcb;
        struct kvm_host_map map;
-       u64 guest;
-       u64 vmcb;
        int ret = 0;
 
-       guest = GET_SMSTATE(u64, smstate, 0x7ed8);
-       vmcb = GET_SMSTATE(u64, smstate, 0x7ee0);
+       if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) {
+               u64 saved_efer = GET_SMSTATE(u64, smstate, 0x7ed0);
+               u64 guest = GET_SMSTATE(u64, smstate, 0x7ed8);
+               u64 vmcb = GET_SMSTATE(u64, smstate, 0x7ee0);
 
-       if (guest) {
-               if (kvm_vcpu_map(&svm->vcpu, gpa_to_gfn(vmcb), &map) == -EINVAL)
-                       return 1;
-               nested_vmcb = map.hva;
-               ret = enter_svm_guest_mode(svm, vmcb, nested_vmcb);
-               kvm_vcpu_unmap(&svm->vcpu, &map, true);
+               if (guest) {
+                       if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM))
+                               return 1;
+
+                       if (!(saved_efer & EFER_SVME))
+                               return 1;
+
+                       if (kvm_vcpu_map(&svm->vcpu,
+                                        gpa_to_gfn(vmcb), &map) == -EINVAL)
+                               return 1;
+
+                       ret = enter_svm_guest_mode(svm, vmcb, map.hva);
+                       kvm_vcpu_unmap(&svm->vcpu, &map, true);
+               }
        }
 
        return ret;
index 23b58c2..1bb6b31 100644 (file)
@@ -4404,6 +4404,14 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
        if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu))
                kvm_vcpu_flush_tlb_current(vcpu);
 
+       /*
+        * VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between
+        * now and the new vmentry.  Ensure that the VMCS02 PDPTR fields are
+        * up-to-date before switching to L1.
+        */
+       if (enable_ept && is_pae_paging(vcpu))
+               vmx_ept_load_pdptrs(vcpu);
+
        leave_guest_mode(vcpu);
 
        if (nested_cpu_has_preemption_timer(vmcs12))
@@ -4668,7 +4676,7 @@ void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu)
                vmx->nested.msrs.entry_ctls_high &=
                                ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
                vmx->nested.msrs.exit_ctls_high &=
-                               ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+                               ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
        }
 }
 
index 819c185..96979c0 100644 (file)
@@ -129,6 +129,9 @@ static bool __read_mostly enable_preemption_timer = 1;
 module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
 #endif
 
+extern bool __read_mostly allow_smaller_maxphyaddr;
+module_param(allow_smaller_maxphyaddr, bool, S_IRUGO);
+
 #define KVM_VM_CR0_ALWAYS_OFF (X86_CR0_NW | X86_CR0_CD)
 #define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR0_NE
 #define KVM_VM_CR0_ALWAYS_ON                           \
@@ -791,6 +794,18 @@ void update_exception_bitmap(struct kvm_vcpu *vcpu)
         */
        if (is_guest_mode(vcpu))
                eb |= get_vmcs12(vcpu)->exception_bitmap;
+        else {
+               /*
+                * If EPT is enabled, #PF is only trapped if MAXPHYADDR is mismatched
+                * between guest and host.  In that case we only care about present
+                * faults.  For vmcs02, however, PFEC_MASK and PFEC_MATCH are set in
+                * prepare_vmcs02_rare.
+                */
+               bool selective_pf_trap = enable_ept && (eb & (1u << PF_VECTOR));
+               int mask = selective_pf_trap ? PFERR_PRESENT_MASK : 0;
+               vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, mask);
+               vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, mask);
+       }
 
        vmcs_write32(EXCEPTION_BITMAP, eb);
 }
@@ -2971,7 +2986,7 @@ static void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu)
        vpid_sync_context(to_vmx(vcpu)->vpid);
 }
 
-static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
+void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu)
 {
        struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
 
@@ -3114,7 +3129,7 @@ static void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd,
                        guest_cr3 = vcpu->arch.cr3;
                else /* vmcs01.GUEST_CR3 is already up-to-date. */
                        update_guest_cr3 = false;
-               ept_load_pdptrs(vcpu);
+               vmx_ept_load_pdptrs(vcpu);
        } else {
                guest_cr3 = pgd;
        }
@@ -4352,16 +4367,6 @@ static void init_vmcs(struct vcpu_vmx *vmx)
                vmx->pt_desc.guest.output_mask = 0x7F;
                vmcs_write64(GUEST_IA32_RTIT_CTL, 0);
        }
-
-       /*
-        * If EPT is enabled, #PF is only trapped if MAXPHYADDR is mismatched
-        * between guest and host.  In that case we only care about present
-        * faults.
-        */
-       if (enable_ept) {
-               vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, PFERR_PRESENT_MASK);
-               vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, PFERR_PRESENT_MASK);
-       }
 }
 
 static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
@@ -4803,6 +4808,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
                         * EPT will cause page fault only if we need to
                         * detect illegal GPAs.
                         */
+                       WARN_ON_ONCE(!allow_smaller_maxphyaddr);
                        kvm_fixup_and_inject_pf_error(vcpu, cr2, error_code);
                        return 1;
                } else
@@ -5331,7 +5337,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
         * would also use advanced VM-exit information for EPT violations to
         * reconstruct the page fault error code.
         */
-       if (unlikely(kvm_mmu_is_illegal_gpa(vcpu, gpa)))
+       if (unlikely(allow_smaller_maxphyaddr && kvm_mmu_is_illegal_gpa(vcpu, gpa)))
                return kvm_emulate_instruction(vcpu, 0);
 
        return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
@@ -6054,6 +6060,7 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
                        (exit_reason != EXIT_REASON_EXCEPTION_NMI &&
                        exit_reason != EXIT_REASON_EPT_VIOLATION &&
                        exit_reason != EXIT_REASON_PML_FULL &&
+                       exit_reason != EXIT_REASON_APIC_ACCESS &&
                        exit_reason != EXIT_REASON_TASK_SWITCH)) {
                vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
@@ -8304,11 +8311,12 @@ static int __init vmx_init(void)
        vmx_check_vmcs12_offsets();
 
        /*
-        * Intel processors don't have problems with
-        * GUEST_MAXPHYADDR < HOST_MAXPHYADDR so enable
-        * it for VMX by default
+        * Shadow paging doesn't have a (further) performance penalty
+        * from GUEST_MAXPHYADDR < HOST_MAXPHYADDR so enable it
+        * by default
         */
-       allow_smaller_maxphyaddr = true;
+       if (!enable_ept)
+               allow_smaller_maxphyaddr = true;
 
        return 0;
 }
index 26175a4..a0e4772 100644 (file)
@@ -356,6 +356,7 @@ void vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp);
 int vmx_find_msr_index(struct vmx_msrs *m, u32 msr);
 int vmx_handle_memory_failure(struct kvm_vcpu *vcpu, int r,
                              struct x86_exception *e);
+void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu);
 
 #define POSTED_INTR_ON  0
 #define POSTED_INTR_SN  1
@@ -551,7 +552,10 @@ static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
 
 static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu)
 {
-       return !enable_ept || cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits;
+       if (!enable_ept)
+               return true;
+
+       return allow_smaller_maxphyaddr && cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits;
 }
 
 void dump_vmcs(void);
index d39d6cf..ce856e0 100644 (file)
@@ -188,7 +188,7 @@ static struct kvm_shared_msrs __percpu *shared_msrs;
 u64 __read_mostly host_efer;
 EXPORT_SYMBOL_GPL(host_efer);
 
-bool __read_mostly allow_smaller_maxphyaddr;
+bool __read_mostly allow_smaller_maxphyaddr = 0;
 EXPORT_SYMBOL_GPL(allow_smaller_maxphyaddr);
 
 static u64 __read_mostly host_xss;
@@ -976,6 +976,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        unsigned long old_cr4 = kvm_read_cr4(vcpu);
        unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE |
                                   X86_CR4_SMEP;
+       unsigned long mmu_role_bits = pdptr_bits | X86_CR4_SMAP | X86_CR4_PKE;
 
        if (kvm_valid_cr4(vcpu, cr4))
                return 1;
@@ -1003,7 +1004,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        if (kvm_x86_ops.set_cr4(vcpu, cr4))
                return 1;
 
-       if (((cr4 ^ old_cr4) & pdptr_bits) ||
+       if (((cr4 ^ old_cr4) & mmu_role_bits) ||
            (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE)))
                kvm_mmu_reset_context(vcpu);
 
@@ -2731,7 +2732,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
                return 1;
 
        if (!lapic_in_kernel(vcpu))
-               return 1;
+               return data ? 1 : 0;
 
        vcpu->arch.apf.msr_en_val = data;
 
@@ -3221,9 +3222,22 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_IA32_POWER_CTL:
                msr_info->data = vcpu->arch.msr_ia32_power_ctl;
                break;
-       case MSR_IA32_TSC:
-               msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + vcpu->arch.tsc_offset;
+       case MSR_IA32_TSC: {
+               /*
+                * Intel SDM states that MSR_IA32_TSC read adds the TSC offset
+                * even when not intercepted. AMD manual doesn't explicitly
+                * state this but appears to behave the same.
+                *
+                * On userspace reads and writes, however, we unconditionally
+                * operate L1's TSC value to ensure backwards-compatible
+                * behavior for migration.
+                */
+               u64 tsc_offset = msr_info->host_initiated ? vcpu->arch.l1_tsc_offset :
+                                                           vcpu->arch.tsc_offset;
+
+               msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + tsc_offset;
                break;
+       }
        case MSR_MTRRcap:
        case 0x200 ... 0x2ff:
                return kvm_mtrr_get_msr(vcpu, msr_info->index, &msr_info->data);
@@ -3578,6 +3592,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_SMALLER_MAXPHYADDR:
                r = (int) allow_smaller_maxphyaddr;
                break;
+       case KVM_CAP_STEAL_TIME:
+               r = sched_info_on();
+               break;
        default:
                break;
        }
index b0dfac3..1847e99 100644 (file)
@@ -120,7 +120,7 @@ long __copy_user_flushcache(void *dst, const void __user *src, unsigned size)
         */
        if (size < 8) {
                if (!IS_ALIGNED(dest, 4) || size != 4)
-                       clean_cache_range(dst, 1);
+                       clean_cache_range(dst, size);
        } else {
                if (!IS_ALIGNED(dest, 8)) {
                        dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
index c34b090..fa98470 100644 (file)
@@ -5896,18 +5896,6 @@ static void bfq_finish_requeue_request(struct request *rq)
        struct bfq_data *bfqd;
 
        /*
-        * Requeue and finish hooks are invoked in blk-mq without
-        * checking whether the involved request is actually still
-        * referenced in the scheduler. To handle this fact, the
-        * following two checks make this function exit in case of
-        * spurious invocations, for which there is nothing to do.
-        *
-        * First, check whether rq has nothing to do with an elevator.
-        */
-       if (unlikely(!(rq->rq_flags & RQF_ELVPRIV)))
-               return;
-
-       /*
         * rq either is not associated with any icq, or is an already
         * requeued request that has not (yet) been re-inserted into
         * a bfq_queue.
index a9931f2..e865ea5 100644 (file)
@@ -879,8 +879,10 @@ bool __bio_try_merge_page(struct bio *bio, struct page *page,
                struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
 
                if (page_is_mergeable(bv, page, len, off, same_page)) {
-                       if (bio->bi_iter.bi_size > UINT_MAX - len)
+                       if (bio->bi_iter.bi_size > UINT_MAX - len) {
+                               *same_page = false;
                                return false;
+                       }
                        bv->bv_len += len;
                        bio->bi_iter.bi_size += len;
                        return true;
index 126021f..e81ca1b 100644 (file)
@@ -66,7 +66,7 @@ static inline void blk_mq_sched_requeue_request(struct request *rq)
        struct request_queue *q = rq->q;
        struct elevator_queue *e = q->elevator;
 
-       if (e && e->type->ops.requeue_request)
+       if ((rq->rq_flags & RQF_ELVPRIV) && e && e->type->ops.requeue_request)
                e->type->ops.requeue_request(rq);
 }
 
index b3d2785..cdced4a 100644 (file)
@@ -1412,6 +1412,11 @@ out:
 
        hctx->dispatched[queued_to_index(queued)]++;
 
+       /* If we didn't flush the entire list, we could have told the driver
+        * there was more coming, but that turned out to be a lie.
+        */
+       if ((!list_empty(list) || errors) && q->mq_ops->commit_rqs && queued)
+               q->mq_ops->commit_rqs(hctx);
        /*
         * Any items that need requeuing? Stuff them into hctx->dispatch,
         * that is where we will continue on next queue run.
@@ -1425,14 +1430,6 @@ out:
 
                blk_mq_release_budgets(q, nr_budgets);
 
-               /*
-                * If we didn't flush the entire list, we could have told
-                * the driver there was more coming, but that turned out to
-                * be a lie.
-                */
-               if (q->mq_ops->commit_rqs && queued)
-                       q->mq_ops->commit_rqs(hctx);
-
                spin_lock(&hctx->lock);
                list_splice_tail_init(list, &hctx->dispatch);
                spin_unlock(&hctx->lock);
@@ -2079,6 +2076,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                struct list_head *list)
 {
        int queued = 0;
+       int errors = 0;
 
        while (!list_empty(list)) {
                blk_status_t ret;
@@ -2095,6 +2093,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                                break;
                        }
                        blk_mq_end_request(rq, ret);
+                       errors++;
                } else
                        queued++;
        }
@@ -2104,7 +2103,8 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
         * the driver there was more coming, but that turned out to
         * be a lie.
         */
-       if (!list_empty(list) && hctx->queue->mq_ops->commit_rqs && queued)
+       if ((!list_empty(list) || errors) &&
+            hctx->queue->mq_ops->commit_rqs && queued)
                hctx->queue->mq_ops->commit_rqs(hctx);
 }
 
index 76a7e03..34b721a 100644 (file)
@@ -801,6 +801,52 @@ bool blk_queue_can_use_dma_map_merging(struct request_queue *q,
 }
 EXPORT_SYMBOL_GPL(blk_queue_can_use_dma_map_merging);
 
+/**
+ * blk_queue_set_zoned - configure a disk queue zoned model.
+ * @disk:      the gendisk of the queue to configure
+ * @model:     the zoned model to set
+ *
+ * Set the zoned model of the request queue of @disk according to @model.
+ * When @model is BLK_ZONED_HM (host managed), this should be called only
+ * if zoned block device support is enabled (CONFIG_BLK_DEV_ZONED option).
+ * If @model specifies BLK_ZONED_HA (host aware), the effective model used
+ * depends on CONFIG_BLK_DEV_ZONED settings and on the existence of partitions
+ * on the disk.
+ */
+void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
+{
+       switch (model) {
+       case BLK_ZONED_HM:
+               /*
+                * Host managed devices are supported only if
+                * CONFIG_BLK_DEV_ZONED is enabled.
+                */
+               WARN_ON_ONCE(!IS_ENABLED(CONFIG_BLK_DEV_ZONED));
+               break;
+       case BLK_ZONED_HA:
+               /*
+                * Host aware devices can be treated either as regular block
+                * devices (similar to drive managed devices) or as zoned block
+                * devices to take advantage of the zone command set, similarly
+                * to host managed devices. We try the latter if there are no
+                * partitions and zoned block device support is enabled, else
+                * we do nothing special as far as the block layer is concerned.
+                */
+               if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) ||
+                   disk_has_partitions(disk))
+                       model = BLK_ZONED_NONE;
+               break;
+       case BLK_ZONED_NONE:
+       default:
+               if (WARN_ON_ONCE(model != BLK_ZONED_NONE))
+                       model = BLK_ZONED_NONE;
+               break;
+       }
+
+       disk->queue->limits.zoned = model;
+}
+EXPORT_SYMBOL_GPL(blk_queue_set_zoned);
+
 static int __init blk_settings_init(void)
 {
        blk_max_low_pfn = max_low_pfn - 1;
index 5b4869c..722406b 100644 (file)
@@ -537,7 +537,7 @@ int bdev_del_partition(struct block_device *bdev, int partno)
 
        bdevp = bdget_disk(bdev->bd_disk, partno);
        if (!bdevp)
-               return -ENOMEM;
+               return -ENXIO;
 
        mutex_lock(&bdevp->bd_mutex);
        mutex_lock_nested(&bdev->bd_mutex, 1);
index d6e18df..4b044e6 100644 (file)
@@ -305,8 +305,6 @@ int ibm_partition(struct parsed_partitions *state)
        if (!disk->fops->getgeo)
                goto out_exit;
        fn = symbol_get(dasd_biodasdinfo);
-       if (!fn)
-               goto out_exit;
        blocksize = bdev_logical_block_size(bdev);
        if (blocksize <= 0)
                goto out_symbol;
@@ -326,7 +324,7 @@ int ibm_partition(struct parsed_partitions *state)
        geo->start = get_start_sect(bdev);
        if (disk->fops->getgeo(bdev, geo))
                goto out_freeall;
-       if (fn(disk, info)) {
+       if (!fn || fn(disk, info)) {
                kfree(info);
                info = NULL;
        }
@@ -370,7 +368,8 @@ out_nolab:
 out_nogeo:
        kfree(info);
 out_symbol:
-       symbol_put(dasd_biodasdinfo);
+       if (fn)
+               symbol_put(dasd_biodasdinfo);
 out_exit:
        return res;
 }
index ef722f0..7210840 100644 (file)
@@ -651,6 +651,7 @@ struct compat_cdrom_generic_command {
        compat_int_t    stat;
        compat_caddr_t  sense;
        unsigned char   data_direction;
+       unsigned char   pad[3];
        compat_int_t    quiet;
        compat_int_t    timeout;
        compat_caddr_t  reserved[1];
index 71a30b0..f66236c 100644 (file)
@@ -161,18 +161,10 @@ static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
 }
 
 /* Power(C) State timer broadcast control */
-static void lapic_timer_state_broadcast(struct acpi_processor *pr,
-                                      struct acpi_processor_cx *cx,
-                                      int broadcast)
+static bool lapic_timer_needs_broadcast(struct acpi_processor *pr,
+                                       struct acpi_processor_cx *cx)
 {
-       int state = cx - pr->power.states;
-
-       if (state >= pr->power.timer_broadcast_on_state) {
-               if (broadcast)
-                       tick_broadcast_enter();
-               else
-                       tick_broadcast_exit();
-       }
+       return cx - pr->power.states >= pr->power.timer_broadcast_on_state;
 }
 
 #else
@@ -180,10 +172,11 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 static void lapic_timer_check_state(int state, struct acpi_processor *pr,
                                   struct acpi_processor_cx *cstate) { }
 static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { }
-static void lapic_timer_state_broadcast(struct acpi_processor *pr,
-                                      struct acpi_processor_cx *cx,
-                                      int broadcast)
+
+static bool lapic_timer_needs_broadcast(struct acpi_processor *pr,
+                                       struct acpi_processor_cx *cx)
 {
+       return false;
 }
 
 #endif
@@ -566,32 +559,43 @@ static DEFINE_RAW_SPINLOCK(c3_lock);
 
 /**
  * acpi_idle_enter_bm - enters C3 with proper BM handling
+ * @drv: cpuidle driver
  * @pr: Target processor
  * @cx: Target state context
- * @timer_bc: Whether or not to change timer mode to broadcast
+ * @index: index of target state
  */
-static void acpi_idle_enter_bm(struct acpi_processor *pr,
-                              struct acpi_processor_cx *cx, bool timer_bc)
+static int acpi_idle_enter_bm(struct cpuidle_driver *drv,
+                              struct acpi_processor *pr,
+                              struct acpi_processor_cx *cx,
+                              int index)
 {
-       acpi_unlazy_tlb(smp_processor_id());
-
-       /*
-        * Must be done before busmaster disable as we might need to
-        * access HPET !
-        */
-       if (timer_bc)
-               lapic_timer_state_broadcast(pr, cx, 1);
+       static struct acpi_processor_cx safe_cx = {
+               .entry_method = ACPI_CSTATE_HALT,
+       };
 
        /*
         * disable bus master
         * bm_check implies we need ARB_DIS
         * bm_control implies whether we can do ARB_DIS
         *
-        * That leaves a case where bm_check is set and bm_control is
-        * not set. In that case we cannot do much, we enter C3
-        * without doing anything.
+        * That leaves a case where bm_check is set and bm_control is not set.
+        * In that case we cannot do much, we enter C3 without doing anything.
         */
-       if (pr->flags.bm_control) {
+       bool dis_bm = pr->flags.bm_control;
+
+       /* If we can skip BM, demote to a safe state. */
+       if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
+               dis_bm = false;
+               index = drv->safe_state_index;
+               if (index >= 0) {
+                       cx = this_cpu_read(acpi_cstate[index]);
+               } else {
+                       cx = &safe_cx;
+                       index = -EBUSY;
+               }
+       }
+
+       if (dis_bm) {
                raw_spin_lock(&c3_lock);
                c3_cpu_count++;
                /* Disable bus master arbitration when all CPUs are in C3 */
@@ -600,18 +604,21 @@ static void acpi_idle_enter_bm(struct acpi_processor *pr,
                raw_spin_unlock(&c3_lock);
        }
 
+       rcu_idle_enter();
+
        acpi_idle_do_entry(cx);
 
+       rcu_idle_exit();
+
        /* Re-enable bus master arbitration */
-       if (pr->flags.bm_control) {
+       if (dis_bm) {
                raw_spin_lock(&c3_lock);
                acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
                c3_cpu_count--;
                raw_spin_unlock(&c3_lock);
        }
 
-       if (timer_bc)
-               lapic_timer_state_broadcast(pr, cx, 0);
+       return index;
 }
 
 static int acpi_idle_enter(struct cpuidle_device *dev,
@@ -625,32 +632,21 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
                return -EINVAL;
 
        if (cx->type != ACPI_STATE_C1) {
+               if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check)
+                       return acpi_idle_enter_bm(drv, pr, cx, index);
+
+               /* C2 to C1 demotion. */
                if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) {
                        index = ACPI_IDLE_STATE_START;
                        cx = per_cpu(acpi_cstate[index], dev->cpu);
-               } else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) {
-                       if (cx->bm_sts_skip || !acpi_idle_bm_check()) {
-                               acpi_idle_enter_bm(pr, cx, true);
-                               return index;
-                       } else if (drv->safe_state_index >= 0) {
-                               index = drv->safe_state_index;
-                               cx = per_cpu(acpi_cstate[index], dev->cpu);
-                       } else {
-                               acpi_safe_halt();
-                               return -EBUSY;
-                       }
                }
        }
 
-       lapic_timer_state_broadcast(pr, cx, 1);
-
        if (cx->type == ACPI_STATE_C3)
                ACPI_FLUSH_CPU_CACHE();
 
        acpi_idle_do_entry(cx);
 
-       lapic_timer_state_broadcast(pr, cx, 0);
-
        return index;
 }
 
@@ -666,7 +662,13 @@ static int acpi_idle_enter_s2idle(struct cpuidle_device *dev,
                        return 0;
 
                if (pr->flags.bm_check) {
-                       acpi_idle_enter_bm(pr, cx, false);
+                       u8 bm_sts_skip = cx->bm_sts_skip;
+
+                       /* Don't check BM_STS, do an unconditional ARB_DIS for S2IDLE */
+                       cx->bm_sts_skip = 1;
+                       acpi_idle_enter_bm(drv, pr, cx, index);
+                       cx->bm_sts_skip = bm_sts_skip;
+
                        return 0;
                } else {
                        ACPI_FLUSH_CPU_CACHE();
@@ -682,11 +684,13 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
 {
        int i, count = ACPI_IDLE_STATE_START;
        struct acpi_processor_cx *cx;
+       struct cpuidle_state *state;
 
        if (max_cstate == 0)
                max_cstate = 1;
 
        for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) {
+               state = &acpi_idle_driver.states[count];
                cx = &pr->power.states[i];
 
                if (!cx->valid)
@@ -694,6 +698,15 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
 
                per_cpu(acpi_cstate[count], dev->cpu) = cx;
 
+               if (lapic_timer_needs_broadcast(pr, cx))
+                       state->flags |= CPUIDLE_FLAG_TIMER_STOP;
+
+               if (cx->type == ACPI_STATE_C3) {
+                       state->flags |= CPUIDLE_FLAG_TLB_FLUSHED;
+                       if (pr->flags.bm_check)
+                               state->flags |= CPUIDLE_FLAG_RCU_IDLE;
+               }
+
                count++;
                if (count == CPUIDLE_STATE_MAX)
                        break;
index 39be444..316a994 100644 (file)
@@ -2224,7 +2224,7 @@ static int eni_init_one(struct pci_dev *pci_dev,
 
        rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
        if (rc < 0)
-               goto out;
+               goto err_disable;
 
        rc = -ENOMEM;
        eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
index f6f620a..bb5806a 100644 (file)
@@ -807,9 +807,7 @@ static void device_link_put_kref(struct device_link *link)
 void device_link_del(struct device_link *link)
 {
        device_links_write_lock();
-       device_pm_lock();
        device_link_put_kref(link);
-       device_pm_unlock();
        device_links_write_unlock();
 }
 EXPORT_SYMBOL_GPL(device_link_del);
@@ -830,7 +828,6 @@ void device_link_remove(void *consumer, struct device *supplier)
                return;
 
        device_links_write_lock();
-       device_pm_lock();
 
        list_for_each_entry(link, &supplier->links.consumers, s_node) {
                if (link->consumer == consumer) {
@@ -839,7 +836,6 @@ void device_link_remove(void *consumer, struct device *supplier)
                }
        }
 
-       device_pm_unlock();
        device_links_write_unlock();
 }
 EXPORT_SYMBOL_GPL(device_link_remove);
@@ -4237,10 +4233,10 @@ int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
        vaf.va = &args;
 
        if (err != -EPROBE_DEFER) {
-               dev_err(dev, "error %d: %pV", err, &vaf);
+               dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
        } else {
                device_set_deferred_probe_reason(dev, &vaf);
-               dev_dbg(dev, "error %d: %pV", err, &vaf);
+               dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
        }
 
        va_end(args);
index 933e219..d08efc7 100644 (file)
@@ -142,10 +142,12 @@ int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags);
 void fw_free_paged_buf(struct fw_priv *fw_priv);
 int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
 int fw_map_paged_buf(struct fw_priv *fw_priv);
+bool fw_is_paged_buf(struct fw_priv *fw_priv);
 #else
 static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
 static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
 static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
+static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; }
 #endif
 
 #endif /* __FIRMWARE_LOADER_H */
index 9da0c9d..63b9714 100644 (file)
@@ -252,9 +252,11 @@ static void __free_fw_priv(struct kref *ref)
        list_del(&fw_priv->list);
        spin_unlock(&fwc->lock);
 
-       fw_free_paged_buf(fw_priv); /* free leftover pages */
-       if (!fw_priv->allocated_size)
+       if (fw_is_paged_buf(fw_priv))
+               fw_free_paged_buf(fw_priv);
+       else if (!fw_priv->allocated_size)
                vfree(fw_priv->data);
+
        kfree_const(fw_priv->fw_name);
        kfree(fw_priv);
 }
@@ -268,6 +270,11 @@ static void free_fw_priv(struct fw_priv *fw_priv)
 }
 
 #ifdef CONFIG_FW_LOADER_PAGED_BUF
+bool fw_is_paged_buf(struct fw_priv *fw_priv)
+{
+       return fw_priv->is_paged_buf;
+}
+
 void fw_free_paged_buf(struct fw_priv *fw_priv)
 {
        int i;
@@ -275,6 +282,8 @@ void fw_free_paged_buf(struct fw_priv *fw_priv)
        if (!fw_priv->pages)
                return;
 
+       vunmap(fw_priv->data);
+
        for (i = 0; i < fw_priv->nr_pages; i++)
                __free_page(fw_priv->pages[i]);
        kvfree(fw_priv->pages);
@@ -328,10 +337,6 @@ int fw_map_paged_buf(struct fw_priv *fw_priv)
        if (!fw_priv->data)
                return -ENOMEM;
 
-       /* page table is no longer needed after mapping, let's free */
-       kvfree(fw_priv->pages);
-       fw_priv->pages = NULL;
-
        return 0;
 }
 #endif
index 508b80f..50af16e 100644 (file)
@@ -761,14 +761,36 @@ static int __ref get_nid_for_pfn(unsigned long pfn)
        return pfn_to_nid(pfn);
 }
 
+static int do_register_memory_block_under_node(int nid,
+                                              struct memory_block *mem_blk)
+{
+       int ret;
+
+       /*
+        * If this memory block spans multiple nodes, we only indicate
+        * the last processed node.
+        */
+       mem_blk->nid = nid;
+
+       ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
+                                      &mem_blk->dev.kobj,
+                                      kobject_name(&mem_blk->dev.kobj));
+       if (ret)
+               return ret;
+
+       return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
+                               &node_devices[nid]->dev.kobj,
+                               kobject_name(&node_devices[nid]->dev.kobj));
+}
+
 /* register memory section under specified node if it spans that node */
-static int register_mem_sect_under_node(struct memory_block *mem_blk,
-                                        void *arg)
+static int register_mem_block_under_node_early(struct memory_block *mem_blk,
+                                              void *arg)
 {
        unsigned long memory_block_pfns = memory_block_size_bytes() / PAGE_SIZE;
        unsigned long start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
        unsigned long end_pfn = start_pfn + memory_block_pfns - 1;
-       int ret, nid = *(int *)arg;
+       int nid = *(int *)arg;
        unsigned long pfn;
 
        for (pfn = start_pfn; pfn <= end_pfn; pfn++) {
@@ -785,39 +807,34 @@ static int register_mem_sect_under_node(struct memory_block *mem_blk,
                }
 
                /*
-                * We need to check if page belongs to nid only for the boot
-                * case, during hotplug we know that all pages in the memory
-                * block belong to the same node.
-                */
-               if (system_state == SYSTEM_BOOTING) {
-                       page_nid = get_nid_for_pfn(pfn);
-                       if (page_nid < 0)
-                               continue;
-                       if (page_nid != nid)
-                               continue;
-               }
-
-               /*
-                * If this memory block spans multiple nodes, we only indicate
-                * the last processed node.
+                * We need to check if page belongs to nid only at the boot
+                * case because node's ranges can be interleaved.
                 */
-               mem_blk->nid = nid;
-
-               ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
-                                       &mem_blk->dev.kobj,
-                                       kobject_name(&mem_blk->dev.kobj));
-               if (ret)
-                       return ret;
+               page_nid = get_nid_for_pfn(pfn);
+               if (page_nid < 0)
+                       continue;
+               if (page_nid != nid)
+                       continue;
 
-               return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
-                               &node_devices[nid]->dev.kobj,
-                               kobject_name(&node_devices[nid]->dev.kobj));
+               return do_register_memory_block_under_node(nid, mem_blk);
        }
        /* mem section does not span the specified node */
        return 0;
 }
 
 /*
+ * During hotplug we know that all pages in the memory block belong to the same
+ * node.
+ */
+static int register_mem_block_under_node_hotplug(struct memory_block *mem_blk,
+                                                void *arg)
+{
+       int nid = *(int *)arg;
+
+       return do_register_memory_block_under_node(nid, mem_blk);
+}
+
+/*
  * Unregister a memory block device under the node it spans. Memory blocks
  * with multiple nodes cannot be offlined and therefore also never be removed.
  */
@@ -832,11 +849,19 @@ void unregister_memory_block_under_nodes(struct memory_block *mem_blk)
                          kobject_name(&node_devices[mem_blk->nid]->dev.kobj));
 }
 
-int link_mem_sections(int nid, unsigned long start_pfn, unsigned long end_pfn)
+int link_mem_sections(int nid, unsigned long start_pfn, unsigned long end_pfn,
+                     enum meminit_context context)
 {
+       walk_memory_blocks_func_t func;
+
+       if (context == MEMINIT_HOTPLUG)
+               func = register_mem_block_under_node_hotplug;
+       else
+               func = register_mem_block_under_node_early;
+
        return walk_memory_blocks(PFN_PHYS(start_pfn),
                                  PFN_PHYS(end_pfn - start_pfn), (void *)&nid,
-                                 register_mem_sect_under_node);
+                                 func);
 }
 
 #ifdef CONFIG_HUGETLBFS
index 3d80c4b..7be2fcf 100644 (file)
@@ -217,7 +217,7 @@ struct regmap_field {
 
 #ifdef CONFIG_DEBUG_FS
 extern void regmap_debugfs_initcall(void);
-extern void regmap_debugfs_init(struct regmap *map, const char *name);
+extern void regmap_debugfs_init(struct regmap *map);
 extern void regmap_debugfs_exit(struct regmap *map);
 
 static inline void regmap_debugfs_disable(struct regmap *map)
@@ -227,7 +227,7 @@ static inline void regmap_debugfs_disable(struct regmap *map)
 
 #else
 static inline void regmap_debugfs_initcall(void) { }
-static inline void regmap_debugfs_init(struct regmap *map, const char *name) { }
+static inline void regmap_debugfs_init(struct regmap *map) { }
 static inline void regmap_debugfs_exit(struct regmap *map) { }
 static inline void regmap_debugfs_disable(struct regmap *map) { }
 #endif
@@ -259,7 +259,7 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
 int regcache_lookup_reg(struct regmap *map, unsigned int reg);
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
-                     const void *val, size_t val_len);
+                     const void *val, size_t val_len, bool noinc);
 
 void regmap_async_complete_cb(struct regmap_async *async, int ret);
 
index a93cafd..7f4b3b6 100644 (file)
@@ -717,7 +717,7 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
 
        map->cache_bypass = true;
 
-       ret = _regmap_raw_write(map, base, *data, count * val_bytes);
+       ret = _regmap_raw_write(map, base, *data, count * val_bytes, false);
        if (ret)
                dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n",
                        base, cur - map->reg_stride, ret);
index f58baff..b6d63ef 100644 (file)
@@ -17,7 +17,6 @@
 
 struct regmap_debugfs_node {
        struct regmap *map;
-       const char *name;
        struct list_head link;
 };
 
@@ -544,11 +543,12 @@ static const struct file_operations regmap_cache_bypass_fops = {
        .write = regmap_cache_bypass_write_file,
 };
 
-void regmap_debugfs_init(struct regmap *map, const char *name)
+void regmap_debugfs_init(struct regmap *map)
 {
        struct rb_node *next;
        struct regmap_range_node *range_node;
        const char *devname = "dummy";
+       const char *name = map->name;
 
        /*
         * Userspace can initiate reads from the hardware over debugfs.
@@ -569,7 +569,6 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
                if (!node)
                        return;
                node->map = map;
-               node->name = name;
                mutex_lock(&regmap_debugfs_early_lock);
                list_add(&node->link, &regmap_debugfs_early_list);
                mutex_unlock(&regmap_debugfs_early_lock);
@@ -679,7 +678,7 @@ void regmap_debugfs_initcall(void)
 
        mutex_lock(&regmap_debugfs_early_lock);
        list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list, link) {
-               regmap_debugfs_init(node->map, node->name);
+               regmap_debugfs_init(node->map);
                list_del(&node->link);
                kfree(node);
        }
index e93700a..b71f9ec 100644 (file)
@@ -581,14 +581,34 @@ static void regmap_range_exit(struct regmap *map)
        kfree(map->selector_work_buf);
 }
 
+static int regmap_set_name(struct regmap *map, const struct regmap_config *config)
+{
+       if (config->name) {
+               const char *name = kstrdup_const(config->name, GFP_KERNEL);
+
+               if (!name)
+                       return -ENOMEM;
+
+               kfree_const(map->name);
+               map->name = name;
+       }
+
+       return 0;
+}
+
 int regmap_attach_dev(struct device *dev, struct regmap *map,
                      const struct regmap_config *config)
 {
        struct regmap **m;
+       int ret;
 
        map->dev = dev;
 
-       regmap_debugfs_init(map, config->name);
+       ret = regmap_set_name(map, config);
+       if (ret)
+               return ret;
+
+       regmap_debugfs_init(map);
 
        /* Add a devres resource for dev_get_regmap() */
        m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
@@ -687,13 +707,9 @@ struct regmap *__regmap_init(struct device *dev,
                goto err;
        }
 
-       if (config->name) {
-               map->name = kstrdup_const(config->name, GFP_KERNEL);
-               if (!map->name) {
-                       ret = -ENOMEM;
-                       goto err_map;
-               }
-       }
+       ret = regmap_set_name(map, config);
+       if (ret)
+               goto err_map;
 
        if (config->disable_locking) {
                map->lock = map->unlock = regmap_lock_unlock_none;
@@ -1137,7 +1153,7 @@ skip_format_initialization:
                if (ret != 0)
                        goto err_regcache;
        } else {
-               regmap_debugfs_init(map, config->name);
+               regmap_debugfs_init(map);
        }
 
        return map;
@@ -1297,6 +1313,8 @@ EXPORT_SYMBOL_GPL(regmap_field_free);
  */
 int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
 {
+       int ret;
+
        regcache_exit(map);
        regmap_debugfs_exit(map);
 
@@ -1309,7 +1327,11 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
        map->readable_noinc_reg = config->readable_noinc_reg;
        map->cache_type = config->cache_type;
 
-       regmap_debugfs_init(map, config->name);
+       ret = regmap_set_name(map, config);
+       if (ret)
+               return ret;
+
+       regmap_debugfs_init(map);
 
        map->cache_bypass = false;
        map->cache_only = false;
@@ -1464,7 +1486,7 @@ static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,
 }
 
 static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
-                                 const void *val, size_t val_len)
+                                 const void *val, size_t val_len, bool noinc)
 {
        struct regmap_range_node *range;
        unsigned long flags;
@@ -1523,7 +1545,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
                                win_residue, val_len / map->format.val_bytes);
                        ret = _regmap_raw_write_impl(map, reg, val,
                                                     win_residue *
-                                                    map->format.val_bytes);
+                                                    map->format.val_bytes, noinc);
                        if (ret != 0)
                                return ret;
 
@@ -1537,7 +1559,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
                        win_residue = range->window_len - win_offset;
                }
 
-               ret = _regmap_select_page(map, &reg, range, val_num);
+               ret = _regmap_select_page(map, &reg, range, noinc ? 1 : val_num);
                if (ret != 0)
                        return ret;
        }
@@ -1745,7 +1767,8 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
                                      map->work_buf +
                                      map->format.reg_bytes +
                                      map->format.pad_bytes,
-                                     map->format.val_bytes);
+                                     map->format.val_bytes,
+                                     false);
 }
 
 static inline void *_regmap_map_get_context(struct regmap *map)
@@ -1839,7 +1862,7 @@ int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
 EXPORT_SYMBOL_GPL(regmap_write_async);
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
-                     const void *val, size_t val_len)
+                     const void *val, size_t val_len, bool noinc)
 {
        size_t val_bytes = map->format.val_bytes;
        size_t val_count = val_len / val_bytes;
@@ -1860,7 +1883,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 
        /* Write as many bytes as possible with chunk_size */
        for (i = 0; i < chunk_count; i++) {
-               ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes);
+               ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc);
                if (ret)
                        return ret;
 
@@ -1871,7 +1894,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 
        /* Write remaining bytes */
        if (val_len)
-               ret = _regmap_raw_write_impl(map, reg, val, val_len);
+               ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc);
 
        return ret;
 }
@@ -1904,7 +1927,7 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 
        map->lock(map->lock_arg);
 
-       ret = _regmap_raw_write(map, reg, val, val_len);
+       ret = _regmap_raw_write(map, reg, val, val_len, false);
 
        map->unlock(map->lock_arg);
 
@@ -1962,7 +1985,7 @@ int regmap_noinc_write(struct regmap *map, unsigned int reg,
                        write_len = map->max_raw_write;
                else
                        write_len = val_len;
-               ret = _regmap_raw_write(map, reg, val, write_len);
+               ret = _regmap_raw_write(map, reg, val, write_len, true);
                if (ret)
                        goto out_unlock;
                val = ((u8 *)val) + write_len;
@@ -2439,7 +2462,7 @@ int regmap_raw_write_async(struct regmap *map, unsigned int reg,
 
        map->async = true;
 
-       ret = _regmap_raw_write(map, reg, val, val_len);
+       ret = _regmap_raw_write(map, reg, val, val_len, false);
 
        map->async = false;
 
@@ -2450,7 +2473,7 @@ int regmap_raw_write_async(struct regmap *map, unsigned int reg,
 EXPORT_SYMBOL_GPL(regmap_raw_write_async);
 
 static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
-                           unsigned int val_len)
+                           unsigned int val_len, bool noinc)
 {
        struct regmap_range_node *range;
        int ret;
@@ -2463,7 +2486,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
        range = _regmap_range_lookup(map, reg);
        if (range) {
                ret = _regmap_select_page(map, &reg, range,
-                                         val_len / map->format.val_bytes);
+                                         noinc ? 1 : val_len / map->format.val_bytes);
                if (ret != 0)
                        return ret;
        }
@@ -2501,7 +2524,7 @@ static int _regmap_bus_read(void *context, unsigned int reg,
        if (!map->format.parse_val)
                return -EINVAL;
 
-       ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes);
+       ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes, false);
        if (ret == 0)
                *val = map->format.parse_val(work_val);
 
@@ -2617,7 +2640,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 
                /* Read bytes that fit into whole chunks */
                for (i = 0; i < chunk_count; i++) {
-                       ret = _regmap_raw_read(map, reg, val, chunk_bytes);
+                       ret = _regmap_raw_read(map, reg, val, chunk_bytes, false);
                        if (ret != 0)
                                goto out;
 
@@ -2628,7 +2651,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 
                /* Read remaining bytes */
                if (val_len) {
-                       ret = _regmap_raw_read(map, reg, val, val_len);
+                       ret = _regmap_raw_read(map, reg, val, val_len, false);
                        if (ret != 0)
                                goto out;
                }
@@ -2703,7 +2726,7 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
                        read_len = map->max_raw_read;
                else
                        read_len = val_len;
-               ret = _regmap_raw_read(map, reg, val, read_len);
+               ret = _regmap_raw_read(map, reg, val, read_len, true);
                if (ret)
                        goto out_unlock;
                val = ((u8 *)val) + read_len;
index 04b6bde..573dbf6 100644 (file)
@@ -1553,7 +1553,7 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa
         * put_page(); and would cause either a VM_BUG directly, or
         * __page_cache_release a page that would actually still be referenced
         * by someone, leading to some obscure delayed Oops somewhere else. */
-       if (drbd_disable_sendpage || (page_count(page) < 1) || PageSlab(page))
+       if (drbd_disable_sendpage || !sendpage_ok(page))
                return _drbd_no_send_page(peer_device, page, offset, size, msg_flags);
 
        msg_flags |= MSG_NOSIGNAL;
index 0115390..e77eaab 100644 (file)
@@ -5120,6 +5120,9 @@ static ssize_t rbd_config_info_show(struct device *dev,
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        return sprintf(buf, "%s\n", rbd_dev->config_info);
 }
 
@@ -5231,6 +5234,9 @@ static ssize_t rbd_image_refresh(struct device *dev,
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
        int ret;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        ret = rbd_dev_refresh(rbd_dev);
        if (ret)
                return ret;
@@ -7059,6 +7065,9 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        struct rbd_client *rbdc;
        int rc;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        if (!try_module_get(THIS_MODULE))
                return -ENODEV;
 
@@ -7209,6 +7218,9 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
        bool force = false;
        int ret;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        dev_id = -1;
        opt_buf[0] = '\0';
        sscanf(buf, "%d %5s", &dev_id, opt_buf);
index 784f12c..ec738f7 100644 (file)
@@ -5,6 +5,7 @@ config CLK_BCM2711_DVP
        depends on ARCH_BCM2835 ||COMPILE_TEST
        depends on COMMON_CLK
        default ARCH_BCM2835
+       select RESET_CONTROLLER
        select RESET_SIMPLE
        help
          Enable common clock framework support for the Broadcom BCM2711
index 6c35e4b..0d75043 100644 (file)
@@ -491,7 +491,7 @@ struct clk *davinci_pll_clk_register(struct device *dev,
                parent_name = postdiv_name;
        }
 
-       pllen = kzalloc(sizeof(*pllout), GFP_KERNEL);
+       pllen = kzalloc(sizeof(*pllen), GFP_KERNEL);
        if (!pllen) {
                ret = -ENOMEM;
                goto err_unregister_postdiv;
index d4c1864..228d08f 100644 (file)
@@ -420,17 +420,18 @@ static int lpass_core_sc7180_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        ret = pm_clk_create(&pdev->dev);
        if (ret)
-               return ret;
+               goto disable_pm_runtime;
 
        ret = pm_clk_add(&pdev->dev, "iface");
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to acquire iface clock\n");
-               goto disable_pm_runtime;
+               goto destroy_pm_clk;
        }
 
+       ret = -EINVAL;
        clk_probe = of_device_get_match_data(&pdev->dev);
        if (!clk_probe)
-               return -EINVAL;
+               goto destroy_pm_clk;
 
        ret = clk_probe(pdev);
        if (ret)
index d7243c0..47d6482 100644 (file)
@@ -137,7 +137,7 @@ PNAME(mux_usb480m_p)                = { "usb480m_phy", "xin24m" };
 PNAME(mux_hdmiphy_p)           = { "hdmiphy_phy", "xin24m" };
 PNAME(mux_aclk_cpu_src_p)      = { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" };
 
-PNAME(mux_pll_src_4plls_p)     = { "cpll", "gpll", "hdmiphy" "usb480m" };
+PNAME(mux_pll_src_4plls_p)     = { "cpll", "gpll", "hdmiphy", "usb480m" };
 PNAME(mux_pll_src_3plls_p)     = { "cpll", "gpll", "hdmiphy" };
 PNAME(mux_pll_src_2plls_p)     = { "cpll", "gpll" };
 PNAME(mux_sclk_hdmi_cec_p)     = { "cpll", "gpll", "xin24m" };
index 51564fc..f408628 100644 (file)
@@ -927,7 +927,7 @@ static const struct samsung_gate_clock exynos4210_gate_clks[] __initconst = {
        GATE(CLK_PCIE, "pcie", "aclk133", GATE_IP_FSYS, 14, 0, 0),
        GATE(CLK_SMMU_PCIE, "smmu_pcie", "aclk133", GATE_IP_FSYS, 18, 0, 0),
        GATE(CLK_MODEMIF, "modemif", "aclk100", GATE_IP_PERIL, 28, 0, 0),
-       GATE(CLK_CHIPID, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+       GATE(CLK_CHIPID, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SYSREG, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0,
                        CLK_IGNORE_UNUSED, 0),
        GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk100", E4210_GATE_IP_PERIR, 11, 0,
@@ -969,7 +969,7 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
                0),
        GATE(CLK_TSADC, "tsadc", "aclk133", E4X12_GATE_BUS_FSYS1, 16, 0, 0),
        GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
-       GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
+       GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
                        CLK_IGNORE_UNUSED, 0),
        GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk100", E4X12_GATE_IP_PERIR, 11, 0,
index fea3339..bd62087 100644 (file)
@@ -1655,6 +1655,11 @@ static void __init exynos5x_clk_init(struct device_node *np,
         * main G3D clock enablement status.
         */
        clk_prepare_enable(__clk_lookup("mout_sw_aclk_g3d"));
+       /*
+        * Keep top BPLL mux enabled permanently to ensure that DRAM operates
+        * properly.
+        */
+       clk_prepare_enable(__clk_lookup("mout_bpll"));
 
        samsung_clk_of_add_provider(np, ctx);
 }
index c1dfc9b..661a8e9 100644 (file)
@@ -209,7 +209,7 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
        { STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
          0, 0, 2, 0xB0, 1},
        { STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
-         ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
+         ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 2, 0xB0, 2},
        { STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
          ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
        { STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
index f180c05..c5cc0a2 100644 (file)
@@ -1611,9 +1611,6 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        unsigned long flags = 0;
        unsigned long input_rate;
 
-       if (clk_pll_is_enabled(hw))
-               return 0;
-
        input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
        if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
@@ -1673,7 +1670,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        pll_writel(val, PLLE_SS_CTRL, pll);
        udelay(1);
 
-       /* Enable hw control of xusb brick pll */
+       /* Enable HW control of XUSB brick PLL */
        val = pll_readl_misc(pll);
        val &= ~PLLE_MISC_IDDQ_SW_CTRL;
        pll_writel_misc(val, pll);
@@ -1696,7 +1693,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
        pll_writel(val, XUSBIO_PLL_CFG0, pll);
 
-       /* Enable hw control of SATA pll */
+       /* Enable HW control of SATA PLL */
        val = pll_readl(SATA_PLL_CFG0, pll);
        val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
        val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET;
index 352a2c3..51fd0ec 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
+#include "clk.h"
+
 #define CLK_SOURCE_EMC 0x19c
 #define  CLK_SOURCE_EMC_2X_CLK_SRC GENMASK(31, 29)
 #define  CLK_SOURCE_EMC_MC_EMC_SAME_FREQ BIT(16)
index ca79824..85c395d 100644 (file)
@@ -109,8 +109,10 @@ static int integrator_impd1_clk_probe(struct platform_device *pdev)
 
        for_each_available_child_of_node(np, child) {
                ret = integrator_impd1_clk_spawn(dev, np, child);
-               if (ret)
+               if (ret) {
+                       of_node_put(child);
                        break;
+               }
        }
 
        return ret;
index 1d740a8..47114c2 100644 (file)
@@ -169,7 +169,7 @@ static int __init h8300_8timer_init(struct device_node *node)
                return PTR_ERR(clk);
        }
 
-       ret = ENXIO;
+       ret = -ENXIO;
        base = of_iomap(node, 0);
        if (!base) {
                pr_err("failed to map registers for clockevent\n");
index 8eeafa8..6cfe2ab 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
 #include <linux/smp.h>
+#include <linux/timex.h>
+
+#ifndef CONFIG_RISCV_M_MODE
+#include <asm/clint.h>
+#endif
 
 #define CLINT_IPI_OFF          0
 #define CLINT_TIMER_CMP_OFF    0x4000
@@ -31,6 +36,11 @@ static u64 __iomem *clint_timer_val;
 static unsigned long clint_timer_freq;
 static unsigned int clint_timer_irq;
 
+#ifdef CONFIG_RISCV_M_MODE
+u64 __iomem *clint_time_val;
+EXPORT_SYMBOL(clint_time_val);
+#endif
+
 static void clint_send_ipi(const struct cpumask *target)
 {
        unsigned int cpu;
@@ -184,6 +194,14 @@ static int __init clint_timer_init_dt(struct device_node *np)
        clint_timer_val = base + CLINT_TIMER_VAL_OFF;
        clint_timer_freq = riscv_timebase;
 
+#ifdef CONFIG_RISCV_M_MODE
+       /*
+        * Yes, that's an odd naming scheme.  time_val is public, but hopefully
+        * will die in favor of something cleaner.
+        */
+       clint_time_val = clint_timer_val;
+#endif
+
        pr_info("%pOFP: timer running at %ld Hz\n", np, clint_timer_freq);
 
        rc = clocksource_register_hz(&clint_clocksource, clint_timer_freq);
index 80d0939..8d386ad 100644 (file)
@@ -28,6 +28,7 @@ static irqreturn_t gx6605s_timer_interrupt(int irq, void *dev)
        void __iomem *base = timer_of_base(to_timer_of(ce));
 
        writel_relaxed(GX6605S_STATUS_CLR, base + TIMER_STATUS);
+       writel_relaxed(0, base + TIMER_INI);
 
        ce->event_handler(ce);
 
index f6fd1c1..33b3e8a 100644 (file)
@@ -69,12 +69,33 @@ static bool dmtimer_systimer_revision1(struct dmtimer_systimer *t)
        return !(tidr >> 16);
 }
 
+static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
+{
+       u32 val;
+
+       if (dmtimer_systimer_revision1(t))
+               val = DMTIMER_TYPE1_ENABLE;
+       else
+               val = DMTIMER_TYPE2_ENABLE;
+
+       writel_relaxed(val, t->base + t->sysc);
+}
+
+static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
+{
+       if (!dmtimer_systimer_revision1(t))
+               return;
+
+       writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
+}
+
 static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t)
 {
        void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET;
        int ret;
        u32 l;
 
+       dmtimer_systimer_enable(t);
        writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl);
        ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100,
                                        DMTIMER_RESET_WAIT);
@@ -88,6 +109,7 @@ static int __init dmtimer_systimer_type2_reset(struct dmtimer_systimer *t)
        void __iomem *sysc = t->base + t->sysc;
        u32 l;
 
+       dmtimer_systimer_enable(t);
        l = readl_relaxed(sysc);
        l |= BIT(0);
        writel_relaxed(l, sysc);
@@ -336,26 +358,6 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
        return 0;
 }
 
-static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
-{
-       u32 val;
-
-       if (dmtimer_systimer_revision1(t))
-               val = DMTIMER_TYPE1_ENABLE;
-       else
-               val = DMTIMER_TYPE2_ENABLE;
-
-       writel_relaxed(val, t->base + t->sysc);
-}
-
-static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
-{
-       if (!dmtimer_systimer_revision1(t))
-               return;
-
-       writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
-}
-
 static int __init dmtimer_systimer_setup(struct device_node *np,
                                         struct dmtimer_systimer *t)
 {
@@ -409,8 +411,8 @@ static int __init dmtimer_systimer_setup(struct device_node *np,
        t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET;
        t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET;
 
-       dmtimer_systimer_enable(t);
        dmtimer_systimer_reset(t);
+       dmtimer_systimer_enable(t);
        pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base),
                 readl_relaxed(t->base + t->sysc));
 
index f7b7743..b7b252c 100644 (file)
@@ -320,8 +320,8 @@ static int mchp_tc_probe(struct platform_device *pdev)
        }
 
        regmap = syscon_node_to_regmap(np->parent);
-       if (IS_ERR(priv->regmap))
-               return PTR_ERR(priv->regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
 
        /* max. channels number is 2 when in QDEC mode */
        priv->num_channels = of_property_count_u32_elems(np, "reg");
index a827b00..9a515c4 100644 (file)
@@ -2781,6 +2781,7 @@ static int intel_pstate_update_status(const char *buf, size_t size)
 
                cpufreq_unregister_driver(intel_pstate_driver);
                intel_pstate_driver_cleanup();
+               return 0;
        }
 
        if (size == 6 && !strncmp(buf, "active", size)) {
index 7446384..d928b37 100644 (file)
@@ -66,7 +66,7 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
                return -1;
 
        /* Do runtime PM to manage a hierarchical CPU toplogy. */
-       pm_runtime_put_sync_suspend(pd_dev);
+       RCU_NONIDLE(pm_runtime_put_sync_suspend(pd_dev));
 
        state = psci_get_domain_state();
        if (!state)
@@ -74,7 +74,7 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
 
        ret = psci_cpu_suspend_enter(state) ? -1 : idx;
 
-       pm_runtime_get_sync(pd_dev);
+       RCU_NONIDLE(pm_runtime_get_sync(pd_dev));
 
        cpu_pm_exit();
 
index ff6d99e..a2b5c6f 100644 (file)
@@ -361,7 +361,10 @@ static void __init fixup_cede0_latency(void)
        for (i = 0; i < nr_xcede_records; i++) {
                struct xcede_latency_record *record = &payload->records[i];
                u64 latency_tb = be64_to_cpu(record->latency_ticks);
-               u64 latency_us = tb_to_ns(latency_tb) / NSEC_PER_USEC;
+               u64 latency_us = DIV_ROUND_UP_ULL(tb_to_ns(latency_tb), NSEC_PER_USEC);
+
+               if (latency_us == 0)
+                       pr_warn("cpuidle: xcede record %d has an unrealistic latency of 0us.\n", i);
 
                if (latency_us < min_latency_us)
                        min_latency_us = latency_us;
@@ -378,10 +381,14 @@ static void __init fixup_cede0_latency(void)
         * Perform the fix-up.
         */
        if (min_latency_us < dedicated_states[1].exit_latency) {
-               u64 cede0_latency = min_latency_us - 1;
+               /*
+                * We set a minimum of 1us wakeup latency for cede0 to
+                * distinguish it from snooze
+                */
+               u64 cede0_latency = 1;
 
-               if (cede0_latency <= 0)
-                       cede0_latency = min_latency_us;
+               if (min_latency_us > cede0_latency)
+                       cede0_latency = min_latency_us - 1;
 
                dedicated_states[1].exit_latency = cede0_latency;
                dedicated_states[1].target_residency = 10 * (cede0_latency);
index 04becd7..29e8468 100644 (file)
@@ -138,14 +138,10 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv,
                                struct cpuidle_device *dev, int index)
 {
        ktime_t time_start, time_end;
+       struct cpuidle_state *target_state = &drv->states[index];
 
        time_start = ns_to_ktime(local_clock());
 
-       /*
-        * trace_suspend_resume() called by tick_freeze() for the last CPU
-        * executing it contains RCU usage regarded as invalid in the idle
-        * context, so tell RCU about that.
-        */
        tick_freeze();
        /*
         * The state used here cannot be a "coupled" one, because the "coupled"
@@ -153,16 +149,13 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv,
         * suspended is generally unsafe.
         */
        stop_critical_timings();
-       rcu_idle_enter();
-       drv->states[index].enter_s2idle(dev, drv, index);
+       if (!(target_state->flags & CPUIDLE_FLAG_RCU_IDLE))
+               rcu_idle_enter();
+       target_state->enter_s2idle(dev, drv, index);
        if (WARN_ON_ONCE(!irqs_disabled()))
                local_irq_disable();
-       /*
-        * timekeeping_resume() that will be called by tick_unfreeze() for the
-        * first CPU executing it calls functions containing RCU read-side
-        * critical sections, so tell RCU about that.
-        */
-       rcu_idle_exit();
+       if (!(target_state->flags & CPUIDLE_FLAG_RCU_IDLE))
+               rcu_idle_exit();
        tick_unfreeze();
        start_critical_timings();
 
@@ -239,9 +232,11 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
        time_start = ns_to_ktime(local_clock());
 
        stop_critical_timings();
-       rcu_idle_enter();
+       if (!(target_state->flags & CPUIDLE_FLAG_RCU_IDLE))
+               rcu_idle_enter();
        entered_state = target_state->enter(dev, drv, index);
-       rcu_idle_exit();
+       if (!(target_state->flags & CPUIDLE_FLAG_RCU_IDLE))
+               rcu_idle_exit();
        start_critical_timings();
 
        sched_clock_idle_wakeup_event();
index 3264263..e84070b 100644 (file)
@@ -85,6 +85,12 @@ bool __generic_fsdax_supported(struct dax_device *dax_dev,
                return false;
        }
 
+       if (!dax_dev) {
+               pr_debug("%s: error: dax unsupported by block device\n",
+                               bdevname(bdev, buf));
+               return false;
+       }
+
        err = bdev_dax_pgoff(bdev, start, PAGE_SIZE, &pgoff);
        if (err) {
                pr_info("%s: error: unaligned partition for dax\n",
@@ -100,12 +106,6 @@ bool __generic_fsdax_supported(struct dax_device *dax_dev,
                return false;
        }
 
-       if (!dax_dev && !bdev_dax_supported(bdev, blocksize)) {
-               pr_debug("%s: error: dax unsupported by block device\n",
-                               bdevname(bdev, buf));
-               return false;
-       }
-
        id = dax_read_lock();
        len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
        len2 = dax_direct_access(dax_dev, pgoff_end, 1, &end_kaddr, &end_pfn);
@@ -325,11 +325,15 @@ EXPORT_SYMBOL_GPL(dax_direct_access);
 bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
                int blocksize, sector_t start, sector_t len)
 {
+       if (!dax_dev)
+               return false;
+
        if (!dax_alive(dax_dev))
                return false;
 
        return dax_dev->ops->dax_supported(dax_dev, bdev, blocksize, start, len);
 }
+EXPORT_SYMBOL_GPL(dax_supported);
 
 size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
                size_t bytes, struct iov_iter *i)
index 561d91b..071b59f 100644 (file)
@@ -1766,20 +1766,23 @@ static int devfreq_summary_show(struct seq_file *s, void *data)
        struct devfreq *p_devfreq = NULL;
        unsigned long cur_freq, min_freq, max_freq;
        unsigned int polling_ms;
+       unsigned int timer;
 
-       seq_printf(s, "%-30s %-30s %-15s %10s %12s %12s %12s\n",
+       seq_printf(s, "%-30s %-30s %-15s %-10s %10s %12s %12s %12s\n",
                        "dev",
                        "parent_dev",
                        "governor",
+                       "timer",
                        "polling_ms",
                        "cur_freq_Hz",
                        "min_freq_Hz",
                        "max_freq_Hz");
-       seq_printf(s, "%30s %30s %15s %10s %12s %12s %12s\n",
+       seq_printf(s, "%30s %30s %15s %10s %10s %12s %12s %12s\n",
                        "------------------------------",
                        "------------------------------",
                        "---------------",
                        "----------",
+                       "----------",
                        "------------",
                        "------------",
                        "------------");
@@ -1803,13 +1806,15 @@ static int devfreq_summary_show(struct seq_file *s, void *data)
                cur_freq = devfreq->previous_freq;
                get_freq_range(devfreq, &min_freq, &max_freq);
                polling_ms = devfreq->profile->polling_ms;
+               timer = devfreq->profile->timer;
                mutex_unlock(&devfreq->lock);
 
                seq_printf(s,
-                       "%-30s %-30s %-15s %10d %12ld %12ld %12ld\n",
+                       "%-30s %-30s %-15s %-10s %10d %12ld %12ld %12ld\n",
                        dev_name(&devfreq->dev),
                        p_devfreq ? dev_name(&p_devfreq->dev) : "null",
                        devfreq->governor_name,
+                       polling_ms ? timer_name[timer] : "null",
                        polling_ms,
                        cur_freq,
                        min_freq,
index e94a278..dedd39d 100644 (file)
@@ -836,7 +836,8 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
        rate = clk_round_rate(tegra->emc_clock, ULONG_MAX);
        if (rate < 0) {
                dev_err(&pdev->dev, "Failed to round clock rate: %ld\n", rate);
-               return rate;
+               err = rate;
+               goto disable_clk;
        }
 
        tegra->max_freq = rate / KHZ;
@@ -897,6 +898,7 @@ remove_opps:
        dev_pm_opp_remove_all_dynamic(&pdev->dev);
 
        reset_control_reset(tegra->reset);
+disable_clk:
        clk_disable_unprepare(tegra->clock);
 
        return err;
index 1699a8e..844967f 100644 (file)
@@ -59,6 +59,8 @@ static void dma_buf_release(struct dentry *dentry)
        struct dma_buf *dmabuf;
 
        dmabuf = dentry->d_fsdata;
+       if (unlikely(!dmabuf))
+               return;
 
        BUG_ON(dmabuf->vmapping_counter);
 
@@ -316,9 +318,9 @@ out:
  * name of the dma-buf if the same piece of memory is used for multiple
  * purpose between different devices.
  *
- * @dmabuf [in]     dmabuf buffer that will be renamed.
- * @buf:   [in]     A piece of userspace memory that contains the name of
- *                  the dma-buf.
+ * @dmabuf: [in]     dmabuf buffer that will be renamed.
+ * @buf:    [in]     A piece of userspace memory that contains the name of
+ *                   the dma-buf.
  *
  * Returns 0 on success. If the dma-buf buffer is already attached to
  * devices, return -EBUSY.
index 3d12350..7d129e6 100644 (file)
@@ -222,6 +222,7 @@ EXPORT_SYMBOL(dma_fence_chain_ops);
  * @chain: the chain node to initialize
  * @prev: the previous fence
  * @fence: the current fence
+ * @seqno: the sequence number to use for the fence chain
  *
  * Initialize a new chain node and either start a new chain or add the node to
  * the existing chain of the previous fence.
index 45d4d92..a819611 100644 (file)
@@ -129,6 +129,7 @@ struct dmatest_params {
  * @nr_channels:       number of channels under test
  * @lock:              access protection to the fields of this structure
  * @did_init:          module has been initialized completely
+ * @last_error:                test has faced configuration issues
  */
 static struct dmatest_info {
        /* Test parameters */
@@ -137,6 +138,7 @@ static struct dmatest_info {
        /* Internal state */
        struct list_head        channels;
        unsigned int            nr_channels;
+       int                     last_error;
        struct mutex            lock;
        bool                    did_init;
 } test_info = {
@@ -1184,10 +1186,22 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
                return ret;
        } else if (dmatest_run) {
                if (!is_threaded_test_pending(info)) {
-                       pr_info("No channels configured, continue with any\n");
-                       if (!is_threaded_test_run(info))
-                               stop_threaded_test(info);
-                       add_threaded_test(info);
+                       /*
+                        * We have nothing to run. This can be due to:
+                        */
+                       ret = info->last_error;
+                       if (ret) {
+                               /* 1) Misconfiguration */
+                               pr_err("Channel misconfigured, can't continue\n");
+                               mutex_unlock(&info->lock);
+                               return ret;
+                       } else {
+                               /* 2) We rely on defaults */
+                               pr_info("No channels configured, continue with any\n");
+                               if (!is_threaded_test_run(info))
+                                       stop_threaded_test(info);
+                               add_threaded_test(info);
+                       }
                }
                start_threaded_tests(info);
        } else {
@@ -1204,7 +1218,7 @@ static int dmatest_chan_set(const char *val, const struct kernel_param *kp)
        struct dmatest_info *info = &test_info;
        struct dmatest_chan *dtc;
        char chan_reset_val[20];
-       int ret = 0;
+       int ret;
 
        mutex_lock(&info->lock);
        ret = param_set_copystring(val, kp);
@@ -1259,12 +1273,14 @@ static int dmatest_chan_set(const char *val, const struct kernel_param *kp)
                goto add_chan_err;
        }
 
+       info->last_error = ret;
        mutex_unlock(&info->lock);
 
        return ret;
 
 add_chan_err:
        param_set_copystring(chan_reset_val, kp);
+       info->last_error = ret;
        mutex_unlock(&info->lock);
 
        return ret;
index 54ebc8a..94d1e31 100644 (file)
@@ -508,6 +508,7 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
                if (!force_load && idx < 0)
                        return -ENODEV;
        } else {
+               force_load = true;
                idx = 0;
        }
 
@@ -629,9 +630,13 @@ void ghes_edac_unregister(struct ghes *ghes)
        struct mem_ctl_info *mci;
        unsigned long flags;
 
+       if (!force_load)
+               return;
+
        mutex_lock(&ghes_reg_mutex);
 
        system_scanned = false;
+       memset(&ghes_hw, 0, sizeof(struct ghes_hw_desc));
 
        if (!refcount_dec_and_test(&ghes_refcount))
                goto unlock;
index 35dccc8..15a4753 100644 (file)
@@ -84,7 +84,7 @@ static int __init efibc_init(void)
 {
        int ret;
 
-       if (!efi_enabled(EFI_RUNTIME_SERVICES))
+       if (!efivars_kobject() || !efivar_supports_writes())
                return -ENODEV;
 
        ret = register_reboot_notifier(&efibc_reboot_notifier);
index e97a9c9..21ae0c4 100644 (file)
@@ -16,9 +16,9 @@
 
 /* Exported for use by lib/test_firmware.c only */
 LIST_HEAD(efi_embedded_fw_list);
-EXPORT_SYMBOL_GPL(efi_embedded_fw_list);
-
-static bool checked_for_fw;
+EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_list, TEST_FIRMWARE);
+bool efi_embedded_fw_checked;
+EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_checked, TEST_FIRMWARE);
 
 static const struct dmi_system_id * const embedded_fw_table[] = {
 #ifdef CONFIG_TOUCHSCREEN_DMI
@@ -116,14 +116,14 @@ void __init efi_check_for_embedded_firmwares(void)
                }
        }
 
-       checked_for_fw = true;
+       efi_embedded_fw_checked = true;
 }
 
 int efi_get_embedded_fw(const char *name, const u8 **data, size_t *size)
 {
        struct efi_embedded_fw *iter, *fw = NULL;
 
-       if (!checked_for_fw) {
+       if (!efi_embedded_fw_checked) {
                pr_warn("Warning %s called while we did not check for embedded fw\n",
                        __func__);
                return -ENOENT;
index 4e44ba4..2a21354 100644 (file)
@@ -92,7 +92,7 @@ static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
        ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       return ret ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
+       return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
 }
 
 static void amd_fch_gpio_set(struct gpio_chip *gc,
index 3aa4593..64e54f8 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
-#define MAX_NR_SGPIO                   80
+/*
+ * MAX_NR_HW_GPIO represents the number of actual hardware-supported GPIOs (ie,
+ * slots within the clocked serial GPIO data). Since each HW GPIO is both an
+ * input and an output, we provide MAX_NR_HW_GPIO * 2 lines on our gpiochip
+ * device.
+ *
+ * We use SGPIO_OUTPUT_OFFSET to define the split between the inputs and
+ * outputs; the inputs start at line 0, the outputs start at OUTPUT_OFFSET.
+ */
+#define MAX_NR_HW_SGPIO                        80
+#define SGPIO_OUTPUT_OFFSET            MAX_NR_HW_SGPIO
 
 #define ASPEED_SGPIO_CTRL              0x54
 
@@ -30,8 +40,8 @@ struct aspeed_sgpio {
        struct clk *pclk;
        spinlock_t lock;
        void __iomem *base;
-       uint32_t dir_in[3];
        int irq;
+       int n_sgpio;
 };
 
 struct aspeed_sgpio_bank {
@@ -111,31 +121,69 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
        }
 }
 
-#define GPIO_BANK(x)    ((x) >> 5)
-#define GPIO_OFFSET(x)  ((x) & 0x1f)
+#define GPIO_BANK(x)    ((x % SGPIO_OUTPUT_OFFSET) >> 5)
+#define GPIO_OFFSET(x)  ((x % SGPIO_OUTPUT_OFFSET) & 0x1f)
 #define GPIO_BIT(x)     BIT(GPIO_OFFSET(x))
 
 static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
 {
-       unsigned int bank = GPIO_BANK(offset);
+       unsigned int bank;
+
+       bank = GPIO_BANK(offset);
 
        WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
        return &aspeed_sgpio_banks[bank];
 }
 
+static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
+               unsigned long *valid_mask, unsigned int ngpios)
+{
+       struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
+       int n = sgpio->n_sgpio;
+       int c = SGPIO_OUTPUT_OFFSET - n;
+
+       WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
+
+       /* input GPIOs in the lower range */
+       bitmap_set(valid_mask, 0, n);
+       bitmap_clear(valid_mask, n, c);
+
+       /* output GPIOS above SGPIO_OUTPUT_OFFSET */
+       bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n);
+       bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c);
+
+       return 0;
+}
+
+static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
+               unsigned long *valid_mask, unsigned int ngpios)
+{
+       struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
+       int n = sgpio->n_sgpio;
+
+       WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
+
+       /* input GPIOs in the lower range */
+       bitmap_set(valid_mask, 0, n);
+       bitmap_clear(valid_mask, n, ngpios - n);
+}
+
+static bool aspeed_sgpio_is_input(unsigned int offset)
+{
+       return offset < SGPIO_OUTPUT_OFFSET;
+}
+
 static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
 {
        struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
        const struct aspeed_sgpio_bank *bank = to_bank(offset);
        unsigned long flags;
        enum aspeed_sgpio_reg reg;
-       bool is_input;
        int rc = 0;
 
        spin_lock_irqsave(&gpio->lock, flags);
 
-       is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
-       reg = is_input ? reg_val : reg_rdata;
+       reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
        rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
 
        spin_unlock_irqrestore(&gpio->lock, flags);
@@ -143,22 +191,31 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
        return rc;
 }
 
-static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
+static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
 {
        struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
        const struct aspeed_sgpio_bank *bank = to_bank(offset);
-       void __iomem *addr;
+       void __iomem *addr_r, *addr_w;
        u32 reg = 0;
 
-       addr = bank_reg(gpio, bank, reg_val);
-       reg = ioread32(addr);
+       if (aspeed_sgpio_is_input(offset))
+               return -EINVAL;
+
+       /* Since this is an output, read the cached value from rdata, then
+        * update val. */
+       addr_r = bank_reg(gpio, bank, reg_rdata);
+       addr_w = bank_reg(gpio, bank, reg_val);
+
+       reg = ioread32(addr_r);
 
        if (val)
                reg |= GPIO_BIT(offset);
        else
                reg &= ~GPIO_BIT(offset);
 
-       iowrite32(reg, addr);
+       iowrite32(reg, addr_w);
+
+       return 0;
 }
 
 static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
@@ -175,43 +232,28 @@ static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
 
 static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
 {
-       struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-       unsigned long flags;
-
-       spin_lock_irqsave(&gpio->lock, flags);
-       gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset);
-       spin_unlock_irqrestore(&gpio->lock, flags);
-
-       return 0;
+       return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
 }
 
 static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
 {
        struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
        unsigned long flags;
+       int rc;
 
-       spin_lock_irqsave(&gpio->lock, flags);
-
-       gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
-       sgpio_set_value(gc, offset, val);
+       /* No special action is required for setting the direction; we'll
+        * error-out in sgpio_set_value if this isn't an output GPIO */
 
+       spin_lock_irqsave(&gpio->lock, flags);
+       rc = sgpio_set_value(gc, offset, val);
        spin_unlock_irqrestore(&gpio->lock, flags);
 
-       return 0;
+       return rc;
 }
 
 static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
-       int dir_status;
-       struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-       unsigned long flags;
-
-       spin_lock_irqsave(&gpio->lock, flags);
-       dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
-       spin_unlock_irqrestore(&gpio->lock, flags);
-
-       return dir_status;
-
+       return !!aspeed_sgpio_is_input(offset);
 }
 
 static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
@@ -402,6 +444,7 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
 
        irq = &gpio->chip.irq;
        irq->chip = &aspeed_sgpio_irqchip;
+       irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
        irq->handler = handle_bad_irq;
        irq->default_type = IRQ_TYPE_NONE;
        irq->parent_handler = aspeed_sgpio_irq_handler;
@@ -409,17 +452,15 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
        irq->parents = &gpio->irq;
        irq->num_parents = 1;
 
-       /* set IRQ settings and Enable Interrupt */
+       /* Apply default IRQ settings */
        for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
                bank = &aspeed_sgpio_banks[i];
                /* set falling or level-low irq */
                iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0));
                /* trigger type is edge */
                iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
-               /* dual edge trigger mode. */
-               iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2));
-               /* enable irq */
-               iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable));
+               /* single edge trigger */
+               iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));
        }
 
        return 0;
@@ -452,11 +493,12 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
        if (rc < 0) {
                dev_err(&pdev->dev, "Could not read ngpios property\n");
                return -EINVAL;
-       } else if (nr_gpios > MAX_NR_SGPIO) {
+       } else if (nr_gpios > MAX_NR_HW_SGPIO) {
                dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
-                       MAX_NR_SGPIO, nr_gpios);
+                       MAX_NR_HW_SGPIO, nr_gpios);
                return -EINVAL;
        }
+       gpio->n_sgpio = nr_gpios;
 
        rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
        if (rc < 0) {
@@ -497,7 +539,8 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
        spin_lock_init(&gpio->lock);
 
        gpio->chip.parent = &pdev->dev;
-       gpio->chip.ngpio = nr_gpios;
+       gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2;
+       gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
        gpio->chip.direction_input = aspeed_sgpio_dir_in;
        gpio->chip.direction_output = aspeed_sgpio_dir_out;
        gpio->chip.get_direction = aspeed_sgpio_get_direction;
@@ -509,9 +552,6 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
        gpio->chip.label = dev_name(&pdev->dev);
        gpio->chip.base = -1;
 
-       /* set all SGPIO pins as input (1). */
-       memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in));
-
        aspeed_sgpio_setup_irqs(gpio, pdev);
 
        rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
index bf08b45..e44d5de 100644 (file)
@@ -1114,8 +1114,8 @@ static const struct aspeed_gpio_config ast2500_config =
 
 static const struct aspeed_bank_props ast2600_bank_props[] = {
        /*     input      output   */
-       {5, 0xffffffff,  0x0000ffff}, /* U/V/W/X */
-       {6, 0xffff0000,  0x0fff0000}, /* Y/Z */
+       {5, 0xffffffff,  0xffffff00}, /* U/V/W/X */
+       {6, 0x0000ffff,  0x0000ffff}, /* Y/Z */
        { },
 };
 
index bc34518..1652897 100644 (file)
@@ -552,6 +552,7 @@ static int __init gpio_mockup_init(void)
        err = platform_driver_register(&gpio_mockup_driver);
        if (err) {
                gpio_mockup_err("error registering platform driver\n");
+               debugfs_remove_recursive(gpio_mockup_dbg_dir);
                return err;
        }
 
@@ -582,6 +583,7 @@ static int __init gpio_mockup_init(void)
                        gpio_mockup_err("error registering device");
                        platform_driver_unregister(&gpio_mockup_driver);
                        gpio_mockup_unregister_pdevs();
+                       debugfs_remove_recursive(gpio_mockup_dbg_dir);
                        return PTR_ERR(pdev);
                }
 
index 7fbe0c9..0ea640f 100644 (file)
@@ -1516,7 +1516,7 @@ static int __maybe_unused omap_gpio_runtime_resume(struct device *dev)
        return 0;
 }
 
-static int omap_gpio_suspend(struct device *dev)
+static int __maybe_unused omap_gpio_suspend(struct device *dev)
 {
        struct gpio_bank *bank = dev_get_drvdata(dev);
 
@@ -1528,7 +1528,7 @@ static int omap_gpio_suspend(struct device *dev)
        return omap_gpio_runtime_suspend(dev);
 }
 
-static int omap_gpio_resume(struct device *dev)
+static int __maybe_unused omap_gpio_resume(struct device *dev)
 {
        struct gpio_bank *bank = dev_get_drvdata(dev);
 
index bd2e96c..fb61f2f 100644 (file)
@@ -818,6 +818,8 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
        int level;
        bool ret;
 
+       bitmap_zero(pending, MAX_LINE);
+
        mutex_lock(&chip->i2c_lock);
        ret = pca953x_irq_pending(chip, pending);
        mutex_unlock(&chip->i2c_lock);
@@ -940,6 +942,7 @@ out:
 static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
 {
        DECLARE_BITMAP(val, MAX_LINE);
+       unsigned int i;
        int ret;
 
        ret = device_pca95xx_init(chip, invert);
@@ -947,7 +950,9 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
                goto out;
 
        /* To enable register 6, 7 to control pull up and pull down */
-       memset(val, 0x02, NBANK(chip));
+       for (i = 0; i < NBANK(chip); i++)
+               bitmap_set_value8(val, 0x02, i * BANK_SZ);
+
        ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
        if (ret)
                goto out;
index 26e1fe0..f8c5e9f 100644 (file)
@@ -245,6 +245,7 @@ static int gpio_siox_probe(struct siox_device *sdevice)
        girq->chip = &ddata->ichip;
        girq->default_type = IRQ_TYPE_NONE;
        girq->handler = handle_level_irq;
+       girq->threaded = true;
 
        ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
        if (ret)
index d7314d3..36ea8a3 100644 (file)
@@ -149,17 +149,20 @@ static int sprd_gpio_irq_set_type(struct irq_data *data,
                sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
                sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
                sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1);
+               sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
                irq_set_handler_locked(data, handle_edge_irq);
                break;
        case IRQ_TYPE_EDGE_FALLING:
                sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
                sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
                sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0);
+               sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
                irq_set_handler_locked(data, handle_edge_irq);
                break;
        case IRQ_TYPE_EDGE_BOTH:
                sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
                sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 1);
+               sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
                irq_set_handler_locked(data, handle_edge_irq);
                break;
        case IRQ_TYPE_LEVEL_HIGH:
index 58b0da9..ea3f68a 100644 (file)
@@ -212,7 +212,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
                                continue;
 
                        tc3589x_gpio->oldregs[i][j] = new;
-                       tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
+                       tc3589x_reg_write(tc3589x, regmap[i] + j, new);
                }
        }
 
index e6c9b78..76c36b0 100644 (file)
@@ -423,6 +423,21 @@ static __poll_t lineevent_poll(struct file *file,
        return events;
 }
 
+static ssize_t lineevent_get_size(void)
+{
+#ifdef __x86_64__
+       /* i386 has no padding after 'id' */
+       if (in_ia32_syscall()) {
+               struct compat_gpioeevent_data {
+                       compat_u64      timestamp;
+                       u32             id;
+               };
+
+               return sizeof(struct compat_gpioeevent_data);
+       }
+#endif
+       return sizeof(struct gpioevent_data);
+}
 
 static ssize_t lineevent_read(struct file *file,
                              char __user *buf,
@@ -432,9 +447,20 @@ static ssize_t lineevent_read(struct file *file,
        struct lineevent_state *le = file->private_data;
        struct gpioevent_data ge;
        ssize_t bytes_read = 0;
+       ssize_t ge_size;
        int ret;
 
-       if (count < sizeof(ge))
+       /*
+        * When compatible system call is being used the struct gpioevent_data,
+        * in case of at least ia32, has different size due to the alignment
+        * differences. Because we have first member 64 bits followed by one of
+        * 32 bits there is no gap between them. The only difference is the
+        * padding at the end of the data structure. Hence, we calculate the
+        * actual sizeof() and pass this as an argument to copy_to_user() to
+        * drop unneeded bytes from the output.
+        */
+       ge_size = lineevent_get_size();
+       if (count < ge_size)
                return -EINVAL;
 
        do {
@@ -470,10 +496,10 @@ static ssize_t lineevent_read(struct file *file,
                        break;
                }
 
-               if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
+               if (copy_to_user(buf + bytes_read, &ge, ge_size))
                        return -EFAULT;
-               bytes_read += sizeof(ge);
-       } while (count >= bytes_read + sizeof(ge));
+               bytes_read += ge_size;
+       } while (count >= bytes_read + ge_size);
 
        return bytes_read;
 }
index eb7cfe8..d0b8d0d 100644 (file)
@@ -80,8 +80,6 @@ MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
-MODULE_FIRMWARE("amdgpu/sienna_cichlid_gpu_info.bin");
-MODULE_FIRMWARE("amdgpu/navy_flounder_gpu_info.bin");
 
 #define AMDGPU_RESUME_MS               2000
 
@@ -1600,6 +1598,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
        case CHIP_CARRIZO:
        case CHIP_STONEY:
        case CHIP_VEGA20:
+       case CHIP_SIENNA_CICHLID:
+       case CHIP_NAVY_FLOUNDER:
        default:
                return 0;
        case CHIP_VEGA10:
@@ -1631,12 +1631,6 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
        case CHIP_NAVI12:
                chip_name = "navi12";
                break;
-       case CHIP_SIENNA_CICHLID:
-               chip_name = "sienna_cichlid";
-               break;
-       case CHIP_NAVY_FLOUNDER:
-               chip_name = "navy_flounder";
-               break;
        }
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
index d761729..44c1f6e 100644 (file)
@@ -297,7 +297,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set,
           take the current one */
        if (active && !adev->have_disp_power_ref) {
                adev->have_disp_power_ref = true;
-               goto out;
+               return ret;
        }
        /* if we have no active crtcs, then drop the power ref
           we got before */
index 26127c7..321032d 100644 (file)
@@ -1044,8 +1044,16 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x1636, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU},
 
        /* Navi12 */
-       {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
-       {0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12},
+       {0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12},
+
+       /* Sienna_Cichlid */
+       {0x1002, 0x73A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
+       {0x1002, 0x73A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
+       {0x1002, 0x73A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
+       {0x1002, 0x73AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
+       {0x1002, 0x73AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
+       {0x1002, 0x73BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
 
        {0, 0, 0}
 };
index d8c6520..0675768 100644 (file)
@@ -178,7 +178,7 @@ static int psp_sw_init(void *handle)
                return ret;
        }
 
-       if (adev->asic_type == CHIP_NAVI10) {
+       if (adev->asic_type == CHIP_NAVI10 || adev->asic_type == CHIP_SIENNA_CICHLID) {
                ret= psp_sysfs_init(adev);
                if (ret) {
                        return ret;
index e11c5d6..978bae7 100644 (file)
@@ -1076,6 +1076,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
 
 release_sg:
        kfree(ttm->sg);
+       ttm->sg = NULL;
        return r;
 }
 
index 037a187..f73ce97 100644 (file)
@@ -3595,6 +3595,9 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)
                if (!gfx_v10_0_navi10_gfxoff_should_enable(adev))
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
                break;
+       case CHIP_NAVY_FLOUNDER:
+               adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
+               break;
        default:
                break;
        }
index e16874f..6c5d961 100644 (file)
@@ -58,7 +58,7 @@ MODULE_FIRMWARE("amdgpu/arcturus_ta.bin");
 MODULE_FIRMWARE("amdgpu/sienna_cichlid_sos.bin");
 MODULE_FIRMWARE("amdgpu/sienna_cichlid_ta.bin");
 MODULE_FIRMWARE("amdgpu/navy_flounder_sos.bin");
-MODULE_FIRMWARE("amdgpu/navy_flounder_asd.bin");
+MODULE_FIRMWARE("amdgpu/navy_flounder_ta.bin");
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS          0x3010024
index 84d811b..c28ebf4 100644 (file)
@@ -694,12 +694,12 @@ static void soc15_reg_base_init(struct amdgpu_device *adev)
                 * it doesn't support SRIOV. */
                if (amdgpu_discovery) {
                        r = amdgpu_discovery_reg_base_init(adev);
-                       if (r) {
-                               DRM_WARN("failed to init reg base from ip discovery table, "
-                                        "fallback to legacy init method\n");
-                               vega10_reg_base_init(adev);
-                       }
+                       if (r == 0)
+                               break;
+                       DRM_WARN("failed to init reg base from ip discovery table, "
+                                "fallback to legacy init method\n");
                }
+               vega10_reg_base_init(adev);
                break;
        case CHIP_VEGA20:
                vega20_reg_base_init(adev);
index 63e5547..3a805ea 100644 (file)
@@ -746,18 +746,18 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
                | UVD_SUVD_CGC_GATE__IME_HEVC_MASK
                | UVD_SUVD_CGC_GATE__EFC_MASK
                | UVD_SUVD_CGC_GATE__SAOE_MASK
-               | 0x08000000
+               | UVD_SUVD_CGC_GATE__SRE_AV1_MASK
                | UVD_SUVD_CGC_GATE__FBC_PCLK_MASK
                | UVD_SUVD_CGC_GATE__FBC_CCLK_MASK
-               | 0x40000000
+               | UVD_SUVD_CGC_GATE__SCM_AV1_MASK
                | UVD_SUVD_CGC_GATE__SMPA_MASK);
        WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE, data);
 
        data = RREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE2);
        data |= (UVD_SUVD_CGC_GATE2__MPBE0_MASK
                | UVD_SUVD_CGC_GATE2__MPBE1_MASK
-               | 0x00000004
-               | 0x00000008
+               | UVD_SUVD_CGC_GATE2__SIT_AV1_MASK
+               | UVD_SUVD_CGC_GATE2__SDB_AV1_MASK
                | UVD_SUVD_CGC_GATE2__MPC1_MASK);
        WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE2, data);
 
@@ -776,8 +776,8 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
                | UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK
                | UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK
                | UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK
-               | 0x00008000
-               | 0x00010000
+               | UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK
                | UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK
                | UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK
                | UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK);
@@ -892,8 +892,8 @@ static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
                | UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK
                | UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK
                | UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK
-               | 0x00008000
-               | 0x00010000
+               | UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK
                | UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK
                | UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK
                | UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK);
index e0e60b0..0f4508b 100644 (file)
@@ -1216,6 +1216,8 @@ static int stop_cpsch(struct device_queue_manager *dqm)
        dqm->sched_running = false;
        dqm_unlock(dqm);
 
+       pm_release_ib(&dqm->packets);
+
        kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
        pm_uninit(&dqm->packets, hanging);
 
@@ -1326,7 +1328,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
        if (q->properties.is_active) {
                increment_queue_count(dqm, q->properties.type);
 
-               retval = execute_queues_cpsch(dqm,
+               execute_queues_cpsch(dqm,
                                KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
        }
 
index b51c527..a717a49 100644 (file)
@@ -1409,7 +1409,7 @@ static int dm_late_init(void *handle)
        if (dmcu)
                ret = dmcu_load_iram(dmcu, params);
        else if (adev->dm.dc->ctx->dmub_srv)
-               ret = dmub_init_abm_config(adev->dm.dc->res_pool->abm, params);
+               ret = dmub_init_abm_config(adev->dm.dc->res_pool, params);
 
        if (!ret)
                return -EINVAL;
@@ -5278,19 +5278,6 @@ static void dm_crtc_helper_disable(struct drm_crtc *crtc)
 {
 }
 
-static bool does_crtc_have_active_cursor(struct drm_crtc_state *new_crtc_state)
-{
-       struct drm_device *dev = new_crtc_state->crtc->dev;
-       struct drm_plane *plane;
-
-       drm_for_each_plane_mask(plane, dev, new_crtc_state->plane_mask) {
-               if (plane->type == DRM_PLANE_TYPE_CURSOR)
-                       return true;
-       }
-
-       return false;
-}
-
 static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
 {
        struct drm_atomic_state *state = new_crtc_state->state;
@@ -5354,19 +5341,20 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
                return ret;
        }
 
-       /* In some use cases, like reset, no stream is attached */
-       if (!dm_crtc_state->stream)
-               return 0;
-
        /*
-        * We want at least one hardware plane enabled to use
-        * the stream with a cursor enabled.
+        * We require the primary plane to be enabled whenever the CRTC is, otherwise
+        * drm_mode_cursor_universal may end up trying to enable the cursor plane while all other
+        * planes are disabled, which is not supported by the hardware. And there is legacy
+        * userspace which stops using the HW cursor altogether in response to the resulting EINVAL.
         */
-       if (state->enable && state->active &&
-           does_crtc_have_active_cursor(state) &&
-           dm_crtc_state->active_planes == 0)
+       if (state->enable &&
+           !(state->plane_mask & drm_plane_mask(crtc->primary)))
                return -EINVAL;
 
+       /* In some use cases, like reset, no stream is attached */
+       if (!dm_crtc_state->stream)
+               return 0;
+
        if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK)
                return 0;
 
index 694c5bc..c2cd184 100644 (file)
@@ -604,7 +604,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
        int i = 0;
 
        hdcp_work = kcalloc(max_caps, sizeof(*hdcp_work), GFP_KERNEL);
-       if (hdcp_work == NULL)
+       if (ZERO_OR_NULL_PTR(hdcp_work))
                return NULL;
 
        hdcp_work->srm = kcalloc(PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, sizeof(*hdcp_work->srm), GFP_KERNEL);
index 543afa3..21a3073 100644 (file)
@@ -783,7 +783,6 @@ void rn_clk_mgr_construct(
        } else {
                struct clk_log_info log_info = {0};
 
-               clk_mgr->smu_ver = rn_vbios_smu_get_smu_version(clk_mgr);
                clk_mgr->periodic_retraining_disabled = rn_vbios_smu_is_periodic_retraining_disabled(clk_mgr);
 
                /* SMU Version 55.51.0 and up no longer have an issue
index 9140b3f..f31f48d 100644 (file)
@@ -409,8 +409,8 @@ static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = {
                        },
                },
        .num_states = 5,
-       .sr_exit_time_us = 8.6,
-       .sr_enter_plus_exit_time_us = 10.9,
+       .sr_exit_time_us = 11.6,
+       .sr_enter_plus_exit_time_us = 13.9,
        .urgent_latency_us = 4.0,
        .urgent_latency_pixel_data_only_us = 4.0,
        .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
index 025637a..bd2a068 100644 (file)
@@ -31,9 +31,21 @@ DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \
        dcn30_dio_link_encoder.o dcn30_resource.o
 
 
-CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse -mpreferred-stack-boundary=4
-
+ifdef CONFIG_X86
 CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -msse
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse
+endif
+
+ifdef CONFIG_PPC64
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -maltivec
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -maltivec
+endif
+
+ifdef CONFIG_ARM64
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mgeneral-regs-only
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mgeneral-regs-only
+endif
+
 ifdef CONFIG_CC_IS_GCC
 ifeq ($(call cc-ifversion, -lt, 0701, y), y)
 IS_OLD_GCC = 1
@@ -45,8 +57,10 @@ ifdef IS_OLD_GCC
 # GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
 # (8B stack alignment).
 CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mpreferred-stack-boundary=4
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mpreferred-stack-boundary=4
 else
 CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -msse2
+CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -msse2
 endif
 
 AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30))
index d3192b9..47f8ee2 100644 (file)
@@ -27,7 +27,7 @@
 #define MOD_HDCP_LOG_H_
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-#define HDCP_LOG_ERR(hdcp, ...) DRM_WARN(__VA_ARGS__)
+#define HDCP_LOG_ERR(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)
 #define HDCP_LOG_VER(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)
 #define HDCP_LOG_FSM(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__)
 #define HDCP_LOG_TOP(hdcp, ...) pr_debug("[HDCP_TOP]:"__VA_ARGS__)
index fb1161d..3a367a5 100644 (file)
@@ -88,7 +88,7 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp,
        enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
 
        if (!psp->dtm_context.dtm_initialized) {
-               DRM_ERROR("Failed to add display topology, DTM TA is not initialized.");
+               DRM_INFO("Failed to add display topology, DTM TA is not initialized.");
                display->state = MOD_HDCP_DISPLAY_INACTIVE;
                return MOD_HDCP_STATUS_FAILURE;
        }
index 8597247..6149795 100644 (file)
@@ -657,7 +657,7 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame
                        params, ram_table, big_endian);
 }
 
-bool dmub_init_abm_config(struct abm *abm,
+bool dmub_init_abm_config(struct resource_pool *res_pool,
        struct dmcu_iram_parameters params)
 {
        struct iram_table_v_2_2 ram_table;
@@ -665,8 +665,13 @@ bool dmub_init_abm_config(struct abm *abm,
        bool result = false;
        uint32_t i, j = 0;
 
-       if (abm == NULL)
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+       if (res_pool->abm == NULL && res_pool->multiple_abms[0] == NULL)
                return false;
+#else
+       if (res_pool->abm == NULL)
+               return false;
+#endif
 
        memset(&ram_table, 0, sizeof(ram_table));
        memset(&config, 0, sizeof(config));
@@ -707,8 +712,14 @@ bool dmub_init_abm_config(struct abm *abm,
 
        config.min_abm_backlight = ram_table.min_abm_backlight;
 
-       result = abm->funcs->init_abm_config(
-               abm, (char *)(&config), sizeof(struct abm_config_table));
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+       if (res_pool->multiple_abms[0]) {
+               result = res_pool->multiple_abms[0]->funcs->init_abm_config(
+                       res_pool->multiple_abms[0], (char *)(&config), sizeof(struct abm_config_table));
+       } else
+#endif
+               result = res_pool->abm->funcs->init_abm_config(
+                       res_pool->abm, (char *)(&config), sizeof(struct abm_config_table));
 
        return result;
 }
index 46fbca2..fa4728d 100644 (file)
@@ -28,6 +28,8 @@
 #include "dc/inc/hw/dmcu.h"
 #include "dc/inc/hw/abm.h"
 
+struct resource_pool;
+
 
 enum abm_defines {
        abm_defines_max_level = 4,
@@ -45,7 +47,7 @@ struct dmcu_iram_parameters {
 
 bool dmcu_load_iram(struct dmcu *dmcu,
                struct dmcu_iram_parameters params);
-bool dmub_init_abm_config(struct abm *abm,
+bool dmub_init_abm_config(struct resource_pool *res_pool,
                struct dmcu_iram_parameters params);
 
 #endif /* MODULES_POWER_POWER_HELPERS_H_ */
index 1116779..e245e91 100644 (file)
 #define mmDB_STENCIL_WRITE_BASE_DEFAULT                                          0x00000000
 #define mmDB_RESERVED_REG_1_DEFAULT                                              0x00000000
 #define mmDB_RESERVED_REG_3_DEFAULT                                              0x00000000
+#define mmDB_VRS_OVERRIDE_CNTL_DEFAULT                                           0x00000000
 #define mmDB_Z_READ_BASE_HI_DEFAULT                                              0x00000000
 #define mmDB_STENCIL_READ_BASE_HI_DEFAULT                                        0x00000000
 #define mmDB_Z_WRITE_BASE_HI_DEFAULT                                             0x00000000
 #define mmPA_SU_OVER_RASTERIZATION_CNTL_DEFAULT                                  0x00000000
 #define mmPA_STEREO_CNTL_DEFAULT                                                 0x00000000
 #define mmPA_STATE_STEREO_X_DEFAULT                                              0x00000000
+#define mmPA_CL_VRS_CNTL_DEFAULT                                                 0x00000000
 #define mmPA_SU_POINT_SIZE_DEFAULT                                               0x00000000
 #define mmPA_SU_POINT_MINMAX_DEFAULT                                             0x00000000
 #define mmPA_SU_LINE_CNTL_DEFAULT                                                0x00000000
index 05d1b0a..644a9fa 100644 (file)
 #define mmDB_RESERVED_REG_1_BASE_IDX                                                                   1
 #define mmDB_RESERVED_REG_3                                                                            0x0017
 #define mmDB_RESERVED_REG_3_BASE_IDX                                                                   1
+#define mmDB_VRS_OVERRIDE_CNTL                                                                         0x0019
+#define mmDB_VRS_OVERRIDE_CNTL_BASE_IDX                                                                1
 #define mmDB_Z_READ_BASE_HI                                                                            0x001a
 #define mmDB_Z_READ_BASE_HI_BASE_IDX                                                                   1
 #define mmDB_STENCIL_READ_BASE_HI                                                                      0x001b
 #define mmPA_STEREO_CNTL_BASE_IDX                                                                      1
 #define mmPA_STATE_STEREO_X                                                                            0x0211
 #define mmPA_STATE_STEREO_X_BASE_IDX                                                                   1
+#define mmPA_CL_VRS_CNTL                                                                               0x0212
+#define mmPA_CL_VRS_CNTL_BASE_IDX                                                                      1
 #define mmPA_SU_POINT_SIZE                                                                             0x0280
 #define mmPA_SU_POINT_SIZE_BASE_IDX                                                                    1
 #define mmPA_SU_POINT_MINMAX                                                                           0x0281
index aac57f7..2e449fc 100644 (file)
 #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_HTILE__SHIFT                                                         0x3
 #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_QUAD__SHIFT                                                          0x4
 #define DB_EXCEPTION_CONTROL__FORCE_SUMMARIZE__SHIFT                                                          0x8
+#define DB_EXCEPTION_CONTROL__FORCE_VRS_RATE_FINE__SHIFT                                                      0x10
 #define DB_EXCEPTION_CONTROL__DTAG_WATERMARK__SHIFT                                                           0x18
 #define DB_EXCEPTION_CONTROL__EARLY_Z_PANIC_DISABLE_MASK                                                      0x00000001L
 #define DB_EXCEPTION_CONTROL__LATE_Z_PANIC_DISABLE_MASK                                                       0x00000002L
 #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_HTILE_MASK                                                           0x00000008L
 #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_QUAD_MASK                                                            0x00000010L
 #define DB_EXCEPTION_CONTROL__FORCE_SUMMARIZE_MASK                                                            0x00000F00L
+#define DB_EXCEPTION_CONTROL__FORCE_VRS_RATE_FINE_MASK                                                        0x00FF0000L
 #define DB_EXCEPTION_CONTROL__DTAG_WATERMARK_MASK                                                             0x7F000000L
 //DB_DFSM_CONFIG
 #define DB_DFSM_CONFIG__BYPASS_DFSM__SHIFT                                                                    0x0
 #define CB_HW_CONTROL_3__DISABLE_NACK_PROCESSING_CM__SHIFT                                                    0x18
 #define CB_HW_CONTROL_3__DISABLE_NACK_COLOR_RD_WR_OPT__SHIFT                                                  0x19
 #define CB_HW_CONTROL_3__DISABLE_BLENDER_CLOCK_GATING__SHIFT                                                  0x1a
+#define CB_HW_CONTROL_3__DISABLE_DCC_VRS_OPT__SHIFT                                                           0x1c
 #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT__SHIFT                                                     0x1e
 #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT_BC__SHIFT                                                  0x1f
 #define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL_MASK                                          0x00000001L
 #define CB_HW_CONTROL_3__DISABLE_NACK_PROCESSING_CM_MASK                                                      0x01000000L
 #define CB_HW_CONTROL_3__DISABLE_NACK_COLOR_RD_WR_OPT_MASK                                                    0x02000000L
 #define CB_HW_CONTROL_3__DISABLE_BLENDER_CLOCK_GATING_MASK                                                    0x04000000L
+#define CB_HW_CONTROL_3__DISABLE_DCC_VRS_OPT_MASK                                                             0x10000000L
 #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT_MASK                                                       0x40000000L
 #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT_BC_MASK                                                    0x80000000L
 //CB_HW_CONTROL
 #define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE__SHIFT                                                      0x0
+#define CB_HW_CONTROL__DISABLE_VRS_FILLRATE_OPTIMIZATION__SHIFT                                               0x1
 #define CB_HW_CONTROL__DISABLE_FILLRATE_OPT_FIX_WITH_CFC__SHIFT                                               0x3
 #define CB_HW_CONTROL__DISABLE_POST_DCC_WITH_CFC_FIX__SHIFT                                                   0x4
+#define CB_HW_CONTROL__DISABLE_COMPRESS_1FRAG_WHEN_VRS_RATE_HINT_EN__SHIFT                                    0x5
 #define CB_HW_CONTROL__RMI_CREDITS__SHIFT                                                                     0x6
 #define CB_HW_CONTROL__CHICKEN_BITS__SHIFT                                                                    0xc
 #define CB_HW_CONTROL__DISABLE_FMASK_MULTI_MGCG_DOMAINS__SHIFT                                                0xf
 #define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT__SHIFT                                              0x1e
 #define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE__SHIFT                                    0x1f
 #define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE_MASK                                                        0x00000001L
+#define CB_HW_CONTROL__DISABLE_VRS_FILLRATE_OPTIMIZATION_MASK                                                 0x00000002L
 #define CB_HW_CONTROL__DISABLE_FILLRATE_OPT_FIX_WITH_CFC_MASK                                                 0x00000008L
 #define CB_HW_CONTROL__DISABLE_POST_DCC_WITH_CFC_FIX_MASK                                                     0x00000010L
+#define CB_HW_CONTROL__DISABLE_COMPRESS_1FRAG_WHEN_VRS_RATE_HINT_EN_MASK                                      0x00000020L
 #define CB_HW_CONTROL__RMI_CREDITS_MASK                                                                       0x00000FC0L
 #define CB_HW_CONTROL__CHICKEN_BITS_MASK                                                                      0x00007000L
 #define CB_HW_CONTROL__DISABLE_FMASK_MULTI_MGCG_DOMAINS_MASK                                                  0x00008000L
 #define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS__SHIFT                                                         0x16
 #define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS__SHIFT                                                         0x17
 #define DB_RENDER_OVERRIDE2__ALLOW_PARTIAL_RES_HIER_KILL__SHIFT                                               0x19
+#define DB_RENDER_OVERRIDE2__FORCE_VRS_RATE_FINE__SHIFT                                                       0x1a
 #define DB_RENDER_OVERRIDE2__CENTROID_COMPUTATION_MODE__SHIFT                                                 0x1b
 #define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL_MASK                                                0x00000003L
 #define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN_MASK                                              0x0000001CL
 #define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS_MASK                                                           0x00400000L
 #define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS_MASK                                                           0x00800000L
 #define DB_RENDER_OVERRIDE2__ALLOW_PARTIAL_RES_HIER_KILL_MASK                                                 0x02000000L
+#define DB_RENDER_OVERRIDE2__FORCE_VRS_RATE_FINE_MASK                                                         0x04000000L
 #define DB_RENDER_OVERRIDE2__CENTROID_COMPUTATION_MODE_MASK                                                   0x18000000L
 //DB_HTILE_DATA_BASE
 #define DB_HTILE_DATA_BASE__BASE_256B__SHIFT                                                                  0x0
 //DB_RESERVED_REG_3
 #define DB_RESERVED_REG_3__FIELD_1__SHIFT                                                                     0x0
 #define DB_RESERVED_REG_3__FIELD_1_MASK                                                                       0x003FFFFFL
+//DB_VRS_OVERRIDE_CNTL
+#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_COMBINER_MODE__SHIFT                                          0x0
+#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_X__SHIFT                                                      0x4
+#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_Y__SHIFT                                                      0x6
+#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_COMBINER_MODE_MASK                                            0x00000007L
+#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_X_MASK                                                        0x00000030L
+#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_Y_MASK                                                        0x000000C0L
 //DB_Z_READ_BASE_HI
 #define DB_Z_READ_BASE_HI__BASE_HI__SHIFT                                                                     0x0
 #define DB_Z_READ_BASE_HI__BASE_HI_MASK                                                                       0x000000FFL
 #define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA__SHIFT                                                    0x18
 #define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG__SHIFT                                                         0x19
 #define PA_CL_VS_OUT_CNTL__USE_VTX_LINE_WIDTH__SHIFT                                                          0x1b
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VRS_RATE__SHIFT                                                            0x1c
 #define PA_CL_VS_OUT_CNTL__BYPASS_VTX_RATE_COMBINER__SHIFT                                                    0x1d
 #define PA_CL_VS_OUT_CNTL__BYPASS_PRIM_RATE_COMBINER__SHIFT                                                   0x1e
 #define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0_MASK                                                               0x00000001L
 #define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA_MASK                                                      0x01000000L
 #define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG_MASK                                                           0x02000000L
 #define PA_CL_VS_OUT_CNTL__USE_VTX_LINE_WIDTH_MASK                                                            0x08000000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VRS_RATE_MASK                                                              0x10000000L
 #define PA_CL_VS_OUT_CNTL__BYPASS_VTX_RATE_COMBINER_MASK                                                      0x20000000L
 #define PA_CL_VS_OUT_CNTL__BYPASS_PRIM_RATE_COMBINER_MASK                                                     0x40000000L
 //PA_CL_NANINF_CNTL
 //PA_STATE_STEREO_X
 #define PA_STATE_STEREO_X__STEREO_X_OFFSET__SHIFT                                                             0x0
 #define PA_STATE_STEREO_X__STEREO_X_OFFSET_MASK                                                               0xFFFFFFFFL
+//PA_CL_VRS_CNTL
+#define PA_CL_VRS_CNTL__VERTEX_RATE_COMBINER_MODE__SHIFT                                                      0x0
+#define PA_CL_VRS_CNTL__PRIMITIVE_RATE_COMBINER_MODE__SHIFT                                                   0x3
+#define PA_CL_VRS_CNTL__HTILE_RATE_COMBINER_MODE__SHIFT                                                       0x6
+#define PA_CL_VRS_CNTL__SAMPLE_ITER_COMBINER_MODE__SHIFT                                                      0x9
+#define PA_CL_VRS_CNTL__EXPOSE_VRS_PIXELS_MASK__SHIFT                                                         0xd
+#define PA_CL_VRS_CNTL__CMASK_RATE_HINT_FORCE_ZERO__SHIFT                                                     0xe
+#define PA_CL_VRS_CNTL__VERTEX_RATE_COMBINER_MODE_MASK                                                        0x00000007L
+#define PA_CL_VRS_CNTL__PRIMITIVE_RATE_COMBINER_MODE_MASK                                                     0x00000038L
+#define PA_CL_VRS_CNTL__HTILE_RATE_COMBINER_MODE_MASK                                                         0x000001C0L
+#define PA_CL_VRS_CNTL__SAMPLE_ITER_COMBINER_MODE_MASK                                                        0x00000E00L
+#define PA_CL_VRS_CNTL__EXPOSE_VRS_PIXELS_MASK_MASK                                                           0x00002000L
+#define PA_CL_VRS_CNTL__CMASK_RATE_HINT_FORCE_ZERO_MASK                                                       0x00004000L
 //PA_SU_POINT_SIZE
 #define PA_SU_POINT_SIZE__HEIGHT__SHIFT                                                                       0x0
 #define PA_SU_POINT_SIZE__WIDTH__SHIFT                                                                        0x10
 #define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE__SHIFT                                                      0x10
 #define DB_HTILE_SURFACE__RESERVED_FIELD_6__SHIFT                                                             0x11
 #define DB_HTILE_SURFACE__PIPE_ALIGNED__SHIFT                                                                 0x12
+#define DB_HTILE_SURFACE__VRS_HTILE_ENCODING__SHIFT                                                           0x13
 #define DB_HTILE_SURFACE__RESERVED_FIELD_1_MASK                                                               0x00000001L
 #define DB_HTILE_SURFACE__FULL_CACHE_MASK                                                                     0x00000002L
 #define DB_HTILE_SURFACE__RESERVED_FIELD_2_MASK                                                               0x00000004L
 #define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE_MASK                                                        0x00010000L
 #define DB_HTILE_SURFACE__RESERVED_FIELD_6_MASK                                                               0x00020000L
 #define DB_HTILE_SURFACE__PIPE_ALIGNED_MASK                                                                   0x00040000L
+#define DB_HTILE_SURFACE__VRS_HTILE_ENCODING_MASK                                                             0x00180000L
 //DB_SRESULTS_COMPARE_STATE0
 #define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0__SHIFT                                                       0x0
 #define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0__SHIFT                                                      0x4
 #define CB_COLOR0_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR0_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR0_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR0_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR0_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR0_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR0_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR0_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR0_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR0_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR0_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR1_ATTRIB3
 #define CB_COLOR1_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR1_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR1_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR1_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR1_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR1_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR1_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR1_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR1_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR1_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR1_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR1_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR1_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR2_ATTRIB3
 #define CB_COLOR2_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR2_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR2_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR2_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR2_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR2_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR2_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR2_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR2_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR2_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR2_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR2_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR2_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR3_ATTRIB3
 #define CB_COLOR3_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR3_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR3_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR3_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR3_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR3_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR3_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR3_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR3_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR3_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR3_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR3_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR3_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR4_ATTRIB3
 #define CB_COLOR4_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR4_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR4_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR4_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR4_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR4_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR4_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR4_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR4_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR4_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR4_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR4_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR4_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR5_ATTRIB3
 #define CB_COLOR5_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR5_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR5_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR5_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR5_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR5_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR5_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR5_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR5_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR5_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR5_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR5_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR5_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR6_ATTRIB3
 #define CB_COLOR6_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR6_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR6_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR6_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR6_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR6_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR6_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR6_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR6_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR6_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR6_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR6_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR6_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 //CB_COLOR7_ATTRIB3
 #define CB_COLOR7_ATTRIB3__MIP0_DEPTH__SHIFT                                                                  0x0
 #define CB_COLOR7_ATTRIB3__META_LINEAR__SHIFT                                                                 0xd
 #define CB_COLOR7_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT                                                          0x1a
 #define CB_COLOR7_ATTRIB3__RESOURCE_LEVEL__SHIFT                                                              0x1b
 #define CB_COLOR7_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT                                                            0x1e
+#define CB_COLOR7_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT                                                        0x1f
 #define CB_COLOR7_ATTRIB3__MIP0_DEPTH_MASK                                                                    0x00001FFFL
 #define CB_COLOR7_ATTRIB3__META_LINEAR_MASK                                                                   0x00002000L
 #define CB_COLOR7_ATTRIB3__COLOR_SW_MODE_MASK                                                                 0x0007C000L
 #define CB_COLOR7_ATTRIB3__CMASK_PIPE_ALIGNED_MASK                                                            0x04000000L
 #define CB_COLOR7_ATTRIB3__RESOURCE_LEVEL_MASK                                                                0x38000000L
 #define CB_COLOR7_ATTRIB3__DCC_PIPE_ALIGNED_MASK                                                              0x40000000L
+#define CB_COLOR7_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK                                                          0x80000000L
 
 
 // addressBlock: gc_gfxudec
index c0efd90..58cf7ad 100644 (file)
 #define VCN_FEATURES__HAS_MJPEG2_IDCT_DEC__SHIFT                                                              0x7
 #define VCN_FEATURES__HAS_SCLR_DEC__SHIFT                                                                     0x8
 #define VCN_FEATURES__HAS_VP9_DEC__SHIFT                                                                      0x9
+#define VCN_FEATURES__HAS_AV1_DEC__SHIFT                                                                      0xa
 #define VCN_FEATURES__HAS_EFC_ENC__SHIFT                                                                      0xb
 #define VCN_FEATURES__HAS_EFC_HDR2SDR_ENC__SHIFT                                                              0xc
 #define VCN_FEATURES__HAS_DUAL_MJPEG_DEC__SHIFT                                                               0xd
 #define VCN_FEATURES__HAS_MJPEG2_IDCT_DEC_MASK                                                                0x00000080L
 #define VCN_FEATURES__HAS_SCLR_DEC_MASK                                                                       0x00000100L
 #define VCN_FEATURES__HAS_VP9_DEC_MASK                                                                        0x00000200L
+#define VCN_FEATURES__HAS_AV1_DEC_MASK                                                                        0x00000400L
 #define VCN_FEATURES__HAS_EFC_ENC_MASK                                                                        0x00000800L
 #define VCN_FEATURES__HAS_EFC_HDR2SDR_ENC_MASK                                                                0x00001000L
 #define VCN_FEATURES__HAS_DUAL_MJPEG_DEC_MASK                                                                 0x00002000L
 #define UVD_SUVD_CGC_GATE__IME_HEVC__SHIFT                                                                    0x18
 #define UVD_SUVD_CGC_GATE__EFC__SHIFT                                                                         0x19
 #define UVD_SUVD_CGC_GATE__SAOE__SHIFT                                                                        0x1a
+#define UVD_SUVD_CGC_GATE__SRE_AV1__SHIFT                                                                     0x1b
 #define UVD_SUVD_CGC_GATE__FBC_PCLK__SHIFT                                                                    0x1c
 #define UVD_SUVD_CGC_GATE__FBC_CCLK__SHIFT                                                                    0x1d
+#define UVD_SUVD_CGC_GATE__SCM_AV1__SHIFT                                                                     0x1e
 #define UVD_SUVD_CGC_GATE__SMPA__SHIFT                                                                        0x1f
 #define UVD_SUVD_CGC_GATE__SRE_MASK                                                                           0x00000001L
 #define UVD_SUVD_CGC_GATE__SIT_MASK                                                                           0x00000002L
 #define UVD_SUVD_CGC_GATE__IME_HEVC_MASK                                                                      0x01000000L
 #define UVD_SUVD_CGC_GATE__EFC_MASK                                                                           0x02000000L
 #define UVD_SUVD_CGC_GATE__SAOE_MASK                                                                          0x04000000L
+#define UVD_SUVD_CGC_GATE__SRE_AV1_MASK                                                                       0x08000000L
 #define UVD_SUVD_CGC_GATE__FBC_PCLK_MASK                                                                      0x10000000L
 #define UVD_SUVD_CGC_GATE__FBC_CCLK_MASK                                                                      0x20000000L
+#define UVD_SUVD_CGC_GATE__SCM_AV1_MASK                                                                       0x40000000L
 #define UVD_SUVD_CGC_GATE__SMPA_MASK                                                                          0x80000000L
 //UVD_SUVD_CGC_STATUS
 #define UVD_SUVD_CGC_STATUS__SRE_VCLK__SHIFT                                                                  0x0
 #define UVD_SUVD_CGC_STATUS__IME_HEVC_DCLK__SHIFT                                                             0x1b
 #define UVD_SUVD_CGC_STATUS__EFC_DCLK__SHIFT                                                                  0x1c
 #define UVD_SUVD_CGC_STATUS__SAOE_DCLK__SHIFT                                                                 0x1d
+#define UVD_SUVD_CGC_STATUS__SRE_AV1_VCLK__SHIFT                                                              0x1e
+#define UVD_SUVD_CGC_STATUS__SCM_AV1_DCLK__SHIFT                                                              0x1f
 #define UVD_SUVD_CGC_STATUS__SRE_VCLK_MASK                                                                    0x00000001L
 #define UVD_SUVD_CGC_STATUS__SRE_DCLK_MASK                                                                    0x00000002L
 #define UVD_SUVD_CGC_STATUS__SIT_DCLK_MASK                                                                    0x00000004L
 #define UVD_SUVD_CGC_STATUS__IME_HEVC_DCLK_MASK                                                               0x08000000L
 #define UVD_SUVD_CGC_STATUS__EFC_DCLK_MASK                                                                    0x10000000L
 #define UVD_SUVD_CGC_STATUS__SAOE_DCLK_MASK                                                                   0x20000000L
+#define UVD_SUVD_CGC_STATUS__SRE_AV1_VCLK_MASK                                                                0x40000000L
+#define UVD_SUVD_CGC_STATUS__SCM_AV1_DCLK_MASK                                                                0x80000000L
 //UVD_SUVD_CGC_CTRL
 #define UVD_SUVD_CGC_CTRL__SRE_MODE__SHIFT                                                                    0x0
 #define UVD_SUVD_CGC_CTRL__SIT_MODE__SHIFT                                                                    0x1
 #define UVD_SUVD_CGC_CTRL__SMPA_MODE__SHIFT                                                                   0xc
 #define UVD_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT                                                                  0xd
 #define UVD_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT                                                                  0xe
+#define UVD_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT                                                                0xf
+#define UVD_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT                                                                0x10
 #define UVD_SUVD_CGC_CTRL__MPC1_MODE__SHIFT                                                                   0x11
 #define UVD_SUVD_CGC_CTRL__FBC_PCLK__SHIFT                                                                    0x1c
 #define UVD_SUVD_CGC_CTRL__FBC_CCLK__SHIFT                                                                    0x1d
 #define UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK                                                                     0x00001000L
 #define UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK                                                                    0x00002000L
 #define UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK                                                                    0x00004000L
+#define UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK                                                                  0x00008000L
+#define UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK                                                                  0x00010000L
 #define UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK                                                                     0x00020000L
 #define UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK                                                                      0x10000000L
 #define UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK                                                                      0x20000000L
 #define UVD_SUVD_CGC_STATUS2__SMPA_VCLK__SHIFT                                                                0x0
 #define UVD_SUVD_CGC_STATUS2__SMPA_DCLK__SHIFT                                                                0x1
 #define UVD_SUVD_CGC_STATUS2__MPBE1_DCLK__SHIFT                                                               0x3
+#define UVD_SUVD_CGC_STATUS2__SIT_AV1_DCLK__SHIFT                                                             0x4
+#define UVD_SUVD_CGC_STATUS2__SDB_AV1_DCLK__SHIFT                                                             0x5
 #define UVD_SUVD_CGC_STATUS2__MPC1_DCLK__SHIFT                                                                0x6
 #define UVD_SUVD_CGC_STATUS2__MPC1_SCLK__SHIFT                                                                0x7
 #define UVD_SUVD_CGC_STATUS2__MPC1_VCLK__SHIFT                                                                0x8
 #define UVD_SUVD_CGC_STATUS2__SMPA_VCLK_MASK                                                                  0x00000001L
 #define UVD_SUVD_CGC_STATUS2__SMPA_DCLK_MASK                                                                  0x00000002L
 #define UVD_SUVD_CGC_STATUS2__MPBE1_DCLK_MASK                                                                 0x00000008L
+#define UVD_SUVD_CGC_STATUS2__SIT_AV1_DCLK_MASK                                                               0x00000010L
+#define UVD_SUVD_CGC_STATUS2__SDB_AV1_DCLK_MASK                                                               0x00000020L
 #define UVD_SUVD_CGC_STATUS2__MPC1_DCLK_MASK                                                                  0x00000040L
 #define UVD_SUVD_CGC_STATUS2__MPC1_SCLK_MASK                                                                  0x00000080L
 #define UVD_SUVD_CGC_STATUS2__MPC1_VCLK_MASK                                                                  0x00000100L
 //UVD_SUVD_CGC_GATE2
 #define UVD_SUVD_CGC_GATE2__MPBE0__SHIFT                                                                      0x0
 #define UVD_SUVD_CGC_GATE2__MPBE1__SHIFT                                                                      0x1
+#define UVD_SUVD_CGC_GATE2__SIT_AV1__SHIFT                                                                    0x2
+#define UVD_SUVD_CGC_GATE2__SDB_AV1__SHIFT                                                                    0x3
 #define UVD_SUVD_CGC_GATE2__MPC1__SHIFT                                                                       0x4
 #define UVD_SUVD_CGC_GATE2__MPBE0_MASK                                                                        0x00000001L
 #define UVD_SUVD_CGC_GATE2__MPBE1_MASK                                                                        0x00000002L
+#define UVD_SUVD_CGC_GATE2__SIT_AV1_MASK                                                                      0x00000004L
+#define UVD_SUVD_CGC_GATE2__SDB_AV1_MASK                                                                      0x00000008L
 #define UVD_SUVD_CGC_GATE2__MPC1_MASK                                                                         0x00000010L
 //UVD_SUVD_INT_STATUS2
 #define UVD_SUVD_INT_STATUS2__SMPA_FUNC_INT__SHIFT                                                            0x0
 #define UVD_SUVD_INT_STATUS2__SMPA_ERR_INT__SHIFT                                                             0x5
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_FUNC_INT__SHIFT                                                         0x6
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_ERR_INT__SHIFT                                                          0xb
 #define UVD_SUVD_INT_STATUS2__SMPA_FUNC_INT_MASK                                                              0x0000001FL
 #define UVD_SUVD_INT_STATUS2__SMPA_ERR_INT_MASK                                                               0x00000020L
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_FUNC_INT_MASK                                                           0x000007C0L
+#define UVD_SUVD_INT_STATUS2__SDB_AV1_ERR_INT_MASK                                                            0x00000800L
 //UVD_SUVD_INT_EN2
 #define UVD_SUVD_INT_EN2__SMPA_FUNC_INT_EN__SHIFT                                                             0x0
 #define UVD_SUVD_INT_EN2__SMPA_ERR_INT_EN__SHIFT                                                              0x5
+#define UVD_SUVD_INT_EN2__SDB_AV1_FUNC_INT_EN__SHIFT                                                          0x6
+#define UVD_SUVD_INT_EN2__SDB_AV1_ERR_INT_EN__SHIFT                                                           0xb
 #define UVD_SUVD_INT_EN2__SMPA_FUNC_INT_EN_MASK                                                               0x0000001FL
 #define UVD_SUVD_INT_EN2__SMPA_ERR_INT_EN_MASK                                                                0x00000020L
+#define UVD_SUVD_INT_EN2__SDB_AV1_FUNC_INT_EN_MASK                                                            0x000007C0L
+#define UVD_SUVD_INT_EN2__SDB_AV1_ERR_INT_EN_MASK                                                             0x00000800L
 //UVD_SUVD_INT_ACK2
 #define UVD_SUVD_INT_ACK2__SMPA_FUNC_INT_ACK__SHIFT                                                           0x0
 #define UVD_SUVD_INT_ACK2__SMPA_ERR_INT_ACK__SHIFT                                                            0x5
+#define UVD_SUVD_INT_ACK2__SDB_AV1_FUNC_INT_ACK__SHIFT                                                        0x6
+#define UVD_SUVD_INT_ACK2__SDB_AV1_ERR_INT_ACK__SHIFT                                                         0xb
 #define UVD_SUVD_INT_ACK2__SMPA_FUNC_INT_ACK_MASK                                                             0x0000001FL
 #define UVD_SUVD_INT_ACK2__SMPA_ERR_INT_ACK_MASK                                                              0x00000020L
+#define UVD_SUVD_INT_ACK2__SDB_AV1_FUNC_INT_ACK_MASK                                                          0x000007C0L
+#define UVD_SUVD_INT_ACK2__SDB_AV1_ERR_INT_ACK_MASK                                                           0x00000800L
 
 
 // addressBlock: uvd0_ecpudec
index 0826625..8dc5abb 100644 (file)
@@ -479,17 +479,6 @@ static int smu_late_init(void *handle)
                return ret;
        }
 
-       /*
-        * Set initialized values (get from vbios) to dpm tables context such as
-        * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each
-        * type of clks.
-        */
-       ret = smu_set_default_dpm_table(smu);
-       if (ret) {
-               dev_err(adev->dev, "Failed to setup default dpm clock tables!\n");
-               return ret;
-       }
-
        ret = smu_populate_umd_state_clk(smu);
        if (ret) {
                dev_err(adev->dev, "Failed to populate UMD state clocks!\n");
@@ -984,6 +973,17 @@ static int smu_smc_hw_setup(struct smu_context *smu)
                return ret;
        }
 
+       /*
+        * Set initialized values (get from vbios) to dpm tables context such as
+        * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each
+        * type of clks.
+        */
+       ret = smu_set_default_dpm_table(smu);
+       if (ret) {
+               dev_err(adev->dev, "Failed to setup default dpm clock tables!\n");
+               return ret;
+       }
+
        ret = smu_notify_display_change(smu);
        if (ret)
                return ret;
@@ -1126,7 +1126,7 @@ static int smu_disable_dpms(struct smu_context *smu)
         */
        if (smu->uploading_custom_pp_table &&
            (adev->asic_type >= CHIP_NAVI10) &&
-           (adev->asic_type <= CHIP_NAVI12))
+           (adev->asic_type <= CHIP_NAVY_FLOUNDER))
                return 0;
 
        /*
@@ -1211,7 +1211,9 @@ static int smu_hw_fini(void *handle)
 int smu_reset(struct smu_context *smu)
 {
        struct amdgpu_device *adev = smu->adev;
-       int ret = 0;
+       int ret;
+
+       amdgpu_gfx_off_ctrl(smu->adev, false);
 
        ret = smu_hw_fini(adev);
        if (ret)
@@ -1222,8 +1224,12 @@ int smu_reset(struct smu_context *smu)
                return ret;
 
        ret = smu_late_init(adev);
+       if (ret)
+               return ret;
 
-       return ret;
+       amdgpu_gfx_off_ctrl(smu->adev, true);
+
+       return 0;
 }
 
 static int smu_suspend(void *handle)
index 9ee8cf8..43f7adf 100644 (file)
@@ -563,6 +563,8 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
        struct smu10_hwmgr *data = hwmgr->backend;
        uint32_t min_sclk = hwmgr->display_config->min_core_set_clock;
        uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100;
+       uint32_t index_fclk = data->clock_vol_info.vdd_dep_on_fclk->count - 1;
+       uint32_t index_socclk = data->clock_vol_info.vdd_dep_on_socclk->count - 1;
 
        if (hwmgr->smu_version < 0x1E3700) {
                pr_info("smu firmware version too old, can not set dpm level\n");
@@ -676,13 +678,13 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetHardMinFclkByFreq,
                                                hwmgr->display_config->num_display > 3 ?
-                                               SMU10_UMD_PSTATE_PEAK_FCLK :
+                                               data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk :
                                                min_mclk,
                                                NULL);
 
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetHardMinSocclkByFreq,
-                                               SMU10_UMD_PSTATE_MIN_SOCCLK,
+                                               data->clock_vol_info.vdd_dep_on_socclk->entries[0].clk,
                                                NULL);
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetHardMinVcn,
@@ -695,11 +697,11 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
                                                NULL);
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetSoftMaxFclkByFreq,
-                                               SMU10_UMD_PSTATE_PEAK_FCLK,
+                                               data->clock_vol_info.vdd_dep_on_fclk->entries[index_fclk].clk,
                                                NULL);
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetSoftMaxSocclkByFreq,
-                                               SMU10_UMD_PSTATE_PEAK_SOCCLK,
+                                               data->clock_vol_info.vdd_dep_on_socclk->entries[index_socclk].clk,
                                                NULL);
                smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetSoftMaxVcn,
index 3d5eae9..b1547a8 100644 (file)
@@ -2265,8 +2265,6 @@ static void navi10_fill_i2c_req(SwI2cRequest_t  *req, bool write,
 {
        int i;
 
-       BUG_ON(numbytes > MAX_SW_I2C_COMMANDS);
-
        req->I2CcontrollerPort = 0;
        req->I2CSpeed = 2;
        req->SlaveAddress = address;
@@ -2304,6 +2302,12 @@ static int navi10_i2c_read_data(struct i2c_adapter *control,
        struct smu_table_context *smu_table = &adev->smu.smu_table;
        struct smu_table *table = &smu_table->driver_table;
 
+       if (numbytes > MAX_SW_I2C_COMMANDS) {
+               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
+                       numbytes, MAX_SW_I2C_COMMANDS);
+               return -EINVAL;
+       }
+
        memset(&req, 0, sizeof(req));
        navi10_fill_i2c_req(&req, false, address, numbytes, data);
 
@@ -2340,6 +2344,12 @@ static int navi10_i2c_write_data(struct i2c_adapter *control,
        SwI2cRequest_t req;
        struct amdgpu_device *adev = to_amdgpu_device(control);
 
+       if (numbytes > MAX_SW_I2C_COMMANDS) {
+               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
+                       numbytes, MAX_SW_I2C_COMMANDS);
+               return -EINVAL;
+       }
+
        memset(&req, 0, sizeof(req));
        navi10_fill_i2c_req(&req, true, address, numbytes, data);
 
index dbb676c..15263cf 100644 (file)
@@ -232,14 +232,16 @@ static int renoir_get_profiling_clk_mask(struct smu_context *smu,
                        *sclk_mask = 0;
        } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
                if (mclk_mask)
-                       *mclk_mask = 0;
+                       /* mclk levels are in reverse order */
+                       *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1;
        } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
                if(sclk_mask)
                        /* The sclk as gfxclk and has three level about max/min/current */
                        *sclk_mask = 3 - 1;
 
                if(mclk_mask)
-                       *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1;
+                       /* mclk levels are in reverse order */
+                       *mclk_mask = 0;
 
                if(soc_mask)
                        *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1;
@@ -333,7 +335,7 @@ static int renoir_get_dpm_ultimate_freq(struct smu_context *smu,
                case SMU_UCLK:
                case SMU_FCLK:
                case SMU_MCLK:
-                       ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min);
+                       ret = renoir_get_dpm_clk_limited(smu, clk_type, NUM_MEMCLK_DPM_LEVELS - 1, min);
                        if (ret)
                                goto failed;
                        break;
index 61f4dda..ace682f 100644 (file)
@@ -2445,8 +2445,6 @@ static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
 {
        int i;
 
-       BUG_ON(numbytes > MAX_SW_I2C_COMMANDS);
-
        req->I2CcontrollerPort = 0;
        req->I2CSpeed = 2;
        req->SlaveAddress = address;
@@ -2484,6 +2482,12 @@ static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
        struct smu_table_context *smu_table = &adev->smu.smu_table;
        struct smu_table *table = &smu_table->driver_table;
 
+       if (numbytes > MAX_SW_I2C_COMMANDS) {
+               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
+                       numbytes, MAX_SW_I2C_COMMANDS);
+               return -EINVAL;
+       }
+
        memset(&req, 0, sizeof(req));
        sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
 
@@ -2520,6 +2524,12 @@ static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
        SwI2cRequest_t req;
        struct amdgpu_device *adev = to_amdgpu_device(control);
 
+       if (numbytes > MAX_SW_I2C_COMMANDS) {
+               dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
+                       numbytes, MAX_SW_I2C_COMMANDS);
+               return -EINVAL;
+       }
+
        memset(&req, 0, sizeof(req));
        sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
 
index 6832567..b18c5ac 100644 (file)
@@ -14956,12 +14956,6 @@ static int intel_atomic_check(struct drm_device *dev,
        if (dev_priv->wm.distrust_bios_wm)
                any_ms = true;
 
-       if (any_ms) {
-               ret = intel_modeset_checks(state);
-               if (ret)
-                       goto fail;
-       }
-
        intel_fbc_choose_crtc(dev_priv, state);
        ret = calc_watermark_data(state);
        if (ret)
@@ -14976,6 +14970,10 @@ static int intel_atomic_check(struct drm_device *dev,
                goto fail;
 
        if (any_ms) {
+               ret = intel_modeset_checks(state);
+               if (ret)
+                       goto fail;
+
                ret = intel_modeset_calc_cdclk(state);
                if (ret)
                        return ret;
index d0bdb6d..ef755dd 100644 (file)
@@ -439,29 +439,36 @@ static bool __cancel_engine(struct intel_engine_cs *engine)
        return __reset_engine(engine);
 }
 
-static struct intel_engine_cs *__active_engine(struct i915_request *rq)
+static bool
+__active_engine(struct i915_request *rq, struct intel_engine_cs **active)
 {
        struct intel_engine_cs *engine, *locked;
+       bool ret = false;
 
        /*
         * Serialise with __i915_request_submit() so that it sees
         * is-banned?, or we know the request is already inflight.
+        *
+        * Note that rq->engine is unstable, and so we double
+        * check that we have acquired the lock on the final engine.
         */
        locked = READ_ONCE(rq->engine);
        spin_lock_irq(&locked->active.lock);
        while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
                spin_unlock(&locked->active.lock);
-               spin_lock(&engine->active.lock);
                locked = engine;
+               spin_lock(&locked->active.lock);
        }
 
-       engine = NULL;
-       if (i915_request_is_active(rq) && rq->fence.error != -EIO)
-               engine = rq->engine;
+       if (!i915_request_completed(rq)) {
+               if (i915_request_is_active(rq) && rq->fence.error != -EIO)
+                       *active = locked;
+               ret = true;
+       }
 
        spin_unlock_irq(&locked->active.lock);
 
-       return engine;
+       return ret;
 }
 
 static struct intel_engine_cs *active_engine(struct intel_context *ce)
@@ -472,17 +479,16 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce)
        if (!ce->timeline)
                return NULL;
 
-       mutex_lock(&ce->timeline->mutex);
-       list_for_each_entry_reverse(rq, &ce->timeline->requests, link) {
-               if (i915_request_completed(rq))
-                       break;
+       rcu_read_lock();
+       list_for_each_entry_rcu(rq, &ce->timeline->requests, link) {
+               if (i915_request_is_active(rq) && i915_request_completed(rq))
+                       continue;
 
                /* Check with the backend if the request is inflight */
-               engine = __active_engine(rq);
-               if (engine)
+               if (__active_engine(rq, &engine))
                        break;
        }
-       mutex_unlock(&ce->timeline->mutex);
+       rcu_read_unlock();
 
        return engine;
 }
@@ -713,6 +719,7 @@ __create_context(struct drm_i915_private *i915)
        ctx->i915 = i915;
        ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL);
        mutex_init(&ctx->mutex);
+       INIT_LIST_HEAD(&ctx->link);
 
        spin_lock_init(&ctx->stale.lock);
        INIT_LIST_HEAD(&ctx->stale.engines);
@@ -740,10 +747,6 @@ __create_context(struct drm_i915_private *i915)
        for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++)
                ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES;
 
-       spin_lock(&i915->gem.contexts.lock);
-       list_add_tail(&ctx->link, &i915->gem.contexts.list);
-       spin_unlock(&i915->gem.contexts.lock);
-
        return ctx;
 
 err_free:
@@ -931,6 +934,7 @@ static int gem_context_register(struct i915_gem_context *ctx,
                                struct drm_i915_file_private *fpriv,
                                u32 *id)
 {
+       struct drm_i915_private *i915 = ctx->i915;
        struct i915_address_space *vm;
        int ret;
 
@@ -949,8 +953,16 @@ static int gem_context_register(struct i915_gem_context *ctx,
        /* And finally expose ourselves to userspace via the idr */
        ret = xa_alloc(&fpriv->context_xa, id, ctx, xa_limit_32b, GFP_KERNEL);
        if (ret)
-               put_pid(fetch_and_zero(&ctx->pid));
+               goto err_pid;
+
+       spin_lock(&i915->gem.contexts.lock);
+       list_add_tail(&ctx->link, &i915->gem.contexts.list);
+       spin_unlock(&i915->gem.contexts.lock);
+
+       return 0;
 
+err_pid:
+       put_pid(fetch_and_zero(&ctx->pid));
        return ret;
 }
 
index 6b4ec66..446e76e 100644 (file)
@@ -45,6 +45,13 @@ struct eb_vma_array {
        struct eb_vma vma[];
 };
 
+enum {
+       FORCE_CPU_RELOC = 1,
+       FORCE_GTT_RELOC,
+       FORCE_GPU_RELOC,
+#define DBG_FORCE_RELOC 0 /* choose one of the above! */
+};
+
 #define __EXEC_OBJECT_HAS_PIN          BIT(31)
 #define __EXEC_OBJECT_HAS_FENCE                BIT(30)
 #define __EXEC_OBJECT_NEEDS_MAP                BIT(29)
@@ -253,6 +260,8 @@ struct i915_execbuffer {
         */
        struct reloc_cache {
                struct drm_mm_node node; /** temporary GTT binding */
+               unsigned long vaddr; /** Current kmap address */
+               unsigned long page; /** Currently mapped page index */
                unsigned int gen; /** Cached value of INTEL_GEN */
                bool use_64bit_reloc : 1;
                bool has_llc : 1;
@@ -596,6 +605,23 @@ eb_add_vma(struct i915_execbuffer *eb,
        }
 }
 
+static inline int use_cpu_reloc(const struct reloc_cache *cache,
+                               const struct drm_i915_gem_object *obj)
+{
+       if (!i915_gem_object_has_struct_page(obj))
+               return false;
+
+       if (DBG_FORCE_RELOC == FORCE_CPU_RELOC)
+               return true;
+
+       if (DBG_FORCE_RELOC == FORCE_GTT_RELOC)
+               return false;
+
+       return (cache->has_llc ||
+               obj->cache_dirty ||
+               obj->cache_level != I915_CACHE_NONE);
+}
+
 static int eb_reserve_vma(const struct i915_execbuffer *eb,
                          struct eb_vma *ev,
                          u64 pin_flags)
@@ -926,6 +952,8 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc,
 static void reloc_cache_init(struct reloc_cache *cache,
                             struct drm_i915_private *i915)
 {
+       cache->page = -1;
+       cache->vaddr = 0;
        /* Must be a variable in the struct to allow GCC to unroll. */
        cache->gen = INTEL_GEN(i915);
        cache->has_llc = HAS_LLC(i915);
@@ -937,6 +965,25 @@ static void reloc_cache_init(struct reloc_cache *cache,
        cache->target = NULL;
 }
 
+static inline void *unmask_page(unsigned long p)
+{
+       return (void *)(uintptr_t)(p & PAGE_MASK);
+}
+
+static inline unsigned int unmask_flags(unsigned long p)
+{
+       return p & ~PAGE_MASK;
+}
+
+#define KMAP 0x4 /* after CLFLUSH_FLAGS */
+
+static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache)
+{
+       struct drm_i915_private *i915 =
+               container_of(cache, struct i915_execbuffer, reloc_cache)->i915;
+       return &i915->ggtt;
+}
+
 #define RELOC_TAIL 4
 
 static int reloc_gpu_chain(struct reloc_cache *cache)
@@ -1049,6 +1096,181 @@ static int reloc_gpu_flush(struct reloc_cache *cache)
        return err;
 }
 
+static void reloc_cache_reset(struct reloc_cache *cache)
+{
+       void *vaddr;
+
+       if (!cache->vaddr)
+               return;
+
+       vaddr = unmask_page(cache->vaddr);
+       if (cache->vaddr & KMAP) {
+               if (cache->vaddr & CLFLUSH_AFTER)
+                       mb();
+
+               kunmap_atomic(vaddr);
+               i915_gem_object_finish_access((struct drm_i915_gem_object *)cache->node.mm);
+       } else {
+               struct i915_ggtt *ggtt = cache_to_ggtt(cache);
+
+               intel_gt_flush_ggtt_writes(ggtt->vm.gt);
+               io_mapping_unmap_atomic((void __iomem *)vaddr);
+
+               if (drm_mm_node_allocated(&cache->node)) {
+                       ggtt->vm.clear_range(&ggtt->vm,
+                                            cache->node.start,
+                                            cache->node.size);
+                       mutex_lock(&ggtt->vm.mutex);
+                       drm_mm_remove_node(&cache->node);
+                       mutex_unlock(&ggtt->vm.mutex);
+               } else {
+                       i915_vma_unpin((struct i915_vma *)cache->node.mm);
+               }
+       }
+
+       cache->vaddr = 0;
+       cache->page = -1;
+}
+
+static void *reloc_kmap(struct drm_i915_gem_object *obj,
+                       struct reloc_cache *cache,
+                       unsigned long page)
+{
+       void *vaddr;
+
+       if (cache->vaddr) {
+               kunmap_atomic(unmask_page(cache->vaddr));
+       } else {
+               unsigned int flushes;
+               int err;
+
+               err = i915_gem_object_prepare_write(obj, &flushes);
+               if (err)
+                       return ERR_PTR(err);
+
+               BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS);
+               BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK);
+
+               cache->vaddr = flushes | KMAP;
+               cache->node.mm = (void *)obj;
+               if (flushes)
+                       mb();
+       }
+
+       vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj, page));
+       cache->vaddr = unmask_flags(cache->vaddr) | (unsigned long)vaddr;
+       cache->page = page;
+
+       return vaddr;
+}
+
+static void *reloc_iomap(struct drm_i915_gem_object *obj,
+                        struct reloc_cache *cache,
+                        unsigned long page)
+{
+       struct i915_ggtt *ggtt = cache_to_ggtt(cache);
+       unsigned long offset;
+       void *vaddr;
+
+       if (cache->vaddr) {
+               intel_gt_flush_ggtt_writes(ggtt->vm.gt);
+               io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr));
+       } else {
+               struct i915_vma *vma;
+               int err;
+
+               if (i915_gem_object_is_tiled(obj))
+                       return ERR_PTR(-EINVAL);
+
+               if (use_cpu_reloc(cache, obj))
+                       return NULL;
+
+               i915_gem_object_lock(obj);
+               err = i915_gem_object_set_to_gtt_domain(obj, true);
+               i915_gem_object_unlock(obj);
+               if (err)
+                       return ERR_PTR(err);
+
+               vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
+                                              PIN_MAPPABLE |
+                                              PIN_NONBLOCK /* NOWARN */ |
+                                              PIN_NOEVICT);
+               if (IS_ERR(vma)) {
+                       memset(&cache->node, 0, sizeof(cache->node));
+                       mutex_lock(&ggtt->vm.mutex);
+                       err = drm_mm_insert_node_in_range
+                               (&ggtt->vm.mm, &cache->node,
+                                PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE,
+                                0, ggtt->mappable_end,
+                                DRM_MM_INSERT_LOW);
+                       mutex_unlock(&ggtt->vm.mutex);
+                       if (err) /* no inactive aperture space, use cpu reloc */
+                               return NULL;
+               } else {
+                       cache->node.start = vma->node.start;
+                       cache->node.mm = (void *)vma;
+               }
+       }
+
+       offset = cache->node.start;
+       if (drm_mm_node_allocated(&cache->node)) {
+               ggtt->vm.insert_page(&ggtt->vm,
+                                    i915_gem_object_get_dma_address(obj, page),
+                                    offset, I915_CACHE_NONE, 0);
+       } else {
+               offset += page << PAGE_SHIFT;
+       }
+
+       vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->iomap,
+                                                        offset);
+       cache->page = page;
+       cache->vaddr = (unsigned long)vaddr;
+
+       return vaddr;
+}
+
+static void *reloc_vaddr(struct drm_i915_gem_object *obj,
+                        struct reloc_cache *cache,
+                        unsigned long page)
+{
+       void *vaddr;
+
+       if (cache->page == page) {
+               vaddr = unmask_page(cache->vaddr);
+       } else {
+               vaddr = NULL;
+               if ((cache->vaddr & KMAP) == 0)
+                       vaddr = reloc_iomap(obj, cache, page);
+               if (!vaddr)
+                       vaddr = reloc_kmap(obj, cache, page);
+       }
+
+       return vaddr;
+}
+
+static void clflush_write32(u32 *addr, u32 value, unsigned int flushes)
+{
+       if (unlikely(flushes & (CLFLUSH_BEFORE | CLFLUSH_AFTER))) {
+               if (flushes & CLFLUSH_BEFORE) {
+                       clflushopt(addr);
+                       mb();
+               }
+
+               *addr = value;
+
+               /*
+                * Writes to the same cacheline are serialised by the CPU
+                * (including clflush). On the write path, we only require
+                * that it hits memory in an orderly fashion and place
+                * mb barriers at the start and end of the relocation phase
+                * to ensure ordering of clflush wrt to the system.
+                */
+               if (flushes & CLFLUSH_AFTER)
+                       clflushopt(addr);
+       } else
+               *addr = value;
+}
+
 static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma)
 {
        struct drm_i915_gem_object *obj = vma->obj;
@@ -1214,6 +1436,17 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb,
        return cmd;
 }
 
+static inline bool use_reloc_gpu(struct i915_vma *vma)
+{
+       if (DBG_FORCE_RELOC == FORCE_GPU_RELOC)
+               return true;
+
+       if (DBG_FORCE_RELOC)
+               return false;
+
+       return !dma_resv_test_signaled_rcu(vma->resv, true);
+}
+
 static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset)
 {
        struct page *page;
@@ -1228,10 +1461,10 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset)
        return addr + offset_in_page(offset);
 }
 
-static int __reloc_entry_gpu(struct i915_execbuffer *eb,
-                            struct i915_vma *vma,
-                            u64 offset,
-                            u64 target_addr)
+static bool __reloc_entry_gpu(struct i915_execbuffer *eb,
+                             struct i915_vma *vma,
+                             u64 offset,
+                             u64 target_addr)
 {
        const unsigned int gen = eb->reloc_cache.gen;
        unsigned int len;
@@ -1247,7 +1480,7 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb,
 
        batch = reloc_gpu(eb, vma, len);
        if (IS_ERR(batch))
-               return PTR_ERR(batch);
+               return false;
 
        addr = gen8_canonical_addr(vma->node.start + offset);
        if (gen >= 8) {
@@ -1296,21 +1529,55 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb,
                *batch++ = target_addr;
        }
 
-       return 0;
+       return true;
+}
+
+static bool reloc_entry_gpu(struct i915_execbuffer *eb,
+                           struct i915_vma *vma,
+                           u64 offset,
+                           u64 target_addr)
+{
+       if (eb->reloc_cache.vaddr)
+               return false;
+
+       if (!use_reloc_gpu(vma))
+               return false;
+
+       return __reloc_entry_gpu(eb, vma, offset, target_addr);
 }
 
 static u64
-relocate_entry(struct i915_execbuffer *eb,
-              struct i915_vma *vma,
+relocate_entry(struct i915_vma *vma,
               const struct drm_i915_gem_relocation_entry *reloc,
+              struct i915_execbuffer *eb,
               const struct i915_vma *target)
 {
        u64 target_addr = relocation_target(reloc, target);
-       int err;
-
-       err = __reloc_entry_gpu(eb, vma, reloc->offset, target_addr);
-       if (err)
-               return err;
+       u64 offset = reloc->offset;
+
+       if (!reloc_entry_gpu(eb, vma, offset, target_addr)) {
+               bool wide = eb->reloc_cache.use_64bit_reloc;
+               void *vaddr;
+
+repeat:
+               vaddr = reloc_vaddr(vma->obj,
+                                   &eb->reloc_cache,
+                                   offset >> PAGE_SHIFT);
+               if (IS_ERR(vaddr))
+                       return PTR_ERR(vaddr);
+
+               GEM_BUG_ON(!IS_ALIGNED(offset, sizeof(u32)));
+               clflush_write32(vaddr + offset_in_page(offset),
+                               lower_32_bits(target_addr),
+                               eb->reloc_cache.vaddr);
+
+               if (wide) {
+                       offset += sizeof(u32);
+                       target_addr >>= 32;
+                       wide = false;
+                       goto repeat;
+               }
+       }
 
        return target->node.start | UPDATE;
 }
@@ -1375,7 +1642,8 @@ eb_relocate_entry(struct i915_execbuffer *eb,
         * If the relocation already has the right value in it, no
         * more work needs to be done.
         */
-       if (gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset)
+       if (!DBG_FORCE_RELOC &&
+           gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset)
                return 0;
 
        /* Check that the relocation address is valid... */
@@ -1407,7 +1675,7 @@ eb_relocate_entry(struct i915_execbuffer *eb,
        ev->flags &= ~EXEC_OBJECT_ASYNC;
 
        /* and update the user's relocation entry */
-       return relocate_entry(eb, ev->vma, reloc, target->vma);
+       return relocate_entry(ev->vma, reloc, eb, target->vma);
 }
 
 static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
@@ -1445,8 +1713,10 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
                 * this is bad and so lockdep complains vehemently.
                 */
                copied = __copy_from_user(r, urelocs, count * sizeof(r[0]));
-               if (unlikely(copied))
-                       return -EFAULT;
+               if (unlikely(copied)) {
+                       remain = -EFAULT;
+                       goto out;
+               }
 
                remain -= count;
                do {
@@ -1454,7 +1724,8 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
 
                        if (likely(offset == 0)) {
                        } else if ((s64)offset < 0) {
-                               return (int)offset;
+                               remain = (int)offset;
+                               goto out;
                        } else {
                                /*
                                 * Note that reporting an error now
@@ -1484,8 +1755,9 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
                } while (r++, --count);
                urelocs += ARRAY_SIZE(stack);
        } while (remain);
-
-       return 0;
+out:
+       reloc_cache_reset(&eb->reloc_cache);
+       return remain;
 }
 
 static int eb_relocate(struct i915_execbuffer *eb)
@@ -2392,7 +2664,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
        eb.i915 = i915;
        eb.file = file;
        eb.args = args;
-       if (!(args->flags & I915_EXEC_NO_RELOC))
+       if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC))
                args->flags |= __EXEC_HAS_RELOC;
 
        eb.exec = exec;
index e5b9276..9cf4ad7 100644 (file)
@@ -258,6 +258,10 @@ struct page *
 i915_gem_object_get_page(struct drm_i915_gem_object *obj,
                         unsigned int n);
 
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
+                              unsigned int n);
+
 dma_addr_t
 i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
                                    unsigned long n,
index d15ff67..e8a0837 100644 (file)
@@ -548,6 +548,20 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
        return nth_page(sg_page(sg), offset);
 }
 
+/* Like i915_gem_object_get_page(), but mark the returned page dirty */
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
+                              unsigned int n)
+{
+       struct page *page;
+
+       page = i915_gem_object_get_page(obj, n);
+       if (!obj->mm.dirty)
+               set_page_dirty(page);
+
+       return page;
+}
+
 dma_addr_t
 i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj,
                                    unsigned long n,
index 57c14d3..a49016f 100644 (file)
@@ -37,14 +37,20 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb,
                return err;
 
        /* 8-Byte aligned */
-       err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0);
-       if (err)
+       if (!__reloc_entry_gpu(eb, vma,
+                              offsets[0] * sizeof(u32),
+                              0)) {
+               err = -EIO;
                goto unpin_vma;
+       }
 
        /* !8-Byte aligned */
-       err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1);
-       if (err)
+       if (!__reloc_entry_gpu(eb, vma,
+                              offsets[1] * sizeof(u32),
+                              1)) {
+               err = -EIO;
                goto unpin_vma;
+       }
 
        /* Skip to the end of the cmd page */
        i = PAGE_SIZE / sizeof(u32) - RELOC_TAIL - 1;
@@ -54,9 +60,12 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb,
        eb->reloc_cache.rq_size += i;
 
        /* Force batch chaining */
-       err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2);
-       if (err)
+       if (!__reloc_entry_gpu(eb, vma,
+                              offsets[2] * sizeof(u32),
+                              2)) {
+               err = -EIO;
                goto unpin_vma;
+       }
 
        GEM_BUG_ON(!eb->reloc_cache.rq);
        rq = i915_request_get(eb->reloc_cache.rq);
index 24322ef..9eeaca9 100644 (file)
@@ -2060,6 +2060,14 @@ static inline void clear_ports(struct i915_request **ports, int count)
        memset_p((void **)ports, NULL, count);
 }
 
+static inline void
+copy_ports(struct i915_request **dst, struct i915_request **src, int count)
+{
+       /* A memcpy_p() would be very useful here! */
+       while (count--)
+               WRITE_ONCE(*dst++, *src++); /* avoid write tearing */
+}
+
 static void execlists_dequeue(struct intel_engine_cs *engine)
 {
        struct intel_engine_execlists * const execlists = &engine->execlists;
@@ -2648,10 +2656,9 @@ static void process_csb(struct intel_engine_cs *engine)
 
                        /* switch pending to inflight */
                        GEM_BUG_ON(!assert_pending_valid(execlists, "promote"));
-                       memcpy(execlists->inflight,
-                              execlists->pending,
-                              execlists_num_ports(execlists) *
-                              sizeof(*execlists->pending));
+                       copy_ports(execlists->inflight,
+                                  execlists->pending,
+                                  execlists_num_ports(execlists));
                        smp_wmb(); /* complete the seqlock */
                        WRITE_ONCE(execlists->active, execlists->inflight);
 
index 8fa9b31..f6d7e33 100644 (file)
@@ -368,6 +368,7 @@ void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu)
 static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
                struct intel_vgpu_creation_params *param)
 {
+       struct drm_i915_private *dev_priv = gvt->gt->i915;
        struct intel_vgpu *vgpu;
        int ret;
 
@@ -436,7 +437,10 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
        if (ret)
                goto out_clean_sched_policy;
 
-       ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D);
+       if (IS_BROADWELL(dev_priv))
+               ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_B);
+       else
+               ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D);
        if (ret)
                goto out_clean_sched_policy;
 
index 0b2fe55..781a678 100644 (file)
@@ -388,17 +388,38 @@ static bool __request_in_flight(const struct i915_request *signal)
         * As we know that there are always preemption points between
         * requests, we know that only the currently executing request
         * may be still active even though we have cleared the flag.
-        * However, we can't rely on our tracking of ELSP[0] to known
+        * However, we can't rely on our tracking of ELSP[0] to know
         * which request is currently active and so maybe stuck, as
         * the tracking maybe an event behind. Instead assume that
         * if the context is still inflight, then it is still active
         * even if the active flag has been cleared.
+        *
+        * To further complicate matters, if there a pending promotion, the HW
+        * may either perform a context switch to the second inflight execlists,
+        * or it may switch to the pending set of execlists. In the case of the
+        * latter, it may send the ACK and we process the event copying the
+        * pending[] over top of inflight[], _overwriting_ our *active. Since
+        * this implies the HW is arbitrating and not struck in *active, we do
+        * not worry about complete accuracy, but we do require no read/write
+        * tearing of the pointer [the read of the pointer must be valid, even
+        * as the array is being overwritten, for which we require the writes
+        * to avoid tearing.]
+        *
+        * Note that the read of *execlists->active may race with the promotion
+        * of execlists->pending[] to execlists->inflight[], overwritting
+        * the value at *execlists->active. This is fine. The promotion implies
+        * that we received an ACK from the HW, and so the context is not
+        * stuck -- if we do not see ourselves in *active, the inflight status
+        * is valid. If instead we see ourselves being copied into *active,
+        * we are inflight and may signal the callback.
         */
        if (!intel_context_inflight(signal->context))
                return false;
 
        rcu_read_lock();
-       for (port = __engine_active(signal->engine); (rq = *port); port++) {
+       for (port = __engine_active(signal->engine);
+            (rq = READ_ONCE(*port)); /* may race with promotion of pending[] */
+            port++) {
                if (rq->context == signal->context) {
                        inflight = i915_seqno_passed(rq->fence.seqno,
                                                     signal->fence.seqno);
index 295b982..4cd2038 100644 (file)
@@ -164,9 +164,13 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
 
                do {
                        list_for_each_entry_safe(pos, next, &x->head, entry) {
-                               pos->func(pos,
-                                         TASK_NORMAL, fence->error,
-                                         &extra);
+                               int wake_flags;
+
+                               wake_flags = fence->error;
+                               if (pos->func == autoremove_wake_function)
+                                       wake_flags = 0;
+
+                               pos->func(pos, TASK_NORMAL, wake_flags, &extra);
                        }
 
                        if (list_empty(&extra))
index f127e63..397c313 100644 (file)
@@ -118,11 +118,11 @@ static struct dev_pm_domain pm_domain = {
 
 struct drm_i915_private *mock_gem_device(void)
 {
-       struct drm_i915_private *i915;
-       struct pci_dev *pdev;
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
-       struct dev_iommu iommu;
+       static struct dev_iommu fake_iommu = { .priv = (void *)-1 };
 #endif
+       struct drm_i915_private *i915;
+       struct pci_dev *pdev;
        int err;
 
        pdev = kzalloc(sizeof(*pdev), GFP_KERNEL);
@@ -141,10 +141,8 @@ struct drm_i915_private *mock_gem_device(void)
        dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 
 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
-       /* HACK HACK HACK to disable iommu for the fake device; force identity mapping */
-       memset(&iommu, 0, sizeof(iommu));
-       iommu.priv = (void *)-1;
-       pdev->dev.iommu = &iommu;
+       /* HACK to disable iommu for the fake device; force identity mapping */
+       pdev->dev.iommu = &fake_iommu;
 #endif
 
        pci_set_drvdata(pdev, i915);
index ada990a..b707416 100644 (file)
@@ -673,7 +673,7 @@ static void ingenic_drm_unbind_all(void *d)
        component_unbind_all(priv->dev, &priv->drm);
 }
 
-static int ingenic_drm_bind(struct device *dev)
+static int ingenic_drm_bind(struct device *dev, bool has_components)
 {
        struct platform_device *pdev = to_platform_device(dev);
        const struct jz_soc_info *soc_info;
@@ -808,7 +808,7 @@ static int ingenic_drm_bind(struct device *dev)
                        return ret;
                }
 
-               if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) {
+               if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) {
                        ret = component_bind_all(dev, drm);
                        if (ret) {
                                if (ret != -EPROBE_DEFER)
@@ -939,6 +939,11 @@ err_pixclk_disable:
        return ret;
 }
 
+static int ingenic_drm_bind_with_components(struct device *dev)
+{
+       return ingenic_drm_bind(dev, true);
+}
+
 static int compare_of(struct device *dev, void *data)
 {
        return dev->of_node == data;
@@ -957,7 +962,7 @@ static void ingenic_drm_unbind(struct device *dev)
 }
 
 static const struct component_master_ops ingenic_master_ops = {
-       .bind = ingenic_drm_bind,
+       .bind = ingenic_drm_bind_with_components,
        .unbind = ingenic_drm_unbind,
 };
 
@@ -968,16 +973,15 @@ static int ingenic_drm_probe(struct platform_device *pdev)
        struct device_node *np;
 
        if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
-               return ingenic_drm_bind(dev);
+               return ingenic_drm_bind(dev, false);
 
        /* IPU is at port address 8 */
        np = of_graph_get_remote_node(dev->of_node, 8, 0);
-       if (!np) {
-               dev_err(dev, "Unable to get IPU node\n");
-               return -EINVAL;
-       }
+       if (!np)
+               return ingenic_drm_bind(dev, false);
 
        drm_of_component_match_add(dev, &match, compare_of, np);
+       of_node_put(np);
 
        return component_master_add_with_match(dev, &ingenic_master_ops, match);
 }
index 3fc5511..4d29568 100644 (file)
@@ -831,13 +831,19 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
                        drm_crtc_index(&mtk_crtc->base));
                mtk_crtc->cmdq_client = NULL;
        }
-       ret = of_property_read_u32_index(priv->mutex_node,
-                                        "mediatek,gce-events",
-                                        drm_crtc_index(&mtk_crtc->base),
-                                        &mtk_crtc->cmdq_event);
-       if (ret)
-               dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
-                       drm_crtc_index(&mtk_crtc->base));
+
+       if (mtk_crtc->cmdq_client) {
+               ret = of_property_read_u32_index(priv->mutex_node,
+                                                "mediatek,gce-events",
+                                                drm_crtc_index(&mtk_crtc->base),
+                                                &mtk_crtc->cmdq_event);
+               if (ret) {
+                       dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
+                               drm_crtc_index(&mtk_crtc->base));
+                       cmdq_mbox_destroy(mtk_crtc->cmdq_client);
+                       mtk_crtc->cmdq_client = NULL;
+               }
+       }
 #endif
        return 0;
 }
index 57c88de..5266488 100644 (file)
@@ -496,6 +496,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        if (of_address_to_resource(node, 0, &res) != 0) {
                dev_err(dev, "Missing reg in %s node\n", node->full_name);
+               put_device(&larb_pdev->dev);
                return -EINVAL;
        }
        comp->regs_pa = res.start;
index 040a8f3..2d98274 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "mtk_drm_crtc.h"
 #include "mtk_drm_ddp.h"
-#include "mtk_drm_ddp.h"
 #include "mtk_drm_ddp_comp.h"
 #include "mtk_drm_drv.h"
 #include "mtk_drm_gem.h"
@@ -165,7 +164,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 
        ret = drmm_mode_config_init(drm);
        if (ret)
-               return ret;
+               goto put_mutex_dev;
 
        drm->mode_config.min_width = 64;
        drm->mode_config.min_height = 64;
@@ -182,7 +181,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 
        ret = component_bind_all(drm->dev, drm);
        if (ret)
-               return ret;
+               goto put_mutex_dev;
 
        /*
         * We currently support two fixed data streams, each optional,
@@ -229,7 +228,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        }
        if (!dma_dev->dma_parms) {
                ret = -ENOMEM;
-               goto err_component_unbind;
+               goto put_dma_dev;
        }
 
        ret = dma_set_max_seg_size(dma_dev, (unsigned int)DMA_BIT_MASK(32));
@@ -256,9 +255,12 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 err_unset_dma_parms:
        if (private->dma_parms_allocated)
                dma_dev->dma_parms = NULL;
+put_dma_dev:
+       put_device(private->dma_dev);
 err_component_unbind:
        component_unbind_all(drm->dev, drm);
-
+put_mutex_dev:
+       put_device(private->mutex_dev);
        return ret;
 }
 
@@ -544,8 +546,13 @@ err_pm:
        pm_runtime_disable(dev);
 err_node:
        of_node_put(private->mutex_node);
-       for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
+       for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) {
                of_node_put(private->comp_node[i]);
+               if (private->ddp_comp[i]) {
+                       put_device(private->ddp_comp[i]->larb_dev);
+                       private->ddp_comp[i] = NULL;
+               }
+       }
        return ret;
 }
 
index 16fd99d..80b7a08 100644 (file)
@@ -466,14 +466,13 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
        horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
 
        if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-               horizontal_backporch_byte =
-                       (vm->hback_porch * dsi_tmp_buf_bpp - 10);
+               horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp;
        else
-               horizontal_backporch_byte = ((vm->hback_porch + vm->hsync_len) *
-                       dsi_tmp_buf_bpp - 10);
+               horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) *
+                                           dsi_tmp_buf_bpp;
 
        data_phy_cycles = timing->lpx + timing->da_hs_prepare +
-                         timing->da_hs_zero + timing->da_hs_exit + 3;
+                         timing->da_hs_zero + timing->da_hs_exit;
 
        if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
                if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp >
index f2e9b42..a977256 100644 (file)
@@ -1507,25 +1507,30 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
                dev_err(dev,
                        "Failed to get system configuration registers: %d\n",
                        ret);
-               return ret;
+               goto put_device;
        }
        hdmi->sys_regmap = regmap;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        hdmi->regs = devm_ioremap_resource(dev, mem);
-       if (IS_ERR(hdmi->regs))
-               return PTR_ERR(hdmi->regs);
+       if (IS_ERR(hdmi->regs)) {
+               ret = PTR_ERR(hdmi->regs);
+               goto put_device;
+       }
 
        remote = of_graph_get_remote_node(np, 1, 0);
-       if (!remote)
-               return -EINVAL;
+       if (!remote) {
+               ret = -EINVAL;
+               goto put_device;
+       }
 
        if (!of_device_is_compatible(remote, "hdmi-connector")) {
                hdmi->next_bridge = of_drm_find_bridge(remote);
                if (!hdmi->next_bridge) {
                        dev_err(dev, "Waiting for external bridge\n");
                        of_node_put(remote);
-                       return -EPROBE_DEFER;
+                       ret = -EPROBE_DEFER;
+                       goto put_device;
                }
        }
 
@@ -1534,7 +1539,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
                dev_err(dev, "Failed to find ddc-i2c-bus node in %pOF\n",
                        remote);
                of_node_put(remote);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto put_device;
        }
        of_node_put(remote);
 
@@ -1542,10 +1548,14 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
        of_node_put(i2c_np);
        if (!hdmi->ddc_adpt) {
                dev_err(dev, "Failed to get ddc i2c adapter by node\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto put_device;
        }
 
        return 0;
+put_device:
+       put_device(hdmi->cec_dev);
+       return ret;
 }
 
 /*
index 6021f8d..48fa49f 100644 (file)
@@ -164,6 +164,11 @@ static int a2xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                return ret;
 
+       gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
+               MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+       gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
+
        /* NOTE: PM4/micro-engine firmware registers look to be the same
         * for a2xx and a3xx.. we could possibly push that part down to
         * adreno_gpu base class.  Or push both PM4 and PFP but
index 0a5ea9f..f647114 100644 (file)
@@ -211,6 +211,16 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                return ret;
 
+       /*
+        * Use the default ringbuffer size and block size but disable the RPTR
+        * shadow
+        */
+       gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
+               MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+       /* Set the ringbuffer address */
+       gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
+
        /* setup access protection: */
        gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
 
index b9b26b2..9547536 100644 (file)
@@ -267,6 +267,16 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                return ret;
 
+       /*
+        * Use the default ringbuffer size and block size but disable the RPTR
+        * shadow
+        */
+       gpu_write(gpu, REG_A4XX_CP_RB_CNTL,
+               MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+       /* Set the ringbuffer address */
+       gpu_write(gpu, REG_A4XX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
+
        /* Load PM4: */
        ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
        len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
index 84a5d9c..91726da 100644 (file)
@@ -703,8 +703,6 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                return ret;
 
-       a5xx_preempt_hw_init(gpu);
-
        if (!adreno_is_a510(adreno_gpu))
                a5xx_gpmu_ucode_init(gpu);
 
@@ -712,6 +710,15 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                return ret;
 
+       /* Set the ringbuffer address */
+       gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI,
+               gpu->rb[0]->iova);
+
+       gpu_write(gpu, REG_A5XX_CP_RB_CNTL,
+               MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+       a5xx_preempt_hw_init(gpu);
+
        /* Disable the interrupts through the initial bringup stage */
        gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
 
@@ -1511,7 +1518,8 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
 
        check_speed_bin(&pdev->dev);
 
-       ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4);
+       /* Restricting nr_rings to 1 to temporarily disable preemption */
+       ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
        if (ret) {
                a5xx_destroy(&(a5xx_gpu->base.base));
                return ERR_PTR(ret);
index 54868d4..1e5b1a1 100644 (file)
@@ -31,6 +31,7 @@ struct a5xx_gpu {
        struct msm_ringbuffer *next_ring;
 
        struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS];
+       struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS];
        struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS];
        uint64_t preempt_iova[MSM_GPU_MAX_RINGS];
 
index 9cf9353..9f3fe17 100644 (file)
@@ -226,19 +226,31 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
        struct adreno_gpu *adreno_gpu = &a5xx_gpu->base;
        struct msm_gpu *gpu = &adreno_gpu->base;
        struct a5xx_preempt_record *ptr;
-       struct drm_gem_object *bo = NULL;
-       u64 iova = 0;
+       void *counters;
+       struct drm_gem_object *bo = NULL, *counters_bo = NULL;
+       u64 iova = 0, counters_iova = 0;
 
        ptr = msm_gem_kernel_new(gpu->dev,
                A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE,
-               MSM_BO_UNCACHED, gpu->aspace, &bo, &iova);
+               MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova);
 
        if (IS_ERR(ptr))
                return PTR_ERR(ptr);
 
+       /* The buffer to store counters needs to be unprivileged */
+       counters = msm_gem_kernel_new(gpu->dev,
+               A5XX_PREEMPT_COUNTER_SIZE,
+               MSM_BO_UNCACHED, gpu->aspace, &counters_bo, &counters_iova);
+       if (IS_ERR(counters)) {
+               msm_gem_kernel_put(bo, gpu->aspace, true);
+               return PTR_ERR(counters);
+       }
+
        msm_gem_object_set_name(bo, "preempt");
+       msm_gem_object_set_name(counters_bo, "preempt_counters");
 
        a5xx_gpu->preempt_bo[ring->id] = bo;
+       a5xx_gpu->preempt_counters_bo[ring->id] = counters_bo;
        a5xx_gpu->preempt_iova[ring->id] = iova;
        a5xx_gpu->preempt[ring->id] = ptr;
 
@@ -249,7 +261,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
        ptr->data = 0;
        ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
        ptr->rptr_addr = rbmemptr(ring, rptr);
-       ptr->counter = iova + A5XX_PREEMPT_RECORD_SIZE;
+       ptr->counter = counters_iova;
 
        return 0;
 }
@@ -260,8 +272,11 @@ void a5xx_preempt_fini(struct msm_gpu *gpu)
        struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
        int i;
 
-       for (i = 0; i < gpu->nr_rings; i++)
+       for (i = 0; i < gpu->nr_rings; i++) {
                msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace, true);
+               msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i],
+                       gpu->aspace, true);
+       }
 }
 
 void a5xx_preempt_init(struct msm_gpu *gpu)
index 3966abd..66a95e2 100644 (file)
@@ -678,7 +678,8 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
                        A6XX_PROTECT_RDONLY(0x980, 0x4));
        gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0));
 
-       if (adreno_is_a650(adreno_gpu)) {
+       /* Enable expanded apriv for targets that support it */
+       if (gpu->hw_apriv) {
                gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL,
                        (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1));
        }
@@ -694,6 +695,13 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                goto out;
 
+       /* Set the ringbuffer address */
+       gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI,
+               gpu->rb[0]->iova);
+
+       gpu_write(gpu, REG_A6XX_CP_RB_CNTL,
+               MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
        /* Always come up on rb 0 */
        a6xx_gpu->cur_ring = gpu->rb[0];
 
@@ -1056,6 +1064,9 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
        adreno_gpu->registers = NULL;
        adreno_gpu->reg_offsets = a6xx_register_offsets;
 
+       if (adreno_is_a650(adreno_gpu))
+               adreno_gpu->base.hw_apriv = true;
+
        ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
        if (ret) {
                a6xx_destroy(&(a6xx_gpu->base.base));
index 288141f..862dd35 100644 (file)
@@ -400,26 +400,6 @@ int adreno_hw_init(struct msm_gpu *gpu)
                ring->memptrs->rptr = 0;
        }
 
-       /*
-        * Setup REG_CP_RB_CNTL.  The same value is used across targets (with
-        * the excpetion of A430 that disables the RPTR shadow) - the cacluation
-        * for the ringbuffer size and block size is moved to msm_gpu.h for the
-        * pre-processor to deal with and the A430 variant is ORed in here
-        */
-       adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_CNTL,
-               MSM_GPU_RB_CNTL_DEFAULT |
-               (adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0));
-
-       /* Setup ringbuffer address - use ringbuffer[0] for GPU init */
-       adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE,
-               REG_ADRENO_CP_RB_BASE_HI, gpu->rb[0]->iova);
-
-       if (!adreno_is_a430(adreno_gpu)) {
-               adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
-                       REG_ADRENO_CP_RB_RPTR_ADDR_HI,
-                       rbmemptr(gpu->rb[0], rptr));
-       }
-
        return 0;
 }
 
@@ -427,11 +407,8 @@ int adreno_hw_init(struct msm_gpu *gpu)
 static uint32_t get_rptr(struct adreno_gpu *adreno_gpu,
                struct msm_ringbuffer *ring)
 {
-       if (adreno_is_a430(adreno_gpu))
-               return ring->memptrs->rptr = adreno_gpu_read(
-                       adreno_gpu, REG_ADRENO_CP_RB_RPTR);
-       else
-               return ring->memptrs->rptr;
+       return ring->memptrs->rptr = adreno_gpu_read(
+               adreno_gpu, REG_ADRENO_CP_RB_RPTR);
 }
 
 struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu)
index d564547..57ddc94 100644 (file)
@@ -908,7 +908,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 
        memptrs = msm_gem_kernel_new(drm,
                sizeof(struct msm_rbmemptrs) * nr_rings,
-               MSM_BO_UNCACHED, gpu->aspace, &gpu->memptrs_bo,
+               check_apriv(gpu, MSM_BO_UNCACHED), gpu->aspace, &gpu->memptrs_bo,
                &memptrs_iova);
 
        if (IS_ERR(memptrs)) {
index 0db117a..37cffac 100644 (file)
@@ -15,6 +15,7 @@
 #include "msm_drv.h"
 #include "msm_fence.h"
 #include "msm_ringbuffer.h"
+#include "msm_gem.h"
 
 struct msm_gem_submit;
 struct msm_gpu_perfcntr;
@@ -139,6 +140,8 @@ struct msm_gpu {
        } devfreq;
 
        struct msm_gpu_state *crashstate;
+       /* True if the hardware supports expanded apriv (a650 and newer) */
+       bool hw_apriv;
 };
 
 /* It turns out that all targets use the same ringbuffer size */
@@ -327,4 +330,12 @@ static inline void msm_gpu_crashstate_put(struct msm_gpu *gpu)
        mutex_unlock(&gpu->dev->struct_mutex);
 }
 
+/*
+ * Simple macro to semi-cleanly add the MAP_PRIV flag for targets that can
+ * support expanded privileges
+ */
+#define check_apriv(gpu, flags) \
+       (((gpu)->hw_apriv ? MSM_BO_MAP_PRIV : 0) | (flags))
+
+
 #endif /* __MSM_GPU_H__ */
index 39ecb5a..935bf9b 100644 (file)
@@ -27,8 +27,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
        ring->id = id;
 
        ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ,
-               MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &ring->bo,
-               &ring->iova);
+               check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY),
+               gpu->aspace, &ring->bo, &ring->iova);
 
        if (IS_ERR(ring->start)) {
                ret = PTR_ERR(ring->start);
index b1bb542..e5fae57 100644 (file)
@@ -176,6 +176,8 @@ void
 nouveau_mem_del(struct ttm_mem_reg *reg)
 {
        struct nouveau_mem *mem = nouveau_mem(reg);
+       if (!mem)
+               return;
        nouveau_mem_fini(mem);
        kfree(reg->mm_node);
        reg->mm_node = NULL;
index 9f4ac26..dcb7067 100644 (file)
@@ -3149,6 +3149,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x168: device->chip = &nv168_chipset; break;
                default:
                        nvdev_error(device, "unknown chipset (%08x)\n", boot0);
+                       ret = -ENODEV;
                        goto done;
                }
 
index 7b69d6d..e0ae911 100644 (file)
@@ -933,7 +933,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
 
        /* get matching reference and feedback divider */
        *ref_div = min(max(den/post_div, 1u), ref_div_max);
-       *fb_div = max(nom * *ref_div * post_div / den, 1u);
+       *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den);
 
        /* limit fb divider to its maximum */
        if (*fb_div > fb_div_max) {
index 072ea11..ed5d866 100644 (file)
@@ -589,8 +589,7 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
 
        /* We can't have an alpha plane at the lowest position */
        if (!backend->quirks->supports_lowest_plane_alpha &&
-           (plane_states[0]->fb->format->has_alpha ||
-           (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE)))
+           (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE))
                return -EINVAL;
 
        for (i = 1; i < num_planes; i++) {
@@ -995,7 +994,6 @@ static const struct sun4i_backend_quirks sun6i_backend_quirks = {
 
 static const struct sun4i_backend_quirks sun7i_backend_quirks = {
        .needs_output_muxing = true,
-       .supports_lowest_plane_alpha = true,
 };
 
 static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = {
index ced9a82..e40c542 100644 (file)
@@ -1433,14 +1433,18 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
        if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
            encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
                ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
-               if (ret)
+               if (ret) {
+                       put_device(&pdev->dev);
                        return ret;
+               }
        }
 
        if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
                ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
-               if (ret)
+               if (ret) {
+                       put_device(&pdev->dev);
                        return ret;
+               }
        }
 
        return 0;
index 7f13f4d..de8a11a 100644 (file)
@@ -889,7 +889,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
        regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
                     sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
 
-       bounce = kzalloc(msg->tx_len + sizeof(crc), GFP_KERNEL);
+       bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL);
        if (!bounce)
                return -ENOMEM;
 
@@ -900,7 +900,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
        memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc));
        len += sizeof(crc);
 
-       regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, len);
+       regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4));
        regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1);
        kfree(bounce);
 
index f42441b..a55a38a 100644 (file)
@@ -12,7 +12,7 @@ struct sun8i_mixer;
 
 /* VI channel CSC units offsets */
 #define CCSC00_OFFSET 0xAA050
-#define CCSC01_OFFSET 0xFA000
+#define CCSC01_OFFSET 0xFA050
 #define CCSC10_OFFSET 0xA0000
 #define CCSC11_OFFSET 0xF0000
 
index cc4fb91..c330402 100644 (file)
@@ -307,7 +307,7 @@ static struct regmap_config sun8i_mixer_regmap_config = {
        .reg_bits       = 32,
        .val_bits       = 32,
        .reg_stride     = 4,
-       .max_register   = 0xbfffc, /* guessed */
+       .max_register   = 0xffffc, /* guessed */
 };
 
 static int sun8i_mixer_of_get_id(struct device_node *node)
index 22c8c53..c0147af 100644 (file)
@@ -211,7 +211,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
        return 0;
 }
 
-static bool sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
+static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format)
 {
        if (!format->is_yuv)
                return SUN8I_CSC_MODE_OFF;
index d733bbc..17ff24d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/version.h>
 #include <linux/dma-buf.h>
 #include <linux/of_graph.h>
+#include <linux/delay.h>
 
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
@@ -130,9 +131,25 @@ static void tve200_display_enable(struct drm_simple_display_pipe *pipe,
        struct drm_connector *connector = priv->connector;
        u32 format = fb->format->format;
        u32 ctrl1 = 0;
+       int retries;
 
        clk_prepare_enable(priv->clk);
 
+       /* Reset the TVE200 and wait for it to come back online */
+       writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
+       for (retries = 0; retries < 5; retries++) {
+               usleep_range(30000, 50000);
+               if (readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET)
+                       continue;
+               else
+                       break;
+       }
+       if (retries == 5 &&
+           readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) {
+               dev_err(drm->dev, "can't get hardware out of reset\n");
+               return;
+       }
+
        /* Function 1 */
        ctrl1 |= TVE200_CTRL_CSMODE;
        /* Interlace mode for CCIR656: parameterize? */
@@ -230,8 +247,9 @@ static void tve200_display_disable(struct drm_simple_display_pipe *pipe)
 
        drm_crtc_vblank_off(crtc);
 
-       /* Disable and Power Down */
+       /* Disable put into reset and Power Down */
        writel(0, priv->regs + TVE200_CTRL);
+       writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
 
        clk_disable_unprepare(priv->clk);
 }
@@ -279,6 +297,8 @@ static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe)
        struct drm_device *drm = crtc->dev;
        struct tve200_drm_dev_private *priv = drm->dev_private;
 
+       /* Clear any IRQs and enable */
+       writel(0xFF, priv->regs + TVE200_INT_CLR);
        writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
        return 0;
 }
index 15a11cd..6339c6f 100644 (file)
@@ -1117,6 +1117,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
        card->num_links = 1;
        card->name = "vc4-hdmi";
        card->dev = dev;
+       card->owner = THIS_MODULE;
 
        /*
         * Be careful, snd_soc_register_card() calls dev_set_drvdata() and
index af55b33..afd0f92 100644 (file)
@@ -97,9 +97,6 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc)
 static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc,
                                          struct drm_crtc_state *old_state)
 {
-       struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc);
-
-       output->enabled = true;
 }
 
 static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc,
@@ -111,7 +108,6 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc,
 
        virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0);
        virtio_gpu_notify(vgdev);
-       output->enabled = false;
 }
 
 static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc,
@@ -123,6 +119,17 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc,
 static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc,
                                         struct drm_crtc_state *old_state)
 {
+       struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc);
+
+       /*
+        * virtio-gpu can't do modeset and plane update operations
+        * independent from each other.  So the actual modeset happens
+        * in the plane update callback, and here we just check
+        * whenever we must force the modeset.
+        */
+       if (drm_atomic_crtc_needs_modeset(crtc->state)) {
+               output->needs_modeset = true;
+       }
 }
 
 static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = {
index 9ff9f4a..fbc0427 100644 (file)
@@ -137,7 +137,7 @@ struct virtio_gpu_output {
        struct edid *edid;
        int cur_x;
        int cur_y;
-       bool enabled;
+       bool needs_modeset;
 };
 #define drm_crtc_to_virtio_gpu_output(x) \
        container_of(x, struct virtio_gpu_output, crtc)
index e83651b..842f8b6 100644 (file)
@@ -151,7 +151,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
        if (ret < 0)
                return -EINVAL;
 
-       shmem->pages = drm_gem_shmem_get_pages_sgt(&bo->base.base);
+       /*
+        * virtio_gpu uses drm_gem_shmem_get_sg_table instead of
+        * drm_gem_shmem_get_pages_sgt because virtio has it's own set of
+        * dma-ops. This is discouraged for other drivers, but should be fine
+        * since virtio_gpu doesn't support dma-buf import from other devices.
+        */
+       shmem->pages = drm_gem_shmem_get_sg_table(&bo->base.base);
        if (!shmem->pages) {
                drm_gem_shmem_unpin(&bo->base.base);
                return -EINVAL;
index 52d2417..6a311cd 100644 (file)
@@ -142,7 +142,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
        if (WARN_ON(!output))
                return;
 
-       if (!plane->state->fb || !output->enabled) {
+       if (!plane->state->fb || !output->crtc.state->active) {
                DRM_DEBUG("nofb\n");
                virtio_gpu_cmd_set_scanout(vgdev, output->index, 0,
                                           plane->state->src_w >> 16,
@@ -163,7 +163,9 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane,
            plane->state->src_w != old_state->src_w ||
            plane->state->src_h != old_state->src_h ||
            plane->state->src_x != old_state->src_x ||
-           plane->state->src_y != old_state->src_y) {
+           plane->state->src_y != old_state->src_y ||
+           output->needs_modeset) {
+               output->needs_modeset = false;
                DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n",
                          bo->hw_res_handle,
                          plane->state->crtc_w, plane->state->crtc_h,
index 4a76fc7..f8bdd4e 100644 (file)
@@ -55,7 +55,7 @@ static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
 
        id = ida_alloc_max(&gman->gmr_ida, gman->max_gmr_ids - 1, GFP_KERNEL);
        if (id < 0)
-               return (id != -ENOMEM ? 0 : id);
+               return id;
 
        spin_lock(&gman->lock);
 
index b7c816b..c8b9335 100644 (file)
@@ -95,7 +95,7 @@ found_unlock:
                mem->start = node->start;
        }
 
-       return 0;
+       return ret;
 }
 
 
index aa6cd88..b52c6cd 100644 (file)
@@ -2,6 +2,7 @@ config DRM_ZYNQMP_DPSUB
        tristate "ZynqMP DisplayPort Controller Driver"
        depends on ARCH_ZYNQMP || COMPILE_TEST
        depends on COMMON_CLK && DRM && OF
+       depends on DMADEVICES
        select DMA_ENGINE
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_CMA_HELPER
index 591106c..1d44bb6 100644 (file)
@@ -731,7 +731,7 @@ static void vmbus_wait_for_unload(void)
        void *page_addr;
        struct hv_message *msg;
        struct vmbus_channel_message_header *hdr;
-       u32 message_type;
+       u32 message_type, i;
 
        /*
         * CHANNELMSG_UNLOAD_RESPONSE is always delivered to the CPU which was
@@ -741,8 +741,11 @@ static void vmbus_wait_for_unload(void)
         * functional and vmbus_unload_response() will complete
         * vmbus_connection.unload_event. If not, the last thing we can do is
         * read message pages for all CPUs directly.
+        *
+        * Wait no more than 10 seconds so that the panic path can't get
+        * hung forever in case the response message isn't seen.
         */
-       while (1) {
+       for (i = 0; i < 1000; i++) {
                if (completion_done(&vmbus_connection.unload_event))
                        break;
 
index 910b6e9..946d0ab 100644 (file)
@@ -2382,7 +2382,10 @@ static int vmbus_bus_suspend(struct device *dev)
        if (atomic_read(&vmbus_connection.nr_chan_close_on_suspend) > 0)
                wait_for_completion(&vmbus_connection.ready_for_suspend_event);
 
-       WARN_ON(atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0);
+       if (atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0) {
+               pr_err("Can not suspend due to a previous failed resuming\n");
+               return -EBUSY;
+       }
 
        mutex_lock(&vmbus_connection.channel_mutex);
 
@@ -2456,7 +2459,9 @@ static int vmbus_bus_resume(struct device *dev)
 
        vmbus_request_offers();
 
-       wait_for_completion(&vmbus_connection.ready_for_resume_event);
+       if (wait_for_completion_timeout(
+               &vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
+               pr_err("Some vmbus device is missing after suspending?\n");
 
        /* Reset the event for the next suspend. */
        reinit_completion(&vmbus_connection.ready_for_suspend_event);
index 710fbef..384af88 100644 (file)
@@ -41,8 +41,22 @@ static void pca_reset(struct i2c_algo_pca_data *adap)
                pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
                pca_outw(adap, I2C_PCA_IND, 0xA5);
                pca_outw(adap, I2C_PCA_IND, 0x5A);
+
+               /*
+                * After a reset we need to re-apply any configuration
+                * (calculated in pca_init) to get the bus in a working state.
+                */
+               pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IMODE);
+               pca_outw(adap, I2C_PCA_IND, adap->bus_settings.mode);
+               pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_ISCLL);
+               pca_outw(adap, I2C_PCA_IND, adap->bus_settings.tlow);
+               pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_ISCLH);
+               pca_outw(adap, I2C_PCA_IND, adap->bus_settings.thi);
+
+               pca_set_con(adap, I2C_PCA_CON_ENSIO);
        } else {
                adap->reset_chip(adap->data);
+               pca_set_con(adap, I2C_PCA_CON_ENSIO | adap->bus_settings.clock_freq);
        }
 }
 
@@ -423,13 +437,14 @@ static int pca_init(struct i2c_adapter *adap)
                                " Use the nominal frequency.\n", adap->name);
                }
 
-               pca_reset(pca_data);
-
                clock = pca_clock(pca_data);
                printk(KERN_INFO "%s: Clock frequency is %dkHz\n",
                     adap->name, freqs[clock]);
 
-               pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
+               /* Store settings as these will be needed when the PCA chip is reset */
+               pca_data->bus_settings.clock_freq = clock;
+
+               pca_reset(pca_data);
        } else {
                int clock;
                int mode;
@@ -496,19 +511,15 @@ static int pca_init(struct i2c_adapter *adap)
                        thi = tlow * min_thi / min_tlow;
                }
 
+               /* Store settings as these will be needed when the PCA chip is reset */
+               pca_data->bus_settings.mode = mode;
+               pca_data->bus_settings.tlow = tlow;
+               pca_data->bus_settings.thi = thi;
+
                pca_reset(pca_data);
 
                printk(KERN_INFO
                     "%s: Clock frequency is %dHz\n", adap->name, clock * 100);
-
-               pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE);
-               pca_outw(pca_data, I2C_PCA_IND, mode);
-               pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL);
-               pca_outw(pca_data, I2C_PCA_IND, tlow);
-               pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH);
-               pca_outw(pca_data, I2C_PCA_IND, thi);
-
-               pca_set_con(pca_data, I2C_PCA_CON_ENSIO);
        }
        udelay(500); /* 500 us for oscillator to stabilise */
 
index 3126807..724bf30 100644 (file)
@@ -69,6 +69,7 @@
  * These share bit definitions, so use the same values for the enable &
  * status bits.
  */
+#define ASPEED_I2CD_INTR_RECV_MASK                     0xf000ffff
 #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT                        BIT(14)
 #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE              BIT(13)
 #define ASPEED_I2CD_INTR_SLAVE_MATCH                   BIT(7)
@@ -604,6 +605,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
        writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
               bus->base + ASPEED_I2C_INTR_STS_REG);
        readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+       irq_received &= ASPEED_I2CD_INTR_RECV_MASK;
        irq_remaining = irq_received;
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
index 1213e19..24d584a 100644 (file)
@@ -65,6 +65,9 @@ struct i2c_ram {
        char    res1[4];        /* Reserved */
        ushort  rpbase;         /* Relocation pointer */
        char    res2[2];        /* Reserved */
+       /* The following elements are only for CPM2 */
+       char    res3[4];        /* Reserved */
+       uint    sdmatmp;        /* Internal */
 };
 
 #define I2COM_START    0x80
index e32ef3f..bffca72 100644 (file)
@@ -1709,6 +1709,16 @@ static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
 static inline void i801_acpi_remove(struct i801_priv *priv) { }
 #endif
 
+static unsigned char i801_setup_hstcfg(struct i801_priv *priv)
+{
+       unsigned char hstcfg = priv->original_hstcfg;
+
+       hstcfg &= ~SMBHSTCFG_I2C_EN;    /* SMBus timing */
+       hstcfg |= SMBHSTCFG_HST_EN;
+       pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
+       return hstcfg;
+}
+
 static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        unsigned char temp;
@@ -1830,14 +1840,10 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return err;
        }
 
-       pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
-       priv->original_hstcfg = temp;
-       temp &= ~SMBHSTCFG_I2C_EN;      /* SMBus timing */
-       if (!(temp & SMBHSTCFG_HST_EN)) {
+       pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg);
+       temp = i801_setup_hstcfg(priv);
+       if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN))
                dev_info(&dev->dev, "Enabling SMBus device\n");
-               temp |= SMBHSTCFG_HST_EN;
-       }
-       pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);
 
        if (temp & SMBHSTCFG_SMB_SMI_EN) {
                dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
@@ -1911,6 +1917,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        pci_set_drvdata(dev, priv);
 
+       dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
        pm_runtime_set_autosuspend_delay(&dev->dev, 1000);
        pm_runtime_use_autosuspend(&dev->dev);
        pm_runtime_put_autosuspend(&dev->dev);
@@ -1952,10 +1959,9 @@ static void i801_shutdown(struct pci_dev *dev)
 #ifdef CONFIG_PM_SLEEP
 static int i801_suspend(struct device *dev)
 {
-       struct pci_dev *pci_dev = to_pci_dev(dev);
-       struct i801_priv *priv = pci_get_drvdata(pci_dev);
+       struct i801_priv *priv = dev_get_drvdata(dev);
 
-       pci_write_config_byte(pci_dev, SMBHSTCFG, priv->original_hstcfg);
+       pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
        return 0;
 }
 
@@ -1963,6 +1969,7 @@ static int i801_resume(struct device *dev)
 {
        struct i801_priv *priv = dev_get_drvdata(dev);
 
+       i801_setup_hstcfg(priv);
        i801_enable_host_notify(&priv->adapter);
 
        return 0;
index efc1404..0cbdfbe 100644 (file)
@@ -681,8 +681,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
        unsigned int cnt_mul;
        int ret = -EINVAL;
 
-       if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ)
-               target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ;
+       if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ)
+               target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ;
 
        max_step_cnt = mtk_i2c_max_step_cnt(target_speed);
        base_step_cnt = max_step_cnt;
@@ -759,7 +759,7 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
        for (clk_div = 1; clk_div <= max_clk_div; clk_div++) {
                clk_src = parent_clk / clk_div;
 
-               if (target_speed > I2C_MAX_FAST_MODE_FREQ) {
+               if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
                        /* Set master code speed register */
                        ret = mtk_i2c_calculate_speed(i2c, clk_src,
                                                      I2C_MAX_FAST_MODE_FREQ,
index 9587347..c4b08a9 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/of_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/dma/mxs-dma.h>
 
 #define DRIVER_NAME "mxs-i2c"
 
@@ -200,7 +201,8 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
                                        DMA_MEM_TO_DEV,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                                       DMA_PREP_INTERRUPT |
+                                       MXS_DMA_CTRL_WAIT4END);
                if (!desc) {
                        dev_err(i2c->dev,
                                "Failed to get DMA data write descriptor.\n");
@@ -228,7 +230,8 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
                                        DMA_DEV_TO_MEM,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                                       DMA_PREP_INTERRUPT |
+                                       MXS_DMA_CTRL_WAIT4END);
                if (!desc) {
                        dev_err(i2c->dev,
                                "Failed to get DMA data write descriptor.\n");
@@ -260,7 +263,8 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
                                        DMA_MEM_TO_DEV,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                                       DMA_PREP_INTERRUPT |
+                                       MXS_DMA_CTRL_WAIT4END);
                if (!desc) {
                        dev_err(i2c->dev,
                                "Failed to get DMA data write descriptor.\n");
index 75f0713..2ad1663 100644 (file)
@@ -2093,8 +2093,12 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                }
        }
 
-       /* Adaptive TimeOut: astimated time in usec + 100% margin */
-       timeout_usec = (2 * 10000 / bus->bus_freq) * (2 + nread + nwrite);
+       /*
+        * Adaptive TimeOut: estimated time in usec + 100% margin:
+        * 2: double the timeout for clock stretching case
+        * 9: bits per transaction (including the ack/nack)
+        */
+       timeout_usec = (2 * 9 * USEC_PER_SEC / bus->bus_freq) * (2 + nread + nwrite);
        timeout = max(msecs_to_jiffies(35), usecs_to_jiffies(timeout_usec));
        if (nwrite >= 32 * 1024 || nread >= 32 * 1024) {
                dev_err(bus->dev, "i2c%d buffer too big\n", bus->num);
@@ -2159,6 +2163,15 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
        if (bus->cmd_err == -EAGAIN)
                ret = i2c_recover_bus(adap);
 
+       /*
+        * After any type of error, check if LAST bit is still set,
+        * due to a HW issue.
+        * It cannot be cleared without resetting the module.
+        */
+       if (bus->cmd_err &&
+           (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
+               npcm_i2c_reset(bus);
+
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
        /* reenable slave if it was enabled */
        if (bus->slave)
index 5ec082e..573b5da 100644 (file)
@@ -1464,8 +1464,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 
        /* create pre-declared device nodes */
        of_i2c_register_devices(adap);
-       i2c_acpi_register_devices(adap);
        i2c_acpi_install_space_handler(adap);
+       i2c_acpi_register_devices(adap);
 
        if (adap->nr < __i2c_first_dynamic_bus_num)
                i2c_scan_static_board_info(adap);
index 24864d9..4843586 100644 (file)
@@ -189,6 +189,14 @@ struct bmc150_accel_data {
        struct mutex mutex;
        u8 fifo_mode, watermark;
        s16 buffer[8];
+       /*
+        * Ensure there is sufficient space and correct alignment for
+        * the timestamp if enabled
+        */
+       struct {
+               __le16 channels[3];
+               s64 ts __aligned(8);
+       } scan;
        u8 bw_bits;
        u32 slope_dur;
        u32 slope_thres;
@@ -922,15 +930,16 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
         * now.
         */
        for (i = 0; i < count; i++) {
-               u16 sample[8];
                int j, bit;
 
                j = 0;
                for_each_set_bit(bit, indio_dev->active_scan_mask,
                                 indio_dev->masklength)
-                       memcpy(&sample[j++], &buffer[i * 3 + bit], 2);
+                       memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit],
+                              sizeof(data->scan.channels[0]));
 
-               iio_push_to_buffers_with_timestamp(indio_dev, sample, tstamp);
+               iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+                                                  tstamp);
 
                tstamp += sample_period;
        }
index 66b2e4c..0e18b92 100644 (file)
@@ -209,14 +209,20 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
        const struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct kxsd9_state *st = iio_priv(indio_dev);
+       /*
+        * Ensure correct positioning and alignment of timestamp.
+        * No need to zero initialize as all elements written.
+        */
+       struct {
+               __be16 chan[4];
+               s64 ts __aligned(8);
+       } hw_values;
        int ret;
-       /* 4 * 16bit values AND timestamp */
-       __be16 hw_values[8];
 
        ret = regmap_bulk_read(st->map,
                               KXSD9_REG_X,
-                              &hw_values,
-                              8);
+                              hw_values.chan,
+                              sizeof(hw_values.chan));
        if (ret) {
                dev_err(st->dev,
                        "error reading data\n");
@@ -224,7 +230,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
        }
 
        iio_push_to_buffers_with_timestamp(indio_dev,
-                                          hw_values,
+                                          &hw_values,
                                           iio_get_time_ns(indio_dev));
        iio_trigger_notify_done(indio_dev->trig);
 
index 7e99bcb..922bd38 100644 (file)
 
 struct mma7455_data {
        struct regmap *regmap;
+       /*
+        * Used to reorganize data.  Will ensure correct alignment of
+        * the timestamp if present
+        */
+       struct {
+               __le16 channels[3];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 static int mma7455_drdy(struct mma7455_data *mma7455)
@@ -82,19 +90,19 @@ static irqreturn_t mma7455_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct mma7455_data *mma7455 = iio_priv(indio_dev);
-       u8 buf[16]; /* 3 x 16-bit channels + padding + ts */
        int ret;
 
        ret = mma7455_drdy(mma7455);
        if (ret)
                goto done;
 
-       ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL, buf,
-                              sizeof(__le16) * 3);
+       ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL,
+                              mma7455->scan.channels,
+                              sizeof(mma7455->scan.channels));
        if (ret)
                goto done;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       iio_push_to_buffers_with_timestamp(indio_dev, &mma7455->scan,
                                           iio_get_time_ns(indio_dev));
 
 done:
index 4e6e702..853febc 100644 (file)
@@ -110,6 +110,12 @@ struct mma8452_data {
        int sleep_val;
        struct regulator *vdd_reg;
        struct regulator *vddio_reg;
+
+       /* Ensure correct alignment of time stamp when present */
+       struct {
+               __be16 channels[3];
+               s64 ts __aligned(8);
+       } buffer;
 };
 
  /**
@@ -1091,14 +1097,13 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct mma8452_data *data = iio_priv(indio_dev);
-       u8 buffer[16]; /* 3 16-bit channels + padding + ts */
        int ret;
 
-       ret = mma8452_read(data, (__be16 *)buffer);
+       ret = mma8452_read(data, data->buffer.channels);
        if (ret < 0)
                goto done;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
                                           iio_get_time_ns(indio_dev));
 
 done:
index 66d9cc0..d94dc80 100644 (file)
@@ -865,6 +865,8 @@ config ROCKCHIP_SARADC
        tristate "Rockchip SARADC driver"
        depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
        depends on RESET_CONTROLLER
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          Say yes here to build support for the SARADC found in SoCs from
          Rockchip.
index 8dce06e..766c733 100644 (file)
@@ -177,12 +177,12 @@ static const struct iio_chan_spec ad7124_channel_template = {
 
 static struct ad7124_chip_info ad7124_chip_info_tbl[] = {
        [ID_AD7124_4] = {
-               .name = "ad7127-4",
+               .name = "ad7124-4",
                .chip_id = CHIPID_AD7124_4,
                .num_inputs = 8,
        },
        [ID_AD7124_8] = {
-               .name = "ad7127-8",
+               .name = "ad7124-8",
                .chip_id = CHIPID_AD7124_8,
                .num_inputs = 16,
        },
index 5ed63e8..b573ec6 100644 (file)
@@ -146,6 +146,11 @@ struct ina2xx_chip_info {
        int range_vbus; /* Bus voltage maximum in V */
        int pga_gain_vshunt; /* Shunt voltage PGA gain */
        bool allow_async_readout;
+       /* data buffer needs space for channel data and timestamp */
+       struct {
+               u16 chan[4];
+               u64 ts __aligned(8);
+       } scan;
 };
 
 static const struct ina2xx_config ina2xx_config[] = {
@@ -738,8 +743,6 @@ static int ina2xx_conversion_ready(struct iio_dev *indio_dev)
 static int ina2xx_work_buffer(struct iio_dev *indio_dev)
 {
        struct ina2xx_chip_info *chip = iio_priv(indio_dev);
-       /* data buffer needs space for channel data and timestap */
-       unsigned short data[4 + sizeof(s64)/sizeof(short)];
        int bit, ret, i = 0;
        s64 time;
 
@@ -758,10 +761,10 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
                if (ret < 0)
                        return ret;
 
-               data[i++] = val;
+               chip->scan.chan[i++] = val;
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, data, time);
+       iio_push_to_buffers_with_timestamp(indio_dev, &chip->scan, time);
 
        return 0;
 };
index 01b20e4..6efb0b4 100644 (file)
@@ -36,6 +36,11 @@ struct max1118 {
        struct spi_device *spi;
        struct mutex lock;
        struct regulator *reg;
+       /* Ensure natural alignment of buffer elements */
+       struct {
+               u8 channels[2];
+               s64 ts __aligned(8);
+       } scan;
 
        u8 data ____cacheline_aligned;
 };
@@ -166,7 +171,6 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct max1118 *adc = iio_priv(indio_dev);
-       u8 data[16] = { }; /* 2x 8-bit ADC data + padding + 8 bytes timestamp */
        int scan_index;
        int i = 0;
 
@@ -184,10 +188,10 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p)
                        goto out;
                }
 
-               data[i] = ret;
+               adc->scan.channels[i] = ret;
                i++;
        }
-       iio_push_to_buffers_with_timestamp(indio_dev, data,
+       iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan,
                                           iio_get_time_ns(indio_dev));
 out:
        mutex_unlock(&adc->lock);
index 5f1706d..da353dc 100644 (file)
@@ -96,16 +96,12 @@ static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig)
 {
        int ret;
 
-       mutex_lock(&adc->lock);
-
        ret = i2c_master_send(adc->i2c, &newconfig, 1);
        if (ret > 0) {
                adc->config = newconfig;
                ret = 0;
        }
 
-       mutex_unlock(&adc->lock);
-
        return ret;
 }
 
@@ -138,6 +134,8 @@ static int mcp3422_read_channel(struct mcp3422 *adc,
        u8 config;
        u8 req_channel = channel->channel;
 
+       mutex_lock(&adc->lock);
+
        if (req_channel != MCP3422_CHANNEL(adc->config)) {
                config = adc->config;
                config &= ~MCP3422_CHANNEL_MASK;
@@ -145,12 +143,18 @@ static int mcp3422_read_channel(struct mcp3422 *adc,
                config &= ~MCP3422_PGA_MASK;
                config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
                ret = mcp3422_update_config(adc, config);
-               if (ret < 0)
+               if (ret < 0) {
+                       mutex_unlock(&adc->lock);
                        return ret;
+               }
                msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]);
        }
 
-       return mcp3422_read(adc, value, &config);
+       ret = mcp3422_read(adc, value, &config);
+
+       mutex_unlock(&adc->lock);
+
+       return ret;
 }
 
 static int mcp3422_read_raw(struct iio_dev *iio,
index 93c2252..1a9189b 100644 (file)
@@ -707,7 +707,7 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
        size_t read_len;
        int ret;
 
-       temperature_calib = devm_nvmem_cell_get(&indio_dev->dev,
+       temperature_calib = devm_nvmem_cell_get(indio_dev->dev.parent,
                                                "temperature_calib");
        if (IS_ERR(temperature_calib)) {
                ret = PTR_ERR(temperature_calib);
index b4b73c9..c10aa28 100644 (file)
@@ -982,7 +982,7 @@ static int adc5_probe(struct platform_device *pdev)
 
 static struct platform_driver adc5_driver = {
        .driver = {
-               .name = "qcom-spmi-adc5.c",
+               .name = "qcom-spmi-adc5",
                .of_match_table = adc5_match_table,
        },
        .probe = adc5_probe,
index 9426f70..cf63983 100644 (file)
@@ -33,6 +33,12 @@ struct adc081c {
 
        /* 8, 10 or 12 */
        int bits;
+
+       /* Ensure natural alignment of buffer elements */
+       struct {
+               u16 channel;
+               s64 ts __aligned(8);
+       } scan;
 };
 
 #define REG_CONV_RES 0x00
@@ -128,14 +134,13 @@ static irqreturn_t adc081c_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct adc081c *data = iio_priv(indio_dev);
-       u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */
        int ret;
 
        ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES);
        if (ret < 0)
                goto out;
-       buf[0] = ret;
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       data->scan.channel = ret;
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
                                           iio_get_time_ns(indio_dev));
 out:
        iio_trigger_notify_done(indio_dev->trig);
index 9017e1e..dfba348 100644 (file)
@@ -26,6 +26,11 @@ struct adc084s021 {
        struct spi_transfer spi_trans;
        struct regulator *reg;
        struct mutex lock;
+       /* Buffer used to align data */
+       struct {
+               __be16 channels[4];
+               s64 ts __aligned(8);
+       } scan;
        /*
         * DMA (thus cache coherency maintenance) requires the
         * transfer buffers to live in their own cache line.
@@ -141,14 +146,13 @@ static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc)
        struct iio_poll_func *pf = pollfunc;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct adc084s021 *adc = iio_priv(indio_dev);
-       __be16 data[8] = {0}; /* 4 * 16-bit words of data + 8 bytes timestamp */
 
        mutex_lock(&adc->lock);
 
-       if (adc084s021_adc_conversion(adc, &data) < 0)
+       if (adc084s021_adc_conversion(adc, adc->scan.channels) < 0)
                dev_err(&adc->spi->dev, "Failed to read data\n");
 
-       iio_push_to_buffers_with_timestamp(indio_dev, data,
+       iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan,
                                           iio_get_time_ns(indio_dev));
        mutex_unlock(&adc->lock);
        iio_trigger_notify_done(indio_dev->trig);
index f42ab11..9fef39b 100644 (file)
@@ -316,6 +316,7 @@ static const struct iio_chan_spec ads1115_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
 };
 
+#ifdef CONFIG_PM
 static int ads1015_set_power_state(struct ads1015_data *data, bool on)
 {
        int ret;
@@ -333,6 +334,15 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on)
        return ret < 0 ? ret : 0;
 }
 
+#else /* !CONFIG_PM */
+
+static int ads1015_set_power_state(struct ads1015_data *data, bool on)
+{
+       return 0;
+}
+
+#endif /* !CONFIG_PM */
+
 static
 int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
 {
index 2b007e7..60dd87e 100644 (file)
@@ -78,6 +78,11 @@ struct ccs811_data {
        struct iio_trigger *drdy_trig;
        struct gpio_desc *wakeup_gpio;
        bool drdy_trig_on;
+       /* Ensures correct alignment of timestamp if present */
+       struct {
+               s16 channels[2];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 static const struct iio_chan_spec ccs811_channels[] = {
@@ -327,17 +332,17 @@ static irqreturn_t ccs811_trigger_handler(int irq, void *p)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct ccs811_data *data = iio_priv(indio_dev);
        struct i2c_client *client = data->client;
-       s16 buf[8]; /* s16 eCO2 + s16 TVOC + padding + 8 byte timestamp */
        int ret;
 
-       ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA, 4,
-                                           (u8 *)&buf);
+       ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA,
+                                           sizeof(data->scan.channels),
+                                           (u8 *)data->scan.channels);
        if (ret != 4) {
                dev_err(&client->dev, "cannot read sensor data\n");
                goto err;
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
                                           iio_get_time_ns(indio_dev));
 
 err:
index ea480c1..1bc6efa 100644 (file)
@@ -72,10 +72,13 @@ static void get_default_min_max_freq(enum motionsensor_type type,
 
        switch (type) {
        case MOTIONSENSE_TYPE_ACCEL:
-       case MOTIONSENSE_TYPE_GYRO:
                *min_freq = 12500;
                *max_freq = 100000;
                break;
+       case MOTIONSENSE_TYPE_GYRO:
+               *min_freq = 25000;
+               *max_freq = 100000;
+               break;
        case MOTIONSENSE_TYPE_MAG:
                *min_freq = 5000;
                *max_freq = 25000;
index 4bac064..b4323d2 100644 (file)
@@ -1243,13 +1243,16 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct ltr501_data *data = iio_priv(indio_dev);
-       u16 buf[8];
+       struct {
+               u16 channels[3];
+               s64 ts __aligned(8);
+       } scan;
        __le16 als_buf[2];
        u8 mask = 0;
        int j = 0;
        int ret, psdata;
 
-       memset(buf, 0, sizeof(buf));
+       memset(&scan, 0, sizeof(scan));
 
        /* figure out which data needs to be ready */
        if (test_bit(0, indio_dev->active_scan_mask) ||
@@ -1268,9 +1271,9 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
                if (ret < 0)
                        return ret;
                if (test_bit(0, indio_dev->active_scan_mask))
-                       buf[j++] = le16_to_cpu(als_buf[1]);
+                       scan.channels[j++] = le16_to_cpu(als_buf[1]);
                if (test_bit(1, indio_dev->active_scan_mask))
-                       buf[j++] = le16_to_cpu(als_buf[0]);
+                       scan.channels[j++] = le16_to_cpu(als_buf[0]);
        }
 
        if (mask & LTR501_STATUS_PS_RDY) {
@@ -1278,10 +1281,10 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
                                       &psdata, 2);
                if (ret < 0)
                        goto done;
-               buf[j++] = psdata & LTR501_PS_DATA_MASK;
+               scan.channels[j++] = psdata & LTR501_PS_DATA_MASK;
        }
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       iio_push_to_buffers_with_timestamp(indio_dev, &scan,
                                           iio_get_time_ns(indio_dev));
 
 done:
index aa8ed1e..b8e721b 100644 (file)
 struct max44000_data {
        struct mutex lock;
        struct regmap *regmap;
+       /* Ensure naturally aligned timestamp */
+       struct {
+               u16 channels[2];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 /* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */
@@ -488,7 +493,6 @@ static irqreturn_t max44000_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct max44000_data *data = iio_priv(indio_dev);
-       u16 buf[8]; /* 2x u16 + padding + 8 bytes timestamp */
        int index = 0;
        unsigned int regval;
        int ret;
@@ -498,17 +502,17 @@ static irqreturn_t max44000_trigger_handler(int irq, void *p)
                ret = max44000_read_alsval(data);
                if (ret < 0)
                        goto out_unlock;
-               buf[index++] = ret;
+               data->scan.channels[index++] = ret;
        }
        if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) {
                ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, &regval);
                if (ret < 0)
                        goto out_unlock;
-               buf[index] = regval;
+               data->scan.channels[index] = regval;
        }
        mutex_unlock(&data->lock);
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buf,
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
                                           iio_get_time_ns(indio_dev));
        iio_trigger_notify_done(indio_dev->trig);
        return IRQ_HANDLED;
index 03d71f7..623766f 100644 (file)
@@ -366,6 +366,12 @@ struct ak8975_data {
        struct iio_mount_matrix orientation;
        struct regulator        *vdd;
        struct regulator        *vid;
+
+       /* Ensure natural alignment of timestamp */
+       struct {
+               s16 channels[3];
+               s64 ts __aligned(8);
+       } scan;
 };
 
 /* Enable attached power regulator if any. */
@@ -793,7 +799,6 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev)
        const struct i2c_client *client = data->client;
        const struct ak_def *def = data->def;
        int ret;
-       s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
        __le16 fval[3];
 
        mutex_lock(&data->lock);
@@ -816,12 +821,13 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev)
        mutex_unlock(&data->lock);
 
        /* Clamp to valid range. */
-       buff[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
-       buff[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
-       buff[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
+       data->scan.channels[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
+       data->scan.channels[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
+       data->scan.channels[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buff,
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
                                           iio_get_time_ns(indio_dev));
+
        return;
 
 unlock:
index 654564c..ad4b1fb 100644 (file)
@@ -40,6 +40,11 @@ struct mb1232_data {
         */
        struct completion       ranging;
        int                     irqnr;
+       /* Ensure correct alignment of data to push to IIO buffer */
+       struct {
+               s16 distance;
+               s64 ts __aligned(8);
+       } scan;
 };
 
 static irqreturn_t mb1232_handle_irq(int irq, void *dev_id)
@@ -113,17 +118,13 @@ static irqreturn_t mb1232_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct mb1232_data *data = iio_priv(indio_dev);
-       /*
-        * triggered buffer
-        * 16-bit channel + 48-bit padding + 64-bit timestamp
-        */
-       s16 buffer[8] = { 0 };
 
-       buffer[0] = mb1232_read_distance(data);
-       if (buffer[0] < 0)
+       data->scan.distance = mb1232_read_distance(data);
+       if (data->scan.distance < 0)
                goto err;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+       iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+                                          pf->timestamp);
 
 err:
        iio_trigger_notify_done(indio_dev->trig);
index ffad73b..5a76611 100644 (file)
@@ -1320,9 +1320,10 @@ struct net_device *rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr)
 }
 EXPORT_SYMBOL(rdma_read_gid_attr_ndev_rcu);
 
-static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
+static int get_lower_dev_vlan(struct net_device *lower_dev,
+                             struct netdev_nested_priv *priv)
 {
-       u16 *vlan_id = data;
+       u16 *vlan_id = (u16 *)priv->data;
 
        if (is_vlan_dev(lower_dev))
                *vlan_id = vlan_dev_vlan_id(lower_dev);
@@ -1348,6 +1349,9 @@ static int get_lower_dev_vlan(struct net_device *lower_dev, void *data)
 int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
                            u16 *vlan_id, u8 *smac)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)vlan_id,
+       };
        struct net_device *ndev;
 
        rcu_read_lock();
@@ -1368,7 +1372,7 @@ int rdma_read_gid_l2_fields(const struct ib_gid_attr *attr,
                         * the lower vlan device for this gid entry.
                         */
                        netdev_walk_all_lower_dev_rcu(attr->ndev,
-                                       get_lower_dev_vlan, vlan_id);
+                                       get_lower_dev_vlan, &priv);
                }
        }
        rcu_read_unlock();
index 7f0e91e..5888311 100644 (file)
@@ -2865,9 +2865,10 @@ struct iboe_prio_tc_map {
        bool found;
 };
 
-static int get_lower_vlan_dev_tc(struct net_device *dev, void *data)
+static int get_lower_vlan_dev_tc(struct net_device *dev,
+                                struct netdev_nested_priv *priv)
 {
-       struct iboe_prio_tc_map *map = data;
+       struct iboe_prio_tc_map *map = (struct iboe_prio_tc_map *)priv->data;
 
        if (is_vlan_dev(dev))
                map->output_tc = get_vlan_ndev_tc(dev, map->input_prio);
@@ -2886,16 +2887,18 @@ static int iboe_tos_to_sl(struct net_device *ndev, int tos)
 {
        struct iboe_prio_tc_map prio_tc_map = {};
        int prio = rt_tos2priority(tos);
+       struct netdev_nested_priv priv;
 
        /* If VLAN device, get it directly from the VLAN netdev */
        if (is_vlan_dev(ndev))
                return get_vlan_ndev_tc(ndev, prio);
 
        prio_tc_map.input_prio = prio;
+       priv.data = (void *)&prio_tc_map;
        rcu_read_lock();
        netdev_walk_all_lower_dev_rcu(ndev,
                                      get_lower_vlan_dev_tc,
-                                     &prio_tc_map);
+                                     &priv);
        rcu_read_unlock();
        /* If map is found from lower device, use it; Otherwise
         * continue with the current netdevice to get priority to tc map.
index 513825e..a92fc3f 100644 (file)
@@ -379,7 +379,7 @@ static int ib_alloc_cqs(struct ib_device *dev, unsigned int nr_cqes,
 {
        LIST_HEAD(tmp_list);
        unsigned int nr_cqs, i;
-       struct ib_cq *cq;
+       struct ib_cq *cq, *n;
        int ret;
 
        if (poll_ctx > IB_POLL_LAST_POOL_TYPE) {
@@ -412,7 +412,7 @@ static int ib_alloc_cqs(struct ib_device *dev, unsigned int nr_cqes,
        return 0;
 
 out_free_cqs:
-       list_for_each_entry(cq, &tmp_list, pool_entry) {
+       list_for_each_entry_safe(cq, n, &tmp_list, pool_entry) {
                cq->shared = false;
                ib_free_cq(cq);
        }
index c36b4d2..23ee65a 100644 (file)
@@ -1285,6 +1285,8 @@ static void disable_device(struct ib_device *device)
                remove_client_context(device, cid);
        }
 
+       ib_cq_pool_destroy(device);
+
        /* Pairs with refcount_set in enable_device */
        ib_device_put(device);
        wait_for_completion(&device->unreg_completion);
@@ -1328,6 +1330,8 @@ static int enable_device_and_get(struct ib_device *device)
                        goto out;
        }
 
+       ib_cq_pool_init(device);
+
        down_read(&clients_rwsem);
        xa_for_each_marked (&clients, index, client, CLIENT_REGISTERED) {
                ret = add_client_context(device, client);
@@ -1400,7 +1404,6 @@ int ib_register_device(struct ib_device *device, const char *name)
                goto dev_cleanup;
        }
 
-       ib_cq_pool_init(device);
        ret = enable_device_and_get(device);
        dev_set_uevent_suppress(&device->dev, false);
        /* Mark for userspace that device is ready */
@@ -1455,7 +1458,6 @@ static void __ib_unregister_device(struct ib_device *ib_dev)
                goto out;
 
        disable_device(ib_dev);
-       ib_cq_pool_destroy(ib_dev);
 
        /* Expedite removing unregistered pointers from the hash table */
        free_netdevs(ib_dev);
index 2860def..6b8364b 100644 (file)
@@ -531,10 +531,11 @@ struct upper_list {
        struct net_device *upper;
 };
 
-static int netdev_upper_walk(struct net_device *upper, void *data)
+static int netdev_upper_walk(struct net_device *upper,
+                            struct netdev_nested_priv *priv)
 {
        struct upper_list *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
-       struct list_head *upper_list = data;
+       struct list_head *upper_list = (struct list_head *)priv->data;
 
        if (!entry)
                return 0;
@@ -553,12 +554,14 @@ static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
                                                      struct net_device *ndev))
 {
        struct net_device *ndev = cookie;
+       struct netdev_nested_priv priv;
        struct upper_list *upper_iter;
        struct upper_list *upper_temp;
        LIST_HEAD(upper_list);
 
+       priv.data = &upper_list;
        rcu_read_lock();
-       netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &upper_list);
+       netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &priv);
        rcu_read_unlock();
 
        handle_netdev(ib_dev, port, ndev);
index 3096e73..3078867 100644 (file)
@@ -1801,7 +1801,7 @@ int ib_get_eth_speed(struct ib_device *dev, u8 port_num, u8 *speed, u8 *width)
 
        dev_put(netdev);
 
-       if (!rc) {
+       if (!rc && lksettings.base.speed != (u32)SPEED_UNKNOWN) {
                netdev_speed = lksettings.base.speed;
        } else {
                netdev_speed = SPEED_1000;
index 5ee272d..1d7a9ca 100644 (file)
@@ -752,12 +752,6 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
        gsi_sqp = rdev->gsi_ctx.gsi_sqp;
        gsi_sah = rdev->gsi_ctx.gsi_sah;
 
-       /* remove from active qp list */
-       mutex_lock(&rdev->qp_lock);
-       list_del(&gsi_sqp->list);
-       mutex_unlock(&rdev->qp_lock);
-       atomic_dec(&rdev->qp_count);
-
        ibdev_dbg(&rdev->ibdev, "Destroy the shadow AH\n");
        bnxt_qplib_destroy_ah(&rdev->qplib_res,
                              &gsi_sah->qplib_ah,
@@ -772,6 +766,12 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
        }
        bnxt_qplib_free_qp_res(&rdev->qplib_res, &gsi_sqp->qplib_qp);
 
+       /* remove from active qp list */
+       mutex_lock(&rdev->qp_lock);
+       list_del(&gsi_sqp->list);
+       mutex_unlock(&rdev->qp_lock);
+       atomic_dec(&rdev->qp_count);
+
        kfree(rdev->gsi_ctx.sqp_tbl);
        kfree(gsi_sah);
        kfree(gsi_sqp);
@@ -792,11 +792,6 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
        unsigned int flags;
        int rc;
 
-       mutex_lock(&rdev->qp_lock);
-       list_del(&qp->list);
-       mutex_unlock(&rdev->qp_lock);
-       atomic_dec(&rdev->qp_count);
-
        bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
 
        rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
@@ -819,6 +814,11 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
                        goto sh_fail;
        }
 
+       mutex_lock(&rdev->qp_lock);
+       list_del(&qp->list);
+       mutex_unlock(&rdev->qp_lock);
+       atomic_dec(&rdev->qp_count);
+
        ib_umem_release(qp->rumem);
        ib_umem_release(qp->sumem);
 
@@ -3264,6 +3264,19 @@ static void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc,
        wc->wc_flags |= IB_WC_GRH;
 }
 
+static bool bnxt_re_check_if_vlan_valid(struct bnxt_re_dev *rdev,
+                                       u16 vlan_id)
+{
+       /*
+        * Check if the vlan is configured in the host.  If not configured, it
+        * can be a transparent VLAN. So dont report the vlan id.
+        */
+       if (!__vlan_find_dev_deep_rcu(rdev->netdev,
+                                     htons(ETH_P_8021Q), vlan_id))
+               return false;
+       return true;
+}
+
 static bool bnxt_re_is_vlan_pkt(struct bnxt_qplib_cqe *orig_cqe,
                                u16 *vid, u8 *sl)
 {
@@ -3332,9 +3345,11 @@ static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp,
        wc->src_qp = orig_cqe->src_qp;
        memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
        if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
-               wc->vlan_id = vlan_id;
-               wc->sl = sl;
-               wc->wc_flags |= IB_WC_WITH_VLAN;
+               if (bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
+                       wc->vlan_id = vlan_id;
+                       wc->sl = sl;
+                       wc->wc_flags |= IB_WC_WITH_VLAN;
+               }
        }
        wc->port_num = 1;
        wc->vendor_err = orig_cqe->status;
index 17ac8b7..53aee5a 100644 (file)
@@ -1009,7 +1009,6 @@ static void bnxt_re_free_res(struct bnxt_re_dev *rdev)
 static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
 {
        struct bnxt_re_ring_attr rattr = {};
-       struct bnxt_qplib_ctx *qplib_ctx;
        int num_vec_created = 0;
        int rc = 0, i;
        u8 type;
@@ -1032,13 +1031,11 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
        if (rc)
                goto dealloc_res;
 
-       qplib_ctx = &rdev->qplib_ctx;
        for (i = 0; i < rdev->num_msix - 1; i++) {
                struct bnxt_qplib_nq *nq;
 
                nq = &rdev->nq[i];
-               nq->hwq.max_elements = (qplib_ctx->cq_count +
-                                       qplib_ctx->srqc_count + 2);
+               nq->hwq.max_elements = BNXT_QPLIB_NQE_MAX_CNT;
                rc = bnxt_qplib_alloc_nq(&rdev->qplib_res, &rdev->nq[i]);
                if (rc) {
                        ibdev_err(&rdev->ibdev, "Alloc Failed NQ%d rc:%#x",
index d60e3dc..f78da54 100644 (file)
@@ -818,6 +818,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
        u16 cmd_flags = 0;
        u32 qp_flags = 0;
        u8 pg_sz_lvl;
+       u32 tbl_indx;
        int rc;
 
        RCFW_CMD_PREP(req, CREATE_QP1, cmd_flags);
@@ -907,8 +908,9 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
                rq->dbinfo.db = qp->dpi->dbr;
                rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size);
        }
-       rcfw->qp_tbl[qp->id].qp_id = qp->id;
-       rcfw->qp_tbl[qp->id].qp_handle = (void *)qp;
+       tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw);
+       rcfw->qp_tbl[tbl_indx].qp_id = qp->id;
+       rcfw->qp_tbl[tbl_indx].qp_handle = (void *)qp;
 
        return 0;
 
@@ -935,10 +937,10 @@ static void bnxt_qplib_init_psn_ptr(struct bnxt_qplib_qp *qp, int size)
 
        sq = &qp->sq;
        hwq = &sq->hwq;
+       /* First psn entry */
        fpsne = (u64)bnxt_qplib_get_qe(hwq, hwq->depth, &psn_pg);
        if (!IS_ALIGNED(fpsne, PAGE_SIZE))
-               indx_pad = ALIGN(fpsne, PAGE_SIZE) / size;
-
+               indx_pad = (fpsne & ~PAGE_MASK) / size;
        hwq->pad_pgofft = indx_pad;
        hwq->pad_pg = (u64 *)psn_pg;
        hwq->pad_stride = size;
@@ -959,6 +961,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
        u16 cmd_flags = 0;
        u32 qp_flags = 0;
        u8 pg_sz_lvl;
+       u32 tbl_indx;
        u16 nsge;
 
        RCFW_CMD_PREP(req, CREATE_QP, cmd_flags);
@@ -1111,8 +1114,9 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
                rq->dbinfo.db = qp->dpi->dbr;
                rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size);
        }
-       rcfw->qp_tbl[qp->id].qp_id = qp->id;
-       rcfw->qp_tbl[qp->id].qp_handle = (void *)qp;
+       tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw);
+       rcfw->qp_tbl[tbl_indx].qp_id = qp->id;
+       rcfw->qp_tbl[tbl_indx].qp_handle = (void *)qp;
 
        return 0;
 fail:
@@ -1457,10 +1461,12 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
        struct cmdq_destroy_qp req;
        struct creq_destroy_qp_resp resp;
        u16 cmd_flags = 0;
+       u32 tbl_indx;
        int rc;
 
-       rcfw->qp_tbl[qp->id].qp_id = BNXT_QPLIB_QP_ID_INVALID;
-       rcfw->qp_tbl[qp->id].qp_handle = NULL;
+       tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw);
+       rcfw->qp_tbl[tbl_indx].qp_id = BNXT_QPLIB_QP_ID_INVALID;
+       rcfw->qp_tbl[tbl_indx].qp_handle = NULL;
 
        RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags);
 
@@ -1468,8 +1474,8 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
        rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
                                          (void *)&resp, NULL, 0);
        if (rc) {
-               rcfw->qp_tbl[qp->id].qp_id = qp->id;
-               rcfw->qp_tbl[qp->id].qp_handle = qp;
+               rcfw->qp_tbl[tbl_indx].qp_id = qp->id;
+               rcfw->qp_tbl[tbl_indx].qp_handle = qp;
                return rc;
        }
 
index 4e21116..f7736e3 100644 (file)
@@ -307,14 +307,15 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
        __le16  mcookie;
        u16 cookie;
        int rc = 0;
-       u32 qp_id;
+       u32 qp_id, tbl_indx;
 
        pdev = rcfw->pdev;
        switch (qp_event->event) {
        case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
                err_event = (struct creq_qp_error_notification *)qp_event;
                qp_id = le32_to_cpu(err_event->xid);
-               qp = rcfw->qp_tbl[qp_id].qp_handle;
+               tbl_indx = map_qp_id_to_tbl_indx(qp_id, rcfw);
+               qp = rcfw->qp_tbl[tbl_indx].qp_handle;
                dev_dbg(&pdev->dev, "Received QP error notification\n");
                dev_dbg(&pdev->dev,
                        "qpid 0x%x, req_err=0x%x, resp_err=0x%x\n",
@@ -615,8 +616,9 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
 
        cmdq->bmap_size = bmap_size;
 
-       rcfw->qp_tbl_size = qp_tbl_sz;
-       rcfw->qp_tbl = kcalloc(qp_tbl_sz, sizeof(struct bnxt_qplib_qp_node),
+       /* Allocate one extra to hold the QP1 entries */
+       rcfw->qp_tbl_size = qp_tbl_sz + 1;
+       rcfw->qp_tbl = kcalloc(rcfw->qp_tbl_size, sizeof(struct bnxt_qplib_qp_node),
                               GFP_KERNEL);
        if (!rcfw->qp_tbl)
                goto fail;
index 1573876..5f2f0a5 100644 (file)
@@ -216,4 +216,9 @@ int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
 int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
                         struct bnxt_qplib_ctx *ctx, int is_virtfn);
 void bnxt_qplib_mark_qp_error(void *qp_handle);
+static inline u32 map_qp_id_to_tbl_indx(u32 qid, struct bnxt_qplib_rcfw *rcfw)
+{
+       /* Last index of the qp_tbl is for QP1 ie. qp_tbl_size - 1*/
+       return (qid == 1) ? rcfw->qp_tbl_size - 1 : qid % rcfw->qp_tbl_size - 2;
+}
 #endif /* __BNXT_QPLIB_RCFW_H__ */
index 4cd475e..64d44f5 100644 (file)
@@ -149,7 +149,7 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
        attr->max_inline_data = le32_to_cpu(sb->max_inline_data);
        attr->l2_db_size = (sb->l2_db_space_size + 1) *
                            (0x01 << RCFW_DBR_BASE_PAGE_SHIFT);
-       attr->max_sgid = le32_to_cpu(sb->max_gid);
+       attr->max_sgid = BNXT_QPLIB_NUM_GIDS_SUPPORTED;
 
        bnxt_qplib_query_version(rcfw, attr->fw_ver);
 
index 6404f0d..967890c 100644 (file)
@@ -47,6 +47,7 @@
 struct bnxt_qplib_dev_attr {
 #define FW_VER_ARR_LEN                 4
        u8                              fw_ver[FW_VER_ARR_LEN];
+#define BNXT_QPLIB_NUM_GIDS_SUPPORTED  256
        u16                             max_sgid;
        u16                             max_mrw;
        u32                             max_qp;
index 5e7910a..bd4f975 100644 (file)
@@ -784,7 +784,8 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
        props->ip_gids = true;
        props->gid_tbl_len      = mdev->dev->caps.gid_table_len[port];
        props->max_msg_sz       = mdev->dev->caps.max_msg_sz;
-       props->pkey_tbl_len     = 1;
+       if (mdev->dev->caps.pkey_table_len[port])
+               props->pkey_tbl_len = 1;
        props->max_mtu          = IB_MTU_4096;
        props->max_vl_num       = 2;
        props->state            = IB_PORT_DOWN;
index 907203a..77f2c7c 100644 (file)
@@ -40,6 +40,8 @@ MODULE_AUTHOR("Bob Pearson, Frank Zago, John Groves, Kamal Heib");
 MODULE_DESCRIPTION("Soft RDMA transport");
 MODULE_LICENSE("Dual BSD/GPL");
 
+bool rxe_initialized;
+
 /* free resources for a rxe device all objects created for this device must
  * have been destroyed
  */
@@ -315,6 +317,7 @@ static int __init rxe_module_init(void)
                return err;
 
        rdma_link_register(&rxe_link_ops);
+       rxe_initialized = true;
        pr_info("loaded\n");
        return 0;
 }
@@ -326,6 +329,7 @@ static void __exit rxe_module_exit(void)
        rxe_net_exit();
        rxe_cache_exit();
 
+       rxe_initialized = false;
        pr_info("unloaded\n");
 }
 
index fb07eed..cae1b0a 100644 (file)
@@ -67,6 +67,8 @@
 
 #define RXE_ROCE_V2_SPORT              (0xc000)
 
+extern bool rxe_initialized;
+
 static inline u32 rxe_crc32(struct rxe_dev *rxe,
                            u32 crc, void *next, size_t len)
 {
index cdd811a..ce24144 100644 (file)
@@ -205,6 +205,7 @@ int rxe_mem_init_user(struct rxe_pd *pd, u64 start,
                        vaddr = page_address(sg_page_iter_page(&sg_iter));
                        if (!vaddr) {
                                pr_warn("null vaddr\n");
+                               ib_umem_release(umem);
                                err = -ENOMEM;
                                goto err1;
                        }
index ccda5f5..2af31d4 100644 (file)
@@ -61,6 +61,11 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp)
        struct net_device *ndev;
        struct rxe_dev *exists;
 
+       if (!rxe_initialized) {
+               pr_err("Module parameters are not supported, use rdma link add or rxe_cfg\n");
+               return -EAGAIN;
+       }
+
        len = sanitize_arg(val, intf, sizeof(intf));
        if (!len) {
                pr_err("add: invalid interface name\n");
index 658939e..8522e9a 100644 (file)
@@ -1056,7 +1056,7 @@ static ssize_t parent_show(struct device *device,
        struct rxe_dev *rxe =
                rdma_device_to_drv_device(device, struct rxe_dev, ib_dev);
 
-       return snprintf(buf, 16, "%s\n", rxe_parent_name(rxe, 1));
+       return scnprintf(buf, PAGE_SIZE, "%s\n", rxe_parent_name(rxe, 1));
 }
 
 static DEVICE_ATTR_RO(parent);
index ab75b7f..f772fe8 100644 (file)
@@ -342,9 +342,10 @@ struct ipoib_walk_data {
        struct net_device *result;
 };
 
-static int ipoib_upper_walk(struct net_device *upper, void *_data)
+static int ipoib_upper_walk(struct net_device *upper,
+                           struct netdev_nested_priv *priv)
 {
-       struct ipoib_walk_data *data = _data;
+       struct ipoib_walk_data *data = (struct ipoib_walk_data *)priv->data;
        int ret = 0;
 
        if (ipoib_is_dev_match_addr_rcu(data->addr, upper)) {
@@ -368,10 +369,12 @@ static int ipoib_upper_walk(struct net_device *upper, void *_data)
 static struct net_device *ipoib_get_net_dev_match_addr(
                const struct sockaddr *addr, struct net_device *dev)
 {
+       struct netdev_nested_priv priv;
        struct ipoib_walk_data data = {
                .addr = addr,
        };
 
+       priv.data = (void *)&data;
        rcu_read_lock();
        if (ipoib_is_dev_match_addr_rcu(addr, dev)) {
                dev_hold(dev);
@@ -379,7 +382,7 @@ static struct net_device *ipoib_get_net_dev_match_addr(
                goto out;
        }
 
-       netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data);
+       netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &priv);
 out:
        rcu_read_unlock();
        return data.result;
index e86acda..695f701 100644 (file)
@@ -140,15 +140,15 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
        rx_desc = isert_conn->rx_descs;
 
        for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
-               dma_addr = ib_dma_map_single(ib_dev, (void *)rx_desc,
-                                       ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+               dma_addr = ib_dma_map_single(ib_dev, rx_desc->buf,
+                                       ISER_RX_SIZE, DMA_FROM_DEVICE);
                if (ib_dma_mapping_error(ib_dev, dma_addr))
                        goto dma_map_fail;
 
                rx_desc->dma_addr = dma_addr;
 
                rx_sg = &rx_desc->rx_sg;
-               rx_sg->addr = rx_desc->dma_addr;
+               rx_sg->addr = rx_desc->dma_addr + isert_get_hdr_offset(rx_desc);
                rx_sg->length = ISER_RX_PAYLOAD_SIZE;
                rx_sg->lkey = device->pd->local_dma_lkey;
                rx_desc->rx_cqe.done = isert_recv_done;
@@ -160,7 +160,7 @@ dma_map_fail:
        rx_desc = isert_conn->rx_descs;
        for (j = 0; j < i; j++, rx_desc++) {
                ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
-                                   ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+                                   ISER_RX_SIZE, DMA_FROM_DEVICE);
        }
        kfree(isert_conn->rx_descs);
        isert_conn->rx_descs = NULL;
@@ -181,7 +181,7 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn)
        rx_desc = isert_conn->rx_descs;
        for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
                ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
-                                   ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+                                   ISER_RX_SIZE, DMA_FROM_DEVICE);
        }
 
        kfree(isert_conn->rx_descs);
@@ -299,10 +299,9 @@ isert_free_login_buf(struct isert_conn *isert_conn)
                            ISER_RX_PAYLOAD_SIZE, DMA_TO_DEVICE);
        kfree(isert_conn->login_rsp_buf);
 
-       ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
-                           ISER_RX_PAYLOAD_SIZE,
-                           DMA_FROM_DEVICE);
-       kfree(isert_conn->login_req_buf);
+       ib_dma_unmap_single(ib_dev, isert_conn->login_desc->dma_addr,
+                           ISER_RX_SIZE, DMA_FROM_DEVICE);
+       kfree(isert_conn->login_desc);
 }
 
 static int
@@ -311,25 +310,25 @@ isert_alloc_login_buf(struct isert_conn *isert_conn,
 {
        int ret;
 
-       isert_conn->login_req_buf = kzalloc(sizeof(*isert_conn->login_req_buf),
+       isert_conn->login_desc = kzalloc(sizeof(*isert_conn->login_desc),
                        GFP_KERNEL);
-       if (!isert_conn->login_req_buf)
+       if (!isert_conn->login_desc)
                return -ENOMEM;
 
-       isert_conn->login_req_dma = ib_dma_map_single(ib_dev,
-                               isert_conn->login_req_buf,
-                               ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
-       ret = ib_dma_mapping_error(ib_dev, isert_conn->login_req_dma);
+       isert_conn->login_desc->dma_addr = ib_dma_map_single(ib_dev,
+                               isert_conn->login_desc->buf,
+                               ISER_RX_SIZE, DMA_FROM_DEVICE);
+       ret = ib_dma_mapping_error(ib_dev, isert_conn->login_desc->dma_addr);
        if (ret) {
-               isert_err("login_req_dma mapping error: %d\n", ret);
-               isert_conn->login_req_dma = 0;
-               goto out_free_login_req_buf;
+               isert_err("login_desc dma mapping error: %d\n", ret);
+               isert_conn->login_desc->dma_addr = 0;
+               goto out_free_login_desc;
        }
 
        isert_conn->login_rsp_buf = kzalloc(ISER_RX_PAYLOAD_SIZE, GFP_KERNEL);
        if (!isert_conn->login_rsp_buf) {
                ret = -ENOMEM;
-               goto out_unmap_login_req_buf;
+               goto out_unmap_login_desc;
        }
 
        isert_conn->login_rsp_dma = ib_dma_map_single(ib_dev,
@@ -346,11 +345,11 @@ isert_alloc_login_buf(struct isert_conn *isert_conn,
 
 out_free_login_rsp_buf:
        kfree(isert_conn->login_rsp_buf);
-out_unmap_login_req_buf:
-       ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
-                           ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
-out_free_login_req_buf:
-       kfree(isert_conn->login_req_buf);
+out_unmap_login_desc:
+       ib_dma_unmap_single(ib_dev, isert_conn->login_desc->dma_addr,
+                           ISER_RX_SIZE, DMA_FROM_DEVICE);
+out_free_login_desc:
+       kfree(isert_conn->login_desc);
        return ret;
 }
 
@@ -476,7 +475,7 @@ isert_connect_release(struct isert_conn *isert_conn)
        if (isert_conn->qp)
                isert_destroy_qp(isert_conn);
 
-       if (isert_conn->login_req_buf)
+       if (isert_conn->login_desc)
                isert_free_login_buf(isert_conn);
 
        isert_device_put(device);
@@ -862,17 +861,18 @@ isert_login_post_recv(struct isert_conn *isert_conn)
        int ret;
 
        memset(&sge, 0, sizeof(struct ib_sge));
-       sge.addr = isert_conn->login_req_dma;
+       sge.addr = isert_conn->login_desc->dma_addr +
+               isert_get_hdr_offset(isert_conn->login_desc);
        sge.length = ISER_RX_PAYLOAD_SIZE;
        sge.lkey = isert_conn->device->pd->local_dma_lkey;
 
        isert_dbg("Setup sge: addr: %llx length: %d 0x%08x\n",
                sge.addr, sge.length, sge.lkey);
 
-       isert_conn->login_req_buf->rx_cqe.done = isert_login_recv_done;
+       isert_conn->login_desc->rx_cqe.done = isert_login_recv_done;
 
        memset(&rx_wr, 0, sizeof(struct ib_recv_wr));
-       rx_wr.wr_cqe = &isert_conn->login_req_buf->rx_cqe;
+       rx_wr.wr_cqe = &isert_conn->login_desc->rx_cqe;
        rx_wr.sg_list = &sge;
        rx_wr.num_sge = 1;
 
@@ -949,7 +949,7 @@ post_send:
 static void
 isert_rx_login_req(struct isert_conn *isert_conn)
 {
-       struct iser_rx_desc *rx_desc = isert_conn->login_req_buf;
+       struct iser_rx_desc *rx_desc = isert_conn->login_desc;
        int rx_buflen = isert_conn->login_req_len;
        struct iscsi_conn *conn = isert_conn->conn;
        struct iscsi_login *login = conn->conn_login;
@@ -961,7 +961,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
 
        if (login->first_request) {
                struct iscsi_login_req *login_req =
-                       (struct iscsi_login_req *)&rx_desc->iscsi_header;
+                       (struct iscsi_login_req *)isert_get_iscsi_hdr(rx_desc);
                /*
                 * Setup the initial iscsi_login values from the leading
                 * login request PDU.
@@ -980,13 +980,13 @@ isert_rx_login_req(struct isert_conn *isert_conn)
                login->tsih             = be16_to_cpu(login_req->tsih);
        }
 
-       memcpy(&login->req[0], (void *)&rx_desc->iscsi_header, ISCSI_HDR_LEN);
+       memcpy(&login->req[0], isert_get_iscsi_hdr(rx_desc), ISCSI_HDR_LEN);
 
        size = min(rx_buflen, MAX_KEY_VALUE_PAIRS);
        isert_dbg("Using login payload size: %d, rx_buflen: %d "
                  "MAX_KEY_VALUE_PAIRS: %d\n", size, rx_buflen,
                  MAX_KEY_VALUE_PAIRS);
-       memcpy(login->req_buf, &rx_desc->data[0], size);
+       memcpy(login->req_buf, isert_get_data(rx_desc), size);
 
        if (login->first_request) {
                complete(&isert_conn->login_comp);
@@ -1051,14 +1051,15 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
        if (imm_data_len != data_len) {
                sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
                sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
-                                   &rx_desc->data[0], imm_data_len);
+                                   isert_get_data(rx_desc), imm_data_len);
                isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
                          sg_nents, imm_data_len);
        } else {
                sg_init_table(&isert_cmd->sg, 1);
                cmd->se_cmd.t_data_sg = &isert_cmd->sg;
                cmd->se_cmd.t_data_nents = 1;
-               sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
+               sg_set_buf(&isert_cmd->sg, isert_get_data(rx_desc),
+                               imm_data_len);
                isert_dbg("Transfer Immediate imm_data_len: %d\n",
                          imm_data_len);
        }
@@ -1127,9 +1128,9 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
        }
        isert_dbg("Copying DataOut: sg_start: %p, sg_off: %u "
                  "sg_nents: %u from %p %u\n", sg_start, sg_off,
-                 sg_nents, &rx_desc->data[0], unsol_data_len);
+                 sg_nents, isert_get_data(rx_desc), unsol_data_len);
 
-       sg_copy_from_buffer(sg_start, sg_nents, &rx_desc->data[0],
+       sg_copy_from_buffer(sg_start, sg_nents, isert_get_data(rx_desc),
                            unsol_data_len);
 
        rc = iscsit_check_dataout_payload(cmd, hdr, false);
@@ -1188,7 +1189,7 @@ isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd
        }
        cmd->text_in_ptr = text_in;
 
-       memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length);
+       memcpy(cmd->text_in_ptr, isert_get_data(rx_desc), payload_length);
 
        return iscsit_process_text_cmd(conn, cmd, hdr);
 }
@@ -1198,7 +1199,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                uint32_t read_stag, uint64_t read_va,
                uint32_t write_stag, uint64_t write_va)
 {
-       struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
+       struct iscsi_hdr *hdr = isert_get_iscsi_hdr(rx_desc);
        struct iscsi_conn *conn = isert_conn->conn;
        struct iscsi_cmd *cmd;
        struct isert_cmd *isert_cmd;
@@ -1296,8 +1297,8 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
        struct isert_conn *isert_conn = wc->qp->qp_context;
        struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct iser_rx_desc *rx_desc = cqe_to_rx_desc(wc->wr_cqe);
-       struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
-       struct iser_ctrl *iser_ctrl = &rx_desc->iser_header;
+       struct iscsi_hdr *hdr = isert_get_iscsi_hdr(rx_desc);
+       struct iser_ctrl *iser_ctrl = isert_get_iser_hdr(rx_desc);
        uint64_t read_va = 0, write_va = 0;
        uint32_t read_stag = 0, write_stag = 0;
 
@@ -1311,7 +1312,7 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
        rx_desc->in_use = true;
 
        ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
-                       ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+                       ISER_RX_SIZE, DMA_FROM_DEVICE);
 
        isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n",
                 rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags,
@@ -1346,7 +1347,7 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
                        read_stag, read_va, write_stag, write_va);
 
        ib_dma_sync_single_for_device(ib_dev, rx_desc->dma_addr,
-                       ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+                       ISER_RX_SIZE, DMA_FROM_DEVICE);
 }
 
 static void
@@ -1360,8 +1361,8 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
                return;
        }
 
-       ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_req_dma,
-                       ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+       ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr,
+                       ISER_RX_SIZE, DMA_FROM_DEVICE);
 
        isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN;
 
@@ -1376,8 +1377,8 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
        complete(&isert_conn->login_req_comp);
        mutex_unlock(&isert_conn->mutex);
 
-       ib_dma_sync_single_for_device(ib_dev, isert_conn->login_req_dma,
-                               ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+       ib_dma_sync_single_for_device(ib_dev, isert_conn->login_desc->dma_addr,
+                               ISER_RX_SIZE, DMA_FROM_DEVICE);
 }
 
 static void
index c55f7d9..7fee4a6 100644 (file)
                                ISERT_MAX_TX_MISC_PDUS  + \
                                ISERT_MAX_RX_MISC_PDUS)
 
-#define ISER_RX_PAD_SIZE       (ISCSI_DEF_MAX_RECV_SEG_LEN + 4096 - \
-               (ISER_RX_PAYLOAD_SIZE + sizeof(u64) + sizeof(struct ib_sge) + \
-                sizeof(struct ib_cqe) + sizeof(bool)))
+/*
+ * RX size is default of 8k plus headers, but data needs to align to
+ * 512 boundary, so use 1024 to have the extra space for alignment.
+ */
+#define ISER_RX_SIZE           (ISCSI_DEF_MAX_RECV_SEG_LEN + 1024)
 
 /* Maximum support is 16MB I/O size */
 #define ISCSI_ISER_MAX_SG_TABLESIZE    4096
@@ -81,21 +83,41 @@ enum iser_conn_state {
 };
 
 struct iser_rx_desc {
-       struct iser_ctrl iser_header;
-       struct iscsi_hdr iscsi_header;
-       char            data[ISCSI_DEF_MAX_RECV_SEG_LEN];
+       char            buf[ISER_RX_SIZE];
        u64             dma_addr;
        struct ib_sge   rx_sg;
        struct ib_cqe   rx_cqe;
        bool            in_use;
-       char            pad[ISER_RX_PAD_SIZE];
-} __packed;
+};
 
 static inline struct iser_rx_desc *cqe_to_rx_desc(struct ib_cqe *cqe)
 {
        return container_of(cqe, struct iser_rx_desc, rx_cqe);
 }
 
+static void *isert_get_iser_hdr(struct iser_rx_desc *desc)
+{
+       return PTR_ALIGN(desc->buf + ISER_HEADERS_LEN, 512) - ISER_HEADERS_LEN;
+}
+
+static size_t isert_get_hdr_offset(struct iser_rx_desc *desc)
+{
+       return isert_get_iser_hdr(desc) - (void *)desc->buf;
+}
+
+static void *isert_get_iscsi_hdr(struct iser_rx_desc *desc)
+{
+       return isert_get_iser_hdr(desc) + sizeof(struct iser_ctrl);
+}
+
+static void *isert_get_data(struct iser_rx_desc *desc)
+{
+       void *data = isert_get_iser_hdr(desc) + ISER_HEADERS_LEN;
+
+       WARN_ON((uintptr_t)data & 511);
+       return data;
+}
+
 struct iser_tx_desc {
        struct iser_ctrl iser_header;
        struct iscsi_hdr iscsi_header;
@@ -142,9 +164,8 @@ struct isert_conn {
        u32                     responder_resources;
        u32                     initiator_depth;
        bool                    pi_support;
-       struct iser_rx_desc     *login_req_buf;
+       struct iser_rx_desc     *login_desc;
        char                    *login_rsp_buf;
-       u64                     login_req_dma;
        int                     login_req_len;
        u64                     login_rsp_dma;
        struct iser_rx_desc     *rx_descs;
index 3d78775..cf6a2be 100644 (file)
@@ -152,13 +152,6 @@ static struct attribute_group rtrs_srv_stats_attr_group = {
        .attrs = rtrs_srv_stats_attrs,
 };
 
-static void rtrs_srv_dev_release(struct device *dev)
-{
-       struct rtrs_srv *srv = container_of(dev, struct rtrs_srv, dev);
-
-       kfree(srv);
-}
-
 static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess)
 {
        struct rtrs_srv *srv = sess->srv;
@@ -172,7 +165,6 @@ static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess)
                goto unlock;
        }
        srv->dev.class = rtrs_dev_class;
-       srv->dev.release = rtrs_srv_dev_release;
        err = dev_set_name(&srv->dev, "%s", sess->s.sessname);
        if (err)
                goto unlock;
@@ -182,16 +174,16 @@ static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess)
         * sysfs files are created
         */
        dev_set_uevent_suppress(&srv->dev, true);
-       err = device_register(&srv->dev);
+       err = device_add(&srv->dev);
        if (err) {
-               pr_err("device_register(): %d\n", err);
+               pr_err("device_add(): %d\n", err);
                goto put;
        }
        srv->kobj_paths = kobject_create_and_add("paths", &srv->dev.kobj);
        if (!srv->kobj_paths) {
                err = -ENOMEM;
                pr_err("kobject_create_and_add(): %d\n", err);
-               device_unregister(&srv->dev);
+               device_del(&srv->dev);
                goto unlock;
        }
        dev_set_uevent_suppress(&srv->dev, false);
@@ -216,7 +208,7 @@ rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess)
                kobject_del(srv->kobj_paths);
                kobject_put(srv->kobj_paths);
                mutex_unlock(&srv->paths_mutex);
-               device_unregister(&srv->dev);
+               device_del(&srv->dev);
        } else {
                mutex_unlock(&srv->paths_mutex);
        }
index a219bd1..28f6414 100644 (file)
@@ -1319,6 +1319,13 @@ static int rtrs_srv_get_next_cq_vector(struct rtrs_srv_sess *sess)
        return sess->cur_cq_vector;
 }
 
+static void rtrs_srv_dev_release(struct device *dev)
+{
+       struct rtrs_srv *srv = container_of(dev, struct rtrs_srv, dev);
+
+       kfree(srv);
+}
+
 static struct rtrs_srv *__alloc_srv(struct rtrs_srv_ctx *ctx,
                                     const uuid_t *paths_uuid)
 {
@@ -1336,6 +1343,8 @@ static struct rtrs_srv *__alloc_srv(struct rtrs_srv_ctx *ctx,
        uuid_copy(&srv->paths_uuid, paths_uuid);
        srv->queue_depth = sess_queue_depth;
        srv->ctx = ctx;
+       device_initialize(&srv->dev);
+       srv->dev.release = rtrs_srv_dev_release;
 
        srv->chunks = kcalloc(srv->queue_depth, sizeof(*srv->chunks),
                              GFP_KERNEL);
index 3eefee2..ef2fa09 100644 (file)
 #include "trackpoint.h"
 
 static const char * const trackpoint_variants[] = {
-       [TP_VARIANT_IBM]        = "IBM",
-       [TP_VARIANT_ALPS]       = "ALPS",
-       [TP_VARIANT_ELAN]       = "Elan",
-       [TP_VARIANT_NXP]        = "NXP",
+       [TP_VARIANT_IBM]                = "IBM",
+       [TP_VARIANT_ALPS]               = "ALPS",
+       [TP_VARIANT_ELAN]               = "Elan",
+       [TP_VARIANT_NXP]                = "NXP",
+       [TP_VARIANT_JYT_SYNAPTICS]      = "JYT_Synaptics",
+       [TP_VARIANT_SYNAPTICS]          = "Synaptics",
 };
 
 /*
@@ -280,6 +282,8 @@ static int trackpoint_start_protocol(struct psmouse *psmouse,
        case TP_VARIANT_ALPS:
        case TP_VARIANT_ELAN:
        case TP_VARIANT_NXP:
+       case TP_VARIANT_JYT_SYNAPTICS:
+       case TP_VARIANT_SYNAPTICS:
                if (variant_id)
                        *variant_id = param[0];
                if (firmware_id)
index 5cb93ed..eb54129 100644 (file)
  * 0x01 was the original IBM trackpoint, others implement very limited
  * subset of trackpoint features.
  */
-#define TP_VARIANT_IBM         0x01
-#define TP_VARIANT_ALPS                0x02
-#define TP_VARIANT_ELAN                0x03
-#define TP_VARIANT_NXP         0x04
+#define TP_VARIANT_IBM                 0x01
+#define TP_VARIANT_ALPS                        0x02
+#define TP_VARIANT_ELAN                        0x03
+#define TP_VARIANT_NXP                 0x04
+#define TP_VARIANT_JYT_SYNAPTICS       0x05
+#define TP_VARIANT_SYNAPTICS           0x06
 
 /*
  * Commands
index 7d7f737..a4c9b96 100644 (file)
@@ -548,6 +548,14 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
                },
        },
+       {
+               /* Entroware Proteus */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Entroware"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),
+               },
+       },
        { }
 };
 
@@ -676,6 +684,14 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"),
                },
        },
+       {
+               /* Entroware Proteus */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Entroware"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),
+               },
+       },
        { }
 };
 
@@ -705,6 +721,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
                },
        },
+       {
+               /* Acer Aspire 5 A515 */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "Grumpy_PK"),
+                       DMI_MATCH(DMI_BOARD_VENDOR, "PK"),
+               },
+       },
        { }
 };
 
index befd111..cf07491 100644 (file)
@@ -55,12 +55,18 @@ static int icc_summary_show(struct seq_file *s, void *data)
 
                        icc_summary_show_one(s, n);
                        hlist_for_each_entry(r, &n->req_list, req_node) {
+                               u32 avg_bw = 0, peak_bw = 0;
+
                                if (!r->dev)
                                        continue;
 
+                               if (r->enabled) {
+                                       avg_bw = r->avg_bw;
+                                       peak_bw = r->peak_bw;
+                               }
+
                                seq_printf(s, "  %-27s %12u %12u %12u\n",
-                                          dev_name(r->dev), r->tag, r->avg_bw,
-                                          r->peak_bw);
+                                          dev_name(r->dev), r->tag, avg_bw, peak_bw);
                        }
                }
        }
index a3d2ef1..609db9c 100644 (file)
@@ -52,8 +52,20 @@ static int cmp_vcd(void *priv, struct list_head *a, struct list_head *b)
                return 1;
 }
 
+static u64 bcm_div(u64 num, u32 base)
+{
+       /* Ensure that small votes aren't lost. */
+       if (num && num < base)
+               return 1;
+
+       do_div(num, base);
+
+       return num;
+}
+
 static void bcm_aggregate(struct qcom_icc_bcm *bcm)
 {
+       struct qcom_icc_node *node;
        size_t i, bucket;
        u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0};
        u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0};
@@ -61,22 +73,21 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm)
 
        for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) {
                for (i = 0; i < bcm->num_nodes; i++) {
-                       temp = bcm->nodes[i]->sum_avg[bucket] * bcm->aux_data.width;
-                       do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels);
+                       node = bcm->nodes[i];
+                       temp = bcm_div(node->sum_avg[bucket] * bcm->aux_data.width,
+                                      node->buswidth * node->channels);
                        agg_avg[bucket] = max(agg_avg[bucket], temp);
 
-                       temp = bcm->nodes[i]->max_peak[bucket] * bcm->aux_data.width;
-                       do_div(temp, bcm->nodes[i]->buswidth);
+                       temp = bcm_div(node->max_peak[bucket] * bcm->aux_data.width,
+                                      node->buswidth);
                        agg_peak[bucket] = max(agg_peak[bucket], temp);
                }
 
                temp = agg_avg[bucket] * 1000ULL;
-               do_div(temp, bcm->aux_data.unit);
-               bcm->vote_x[bucket] = temp;
+               bcm->vote_x[bucket] = bcm_div(temp, bcm->aux_data.unit);
 
                temp = agg_peak[bucket] * 1000ULL;
-               do_div(temp, bcm->aux_data.unit);
-               bcm->vote_y[bucket] = temp;
+               bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit);
        }
 
        if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 &&
index 445a08d..1ba6b4c 100644 (file)
@@ -1104,25 +1104,6 @@ static int __init add_early_maps(void)
 }
 
 /*
- * Reads the device exclusion range from ACPI and initializes the IOMMU with
- * it
- */
-static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
-{
-       if (!(m->flags & IVMD_FLAG_EXCL_RANGE))
-               return;
-
-       /*
-        * Treat per-device exclusion ranges as r/w unity-mapped regions
-        * since some buggy BIOSes might lead to the overwritten exclusion
-        * range (exclusion_start and exclusion_length members). This
-        * happens when there are multiple exclusion ranges (IVMD entries)
-        * defined in ACPI table.
-        */
-       m->flags = (IVMD_FLAG_IW | IVMD_FLAG_IR | IVMD_FLAG_UNITY_MAP);
-}
-
-/*
  * Takes a pointer to an AMD IOMMU entry in the ACPI table and
  * initializes the hardware and our data structures with it.
  */
@@ -2073,30 +2054,6 @@ static void __init free_unity_maps(void)
        }
 }
 
-/* called when we find an exclusion range definition in ACPI */
-static int __init init_exclusion_range(struct ivmd_header *m)
-{
-       int i;
-
-       switch (m->type) {
-       case ACPI_IVMD_TYPE:
-               set_device_exclusion_range(m->devid, m);
-               break;
-       case ACPI_IVMD_TYPE_ALL:
-               for (i = 0; i <= amd_iommu_last_bdf; ++i)
-                       set_device_exclusion_range(i, m);
-               break;
-       case ACPI_IVMD_TYPE_RANGE:
-               for (i = m->devid; i <= m->aux; ++i)
-                       set_device_exclusion_range(i, m);
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
 /* called for unity map ACPI definition */
 static int __init init_unity_map_range(struct ivmd_header *m)
 {
@@ -2107,9 +2064,6 @@ static int __init init_unity_map_range(struct ivmd_header *m)
        if (e == NULL)
                return -ENOMEM;
 
-       if (m->flags & IVMD_FLAG_EXCL_RANGE)
-               init_exclusion_range(m);
-
        switch (m->type) {
        default:
                kfree(e);
@@ -2133,6 +2087,16 @@ static int __init init_unity_map_range(struct ivmd_header *m)
        e->address_end = e->address_start + PAGE_ALIGN(m->range_length);
        e->prot = m->flags >> 1;
 
+       /*
+        * Treat per-device exclusion ranges as r/w unity-mapped regions
+        * since some buggy BIOSes might lead to the overwritten exclusion
+        * range (exclusion_start and exclusion_length members). This
+        * happens when there are multiple exclusion ranges (IVMD entries)
+        * defined in ACPI table.
+        */
+       if (m->flags & IVMD_FLAG_EXCL_RANGE)
+               e->prot = (IVMD_FLAG_IW | IVMD_FLAG_IR) >> 1;
+
        DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
                    " range_start: %016llx range_end: %016llx flags: %x\n", s,
                    PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start),
index 07ae8b9..10e4200 100644 (file)
@@ -3840,14 +3840,18 @@ int amd_iommu_activate_guest_mode(void *data)
 {
        struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
        struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
+       u64 valid;
 
        if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
            !entry || entry->lo.fields_vapic.guest_mode)
                return 0;
 
+       valid = entry->lo.fields_vapic.valid;
+
        entry->lo.val = 0;
        entry->hi.val = 0;
 
+       entry->lo.fields_vapic.valid       = valid;
        entry->lo.fields_vapic.guest_mode  = 1;
        entry->lo.fields_vapic.ga_log_intr = 1;
        entry->hi.fields.ga_root_ptr       = ir_data->ga_root_ptr;
@@ -3864,12 +3868,14 @@ int amd_iommu_deactivate_guest_mode(void *data)
        struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
        struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
        struct irq_cfg *cfg = ir_data->cfg;
-       u64 valid = entry->lo.fields_remap.valid;
+       u64 valid;
 
        if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
            !entry || !entry->lo.fields_vapic.guest_mode)
                return 0;
 
+       valid = entry->lo.fields_remap.valid;
+
        entry->lo.val = 0;
        entry->hi.val = 0;
 
index bad3c0c..de324b4 100644 (file)
@@ -1295,13 +1295,17 @@ static int exynos_iommu_of_xlate(struct device *dev,
                return -ENODEV;
 
        data = platform_get_drvdata(sysmmu);
-       if (!data)
+       if (!data) {
+               put_device(&sysmmu->dev);
                return -ENODEV;
+       }
 
        if (!owner) {
                owner = kzalloc(sizeof(*owner), GFP_KERNEL);
-               if (!owner)
+               if (!owner) {
+                       put_device(&sysmmu->dev);
                        return -ENOMEM;
+               }
 
                INIT_LIST_HEAD(&owner->controllers);
                mutex_init(&owner->rpm_lock);
index 87b17ba..2239c21 100644 (file)
@@ -2664,7 +2664,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
                }
 
                /* Setup the PASID entry for requests without PASID: */
-               spin_lock(&iommu->lock);
+               spin_lock_irqsave(&iommu->lock, flags);
                if (hw_pass_through && domain_type_is_si(domain))
                        ret = intel_pasid_setup_pass_through(iommu, domain,
                                        dev, PASID_RID2PASID);
@@ -2674,7 +2674,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
                else
                        ret = intel_pasid_setup_second_level(iommu, domain,
                                        dev, PASID_RID2PASID);
-               spin_unlock(&iommu->lock);
+               spin_unlock_irqrestore(&iommu->lock, flags);
                if (ret) {
                        dev_err(dev, "Setup RID2PASID failed\n");
                        dmar_remove_one_dev_info(dev);
index 5edc307..229f461 100644 (file)
@@ -860,10 +860,14 @@ EXPORT_SYMBOL_GPL(dm_table_set_type);
 int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
                        sector_t start, sector_t len, void *data)
 {
-       int blocksize = *(int *) data;
+       int blocksize = *(int *) data, id;
+       bool rc;
 
-       return generic_fsdax_supported(dev->dax_dev, dev->bdev, blocksize,
-                                      start, len);
+       id = dax_read_lock();
+       rc = dax_supported(dev->dax_dev, dev->bdev, blocksize, start, len);
+       dax_read_unlock(id);
+
+       return rc;
 }
 
 /* Check devices support synchronous DAX */
index fb0255d..6ed05ca 100644 (file)
@@ -1136,15 +1136,16 @@ static bool dm_dax_supported(struct dax_device *dax_dev, struct block_device *bd
 {
        struct mapped_device *md = dax_get_private(dax_dev);
        struct dm_table *map;
+       bool ret = false;
        int srcu_idx;
-       bool ret;
 
        map = dm_get_live_table(md, &srcu_idx);
        if (!map)
-               return false;
+               goto out;
 
        ret = dm_table_supports_dax(map, device_supports_dax, &blocksize);
 
+out:
        dm_put_live_table(md, srcu_idx);
 
        return ret;
@@ -1723,23 +1724,6 @@ out:
        return ret;
 }
 
-static void dm_queue_split(struct mapped_device *md, struct dm_target *ti, struct bio **bio)
-{
-       unsigned len, sector_count;
-
-       sector_count = bio_sectors(*bio);
-       len = min_t(sector_t, max_io_len((*bio)->bi_iter.bi_sector, ti), sector_count);
-
-       if (sector_count > len) {
-               struct bio *split = bio_split(*bio, len, GFP_NOIO, &md->queue->bio_split);
-
-               bio_chain(split, *bio);
-               trace_block_split(md->queue, split, (*bio)->bi_iter.bi_sector);
-               submit_bio_noacct(*bio);
-               *bio = split;
-       }
-}
-
 static blk_qc_t dm_process_bio(struct mapped_device *md,
                               struct dm_table *map, struct bio *bio)
 {
@@ -1760,21 +1744,21 @@ static blk_qc_t dm_process_bio(struct mapped_device *md,
        }
 
        /*
-        * If in ->queue_bio we need to use blk_queue_split(), otherwise
+        * If in ->submit_bio we need to use blk_queue_split(), otherwise
         * queue_limits for abnormal requests (e.g. discard, writesame, etc)
         * won't be imposed.
+        * If called from dm_wq_work() for deferred bio processing, bio
+        * was already handled by following code with previous ->submit_bio.
         */
        if (current->bio_list) {
                if (is_abnormal_io(bio))
                        blk_queue_split(&bio);
-               else
-                       dm_queue_split(md, ti, &bio);
+               /* regular IO is split by __split_and_process_bio */
        }
 
        if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
                return __process_bio(md, map, bio, ti);
-       else
-               return __split_and_process_bio(md, map, bio);
+       return __split_and_process_bio(md, map, bio);
 }
 
 static blk_qc_t dm_submit_bio(struct bio *bio)
index 4efe801..926d65d 100644 (file)
@@ -1199,7 +1199,7 @@ void cec_received_msg_ts(struct cec_adapter *adap,
                        /* Cancel the pending timeout work */
                        if (!cancel_delayed_work(&data->work)) {
                                mutex_unlock(&adap->lock);
-                               flush_scheduled_work();
+                               cancel_delayed_work_sync(&data->work);
                                mutex_lock(&adap->lock);
                        }
                        /*
index f544d33..4eab6d8 100644 (file)
@@ -721,39 +721,14 @@ int vb2_verify_memory_type(struct vb2_queue *q,
 }
 EXPORT_SYMBOL(vb2_verify_memory_type);
 
-static void set_queue_consistency(struct vb2_queue *q, bool consistent_mem)
-{
-       q->dma_attrs &= ~DMA_ATTR_NON_CONSISTENT;
-
-       if (!vb2_queue_allows_cache_hints(q))
-               return;
-       if (!consistent_mem)
-               q->dma_attrs |= DMA_ATTR_NON_CONSISTENT;
-}
-
-static bool verify_consistency_attr(struct vb2_queue *q, bool consistent_mem)
-{
-       bool queue_is_consistent = !(q->dma_attrs & DMA_ATTR_NON_CONSISTENT);
-
-       if (consistent_mem != queue_is_consistent) {
-               dprintk(q, 1, "memory consistency model mismatch\n");
-               return false;
-       }
-       return true;
-}
-
 int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
-                    unsigned int flags, unsigned int *count)
+                    unsigned int *count)
 {
        unsigned int num_buffers, allocated_buffers, num_planes = 0;
        unsigned plane_sizes[VB2_MAX_PLANES] = { };
-       bool consistent_mem = true;
        unsigned int i;
        int ret;
 
-       if (flags & V4L2_FLAG_MEMORY_NON_CONSISTENT)
-               consistent_mem = false;
-
        if (q->streaming) {
                dprintk(q, 1, "streaming active\n");
                return -EBUSY;
@@ -765,8 +740,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
        }
 
        if (*count == 0 || q->num_buffers != 0 ||
-           (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory) ||
-           !verify_consistency_attr(q, consistent_mem)) {
+           (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) {
                /*
                 * We already have buffers allocated, so first check if they
                 * are not in use and can be freed.
@@ -803,7 +777,6 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
        num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
        memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
        q->memory = memory;
-       set_queue_consistency(q, consistent_mem);
 
        /*
         * Ask the driver how many buffers and planes per buffer it requires.
@@ -888,18 +861,14 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
 EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
 
 int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
-                        unsigned int flags, unsigned int *count,
+                        unsigned int *count,
                         unsigned int requested_planes,
                         const unsigned int requested_sizes[])
 {
        unsigned int num_planes = 0, num_buffers, allocated_buffers;
        unsigned plane_sizes[VB2_MAX_PLANES] = { };
-       bool consistent_mem = true;
        int ret;
 
-       if (flags & V4L2_FLAG_MEMORY_NON_CONSISTENT)
-               consistent_mem = false;
-
        if (q->num_buffers == VB2_MAX_FRAME) {
                dprintk(q, 1, "maximum number of buffers already allocated\n");
                return -ENOBUFS;
@@ -912,15 +881,12 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
                }
                memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
                q->memory = memory;
-               set_queue_consistency(q, consistent_mem);
                q->waiting_for_buffers = !q->is_output;
        } else {
                if (q->memory != memory) {
                        dprintk(q, 1, "memory model mismatch\n");
                        return -EINVAL;
                }
-               if (!verify_consistency_attr(q, consistent_mem))
-                       return -EINVAL;
        }
 
        num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
@@ -2581,7 +2547,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
        fileio->memory = VB2_MEMORY_MMAP;
        fileio->type = q->type;
        q->fileio = fileio;
-       ret = vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
+       ret = vb2_core_reqbufs(q, fileio->memory, &fileio->count);
        if (ret)
                goto err_kfree;
 
@@ -2638,7 +2604,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 
 err_reqbufs:
        fileio->count = 0;
-       vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
+       vb2_core_reqbufs(q, fileio->memory, &fileio->count);
 
 err_kfree:
        q->fileio = NULL;
@@ -2658,7 +2624,7 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q)
                vb2_core_streamoff(q, q->type);
                q->fileio = NULL;
                fileio->count = 0;
-               vb2_core_reqbufs(q, fileio->memory, 0, &fileio->count);
+               vb2_core_reqbufs(q, fileio->memory, &fileio->count);
                kfree(fileio);
                dprintk(q, 3, "file io emulator closed\n");
        }
index ec3446c..7b1b86e 100644 (file)
@@ -42,11 +42,6 @@ struct vb2_dc_buf {
        struct dma_buf_attachment       *db_attach;
 };
 
-static inline bool vb2_dc_buffer_consistent(unsigned long attr)
-{
-       return !(attr & DMA_ATTR_NON_CONSISTENT);
-}
-
 /*********************************************/
 /*        scatterlist table functions        */
 /*********************************************/
@@ -341,13 +336,6 @@ static int
 vb2_dc_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
                                   enum dma_data_direction direction)
 {
-       struct vb2_dc_buf *buf = dbuf->priv;
-       struct sg_table *sgt = buf->dma_sgt;
-
-       if (vb2_dc_buffer_consistent(buf->attrs))
-               return 0;
-
-       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
        return 0;
 }
 
@@ -355,13 +343,6 @@ static int
 vb2_dc_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
                                 enum dma_data_direction direction)
 {
-       struct vb2_dc_buf *buf = dbuf->priv;
-       struct sg_table *sgt = buf->dma_sgt;
-
-       if (vb2_dc_buffer_consistent(buf->attrs))
-               return 0;
-
-       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
        return 0;
 }
 
index 0a40e00..a86fce5 100644 (file)
@@ -123,8 +123,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs,
        /*
         * NOTE: dma-sg allocates memory using the page allocator directly, so
         * there is no memory consistency guarantee, hence dma-sg ignores DMA
-        * attributes passed from the upper layer. That means that
-        * V4L2_FLAG_MEMORY_NON_CONSISTENT has no effect on dma-sg buffers.
+        * attributes passed from the upper layer.
         */
        buf->pages = kvmalloc_array(buf->num_pages, sizeof(struct page *),
                                    GFP_KERNEL | __GFP_ZERO);
index 30caad2..cfe197d 100644 (file)
@@ -722,22 +722,12 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps)
 #endif
 }
 
-static void clear_consistency_attr(struct vb2_queue *q,
-                                  int memory,
-                                  unsigned int *flags)
-{
-       if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP)
-               *flags &= ~V4L2_FLAG_MEMORY_NON_CONSISTENT;
-}
-
 int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 {
        int ret = vb2_verify_memory_type(q, req->memory, req->type);
 
        fill_buf_caps(q, &req->capabilities);
-       clear_consistency_attr(q, req->memory, &req->flags);
-       return ret ? ret : vb2_core_reqbufs(q, req->memory,
-                                           req->flags, &req->count);
+       return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
 }
 EXPORT_SYMBOL_GPL(vb2_reqbufs);
 
@@ -769,7 +759,6 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
        unsigned i;
 
        fill_buf_caps(q, &create->capabilities);
-       clear_consistency_attr(q, create->memory, &create->flags);
        create->index = q->num_buffers;
        if (create->count == 0)
                return ret != -EBUSY ? ret : 0;
@@ -813,7 +802,6 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
                if (requested_sizes[i] == 0)
                        return -EINVAL;
        return ret ? ret : vb2_core_create_bufs(q, create->memory,
-                                               create->flags,
                                                &create->count,
                                                requested_planes,
                                                requested_sizes);
@@ -998,12 +986,11 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv,
        int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
 
        fill_buf_caps(vdev->queue, &p->capabilities);
-       clear_consistency_attr(vdev->queue, p->memory, &p->flags);
        if (res)
                return res;
        if (vb2_queue_is_busy(vdev, file))
                return -EBUSY;
-       res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count);
+       res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
        /* If count == 0, then the owner has released all buffers and he
           is no longer owner of the queue. Otherwise we have a new owner. */
        if (res == 0)
@@ -1021,7 +1008,6 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
 
        p->index = vdev->queue->num_buffers;
        fill_buf_caps(vdev->queue, &p->capabilities);
-       clear_consistency_attr(vdev->queue, p->memory, &p->flags);
        /*
         * If count == 0, then just check if memory and type are valid.
         * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0.
index 959d110..6974f17 100644 (file)
@@ -342,7 +342,7 @@ int dvb_vb2_reqbufs(struct dvb_vb2_ctx *ctx, struct dmx_requestbuffers *req)
 
        ctx->buf_siz = req->size;
        ctx->buf_cnt = req->count;
-       ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, 0, &req->count);
+       ret = vb2_core_reqbufs(&ctx->vb_q, VB2_MEMORY_MMAP, &req->count);
        if (ret) {
                ctx->state = DVB_VB2_STATE_NONE;
                dprintk(1, "[%s] count=%d size=%d errno=%d\n", ctx->name,
index 593bcf6..a99e82e 100644 (file)
@@ -246,9 +246,6 @@ struct v4l2_format32 {
  * @memory:    buffer memory type
  * @format:    frame format, for which buffers are requested
  * @capabilities: capabilities of this buffer type.
- * @flags:     additional buffer management attributes (ignored unless the
- *             queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
- *             configured for MMAP streaming I/O).
  * @reserved:  future extensions
  */
 struct v4l2_create_buffers32 {
@@ -257,8 +254,7 @@ struct v4l2_create_buffers32 {
        __u32                   memory; /* enum v4l2_memory */
        struct v4l2_format32    format;
        __u32                   capabilities;
-       __u32                   flags;
-       __u32                   reserved[6];
+       __u32                   reserved[7];
 };
 
 static int __bufsize_v4l2_format(struct v4l2_format32 __user *p32, u32 *size)
@@ -359,8 +355,7 @@ static int get_v4l2_create32(struct v4l2_create_buffers __user *p64,
 {
        if (!access_ok(p32, sizeof(*p32)) ||
            copy_in_user(p64, p32,
-                        offsetof(struct v4l2_create_buffers32, format)) ||
-           assign_in_user(&p64->flags, &p32->flags))
+                        offsetof(struct v4l2_create_buffers32, format)))
                return -EFAULT;
        return __get_v4l2_format32(&p64->format, &p32->format,
                                   aux_buf, aux_space);
@@ -422,7 +417,6 @@ static int put_v4l2_create32(struct v4l2_create_buffers __user *p64,
            copy_in_user(p32, p64,
                         offsetof(struct v4l2_create_buffers32, format)) ||
            assign_in_user(&p32->capabilities, &p64->capabilities) ||
-           assign_in_user(&p32->flags, &p64->flags) ||
            copy_in_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
                return -EFAULT;
        return __put_v4l2_format32(&p64->format, &p32->format);
index f74b422..eeff398 100644 (file)
@@ -2042,6 +2042,9 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
 
        if (ret)
                return ret;
+
+       CLEAR_AFTER_FIELD(p, capabilities);
+
        return ops->vidioc_reqbufs(file, fh, p);
 }
 
@@ -2081,7 +2084,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
        if (ret)
                return ret;
 
-       CLEAR_AFTER_FIELD(create, flags);
+       CLEAR_AFTER_FIELD(create, capabilities);
 
        v4l_sanitize_format(&create->format);
 
index 2591c21..26a23ab 100644 (file)
@@ -692,10 +692,6 @@ static int at24_probe(struct i2c_client *client)
        nvmem_config.word_size = 1;
        nvmem_config.size = byte_len;
 
-       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
-       if (IS_ERR(at24->nvmem))
-               return PTR_ERR(at24->nvmem);
-
        i2c_set_clientdata(client, at24);
 
        err = regulator_enable(at24->vcc_reg);
@@ -708,6 +704,13 @@ static int at24_probe(struct i2c_client *client)
        pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
 
+       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
+       if (IS_ERR(at24->nvmem)) {
+               pm_runtime_disable(dev);
+               regulator_disable(at24->vcc_reg);
+               return PTR_ERR(at24->nvmem);
+       }
+
        /*
         * Perform a one-byte test read to verify that the
         * chip is functional.
index 37701e4..aa77771 100644 (file)
@@ -982,7 +982,7 @@ static ssize_t hl_clk_gate_read(struct file *f, char __user *buf,
                return 0;
 
        sprintf(tmp_buf, "0x%llx\n", hdev->clock_gating_mask);
-       rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
+       rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
                        strlen(tmp_buf) + 1);
 
        return rc;
index 13ef6b2..3510c42 100644 (file)
@@ -378,15 +378,15 @@ enum axi_id {
        ((((y) & RAZWI_INITIATOR_Y_MASK) << RAZWI_INITIATOR_Y_SHIFT) | \
                (((x) & RAZWI_INITIATOR_X_MASK) << RAZWI_INITIATOR_X_SHIFT))
 
-#define RAZWI_INITIATOR_ID_X_Y_TPC0_NIC0       RAZWI_INITIATOR_ID_X_Y(1, 0)
-#define RAZWI_INITIATOR_ID_X_Y_TPC1            RAZWI_INITIATOR_ID_X_Y(2, 0)
-#define RAZWI_INITIATOR_ID_X_Y_MME0_0          RAZWI_INITIATOR_ID_X_Y(3, 0)
-#define RAZWI_INITIATOR_ID_X_Y_MME0_1          RAZWI_INITIATOR_ID_X_Y(4, 0)
-#define RAZWI_INITIATOR_ID_X_Y_MME1_0          RAZWI_INITIATOR_ID_X_Y(5, 0)
-#define RAZWI_INITIATOR_ID_X_Y_MME1_1          RAZWI_INITIATOR_ID_X_Y(6, 0)
-#define RAZWI_INITIATOR_ID_X_Y_TPC2            RAZWI_INITIATOR_ID_X_Y(7, 0)
+#define RAZWI_INITIATOR_ID_X_Y_TPC0_NIC0       RAZWI_INITIATOR_ID_X_Y(1, 1)
+#define RAZWI_INITIATOR_ID_X_Y_TPC1            RAZWI_INITIATOR_ID_X_Y(2, 1)
+#define RAZWI_INITIATOR_ID_X_Y_MME0_0          RAZWI_INITIATOR_ID_X_Y(3, 1)
+#define RAZWI_INITIATOR_ID_X_Y_MME0_1          RAZWI_INITIATOR_ID_X_Y(4, 1)
+#define RAZWI_INITIATOR_ID_X_Y_MME1_0          RAZWI_INITIATOR_ID_X_Y(5, 1)
+#define RAZWI_INITIATOR_ID_X_Y_MME1_1          RAZWI_INITIATOR_ID_X_Y(6, 1)
+#define RAZWI_INITIATOR_ID_X_Y_TPC2            RAZWI_INITIATOR_ID_X_Y(7, 1)
 #define RAZWI_INITIATOR_ID_X_Y_TPC3_PCI_CPU_PSOC \
-                                               RAZWI_INITIATOR_ID_X_Y(8, 0)
+                                               RAZWI_INITIATOR_ID_X_Y(8, 1)
 #define RAZWI_INITIATOR_ID_X_Y_DMA_IF_W_S_0    RAZWI_INITIATOR_ID_X_Y(0, 1)
 #define RAZWI_INITIATOR_ID_X_Y_DMA_IF_E_S_0    RAZWI_INITIATOR_ID_X_Y(9, 1)
 #define RAZWI_INITIATOR_ID_X_Y_DMA_IF_W_S_1    RAZWI_INITIATOR_ID_X_Y(0, 2)
@@ -395,14 +395,14 @@ enum axi_id {
 #define RAZWI_INITIATOR_ID_X_Y_DMA_IF_E_N_0    RAZWI_INITIATOR_ID_X_Y(9, 3)
 #define RAZWI_INITIATOR_ID_X_Y_DMA_IF_W_N_1    RAZWI_INITIATOR_ID_X_Y(0, 4)
 #define RAZWI_INITIATOR_ID_X_Y_DMA_IF_E_N_1    RAZWI_INITIATOR_ID_X_Y(9, 4)
-#define RAZWI_INITIATOR_ID_X_Y_TPC4_NIC1_NIC2  RAZWI_INITIATOR_ID_X_Y(1, 5)
-#define RAZWI_INITIATOR_ID_X_Y_TPC5            RAZWI_INITIATOR_ID_X_Y(2, 5)
-#define RAZWI_INITIATOR_ID_X_Y_MME2_0          RAZWI_INITIATOR_ID_X_Y(3, 5)
-#define RAZWI_INITIATOR_ID_X_Y_MME2_1          RAZWI_INITIATOR_ID_X_Y(4, 5)
-#define RAZWI_INITIATOR_ID_X_Y_MME3_0          RAZWI_INITIATOR_ID_X_Y(5, 5)
-#define RAZWI_INITIATOR_ID_X_Y_MME3_1          RAZWI_INITIATOR_ID_X_Y(6, 5)
-#define RAZWI_INITIATOR_ID_X_Y_TPC6            RAZWI_INITIATOR_ID_X_Y(7, 5)
-#define RAZWI_INITIATOR_ID_X_Y_TPC7_NIC4_NIC5  RAZWI_INITIATOR_ID_X_Y(8, 5)
+#define RAZWI_INITIATOR_ID_X_Y_TPC4_NIC1_NIC2  RAZWI_INITIATOR_ID_X_Y(1, 6)
+#define RAZWI_INITIATOR_ID_X_Y_TPC5            RAZWI_INITIATOR_ID_X_Y(2, 6)
+#define RAZWI_INITIATOR_ID_X_Y_MME2_0          RAZWI_INITIATOR_ID_X_Y(3, 6)
+#define RAZWI_INITIATOR_ID_X_Y_MME2_1          RAZWI_INITIATOR_ID_X_Y(4, 6)
+#define RAZWI_INITIATOR_ID_X_Y_MME3_0          RAZWI_INITIATOR_ID_X_Y(5, 6)
+#define RAZWI_INITIATOR_ID_X_Y_MME3_1          RAZWI_INITIATOR_ID_X_Y(6, 6)
+#define RAZWI_INITIATOR_ID_X_Y_TPC6            RAZWI_INITIATOR_ID_X_Y(7, 6)
+#define RAZWI_INITIATOR_ID_X_Y_TPC7_NIC4_NIC5  RAZWI_INITIATOR_ID_X_Y(8, 6)
 
 #define PSOC_ETR_AXICTL_PROTCTRLBIT1_SHIFT                           1
 
index 65eff4c..0369d98 100644 (file)
@@ -1907,16 +1907,15 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 }
 
 /**
- * spi_nor_sr1_bit6_quad_enable() - Set/Unset the Quad Enable BIT(6) in the
- *                                  Status Register 1.
+ * spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status
+ * Register 1.
  * @nor:       pointer to a 'struct spi_nor'
- * @enable:    true to enable Quad mode, false to disable Quad mode.
  *
  * Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI memories.
  *
  * Return: 0 on success, -errno otherwise.
  */
-int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor, bool enable)
+int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
 {
        int ret;
 
@@ -1924,56 +1923,45 @@ int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor, bool enable)
        if (ret)
                return ret;
 
-       if ((enable && (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)) ||
-           (!enable && !(nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)))
+       if (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)
                return 0;
 
-       if (enable)
-               nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6;
-       else
-               nor->bouncebuf[0] &= ~SR1_QUAD_EN_BIT6;
+       nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6;
 
        return spi_nor_write_sr1_and_check(nor, nor->bouncebuf[0]);
 }
 
 /**
- * spi_nor_sr2_bit1_quad_enable() - set/unset the Quad Enable BIT(1) in the
- *                                  Status Register 2.
+ * spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Status
+ * Register 2.
  * @nor:       pointer to a 'struct spi_nor'.
- * @enable:    true to enable Quad mode, false to disable Quad mode.
  *
  * Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI memories.
  *
  * Return: 0 on success, -errno otherwise.
  */
-int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor, bool enable)
+int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
 {
        int ret;
 
        if (nor->flags & SNOR_F_NO_READ_CR)
-               return spi_nor_write_16bit_cr_and_check(nor,
-                                               enable ? SR2_QUAD_EN_BIT1 : 0);
+               return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1);
 
        ret = spi_nor_read_cr(nor, nor->bouncebuf);
        if (ret)
                return ret;
 
-       if ((enable && (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)) ||
-           (!enable && !(nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)))
+       if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)
                return 0;
 
-       if (enable)
-               nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1;
-       else
-               nor->bouncebuf[0] &= ~SR2_QUAD_EN_BIT1;
+       nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1;
 
        return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]);
 }
 
 /**
- * spi_nor_sr2_bit7_quad_enable() - set/unset QE bit in Status Register 2.
+ * spi_nor_sr2_bit7_quad_enable() - set QE bit in Status Register 2.
  * @nor:       pointer to a 'struct spi_nor'
- * @enable:    true to enable Quad mode, false to disable Quad mode.
  *
  * Set the Quad Enable (QE) bit in the Status Register 2.
  *
@@ -1983,7 +1971,7 @@ int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor, bool enable)
  *
  * Return: 0 on success, -errno otherwise.
  */
-int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor, bool enable)
+int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
 {
        u8 *sr2 = nor->bouncebuf;
        int ret;
@@ -1993,15 +1981,11 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor, bool enable)
        ret = spi_nor_read_sr2(nor, sr2);
        if (ret)
                return ret;
-       if ((enable && (*sr2 & SR2_QUAD_EN_BIT7)) ||
-           (!enable && !(*sr2 & SR2_QUAD_EN_BIT7)))
+       if (*sr2 & SR2_QUAD_EN_BIT7)
                return 0;
 
        /* Update the Quad Enable bit. */
-       if (enable)
-               *sr2 |= SR2_QUAD_EN_BIT7;
-       else
-               *sr2 &= ~SR2_QUAD_EN_BIT7;
+       *sr2 |= SR2_QUAD_EN_BIT7;
 
        ret = spi_nor_write_sr2(nor, sr2);
        if (ret)
@@ -2914,13 +2898,12 @@ static int spi_nor_init_params(struct spi_nor *nor)
 }
 
 /**
- * spi_nor_quad_enable() - enable/disable Quad I/O if needed.
+ * spi_nor_quad_enable() - enable Quad I/O if needed.
  * @nor:                pointer to a 'struct spi_nor'
- * @enable:             true to enable Quad mode. false to disable Quad mode.
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_quad_enable(struct spi_nor *nor, bool enable)
+static int spi_nor_quad_enable(struct spi_nor *nor)
 {
        if (!nor->params->quad_enable)
                return 0;
@@ -2929,7 +2912,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor, bool enable)
              spi_nor_get_protocol_width(nor->write_proto) == 4))
                return 0;
 
-       return nor->params->quad_enable(nor, enable);
+       return nor->params->quad_enable(nor);
 }
 
 /**
@@ -2953,7 +2936,7 @@ static int spi_nor_init(struct spi_nor *nor)
 {
        int err;
 
-       err = spi_nor_quad_enable(nor, true);
+       err = spi_nor_quad_enable(nor);
        if (err) {
                dev_dbg(nor->dev, "quad mode not supported\n");
                return err;
@@ -3000,8 +2983,6 @@ void spi_nor_restore(struct spi_nor *nor)
        if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
            nor->flags & SNOR_F_BROKEN_RESET)
                nor->params->set_4byte_addr_mode(nor, false);
-
-       spi_nor_quad_enable(nor, false);
 }
 EXPORT_SYMBOL_GPL(spi_nor_restore);
 
index 95aa32f..6f2f6b2 100644 (file)
@@ -198,7 +198,7 @@ struct spi_nor_locking_ops {
  *                      higher index in the array, the higher priority.
  * @erase_map:         the erase map parsed from the SFDP Sector Map Parameter
  *                      Table.
- * @quad_enable:       enables/disables SPI NOR Quad mode.
+ * @quad_enable:       enables SPI NOR quad mode.
  * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
  * @convert_addr:      converts an absolute address into something the flash
  *                      will understand. Particularly useful when pagesize is
@@ -219,7 +219,7 @@ struct spi_nor_flash_parameter {
 
        struct spi_nor_erase_map        erase_map;
 
-       int (*quad_enable)(struct spi_nor *nor, bool enable);
+       int (*quad_enable)(struct spi_nor *nor);
        int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable);
        u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
        int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
@@ -406,9 +406,9 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
 int spi_nor_wait_till_ready(struct spi_nor *nor);
 int spi_nor_lock_and_prep(struct spi_nor *nor);
 void spi_nor_unlock_and_unprep(struct spi_nor *nor);
-int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor, bool enable);
-int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor, bool enable);
-int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor, bool enable);
+int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor);
+int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor);
+int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor);
 
 int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr);
 ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
index 4e1b7de..c3091e0 100644 (file)
@@ -942,9 +942,10 @@ struct alb_walk_data {
        bool strict_match;
 };
 
-static int alb_upper_dev_walk(struct net_device *upper, void *_data)
+static int alb_upper_dev_walk(struct net_device *upper,
+                             struct netdev_nested_priv *priv)
 {
-       struct alb_walk_data *data = _data;
+       struct alb_walk_data *data = (struct alb_walk_data *)priv->data;
        bool strict_match = data->strict_match;
        struct bonding *bond = data->bond;
        struct slave *slave = data->slave;
@@ -983,6 +984,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
                                      bool strict_match)
 {
        struct bonding *bond = bond_get_bond_by_slave(slave);
+       struct netdev_nested_priv priv;
        struct alb_walk_data data = {
                .strict_match = strict_match,
                .mac_addr = mac_addr,
@@ -990,6 +992,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
                .bond = bond,
        };
 
+       priv.data = (void *)&data;
        /* send untagged */
        alb_send_lp_vid(slave, mac_addr, 0, 0);
 
@@ -997,7 +1000,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
         * for that device.
         */
        rcu_read_lock();
-       netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &data);
+       netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &priv);
        rcu_read_unlock();
 }
 
index 42ef25e..84ecbc6 100644 (file)
@@ -1315,6 +1315,7 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
 
        bond_dev->type              = slave_dev->type;
        bond_dev->hard_header_len   = slave_dev->hard_header_len;
+       bond_dev->needed_headroom   = slave_dev->needed_headroom;
        bond_dev->addr_len          = slave_dev->addr_len;
 
        memcpy(bond_dev->broadcast, slave_dev->broadcast,
@@ -2510,22 +2511,26 @@ re_arm:
        }
 }
 
-static int bond_upper_dev_walk(struct net_device *upper, void *data)
+static int bond_upper_dev_walk(struct net_device *upper,
+                              struct netdev_nested_priv *priv)
 {
-       __be32 ip = *((__be32 *)data);
+       __be32 ip = *(__be32 *)priv->data;
 
        return ip == bond_confirm_addr(upper, 0, ip);
 }
 
 static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)&ip,
+       };
        bool ret = false;
 
        if (ip == bond_confirm_addr(bond->dev, 0, ip))
                return true;
 
        rcu_read_lock();
-       if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_upper_dev_walk, &ip))
+       if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_upper_dev_walk, &priv))
                ret = true;
        rcu_read_unlock();
 
index 8f1d15e..f5779e1 100644 (file)
@@ -932,11 +932,19 @@ static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port)
        ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true);
 
        if (cpu_port) {
+               if (!p->interface && dev->compat_interface) {
+                       dev_warn(dev->dev,
+                                "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. "
+                                "Please update your device tree.\n",
+                                port);
+                       p->interface = dev->compat_interface;
+               }
+
                /* Configure MII interface for proper network communication. */
                ksz_read8(dev, REG_PORT_5_CTRL_6, &data8);
                data8 &= ~PORT_INTERFACE_TYPE;
                data8 &= ~PORT_GMII_1GPS_MODE;
-               switch (dev->interface) {
+               switch (p->interface) {
                case PHY_INTERFACE_MODE_MII:
                        p->phydev.speed = SPEED_100;
                        break;
@@ -952,11 +960,11 @@ static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port)
                default:
                        data8 &= ~PORT_RGMII_ID_IN_ENABLE;
                        data8 &= ~PORT_RGMII_ID_OUT_ENABLE;
-                       if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-                           dev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+                       if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                           p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
                                data8 |= PORT_RGMII_ID_IN_ENABLE;
-                       if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-                           dev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+                       if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                           p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
                                data8 |= PORT_RGMII_ID_OUT_ENABLE;
                        data8 |= PORT_GMII_1GPS_MODE;
                        data8 |= PORT_INTERFACE_RGMII;
@@ -1252,7 +1260,7 @@ static int ksz8795_switch_init(struct ksz_device *dev)
        }
 
        /* set the real number of ports */
-       dev->ds->num_ports = dev->port_cnt;
+       dev->ds->num_ports = dev->port_cnt + 1;
 
        return 0;
 }
index 3cb22d1..2f5506a 100644 (file)
@@ -1208,7 +1208,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 
                /* configure MAC to 1G & RGMII mode */
                ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
-               switch (dev->interface) {
+               switch (p->interface) {
                case PHY_INTERFACE_MODE_MII:
                        ksz9477_set_xmii(dev, 0, &data8);
                        ksz9477_set_gbit(dev, false, &data8);
@@ -1229,11 +1229,11 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
                        ksz9477_set_gbit(dev, true, &data8);
                        data8 &= ~PORT_RGMII_ID_IG_ENABLE;
                        data8 &= ~PORT_RGMII_ID_EG_ENABLE;
-                       if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-                           dev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+                       if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                           p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
                                data8 |= PORT_RGMII_ID_IG_ENABLE;
-                       if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-                           dev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+                       if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                           p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
                                data8 |= PORT_RGMII_ID_EG_ENABLE;
                        p->phydev.speed = SPEED_1000;
                        break;
@@ -1269,23 +1269,32 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
                        dev->cpu_port = i;
                        dev->host_mask = (1 << dev->cpu_port);
                        dev->port_mask |= dev->host_mask;
+                       p = &dev->ports[i];
 
                        /* Read from XMII register to determine host port
                         * interface.  If set specifically in device tree
                         * note the difference to help debugging.
                         */
                        interface = ksz9477_get_interface(dev, i);
-                       if (!dev->interface)
-                               dev->interface = interface;
-                       if (interface && interface != dev->interface)
+                       if (!p->interface) {
+                               if (dev->compat_interface) {
+                                       dev_warn(dev->dev,
+                                                "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. "
+                                                "Please update your device tree.\n",
+                                                i);
+                                       p->interface = dev->compat_interface;
+                               } else {
+                                       p->interface = interface;
+                               }
+                       }
+                       if (interface && interface != p->interface)
                                dev_info(dev->dev,
                                         "use %s instead of %s\n",
-                                         phy_modes(dev->interface),
+                                         phy_modes(p->interface),
                                          phy_modes(interface));
 
                        /* enable cpu port */
                        ksz9477_port_setup(dev, i, true);
-                       p = &dev->ports[dev->cpu_port];
                        p->vid_member = dev->port_mask;
                        p->on = 1;
                }
index 8d53b12..c796d42 100644 (file)
@@ -387,7 +387,9 @@ EXPORT_SYMBOL(ksz_switch_alloc);
 int ksz_switch_register(struct ksz_device *dev,
                        const struct ksz_dev_ops *ops)
 {
+       struct device_node *port, *ports;
        phy_interface_t interface;
+       unsigned int port_num;
        int ret;
 
        if (dev->pdata)
@@ -421,10 +423,23 @@ int ksz_switch_register(struct ksz_device *dev,
        /* Host port interface will be self detected, or specifically set in
         * device tree.
         */
+       for (port_num = 0; port_num < dev->port_cnt; ++port_num)
+               dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA;
        if (dev->dev->of_node) {
                ret = of_get_phy_mode(dev->dev->of_node, &interface);
                if (ret == 0)
-                       dev->interface = interface;
+                       dev->compat_interface = interface;
+               ports = of_get_child_by_name(dev->dev->of_node, "ports");
+               if (ports)
+                       for_each_available_child_of_node(ports, port) {
+                               if (of_property_read_u32(port, "reg",
+                                                        &port_num))
+                                       continue;
+                               if (port_num >= dev->port_cnt)
+                                       return -EINVAL;
+                               of_get_phy_mode(port,
+                                               &dev->ports[port_num].interface);
+                       }
                dev->synclko_125 = of_property_read_bool(dev->dev->of_node,
                                                         "microchip,synclko-125");
        }
index 2068381..cf866e4 100644 (file)
@@ -39,6 +39,7 @@ struct ksz_port {
        u32 freeze:1;                   /* MIB counter freeze is enabled */
 
        struct ksz_port_mib mib;
+       phy_interface_t interface;
 };
 
 struct ksz_device {
@@ -72,7 +73,7 @@ struct ksz_device {
        int mib_cnt;
        int mib_port_cnt;
        int last_port;                  /* ports after that not used */
-       phy_interface_t interface;
+       phy_interface_t compat_interface;
        u32 regs_size;
        bool phy_errata_9477;
        bool synclko_125;
index 04bfa6e..01427cd 100644 (file)
@@ -585,7 +585,10 @@ static int felix_setup(struct dsa_switch *ds)
        if (err)
                return err;
 
-       ocelot_init(ocelot);
+       err = ocelot_init(ocelot);
+       if (err)
+               return err;
+
        if (ocelot->ptp) {
                err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
                if (err) {
@@ -640,10 +643,13 @@ static void felix_teardown(struct dsa_switch *ds)
 {
        struct ocelot *ocelot = ds->priv;
        struct felix *felix = ocelot_to_felix(ocelot);
+       int port;
 
        if (felix->info->mdio_bus_free)
                felix->info->mdio_bus_free(ocelot);
 
+       for (port = 0; port < ocelot->num_phys_ports; port++)
+               ocelot_deinit_port(ocelot, port);
        ocelot_deinit_timestamp(ocelot);
        /* stop workqueue thread */
        ocelot_deinit(ocelot);
index 9b720c8..3a96374 100644 (file)
@@ -645,17 +645,17 @@ static struct vcap_field vsc9959_vcap_is2_keys[] = {
        [VCAP_IS2_HK_DIP_EQ_SIP]                = {118,   1},
        /* IP4_TCP_UDP (TYPE=100) */
        [VCAP_IS2_HK_TCP]                       = {119,   1},
-       [VCAP_IS2_HK_L4_SPORT]                  = {120,  16},
-       [VCAP_IS2_HK_L4_DPORT]                  = {136,  16},
+       [VCAP_IS2_HK_L4_DPORT]                  = {120,  16},
+       [VCAP_IS2_HK_L4_SPORT]                  = {136,  16},
        [VCAP_IS2_HK_L4_RNG]                    = {152,   8},
        [VCAP_IS2_HK_L4_SPORT_EQ_DPORT]         = {160,   1},
        [VCAP_IS2_HK_L4_SEQUENCE_EQ0]           = {161,   1},
-       [VCAP_IS2_HK_L4_URG]                    = {162,   1},
-       [VCAP_IS2_HK_L4_ACK]                    = {163,   1},
-       [VCAP_IS2_HK_L4_PSH]                    = {164,   1},
-       [VCAP_IS2_HK_L4_RST]                    = {165,   1},
-       [VCAP_IS2_HK_L4_SYN]                    = {166,   1},
-       [VCAP_IS2_HK_L4_FIN]                    = {167,   1},
+       [VCAP_IS2_HK_L4_FIN]                    = {162,   1},
+       [VCAP_IS2_HK_L4_SYN]                    = {163,   1},
+       [VCAP_IS2_HK_L4_RST]                    = {164,   1},
+       [VCAP_IS2_HK_L4_PSH]                    = {165,   1},
+       [VCAP_IS2_HK_L4_ACK]                    = {166,   1},
+       [VCAP_IS2_HK_L4_URG]                    = {167,   1},
        [VCAP_IS2_HK_L4_1588_DOM]               = {168,   8},
        [VCAP_IS2_HK_L4_1588_VER]               = {176,   4},
        /* IP4_OTHER (TYPE=101) */
@@ -685,12 +685,12 @@ static struct vcap_field vsc9959_vcap_is2_actions[] = {
        [VCAP_IS2_ACT_POLICE_ENA]               = {  9,  1},
        [VCAP_IS2_ACT_POLICE_IDX]               = { 10,  9},
        [VCAP_IS2_ACT_POLICE_VCAP_ONLY]         = { 19,  1},
-       [VCAP_IS2_ACT_PORT_MASK]                = { 20, 11},
-       [VCAP_IS2_ACT_REW_OP]                   = { 31,  9},
-       [VCAP_IS2_ACT_SMAC_REPLACE_ENA]         = { 40,  1},
-       [VCAP_IS2_ACT_RSV]                      = { 41,  2},
-       [VCAP_IS2_ACT_ACL_ID]                   = { 43,  6},
-       [VCAP_IS2_ACT_HIT_CNT]                  = { 49, 32},
+       [VCAP_IS2_ACT_PORT_MASK]                = { 20,  6},
+       [VCAP_IS2_ACT_REW_OP]                   = { 26,  9},
+       [VCAP_IS2_ACT_SMAC_REPLACE_ENA]         = { 35,  1},
+       [VCAP_IS2_ACT_RSV]                      = { 36,  2},
+       [VCAP_IS2_ACT_ACL_ID]                   = { 38,  6},
+       [VCAP_IS2_ACT_HIT_CNT]                  = { 44, 32},
 };
 
 static const struct vcap_props vsc9959_vcap_props[] = {
@@ -1171,6 +1171,8 @@ static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port,
  */
 static u16 vsc9959_wm_enc(u16 value)
 {
+       WARN_ON(value >= 16 * BIT(8));
+
        if (value >= BIT(8))
                return BIT(8) | (value / 16);
 
@@ -1284,8 +1286,28 @@ void vsc9959_mdio_bus_free(struct ocelot *ocelot)
 static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
                                    u32 speed)
 {
+       u8 tas_speed;
+
+       switch (speed) {
+       case SPEED_10:
+               tas_speed = OCELOT_SPEED_10;
+               break;
+       case SPEED_100:
+               tas_speed = OCELOT_SPEED_100;
+               break;
+       case SPEED_1000:
+               tas_speed = OCELOT_SPEED_1000;
+               break;
+       case SPEED_2500:
+               tas_speed = OCELOT_SPEED_2500;
+               break;
+       default:
+               tas_speed = OCELOT_SPEED_1000;
+               break;
+       }
+
        ocelot_rmw_rix(ocelot,
-                      QSYS_TAG_CONFIG_LINK_SPEED(speed),
+                      QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
                       QSYS_TAG_CONFIG_LINK_SPEED_M,
                       QSYS_TAG_CONFIG, port);
 }
index 625b189..9e9fd19 100644 (file)
@@ -659,17 +659,17 @@ static struct vcap_field vsc9953_vcap_is2_keys[] = {
        [VCAP_IS2_HK_DIP_EQ_SIP]                = {122,   1},
        /* IP4_TCP_UDP (TYPE=100) */
        [VCAP_IS2_HK_TCP]                       = {123,   1},
-       [VCAP_IS2_HK_L4_SPORT]                  = {124,  16},
-       [VCAP_IS2_HK_L4_DPORT]                  = {140,  16},
+       [VCAP_IS2_HK_L4_DPORT]                  = {124,  16},
+       [VCAP_IS2_HK_L4_SPORT]                  = {140,  16},
        [VCAP_IS2_HK_L4_RNG]                    = {156,   8},
        [VCAP_IS2_HK_L4_SPORT_EQ_DPORT]         = {164,   1},
        [VCAP_IS2_HK_L4_SEQUENCE_EQ0]           = {165,   1},
-       [VCAP_IS2_HK_L4_URG]                    = {166,   1},
-       [VCAP_IS2_HK_L4_ACK]                    = {167,   1},
-       [VCAP_IS2_HK_L4_PSH]                    = {168,   1},
-       [VCAP_IS2_HK_L4_RST]                    = {169,   1},
-       [VCAP_IS2_HK_L4_SYN]                    = {170,   1},
-       [VCAP_IS2_HK_L4_FIN]                    = {171,   1},
+       [VCAP_IS2_HK_L4_FIN]                    = {166,   1},
+       [VCAP_IS2_HK_L4_SYN]                    = {167,   1},
+       [VCAP_IS2_HK_L4_RST]                    = {168,   1},
+       [VCAP_IS2_HK_L4_PSH]                    = {169,   1},
+       [VCAP_IS2_HK_L4_ACK]                    = {170,   1},
+       [VCAP_IS2_HK_L4_URG]                    = {171,   1},
        /* IP4_OTHER (TYPE=101) */
        [VCAP_IS2_HK_IP4_L3_PROTO]              = {123,   8},
        [VCAP_IS2_HK_L3_PAYLOAD]                = {131,  56},
@@ -706,7 +706,7 @@ static const struct vcap_props vsc9953_vcap_props[] = {
                .action_type_width = 1,
                .action_table = {
                        [IS2_ACTION_TYPE_NORMAL] = {
-                               .width = 44,
+                               .width = 50, /* HIT_CNT not included */
                                .count = 2
                        },
                        [IS2_ACTION_TYPE_SMAC_SIP] = {
@@ -911,6 +911,8 @@ static int vsc9953_prevalidate_phy_mode(struct ocelot *ocelot, int port,
  */
 static u16 vsc9953_wm_enc(u16 value)
 {
+       WARN_ON(value >= 16 * BIT(9));
+
        if (value >= BIT(9))
                return BIT(9) | (value / 16);
 
@@ -1008,7 +1010,7 @@ static const struct felix_info seville_info_vsc9953 = {
        .vcap_is2_keys          = vsc9953_vcap_is2_keys,
        .vcap_is2_actions       = vsc9953_vcap_is2_actions,
        .vcap                   = vsc9953_vcap_props,
-       .shared_queue_sz        = 128 * 1024,
+       .shared_queue_sz        = 2048 * 1024,
        .num_mact_rows          = 2048,
        .num_ports              = 10,
        .mdio_bus_alloc         = vsc9953_mdio_bus_alloc,
index 8f40fbf..a8c5a93 100644 (file)
@@ -452,13 +452,19 @@ int rtl8366_vlan_del(struct dsa_switch *ds, int port,
                                return ret;
 
                        if (vid == vlanmc.vid) {
-                               /* clear VLAN member configurations */
-                               vlanmc.vid = 0;
-                               vlanmc.priority = 0;
-                               vlanmc.member = 0;
-                               vlanmc.untag = 0;
-                               vlanmc.fid = 0;
-
+                               /* Remove this port from the VLAN */
+                               vlanmc.member &= ~BIT(port);
+                               vlanmc.untag &= ~BIT(port);
+                               /*
+                                * If no ports are members of this VLAN
+                                * anymore then clear the whole member
+                                * config so it can be reused.
+                                */
+                               if (!vlanmc.member && vlanmc.untag) {
+                                       vlanmc.vid = 0;
+                                       vlanmc.priority = 0;
+                                       vlanmc.fid = 0;
+                               }
                                ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
                                if (ret) {
                                        dev_err(smi->dev,
index 2f634c6..38e6dca 100644 (file)
@@ -33,7 +33,7 @@ struct basic_ring {
        u32 lastWrite;
 };
 
-/* The Typoon transmit ring -- same as a basic ring, plus:
+/* The Typhoon transmit ring -- same as a basic ring, plus:
  * lastRead:      where we're at in regard to cleaning up the ring
  * writeRegister: register to use for writing (different for Hi & Lo rings)
  */
index 130a105..8ebcc68 100644 (file)
@@ -8,7 +8,7 @@
 
 obj-$(CONFIG_AQTION) += atlantic.o
 
-ccflags-y += -I$(src)
+ccflags-y += -I$(srctree)/$(src)
 
 atlantic-objs := aq_main.o \
        aq_nic.o \
@@ -33,4 +33,4 @@ atlantic-objs := aq_main.o \
 
 atlantic-$(CONFIG_MACSEC) += aq_macsec.o
 
-atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o
\ No newline at end of file
+atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o
index bfc0e45..5caa75b 100644 (file)
 #define CCM_REG_GR_ARB_TYPE                                     0xd015c
 /* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed; that the Store channel priority is
-   the compliment to 4 of the rest priorities - Aggregation channel; Load
+   the complement to 4 of the rest priorities - Aggregation channel; Load
    (FIC0) channel and Load (FIC1). */
 #define CCM_REG_GR_LD0_PR                                       0xd0164
 /* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed; that the Store channel priority is
-   the compliment to 4 of the rest priorities - Aggregation channel; Load
+   the complement to 4 of the rest priorities - Aggregation channel; Load
    (FIC0) channel and Load (FIC1). */
 #define CCM_REG_GR_LD1_PR                                       0xd0168
 /* [RW 2] General flags index. */
 #define TCM_REG_GR_ARB_TYPE                                     0x50114
 /* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed that the Store channel is the
-   compliment of the other 3 groups. */
+   complement of the other 3 groups. */
 #define TCM_REG_GR_LD0_PR                                       0x5011c
 /* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed that the Store channel is the
-   compliment of the other 3 groups. */
+   complement of the other 3 groups. */
 #define TCM_REG_GR_LD1_PR                                       0x50120
 /* [RW 4] The number of double REG-pairs; loaded from the STORM context and
    sent to STORM; for a specific connection type. The double REG-pairs are
 #define UCM_REG_GR_ARB_TYPE                                     0xe0144
 /* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed that the Store channel group is
-   compliment to the others. */
+   complement to the others. */
 #define UCM_REG_GR_LD0_PR                                       0xe014c
 /* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed that the Store channel group is
-   compliment to the others. */
+   complement to the others. */
 #define UCM_REG_GR_LD1_PR                                       0xe0150
 /* [RW 2] The queue index for invalidate counter flag decision. */
 #define UCM_REG_INV_CFLG_Q                                      0xe00e4
 #define XCM_REG_GR_ARB_TYPE                                     0x2020c
 /* [RW 2] Load (FIC0) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed that the Channel group is the
-   compliment of the other 3 groups. */
+   complement of the other 3 groups. */
 #define XCM_REG_GR_LD0_PR                                       0x20214
 /* [RW 2] Load (FIC1) channel group priority. The lowest priority is 0; the
    highest priority is 3. It is supposed that the Channel group is the
-   compliment of the other 3 groups. */
+   complement of the other 3 groups. */
 #define XCM_REG_GR_LD1_PR                                       0x20218
 /* [RW 1] Input nig0 Interface enable. If 0 - the valid input is
    disregarded; acknowledge output is deasserted; all other signals are
index b167066..7b7e8b7 100644 (file)
@@ -3782,6 +3782,7 @@ static int bnxt_hwrm_func_qstat_ext(struct bnxt *bp,
                return -EOPNOTSUPP;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QSTATS_EXT, -1, -1);
+       req.fid = cpu_to_le16(0xffff);
        req.flags = FUNC_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK;
        mutex_lock(&bp->hwrm_cmd_lock);
        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -3852,7 +3853,7 @@ static void bnxt_init_stats(struct bnxt *bp)
                tx_masks = stats->hw_masks;
                tx_count = sizeof(struct tx_port_stats_ext) / 8;
 
-               flags = FUNC_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK;
+               flags = PORT_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK;
                rc = bnxt_hwrm_port_qstats_ext(bp, flags);
                if (rc) {
                        mask = (1ULL << 40) - 1;
@@ -4305,7 +4306,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
        u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
        u16 dst = BNXT_HWRM_CHNL_CHIMP;
 
-       if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+       if (BNXT_NO_FW_ACCESS(bp))
                return -EBUSY;
 
        if (msg_len > BNXT_HWRM_MAX_REQ_LEN) {
@@ -5723,7 +5724,7 @@ static int hwrm_ring_free_send_msg(struct bnxt *bp,
        struct hwrm_ring_free_output *resp = bp->hwrm_cmd_resp_addr;
        u16 error_code;
 
-       if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+       if (BNXT_NO_FW_ACCESS(bp))
                return 0;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, cmpl_ring_id, -1);
@@ -7817,7 +7818,7 @@ static int bnxt_set_tpa(struct bnxt *bp, bool set_tpa)
 
        if (set_tpa)
                tpa_flags = bp->flags & BNXT_FLAG_TPA;
-       else if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+       else if (BNXT_NO_FW_ACCESS(bp))
                return 0;
        for (i = 0; i < bp->nr_vnics; i++) {
                rc = bnxt_hwrm_vnic_set_tpa(bp, i, tpa_flags);
@@ -9311,18 +9312,16 @@ static ssize_t bnxt_show_temp(struct device *dev,
        struct hwrm_temp_monitor_query_output *resp;
        struct bnxt *bp = dev_get_drvdata(dev);
        u32 len = 0;
+       int rc;
 
        resp = bp->hwrm_cmd_resp_addr;
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TEMP_MONITOR_QUERY, -1, -1);
        mutex_lock(&bp->hwrm_cmd_lock);
-       if (!_hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT))
+       rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (!rc)
                len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
        mutex_unlock(&bp->hwrm_cmd_lock);
-
-       if (len)
-               return len;
-
-       return sprintf(buf, "unknown\n");
+       return rc ?: len;
 }
 static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
 
@@ -9342,7 +9341,16 @@ static void bnxt_hwmon_close(struct bnxt *bp)
 
 static void bnxt_hwmon_open(struct bnxt *bp)
 {
+       struct hwrm_temp_monitor_query_input req = {0};
        struct pci_dev *pdev = bp->pdev;
+       int rc;
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TEMP_MONITOR_QUERY, -1, -1);
+       rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (rc == -EACCES || rc == -EOPNOTSUPP) {
+               bnxt_hwmon_close(bp);
+               return;
+       }
 
        if (bp->hwmon_dev)
                return;
@@ -11779,6 +11787,10 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        if (BNXT_PF(bp))
                bnxt_sriov_disable(bp);
 
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+       bnxt_cancel_sp_work(bp);
+       bp->sp_event = 0;
+
        bnxt_dl_fw_reporters_destroy(bp, true);
        if (BNXT_PF(bp))
                devlink_port_type_clear(&bp->dl_port);
@@ -11786,9 +11798,6 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        unregister_netdev(dev);
        bnxt_dl_unregister(bp);
        bnxt_shutdown_tc(bp);
-       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
-       bnxt_cancel_sp_work(bp);
-       bp->sp_event = 0;
 
        bnxt_clear_int_mode(bp);
        bnxt_hwrm_func_drv_unrgtr(bp);
@@ -12089,7 +12098,7 @@ static int bnxt_init_mac_addr(struct bnxt *bp)
 static void bnxt_vpd_read_info(struct bnxt *bp)
 {
        struct pci_dev *pdev = bp->pdev;
-       int i, len, pos, ro_size;
+       int i, len, pos, ro_size, size;
        ssize_t vpd_size;
        u8 *vpd_data;
 
@@ -12124,7 +12133,8 @@ static void bnxt_vpd_read_info(struct bnxt *bp)
        if (len + pos > vpd_size)
                goto read_sn;
 
-       strlcpy(bp->board_partno, &vpd_data[pos], min(len, BNXT_VPD_FLD_LEN));
+       size = min(len, BNXT_VPD_FLD_LEN - 1);
+       memcpy(bp->board_partno, &vpd_data[pos], size);
 
 read_sn:
        pos = pci_vpd_find_info_keyword(vpd_data, i, ro_size,
@@ -12137,7 +12147,8 @@ read_sn:
        if (len + pos > vpd_size)
                goto exit;
 
-       strlcpy(bp->board_serialno, &vpd_data[pos], min(len, BNXT_VPD_FLD_LEN));
+       size = min(len, BNXT_VPD_FLD_LEN - 1);
+       memcpy(bp->board_serialno, &vpd_data[pos], size);
 exit:
        kfree(vpd_data);
 }
index 5a13eb6..0ef89da 100644 (file)
@@ -1737,6 +1737,10 @@ struct bnxt {
 #define BNXT_STATE_FW_FATAL_COND       6
 #define BNXT_STATE_DRV_REGISTERED      7
 
+#define BNXT_NO_FW_ACCESS(bp)                                  \
+       (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) ||    \
+        pci_channel_offline((bp)->pdev))
+
        struct bnxt_irq *irq_tbl;
        int                     total_irqs;
        u8                      mac_addr[ETH_ALEN];
index d092833..fecdfd8 100644 (file)
@@ -1322,6 +1322,9 @@ static int bnxt_get_regs_len(struct net_device *dev)
        struct bnxt *bp = netdev_priv(dev);
        int reg_len;
 
+       if (!BNXT_PF(bp))
+               return -EOPNOTSUPP;
+
        reg_len = BNXT_PXP_REG_LEN;
 
        if (bp->fw_cap & BNXT_FW_CAP_PCIE_STATS_SUPPORTED)
@@ -1788,9 +1791,12 @@ static int bnxt_set_pauseparam(struct net_device *dev,
        if (!BNXT_PHY_CFG_ABLE(bp))
                return -EOPNOTSUPP;
 
+       mutex_lock(&bp->link_lock);
        if (epause->autoneg) {
-               if (!(link_info->autoneg & BNXT_AUTONEG_SPEED))
-                       return -EINVAL;
+               if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
+                       rc = -EINVAL;
+                       goto pause_exit;
+               }
 
                link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
                if (bp->hwrm_spec_code >= 0x10201)
@@ -1811,11 +1817,11 @@ static int bnxt_set_pauseparam(struct net_device *dev,
        if (epause->tx_pause)
                link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX;
 
-       if (netif_running(dev)) {
-               mutex_lock(&bp->link_lock);
+       if (netif_running(dev))
                rc = bnxt_hwrm_set_pause(bp);
-               mutex_unlock(&bp->link_lock);
-       }
+
+pause_exit:
+       mutex_unlock(&bp->link_lock);
        return rc;
 }
 
@@ -2552,8 +2558,7 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
        struct bnxt *bp = netdev_priv(dev);
        struct ethtool_eee *eee = &bp->eee;
        struct bnxt_link_info *link_info = &bp->link_info;
-       u32 advertising =
-                _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
+       u32 advertising;
        int rc = 0;
 
        if (!BNXT_PHY_CFG_ABLE(bp))
@@ -2562,19 +2567,23 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
        if (!(bp->flags & BNXT_FLAG_EEE_CAP))
                return -EOPNOTSUPP;
 
+       mutex_lock(&bp->link_lock);
+       advertising = _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
        if (!edata->eee_enabled)
                goto eee_ok;
 
        if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
                netdev_warn(dev, "EEE requires autoneg\n");
-               return -EINVAL;
+               rc = -EINVAL;
+               goto eee_exit;
        }
        if (edata->tx_lpi_enabled) {
                if (bp->lpi_tmr_hi && (edata->tx_lpi_timer > bp->lpi_tmr_hi ||
                                       edata->tx_lpi_timer < bp->lpi_tmr_lo)) {
                        netdev_warn(dev, "Valid LPI timer range is %d and %d microsecs\n",
                                    bp->lpi_tmr_lo, bp->lpi_tmr_hi);
-                       return -EINVAL;
+                       rc = -EINVAL;
+                       goto eee_exit;
                } else if (!bp->lpi_tmr_hi) {
                        edata->tx_lpi_timer = eee->tx_lpi_timer;
                }
@@ -2584,7 +2593,8 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
        } else if (edata->advertised & ~advertising) {
                netdev_warn(dev, "EEE advertised %x must be a subset of autoneg advertised speeds %x\n",
                            edata->advertised, advertising);
-               return -EINVAL;
+               rc = -EINVAL;
+               goto eee_exit;
        }
 
        eee->advertised = edata->advertised;
@@ -2596,6 +2606,8 @@ eee_ok:
        if (netif_running(dev))
                rc = bnxt_hwrm_set_link_setting(bp, false, true);
 
+eee_exit:
+       mutex_unlock(&bp->link_lock);
        return rc;
 }
 
index 6761f40..9179f7b 100644 (file)
@@ -647,8 +647,7 @@ static void macb_mac_link_up(struct phylink_config *config,
                                ctrl |= GEM_BIT(GBE);
                }
 
-               /* We do not support MLO_PAUSE_RX yet */
-               if (tx_pause)
+               if (rx_pause)
                        ctrl |= MACB_BIT(PAE);
 
                macb_set_tx_clk(bp->tx_clk, speed, ndev);
index 3e17ce0..6cb2162 100644 (file)
@@ -1219,7 +1219,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
         */
        if (netdev->phydev) {
                netif_carrier_off(netdev);
-               phy_start_aneg(netdev->phydev);
+               phy_start(netdev->phydev);
        }
 
        netif_wake_queue(netdev);
@@ -1247,8 +1247,10 @@ static int octeon_mgmt_stop(struct net_device *netdev)
        napi_disable(&p->napi);
        netif_stop_queue(netdev);
 
-       if (netdev->phydev)
+       if (netdev->phydev) {
+               phy_stop(netdev->phydev);
                phy_disconnect(netdev->phydev);
+       }
 
        netif_carrier_off(netdev);
 
index 650db92..4814985 100644 (file)
@@ -1911,13 +1911,16 @@ out:
 static int configure_filter_tcb(struct adapter *adap, unsigned int tid,
                                struct filter_entry *f)
 {
-       if (f->fs.hitcnts)
+       if (f->fs.hitcnts) {
                set_tcb_field(adap, f, tid, TCB_TIMESTAMP_W,
-                             TCB_TIMESTAMP_V(TCB_TIMESTAMP_M) |
+                             TCB_TIMESTAMP_V(TCB_TIMESTAMP_M),
+                             TCB_TIMESTAMP_V(0ULL),
+                             1);
+               set_tcb_field(adap, f, tid, TCB_RTT_TS_RECENT_AGE_W,
                              TCB_RTT_TS_RECENT_AGE_V(TCB_RTT_TS_RECENT_AGE_M),
-                             TCB_TIMESTAMP_V(0ULL) |
                              TCB_RTT_TS_RECENT_AGE_V(0ULL),
                              1);
+       }
 
        if (f->fs.newdmac)
                set_tcb_tflag(adap, f, tid, TF_CCTRL_ECE_S, 1,
index b1a073e..a020e84 100644 (file)
@@ -229,7 +229,7 @@ void cxgb4_free_mps_ref_entries(struct adapter *adap)
 {
        struct mps_entries_ref *mps_entry, *tmp;
 
-       if (!list_empty(&adap->mps_ref))
+       if (list_empty(&adap->mps_ref))
                return;
 
        spin_lock(&adap->mps_ref_lock);
index cb116b5..2610efe 100644 (file)
@@ -85,7 +85,7 @@ MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copi
 #define DSL                    CONFIG_DE2104X_DSL
 #endif
 
-#define DE_RX_RING_SIZE                64
+#define DE_RX_RING_SIZE                128
 #define DE_TX_RING_SIZE                64
 #define DE_RING_BYTES          \
                ((sizeof(struct de_desc) * DE_RX_RING_SIZE) +   \
index 3ea51dd..a24b20f 100644 (file)
@@ -66,8 +66,8 @@ struct dpmac_cmd_get_counter {
 };
 
 struct dpmac_rsp_get_counter {
-       u64 pad;
-       u64 counter;
+       __le64 pad;
+       __le64 counter;
 };
 
 #endif /* _FSL_DPMAC_CMD_H */
index 593e381..3c06f5f 100644 (file)
 #define DPNI_VER_MAJOR                         7
 #define DPNI_VER_MINOR                         0
 #define DPNI_CMD_BASE_VERSION                  1
+#define DPNI_CMD_2ND_VERSION                   2
 #define DPNI_CMD_ID_OFFSET                     4
 
 #define DPNI_CMD(id)   (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_BASE_VERSION)
+#define DPNI_CMD_V2(id)        (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_2ND_VERSION)
 
 #define DPNI_CMDID_OPEN                                        DPNI_CMD(0x801)
 #define DPNI_CMDID_CLOSE                               DPNI_CMD(0x800)
@@ -45,7 +47,7 @@
 #define DPNI_CMDID_SET_MAX_FRAME_LENGTH                        DPNI_CMD(0x216)
 #define DPNI_CMDID_GET_MAX_FRAME_LENGTH                        DPNI_CMD(0x217)
 #define DPNI_CMDID_SET_LINK_CFG                                DPNI_CMD(0x21A)
-#define DPNI_CMDID_SET_TX_SHAPING                      DPNI_CMD(0x21B)
+#define DPNI_CMDID_SET_TX_SHAPING                      DPNI_CMD_V2(0x21B)
 
 #define DPNI_CMDID_SET_MCAST_PROMISC                   DPNI_CMD(0x220)
 #define DPNI_CMDID_GET_MCAST_PROMISC                   DPNI_CMD(0x221)
index 26d5981..177334f 100644 (file)
@@ -1053,7 +1053,6 @@ static int enetc_pf_probe(struct pci_dev *pdev,
 
 err_reg_netdev:
        enetc_teardown_serdes(priv);
-       enetc_mdio_remove(pf);
        enetc_free_msix(priv);
 err_alloc_msix:
        enetc_free_si_resources(priv);
@@ -1061,6 +1060,7 @@ err_alloc_si_res:
        si->ndev = NULL;
        free_netdev(ndev);
 err_alloc_netdev:
+       enetc_mdio_remove(pf);
        enetc_of_put_phy(pf);
 err_map_pf_space:
        enetc_pci_remove(pdev);
index 98be51d..bfa2826 100644 (file)
@@ -229,7 +229,7 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
        /* Return all Fs if nothing was there */
        if ((xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) &&
            !priv->has_a011043) {
-               dev_err(&bus->dev,
+               dev_dbg(&bus->dev,
                        "Error while reading PHY%d reg at %d.%hhu\n",
                        phy_id, dev_addr, regnum);
                return 0xffff;
index ed3829a..a769273 100644 (file)
@@ -334,7 +334,7 @@ static void hns_dsaf_xge_srst_by_port_acpi(struct dsaf_device *dsaf_dev,
  * bit6-11 for ppe0-5
  * bit12-17 for roce0-5
  * bit18-19 for com/dfx
- * @enable: false - request reset , true - drop reset
+ * @dereset: false - request reset , true - drop reset
  */
 static void
 hns_dsaf_srst_chns(struct dsaf_device *dsaf_dev, u32 msk, bool dereset)
@@ -357,7 +357,7 @@ hns_dsaf_srst_chns(struct dsaf_device *dsaf_dev, u32 msk, bool dereset)
  * bit6-11 for ppe0-5
  * bit12-17 for roce0-5
  * bit18-19 for com/dfx
- * @enable: false - request reset , true - drop reset
+ * @dereset: false - request reset , true - drop reset
  */
 static void
 hns_dsaf_srst_chns_acpi(struct dsaf_device *dsaf_dev, u32 msk, bool dereset)
index 4eb5029..14e60c9 100644 (file)
@@ -463,8 +463,8 @@ static int __lb_clean_rings(struct hns_nic_priv *priv,
 
 /**
  * nic_run_loopback_test -  run loopback test
- * @nic_dev: net device
- * @loopback_type: loopback type
+ * @ndev: net device
+ * @loop_mode: loopback mode
  */
 static int __lb_run_test(struct net_device *ndev,
                         enum hnae_loop loop_mode)
@@ -572,7 +572,7 @@ static int __lb_down(struct net_device *ndev, enum hnae_loop loop)
 
 /**
  * hns_nic_self_test - self test
- * @dev: net device
+ * @ndev: net device
  * @eth_test: test cmd
  * @data: test result
  */
@@ -633,7 +633,7 @@ static void hns_nic_self_test(struct net_device *ndev,
 
 /**
  * hns_nic_get_drvinfo - get net driver info
- * @dev: net device
+ * @net_dev: net device
  * @drvinfo: driver info
  */
 static void hns_nic_get_drvinfo(struct net_device *net_dev,
@@ -658,7 +658,7 @@ static void hns_nic_get_drvinfo(struct net_device *net_dev,
 
 /**
  * hns_get_ringparam - get ring parameter
- * @dev: net device
+ * @net_dev: net device
  * @param: ethtool parameter
  */
 static void hns_get_ringparam(struct net_device *net_dev,
@@ -683,7 +683,7 @@ static void hns_get_ringparam(struct net_device *net_dev,
 
 /**
  * hns_get_pauseparam - get pause parameter
- * @dev: net device
+ * @net_dev: net device
  * @param: pause parameter
  */
 static void hns_get_pauseparam(struct net_device *net_dev,
@@ -701,7 +701,7 @@ static void hns_get_pauseparam(struct net_device *net_dev,
 
 /**
  * hns_set_pauseparam - set pause parameter
- * @dev: net device
+ * @net_dev: net device
  * @param: pause parameter
  *
  * Return 0 on success, negative on failure
@@ -725,7 +725,7 @@ static int hns_set_pauseparam(struct net_device *net_dev,
 
 /**
  * hns_get_coalesce - get coalesce info.
- * @dev: net device
+ * @net_dev: net device
  * @ec: coalesce info.
  *
  * Return 0 on success, negative on failure.
@@ -769,7 +769,7 @@ static int hns_get_coalesce(struct net_device *net_dev,
 
 /**
  * hns_set_coalesce - set coalesce info.
- * @dev: net device
+ * @net_dev: net device
  * @ec: coalesce info.
  *
  * Return 0 on success, negative on failure.
@@ -808,7 +808,7 @@ static int hns_set_coalesce(struct net_device *net_dev,
 
 /**
  * hns_get_channels - get channel info.
- * @dev: net device
+ * @net_dev: net device
  * @ch: channel info.
  */
 static void
@@ -825,7 +825,7 @@ hns_get_channels(struct net_device *net_dev, struct ethtool_channels *ch)
 
 /**
  * get_ethtool_stats - get detail statistics.
- * @dev: net device
+ * @netdev: net device
  * @stats: statistics info.
  * @data: statistics data.
  */
@@ -883,8 +883,8 @@ static void hns_get_ethtool_stats(struct net_device *netdev,
 
 /**
  * get_strings: Return a set of strings that describe the requested objects
- * @dev: net device
- * @stats: string set ID.
+ * @netdev: net device
+ * @stringset: string set ID.
  * @data: objects data.
  */
 static void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
@@ -972,7 +972,7 @@ static void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 
 /**
  * nic_get_sset_count - get string set count witch returned by nic_get_strings.
- * @dev: net device
+ * @netdev: net device
  * @stringset: string set index, 0: self test string; 1: statistics string.
  *
  * Return string set count.
@@ -1006,7 +1006,7 @@ static int hns_get_sset_count(struct net_device *netdev, int stringset)
 
 /**
  * hns_phy_led_set - set phy LED status.
- * @dev: net device
+ * @netdev: net device
  * @value: LED state.
  *
  * Return 0 on success, negative on failure.
@@ -1028,7 +1028,7 @@ static int hns_phy_led_set(struct net_device *netdev, int value)
 
 /**
  * nic_set_phys_id - set phy identify LED.
- * @dev: net device
+ * @netdev: net device
  * @state: LED state.
  *
  * Return 0 on success, negative on failure.
@@ -1104,9 +1104,9 @@ hns_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
 
 /**
  * hns_get_regs - get net device register
- * @dev: net device
+ * @net_dev: net device
  * @cmd: ethtool cmd
- * @date: register data
+ * @data: register data
  */
 static void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd,
                         void *data)
@@ -1126,7 +1126,7 @@ static void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd,
 
 /**
  * nic_get_regs_len - get total register len.
- * @dev: net device
+ * @net_dev: net device
  *
  * Return total register len.
  */
@@ -1151,7 +1151,7 @@ static int hns_get_regs_len(struct net_device *net_dev)
 
 /**
  * hns_nic_nway_reset - nway reset
- * @dev: net device
+ * @netdev: net device
  *
  * Return 0 on success, negative on failure
  */
index 936e2dd..b47bd54 100644 (file)
@@ -6,6 +6,7 @@
 config HINIC
        tristate "Huawei Intelligent PCIE Network Interface Card"
        depends on (PCI_MSI && (X86 || ARM64))
+       select NET_DEVLINK
        help
          This driver supports HiNIC PCIE Ethernet cards.
          To compile this driver as part of the kernel, choose Y here.
index 6bb65ad..c340d9a 100644 (file)
@@ -1654,6 +1654,7 @@ static void hinic_diag_test(struct net_device *netdev,
        }
 
        netif_carrier_off(netdev);
+       netif_tx_disable(netdev);
 
        err = do_lp_test(nic_dev, eth_test->flags, LP_DEFAULT_TIME,
                         &test_index);
@@ -1662,9 +1663,12 @@ static void hinic_diag_test(struct net_device *netdev,
                data[test_index] = 1;
        }
 
+       netif_tx_wake_all_queues(netdev);
+
        err = hinic_port_link_state(nic_dev, &link_state);
        if (!err && link_state == HINIC_LINK_STATE_UP)
                netif_carrier_on(netdev);
+
 }
 
 static int hinic_set_phys_id(struct net_device *netdev,
index c6ce596..2ebae6c 100644 (file)
 
 #define MGMT_MSG_TIMEOUT                5000
 
+#define SET_FUNC_PORT_MBOX_TIMEOUT     30000
+
 #define SET_FUNC_PORT_MGMT_TIMEOUT     25000
 
+#define UPDATE_FW_MGMT_TIMEOUT         20000
+
 #define mgmt_to_pfhwdev(pf_mgmt)        \
                container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
 
@@ -361,16 +365,22 @@ int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
                return -EINVAL;
        }
 
-       if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
-               timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
+       if (HINIC_IS_VF(hwif)) {
+               if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
+                       timeout = SET_FUNC_PORT_MBOX_TIMEOUT;
 
-       if (HINIC_IS_VF(hwif))
                return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,
-                                       in_size, buf_out, out_size, 0);
-       else
+                                       in_size, buf_out, out_size, timeout);
+       } else {
+               if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
+                       timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
+               else if (cmd == HINIC_PORT_CMD_UPDATE_FW)
+                       timeout = UPDATE_FW_MGMT_TIMEOUT;
+
                return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
                                buf_out, out_size, MGMT_DIRECT_SEND,
                                MSG_NOT_RESP, timeout);
+       }
 }
 
 static void recv_mgmt_msg_work_handler(struct work_struct *work)
index 501056f..28581bd 100644 (file)
@@ -174,6 +174,24 @@ err_init_txq:
        return err;
 }
 
+static void enable_txqs_napi(struct hinic_dev *nic_dev)
+{
+       int num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev);
+       int i;
+
+       for (i = 0; i < num_txqs; i++)
+               napi_enable(&nic_dev->txqs[i].napi);
+}
+
+static void disable_txqs_napi(struct hinic_dev *nic_dev)
+{
+       int num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev);
+       int i;
+
+       for (i = 0; i < num_txqs; i++)
+               napi_disable(&nic_dev->txqs[i].napi);
+}
+
 /**
  * free_txqs - Free the Logical Tx Queues of specific NIC device
  * @nic_dev: the specific NIC device
@@ -400,6 +418,8 @@ int hinic_open(struct net_device *netdev)
                goto err_create_txqs;
        }
 
+       enable_txqs_napi(nic_dev);
+
        err = create_rxqs(nic_dev);
        if (err) {
                netif_err(nic_dev, drv, netdev,
@@ -484,6 +504,7 @@ err_port_state:
        }
 
 err_create_rxqs:
+       disable_txqs_napi(nic_dev);
        free_txqs(nic_dev);
 
 err_create_txqs:
@@ -497,6 +518,9 @@ int hinic_close(struct net_device *netdev)
        struct hinic_dev *nic_dev = netdev_priv(netdev);
        unsigned int flags;
 
+       /* Disable txq napi firstly to aviod rewaking txq in free_tx_poll */
+       disable_txqs_napi(nic_dev);
+
        down(&nic_dev->mgmt_lock);
 
        flags = nic_dev->flags;
index 02cd635..eb97f2d 100644 (file)
@@ -58,9 +58,9 @@ static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
                                 sizeof(port_mac_cmd),
                                 &port_mac_cmd, &out_size);
        if (err || out_size != sizeof(port_mac_cmd) ||
-           (port_mac_cmd.status  &&
-           port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY &&
-           port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
+           (port_mac_cmd.status &&
+            (port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY || !HINIC_IS_VF(hwif)) &&
+            port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
                dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
                        err, port_mac_cmd.status, out_size);
                return -EFAULT;
index 5bee951..d0072f5 100644 (file)
@@ -543,18 +543,25 @@ static int rx_request_irq(struct hinic_rxq *rxq)
        if (err) {
                netif_err(nic_dev, drv, rxq->netdev,
                          "Failed to set RX interrupt coalescing attribute\n");
-               rx_del_napi(rxq);
-               return err;
+               goto err_req_irq;
        }
 
        err = request_irq(rq->irq, rx_irq, 0, rxq->irq_name, rxq);
-       if (err) {
-               rx_del_napi(rxq);
-               return err;
-       }
+       if (err)
+               goto err_req_irq;
 
        cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask);
-       return irq_set_affinity_hint(rq->irq, &rq->affinity_mask);
+       err = irq_set_affinity_hint(rq->irq, &rq->affinity_mask);
+       if (err)
+               goto err_irq_affinity;
+
+       return 0;
+
+err_irq_affinity:
+       free_irq(rq->irq, rxq);
+err_req_irq:
+       rx_del_napi(rxq);
+       return err;
 }
 
 static void rx_free_irq(struct hinic_rxq *rxq)
index 4d63680..f8a2645 100644 (file)
@@ -38,8 +38,7 @@ static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
                                 sizeof(mac_info), &mac_info, &out_size);
        if (err || out_size != sizeof(mac_info) ||
-           (mac_info.status && mac_info.status != HINIC_PF_SET_VF_ALREADY &&
-           mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
+           (mac_info.status && mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
                dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",
                        err, mac_info.status, out_size);
                return -EIO;
@@ -503,8 +502,7 @@ struct hinic_sriov_info *hinic_get_sriov_info_by_pcidev(struct pci_dev *pdev)
 
 static int hinic_check_mac_info(u8 status, u16 vlan_id)
 {
-       if ((status && status != HINIC_MGMT_STATUS_EXIST &&
-            status != HINIC_PF_SET_VF_ALREADY) ||
+       if ((status && status != HINIC_MGMT_STATUS_EXIST) ||
            (vlan_id & CHECK_IPSU_15BIT &&
             status == HINIC_MGMT_STATUS_EXIST))
                return -EINVAL;
@@ -546,12 +544,6 @@ static int hinic_update_mac(struct hinic_hwdev *hwdev, u8 *old_mac,
                return -EINVAL;
        }
 
-       if (mac_info.status == HINIC_PF_SET_VF_ALREADY) {
-               dev_warn(&hwdev->hwif->pdev->dev,
-                        "PF has already set VF MAC. Ignore update operation\n");
-               return HINIC_PF_SET_VF_ALREADY;
-       }
-
        if (mac_info.status == HINIC_MGMT_STATUS_EXIST)
                dev_warn(&hwdev->hwif->pdev->dev, "MAC is repeated. Ignore update operation\n");
 
index a97498e..c1f81e9 100644 (file)
@@ -717,8 +717,8 @@ static int free_tx_poll(struct napi_struct *napi, int budget)
                netdev_txq = netdev_get_tx_queue(txq->netdev, qp->q_id);
 
                __netif_tx_lock(netdev_txq, smp_processor_id());
-
-               netif_wake_subqueue(nic_dev->netdev, qp->q_id);
+               if (!netif_testing(nic_dev->netdev))
+                       netif_wake_subqueue(nic_dev->netdev, qp->q_id);
 
                __netif_tx_unlock(netdev_txq);
 
@@ -745,18 +745,6 @@ static int free_tx_poll(struct napi_struct *napi, int budget)
        return budget;
 }
 
-static void tx_napi_add(struct hinic_txq *txq, int weight)
-{
-       netif_napi_add(txq->netdev, &txq->napi, free_tx_poll, weight);
-       napi_enable(&txq->napi);
-}
-
-static void tx_napi_del(struct hinic_txq *txq)
-{
-       napi_disable(&txq->napi);
-       netif_napi_del(&txq->napi);
-}
-
 static irqreturn_t tx_irq(int irq, void *data)
 {
        struct hinic_txq *txq = data;
@@ -790,7 +778,7 @@ static int tx_request_irq(struct hinic_txq *txq)
 
        qp = container_of(sq, struct hinic_qp, sq);
 
-       tx_napi_add(txq, nic_dev->tx_weight);
+       netif_napi_add(txq->netdev, &txq->napi, free_tx_poll, nic_dev->tx_weight);
 
        hinic_hwdev_msix_set(nic_dev->hwdev, sq->msix_entry,
                             TX_IRQ_NO_PENDING, TX_IRQ_NO_COALESC,
@@ -807,14 +795,14 @@ static int tx_request_irq(struct hinic_txq *txq)
        if (err) {
                netif_err(nic_dev, drv, txq->netdev,
                          "Failed to set TX interrupt coalescing attribute\n");
-               tx_napi_del(txq);
+               netif_napi_del(&txq->napi);
                return err;
        }
 
        err = request_irq(sq->irq, tx_irq, 0, txq->irq_name, txq);
        if (err) {
                dev_err(&pdev->dev, "Failed to request Tx irq\n");
-               tx_napi_del(txq);
+               netif_napi_del(&txq->napi);
                return err;
        }
 
@@ -826,7 +814,7 @@ static void tx_free_irq(struct hinic_txq *txq)
        struct hinic_sq *sq = txq->sq;
 
        free_irq(sq->irq, txq);
-       tx_napi_del(txq);
+       netif_napi_del(&txq->napi);
 }
 
 /**
index d3a7743..1b702a4 100644 (file)
@@ -2032,16 +2032,18 @@ static int do_reset(struct ibmvnic_adapter *adapter,
 
                } else {
                        rc = reset_tx_pools(adapter);
-                       if (rc)
+                       if (rc) {
                                netdev_dbg(adapter->netdev, "reset tx pools failed (%d)\n",
                                                rc);
                                goto out;
+                       }
 
                        rc = reset_rx_pools(adapter);
-                       if (rc)
+                       if (rc) {
                                netdev_dbg(adapter->netdev, "reset rx pools failed (%d)\n",
                                                rc);
                                goto out;
+                       }
                }
                ibmvnic_disable_irqs(adapter);
        }
index 8e133d6..47bfb2e 100644 (file)
@@ -1115,7 +1115,7 @@ static int i40e_quiesce_vf_pci(struct i40e_vf *vf)
 static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
 {
        struct i40e_mac_filter *f;
-       int num_vlans = 0, bkt;
+       u16 num_vlans = 0, bkt;
 
        hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
                if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID)
@@ -1134,8 +1134,8 @@ static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
  *
  * Called to get number of VLANs and VLAN list present in mac_filter_hash.
  **/
-static void i40e_get_vlan_list_sync(struct i40e_vsi *vsi, int *num_vlans,
-                                          s16 **vlan_list)
+static void i40e_get_vlan_list_sync(struct i40e_vsi *vsi, u16 *num_vlans,
+                                   s16 **vlan_list)
 {
        struct i40e_mac_filter *f;
        int i = 0;
@@ -1169,11 +1169,11 @@ err:
  **/
 static i40e_status
 i40e_set_vsi_promisc(struct i40e_vf *vf, u16 seid, bool multi_enable,
-                    bool unicast_enable, s16 *vl, int num_vlans)
+                    bool unicast_enable, s16 *vl, u16 num_vlans)
 {
+       i40e_status aq_ret, aq_tmp = 0;
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
-       i40e_status aq_ret;
        int i;
 
        /* No VLAN to set promisc on, set on VSI */
@@ -1222,6 +1222,9 @@ i40e_set_vsi_promisc(struct i40e_vf *vf, u16 seid, bool multi_enable,
                                vf->vf_id,
                                i40e_stat_str(&pf->hw, aq_ret),
                                i40e_aq_str(&pf->hw, aq_err));
+
+                       if (!aq_tmp)
+                               aq_tmp = aq_ret;
                }
 
                aq_ret = i40e_aq_set_vsi_uc_promisc_on_vlan(hw, seid,
@@ -1235,8 +1238,15 @@ i40e_set_vsi_promisc(struct i40e_vf *vf, u16 seid, bool multi_enable,
                                vf->vf_id,
                                i40e_stat_str(&pf->hw, aq_ret),
                                i40e_aq_str(&pf->hw, aq_err));
+
+                       if (!aq_tmp)
+                               aq_tmp = aq_ret;
                }
        }
+
+       if (aq_tmp)
+               aq_ret = aq_tmp;
+
        return aq_ret;
 }
 
@@ -1258,7 +1268,7 @@ static i40e_status i40e_config_vf_promiscuous_mode(struct i40e_vf *vf,
        i40e_status aq_ret = I40E_SUCCESS;
        struct i40e_pf *pf = vf->pf;
        struct i40e_vsi *vsi;
-       int num_vlans;
+       u16 num_vlans;
        s16 *vl;
 
        vsi = i40e_find_vsi_from_id(pf, vsi_id);
index d870343..cf539db 100644 (file)
@@ -3806,8 +3806,8 @@ static int __maybe_unused iavf_suspend(struct device *dev_d)
 static int __maybe_unused iavf_resume(struct device *dev_d)
 {
        struct pci_dev *pdev = to_pci_dev(dev_d);
-       struct iavf_adapter *adapter = pci_get_drvdata(pdev);
-       struct net_device *netdev = adapter->netdev;
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 err;
 
        pci_set_master(pdev);
index 34abfce..7db5fd9 100644 (file)
@@ -2288,26 +2288,28 @@ void ice_set_safe_mode_caps(struct ice_hw *hw)
 {
        struct ice_hw_func_caps *func_caps = &hw->func_caps;
        struct ice_hw_dev_caps *dev_caps = &hw->dev_caps;
-       u32 valid_func, rxq_first_id, txq_first_id;
-       u32 msix_vector_first_id, max_mtu;
+       struct ice_hw_common_caps cached_caps;
        u32 num_funcs;
 
        /* cache some func_caps values that should be restored after memset */
-       valid_func = func_caps->common_cap.valid_functions;
-       txq_first_id = func_caps->common_cap.txq_first_id;
-       rxq_first_id = func_caps->common_cap.rxq_first_id;
-       msix_vector_first_id = func_caps->common_cap.msix_vector_first_id;
-       max_mtu = func_caps->common_cap.max_mtu;
+       cached_caps = func_caps->common_cap;
 
        /* unset func capabilities */
        memset(func_caps, 0, sizeof(*func_caps));
 
+#define ICE_RESTORE_FUNC_CAP(name) \
+       func_caps->common_cap.name = cached_caps.name
+
        /* restore cached values */
-       func_caps->common_cap.valid_functions = valid_func;
-       func_caps->common_cap.txq_first_id = txq_first_id;
-       func_caps->common_cap.rxq_first_id = rxq_first_id;
-       func_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
-       func_caps->common_cap.max_mtu = max_mtu;
+       ICE_RESTORE_FUNC_CAP(valid_functions);
+       ICE_RESTORE_FUNC_CAP(txq_first_id);
+       ICE_RESTORE_FUNC_CAP(rxq_first_id);
+       ICE_RESTORE_FUNC_CAP(msix_vector_first_id);
+       ICE_RESTORE_FUNC_CAP(max_mtu);
+       ICE_RESTORE_FUNC_CAP(nvm_unified_update);
+       ICE_RESTORE_FUNC_CAP(nvm_update_pending_nvm);
+       ICE_RESTORE_FUNC_CAP(nvm_update_pending_orom);
+       ICE_RESTORE_FUNC_CAP(nvm_update_pending_netlist);
 
        /* one Tx and one Rx queue in safe mode */
        func_caps->common_cap.num_rxq = 1;
@@ -2318,22 +2320,25 @@ void ice_set_safe_mode_caps(struct ice_hw *hw)
        func_caps->guar_num_vsi = 1;
 
        /* cache some dev_caps values that should be restored after memset */
-       valid_func = dev_caps->common_cap.valid_functions;
-       txq_first_id = dev_caps->common_cap.txq_first_id;
-       rxq_first_id = dev_caps->common_cap.rxq_first_id;
-       msix_vector_first_id = dev_caps->common_cap.msix_vector_first_id;
-       max_mtu = dev_caps->common_cap.max_mtu;
+       cached_caps = dev_caps->common_cap;
        num_funcs = dev_caps->num_funcs;
 
        /* unset dev capabilities */
        memset(dev_caps, 0, sizeof(*dev_caps));
 
+#define ICE_RESTORE_DEV_CAP(name) \
+       dev_caps->common_cap.name = cached_caps.name
+
        /* restore cached values */
-       dev_caps->common_cap.valid_functions = valid_func;
-       dev_caps->common_cap.txq_first_id = txq_first_id;
-       dev_caps->common_cap.rxq_first_id = rxq_first_id;
-       dev_caps->common_cap.msix_vector_first_id = msix_vector_first_id;
-       dev_caps->common_cap.max_mtu = max_mtu;
+       ICE_RESTORE_DEV_CAP(valid_functions);
+       ICE_RESTORE_DEV_CAP(txq_first_id);
+       ICE_RESTORE_DEV_CAP(rxq_first_id);
+       ICE_RESTORE_DEV_CAP(msix_vector_first_id);
+       ICE_RESTORE_DEV_CAP(max_mtu);
+       ICE_RESTORE_DEV_CAP(nvm_unified_update);
+       ICE_RESTORE_DEV_CAP(nvm_update_pending_nvm);
+       ICE_RESTORE_DEV_CAP(nvm_update_pending_orom);
+       ICE_RESTORE_DEV_CAP(nvm_update_pending_netlist);
        dev_caps->num_funcs = num_funcs;
 
        /* one Tx and one Rx queue per function in safe mode */
index deaefe0..8968fdd 100644 (file)
@@ -289,7 +289,13 @@ ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset,
                return -EIO;
        }
 
-       err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_write, HZ, &event);
+       /* In most cases, firmware reports a write completion within a few
+        * milliseconds. However, it has been observed that a completion might
+        * take more than a second to complete in some cases. The timeout here
+        * is conservative and is intended to prevent failure to update when
+        * firmware is slow to respond.
+        */
+       err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_write, 15 * HZ, &event);
        if (err) {
                dev_err(dev, "Timed out waiting for firmware write completion for module 0x%02x, err %d\n",
                        module, err);
@@ -513,7 +519,7 @@ static int ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags,
                return -EIO;
        }
 
-       err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_write_activate, HZ,
+       err = ice_aq_wait_for_event(pf, ice_aqc_opc_nvm_write_activate, 30 * HZ,
                                    &event);
        if (err) {
                dev_err(dev, "Timed out waiting for firmware to switch active flash banks, err %d\n",
index f268277..ebbb8f5 100644 (file)
@@ -246,7 +246,7 @@ static int ice_get_free_slot(void *array, int size, int curr)
  * ice_vsi_delete - delete a VSI from the switch
  * @vsi: pointer to VSI being removed
  */
-void ice_vsi_delete(struct ice_vsi *vsi)
+static void ice_vsi_delete(struct ice_vsi *vsi)
 {
        struct ice_pf *pf = vsi->back;
        struct ice_vsi_ctx *ctxt;
@@ -313,7 +313,7 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi)
  *
  * Returns 0 on success, negative on failure
  */
-int ice_vsi_clear(struct ice_vsi *vsi)
+static int ice_vsi_clear(struct ice_vsi *vsi)
 {
        struct ice_pf *pf = NULL;
        struct device *dev;
@@ -563,7 +563,7 @@ static int ice_vsi_get_qs(struct ice_vsi *vsi)
  * ice_vsi_put_qs - Release queues from VSI to PF
  * @vsi: the VSI that is going to release queues
  */
-void ice_vsi_put_qs(struct ice_vsi *vsi)
+static void ice_vsi_put_qs(struct ice_vsi *vsi)
 {
        struct ice_pf *pf = vsi->back;
        int i;
@@ -1196,6 +1196,18 @@ static void ice_vsi_clear_rings(struct ice_vsi *vsi)
 {
        int i;
 
+       /* Avoid stale references by clearing map from vector to ring */
+       if (vsi->q_vectors) {
+               ice_for_each_q_vector(vsi, i) {
+                       struct ice_q_vector *q_vector = vsi->q_vectors[i];
+
+                       if (q_vector) {
+                               q_vector->tx.ring = NULL;
+                               q_vector->rx.ring = NULL;
+                       }
+               }
+       }
+
        if (vsi->tx_rings) {
                for (i = 0; i < vsi->alloc_txq; i++) {
                        if (vsi->tx_rings[i]) {
@@ -2291,7 +2303,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
        if (status) {
                dev_err(dev, "VSI %d failed lan queue config, error %s\n",
                        vsi->vsi_num, ice_stat_str(status));
-               goto unroll_vector_base;
+               goto unroll_clear_rings;
        }
 
        /* Add switch rule to drop all Tx Flow Control Frames, of look up
index 981f3a1..3da1789 100644 (file)
@@ -45,10 +45,6 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc);
 
 void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create);
 
-void ice_vsi_delete(struct ice_vsi *vsi);
-
-int ice_vsi_clear(struct ice_vsi *vsi);
-
 #ifdef CONFIG_DCB
 int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc);
 #endif /* CONFIG_DCB */
@@ -79,8 +75,6 @@ bool ice_is_reset_in_progress(unsigned long *state);
 void
 ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio);
 
-void ice_vsi_put_qs(struct ice_vsi *vsi);
-
 void ice_vsi_dis_irq(struct ice_vsi *vsi);
 
 void ice_vsi_free_irq(struct ice_vsi *vsi);
index 4634b48..54a7f55 100644 (file)
@@ -3169,10 +3169,8 @@ static int ice_setup_pf_sw(struct ice_pf *pf)
                return -EBUSY;
 
        vsi = ice_pf_vsi_setup(pf, pf->hw.port_info);
-       if (!vsi) {
-               status = -ENOMEM;
-               goto unroll_vsi_setup;
-       }
+       if (!vsi)
+               return -ENOMEM;
 
        status = ice_cfg_netdev(vsi);
        if (status) {
@@ -3219,12 +3217,7 @@ unroll_napi_add:
        }
 
 unroll_vsi_setup:
-       if (vsi) {
-               ice_vsi_free_q_vectors(vsi);
-               ice_vsi_delete(vsi);
-               ice_vsi_put_qs(vsi);
-               ice_vsi_clear(vsi);
-       }
+       ice_vsi_release(vsi);
        return status;
 }
 
@@ -4522,6 +4515,7 @@ static int __maybe_unused ice_suspend(struct device *dev)
        }
        ice_clear_interrupt_scheme(pf);
 
+       pci_save_state(pdev);
        pci_wake_from_d3(pdev, pf->wol_ena);
        pci_set_power_state(pdev, PCI_D3hot);
        return 0;
index 3070dfd..2d566f3 100644 (file)
@@ -299,18 +299,14 @@ extern char igc_driver_name[];
 #define IGC_RX_HDR_LEN                 IGC_RXBUFFER_256
 
 /* Transmit and receive latency (for PTP timestamps) */
-/* FIXME: These values were estimated using the ones that i225 has as
- * basis, they seem to provide good numbers with ptp4l/phc2sys, but we
- * need to confirm them.
- */
-#define IGC_I225_TX_LATENCY_10         9542
-#define IGC_I225_TX_LATENCY_100                1024
-#define IGC_I225_TX_LATENCY_1000       178
-#define IGC_I225_TX_LATENCY_2500       64
-#define IGC_I225_RX_LATENCY_10         20662
-#define IGC_I225_RX_LATENCY_100                2213
-#define IGC_I225_RX_LATENCY_1000       448
-#define IGC_I225_RX_LATENCY_2500       160
+#define IGC_I225_TX_LATENCY_10         240
+#define IGC_I225_TX_LATENCY_100                58
+#define IGC_I225_TX_LATENCY_1000       80
+#define IGC_I225_TX_LATENCY_2500       1325
+#define IGC_I225_RX_LATENCY_10         6450
+#define IGC_I225_RX_LATENCY_100                185
+#define IGC_I225_RX_LATENCY_1000       300
+#define IGC_I225_RX_LATENCY_2500       1485
 
 /* RX and TX descriptor control thresholds.
  * PTHRESH - MAC will consider prefetch if it has fewer than this number of
index 36c9992..6a9b510 100644 (file)
@@ -364,6 +364,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
        struct sk_buff *skb = adapter->ptp_tx_skb;
        struct skb_shared_hwtstamps shhwtstamps;
        struct igc_hw *hw = &adapter->hw;
+       int adjust = 0;
        u64 regval;
 
        if (WARN_ON_ONCE(!skb))
@@ -373,6 +374,24 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
        regval |= (u64)rd32(IGC_TXSTMPH) << 32;
        igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
 
+       switch (adapter->link_speed) {
+       case SPEED_10:
+               adjust = IGC_I225_TX_LATENCY_10;
+               break;
+       case SPEED_100:
+               adjust = IGC_I225_TX_LATENCY_100;
+               break;
+       case SPEED_1000:
+               adjust = IGC_I225_TX_LATENCY_1000;
+               break;
+       case SPEED_2500:
+               adjust = IGC_I225_TX_LATENCY_2500;
+               break;
+       }
+
+       shhwtstamps.hwtstamp =
+               ktime_add_ns(shhwtstamps.hwtstamp, adjust);
+
        /* Clear the lock early before calling skb_tstamp_tx so that
         * applications are not woken up before the lock bit is clear. We use
         * a copy of the skb pointer to ensure other threads can't change it
index 2f8a4cf..86ca8b9 100644 (file)
@@ -5396,9 +5396,10 @@ static int ixgbe_fwd_ring_up(struct ixgbe_adapter *adapter,
        return err;
 }
 
-static int ixgbe_macvlan_up(struct net_device *vdev, void *data)
+static int ixgbe_macvlan_up(struct net_device *vdev,
+                           struct netdev_nested_priv *priv)
 {
-       struct ixgbe_adapter *adapter = data;
+       struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)priv->data;
        struct ixgbe_fwd_adapter *accel;
 
        if (!netif_is_macvlan(vdev))
@@ -5415,8 +5416,12 @@ static int ixgbe_macvlan_up(struct net_device *vdev, void *data)
 
 static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)adapter,
+       };
+
        netdev_walk_all_upper_dev_rcu(adapter->netdev,
-                                     ixgbe_macvlan_up, adapter);
+                                     ixgbe_macvlan_up, &priv);
 }
 
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
@@ -9023,9 +9028,10 @@ static void ixgbe_set_prio_tc_map(struct ixgbe_adapter *adapter)
 }
 
 #endif /* CONFIG_IXGBE_DCB */
-static int ixgbe_reassign_macvlan_pool(struct net_device *vdev, void *data)
+static int ixgbe_reassign_macvlan_pool(struct net_device *vdev,
+                                      struct netdev_nested_priv *priv)
 {
-       struct ixgbe_adapter *adapter = data;
+       struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)priv->data;
        struct ixgbe_fwd_adapter *accel;
        int pool;
 
@@ -9062,13 +9068,16 @@ static int ixgbe_reassign_macvlan_pool(struct net_device *vdev, void *data)
 static void ixgbe_defrag_macvlan_pools(struct net_device *dev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
+       struct netdev_nested_priv priv = {
+               .data = (void *)adapter,
+       };
 
        /* flush any stale bits out of the fwd bitmask */
        bitmap_clear(adapter->fwd_bitmask, 1, 63);
 
        /* walk through upper devices reassigning pools */
        netdev_walk_all_upper_dev_rcu(dev, ixgbe_reassign_macvlan_pool,
-                                     adapter);
+                                     &priv);
 }
 
 /**
@@ -9242,14 +9251,18 @@ struct upper_walk_data {
        u8 queue;
 };
 
-static int get_macvlan_queue(struct net_device *upper, void *_data)
+static int get_macvlan_queue(struct net_device *upper,
+                            struct netdev_nested_priv *priv)
 {
        if (netif_is_macvlan(upper)) {
                struct ixgbe_fwd_adapter *vadapter = macvlan_accel_priv(upper);
-               struct upper_walk_data *data = _data;
-               struct ixgbe_adapter *adapter = data->adapter;
-               int ifindex = data->ifindex;
+               struct ixgbe_adapter *adapter;
+               struct upper_walk_data *data;
+               int ifindex;
 
+               data = (struct upper_walk_data *)priv->data;
+               ifindex = data->ifindex;
+               adapter = data->adapter;
                if (vadapter && upper->ifindex == ifindex) {
                        data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
                        data->action = data->queue;
@@ -9265,6 +9278,7 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
 {
        struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
        unsigned int num_vfs = adapter->num_vfs, vf;
+       struct netdev_nested_priv priv;
        struct upper_walk_data data;
        struct net_device *upper;
 
@@ -9284,8 +9298,9 @@ static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
        data.ifindex = ifindex;
        data.action = 0;
        data.queue = 0;
+       priv.data = (void *)&data;
        if (netdev_walk_all_upper_dev_rcu(adapter->netdev,
-                                         get_macvlan_queue, &data)) {
+                                         get_macvlan_queue, &priv)) {
                *action = data.action;
                *queue = data.queue;
 
index 1645e4e..51ed8a5 100644 (file)
@@ -230,8 +230,8 @@ static int xrx200_poll_rx(struct napi_struct *napi, int budget)
        }
 
        if (rx < budget) {
-               napi_complete(&ch->napi);
-               ltq_dma_enable_irq(&ch->dma);
+               if (napi_complete_done(&ch->napi, rx))
+                       ltq_dma_enable_irq(&ch->dma);
        }
 
        return rx;
@@ -245,6 +245,7 @@ static int xrx200_tx_housekeeping(struct napi_struct *napi, int budget)
        int pkts = 0;
        int bytes = 0;
 
+       netif_tx_lock(net_dev);
        while (pkts < budget) {
                struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->tx_free];
 
@@ -268,9 +269,13 @@ static int xrx200_tx_housekeeping(struct napi_struct *napi, int budget)
        net_dev->stats.tx_bytes += bytes;
        netdev_completed_queue(ch->priv->net_dev, pkts, bytes);
 
+       netif_tx_unlock(net_dev);
+       if (netif_queue_stopped(net_dev))
+               netif_wake_queue(net_dev);
+
        if (pkts < budget) {
-               napi_complete(&ch->napi);
-               ltq_dma_enable_irq(&ch->dma);
+               if (napi_complete_done(&ch->napi, pkts))
+                       ltq_dma_enable_irq(&ch->dma);
        }
 
        return pkts;
@@ -342,10 +347,12 @@ static irqreturn_t xrx200_dma_irq(int irq, void *ptr)
 {
        struct xrx200_chan *ch = ptr;
 
-       ltq_dma_disable_irq(&ch->dma);
-       ltq_dma_ack_irq(&ch->dma);
+       if (napi_schedule_prep(&ch->napi)) {
+               __napi_schedule(&ch->napi);
+               ltq_dma_disable_irq(&ch->dma);
+       }
 
-       napi_schedule(&ch->napi);
+       ltq_dma_ack_irq(&ch->dma);
 
        return IRQ_HANDLED;
 }
@@ -499,7 +506,7 @@ static int xrx200_probe(struct platform_device *pdev)
 
        /* setup NAPI */
        netif_napi_add(net_dev, &priv->chan_rx.napi, xrx200_poll_rx, 32);
-       netif_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, 32);
+       netif_tx_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, 32);
 
        platform_set_drvdata(pdev, priv);
 
index dfcb176..5bf0409 100644 (file)
@@ -2029,11 +2029,11 @@ mvneta_xdp_put_buff(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
        struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
        int i;
 
-       page_pool_put_page(rxq->page_pool, virt_to_head_page(xdp->data),
-                          sync_len, napi);
        for (i = 0; i < sinfo->nr_frags; i++)
                page_pool_put_full_page(rxq->page_pool,
                                        skb_frag_page(&sinfo->frags[i]), napi);
+       page_pool_put_page(rxq->page_pool, virt_to_head_page(xdp->data),
+                          sync_len, napi);
 }
 
 static int
@@ -2383,8 +2383,12 @@ static int mvneta_rx_swbm(struct napi_struct *napi,
                        mvneta_swbm_rx_frame(pp, rx_desc, rxq, &xdp_buf,
                                             &size, page, &ps);
                } else {
-                       if (unlikely(!xdp_buf.data_hard_start))
+                       if (unlikely(!xdp_buf.data_hard_start)) {
+                               rx_desc->buf_phys_addr = 0;
+                               page_pool_put_full_page(rxq->page_pool, page,
+                                                       true);
                                continue;
+                       }
 
                        mvneta_swbm_add_rx_fragment(pp, rx_desc, rxq, &xdp_buf,
                                                    &size, page);
@@ -3396,24 +3400,15 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp,
        txq->last_desc = txq->size - 1;
 
        txq->buf = kmalloc_array(txq->size, sizeof(*txq->buf), GFP_KERNEL);
-       if (!txq->buf) {
-               dma_free_coherent(pp->dev->dev.parent,
-                                 txq->size * MVNETA_DESC_ALIGNED_SIZE,
-                                 txq->descs, txq->descs_phys);
+       if (!txq->buf)
                return -ENOMEM;
-       }
 
        /* Allocate DMA buffers for TSO MAC/IP/TCP headers */
        txq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent,
                                           txq->size * TSO_HEADER_SIZE,
                                           &txq->tso_hdrs_phys, GFP_KERNEL);
-       if (!txq->tso_hdrs) {
-               kfree(txq->buf);
-               dma_free_coherent(pp->dev->dev.parent,
-                                 txq->size * MVNETA_DESC_ALIGNED_SIZE,
-                                 txq->descs, txq->descs_phys);
+       if (!txq->tso_hdrs)
                return -ENOMEM;
-       }
 
        /* Setup XPS mapping */
        if (txq_number > 1)
index 387e33f..2718fe2 100644 (file)
@@ -17,7 +17,7 @@
 
 static const u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
 
-void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
+void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
 {
        void *hw_mbase = mbox->hwbase + (devid * MBOX_SIZE);
        struct otx2_mbox_dev *mdev = &mbox->dev[devid];
@@ -26,13 +26,21 @@ void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
        tx_hdr = hw_mbase + mbox->tx_start;
        rx_hdr = hw_mbase + mbox->rx_start;
 
-       spin_lock(&mdev->mbox_lock);
        mdev->msg_size = 0;
        mdev->rsp_size = 0;
        tx_hdr->num_msgs = 0;
        tx_hdr->msg_size = 0;
        rx_hdr->num_msgs = 0;
        rx_hdr->msg_size = 0;
+}
+EXPORT_SYMBOL(__otx2_mbox_reset);
+
+void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
+{
+       struct otx2_mbox_dev *mdev = &mbox->dev[devid];
+
+       spin_lock(&mdev->mbox_lock);
+       __otx2_mbox_reset(mbox, devid);
        spin_unlock(&mdev->mbox_lock);
 }
 EXPORT_SYMBOL(otx2_mbox_reset);
index 6dfd0f9..ab43378 100644 (file)
@@ -93,6 +93,7 @@ struct mbox_msghdr {
 };
 
 void otx2_mbox_reset(struct otx2_mbox *mbox, int devid);
+void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid);
 void otx2_mbox_destroy(struct otx2_mbox *mbox);
 int otx2_mbox_init(struct otx2_mbox *mbox, void __force *hwbase,
                   struct pci_dev *pdev, void __force *reg_base,
index dcf25a0..b89dde2 100644 (file)
@@ -463,6 +463,7 @@ void rvu_nix_freemem(struct rvu *rvu);
 int rvu_get_nixlf_count(struct rvu *rvu);
 void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int npalf);
 int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr);
+int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
 
 /* NPC APIs */
 int rvu_npc_init(struct rvu *rvu);
@@ -477,7 +478,7 @@ void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
                                       int nixlf, u64 chan);
-void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc);
+void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable);
 int rvu_npc_update_rxvlan(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
 void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
index 01a7931..0fc7082 100644 (file)
@@ -17,7 +17,6 @@
 #include "npc.h"
 #include "cgx.h"
 
-static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
 static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
                            int type, int chan_id);
 
@@ -2020,7 +2019,7 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
        return 0;
 }
 
-static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
+int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
 {
        int err = 0, idx, next_idx, last_idx;
        struct nix_mce_list *mce_list;
@@ -2065,7 +2064,7 @@ static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
 
        /* Disable MCAM entry in NPC */
        if (!mce_list->count) {
-               rvu_npc_disable_bcast_entry(rvu, pcifunc);
+               rvu_npc_enable_bcast_entry(rvu, pcifunc, false);
                goto end;
        }
 
index 0a21408..fbaf9bc 100644 (file)
@@ -530,7 +530,7 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
                              NIX_INTF_RX, &entry, true);
 }
 
-void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc)
+void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable)
 {
        struct npc_mcam *mcam = &rvu->hw->mcam;
        int blkaddr, index;
@@ -543,7 +543,7 @@ void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc)
        pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc, 0, NIXLF_BCAST_ENTRY);
-       npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
+       npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
 }
 
 void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
@@ -622,23 +622,35 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
                                         nixlf, NIXLF_UCAST_ENTRY);
        npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
 
-       /* For PF, ena/dis promisc and bcast MCAM match entries */
-       if (pcifunc & RVU_PFVF_FUNC_MASK)
+       /* For PF, ena/dis promisc and bcast MCAM match entries.
+        * For VFs add/delete from bcast list when RX multicast
+        * feature is present.
+        */
+       if (pcifunc & RVU_PFVF_FUNC_MASK && !rvu->hw->cap.nix_rx_multicast)
                return;
 
        /* For bcast, enable/disable only if it's action is not
         * packet replication, incase if action is replication
-        * then this PF's nixlf is removed from bcast replication
+        * then this PF/VF's nixlf is removed from bcast replication
         * list.
         */
-       index = npc_get_nixlf_mcam_index(mcam, pcifunc,
+       index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
                                         nixlf, NIXLF_BCAST_ENTRY);
        bank = npc_get_bank(mcam, index);
        *(u64 *)&action = rvu_read64(rvu, blkaddr,
             NPC_AF_MCAMEX_BANKX_ACTION(index & (mcam->banksize - 1), bank));
-       if (action.op != NIX_RX_ACTIONOP_MCAST)
+
+       /* VFs will not have BCAST entry */
+       if (action.op != NIX_RX_ACTIONOP_MCAST &&
+           !(pcifunc & RVU_PFVF_FUNC_MASK)) {
                npc_enable_mcam_entry(rvu, mcam,
                                      blkaddr, index, enable);
+       } else {
+               nix_update_bcast_mce_list(rvu, pcifunc, enable);
+               /* Enable PF's BCAST entry for packet replication */
+               rvu_npc_enable_bcast_entry(rvu, pcifunc, enable);
+       }
+
        if (enable)
                rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf);
        else
index 75a8c40..2fb4567 100644 (file)
@@ -370,8 +370,8 @@ static int otx2_forward_vf_mbox_msgs(struct otx2_nic *pf,
                dst_mbox = &pf->mbox;
                dst_size = dst_mbox->mbox.tx_size -
                                ALIGN(sizeof(*mbox_hdr), MBOX_MSG_ALIGN);
-               /* Check if msgs fit into destination area */
-               if (mbox_hdr->msg_size > dst_size)
+               /* Check if msgs fit into destination area and has valid size */
+               if (mbox_hdr->msg_size > dst_size || !mbox_hdr->msg_size)
                        return -EINVAL;
 
                dst_mdev = &dst_mbox->mbox.dev[0];
@@ -526,10 +526,10 @@ static void otx2_pfvf_mbox_up_handler(struct work_struct *work)
 
 end:
                offset = mbox->rx_start + msg->next_msgoff;
+               if (mdev->msgs_acked == (vf_mbox->up_num_msgs - 1))
+                       __otx2_mbox_reset(mbox, 0);
                mdev->msgs_acked++;
        }
-
-       otx2_mbox_reset(mbox, vf_idx);
 }
 
 static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
@@ -803,10 +803,11 @@ static void otx2_pfaf_mbox_handler(struct work_struct *work)
                msg = (struct mbox_msghdr *)(mdev->mbase + offset);
                otx2_process_pfaf_mbox_msg(pf, msg);
                offset = mbox->rx_start + msg->next_msgoff;
+               if (mdev->msgs_acked == (af_mbox->num_msgs - 1))
+                       __otx2_mbox_reset(mbox, 0);
                mdev->msgs_acked++;
        }
 
-       otx2_mbox_reset(mbox, 0);
 }
 
 static void otx2_handle_link_event(struct otx2_nic *pf)
@@ -1560,10 +1561,13 @@ int otx2_open(struct net_device *netdev)
 
        err = otx2_rxtx_enable(pf, true);
        if (err)
-               goto err_free_cints;
+               goto err_tx_stop_queues;
 
        return 0;
 
+err_tx_stop_queues:
+       netif_tx_stop_all_queues(netdev);
+       netif_carrier_off(netdev);
 err_free_cints:
        otx2_free_cints(pf, qidx);
        vec = pci_irq_vector(pf->pdev,
index 3a5b34a..e46834e 100644 (file)
@@ -524,6 +524,7 @@ static void otx2_sqe_add_hdr(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
                        sqe_hdr->ol3type = NIX_SENDL3TYPE_IP4_CKSUM;
                } else if (skb->protocol == htons(ETH_P_IPV6)) {
                        proto = ipv6_hdr(skb)->nexthdr;
+                       sqe_hdr->ol3type = NIX_SENDL3TYPE_IP6;
                }
 
                if (proto == IPPROTO_TCP)
index 92a3db6..2f90f17 100644 (file)
@@ -99,10 +99,10 @@ static void otx2vf_vfaf_mbox_handler(struct work_struct *work)
                msg = (struct mbox_msghdr *)(mdev->mbase + offset);
                otx2vf_process_vfaf_mbox_msg(af_mbox->pfvf, msg);
                offset = mbox->rx_start + msg->next_msgoff;
+               if (mdev->msgs_acked == (af_mbox->num_msgs - 1))
+                       __otx2_mbox_reset(mbox, 0);
                mdev->msgs_acked++;
        }
-
-       otx2_mbox_reset(mbox, 0);
 }
 
 static int otx2vf_process_mbox_msg_up(struct otx2_nic *vf,
index 1d91a0d..2d1f4b3 100644 (file)
@@ -69,12 +69,10 @@ enum {
        MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR            = 0x10,
 };
 
-static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
-                                          struct mlx5_cmd_msg *in,
-                                          struct mlx5_cmd_msg *out,
-                                          void *uout, int uout_size,
-                                          mlx5_cmd_cbk_t cbk,
-                                          void *context, int page_queue)
+static struct mlx5_cmd_work_ent *
+cmd_alloc_ent(struct mlx5_cmd *cmd, struct mlx5_cmd_msg *in,
+             struct mlx5_cmd_msg *out, void *uout, int uout_size,
+             mlx5_cmd_cbk_t cbk, void *context, int page_queue)
 {
        gfp_t alloc_flags = cbk ? GFP_ATOMIC : GFP_KERNEL;
        struct mlx5_cmd_work_ent *ent;
@@ -83,6 +81,7 @@ static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
        if (!ent)
                return ERR_PTR(-ENOMEM);
 
+       ent->idx        = -EINVAL;
        ent->in         = in;
        ent->out        = out;
        ent->uout       = uout;
@@ -91,10 +90,16 @@ static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
        ent->context    = context;
        ent->cmd        = cmd;
        ent->page_queue = page_queue;
+       refcount_set(&ent->refcnt, 1);
 
        return ent;
 }
 
+static void cmd_free_ent(struct mlx5_cmd_work_ent *ent)
+{
+       kfree(ent);
+}
+
 static u8 alloc_token(struct mlx5_cmd *cmd)
 {
        u8 token;
@@ -109,7 +114,7 @@ static u8 alloc_token(struct mlx5_cmd *cmd)
        return token;
 }
 
-static int alloc_ent(struct mlx5_cmd *cmd)
+static int cmd_alloc_index(struct mlx5_cmd *cmd)
 {
        unsigned long flags;
        int ret;
@@ -123,7 +128,7 @@ static int alloc_ent(struct mlx5_cmd *cmd)
        return ret < cmd->max_reg_cmds ? ret : -ENOMEM;
 }
 
-static void free_ent(struct mlx5_cmd *cmd, int idx)
+static void cmd_free_index(struct mlx5_cmd *cmd, int idx)
 {
        unsigned long flags;
 
@@ -132,6 +137,22 @@ static void free_ent(struct mlx5_cmd *cmd, int idx)
        spin_unlock_irqrestore(&cmd->alloc_lock, flags);
 }
 
+static void cmd_ent_get(struct mlx5_cmd_work_ent *ent)
+{
+       refcount_inc(&ent->refcnt);
+}
+
+static void cmd_ent_put(struct mlx5_cmd_work_ent *ent)
+{
+       if (!refcount_dec_and_test(&ent->refcnt))
+               return;
+
+       if (ent->idx >= 0)
+               cmd_free_index(ent->cmd, ent->idx);
+
+       cmd_free_ent(ent);
+}
+
 static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx)
 {
        return cmd->cmd_buf + (idx << cmd->log_stride);
@@ -219,11 +240,6 @@ static void poll_timeout(struct mlx5_cmd_work_ent *ent)
        ent->ret = -ETIMEDOUT;
 }
 
-static void free_cmd(struct mlx5_cmd_work_ent *ent)
-{
-       kfree(ent);
-}
-
 static int verify_signature(struct mlx5_cmd_work_ent *ent)
 {
        struct mlx5_cmd_mailbox *next = ent->out->next;
@@ -837,11 +853,22 @@ static void cb_timeout_handler(struct work_struct *work)
        struct mlx5_core_dev *dev = container_of(ent->cmd, struct mlx5_core_dev,
                                                 cmd);
 
+       mlx5_cmd_eq_recover(dev);
+
+       /* Maybe got handled by eq recover ? */
+       if (!test_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state)) {
+               mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, recovered after timeout\n", ent->idx,
+                              mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+               goto out; /* phew, already handled */
+       }
+
        ent->ret = -ETIMEDOUT;
-       mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
-                      mlx5_command_str(msg_to_opcode(ent->in)),
-                      msg_to_opcode(ent->in));
+       mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, timeout. Will cause a leak of a command resource\n",
+                      ent->idx, mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
        mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+
+out:
+       cmd_ent_put(ent); /* for the cmd_ent_get() took on schedule delayed work */
 }
 
 static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg);
@@ -856,6 +883,32 @@ static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode)
        return cmd->allowed_opcode == opcode;
 }
 
+static int cmd_alloc_index_retry(struct mlx5_cmd *cmd)
+{
+       unsigned long alloc_end = jiffies + msecs_to_jiffies(1000);
+       int idx;
+
+retry:
+       idx = cmd_alloc_index(cmd);
+       if (idx < 0 && time_before(jiffies, alloc_end)) {
+               /* Index allocation can fail on heavy load of commands. This is a temporary
+                * situation as the current command already holds the semaphore, meaning that
+                * another command completion is being handled and it is expected to release
+                * the entry index soon.
+                */
+               cpu_relax();
+               goto retry;
+       }
+       return idx;
+}
+
+bool mlx5_cmd_is_down(struct mlx5_core_dev *dev)
+{
+       return pci_channel_offline(dev->pdev) ||
+              dev->cmd.state != MLX5_CMDIF_STATE_UP ||
+              dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR;
+}
+
 static void cmd_work_handler(struct work_struct *work)
 {
        struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work);
@@ -873,14 +926,14 @@ static void cmd_work_handler(struct work_struct *work)
        sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
        down(sem);
        if (!ent->page_queue) {
-               alloc_ret = alloc_ent(cmd);
+               alloc_ret = cmd_alloc_index_retry(cmd);
                if (alloc_ret < 0) {
                        mlx5_core_err_rl(dev, "failed to allocate command entry\n");
                        if (ent->callback) {
                                ent->callback(-EAGAIN, ent->context);
                                mlx5_free_cmd_msg(dev, ent->out);
                                free_msg(dev, ent->in);
-                               free_cmd(ent);
+                               cmd_ent_put(ent);
                        } else {
                                ent->ret = -EAGAIN;
                                complete(&ent->done);
@@ -916,15 +969,12 @@ static void cmd_work_handler(struct work_struct *work)
        ent->ts1 = ktime_get_ns();
        cmd_mode = cmd->mode;
 
-       if (ent->callback)
-               schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
+       if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, cb_timeout))
+               cmd_ent_get(ent);
        set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
 
        /* Skip sending command to fw if internal error */
-       if (pci_channel_offline(dev->pdev) ||
-           dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR ||
-           cmd->state != MLX5_CMDIF_STATE_UP ||
-           !opcode_allowed(&dev->cmd, ent->op)) {
+       if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, ent->op)) {
                u8 status = 0;
                u32 drv_synd;
 
@@ -933,13 +983,10 @@ static void cmd_work_handler(struct work_struct *work)
                MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
 
                mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
-               /* no doorbell, no need to keep the entry */
-               free_ent(cmd, ent->idx);
-               if (ent->callback)
-                       free_cmd(ent);
                return;
        }
 
+       cmd_ent_get(ent); /* for the _real_ FW event on completion */
        /* ring doorbell after the descriptor is valid */
        mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
        wmb();
@@ -983,6 +1030,35 @@ static const char *deliv_status_to_str(u8 status)
        }
 }
 
+enum {
+       MLX5_CMD_TIMEOUT_RECOVER_MSEC   = 5 * 1000,
+};
+
+static void wait_func_handle_exec_timeout(struct mlx5_core_dev *dev,
+                                         struct mlx5_cmd_work_ent *ent)
+{
+       unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_RECOVER_MSEC);
+
+       mlx5_cmd_eq_recover(dev);
+
+       /* Re-wait on the ent->done after executing the recovery flow. If the
+        * recovery flow (or any other recovery flow running simultaneously)
+        * has recovered an EQE, it should cause the entry to be completed by
+        * the command interface.
+        */
+       if (wait_for_completion_timeout(&ent->done, timeout)) {
+               mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) recovered after timeout\n", ent->idx,
+                              mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+               return;
+       }
+
+       mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) No done completion\n", ent->idx,
+                      mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+
+       ent->ret = -ETIMEDOUT;
+       mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+}
+
 static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
 {
        unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
@@ -994,12 +1070,10 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
                ent->ret = -ECANCELED;
                goto out_err;
        }
-       if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
+       if (cmd->mode == CMD_MODE_POLLING || ent->polling)
                wait_for_completion(&ent->done);
-       } else if (!wait_for_completion_timeout(&ent->done, timeout)) {
-               ent->ret = -ETIMEDOUT;
-               mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
-       }
+       else if (!wait_for_completion_timeout(&ent->done, timeout))
+               wait_func_handle_exec_timeout(dev, ent);
 
 out_err:
        err = ent->ret;
@@ -1039,11 +1113,16 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
        if (callback && page_queue)
                return -EINVAL;
 
-       ent = alloc_cmd(cmd, in, out, uout, uout_size, callback, context,
-                       page_queue);
+       ent = cmd_alloc_ent(cmd, in, out, uout, uout_size,
+                           callback, context, page_queue);
        if (IS_ERR(ent))
                return PTR_ERR(ent);
 
+       /* put for this ent is when consumed, depending on the use case
+        * 1) (!callback) blocking flow: by caller after wait_func completes
+        * 2) (callback) flow: by mlx5_cmd_comp_handler() when ent is handled
+        */
+
        ent->token = token;
        ent->polling = force_polling;
 
@@ -1062,12 +1141,10 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
        }
 
        if (callback)
-               goto out;
+               goto out; /* mlx5_cmd_comp_handler() will put(ent) */
 
        err = wait_func(dev, ent);
-       if (err == -ETIMEDOUT)
-               goto out;
-       if (err == -ECANCELED)
+       if (err == -ETIMEDOUT || err == -ECANCELED)
                goto out_free;
 
        ds = ent->ts2 - ent->ts1;
@@ -1085,7 +1162,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
        *status = ent->status;
 
 out_free:
-       free_cmd(ent);
+       cmd_ent_put(ent);
 out:
        return err;
 }
@@ -1516,14 +1593,19 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
                                if (!forced) {
                                        mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n",
                                                      ent->idx);
-                                       free_ent(cmd, ent->idx);
-                                       free_cmd(ent);
+                                       cmd_ent_put(ent);
                                }
                                continue;
                        }
 
-                       if (ent->callback)
-                               cancel_delayed_work(&ent->cb_timeout_work);
+                       if (ent->callback && cancel_delayed_work(&ent->cb_timeout_work))
+                               cmd_ent_put(ent); /* timeout work was canceled */
+
+                       if (!forced || /* Real FW completion */
+                           pci_channel_offline(dev->pdev) || /* FW is inaccessible */
+                           dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+                               cmd_ent_put(ent);
+
                        if (ent->page_queue)
                                sem = &cmd->pages_sem;
                        else
@@ -1545,10 +1627,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
                                              ent->ret, deliv_status_to_str(ent->status), ent->status);
                        }
 
-                       /* only real completion will free the entry slot */
-                       if (!forced)
-                               free_ent(cmd, ent->idx);
-
                        if (ent->callback) {
                                ds = ent->ts2 - ent->ts1;
                                if (ent->op < MLX5_CMD_OP_MAX) {
@@ -1576,10 +1654,13 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
                                free_msg(dev, ent->in);
 
                                err = err ? err : ent->status;
-                               if (!forced)
-                                       free_cmd(ent);
+                               /* final consumer is done, release ent */
+                               cmd_ent_put(ent);
                                callback(err, context);
                        } else {
+                               /* release wait_func() so mlx5_cmd_invoke()
+                                * can make the final ent_put()
+                                */
                                complete(&ent->done);
                        }
                        up(sem);
@@ -1589,8 +1670,11 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
 
 void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
 {
+       struct mlx5_cmd *cmd = &dev->cmd;
+       unsigned long bitmask;
        unsigned long flags;
        u64 vector;
+       int i;
 
        /* wait for pending handlers to complete */
        mlx5_eq_synchronize_cmd_irq(dev);
@@ -1599,11 +1683,20 @@ void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
        if (!vector)
                goto no_trig;
 
+       bitmask = vector;
+       /* we must increment the allocated entries refcount before triggering the completions
+        * to guarantee pending commands will not get freed in the meanwhile.
+        * For that reason, it also has to be done inside the alloc_lock.
+        */
+       for_each_set_bit(i, &bitmask, (1 << cmd->log_sz))
+               cmd_ent_get(cmd->ent_arr[i]);
        vector |= MLX5_TRIGGERED_CMD_COMP;
        spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 
        mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
        mlx5_cmd_comp_handler(dev, vector, true);
+       for_each_set_bit(i, &bitmask, (1 << cmd->log_sz))
+               cmd_ent_put(cmd->ent_arr[i]);
        return;
 
 no_trig:
@@ -1711,10 +1804,7 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
        u8 token;
 
        opcode = MLX5_GET(mbox_in, in, opcode);
-       if (pci_channel_offline(dev->pdev) ||
-           dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR ||
-           dev->cmd.state != MLX5_CMDIF_STATE_UP ||
-           !opcode_allowed(&dev->cmd, opcode)) {
+       if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, opcode)) {
                err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status);
                MLX5_SET(mbox_out, out, status, status);
                MLX5_SET(mbox_out, out, syndrome, drv_synd);
index 0cc2080..356f585 100644 (file)
@@ -91,7 +91,12 @@ struct page_pool;
 #define MLX5_MPWRQ_PAGES_PER_WQE               BIT(MLX5_MPWRQ_WQE_PAGE_ORDER)
 
 #define MLX5_MTT_OCTW(npages) (ALIGN(npages, 8) / 2)
-#define MLX5E_REQUIRED_WQE_MTTS                (ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
+/* Add another page to MLX5E_REQUIRED_WQE_MTTS as a buffer between
+ * WQEs, This page will absorb write overflow by the hardware, when
+ * receiving packets larger than MTU. These oversize packets are
+ * dropped by the driver at a later stage.
+ */
+#define MLX5E_REQUIRED_WQE_MTTS                (ALIGN(MLX5_MPWRQ_PAGES_PER_WQE + 1, 8))
 #define MLX5E_LOG_ALIGNED_MPWQE_PPW    (ilog2(MLX5E_REQUIRED_WQE_MTTS))
 #define MLX5E_REQUIRED_MTTS(wqes)      (wqes * MLX5E_REQUIRED_WQE_MTTS)
 #define MLX5E_MAX_RQ_NUM_MTTS  \
@@ -600,7 +605,7 @@ struct mlx5e_rq {
        struct dim         dim; /* Dynamic Interrupt Moderation */
 
        /* XDP */
-       struct bpf_prog       *xdp_prog;
+       struct bpf_prog __rcu *xdp_prog;
        struct mlx5e_xdpsq    *xdpsq;
        DECLARE_BITMAP(flags, 8);
        struct page_pool      *page_pool;
@@ -617,6 +622,7 @@ struct mlx5e_rq {
        u32                    rqn;
        struct mlx5_core_dev  *mdev;
        struct mlx5_core_mkey  umr_mkey;
+       struct mlx5e_dma_info  wqe_overflow;
 
        /* XDP read-mostly */
        struct xdp_rxq_info    xdp_rxq;
@@ -1005,7 +1011,6 @@ int mlx5e_update_nic_rx(struct mlx5e_priv *priv);
 void mlx5e_update_carrier(struct mlx5e_priv *priv);
 int mlx5e_close(struct net_device *netdev);
 int mlx5e_open(struct net_device *netdev);
-void mlx5e_update_ndo_stats(struct mlx5e_priv *priv);
 
 void mlx5e_queue_update_stats(struct mlx5e_priv *priv);
 int mlx5e_bits_invert(unsigned long a, int size);
index 8fe8b4d..254c847 100644 (file)
@@ -51,7 +51,7 @@ static void mlx5e_monitor_counters_work(struct work_struct *work)
                                               monitor_counters_work);
 
        mutex_lock(&priv->state_lock);
-       mlx5e_update_ndo_stats(priv);
+       mlx5e_stats_update_ndo_stats(priv);
        mutex_unlock(&priv->state_lock);
        mlx5e_monitor_counter_arm(priv);
 }
index 5de1cb9..308fd27 100644 (file)
@@ -490,11 +490,8 @@ bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
        int err;
        int i;
 
-       if (!MLX5_CAP_GEN(dev, pcam_reg))
-               return -EOPNOTSUPP;
-
-       if (!MLX5_CAP_PCAM_REG(dev, pplm))
-               return -EOPNOTSUPP;
+       if (!MLX5_CAP_GEN(dev, pcam_reg) || !MLX5_CAP_PCAM_REG(dev, pplm))
+               return false;
 
        MLX5_SET(pplm_reg, in, local_port, 1);
        err =  mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
@@ -572,6 +569,9 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
        if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane)
                return -EOPNOTSUPP;
 
+       if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy))
+               return -EOPNOTSUPP;
+
        MLX5_SET(pplm_reg, in, local_port, 1);
        err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
        if (err)
index 9062920..58e2703 100644 (file)
@@ -110,11 +110,25 @@ static void mlx5e_rep_neigh_stats_work(struct work_struct *work)
        rtnl_unlock();
 }
 
+struct neigh_update_work {
+       struct work_struct work;
+       struct neighbour *n;
+       struct mlx5e_neigh_hash_entry *nhe;
+};
+
+static void mlx5e_release_neigh_update_work(struct neigh_update_work *update_work)
+{
+       neigh_release(update_work->n);
+       mlx5e_rep_neigh_entry_release(update_work->nhe);
+       kfree(update_work);
+}
+
 static void mlx5e_rep_neigh_update(struct work_struct *work)
 {
-       struct mlx5e_neigh_hash_entry *nhe =
-               container_of(work, struct mlx5e_neigh_hash_entry, neigh_update_work);
-       struct neighbour *n = nhe->n;
+       struct neigh_update_work *update_work = container_of(work, struct neigh_update_work,
+                                                            work);
+       struct mlx5e_neigh_hash_entry *nhe = update_work->nhe;
+       struct neighbour *n = update_work->n;
        struct mlx5e_encap_entry *e;
        unsigned char ha[ETH_ALEN];
        struct mlx5e_priv *priv;
@@ -146,30 +160,42 @@ static void mlx5e_rep_neigh_update(struct work_struct *work)
                mlx5e_rep_update_flows(priv, e, neigh_connected, ha);
                mlx5e_encap_put(priv, e);
        }
-       mlx5e_rep_neigh_entry_release(nhe);
        rtnl_unlock();
-       neigh_release(n);
+       mlx5e_release_neigh_update_work(update_work);
 }
 
-static void mlx5e_rep_queue_neigh_update_work(struct mlx5e_priv *priv,
-                                             struct mlx5e_neigh_hash_entry *nhe,
-                                             struct neighbour *n)
+static struct neigh_update_work *mlx5e_alloc_neigh_update_work(struct mlx5e_priv *priv,
+                                                              struct neighbour *n)
 {
-       /* Take a reference to ensure the neighbour and mlx5 encap
-        * entry won't be destructed until we drop the reference in
-        * delayed work.
-        */
-       neigh_hold(n);
+       struct neigh_update_work *update_work;
+       struct mlx5e_neigh_hash_entry *nhe;
+       struct mlx5e_neigh m_neigh = {};
 
-       /* This assignment is valid as long as the the neigh reference
-        * is taken
-        */
-       nhe->n = n;
+       update_work = kzalloc(sizeof(*update_work), GFP_ATOMIC);
+       if (WARN_ON(!update_work))
+               return NULL;
 
-       if (!queue_work(priv->wq, &nhe->neigh_update_work)) {
-               mlx5e_rep_neigh_entry_release(nhe);
-               neigh_release(n);
+       m_neigh.dev = n->dev;
+       m_neigh.family = n->ops->family;
+       memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
+
+       /* Obtain reference to nhe as last step in order not to release it in
+        * atomic context.
+        */
+       rcu_read_lock();
+       nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh);
+       rcu_read_unlock();
+       if (!nhe) {
+               kfree(update_work);
+               return NULL;
        }
+
+       INIT_WORK(&update_work->work, mlx5e_rep_neigh_update);
+       neigh_hold(n);
+       update_work->n = n;
+       update_work->nhe = nhe;
+
+       return update_work;
 }
 
 static int mlx5e_rep_netevent_event(struct notifier_block *nb,
@@ -181,7 +207,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
        struct net_device *netdev = rpriv->netdev;
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5e_neigh_hash_entry *nhe = NULL;
-       struct mlx5e_neigh m_neigh = {};
+       struct neigh_update_work *update_work;
        struct neigh_parms *p;
        struct neighbour *n;
        bool found = false;
@@ -196,17 +222,11 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
 #endif
                        return NOTIFY_DONE;
 
-               m_neigh.dev = n->dev;
-               m_neigh.family = n->ops->family;
-               memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
-
-               rcu_read_lock();
-               nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh);
-               rcu_read_unlock();
-               if (!nhe)
+               update_work = mlx5e_alloc_neigh_update_work(priv, n);
+               if (!update_work)
                        return NOTIFY_DONE;
 
-               mlx5e_rep_queue_neigh_update_work(priv, nhe, n);
+               queue_work(priv->wq, &update_work->work);
                break;
 
        case NETEVENT_DELAY_PROBE_TIME_UPDATE:
@@ -352,7 +372,6 @@ int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv,
 
        (*nhe)->priv = priv;
        memcpy(&(*nhe)->m_neigh, &e->m_neigh, sizeof(e->m_neigh));
-       INIT_WORK(&(*nhe)->neigh_update_work, mlx5e_rep_neigh_update);
        spin_lock_init(&(*nhe)->encap_list_lock);
        INIT_LIST_HEAD(&(*nhe)->encap_list);
        refcount_set(&(*nhe)->refcnt, 1);
index c6bc922..a8be40c 100644 (file)
@@ -246,8 +246,10 @@ mlx5_tc_ct_rule_to_tuple_nat(struct mlx5_ct_tuple *tuple,
                case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
                        ip6_offset = (offset - offsetof(struct ipv6hdr, saddr));
                        ip6_offset /= 4;
-                       if (ip6_offset < 8)
+                       if (ip6_offset < 4)
                                tuple->ip.src_v6.s6_addr32[ip6_offset] = cpu_to_be32(val);
+                       else if (ip6_offset < 8)
+                               tuple->ip.dst_v6.s6_addr32[ip6_offset - 4] = cpu_to_be32(val);
                        else
                                return -EOPNOTSUPP;
                        break;
@@ -699,6 +701,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
 err_rule:
        mlx5e_mod_hdr_detach(ct_priv->esw->dev,
                             &esw->offloads.mod_hdr, zone_rule->mh);
+       mapping_remove(ct_priv->labels_mapping, attr->ct_attr.ct_labels_id);
 err_mod_hdr:
        kfree(spec);
        return err;
@@ -958,12 +961,22 @@ mlx5_tc_ct_add_no_trk_match(struct mlx5e_priv *priv,
        return 0;
 }
 
+void mlx5_tc_ct_match_del(struct mlx5e_priv *priv, struct mlx5_ct_attr *ct_attr)
+{
+       struct mlx5_tc_ct_priv *ct_priv = mlx5_tc_ct_get_ct_priv(priv);
+
+       if (!ct_priv || !ct_attr->ct_labels_id)
+               return;
+
+       mapping_remove(ct_priv->labels_mapping, ct_attr->ct_labels_id);
+}
+
 int
-mlx5_tc_ct_parse_match(struct mlx5e_priv *priv,
-                      struct mlx5_flow_spec *spec,
-                      struct flow_cls_offload *f,
-                      struct mlx5_ct_attr *ct_attr,
-                      struct netlink_ext_ack *extack)
+mlx5_tc_ct_match_add(struct mlx5e_priv *priv,
+                    struct mlx5_flow_spec *spec,
+                    struct flow_cls_offload *f,
+                    struct mlx5_ct_attr *ct_attr,
+                    struct netlink_ext_ack *extack)
 {
        struct mlx5_tc_ct_priv *ct_priv = mlx5_tc_ct_get_ct_priv(priv);
        struct flow_rule *rule = flow_cls_offload_flow_rule(f);
index 3baef91..708c216 100644 (file)
@@ -87,12 +87,15 @@ mlx5_tc_ct_init(struct mlx5_rep_uplink_priv *uplink_priv);
 void
 mlx5_tc_ct_clean(struct mlx5_rep_uplink_priv *uplink_priv);
 
+void
+mlx5_tc_ct_match_del(struct mlx5e_priv *priv, struct mlx5_ct_attr *ct_attr);
+
 int
-mlx5_tc_ct_parse_match(struct mlx5e_priv *priv,
-                      struct mlx5_flow_spec *spec,
-                      struct flow_cls_offload *f,
-                      struct mlx5_ct_attr *ct_attr,
-                      struct netlink_ext_ack *extack);
+mlx5_tc_ct_match_add(struct mlx5e_priv *priv,
+                    struct mlx5_flow_spec *spec,
+                    struct flow_cls_offload *f,
+                    struct mlx5_ct_attr *ct_attr,
+                    struct netlink_ext_ack *extack);
 int
 mlx5_tc_ct_add_no_trk_match(struct mlx5e_priv *priv,
                            struct mlx5_flow_spec *spec);
@@ -130,12 +133,15 @@ mlx5_tc_ct_clean(struct mlx5_rep_uplink_priv *uplink_priv)
 {
 }
 
+static inline void
+mlx5_tc_ct_match_del(struct mlx5e_priv *priv, struct mlx5_ct_attr *ct_attr) {}
+
 static inline int
-mlx5_tc_ct_parse_match(struct mlx5e_priv *priv,
-                      struct mlx5_flow_spec *spec,
-                      struct flow_cls_offload *f,
-                      struct mlx5_ct_attr *ct_attr,
-                      struct netlink_ext_ack *extack)
+mlx5_tc_ct_match_add(struct mlx5e_priv *priv,
+                    struct mlx5_flow_spec *spec,
+                    struct flow_cls_offload *f,
+                    struct mlx5_ct_attr *ct_attr,
+                    struct netlink_ext_ack *extack)
 {
        struct flow_rule *rule = flow_cls_offload_flow_rule(f);
 
index 9334c9c..24336c6 100644 (file)
@@ -20,6 +20,11 @@ enum mlx5e_icosq_wqe_type {
 };
 
 /* General */
+static inline bool mlx5e_skb_is_multicast(struct sk_buff *skb)
+{
+       return skb->pkt_type == PACKET_MULTICAST || skb->pkt_type == PACKET_BROADCAST;
+}
+
 void mlx5e_trigger_irq(struct mlx5e_icosq *sq);
 void mlx5e_completion_event(struct mlx5_core_cq *mcq, struct mlx5_eqe *eqe);
 void mlx5e_cq_error_event(struct mlx5_core_cq *mcq, enum mlx5_event event);
index 0e6946f..b28df21 100644 (file)
@@ -122,7 +122,7 @@ mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_rq *rq,
 bool mlx5e_xdp_handle(struct mlx5e_rq *rq, struct mlx5e_dma_info *di,
                      u32 *len, struct xdp_buff *xdp)
 {
-       struct bpf_prog *prog = READ_ONCE(rq->xdp_prog);
+       struct bpf_prog *prog = rcu_dereference(rq->xdp_prog);
        u32 act;
        int err;
 
index a33a1f7..40db27b 100644 (file)
@@ -31,7 +31,6 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq,
 {
        struct xdp_buff *xdp = wi->umr.dma_info[page_idx].xsk;
        u32 cqe_bcnt32 = cqe_bcnt;
-       bool consumed;
 
        /* Check packet size. Note LRO doesn't use linear SKB */
        if (unlikely(cqe_bcnt > rq->hw_mtu)) {
@@ -51,10 +50,6 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq,
        xsk_buff_dma_sync_for_cpu(xdp);
        prefetch(xdp->data);
 
-       rcu_read_lock();
-       consumed = mlx5e_xdp_handle(rq, NULL, &cqe_bcnt32, xdp);
-       rcu_read_unlock();
-
        /* Possible flows:
         * - XDP_REDIRECT to XSKMAP:
         *   The page is owned by the userspace from now.
@@ -70,7 +65,7 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq,
         * allocated first from the Reuse Ring, so it has enough space.
         */
 
-       if (likely(consumed)) {
+       if (likely(mlx5e_xdp_handle(rq, NULL, &cqe_bcnt32, xdp))) {
                if (likely(__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)))
                        __set_bit(page_idx, wi->xdp_xmit_bitmap); /* non-atomic */
                return NULL; /* page/packet was consumed by XDP */
@@ -88,7 +83,6 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq,
                                              u32 cqe_bcnt)
 {
        struct xdp_buff *xdp = wi->di->xsk;
-       bool consumed;
 
        /* wi->offset is not used in this function, because xdp->data and the
         * DMA address point directly to the necessary place. Furthermore, the
@@ -107,11 +101,7 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq,
                return NULL;
        }
 
-       rcu_read_lock();
-       consumed = mlx5e_xdp_handle(rq, NULL, &cqe_bcnt, xdp);
-       rcu_read_unlock();
-
-       if (likely(consumed))
+       if (likely(mlx5e_xdp_handle(rq, NULL, &cqe_bcnt, xdp)))
                return NULL; /* page/packet was consumed by XDP */
 
        /* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse
index dd9df51..55e65a4 100644 (file)
@@ -106,8 +106,7 @@ err_free_cparam:
 void mlx5e_close_xsk(struct mlx5e_channel *c)
 {
        clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
-       napi_synchronize(&c->napi);
-       synchronize_rcu(); /* Sync with the XSK wakeup. */
+       synchronize_rcu(); /* Sync with the XSK wakeup and with NAPI. */
 
        mlx5e_close_rq(&c->xskrq);
        mlx5e_close_cq(&c->xskrq.cq);
index acf6d80..6bbfcf1 100644 (file)
@@ -234,7 +234,7 @@ mlx5e_get_ktls_rx_priv_ctx(struct tls_context *tls_ctx)
 
 /* Re-sync */
 /* Runs in work context */
-static struct mlx5_wqe_ctrl_seg *
+static int
 resync_post_get_progress_params(struct mlx5e_icosq *sq,
                                struct mlx5e_ktls_offload_context_rx *priv_rx)
 {
@@ -258,15 +258,19 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq,
                                       PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
        if (unlikely(dma_mapping_error(pdev, buf->dma_addr))) {
                err = -ENOMEM;
-               goto err_out;
+               goto err_free;
        }
 
        buf->priv_rx = priv_rx;
 
        BUILD_BUG_ON(MLX5E_KTLS_GET_PROGRESS_WQEBBS != 1);
+
+       spin_lock(&sq->channel->async_icosq_lock);
+
        if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, 1))) {
+               spin_unlock(&sq->channel->async_icosq_lock);
                err = -ENOSPC;
-               goto err_out;
+               goto err_dma_unmap;
        }
 
        pi = mlx5e_icosq_get_next_pi(sq, 1);
@@ -294,12 +298,18 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq,
        };
        icosq_fill_wi(sq, pi, &wi);
        sq->pc++;
+       mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg);
+       spin_unlock(&sq->channel->async_icosq_lock);
 
-       return cseg;
+       return 0;
 
+err_dma_unmap:
+       dma_unmap_single(pdev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
+err_free:
+       kfree(buf);
 err_out:
        priv_rx->stats->tls_resync_req_skip++;
-       return ERR_PTR(err);
+       return err;
 }
 
 /* Function is called with elevated refcount.
@@ -309,10 +319,8 @@ static void resync_handle_work(struct work_struct *work)
 {
        struct mlx5e_ktls_offload_context_rx *priv_rx;
        struct mlx5e_ktls_rx_resync_ctx *resync;
-       struct mlx5_wqe_ctrl_seg *cseg;
        struct mlx5e_channel *c;
        struct mlx5e_icosq *sq;
-       struct mlx5_wq_cyc *wq;
 
        resync = container_of(work, struct mlx5e_ktls_rx_resync_ctx, work);
        priv_rx = container_of(resync, struct mlx5e_ktls_offload_context_rx, resync);
@@ -324,18 +332,9 @@ static void resync_handle_work(struct work_struct *work)
 
        c = resync->priv->channels.c[priv_rx->rxq];
        sq = &c->async_icosq;
-       wq = &sq->wq;
-
-       spin_lock(&c->async_icosq_lock);
 
-       cseg = resync_post_get_progress_params(sq, priv_rx);
-       if (IS_ERR(cseg)) {
+       if (resync_post_get_progress_params(sq, priv_rx))
                refcount_dec(&resync->refcnt);
-               goto unlock;
-       }
-       mlx5e_notify_hw(wq, sq->pc, sq->uar_map, cseg);
-unlock:
-       spin_unlock(&c->async_icosq_lock);
 }
 
 static void resync_init(struct mlx5e_ktls_rx_resync_ctx *resync,
@@ -386,16 +385,17 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
        struct mlx5e_ktls_offload_context_rx *priv_rx;
        struct mlx5e_ktls_rx_resync_ctx *resync;
        u8 tracker_state, auth_state, *ctx;
+       struct device *dev;
        u32 hw_seq;
 
        priv_rx = buf->priv_rx;
        resync = &priv_rx->resync;
-
+       dev = resync->priv->mdev->device;
        if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags)))
                goto out;
 
-       dma_sync_single_for_cpu(resync->priv->mdev->device, buf->dma_addr,
-                               PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
+       dma_sync_single_for_cpu(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE,
+                               DMA_FROM_DEVICE);
 
        ctx = buf->progress.ctx;
        tracker_state = MLX5_GET(tls_progress_params, ctx, record_tracker_state);
@@ -411,6 +411,7 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi,
        priv_rx->stats->tls_resync_req_end++;
 out:
        refcount_dec(&resync->refcnt);
+       dma_unmap_single(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE);
        kfree(buf);
 }
 
@@ -659,7 +660,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx)
        priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_ctx);
        set_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags);
        mlx5e_set_ktls_rx_priv_ctx(tls_ctx, NULL);
-       napi_synchronize(&priv->channels.c[priv_rx->rxq]->napi);
+       synchronize_rcu(); /* Sync with NAPI */
        if (!cancel_work_sync(&priv_rx->rule.work))
                /* completion is needed, as the priv_rx in the add flow
                 * is maintained on the wqe info (wi), not on the socket.
index 01468ec..b949b9a 100644 (file)
@@ -35,7 +35,6 @@
 #include <net/sock.h>
 
 #include "en.h"
-#include "accel/tls.h"
 #include "fpga/sdk.h"
 #include "en_accel/tls.h"
 
@@ -51,9 +50,14 @@ static const struct counter_desc mlx5e_tls_sw_stats_desc[] = {
 
 #define NUM_TLS_SW_COUNTERS ARRAY_SIZE(mlx5e_tls_sw_stats_desc)
 
+static bool is_tls_atomic_stats(struct mlx5e_priv *priv)
+{
+       return priv->tls && !mlx5_accel_is_ktls_device(priv->mdev);
+}
+
 int mlx5e_tls_get_count(struct mlx5e_priv *priv)
 {
-       if (!priv->tls)
+       if (!is_tls_atomic_stats(priv))
                return 0;
 
        return NUM_TLS_SW_COUNTERS;
@@ -63,7 +67,7 @@ int mlx5e_tls_get_strings(struct mlx5e_priv *priv, uint8_t *data)
 {
        unsigned int i, idx = 0;
 
-       if (!priv->tls)
+       if (!is_tls_atomic_stats(priv))
                return 0;
 
        for (i = 0; i < NUM_TLS_SW_COUNTERS; i++)
@@ -77,7 +81,7 @@ int mlx5e_tls_get_stats(struct mlx5e_priv *priv, u64 *data)
 {
        int i, idx = 0;
 
-       if (!priv->tls)
+       if (!is_tls_atomic_stats(priv))
                return 0;
 
        for (i = 0; i < NUM_TLS_SW_COUNTERS; i++)
index 64d002d..1f48f99 100644 (file)
@@ -217,6 +217,9 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
                break;
        }
 
+       if (WARN_ONCE(*rule_p, "VLAN rule already exists type %d", rule_type))
+               return 0;
+
        *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 
        if (IS_ERR(*rule_p)) {
@@ -397,8 +400,7 @@ static void mlx5e_add_vlan_rules(struct mlx5e_priv *priv)
        for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
                mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 
-       if (priv->fs.vlan.cvlan_filter_disabled &&
-           !(priv->netdev->flags & IFF_PROMISC))
+       if (priv->fs.vlan.cvlan_filter_disabled)
                mlx5e_add_any_vid_rules(priv);
 }
 
@@ -415,8 +417,12 @@ static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)
        for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
                mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 
-       if (priv->fs.vlan.cvlan_filter_disabled &&
-           !(priv->netdev->flags & IFF_PROMISC))
+       WARN_ON_ONCE(!(test_bit(MLX5E_STATE_DESTROYING, &priv->state)));
+
+       /* must be called after DESTROY bit is set and
+        * set_rx_mode is called and flushed
+        */
+       if (priv->fs.vlan.cvlan_filter_disabled)
                mlx5e_del_any_vid_rules(priv);
 }
 
index aebcf73..42ec28e 100644 (file)
@@ -158,16 +158,6 @@ static void mlx5e_update_carrier_work(struct work_struct *work)
        mutex_unlock(&priv->state_lock);
 }
 
-void mlx5e_update_ndo_stats(struct mlx5e_priv *priv)
-{
-       int i;
-
-       for (i = mlx5e_nic_stats_grps_num(priv) - 1; i >= 0; i--)
-               if (mlx5e_nic_stats_grps[i]->update_stats_mask &
-                   MLX5E_NDO_UPDATE_STATS)
-                       mlx5e_nic_stats_grps[i]->update_stats(priv);
-}
-
 static void mlx5e_update_stats_work(struct work_struct *work)
 {
        struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
@@ -256,12 +246,17 @@ static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq,
 
 static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
                                 u64 npages, u8 page_shift,
-                                struct mlx5_core_mkey *umr_mkey)
+                                struct mlx5_core_mkey *umr_mkey,
+                                dma_addr_t filler_addr)
 {
-       int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
+       struct mlx5_mtt *mtt;
+       int inlen;
        void *mkc;
        u32 *in;
        int err;
+       int i;
+
+       inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + sizeof(*mtt) * npages;
 
        in = kvzalloc(inlen, GFP_KERNEL);
        if (!in)
@@ -281,6 +276,18 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
        MLX5_SET(mkc, mkc, translations_octword_size,
                 MLX5_MTT_OCTW(npages));
        MLX5_SET(mkc, mkc, log_page_size, page_shift);
+       MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
+                MLX5_MTT_OCTW(npages));
+
+       /* Initialize the mkey with all MTTs pointing to a default
+        * page (filler_addr). When the channels are activated, UMR
+        * WQEs will redirect the RX WQEs to the actual memory from
+        * the RQ's pool, while the gaps (wqe_overflow) remain mapped
+        * to the default page.
+        */
+       mtt = MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
+       for (i = 0 ; i < npages ; i++)
+               mtt[i].ptag = cpu_to_be64(filler_addr);
 
        err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
 
@@ -292,7 +299,8 @@ static int mlx5e_create_rq_umr_mkey(struct mlx5_core_dev *mdev, struct mlx5e_rq
 {
        u64 num_mtts = MLX5E_REQUIRED_MTTS(mlx5_wq_ll_get_size(&rq->mpwqe.wq));
 
-       return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
+       return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey,
+                                    rq->wqe_overflow.addr);
 }
 
 static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
@@ -360,6 +368,28 @@ static void mlx5e_rq_err_cqe_work(struct work_struct *recover_work)
        mlx5e_reporter_rq_cqe_err(rq);
 }
 
+static int mlx5e_alloc_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
+{
+       rq->wqe_overflow.page = alloc_page(GFP_KERNEL);
+       if (!rq->wqe_overflow.page)
+               return -ENOMEM;
+
+       rq->wqe_overflow.addr = dma_map_page(rq->pdev, rq->wqe_overflow.page, 0,
+                                            PAGE_SIZE, rq->buff.map_dir);
+       if (dma_mapping_error(rq->pdev, rq->wqe_overflow.addr)) {
+               __free_page(rq->wqe_overflow.page);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void mlx5e_free_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
+{
+        dma_unmap_page(rq->pdev, rq->wqe_overflow.addr, PAGE_SIZE,
+                       rq->buff.map_dir);
+        __free_page(rq->wqe_overflow.page);
+}
+
 static int mlx5e_alloc_rq(struct mlx5e_channel *c,
                          struct mlx5e_params *params,
                          struct mlx5e_xsk_param *xsk,
@@ -399,16 +429,16 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
 
        if (params->xdp_prog)
                bpf_prog_inc(params->xdp_prog);
-       rq->xdp_prog = params->xdp_prog;
+       RCU_INIT_POINTER(rq->xdp_prog, params->xdp_prog);
 
        rq_xdp_ix = rq->ix;
        if (xsk)
                rq_xdp_ix += params->num_channels * MLX5E_RQ_GROUP_XSK;
        err = xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix);
        if (err < 0)
-               goto err_rq_wq_destroy;
+               goto err_rq_xdp_prog;
 
-       rq->buff.map_dir = rq->xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
+       rq->buff.map_dir = params->xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
        rq->buff.headroom = mlx5e_get_rq_headroom(mdev, params, xsk);
        pool_size = 1 << params->log_rq_mtu_frames;
 
@@ -417,6 +447,10 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
                err = mlx5_wq_ll_create(mdev, &rqp->wq, rqc_wq, &rq->mpwqe.wq,
                                        &rq->wq_ctrl);
                if (err)
+                       goto err_rq_xdp;
+
+               err = mlx5e_alloc_mpwqe_rq_drop_page(rq);
+               if (err)
                        goto err_rq_wq_destroy;
 
                rq->mpwqe.wq.db = &rq->mpwqe.wq.db[MLX5_RCV_DBR];
@@ -434,18 +468,18 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
 
                err = mlx5e_create_rq_umr_mkey(mdev, rq);
                if (err)
-                       goto err_rq_wq_destroy;
+                       goto err_rq_drop_page;
                rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);
 
                err = mlx5e_rq_alloc_mpwqe_info(rq, c);
                if (err)
-                       goto err_free;
+                       goto err_rq_mkey;
                break;
        default: /* MLX5_WQ_TYPE_CYCLIC */
                err = mlx5_wq_cyc_create(mdev, &rqp->wq, rqc_wq, &rq->wqe.wq,
                                         &rq->wq_ctrl);
                if (err)
-                       goto err_rq_wq_destroy;
+                       goto err_rq_xdp;
 
                rq->wqe.wq.db = &rq->wqe.wq.db[MLX5_RCV_DBR];
 
@@ -460,19 +494,19 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
                                      GFP_KERNEL, cpu_to_node(c->cpu));
                if (!rq->wqe.frags) {
                        err = -ENOMEM;
-                       goto err_free;
+                       goto err_rq_wq_destroy;
                }
 
                err = mlx5e_init_di_list(rq, wq_sz, c->cpu);
                if (err)
-                       goto err_free;
+                       goto err_rq_frags;
 
                rq->mkey_be = c->mkey_be;
        }
 
        err = mlx5e_rq_set_handlers(rq, params, xsk);
        if (err)
-               goto err_free;
+               goto err_free_by_rq_type;
 
        if (xsk) {
                err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
@@ -496,13 +530,13 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
                if (IS_ERR(rq->page_pool)) {
                        err = PTR_ERR(rq->page_pool);
                        rq->page_pool = NULL;
-                       goto err_free;
+                       goto err_free_by_rq_type;
                }
                err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
                                                 MEM_TYPE_PAGE_POOL, rq->page_pool);
        }
        if (err)
-               goto err_free;
+               goto err_free_by_rq_type;
 
        for (i = 0; i < wq_sz; i++) {
                if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
@@ -552,38 +586,49 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
 
        return 0;
 
-err_free:
+err_free_by_rq_type:
        switch (rq->wq_type) {
        case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
                kvfree(rq->mpwqe.info);
+err_rq_mkey:
                mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
+err_rq_drop_page:
+               mlx5e_free_mpwqe_rq_drop_page(rq);
                break;
        default: /* MLX5_WQ_TYPE_CYCLIC */
-               kvfree(rq->wqe.frags);
                mlx5e_free_di_list(rq);
+err_rq_frags:
+               kvfree(rq->wqe.frags);
        }
-
 err_rq_wq_destroy:
-       if (rq->xdp_prog)
-               bpf_prog_put(rq->xdp_prog);
-       xdp_rxq_info_unreg(&rq->xdp_rxq);
-       page_pool_destroy(rq->page_pool);
        mlx5_wq_destroy(&rq->wq_ctrl);
+err_rq_xdp:
+       xdp_rxq_info_unreg(&rq->xdp_rxq);
+err_rq_xdp_prog:
+       if (params->xdp_prog)
+               bpf_prog_put(params->xdp_prog);
 
        return err;
 }
 
 static void mlx5e_free_rq(struct mlx5e_rq *rq)
 {
+       struct mlx5e_channel *c = rq->channel;
+       struct bpf_prog *old_prog = NULL;
        int i;
 
-       if (rq->xdp_prog)
-               bpf_prog_put(rq->xdp_prog);
+       /* drop_rq has neither channel nor xdp_prog. */
+       if (c)
+               old_prog = rcu_dereference_protected(rq->xdp_prog,
+                                                    lockdep_is_held(&c->priv->state_lock));
+       if (old_prog)
+               bpf_prog_put(old_prog);
 
        switch (rq->wq_type) {
        case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
                kvfree(rq->mpwqe.info);
                mlx5_core_destroy_mkey(rq->mdev, &rq->umr_mkey);
+               mlx5e_free_mpwqe_rq_drop_page(rq);
                break;
        default: /* MLX5_WQ_TYPE_CYCLIC */
                kvfree(rq->wqe.frags);
@@ -867,7 +912,7 @@ void mlx5e_activate_rq(struct mlx5e_rq *rq)
 void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
 {
        clear_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
-       napi_synchronize(&rq->channel->napi); /* prevent mlx5e_post_rx_wqes */
+       synchronize_rcu(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */
 }
 
 void mlx5e_close_rq(struct mlx5e_rq *rq)
@@ -1312,12 +1357,10 @@ void mlx5e_tx_disable_queue(struct netdev_queue *txq)
 
 static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
 {
-       struct mlx5e_channel *c = sq->channel;
        struct mlx5_wq_cyc *wq = &sq->wq;
 
        clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
-       /* prevent netif_tx_wake_queue */
-       napi_synchronize(&c->napi);
+       synchronize_rcu(); /* Sync with NAPI to prevent netif_tx_wake_queue. */
 
        mlx5e_tx_disable_queue(sq->txq);
 
@@ -1392,10 +1435,8 @@ void mlx5e_activate_icosq(struct mlx5e_icosq *icosq)
 
 void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq)
 {
-       struct mlx5e_channel *c = icosq->channel;
-
        clear_bit(MLX5E_SQ_STATE_ENABLED, &icosq->state);
-       napi_synchronize(&c->napi);
+       synchronize_rcu(); /* Sync with NAPI. */
 }
 
 void mlx5e_close_icosq(struct mlx5e_icosq *sq)
@@ -1474,7 +1515,7 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq)
        struct mlx5e_channel *c = sq->channel;
 
        clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
-       napi_synchronize(&c->napi);
+       synchronize_rcu(); /* Sync with NAPI. */
 
        mlx5e_destroy_sq(c->mdev, sq->sqn);
        mlx5e_free_xdpsq_descs(sq);
@@ -3567,6 +3608,7 @@ void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
 
                s->rx_packets   += rq_stats->packets + xskrq_stats->packets;
                s->rx_bytes     += rq_stats->bytes + xskrq_stats->bytes;
+               s->multicast    += rq_stats->mcast_packets + xskrq_stats->mcast_packets;
 
                for (j = 0; j < priv->max_opened_tc; j++) {
                        struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j];
@@ -3582,7 +3624,6 @@ void
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
-       struct mlx5e_vport_stats *vstats = &priv->stats.vport;
        struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 
        /* In switchdev mode, monitor counters doesn't monitor
@@ -3617,12 +3658,6 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
        stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
                           stats->rx_frame_errors;
        stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors;
-
-       /* vport multicast also counts packets that are dropped due to steering
-        * or rx out of buffer
-        */
-       stats->multicast =
-               VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
 }
 
 static void mlx5e_set_rx_mode(struct net_device *dev)
@@ -4191,6 +4226,21 @@ int mlx5e_get_vf_stats(struct net_device *dev,
 }
 #endif
 
+static bool mlx5e_gre_tunnel_inner_proto_offload_supported(struct mlx5_core_dev *mdev,
+                                                          struct sk_buff *skb)
+{
+       switch (skb->inner_protocol) {
+       case htons(ETH_P_IP):
+       case htons(ETH_P_IPV6):
+       case htons(ETH_P_TEB):
+               return true;
+       case htons(ETH_P_MPLS_UC):
+       case htons(ETH_P_MPLS_MC):
+               return MLX5_CAP_ETH(mdev, tunnel_stateless_mpls_over_gre);
+       }
+       return false;
+}
+
 static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
                                                     struct sk_buff *skb,
                                                     netdev_features_t features)
@@ -4213,7 +4263,9 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
 
        switch (proto) {
        case IPPROTO_GRE:
-               return features;
+               if (mlx5e_gre_tunnel_inner_proto_offload_supported(priv->mdev, skb))
+                       return features;
+               break;
        case IPPROTO_IPIP:
        case IPPROTO_IPV6:
                if (mlx5e_tunnel_proto_supported(priv->mdev, IPPROTO_IPIP))
@@ -4330,6 +4382,16 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
        return 0;
 }
 
+static void mlx5e_rq_replace_xdp_prog(struct mlx5e_rq *rq, struct bpf_prog *prog)
+{
+       struct bpf_prog *old_prog;
+
+       old_prog = rcu_replace_pointer(rq->xdp_prog, prog,
+                                      lockdep_is_held(&rq->channel->priv->state_lock));
+       if (old_prog)
+               bpf_prog_put(old_prog);
+}
+
 static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -4388,29 +4450,10 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
         */
        for (i = 0; i < priv->channels.num; i++) {
                struct mlx5e_channel *c = priv->channels.c[i];
-               bool xsk_open = test_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
-
-               clear_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
-               if (xsk_open)
-                       clear_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
-               napi_synchronize(&c->napi);
-               /* prevent mlx5e_poll_rx_cq from accessing rq->xdp_prog */
-
-               old_prog = xchg(&c->rq.xdp_prog, prog);
-               if (old_prog)
-                       bpf_prog_put(old_prog);
-
-               if (xsk_open) {
-                       old_prog = xchg(&c->xskrq.xdp_prog, prog);
-                       if (old_prog)
-                               bpf_prog_put(old_prog);
-               }
 
-               set_bit(MLX5E_RQ_STATE_ENABLED, &c->rq.state);
-               if (xsk_open)
-                       set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state);
-               /* napi_schedule in case we have missed anything */
-               napi_schedule(&c->napi);
+               mlx5e_rq_replace_xdp_prog(&c->rq, prog);
+               if (test_bit(MLX5E_CHANNEL_STATE_XSK, c->state))
+                       mlx5e_rq_replace_xdp_prog(&c->xskrq, prog);
        }
 
 unlock:
@@ -5200,7 +5243,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
        .enable            = mlx5e_nic_enable,
        .disable           = mlx5e_nic_disable,
        .update_rx         = mlx5e_update_nic_rx,
-       .update_stats      = mlx5e_update_ndo_stats,
+       .update_stats      = mlx5e_stats_update_ndo_stats,
        .update_carrier    = mlx5e_update_carrier,
        .rx_handlers       = &mlx5e_rx_handlers_nic,
        .max_tc            = MLX5E_MAX_NUM_TC,
index e13e5d1..e979bff 100644 (file)
@@ -1171,7 +1171,7 @@ static const struct mlx5e_profile mlx5e_rep_profile = {
        .cleanup_tx             = mlx5e_cleanup_rep_tx,
        .enable                 = mlx5e_rep_enable,
        .update_rx              = mlx5e_update_rep_rx,
-       .update_stats           = mlx5e_update_ndo_stats,
+       .update_stats           = mlx5e_stats_update_ndo_stats,
        .rx_handlers            = &mlx5e_rx_handlers_rep,
        .max_tc                 = 1,
        .rq_groups              = MLX5E_NUM_RQ_GROUPS(REGULAR),
@@ -1189,7 +1189,7 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
        .enable                 = mlx5e_uplink_rep_enable,
        .disable                = mlx5e_uplink_rep_disable,
        .update_rx              = mlx5e_update_rep_rx,
-       .update_stats           = mlx5e_update_ndo_stats,
+       .update_stats           = mlx5e_stats_update_ndo_stats,
        .update_carrier         = mlx5e_update_carrier,
        .rx_handlers            = &mlx5e_rx_handlers_rep,
        .max_tc                 = MLX5E_MAX_NUM_TC,
index 622c27a..0d1562e 100644 (file)
@@ -135,12 +135,6 @@ struct mlx5e_neigh_hash_entry {
        /* encap list sharing the same neigh */
        struct list_head encap_list;
 
-       /* valid only when the neigh reference is taken during
-        * neigh_update_work workqueue callback.
-        */
-       struct neighbour *n;
-       struct work_struct neigh_update_work;
-
        /* neigh hash entry can be deleted only when the refcount is zero.
         * refcount is needed to avoid neigh hash entry removal by TC, while
         * it's used by the neigh notification call.
index 65828af..64c8ac5 100644 (file)
@@ -53,6 +53,7 @@
 #include "en/xsk/rx.h"
 #include "en/health.h"
 #include "en/params.h"
+#include "en/txrx.h"
 
 static struct sk_buff *
 mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
@@ -1080,6 +1081,9 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
                mlx5e_enable_ecn(rq, skb);
 
        skb->protocol = eth_type_trans(skb, netdev);
+
+       if (unlikely(mlx5e_skb_is_multicast(skb)))
+               stats->mcast_packets++;
 }
 
 static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq,
@@ -1132,7 +1136,6 @@ mlx5e_skb_from_cqe_linear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
        struct xdp_buff xdp;
        struct sk_buff *skb;
        void *va, *data;
-       bool consumed;
        u32 frag_size;
 
        va             = page_address(di->page) + wi->offset;
@@ -1144,11 +1147,8 @@ mlx5e_skb_from_cqe_linear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
        prefetchw(va); /* xdp_frame data area */
        prefetch(data);
 
-       rcu_read_lock();
        mlx5e_fill_xdp_buff(rq, va, rx_headroom, cqe_bcnt, &xdp);
-       consumed = mlx5e_xdp_handle(rq, di, &cqe_bcnt, &xdp);
-       rcu_read_unlock();
-       if (consumed)
+       if (mlx5e_xdp_handle(rq, di, &cqe_bcnt, &xdp))
                return NULL; /* page/packet was consumed by XDP */
 
        rx_headroom = xdp.data - xdp.data_hard_start;
@@ -1438,7 +1438,6 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
        struct sk_buff *skb;
        void *va, *data;
        u32 frag_size;
-       bool consumed;
 
        /* Check packet size. Note LRO doesn't use linear SKB */
        if (unlikely(cqe_bcnt > rq->hw_mtu)) {
@@ -1455,11 +1454,8 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
        prefetchw(va); /* xdp_frame data area */
        prefetch(data);
 
-       rcu_read_lock();
        mlx5e_fill_xdp_buff(rq, va, rx_headroom, cqe_bcnt32, &xdp);
-       consumed = mlx5e_xdp_handle(rq, di, &cqe_bcnt32, &xdp);
-       rcu_read_unlock();
-       if (consumed) {
+       if (mlx5e_xdp_handle(rq, di, &cqe_bcnt32, &xdp)) {
                if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
                        __set_bit(page_idx, wi->xdp_xmit_bitmap); /* non-atomic */
                return NULL; /* page/packet was consumed by XDP */
index e3b2f59..f6383bc 100644 (file)
@@ -54,6 +54,18 @@ unsigned int mlx5e_stats_total_num(struct mlx5e_priv *priv)
        return total;
 }
 
+void mlx5e_stats_update_ndo_stats(struct mlx5e_priv *priv)
+{
+       mlx5e_stats_grp_t *stats_grps = priv->profile->stats_grps;
+       const unsigned int num_stats_grps = stats_grps_num(priv);
+       int i;
+
+       for (i = num_stats_grps - 1; i >= 0; i--)
+               if (stats_grps[i]->update_stats &&
+                   stats_grps[i]->update_stats_mask & MLX5E_NDO_UPDATE_STATS)
+                       stats_grps[i]->update_stats(priv);
+}
+
 void mlx5e_stats_update(struct mlx5e_priv *priv)
 {
        mlx5e_stats_grp_t *stats_grps = priv->profile->stats_grps;
index 2e1cca1..562263d 100644 (file)
@@ -103,6 +103,7 @@ unsigned int mlx5e_stats_total_num(struct mlx5e_priv *priv);
 void mlx5e_stats_update(struct mlx5e_priv *priv);
 void mlx5e_stats_fill(struct mlx5e_priv *priv, u64 *data, int idx);
 void mlx5e_stats_fill_strings(struct mlx5e_priv *priv, u8 *data);
+void mlx5e_stats_update_ndo_stats(struct mlx5e_priv *priv);
 
 /* Concrete NIC Stats */
 
@@ -119,6 +120,7 @@ struct mlx5e_sw_stats {
        u64 tx_nop;
        u64 rx_lro_packets;
        u64 rx_lro_bytes;
+       u64 rx_mcast_packets;
        u64 rx_ecn_mark;
        u64 rx_removed_vlan_packets;
        u64 rx_csum_unnecessary;
@@ -298,6 +300,7 @@ struct mlx5e_rq_stats {
        u64 csum_none;
        u64 lro_packets;
        u64 lro_bytes;
+       u64 mcast_packets;
        u64 ecn_mark;
        u64 removed_vlan_packets;
        u64 xdp_drop;
index fd53d10..1c93f92 100644 (file)
@@ -1290,11 +1290,8 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 
        mlx5e_put_flow_tunnel_id(flow);
 
-       if (flow_flag_test(flow, NOT_READY)) {
+       if (flow_flag_test(flow, NOT_READY))
                remove_unready_flow(flow);
-               kvfree(attr->parse_attr);
-               return;
-       }
 
        if (mlx5e_is_offloaded_flow(flow)) {
                if (flow_flag_test(flow, SLOW))
@@ -1315,6 +1312,8 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
                }
        kvfree(attr->parse_attr);
 
+       mlx5_tc_ct_match_del(priv, &flow->esw_attr->ct_attr);
+
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                mlx5e_detach_mod_hdr(priv, flow);
 
@@ -2625,6 +2624,22 @@ static struct mlx5_fields fields[] = {
        OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest,   0, udp_dport),
 };
 
+static unsigned long mask_to_le(unsigned long mask, int size)
+{
+       __be32 mask_be32;
+       __be16 mask_be16;
+
+       if (size == 32) {
+               mask_be32 = (__force __be32)(mask);
+               mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
+       } else if (size == 16) {
+               mask_be32 = (__force __be32)(mask);
+               mask_be16 = *(__be16 *)&mask_be32;
+               mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
+       }
+
+       return mask;
+}
 static int offload_pedit_fields(struct mlx5e_priv *priv,
                                int namespace,
                                struct pedit_headers_action *hdrs,
@@ -2638,9 +2653,7 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
        u32 *s_masks_p, *a_masks_p, s_mask, a_mask;
        struct mlx5e_tc_mod_hdr_acts *mod_acts;
        struct mlx5_fields *f;
-       unsigned long mask;
-       __be32 mask_be32;
-       __be16 mask_be16;
+       unsigned long mask, field_mask;
        int err;
        u8 cmd;
 
@@ -2706,14 +2719,7 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
                if (skip)
                        continue;
 
-               if (f->field_bsize == 32) {
-                       mask_be32 = (__force __be32)(mask);
-                       mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
-               } else if (f->field_bsize == 16) {
-                       mask_be32 = (__force __be32)(mask);
-                       mask_be16 = *(__be16 *)&mask_be32;
-                       mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
-               }
+               mask = mask_to_le(mask, f->field_bsize);
 
                first = find_first_bit(&mask, f->field_bsize);
                next_z = find_next_zero_bit(&mask, f->field_bsize, first);
@@ -2744,9 +2750,10 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
                if (cmd == MLX5_ACTION_TYPE_SET) {
                        int start;
 
+                       field_mask = mask_to_le(f->field_mask, f->field_bsize);
+
                        /* if field is bit sized it can start not from first bit */
-                       start = find_first_bit((unsigned long *)&f->field_mask,
-                                              f->field_bsize);
+                       start = find_first_bit(&field_mask, f->field_bsize);
 
                        MLX5_SET(set_action_in, action, offset, first - start);
                        /* length is num of bits to be written, zero means length of 32 */
@@ -4402,8 +4409,8 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
                goto err_free;
 
        /* actions validation depends on parsing the ct matches first */
-       err = mlx5_tc_ct_parse_match(priv, &parse_attr->spec, f,
-                                    &flow->esw_attr->ct_attr, extack);
+       err = mlx5_tc_ct_match_add(priv, &parse_attr->spec, f,
+                                  &flow->esw_attr->ct_attr, extack);
        if (err)
                goto err_free;
 
index de10b06..d586867 100644 (file)
@@ -121,13 +121,17 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
        struct mlx5e_xdpsq *xsksq = &c->xsksq;
        struct mlx5e_rq *xskrq = &c->xskrq;
        struct mlx5e_rq *rq = &c->rq;
-       bool xsk_open = test_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
        bool aff_change = false;
        bool busy_xsk = false;
        bool busy = false;
        int work_done = 0;
+       bool xsk_open;
        int i;
 
+       rcu_read_lock();
+
+       xsk_open = test_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
+
        ch_stats->poll++;
 
        for (i = 0; i < c->num_tc; i++)
@@ -167,8 +171,10 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
        busy |= busy_xsk;
 
        if (busy) {
-               if (likely(mlx5e_channel_no_affinity_change(c)))
-                       return budget;
+               if (likely(mlx5e_channel_no_affinity_change(c))) {
+                       work_done = budget;
+                       goto out;
+               }
                ch_stats->aff_change++;
                aff_change = true;
                if (budget && work_done == budget)
@@ -176,7 +182,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
        }
 
        if (unlikely(!napi_complete_done(napi, work_done)))
-               return work_done;
+               goto out;
 
        ch_stats->arm++;
 
@@ -203,6 +209,9 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
                ch_stats->force_irq++;
        }
 
+out:
+       rcu_read_unlock();
+
        return work_done;
 }
 
index 31ef9f8..22a19d3 100644 (file)
@@ -189,6 +189,29 @@ u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq)
        return count_eqe;
 }
 
+static void mlx5_eq_async_int_lock(struct mlx5_eq_async *eq, unsigned long *flags)
+       __acquires(&eq->lock)
+{
+       if (in_irq())
+               spin_lock(&eq->lock);
+       else
+               spin_lock_irqsave(&eq->lock, *flags);
+}
+
+static void mlx5_eq_async_int_unlock(struct mlx5_eq_async *eq, unsigned long *flags)
+       __releases(&eq->lock)
+{
+       if (in_irq())
+               spin_unlock(&eq->lock);
+       else
+               spin_unlock_irqrestore(&eq->lock, *flags);
+}
+
+enum async_eq_nb_action {
+       ASYNC_EQ_IRQ_HANDLER = 0,
+       ASYNC_EQ_RECOVER = 1,
+};
+
 static int mlx5_eq_async_int(struct notifier_block *nb,
                             unsigned long action, void *data)
 {
@@ -198,11 +221,14 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
        struct mlx5_eq_table *eqt;
        struct mlx5_core_dev *dev;
        struct mlx5_eqe *eqe;
+       unsigned long flags;
        int num_eqes = 0;
 
        dev = eq->dev;
        eqt = dev->priv.eq_table;
 
+       mlx5_eq_async_int_lock(eq_async, &flags);
+
        eqe = next_eqe_sw(eq);
        if (!eqe)
                goto out;
@@ -223,8 +249,19 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
 
 out:
        eq_update_ci(eq, 1);
+       mlx5_eq_async_int_unlock(eq_async, &flags);
 
-       return 0;
+       return unlikely(action == ASYNC_EQ_RECOVER) ? num_eqes : 0;
+}
+
+void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev)
+{
+       struct mlx5_eq_async *eq = &dev->priv.eq_table->cmd_eq;
+       int eqes;
+
+       eqes = mlx5_eq_async_int(&eq->irq_nb, ASYNC_EQ_RECOVER, NULL);
+       if (eqes)
+               mlx5_core_warn(dev, "Recovered %d EQEs on cmd_eq\n", eqes);
 }
 
 static void init_eq_buf(struct mlx5_eq *eq)
@@ -569,6 +606,7 @@ setup_async_eq(struct mlx5_core_dev *dev, struct mlx5_eq_async *eq,
        int err;
 
        eq->irq_nb.notifier_call = mlx5_eq_async_int;
+       spin_lock_init(&eq->lock);
 
        err = create_async_eq(dev, &eq->core, param);
        if (err) {
@@ -656,8 +694,10 @@ static void destroy_async_eqs(struct mlx5_core_dev *dev)
 
        cleanup_async_eq(dev, &table->pages_eq, "pages");
        cleanup_async_eq(dev, &table->async_eq, "async");
+       mlx5_cmd_allowed_opcode(dev, MLX5_CMD_OP_DESTROY_EQ);
        mlx5_cmd_use_polling(dev);
        cleanup_async_eq(dev, &table->cmd_eq, "cmd");
+       mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL);
        mlx5_eq_notifier_unregister(dev, &table->cq_err_nb);
 }
 
index d251692..1bcf260 100644 (file)
@@ -1219,35 +1219,37 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
        }
        esw->fdb_table.offloads.send_to_vport_grp = g;
 
-       /* create peer esw miss group */
-       memset(flow_group_in, 0, inlen);
+       if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
+               /* create peer esw miss group */
+               memset(flow_group_in, 0, inlen);
 
-       esw_set_flow_group_source_port(esw, flow_group_in);
+               esw_set_flow_group_source_port(esw, flow_group_in);
 
-       if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
-               match_criteria = MLX5_ADDR_OF(create_flow_group_in,
-                                             flow_group_in,
-                                             match_criteria);
+               if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
+                       match_criteria = MLX5_ADDR_OF(create_flow_group_in,
+                                                     flow_group_in,
+                                                     match_criteria);
 
-               MLX5_SET_TO_ONES(fte_match_param, match_criteria,
-                                misc_parameters.source_eswitch_owner_vhca_id);
+                       MLX5_SET_TO_ONES(fte_match_param, match_criteria,
+                                        misc_parameters.source_eswitch_owner_vhca_id);
 
-               MLX5_SET(create_flow_group_in, flow_group_in,
-                        source_eswitch_owner_vhca_id_valid, 1);
-       }
+                       MLX5_SET(create_flow_group_in, flow_group_in,
+                                source_eswitch_owner_vhca_id_valid, 1);
+               }
 
-       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
-       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
-                ix + esw->total_vports - 1);
-       ix += esw->total_vports;
+               MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
+               MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
+                        ix + esw->total_vports - 1);
+               ix += esw->total_vports;
 
-       g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR(g)) {
-               err = PTR_ERR(g);
-               esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
-               goto peer_miss_err;
+               g = mlx5_create_flow_group(fdb, flow_group_in);
+               if (IS_ERR(g)) {
+                       err = PTR_ERR(g);
+                       esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
+                       goto peer_miss_err;
+               }
+               esw->fdb_table.offloads.peer_miss_grp = g;
        }
-       esw->fdb_table.offloads.peer_miss_grp = g;
 
        /* create miss group */
        memset(flow_group_in, 0, inlen);
@@ -1281,7 +1283,8 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
 miss_rule_err:
        mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 miss_err:
-       mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
+       if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
+               mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
 peer_miss_err:
        mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
 send_vport_err:
@@ -1305,7 +1308,8 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
        mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
        mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
        mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
-       mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
+       if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
+               mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
        mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 
        mlx5_esw_chains_destroy(esw);
index 9ccec5f..75fa44e 100644 (file)
@@ -654,7 +654,7 @@ static struct fs_fte *alloc_fte(struct mlx5_flow_table *ft,
        fte->action = *flow_act;
        fte->flow_context = spec->flow_context;
 
-       tree_init_node(&fte->node, NULL, del_sw_fte);
+       tree_init_node(&fte->node, del_hw_fte, del_sw_fte);
 
        return fte;
 }
@@ -1792,7 +1792,6 @@ skip_search:
                up_write_ref_node(&g->node, false);
                rule = add_rule_fg(g, spec, flow_act, dest, dest_num, fte);
                up_write_ref_node(&fte->node, false);
-               tree_put_node(&fte->node, false);
                return rule;
        }
        rule = ERR_PTR(-ENOENT);
@@ -1891,7 +1890,6 @@ search_again_locked:
        up_write_ref_node(&g->node, false);
        rule = add_rule_fg(g, spec, flow_act, dest, dest_num, fte);
        up_write_ref_node(&fte->node, false);
-       tree_put_node(&fte->node, false);
        tree_put_node(&g->node, false);
        return rule;
 
@@ -2001,7 +1999,9 @@ void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
                up_write_ref_node(&fte->node, false);
        } else {
                del_hw_fte(&fte->node);
-               up_write(&fte->node.lock);
+               /* Avoid double call to del_hw_fte */
+               fte->node.del_hw_func = NULL;
+               up_write_ref_node(&fte->node, false);
                tree_put_node(&fte->node, false);
        }
        kfree(handle);
index 4aaca74..5c681e3 100644 (file)
@@ -37,6 +37,7 @@ struct mlx5_eq {
 struct mlx5_eq_async {
        struct mlx5_eq          core;
        struct notifier_block   irq_nb;
+       spinlock_t              lock; /* To avoid irq EQ handle races with resiliency flows */
 };
 
 struct mlx5_eq_comp {
@@ -81,6 +82,7 @@ void mlx5_cq_tasklet_cb(unsigned long data);
 struct cpumask *mlx5_eq_comp_cpumask(struct mlx5_core_dev *dev, int ix);
 
 u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq);
+void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev);
 void mlx5_eq_synchronize_async_irq(struct mlx5_core_dev *dev);
 void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev);
 
index f9b798a..c0e18f2 100644 (file)
@@ -432,7 +432,7 @@ static int reclaim_pages_cmd(struct mlx5_core_dev *dev,
        u32 npages;
        u32 i = 0;
 
-       if (dev->state != MLX5_DEVICE_STATE_INTERNAL_ERROR)
+       if (!mlx5_cmd_is_down(dev))
                return mlx5_cmd_exec(dev, in, in_size, out, out_size);
 
        /* No hard feelings, we want our pages back! */
index 373981a..6fd9749 100644 (file)
@@ -115,7 +115,7 @@ static int request_irqs(struct mlx5_core_dev *dev, int nvec)
        return 0;
 
 err_request_irq:
-       for (; i >= 0; i--) {
+       while (i--) {
                struct mlx5_irq *irq = mlx5_irq_get(dev, i);
                int irqn = pci_irq_vector(dev->pdev, i);
 
index 4186e29..f3c0e24 100644 (file)
@@ -3690,13 +3690,13 @@ bool mlxsw_sp_port_dev_check(const struct net_device *dev)
        return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
 }
 
-static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, void *data)
+static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev,
+                                  struct netdev_nested_priv *priv)
 {
-       struct mlxsw_sp_port **p_mlxsw_sp_port = data;
        int ret = 0;
 
        if (mlxsw_sp_port_dev_check(lower_dev)) {
-               *p_mlxsw_sp_port = netdev_priv(lower_dev);
+               priv->data = (void *)netdev_priv(lower_dev);
                ret = 1;
        }
 
@@ -3705,15 +3705,16 @@ static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, void *data)
 
 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
 {
-       struct mlxsw_sp_port *mlxsw_sp_port;
+       struct netdev_nested_priv priv = {
+               .data = NULL,
+       };
 
        if (mlxsw_sp_port_dev_check(dev))
                return netdev_priv(dev);
 
-       mlxsw_sp_port = NULL;
-       netdev_walk_all_lower_dev(dev, mlxsw_sp_lower_dev_walk, &mlxsw_sp_port);
+       netdev_walk_all_lower_dev(dev, mlxsw_sp_lower_dev_walk, &priv);
 
-       return mlxsw_sp_port;
+       return (struct mlxsw_sp_port *)priv.data;
 }
 
 struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
@@ -3726,16 +3727,17 @@ struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
 
 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
 {
-       struct mlxsw_sp_port *mlxsw_sp_port;
+       struct netdev_nested_priv priv = {
+               .data = NULL,
+       };
 
        if (mlxsw_sp_port_dev_check(dev))
                return netdev_priv(dev);
 
-       mlxsw_sp_port = NULL;
        netdev_walk_all_lower_dev_rcu(dev, mlxsw_sp_lower_dev_walk,
-                                     &mlxsw_sp_port);
+                                     &priv);
 
-       return mlxsw_sp_port;
+       return (struct mlxsw_sp_port *)priv.data;
 }
 
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
index 5c02040..7cccc41 100644 (file)
@@ -292,13 +292,14 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam,
        int err;
 
        group->tcam = tcam;
-       mutex_init(&group->lock);
        INIT_LIST_HEAD(&group->region_list);
 
        err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
        if (err)
                return err;
 
+       mutex_init(&group->lock);
+
        return 0;
 }
 
index 24f1fd1..460cb52 100644 (file)
@@ -7351,9 +7351,10 @@ int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
        return err;
 }
 
-static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev, void *data)
+static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev,
+                                       struct netdev_nested_priv *priv)
 {
-       struct mlxsw_sp_rif *rif = data;
+       struct mlxsw_sp_rif *rif = (struct mlxsw_sp_rif *)priv->data;
 
        if (!netif_is_macvlan(dev))
                return 0;
@@ -7364,12 +7365,16 @@ static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev, void *data)
 
 static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)rif,
+       };
+
        if (!netif_is_macvlan_port(rif->dev))
                return 0;
 
        netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n");
        return netdev_walk_all_upper_dev_rcu(rif->dev,
-                                            __mlxsw_sp_rif_macvlan_flush, rif);
+                                            __mlxsw_sp_rif_macvlan_flush, &priv);
 }
 
 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
index 72912af..6501ce9 100644 (file)
@@ -136,9 +136,9 @@ bool mlxsw_sp_bridge_device_is_offloaded(const struct mlxsw_sp *mlxsw_sp,
 }
 
 static int mlxsw_sp_bridge_device_upper_rif_destroy(struct net_device *dev,
-                                                   void *data)
+                                                   struct netdev_nested_priv *priv)
 {
-       struct mlxsw_sp *mlxsw_sp = data;
+       struct mlxsw_sp *mlxsw_sp = priv->data;
 
        mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev);
        return 0;
@@ -147,10 +147,14 @@ static int mlxsw_sp_bridge_device_upper_rif_destroy(struct net_device *dev,
 static void mlxsw_sp_bridge_device_rifs_destroy(struct mlxsw_sp *mlxsw_sp,
                                                struct net_device *dev)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)mlxsw_sp,
+       };
+
        mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev);
        netdev_walk_all_upper_dev_rcu(dev,
                                      mlxsw_sp_bridge_device_upper_rif_destroy,
-                                     mlxsw_sp);
+                                     &priv);
 }
 
 static int mlxsw_sp_bridge_device_vxlan_init(struct mlxsw_sp_bridge *bridge,
index 5abb7d2..aa002db 100644 (file)
@@ -421,10 +421,15 @@ int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
 
        if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
            ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+               spin_lock(&ocelot_port->ts_id_lock);
+
                shinfo->tx_flags |= SKBTX_IN_PROGRESS;
                /* Store timestamp ID in cb[0] of sk_buff */
-               skb->cb[0] = ocelot_port->ts_id % 4;
+               skb->cb[0] = ocelot_port->ts_id;
+               ocelot_port->ts_id = (ocelot_port->ts_id + 1) % 4;
                skb_queue_tail(&ocelot_port->tx_skbs, skb);
+
+               spin_unlock(&ocelot_port->ts_id_lock);
                return 0;
        }
        return -ENODATA;
@@ -1248,7 +1253,7 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
        struct ocelot_port *ocelot_port = ocelot->ports[port];
        int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
        int pause_start, pause_stop;
-       int atop_wm;
+       int atop, atop_tot;
 
        if (port == ocelot->npi) {
                maxlen += OCELOT_TAG_LEN;
@@ -1269,12 +1274,12 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
        ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_STOP,
                            pause_stop);
 
-       /* Tail dropping watermark */
-       atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
+       /* Tail dropping watermarks */
+       atop_tot = (ocelot->shared_queue_sz - 9 * maxlen) /
                   OCELOT_BUFFER_CELL_SZ;
-       ocelot_write_rix(ocelot, ocelot->ops->wm_enc(9 * maxlen),
-                        SYS_ATOP, port);
-       ocelot_write(ocelot, ocelot->ops->wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
+       atop = (9 * maxlen) / OCELOT_BUFFER_CELL_SZ;
+       ocelot_write_rix(ocelot, ocelot->ops->wm_enc(atop), SYS_ATOP, port);
+       ocelot_write(ocelot, ocelot->ops->wm_enc(atop_tot), SYS_ATOP_TOT_CFG);
 }
 EXPORT_SYMBOL(ocelot_port_set_maxlen);
 
@@ -1300,6 +1305,7 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
        struct ocelot_port *ocelot_port = ocelot->ports[port];
 
        skb_queue_head_init(&ocelot_port->tx_skbs);
+       spin_lock_init(&ocelot_port->ts_id_lock);
 
        /* Basic L2 initialization */
 
@@ -1544,18 +1550,18 @@ EXPORT_SYMBOL(ocelot_init);
 
 void ocelot_deinit(struct ocelot *ocelot)
 {
-       struct ocelot_port *port;
-       int i;
-
        cancel_delayed_work(&ocelot->stats_work);
        destroy_workqueue(ocelot->stats_queue);
        mutex_destroy(&ocelot->stats_lock);
-
-       for (i = 0; i < ocelot->num_phys_ports; i++) {
-               port = ocelot->ports[i];
-               skb_queue_purge(&port->tx_skbs);
-       }
 }
 EXPORT_SYMBOL(ocelot_deinit);
 
+void ocelot_deinit_port(struct ocelot *ocelot, int port)
+{
+       struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+       skb_queue_purge(&ocelot_port->tx_skbs);
+}
+EXPORT_SYMBOL(ocelot_deinit_port);
+
 MODULE_LICENSE("Dual MIT/GPL");
index 0668d23..8490e42 100644 (file)
@@ -330,6 +330,7 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
        u8 grp = 0; /* Send everything on CPU group 0 */
        unsigned int i, count, last;
        int port = priv->chip_port;
+       bool do_tstamp;
 
        val = ocelot_read(ocelot, QS_INJ_STATUS);
        if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp))) ||
@@ -344,10 +345,12 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
        info.vid = skb_vlan_tag_get(skb);
 
        /* Check if timestamping is needed */
+       do_tstamp = (ocelot_port_add_txtstamp_skb(ocelot_port, skb) == 0);
+
        if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
                info.rew_op = ocelot_port->ptp_cmd;
                if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
-                       info.rew_op |= (ocelot_port->ts_id  % 4) << 3;
+                       info.rew_op |= skb->cb[0] << 3;
        }
 
        ocelot_gen_ifh(ifh, &info);
@@ -380,12 +383,9 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += skb->len;
 
-       if (!ocelot_port_add_txtstamp_skb(ocelot_port, skb)) {
-               ocelot_port->ts_id++;
-               return NETDEV_TX_OK;
-       }
+       if (!do_tstamp)
+               dev_kfree_skb_any(skb);
 
-       dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
 }
 
index 65408bc..8a69176 100644 (file)
@@ -745,6 +745,8 @@ static int ocelot_reset(struct ocelot *ocelot)
  */
 static u16 ocelot_wm_enc(u16 value)
 {
+       WARN_ON(value >= 16 * BIT(8));
+
        if (value >= BIT(8))
                return BIT(8) | (value / 16);
 
@@ -806,17 +808,17 @@ static const struct vcap_field vsc7514_vcap_is2_keys[] = {
        [VCAP_IS2_HK_DIP_EQ_SIP]                = {123,   1},
        /* IP4_TCP_UDP (TYPE=100) */
        [VCAP_IS2_HK_TCP]                       = {124,   1},
-       [VCAP_IS2_HK_L4_SPORT]                  = {125,  16},
-       [VCAP_IS2_HK_L4_DPORT]                  = {141,  16},
+       [VCAP_IS2_HK_L4_DPORT]                  = {125,  16},
+       [VCAP_IS2_HK_L4_SPORT]                  = {141,  16},
        [VCAP_IS2_HK_L4_RNG]                    = {157,   8},
        [VCAP_IS2_HK_L4_SPORT_EQ_DPORT]         = {165,   1},
        [VCAP_IS2_HK_L4_SEQUENCE_EQ0]           = {166,   1},
-       [VCAP_IS2_HK_L4_URG]                    = {167,   1},
-       [VCAP_IS2_HK_L4_ACK]                    = {168,   1},
-       [VCAP_IS2_HK_L4_PSH]                    = {169,   1},
-       [VCAP_IS2_HK_L4_RST]                    = {170,   1},
-       [VCAP_IS2_HK_L4_SYN]                    = {171,   1},
-       [VCAP_IS2_HK_L4_FIN]                    = {172,   1},
+       [VCAP_IS2_HK_L4_FIN]                    = {167,   1},
+       [VCAP_IS2_HK_L4_SYN]                    = {168,   1},
+       [VCAP_IS2_HK_L4_RST]                    = {169,   1},
+       [VCAP_IS2_HK_L4_PSH]                    = {170,   1},
+       [VCAP_IS2_HK_L4_ACK]                    = {171,   1},
+       [VCAP_IS2_HK_L4_URG]                    = {172,   1},
        [VCAP_IS2_HK_L4_1588_DOM]               = {173,   8},
        [VCAP_IS2_HK_L4_1588_VER]               = {181,   4},
        /* IP4_OTHER (TYPE=101) */
@@ -896,11 +898,137 @@ static struct ptp_clock_info ocelot_ptp_clock_info = {
        .enable         = ocelot_ptp_enable,
 };
 
+static void mscc_ocelot_release_ports(struct ocelot *ocelot)
+{
+       int port;
+
+       for (port = 0; port < ocelot->num_phys_ports; port++) {
+               struct ocelot_port_private *priv;
+               struct ocelot_port *ocelot_port;
+
+               ocelot_port = ocelot->ports[port];
+               if (!ocelot_port)
+                       continue;
+
+               ocelot_deinit_port(ocelot, port);
+
+               priv = container_of(ocelot_port, struct ocelot_port_private,
+                                   port);
+
+               unregister_netdev(priv->dev);
+               free_netdev(priv->dev);
+       }
+}
+
+static int mscc_ocelot_init_ports(struct platform_device *pdev,
+                                 struct device_node *ports)
+{
+       struct ocelot *ocelot = platform_get_drvdata(pdev);
+       struct device_node *portnp;
+       int err;
+
+       ocelot->ports = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
+                                    sizeof(struct ocelot_port *), GFP_KERNEL);
+       if (!ocelot->ports)
+               return -ENOMEM;
+
+       /* No NPI port */
+       ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
+                            OCELOT_TAG_PREFIX_NONE);
+
+       for_each_available_child_of_node(ports, portnp) {
+               struct ocelot_port_private *priv;
+               struct ocelot_port *ocelot_port;
+               struct device_node *phy_node;
+               phy_interface_t phy_mode;
+               struct phy_device *phy;
+               struct regmap *target;
+               struct resource *res;
+               struct phy *serdes;
+               char res_name[8];
+               u32 port;
+
+               if (of_property_read_u32(portnp, "reg", &port))
+                       continue;
+
+               snprintf(res_name, sizeof(res_name), "port%d", port);
+
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                  res_name);
+               target = ocelot_regmap_init(ocelot, res);
+               if (IS_ERR(target))
+                       continue;
+
+               phy_node = of_parse_phandle(portnp, "phy-handle", 0);
+               if (!phy_node)
+                       continue;
+
+               phy = of_phy_find_device(phy_node);
+               of_node_put(phy_node);
+               if (!phy)
+                       continue;
+
+               err = ocelot_probe_port(ocelot, port, target, phy);
+               if (err) {
+                       of_node_put(portnp);
+                       return err;
+               }
+
+               ocelot_port = ocelot->ports[port];
+               priv = container_of(ocelot_port, struct ocelot_port_private,
+                                   port);
+
+               of_get_phy_mode(portnp, &phy_mode);
+
+               ocelot_port->phy_mode = phy_mode;
+
+               switch (ocelot_port->phy_mode) {
+               case PHY_INTERFACE_MODE_NA:
+                       continue;
+               case PHY_INTERFACE_MODE_SGMII:
+                       break;
+               case PHY_INTERFACE_MODE_QSGMII:
+                       /* Ensure clock signals and speed is set on all
+                        * QSGMII links
+                        */
+                       ocelot_port_writel(ocelot_port,
+                                          DEV_CLOCK_CFG_LINK_SPEED
+                                          (OCELOT_SPEED_1000),
+                                          DEV_CLOCK_CFG);
+                       break;
+               default:
+                       dev_err(ocelot->dev,
+                               "invalid phy mode for port%d, (Q)SGMII only\n",
+                               port);
+                       of_node_put(portnp);
+                       return -EINVAL;
+               }
+
+               serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
+               if (IS_ERR(serdes)) {
+                       err = PTR_ERR(serdes);
+                       if (err == -EPROBE_DEFER)
+                               dev_dbg(ocelot->dev, "deferring probe\n");
+                       else
+                               dev_err(ocelot->dev,
+                                       "missing SerDes phys for port%d\n",
+                                       port);
+
+                       of_node_put(portnp);
+                       return err;
+               }
+
+               priv->serdes = serdes;
+       }
+
+       return 0;
+}
+
 static int mscc_ocelot_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       struct device_node *ports, *portnp;
        int err, irq_xtr, irq_ptp_rdy;
+       struct device_node *ports;
        struct ocelot *ocelot;
        struct regmap *hsio;
        unsigned int i;
@@ -985,20 +1113,24 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
 
        ports = of_get_child_by_name(np, "ethernet-ports");
        if (!ports) {
-               dev_err(&pdev->dev, "no ethernet-ports child node found\n");
+               dev_err(ocelot->dev, "no ethernet-ports child node found\n");
                return -ENODEV;
        }
 
        ocelot->num_phys_ports = of_get_child_count(ports);
 
-       ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports,
-                                    sizeof(struct ocelot_port *), GFP_KERNEL);
-
        ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys;
        ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions;
        ocelot->vcap = vsc7514_vcap_props;
 
-       ocelot_init(ocelot);
+       err = ocelot_init(ocelot);
+       if (err)
+               goto out_put_ports;
+
+       err = mscc_ocelot_init_ports(pdev, ports);
+       if (err)
+               goto out_put_ports;
+
        if (ocelot->ptp) {
                err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
                if (err) {
@@ -1008,96 +1140,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
                }
        }
 
-       /* No NPI port */
-       ocelot_configure_cpu(ocelot, -1, OCELOT_TAG_PREFIX_NONE,
-                            OCELOT_TAG_PREFIX_NONE);
-
-       for_each_available_child_of_node(ports, portnp) {
-               struct ocelot_port_private *priv;
-               struct ocelot_port *ocelot_port;
-               struct device_node *phy_node;
-               phy_interface_t phy_mode;
-               struct phy_device *phy;
-               struct regmap *target;
-               struct resource *res;
-               struct phy *serdes;
-               char res_name[8];
-               u32 port;
-
-               if (of_property_read_u32(portnp, "reg", &port))
-                       continue;
-
-               snprintf(res_name, sizeof(res_name), "port%d", port);
-
-               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                                  res_name);
-               target = ocelot_regmap_init(ocelot, res);
-               if (IS_ERR(target))
-                       continue;
-
-               phy_node = of_parse_phandle(portnp, "phy-handle", 0);
-               if (!phy_node)
-                       continue;
-
-               phy = of_phy_find_device(phy_node);
-               of_node_put(phy_node);
-               if (!phy)
-                       continue;
-
-               err = ocelot_probe_port(ocelot, port, target, phy);
-               if (err) {
-                       of_node_put(portnp);
-                       goto out_put_ports;
-               }
-
-               ocelot_port = ocelot->ports[port];
-               priv = container_of(ocelot_port, struct ocelot_port_private,
-                                   port);
-
-               of_get_phy_mode(portnp, &phy_mode);
-
-               ocelot_port->phy_mode = phy_mode;
-
-               switch (ocelot_port->phy_mode) {
-               case PHY_INTERFACE_MODE_NA:
-                       continue;
-               case PHY_INTERFACE_MODE_SGMII:
-                       break;
-               case PHY_INTERFACE_MODE_QSGMII:
-                       /* Ensure clock signals and speed is set on all
-                        * QSGMII links
-                        */
-                       ocelot_port_writel(ocelot_port,
-                                          DEV_CLOCK_CFG_LINK_SPEED
-                                          (OCELOT_SPEED_1000),
-                                          DEV_CLOCK_CFG);
-                       break;
-               default:
-                       dev_err(ocelot->dev,
-                               "invalid phy mode for port%d, (Q)SGMII only\n",
-                               port);
-                       of_node_put(portnp);
-                       err = -EINVAL;
-                       goto out_put_ports;
-               }
-
-               serdes = devm_of_phy_get(ocelot->dev, portnp, NULL);
-               if (IS_ERR(serdes)) {
-                       err = PTR_ERR(serdes);
-                       if (err == -EPROBE_DEFER)
-                               dev_dbg(ocelot->dev, "deferring probe\n");
-                       else
-                               dev_err(ocelot->dev,
-                                       "missing SerDes phys for port%d\n",
-                                       port);
-
-                       of_node_put(portnp);
-                       goto out_put_ports;
-               }
-
-               priv->serdes = serdes;
-       }
-
        register_netdevice_notifier(&ocelot_netdevice_nb);
        register_switchdev_notifier(&ocelot_switchdev_nb);
        register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
@@ -1114,6 +1156,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
        struct ocelot *ocelot = platform_get_drvdata(pdev);
 
        ocelot_deinit_timestamp(ocelot);
+       mscc_ocelot_release_ports(ocelot);
        ocelot_deinit(ocelot);
        unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
        unregister_switchdev_notifier(&ocelot_switchdev_nb);
index 6eb9fb9..9c9ae33 100644 (file)
@@ -829,8 +829,8 @@ nfp_port_get_fecparam(struct net_device *netdev,
        struct nfp_eth_table_port *eth_port;
        struct nfp_port *port;
 
-       param->active_fec = ETHTOOL_FEC_NONE_BIT;
-       param->fec = ETHTOOL_FEC_NONE_BIT;
+       param->active_fec = ETHTOOL_FEC_NONE;
+       param->fec = ETHTOOL_FEC_NONE;
 
        port = nfp_port_from_netdev(netdev);
        eth_port = nfp_port_get_eth_port(port);
index b8f076e..3db181f 100644 (file)
@@ -4253,7 +4253,8 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
                        cdev->mf_bits = BIT(QED_MF_LLH_MAC_CLSS) |
                                        BIT(QED_MF_LLH_PROTO_CLSS) |
                                        BIT(QED_MF_LL2_NON_UNICAST) |
-                                       BIT(QED_MF_INTER_PF_SWITCH);
+                                       BIT(QED_MF_INTER_PF_SWITCH) |
+                                       BIT(QED_MF_DISABLE_ARFS);
                        break;
                case NVM_CFG1_GLOB_MF_MODE_DEFAULT:
                        cdev->mf_bits = BIT(QED_MF_LLH_MAC_CLSS) |
@@ -4266,6 +4267,14 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 
                DP_INFO(p_hwfn, "Multi function mode is 0x%lx\n",
                        cdev->mf_bits);
+
+               /* In CMT the PF is unknown when the GFS block processes the
+                * packet. Therefore cannot use searcher as it has a per PF
+                * database, and thus ARFS must be disabled.
+                *
+                */
+               if (QED_IS_CMT(cdev))
+                       cdev->mf_bits |= BIT(QED_MF_DISABLE_ARFS);
        }
 
        DP_INFO(p_hwfn, "Multi function mode is 0x%lx\n",
index 4c6ac88..07824bf 100644 (file)
@@ -1980,6 +1980,9 @@ void qed_arfs_mode_configure(struct qed_hwfn *p_hwfn,
                             struct qed_ptt *p_ptt,
                             struct qed_arfs_config_params *p_cfg_params)
 {
+       if (test_bit(QED_MF_DISABLE_ARFS, &p_hwfn->cdev->mf_bits))
+               return;
+
        if (p_cfg_params->mode != QED_FILTER_CONFIG_MODE_DISABLE) {
                qed_gft_config(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
                               p_cfg_params->tcp,
index f39f629..50e5eb2 100644 (file)
@@ -444,6 +444,8 @@ int qed_fill_dev_info(struct qed_dev *cdev,
                dev_info->fw_eng = FW_ENGINEERING_VERSION;
                dev_info->b_inter_pf_switch = test_bit(QED_MF_INTER_PF_SWITCH,
                                                       &cdev->mf_bits);
+               if (!test_bit(QED_MF_DISABLE_ARFS, &cdev->mf_bits))
+                       dev_info->b_arfs_capable = true;
                dev_info->tx_switching = true;
 
                if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME)
index f1f75b6..b8dc5c4 100644 (file)
@@ -71,6 +71,7 @@ static int qed_sp_vf_start(struct qed_hwfn *p_hwfn, struct qed_vf_info *p_vf)
                p_ramrod->personality = PERSONALITY_ETH;
                break;
        case QED_PCI_ETH_ROCE:
+       case QED_PCI_ETH_IWARP:
                p_ramrod->personality = PERSONALITY_RDMA_AND_ETH;
                break;
        default:
index f961f65..c59b72c 100644 (file)
@@ -311,6 +311,9 @@ int qede_alloc_arfs(struct qede_dev *edev)
 {
        int i;
 
+       if (!edev->dev_info.common.b_arfs_capable)
+               return -EINVAL;
+
        edev->arfs = vzalloc(sizeof(*edev->arfs));
        if (!edev->arfs)
                return -ENOMEM;
index 140a392..9e1f41b 100644 (file)
@@ -804,7 +804,7 @@ static void qede_init_ndev(struct qede_dev *edev)
                      NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                      NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_TC;
 
-       if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1)
+       if (edev->dev_info.common.b_arfs_capable)
                hw_features |= NETIF_F_NTUPLE;
 
        if (edev->dev_info.common.vxlan_enable ||
@@ -2274,7 +2274,7 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode,
        qede_vlan_mark_nonconfigured(edev);
        edev->ops->fastpath_stop(edev->cdev);
 
-       if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1) {
+       if (edev->dev_info.common.b_arfs_capable) {
                qede_poll_for_freeing_arfs_filters(edev);
                qede_free_arfs(edev);
        }
@@ -2341,10 +2341,9 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
        if (rc)
                goto err2;
 
-       if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1) {
-               rc = qede_alloc_arfs(edev);
-               if (rc)
-                       DP_NOTICE(edev, "aRFS memory allocation failed\n");
+       if (qede_alloc_arfs(edev)) {
+               edev->ndev->features &= ~NETIF_F_NTUPLE;
+               edev->dev_info.common.b_arfs_capable = false;
        }
 
        qede_napi_add_enable(edev);
index fc9e662..11e6962 100644 (file)
@@ -2058,11 +2058,18 @@ static void rtl_release_firmware(struct rtl8169_private *tp)
 
 void r8169_apply_firmware(struct rtl8169_private *tp)
 {
+       int val;
+
        /* TODO: release firmware if rtl_fw_write_firmware signals failure. */
        if (tp->rtl_fw) {
                rtl_fw_write_firmware(tp, tp->rtl_fw);
                /* At least one firmware doesn't reset tp->ocp_base. */
                tp->ocp_base = OCP_STD_PHY_BASE;
+
+               /* PHY soft reset may still be in progress */
+               phy_read_poll_timeout(tp->phydev, MII_BMCR, val,
+                                     !(val & BMCR_RESET),
+                                     50000, 600000, true);
        }
 }
 
@@ -2239,14 +2246,10 @@ static void rtl_pll_power_down(struct rtl8169_private *tp)
        default:
                break;
        }
-
-       clk_disable_unprepare(tp->clk);
 }
 
 static void rtl_pll_power_up(struct rtl8169_private *tp)
 {
-       clk_prepare_enable(tp->clk);
-
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33:
        case RTL_GIGA_MAC_VER_37:
@@ -2904,7 +2907,7 @@ static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
                { 0x08, 0x0001, 0x0002 },
                { 0x09, 0x0000, 0x0080 },
                { 0x19, 0x0000, 0x0224 },
-               { 0x00, 0x0000, 0x0004 },
+               { 0x00, 0x0000, 0x0008 },
                { 0x0c, 0x3df0, 0x0200 },
        };
 
@@ -2921,7 +2924,7 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp)
                { 0x06, 0x00c0, 0x0020 },
                { 0x0f, 0xffff, 0x5200 },
                { 0x19, 0x0000, 0x0224 },
-               { 0x00, 0x0000, 0x0004 },
+               { 0x00, 0x0000, 0x0008 },
                { 0x0c, 0x3df0, 0x0200 },
        };
 
@@ -4826,29 +4829,43 @@ static void rtl8169_net_suspend(struct rtl8169_private *tp)
 
 #ifdef CONFIG_PM
 
+static int rtl8169_net_resume(struct rtl8169_private *tp)
+{
+       rtl_rar_set(tp, tp->dev->dev_addr);
+
+       if (tp->TxDescArray)
+               rtl8169_up(tp);
+
+       netif_device_attach(tp->dev);
+
+       return 0;
+}
+
 static int __maybe_unused rtl8169_suspend(struct device *device)
 {
        struct rtl8169_private *tp = dev_get_drvdata(device);
 
        rtnl_lock();
        rtl8169_net_suspend(tp);
+       if (!device_may_wakeup(tp_to_dev(tp)))
+               clk_disable_unprepare(tp->clk);
        rtnl_unlock();
 
        return 0;
 }
 
-static int rtl8169_resume(struct device *device)
+static int __maybe_unused rtl8169_resume(struct device *device)
 {
        struct rtl8169_private *tp = dev_get_drvdata(device);
 
-       rtl_rar_set(tp, tp->dev->dev_addr);
+       if (!device_may_wakeup(tp_to_dev(tp)))
+               clk_prepare_enable(tp->clk);
 
-       if (tp->TxDescArray)
-               rtl8169_up(tp);
+       /* Reportedly at least Asus X453MA truncates packets otherwise */
+       if (tp->mac_version == RTL_GIGA_MAC_VER_37)
+               rtl_init_rxcfg(tp);
 
-       netif_device_attach(tp->dev);
-
-       return 0;
+       return rtl8169_net_resume(tp);
 }
 
 static int rtl8169_runtime_suspend(struct device *device)
@@ -4874,7 +4891,7 @@ static int rtl8169_runtime_resume(struct device *device)
 
        __rtl8169_set_wol(tp, tp->saved_wolopts);
 
-       return rtl8169_resume(device);
+       return rtl8169_net_resume(tp);
 }
 
 static int rtl8169_runtime_idle(struct device *device)
index df89d09..99f7aae 100644 (file)
@@ -1342,51 +1342,6 @@ static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
        return error;
 }
 
-/* MDIO bus init function */
-static int ravb_mdio_init(struct ravb_private *priv)
-{
-       struct platform_device *pdev = priv->pdev;
-       struct device *dev = &pdev->dev;
-       int error;
-
-       /* Bitbang init */
-       priv->mdiobb.ops = &bb_ops;
-
-       /* MII controller setting */
-       priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
-       if (!priv->mii_bus)
-               return -ENOMEM;
-
-       /* Hook up MII support for ethtool */
-       priv->mii_bus->name = "ravb_mii";
-       priv->mii_bus->parent = dev;
-       snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
-                pdev->name, pdev->id);
-
-       /* Register MDIO bus */
-       error = of_mdiobus_register(priv->mii_bus, dev->of_node);
-       if (error)
-               goto out_free_bus;
-
-       return 0;
-
-out_free_bus:
-       free_mdio_bitbang(priv->mii_bus);
-       return error;
-}
-
-/* MDIO bus release function */
-static int ravb_mdio_release(struct ravb_private *priv)
-{
-       /* Unregister mdio bus */
-       mdiobus_unregister(priv->mii_bus);
-
-       /* Free bitbang info */
-       free_mdio_bitbang(priv->mii_bus);
-
-       return 0;
-}
-
 /* Network device open function for Ethernet AVB */
 static int ravb_open(struct net_device *ndev)
 {
@@ -1395,13 +1350,6 @@ static int ravb_open(struct net_device *ndev)
        struct device *dev = &pdev->dev;
        int error;
 
-       /* MDIO bus init */
-       error = ravb_mdio_init(priv);
-       if (error) {
-               netdev_err(ndev, "failed to initialize MDIO\n");
-               return error;
-       }
-
        napi_enable(&priv->napi[RAVB_BE]);
        napi_enable(&priv->napi[RAVB_NC]);
 
@@ -1479,7 +1427,6 @@ out_free_irq:
 out_napi_off:
        napi_disable(&priv->napi[RAVB_NC]);
        napi_disable(&priv->napi[RAVB_BE]);
-       ravb_mdio_release(priv);
        return error;
 }
 
@@ -1789,8 +1736,6 @@ static int ravb_close(struct net_device *ndev)
        ravb_ring_free(ndev, RAVB_BE);
        ravb_ring_free(ndev, RAVB_NC);
 
-       ravb_mdio_release(priv);
-
        return 0;
 }
 
@@ -1942,6 +1887,51 @@ static const struct net_device_ops ravb_netdev_ops = {
        .ndo_set_features       = ravb_set_features,
 };
 
+/* MDIO bus init function */
+static int ravb_mdio_init(struct ravb_private *priv)
+{
+       struct platform_device *pdev = priv->pdev;
+       struct device *dev = &pdev->dev;
+       int error;
+
+       /* Bitbang init */
+       priv->mdiobb.ops = &bb_ops;
+
+       /* MII controller setting */
+       priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
+       if (!priv->mii_bus)
+               return -ENOMEM;
+
+       /* Hook up MII support for ethtool */
+       priv->mii_bus->name = "ravb_mii";
+       priv->mii_bus->parent = dev;
+       snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+                pdev->name, pdev->id);
+
+       /* Register MDIO bus */
+       error = of_mdiobus_register(priv->mii_bus, dev->of_node);
+       if (error)
+               goto out_free_bus;
+
+       return 0;
+
+out_free_bus:
+       free_mdio_bitbang(priv->mii_bus);
+       return error;
+}
+
+/* MDIO bus release function */
+static int ravb_mdio_release(struct ravb_private *priv)
+{
+       /* Unregister mdio bus */
+       mdiobus_unregister(priv->mii_bus);
+
+       /* Free bitbang info */
+       free_mdio_bitbang(priv->mii_bus);
+
+       return 0;
+}
+
 static const struct of_device_id ravb_match_table[] = {
        { .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 },
        { .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 },
@@ -2184,6 +2174,13 @@ static int ravb_probe(struct platform_device *pdev)
                eth_hw_addr_random(ndev);
        }
 
+       /* MDIO bus init */
+       error = ravb_mdio_init(priv);
+       if (error) {
+               dev_err(&pdev->dev, "failed to initialize MDIO\n");
+               goto out_dma_free;
+       }
+
        netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll, 64);
        netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll, 64);
 
@@ -2205,6 +2202,8 @@ static int ravb_probe(struct platform_device *pdev)
 out_napi_del:
        netif_napi_del(&priv->napi[RAVB_NC]);
        netif_napi_del(&priv->napi[RAVB_BE]);
+       ravb_mdio_release(priv);
+out_dma_free:
        dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
                          priv->desc_bat_dma);
 
@@ -2236,6 +2235,7 @@ static int ravb_remove(struct platform_device *pdev)
        unregister_netdev(ndev);
        netif_napi_del(&priv->napi[RAVB_NC]);
        netif_napi_del(&priv->napi[RAVB_BE]);
+       ravb_mdio_release(priv);
        pm_runtime_disable(&pdev->dev);
        free_netdev(ndev);
        platform_set_drvdata(pdev, NULL);
index 42458a4..9cc31f7 100644 (file)
@@ -3099,9 +3099,10 @@ struct rocker_walk_data {
        struct rocker_port *port;
 };
 
-static int rocker_lower_dev_walk(struct net_device *lower_dev, void *_data)
+static int rocker_lower_dev_walk(struct net_device *lower_dev,
+                                struct netdev_nested_priv *priv)
 {
-       struct rocker_walk_data *data = _data;
+       struct rocker_walk_data *data = (struct rocker_walk_data *)priv->data;
        int ret = 0;
 
        if (rocker_port_dev_check_under(lower_dev, data->rocker)) {
@@ -3115,6 +3116,7 @@ static int rocker_lower_dev_walk(struct net_device *lower_dev, void *_data)
 struct rocker_port *rocker_port_dev_lower_find(struct net_device *dev,
                                               struct rocker *rocker)
 {
+       struct netdev_nested_priv priv;
        struct rocker_walk_data data;
 
        if (rocker_port_dev_check_under(dev, rocker))
@@ -3122,7 +3124,8 @@ struct rocker_port *rocker_port_dev_lower_find(struct net_device *dev,
 
        data.rocker = rocker;
        data.port = NULL;
-       netdev_walk_all_lower_dev(dev, rocker_lower_dev_walk, &data);
+       priv.data = (void *)&data;
+       netdev_walk_all_lower_dev(dev, rocker_lower_dev_walk, &priv);
 
        return data.port;
 }
index c54b7f8..ffdb367 100644 (file)
@@ -490,6 +490,7 @@ static int ef100_pci_probe(struct pci_dev *pci_dev,
        if (fcw.offset > pci_resource_len(efx->pci_dev, fcw.bar) - ESE_GZ_FCW_LEN) {
                netif_err(efx, probe, efx->net_dev,
                          "Func control window overruns BAR\n");
+               rc = -EIO;
                goto fail;
        }
 
index 2ac9dfb..9e6d60e 100644 (file)
@@ -653,7 +653,6 @@ static void intel_eth_pci_remove(struct pci_dev *pdev)
 
        pci_free_irq_vectors(pdev);
 
-       clk_disable_unprepare(priv->plat->stmmac_clk);
        clk_unregister_fixed_rate(priv->plat->stmmac_clk);
 
        pcim_iounmap_regions(pdev, BIT(0));
index 9c02fc7..5456969 100644 (file)
@@ -203,6 +203,8 @@ struct stmmac_priv {
        int eee_enabled;
        int eee_active;
        int tx_lpi_timer;
+       int tx_lpi_enabled;
+       int eee_tw_timer;
        unsigned int mode;
        unsigned int chain_mode;
        int extend_desc;
index ac5e8cc..814879f 100644 (file)
@@ -665,6 +665,7 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,
        edata->eee_enabled = priv->eee_enabled;
        edata->eee_active = priv->eee_active;
        edata->tx_lpi_timer = priv->tx_lpi_timer;
+       edata->tx_lpi_enabled = priv->tx_lpi_enabled;
 
        return phylink_ethtool_get_eee(priv->phylink, edata);
 }
@@ -675,24 +676,26 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret;
 
-       if (!edata->eee_enabled) {
+       if (!priv->dma_cap.eee)
+               return -EOPNOTSUPP;
+
+       if (priv->tx_lpi_enabled != edata->tx_lpi_enabled)
+               netdev_warn(priv->dev,
+                           "Setting EEE tx-lpi is not supported\n");
+
+       if (!edata->eee_enabled)
                stmmac_disable_eee_mode(priv);
-       } else {
-               /* We are asking for enabling the EEE but it is safe
-                * to verify all by invoking the eee_init function.
-                * In case of failure it will return an error.
-                */
-               edata->eee_enabled = stmmac_eee_init(priv);
-               if (!edata->eee_enabled)
-                       return -EOPNOTSUPP;
-       }
 
        ret = phylink_ethtool_set_eee(priv->phylink, edata);
        if (ret)
                return ret;
 
-       priv->eee_enabled = edata->eee_enabled;
-       priv->tx_lpi_timer = edata->tx_lpi_timer;
+       if (edata->eee_enabled &&
+           priv->tx_lpi_timer != edata->tx_lpi_timer) {
+               priv->tx_lpi_timer = edata->tx_lpi_timer;
+               stmmac_eee_init(priv);
+       }
+
        return 0;
 }
 
index 89b2b34..b56b13d 100644 (file)
@@ -94,7 +94,7 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
 static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
 module_param(eee_timer, int, 0644);
 MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
-#define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
+#define STMMAC_LPI_T(x) (jiffies + usecs_to_jiffies(x))
 
 /* By default the driver will use the ring mode to manage tx and rx descriptors,
  * but allow user to force to use the chain instead of the ring
@@ -370,7 +370,7 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
        struct stmmac_priv *priv = from_timer(priv, t, eee_ctrl_timer);
 
        stmmac_enable_eee_mode(priv);
-       mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
+       mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer));
 }
 
 /**
@@ -383,7 +383,7 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
  */
 bool stmmac_eee_init(struct stmmac_priv *priv)
 {
-       int tx_lpi_timer = priv->tx_lpi_timer;
+       int eee_tw_timer = priv->eee_tw_timer;
 
        /* Using PCS we cannot dial with the phy registers at this stage
         * so we do not support extra feature like EEE.
@@ -403,7 +403,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                if (priv->eee_enabled) {
                        netdev_dbg(priv->dev, "disable EEE\n");
                        del_timer_sync(&priv->eee_ctrl_timer);
-                       stmmac_set_eee_timer(priv, priv->hw, 0, tx_lpi_timer);
+                       stmmac_set_eee_timer(priv, priv->hw, 0, eee_tw_timer);
                }
                mutex_unlock(&priv->lock);
                return false;
@@ -411,11 +411,12 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
 
        if (priv->eee_active && !priv->eee_enabled) {
                timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0);
-               mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
                stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
-                                    tx_lpi_timer);
+                                    eee_tw_timer);
        }
 
+       mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer));
+
        mutex_unlock(&priv->lock);
        netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
        return true;
@@ -930,6 +931,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
 
        stmmac_mac_set(priv, priv->ioaddr, false);
        priv->eee_active = false;
+       priv->tx_lpi_enabled = false;
        stmmac_eee_init(priv);
        stmmac_set_eee_pls(priv, priv->hw, false);
 }
@@ -1027,6 +1029,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
        if (phy && priv->dma_cap.eee) {
                priv->eee_active = phy_init_eee(phy, 1) >= 0;
                priv->eee_enabled = stmmac_eee_init(priv);
+               priv->tx_lpi_enabled = priv->eee_enabled;
                stmmac_set_eee_pls(priv, priv->hw, true);
        }
 }
@@ -2061,7 +2064,7 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
 
        if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
                stmmac_enable_eee_mode(priv);
-               mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
+               mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer));
        }
 
        /* We still have pending packets, let's call for a new scheduling */
@@ -2694,7 +2697,11 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
                        netdev_warn(priv->dev, "PTP init failed\n");
        }
 
-       priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
+       priv->eee_tw_timer = STMMAC_DEFAULT_TWT_LS;
+
+       /* Convert the timer from msec to usec */
+       if (!priv->tx_lpi_timer)
+               priv->tx_lpi_timer = eee_timer * 1000;
 
        if (priv->use_riwt) {
                if (!priv->rx_riwt)
index 8ed7857..15672d0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/phy.h>
 #include <linux/phy/phy.h>
 #include <linux/delay.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/gpio/consumer.h>
 #include <linux/of.h>
@@ -2070,9 +2071,61 @@ static int cpsw_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int __maybe_unused cpsw_suspend(struct device *dev)
+{
+       struct cpsw_common *cpsw = dev_get_drvdata(dev);
+       int i;
+
+       rtnl_lock();
+
+       for (i = 0; i < cpsw->data.slaves; i++) {
+               struct net_device *ndev = cpsw->slaves[i].ndev;
+
+               if (!(ndev && netif_running(ndev)))
+                       continue;
+
+               cpsw_ndo_stop(ndev);
+       }
+
+       rtnl_unlock();
+
+       /* Select sleep pin state */
+       pinctrl_pm_select_sleep_state(dev);
+
+       return 0;
+}
+
+static int __maybe_unused cpsw_resume(struct device *dev)
+{
+       struct cpsw_common *cpsw = dev_get_drvdata(dev);
+       int i;
+
+       /* Select default pin state */
+       pinctrl_pm_select_default_state(dev);
+
+       /* shut up ASSERT_RTNL() warning in netif_set_real_num_tx/rx_queues */
+       rtnl_lock();
+
+       for (i = 0; i < cpsw->data.slaves; i++) {
+               struct net_device *ndev = cpsw->slaves[i].ndev;
+
+               if (!(ndev && netif_running(ndev)))
+                       continue;
+
+               cpsw_ndo_open(ndev);
+       }
+
+       rtnl_unlock();
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(cpsw_pm_ops, cpsw_suspend, cpsw_resume);
+
 static struct platform_driver cpsw_driver = {
        .driver = {
                .name    = "cpsw-switch",
+               .pm      = &cpsw_pm_ops,
                .of_match_table = cpsw_of_mtable,
        },
        .probe = cpsw_probe,
index 803247d..55b0dda 100644 (file)
@@ -2,7 +2,7 @@
 /*
        Written 1998-2001 by Donald Becker.
 
-       Current Maintainer: Roger Luethi <rl@hellgate.ch>
+       Current Maintainer: Kevin Brace <kevinbrace@bracecomputerlab.com>
 
        This software may be used and distributed according to the terms of
        the GNU General Public License (GPL), incorporated herein by reference.
@@ -32,8 +32,6 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define DRV_NAME       "via-rhine"
-#define DRV_VERSION    "1.5.1"
-#define DRV_RELDATE    "2010-10-09"
 
 #include <linux/types.h>
 
@@ -117,10 +115,6 @@ static const int multicast_filter_limit = 32;
 #include <linux/uaccess.h>
 #include <linux/dmi.h>
 
-/* These identify the driver base version and may not be removed. */
-static const char version[] =
-       "v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker";
-
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_LICENSE("GPL");
@@ -243,7 +237,7 @@ enum rhine_revs {
        VT8233          = 0x60, /* Integrated MAC */
        VT8235          = 0x74, /* Integrated MAC */
        VT8237          = 0x78, /* Integrated MAC */
-       VTunknown1      = 0x7C,
+       VT8251          = 0x7C, /* Integrated MAC */
        VT6105          = 0x80,
        VT6105_B0       = 0x83,
        VT6105L         = 0x8A,
@@ -1051,11 +1045,6 @@ static int rhine_init_one_pci(struct pci_dev *pdev,
        u32 quirks = 0;
 #endif
 
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-       pr_info_once("%s\n", version);
-#endif
-
        rc = pci_enable_device(pdev);
        if (rc)
                goto err_out;
@@ -1706,6 +1695,8 @@ static int rhine_open(struct net_device *dev)
                goto out_free_ring;
 
        alloc_tbufs(dev);
+       enable_mmio(rp->pioaddr, rp->quirks);
+       rhine_power_init(dev);
        rhine_chip_reset(dev);
        rhine_task_enable(rp);
        init_registers(dev);
@@ -2294,7 +2285,6 @@ static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
        struct device *hwdev = dev->dev.parent;
 
        strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
        strlcpy(info->bus_info, dev_name(hwdev), sizeof(info->bus_info));
 }
 
@@ -2616,9 +2606,6 @@ static int __init rhine_init(void)
        int ret_pci, ret_platform;
 
 /* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-       pr_info("%s\n", version);
-#endif
        if (dmi_check_system(rhine_dmi_table)) {
                /* these BIOSes fail at PXE boot if chip is in D3 */
                avoid_D3 = true;
index c71f994..974a244 100644 (file)
@@ -777,7 +777,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
                                       struct net_device *dev,
                                       struct geneve_sock *gs4,
                                       struct flowi4 *fl4,
-                                      const struct ip_tunnel_info *info)
+                                      const struct ip_tunnel_info *info,
+                                      __be16 dport, __be16 sport)
 {
        bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
        struct geneve_dev *geneve = netdev_priv(dev);
@@ -793,6 +794,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
        fl4->flowi4_proto = IPPROTO_UDP;
        fl4->daddr = info->key.u.ipv4.dst;
        fl4->saddr = info->key.u.ipv4.src;
+       fl4->fl4_dport = dport;
+       fl4->fl4_sport = sport;
 
        tos = info->key.tos;
        if ((tos == 1) && !geneve->cfg.collect_md) {
@@ -827,7 +830,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
                                           struct net_device *dev,
                                           struct geneve_sock *gs6,
                                           struct flowi6 *fl6,
-                                          const struct ip_tunnel_info *info)
+                                          const struct ip_tunnel_info *info,
+                                          __be16 dport, __be16 sport)
 {
        bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
        struct geneve_dev *geneve = netdev_priv(dev);
@@ -843,6 +847,9 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
        fl6->flowi6_proto = IPPROTO_UDP;
        fl6->daddr = info->key.u.ipv6.dst;
        fl6->saddr = info->key.u.ipv6.src;
+       fl6->fl6_dport = dport;
+       fl6->fl6_sport = sport;
+
        prio = info->key.tos;
        if ((prio == 1) && !geneve->cfg.collect_md) {
                prio = ip_tunnel_get_dsfield(ip_hdr(skb), skb);
@@ -889,7 +896,9 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        __be16 sport;
        int err;
 
-       rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info);
+       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+       rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info,
+                             geneve->cfg.info.key.tp_dst, sport);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
@@ -919,7 +928,6 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                return -EMSGSIZE;
        }
 
-       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        if (geneve->cfg.collect_md) {
                tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
@@ -974,7 +982,9 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        __be16 sport;
        int err;
 
-       dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info);
+       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+       dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info,
+                               geneve->cfg.info.key.tp_dst, sport);
        if (IS_ERR(dst))
                return PTR_ERR(dst);
 
@@ -1003,7 +1013,6 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                return -EMSGSIZE;
        }
 
-       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        if (geneve->cfg.collect_md) {
                prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
@@ -1085,13 +1094,18 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 {
        struct ip_tunnel_info *info = skb_tunnel_info(skb);
        struct geneve_dev *geneve = netdev_priv(dev);
+       __be16 sport;
 
        if (ip_tunnel_info_af(info) == AF_INET) {
                struct rtable *rt;
                struct flowi4 fl4;
+
                struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
+               sport = udp_flow_src_port(geneve->net, skb,
+                                         1, USHRT_MAX, true);
 
-               rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info);
+               rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info,
+                                     geneve->cfg.info.key.tp_dst, sport);
                if (IS_ERR(rt))
                        return PTR_ERR(rt);
 
@@ -1101,9 +1115,13 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
        } else if (ip_tunnel_info_af(info) == AF_INET6) {
                struct dst_entry *dst;
                struct flowi6 fl6;
+
                struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
+               sport = udp_flow_src_port(geneve->net, skb,
+                                         1, USHRT_MAX, true);
 
-               dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info);
+               dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info,
+                                       geneve->cfg.info.key.tp_dst, sport);
                if (IS_ERR(dst))
                        return PTR_ERR(dst);
 
@@ -1114,8 +1132,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
                return -EINVAL;
        }
 
-       info->key.tp_src = udp_flow_src_port(geneve->net, skb,
-                                            1, USHRT_MAX, true);
+       info->key.tp_src = sport;
        info->key.tp_dst = geneve->cfg.info.key.tp_dst;
        return 0;
 }
index 2181d45..a0f338c 100644 (file)
@@ -847,6 +847,10 @@ struct nvsp_message {
 
 #define NETVSC_XDP_HDRM 256
 
+#define NETVSC_XFER_HEADER_SIZE(rng_cnt) \
+               (offsetof(struct vmtransfer_page_packet_header, ranges) + \
+               (rng_cnt) * sizeof(struct vmtransfer_page_range))
+
 struct multi_send_data {
        struct sk_buff *skb; /* skb containing the pkt */
        struct hv_netvsc_packet *pkt; /* netvsc pkt pending */
@@ -974,6 +978,9 @@ struct net_device_context {
        /* Serial number of the VF to team with */
        u32 vf_serial;
 
+       /* Is the current data path through the VF NIC? */
+       bool  data_path_is_vf;
+
        /* Used to temporarily save the config info across hibernation */
        struct netvsc_device_info *saved_netvsc_dev_info;
 };
index 41f5cf0..5a57d19 100644 (file)
@@ -388,6 +388,15 @@ static int netvsc_init_buf(struct hv_device *device,
        net_device->recv_section_size = resp->sections[0].sub_alloc_size;
        net_device->recv_section_cnt = resp->sections[0].num_sub_allocs;
 
+       /* Ensure buffer will not overflow */
+       if (net_device->recv_section_size < NETVSC_MTU_MIN || (u64)net_device->recv_section_size *
+           (u64)net_device->recv_section_cnt > (u64)buf_size) {
+               netdev_err(ndev, "invalid recv_section_size %u\n",
+                          net_device->recv_section_size);
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
        /* Setup receive completion ring.
         * Add 1 to the recv_section_cnt because at least one entry in a
         * ring buffer has to be empty.
@@ -460,6 +469,12 @@ static int netvsc_init_buf(struct hv_device *device,
        /* Parse the response */
        net_device->send_section_size = init_packet->msg.
                                v1_msg.send_send_buf_complete.section_size;
+       if (net_device->send_section_size < NETVSC_MTU_MIN) {
+               netdev_err(ndev, "invalid send_section_size %u\n",
+                          net_device->send_section_size);
+               ret = -EINVAL;
+               goto cleanup;
+       }
 
        /* Section count is simply the size divided by the section size. */
        net_device->send_section_cnt = buf_size / net_device->send_section_size;
@@ -731,12 +746,49 @@ static void netvsc_send_completion(struct net_device *ndev,
                                   int budget)
 {
        const struct nvsp_message *nvsp_packet = hv_pkt_data(desc);
+       u32 msglen = hv_pkt_datalen(desc);
+
+       /* Ensure packet is big enough to read header fields */
+       if (msglen < sizeof(struct nvsp_message_header)) {
+               netdev_err(ndev, "nvsp_message length too small: %u\n", msglen);
+               return;
+       }
 
        switch (nvsp_packet->hdr.msg_type) {
        case NVSP_MSG_TYPE_INIT_COMPLETE:
+               if (msglen < sizeof(struct nvsp_message_header) +
+                               sizeof(struct nvsp_message_init_complete)) {
+                       netdev_err(ndev, "nvsp_msg length too small: %u\n",
+                                  msglen);
+                       return;
+               }
+               fallthrough;
+
        case NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE:
+               if (msglen < sizeof(struct nvsp_message_header) +
+                               sizeof(struct nvsp_1_message_send_receive_buffer_complete)) {
+                       netdev_err(ndev, "nvsp_msg1 length too small: %u\n",
+                                  msglen);
+                       return;
+               }
+               fallthrough;
+
        case NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE:
+               if (msglen < sizeof(struct nvsp_message_header) +
+                               sizeof(struct nvsp_1_message_send_send_buffer_complete)) {
+                       netdev_err(ndev, "nvsp_msg1 length too small: %u\n",
+                                  msglen);
+                       return;
+               }
+               fallthrough;
+
        case NVSP_MSG5_TYPE_SUBCHANNEL:
+               if (msglen < sizeof(struct nvsp_message_header) +
+                               sizeof(struct nvsp_5_subchannel_complete)) {
+                       netdev_err(ndev, "nvsp_msg5 length too small: %u\n",
+                                  msglen);
+                       return;
+               }
                /* Copy the response back */
                memcpy(&net_device->channel_init_pkt, nvsp_packet,
                       sizeof(struct nvsp_message));
@@ -1117,19 +1169,28 @@ static void enq_receive_complete(struct net_device *ndev,
 static int netvsc_receive(struct net_device *ndev,
                          struct netvsc_device *net_device,
                          struct netvsc_channel *nvchan,
-                         const struct vmpacket_descriptor *desc,
-                         const struct nvsp_message *nvsp)
+                         const struct vmpacket_descriptor *desc)
 {
        struct net_device_context *net_device_ctx = netdev_priv(ndev);
        struct vmbus_channel *channel = nvchan->channel;
        const struct vmtransfer_page_packet_header *vmxferpage_packet
                = container_of(desc, const struct vmtransfer_page_packet_header, d);
+       const struct nvsp_message *nvsp = hv_pkt_data(desc);
+       u32 msglen = hv_pkt_datalen(desc);
        u16 q_idx = channel->offermsg.offer.sub_channel_index;
        char *recv_buf = net_device->recv_buf;
        u32 status = NVSP_STAT_SUCCESS;
        int i;
        int count = 0;
 
+       /* Ensure packet is big enough to read header fields */
+       if (msglen < sizeof(struct nvsp_message_header)) {
+               netif_err(net_device_ctx, rx_err, ndev,
+                         "invalid nvsp header, length too small: %u\n",
+                         msglen);
+               return 0;
+       }
+
        /* Make sure this is a valid nvsp packet */
        if (unlikely(nvsp->hdr.msg_type != NVSP_MSG1_TYPE_SEND_RNDIS_PKT)) {
                netif_err(net_device_ctx, rx_err, ndev,
@@ -1138,6 +1199,14 @@ static int netvsc_receive(struct net_device *ndev,
                return 0;
        }
 
+       /* Validate xfer page pkt header */
+       if ((desc->offset8 << 3) < sizeof(struct vmtransfer_page_packet_header)) {
+               netif_err(net_device_ctx, rx_err, ndev,
+                         "Invalid xfer page pkt, offset too small: %u\n",
+                         desc->offset8 << 3);
+               return 0;
+       }
+
        if (unlikely(vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID)) {
                netif_err(net_device_ctx, rx_err, ndev,
                          "Invalid xfer page set id - expecting %x got %x\n",
@@ -1148,6 +1217,14 @@ static int netvsc_receive(struct net_device *ndev,
 
        count = vmxferpage_packet->range_cnt;
 
+       /* Check count for a valid value */
+       if (NETVSC_XFER_HEADER_SIZE(count) > desc->offset8 << 3) {
+               netif_err(net_device_ctx, rx_err, ndev,
+                         "Range count is not valid: %d\n",
+                         count);
+               return 0;
+       }
+
        /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
        for (i = 0; i < count; i++) {
                u32 offset = vmxferpage_packet->ranges[i].byte_offset;
@@ -1155,7 +1232,8 @@ static int netvsc_receive(struct net_device *ndev,
                void *data;
                int ret;
 
-               if (unlikely(offset + buflen > net_device->recv_buf_size)) {
+               if (unlikely(offset > net_device->recv_buf_size ||
+                            buflen > net_device->recv_buf_size - offset)) {
                        nvchan->rsc.cnt = 0;
                        status = NVSP_STAT_FAIL;
                        netif_err(net_device_ctx, rx_err, ndev,
@@ -1194,6 +1272,13 @@ static void netvsc_send_table(struct net_device *ndev,
        u32 count, offset, *tab;
        int i;
 
+       /* Ensure packet is big enough to read send_table fields */
+       if (msglen < sizeof(struct nvsp_message_header) +
+                    sizeof(struct nvsp_5_send_indirect_table)) {
+               netdev_err(ndev, "nvsp_v5_msg length too small: %u\n", msglen);
+               return;
+       }
+
        count = nvmsg->msg.v5_msg.send_table.count;
        offset = nvmsg->msg.v5_msg.send_table.offset;
 
@@ -1225,10 +1310,18 @@ static void netvsc_send_table(struct net_device *ndev,
 }
 
 static void netvsc_send_vf(struct net_device *ndev,
-                          const struct nvsp_message *nvmsg)
+                          const struct nvsp_message *nvmsg,
+                          u32 msglen)
 {
        struct net_device_context *net_device_ctx = netdev_priv(ndev);
 
+       /* Ensure packet is big enough to read its fields */
+       if (msglen < sizeof(struct nvsp_message_header) +
+                    sizeof(struct nvsp_4_send_vf_association)) {
+               netdev_err(ndev, "nvsp_v4_msg length too small: %u\n", msglen);
+               return;
+       }
+
        net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
        net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
        netdev_info(ndev, "VF slot %u %s\n",
@@ -1238,16 +1331,24 @@ static void netvsc_send_vf(struct net_device *ndev,
 
 static void netvsc_receive_inband(struct net_device *ndev,
                                  struct netvsc_device *nvscdev,
-                                 const struct nvsp_message *nvmsg,
-                                 u32 msglen)
+                                 const struct vmpacket_descriptor *desc)
 {
+       const struct nvsp_message *nvmsg = hv_pkt_data(desc);
+       u32 msglen = hv_pkt_datalen(desc);
+
+       /* Ensure packet is big enough to read header fields */
+       if (msglen < sizeof(struct nvsp_message_header)) {
+               netdev_err(ndev, "inband nvsp_message length too small: %u\n", msglen);
+               return;
+       }
+
        switch (nvmsg->hdr.msg_type) {
        case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
                netvsc_send_table(ndev, nvscdev, nvmsg, msglen);
                break;
 
        case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
-               netvsc_send_vf(ndev, nvmsg);
+               netvsc_send_vf(ndev, nvmsg, msglen);
                break;
        }
 }
@@ -1261,23 +1362,20 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
 {
        struct vmbus_channel *channel = nvchan->channel;
        const struct nvsp_message *nvmsg = hv_pkt_data(desc);
-       u32 msglen = hv_pkt_datalen(desc);
 
        trace_nvsp_recv(ndev, channel, nvmsg);
 
        switch (desc->type) {
        case VM_PKT_COMP:
-               netvsc_send_completion(ndev, net_device, channel,
-                                      desc, budget);
+               netvsc_send_completion(ndev, net_device, channel, desc, budget);
                break;
 
        case VM_PKT_DATA_USING_XFER_PAGES:
-               return netvsc_receive(ndev, net_device, nvchan,
-                                     desc, nvmsg);
+               return netvsc_receive(ndev, net_device, nvchan, desc);
                break;
 
        case VM_PKT_DATA_INBAND:
-               netvsc_receive_inband(ndev, net_device, nvmsg, msglen);
+               netvsc_receive_inband(ndev, net_device, desc);
                break;
 
        default:
index 64b0a74..9869e39 100644 (file)
@@ -748,6 +748,13 @@ void netvsc_linkstatus_callback(struct net_device *net,
        struct netvsc_reconfig *event;
        unsigned long flags;
 
+       /* Ensure the packet is big enough to access its fields */
+       if (resp->msg_len - RNDIS_HEADER_SIZE < sizeof(struct rndis_indicate_status)) {
+               netdev_err(net, "invalid rndis_indicate_status packet, len: %u\n",
+                          resp->msg_len);
+               return;
+       }
+
        /* Update the physical link speed when changing to another vSwitch */
        if (indicate->status == RNDIS_STATUS_LINK_SPEED_CHANGE) {
                u32 speed;
@@ -2366,7 +2373,16 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
        return NOTIFY_OK;
 }
 
-/* VF up/down change detected, schedule to change data path */
+/* Change the data path when VF UP/DOWN/CHANGE are detected.
+ *
+ * Typically a UP or DOWN event is followed by a CHANGE event, so
+ * net_device_ctx->data_path_is_vf is used to cache the current data path
+ * to avoid the duplicate call of netvsc_switch_datapath() and the duplicate
+ * message.
+ *
+ * During hibernation, if a VF NIC driver (e.g. mlx5) preserves the network
+ * interface, there is only the CHANGE event and no UP or DOWN event.
+ */
 static int netvsc_vf_changed(struct net_device *vf_netdev)
 {
        struct net_device_context *net_device_ctx;
@@ -2383,6 +2399,10 @@ static int netvsc_vf_changed(struct net_device *vf_netdev)
        if (!netvsc_dev)
                return NOTIFY_DONE;
 
+       if (net_device_ctx->data_path_is_vf == vf_is_up)
+               return NOTIFY_OK;
+       net_device_ctx->data_path_is_vf = vf_is_up;
+
        netvsc_switch_datapath(ndev, vf_is_up);
        netdev_info(ndev, "Data path switched %s VF: %s\n",
                    vf_is_up ? "to" : "from", vf_netdev->name);
@@ -2587,8 +2607,8 @@ static int netvsc_remove(struct hv_device *dev)
 static int netvsc_suspend(struct hv_device *dev)
 {
        struct net_device_context *ndev_ctx;
-       struct net_device *vf_netdev, *net;
        struct netvsc_device *nvdev;
+       struct net_device *net;
        int ret;
 
        net = hv_get_drvdata(dev);
@@ -2604,10 +2624,6 @@ static int netvsc_suspend(struct hv_device *dev)
                goto out;
        }
 
-       vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
-       if (vf_netdev)
-               netvsc_unregister_vf(vf_netdev);
-
        /* Save the current config info */
        ndev_ctx->saved_netvsc_dev_info = netvsc_devinfo_get(nvdev);
 
@@ -2628,6 +2644,12 @@ static int netvsc_resume(struct hv_device *dev)
        rtnl_lock();
 
        net_device_ctx = netdev_priv(net);
+
+       /* Reset the data path to the netvsc NIC before re-opening the vmbus
+        * channel. Later netvsc_netdev_event() will switch the data path to
+        * the VF upon the UP or CHANGE event.
+        */
+       net_device_ctx->data_path_is_vf = false;
        device_info = net_device_ctx->saved_netvsc_dev_info;
 
        ret = netvsc_attach(net, device_info);
@@ -2695,6 +2717,7 @@ static int netvsc_netdev_event(struct notifier_block *this,
                return netvsc_unregister_vf(event_dev);
        case NETDEV_UP:
        case NETDEV_DOWN:
+       case NETDEV_CHANGE:
                return netvsc_vf_changed(event_dev);
        default:
                return NOTIFY_DONE;
index b81ceba..12ad471 100644 (file)
@@ -275,6 +275,16 @@ static void rndis_filter_receive_response(struct net_device *ndev,
                return;
        }
 
+       /* Ensure the packet is big enough to read req_id. Req_id is the 1st
+        * field in any request/response message, so the payload should have at
+        * least sizeof(u32) bytes
+        */
+       if (resp->msg_len - RNDIS_HEADER_SIZE < sizeof(u32)) {
+               netdev_err(ndev, "rndis msg_len too small: %u\n",
+                          resp->msg_len);
+               return;
+       }
+
        spin_lock_irqsave(&dev->request_lock, flags);
        list_for_each_entry(request, &dev->req_list, list_ent) {
                /*
@@ -331,8 +341,9 @@ static void rndis_filter_receive_response(struct net_device *ndev,
  * Get the Per-Packet-Info with the specified type
  * return NULL if not found.
  */
-static inline void *rndis_get_ppi(struct rndis_packet *rpkt,
-                                 u32 type, u8 internal)
+static inline void *rndis_get_ppi(struct net_device *ndev,
+                                 struct rndis_packet *rpkt,
+                                 u32 rpkt_len, u32 type, u8 internal)
 {
        struct rndis_per_packet_info *ppi;
        int len;
@@ -340,11 +351,36 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt,
        if (rpkt->per_pkt_info_offset == 0)
                return NULL;
 
+       /* Validate info_offset and info_len */
+       if (rpkt->per_pkt_info_offset < sizeof(struct rndis_packet) ||
+           rpkt->per_pkt_info_offset > rpkt_len) {
+               netdev_err(ndev, "Invalid per_pkt_info_offset: %u\n",
+                          rpkt->per_pkt_info_offset);
+               return NULL;
+       }
+
+       if (rpkt->per_pkt_info_len > rpkt_len - rpkt->per_pkt_info_offset) {
+               netdev_err(ndev, "Invalid per_pkt_info_len: %u\n",
+                          rpkt->per_pkt_info_len);
+               return NULL;
+       }
+
        ppi = (struct rndis_per_packet_info *)((ulong)rpkt +
                rpkt->per_pkt_info_offset);
        len = rpkt->per_pkt_info_len;
 
        while (len > 0) {
+               /* Validate ppi_offset and ppi_size */
+               if (ppi->size > len) {
+                       netdev_err(ndev, "Invalid ppi size: %u\n", ppi->size);
+                       continue;
+               }
+
+               if (ppi->ppi_offset >= ppi->size) {
+                       netdev_err(ndev, "Invalid ppi_offset: %u\n", ppi->ppi_offset);
+                       continue;
+               }
+
                if (ppi->type == type && ppi->internal == internal)
                        return (void *)((ulong)ppi + ppi->ppi_offset);
                len -= ppi->size;
@@ -388,14 +424,29 @@ static int rndis_filter_receive_data(struct net_device *ndev,
        const struct ndis_pkt_8021q_info *vlan;
        const struct rndis_pktinfo_id *pktinfo_id;
        const u32 *hash_info;
-       u32 data_offset;
+       u32 data_offset, rpkt_len;
        void *data;
        bool rsc_more = false;
        int ret;
 
+       /* Ensure data_buflen is big enough to read header fields */
+       if (data_buflen < RNDIS_HEADER_SIZE + sizeof(struct rndis_packet)) {
+               netdev_err(ndev, "invalid rndis pkt, data_buflen too small: %u\n",
+                          data_buflen);
+               return NVSP_STAT_FAIL;
+       }
+
+       /* Validate rndis_pkt offset */
+       if (rndis_pkt->data_offset >= data_buflen - RNDIS_HEADER_SIZE) {
+               netdev_err(ndev, "invalid rndis packet offset: %u\n",
+                          rndis_pkt->data_offset);
+               return NVSP_STAT_FAIL;
+       }
+
        /* Remove the rndis header and pass it back up the stack */
        data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
 
+       rpkt_len = data_buflen - RNDIS_HEADER_SIZE;
        data_buflen -= data_offset;
 
        /*
@@ -410,13 +461,13 @@ static int rndis_filter_receive_data(struct net_device *ndev,
                return NVSP_STAT_FAIL;
        }
 
-       vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO, 0);
+       vlan = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, IEEE_8021Q_INFO, 0);
 
-       csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO, 0);
+       csum_info = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, TCPIP_CHKSUM_PKTINFO, 0);
 
-       hash_info = rndis_get_ppi(rndis_pkt, NBL_HASH_VALUE, 0);
+       hash_info = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, NBL_HASH_VALUE, 0);
 
-       pktinfo_id = rndis_get_ppi(rndis_pkt, RNDIS_PKTINFO_ID, 1);
+       pktinfo_id = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, RNDIS_PKTINFO_ID, 1);
 
        data = (void *)msg + data_offset;
 
@@ -474,6 +525,14 @@ int rndis_filter_receive(struct net_device *ndev,
        if (netif_msg_rx_status(net_device_ctx))
                dump_rndis_message(ndev, rndis_msg);
 
+       /* Validate incoming rndis_message packet */
+       if (buflen < RNDIS_HEADER_SIZE || rndis_msg->msg_len < RNDIS_HEADER_SIZE ||
+           buflen < rndis_msg->msg_len) {
+               netdev_err(ndev, "Invalid rndis_msg (buflen: %u, msg_len: %u)\n",
+                          buflen, rndis_msg->msg_len);
+               return NVSP_STAT_FAIL;
+       }
+
        switch (rndis_msg->ndis_msg_type) {
        case RNDIS_MSG_PACKET:
                return rndis_filter_receive_data(ndev, net_dev, nvchan,
index c11f32f..7db9cbd 100644 (file)
@@ -882,7 +882,9 @@ static int adf7242_rx(struct adf7242_local *lp)
        int ret;
        u8 lqi, len_u8, *data;
 
-       adf7242_read_reg(lp, 0, &len_u8);
+       ret = adf7242_read_reg(lp, 0, &len_u8);
+       if (ret)
+               return ret;
 
        len = len_u8;
 
index e04c3b6..4eb6470 100644 (file)
@@ -2925,6 +2925,7 @@ static int ca8210_dev_com_init(struct ca8210_priv *priv)
        );
        if (!priv->irq_workqueue) {
                dev_crit(&priv->spi->dev, "alloc of irq_workqueue failed!\n");
+               destroy_workqueue(priv->mlme_workqueue);
                return -ENOMEM;
        }
 
index 2098ca2..b3790aa 100644 (file)
@@ -521,7 +521,7 @@ static void ipa_filter_tuple_zero(struct ipa_endpoint *endpoint)
        val = ioread32(endpoint->ipa->reg_virt + offset);
 
        /* Zero all filter-related fields, preserving the rest */
-       u32_replace_bits(val, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
+       u32p_replace_bits(&val, 0, IPA_REG_ENDP_FILTER_HASH_MSK_ALL);
 
        iowrite32(val, endpoint->ipa->reg_virt + offset);
 }
@@ -573,7 +573,7 @@ static void ipa_route_tuple_zero(struct ipa *ipa, u32 route_id)
        val = ioread32(ipa->reg_virt + offset);
 
        /* Zero all route-related fields, preserving the rest */
-       u32_replace_bits(val, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
+       u32p_replace_bits(&val, 0, IPA_REG_ENDP_ROUTER_HASH_MSK_ALL);
 
        iowrite32(val, ipa->reg_virt + offset);
 }
index 9159846..787ac2c 100644 (file)
@@ -1077,6 +1077,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
        struct macsec_rx_sa *rx_sa;
        struct macsec_rxh_data *rxd;
        struct macsec_dev *macsec;
+       unsigned int len;
        sci_t sci;
        u32 hdr_pn;
        bool cbit;
@@ -1232,9 +1233,10 @@ deliver:
        macsec_rxsc_put(rx_sc);
 
        skb_orphan(skb);
+       len = skb->len;
        ret = gro_cells_receive(&macsec->gro_cells, skb);
        if (ret == NET_RX_SUCCESS)
-               count_rx(dev, skb->len);
+               count_rx(dev, len);
        else
                macsec->secy.netdev->stats.rx_dropped++;
 
index 726e4b2..1c5a10b 100644 (file)
@@ -222,6 +222,7 @@ config MDIO_THUNDER
        depends on 64BIT
        depends on PCI
        select MDIO_CAVIUM
+       select MDIO_DEVRES
        help
          This driver supports the MDIO interfaces found on Cavium
          ThunderX SoCs when the MDIO bus device appears as a PCI
index 735a806..8947d58 100644 (file)
@@ -996,7 +996,7 @@ void phy_stop(struct phy_device *phydev)
 {
        struct net_device *dev = phydev->attached_dev;
 
-       if (!phy_is_started(phydev)) {
+       if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
                WARN(1, "called from state %s\n",
                     phy_state_to_str(phydev->state));
                return;
index 8adfbad..5dab6be 100644 (file)
@@ -1143,10 +1143,6 @@ int phy_init_hw(struct phy_device *phydev)
        if (ret < 0)
                return ret;
 
-       ret = phy_disable_interrupts(phydev);
-       if (ret)
-               return ret;
-
        if (phydev->drv->config_init)
                ret = phydev->drv->config_init(phydev);
 
@@ -1423,6 +1419,10 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
        if (err)
                goto error;
 
+       err = phy_disable_interrupts(phydev);
+       if (err)
+               return err;
+
        phy_resume(phydev);
        phy_led_triggers_register(phydev);
 
@@ -1682,7 +1682,8 @@ void phy_detach(struct phy_device *phydev)
 
        phy_led_triggers_unregister(phydev);
 
-       module_put(phydev->mdio.dev.driver->owner);
+       if (phydev->mdio.dev.driver)
+               module_put(phydev->mdio.dev.driver->owner);
 
        /* If the device had no specific driver before (i.e. - it
         * was using the generic driver), we unbind the device
index 95dbe5e..0f09609 100644 (file)
@@ -1,6 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0+
-/*
- * drivers/net/phy/realtek.c
+/* drivers/net/phy/realtek.c
  *
  * Driver for Realtek PHYs
  *
@@ -32,9 +31,9 @@
 #define RTL8211F_TX_DELAY                      BIT(8)
 #define RTL8211F_RX_DELAY                      BIT(3)
 
-#define RTL8211E_TX_DELAY                      BIT(1)
-#define RTL8211E_RX_DELAY                      BIT(2)
-#define RTL8211E_MODE_MII_GMII                 BIT(3)
+#define RTL8211E_CTRL_DELAY                    BIT(13)
+#define RTL8211E_TX_DELAY                      BIT(12)
+#define RTL8211E_RX_DELAY                      BIT(11)
 
 #define RTL8201F_ISR                           0x1e
 #define RTL8201F_IER                           0x13
@@ -246,16 +245,16 @@ static int rtl8211e_config_init(struct phy_device *phydev)
        /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
        switch (phydev->interface) {
        case PHY_INTERFACE_MODE_RGMII:
-               val = 0;
+               val = RTL8211E_CTRL_DELAY | 0;
                break;
        case PHY_INTERFACE_MODE_RGMII_ID:
-               val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
+               val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
                break;
        case PHY_INTERFACE_MODE_RGMII_RXID:
-               val = RTL8211E_RX_DELAY;
+               val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY;
                break;
        case PHY_INTERFACE_MODE_RGMII_TXID:
-               val = RTL8211E_TX_DELAY;
+               val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY;
                break;
        default: /* the rest of the modes imply leaving delays as is. */
                return 0;
@@ -263,11 +262,12 @@ static int rtl8211e_config_init(struct phy_device *phydev)
 
        /* According to a sample driver there is a 0x1c config register on the
         * 0xa4 extension page (0x7) layout. It can be used to disable/enable
-        * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can
-        * also be used to customize the whole configuration register:
-        * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select,
-        * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
-        * for details).
+        * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins.
+        * The configuration register definition:
+        * 14 = reserved
+        * 13 = Force Tx RX Delay controlled by bit12 bit11,
+        * 12 = RX Delay, 11 = TX Delay
+        * 10:0 = Test && debug settings reserved by realtek
         */
        oldpage = phy_select_page(phydev, 0x7);
        if (oldpage < 0)
@@ -277,7 +277,8 @@ static int rtl8211e_config_init(struct phy_device *phydev)
        if (ret)
                goto err_restore_page;
 
-       ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
+       ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY
+                          | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
                           val);
 
 err_restore_page:
index 8c1e027..bcc4a4c 100644 (file)
@@ -287,7 +287,7 @@ inst_rollback:
        for (i--; i >= 0; i--)
                __team_option_inst_del_option(team, dst_opts[i]);
 
-       i = option_count - 1;
+       i = option_count;
 alloc_rollback:
        for (i--; i >= 0; i--)
                kfree(dst_opts[i]);
@@ -2112,6 +2112,7 @@ static void team_setup_by_port(struct net_device *dev,
        dev->header_ops = port_dev->header_ops;
        dev->type = port_dev->type;
        dev->hard_header_len = port_dev->hard_header_len;
+       dev->needed_headroom = port_dev->needed_headroom;
        dev->addr_len = port_dev->addr_len;
        dev->mtu = port_dev->mtu;
        memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
index a38e868..5541f3f 100644 (file)
@@ -1823,6 +1823,33 @@ static const struct driver_info belkin_info = {
        .status = ax88179_status,
        .link_reset = ax88179_link_reset,
        .reset  = ax88179_reset,
+       .stop   = ax88179_stop,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
+static const struct driver_info toshiba_info = {
+       .description = "Toshiba USB Ethernet Adapter",
+       .bind   = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset  = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
+static const struct driver_info mct_info = {
+       .description = "MCT USB 3.0 Gigabit Ethernet Adapter",
+       .bind   = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset  = ax88179_reset,
+       .stop   = ax88179_stop,
        .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
        .rx_fixup = ax88179_rx_fixup,
        .tx_fixup = ax88179_tx_fixup,
@@ -1861,6 +1888,14 @@ static const struct usb_device_id products[] = {
        /* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */
        USB_DEVICE(0x050d, 0x0128),
        .driver_info = (unsigned long)&belkin_info,
+}, {
+       /* Toshiba USB 3.0 GBit Ethernet Adapter */
+       USB_DEVICE(0x0930, 0x0a13),
+       .driver_info = (unsigned long)&toshiba_info,
+}, {
+       /* Magic Control Technology U3-A9003 USB 3.0 Gigabit Ethernet Adapter */
+       USB_DEVICE(0x0711, 0x0179),
+       .driver_info = (unsigned long)&mct_info,
 },
        { },
 };
index e92cb51..060a8a0 100644 (file)
@@ -360,28 +360,47 @@ fail:
 }
 #endif                         /* PEGASUS_WRITE_EEPROM */
 
-static inline void get_node_id(pegasus_t *pegasus, __u8 *id)
+static inline int get_node_id(pegasus_t *pegasus, u8 *id)
 {
-       int i;
-       __u16 w16;
+       int i, ret;
+       u16 w16;
 
        for (i = 0; i < 3; i++) {
-               read_eprom_word(pegasus, i, &w16);
+               ret = read_eprom_word(pegasus, i, &w16);
+               if (ret < 0)
+                       return ret;
                ((__le16 *) id)[i] = cpu_to_le16(w16);
        }
+
+       return 0;
 }
 
 static void set_ethernet_addr(pegasus_t *pegasus)
 {
-       __u8 node_id[6];
+       int ret;
+       u8 node_id[6];
 
        if (pegasus->features & PEGASUS_II) {
-               get_registers(pegasus, 0x10, sizeof(node_id), node_id);
+               ret = get_registers(pegasus, 0x10, sizeof(node_id), node_id);
+               if (ret < 0)
+                       goto err;
        } else {
-               get_node_id(pegasus, node_id);
-               set_registers(pegasus, EthID, sizeof(node_id), node_id);
+               ret = get_node_id(pegasus, node_id);
+               if (ret < 0)
+                       goto err;
+               ret = set_registers(pegasus, EthID, sizeof(node_id), node_id);
+               if (ret < 0)
+                       goto err;
        }
+
        memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id));
+
+       return;
+err:
+       eth_hw_addr_random(pegasus->net);
+       dev_info(&pegasus->intf->dev, "software assigned MAC address.\n");
+
+       return;
 }
 
 static inline int reset_mac(pegasus_t *pegasus)
index 07c42c0..5ca1356 100644 (file)
@@ -1375,6 +1375,7 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
        {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)},    /* Foxconn T77W968 LTE */
        {QMI_FIXED_INTF(0x0489, 0xe0b5, 0)},    /* Foxconn T77W968 LTE with eSIM support*/
+       {QMI_FIXED_INTF(0x2692, 0x9025, 4)},    /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index bd9c078..6fa7a00 100644 (file)
@@ -201,7 +201,7 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
                        dev_dbg(&info->control->dev,
                                "rndis response error, code %d\n", retval);
                }
-               msleep(20);
+               msleep(40);
        }
        dev_dbg(&info->control->dev, "rndis response timeout\n");
        return -ETIMEDOUT;
index 733f120..9d079dc 100644 (file)
@@ -274,12 +274,20 @@ static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg)
                return 1;
 }
 
-static inline void set_ethernet_addr(rtl8150_t * dev)
+static void set_ethernet_addr(rtl8150_t *dev)
 {
-       u8 node_id[6];
+       u8 node_id[ETH_ALEN];
+       int ret;
+
+       ret = get_registers(dev, IDR, sizeof(node_id), node_id);
 
-       get_registers(dev, IDR, sizeof(node_id), node_id);
-       memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));
+       if (ret == sizeof(node_id)) {
+               ether_addr_copy(dev->netdev->dev_addr, node_id);
+       } else {
+               eth_hw_addr_random(dev->netdev);
+               netdev_notice(dev->netdev, "Assigned a random MAC address: %pM\n",
+                             dev->netdev->dev_addr);
+       }
 }
 
 static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
index 263b005..668685c 100644 (file)
@@ -63,6 +63,11 @@ static const unsigned long guest_offloads[] = {
        VIRTIO_NET_F_GUEST_CSUM
 };
 
+#define GUEST_OFFLOAD_LRO_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+                               (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
+                               (1ULL << VIRTIO_NET_F_GUEST_ECN)  | \
+                               (1ULL << VIRTIO_NET_F_GUEST_UFO))
+
 struct virtnet_stat_desc {
        char desc[ETH_GSTRING_LEN];
        size_t offset;
@@ -2531,7 +2536,8 @@ static int virtnet_set_features(struct net_device *dev,
                if (features & NETIF_F_LRO)
                        offloads = vi->guest_offloads_capable;
                else
-                       offloads = 0;
+                       offloads = vi->guest_offloads_capable &
+                                  ~GUEST_OFFLOAD_LRO_MASK;
 
                err = virtnet_set_guest_offloads(vi, offloads);
                if (err)
index 2818015..336504b 100644 (file)
@@ -1032,7 +1032,6 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        /* Use temporary descriptor to avoid touching bits multiple times */
        union Vmxnet3_GenericDesc tempTxDesc;
 #endif
-       struct udphdr *udph;
 
        count = txd_estimate(skb);
 
@@ -1135,8 +1134,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
                        gdesc->txd.om = VMXNET3_OM_ENCAP;
                        gdesc->txd.msscof = ctx.mss;
 
-                       udph = udp_hdr(skb);
-                       if (udph->check)
+                       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
                                gdesc->txd.oco = 1;
                } else {
                        gdesc->txd.hlen = ctx.l4_offset + ctx.l4_hdr_size;
@@ -3371,6 +3369,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
                .ndo_change_mtu = vmxnet3_change_mtu,
                .ndo_fix_features = vmxnet3_fix_features,
                .ndo_set_features = vmxnet3_set_features,
+               .ndo_features_check = vmxnet3_features_check,
                .ndo_get_stats64 = vmxnet3_get_stats64,
                .ndo_tx_timeout = vmxnet3_tx_timeout,
                .ndo_set_rx_mode = vmxnet3_set_mc,
index 1014693..7ec8652 100644 (file)
@@ -267,6 +267,34 @@ netdev_features_t vmxnet3_fix_features(struct net_device *netdev,
        return features;
 }
 
+netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
+                                        struct net_device *netdev,
+                                        netdev_features_t features)
+{
+       struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+
+       /* Validate if the tunneled packet is being offloaded by the device */
+       if (VMXNET3_VERSION_GE_4(adapter) &&
+           skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL) {
+               u8 l4_proto = 0;
+
+               switch (vlan_get_protocol(skb)) {
+               case htons(ETH_P_IP):
+                       l4_proto = ip_hdr(skb)->protocol;
+                       break;
+               case htons(ETH_P_IPV6):
+                       l4_proto = ipv6_hdr(skb)->nexthdr;
+                       break;
+               default:
+                       return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+               }
+
+               if (l4_proto != IPPROTO_UDP)
+                       return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+       }
+       return features;
+}
+
 static void vmxnet3_enable_encap_offloads(struct net_device *netdev)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
index 5d2b062..d958b92 100644 (file)
@@ -470,6 +470,10 @@ vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter);
 netdev_features_t
 vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features);
 
+netdev_features_t
+vmxnet3_features_check(struct sk_buff *skb,
+                      struct net_device *netdev, netdev_features_t features);
+
 int
 vmxnet3_set_features(struct net_device *netdev, netdev_features_t features);
 
index 4441306..cb5898f 100644 (file)
@@ -118,6 +118,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
        skb_put(skb, sizeof(struct cisco_packet));
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = dev;
+       skb->protocol = htons(ETH_P_HDLC);
        skb_reset_network_header(skb);
 
        dev_queue_xmit(skb);
index 9acad65..d6cfd51 100644 (file)
@@ -433,6 +433,8 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
                        if (pvc->state.fecn) /* TX Congestion counter */
                                dev->stats.tx_compressed++;
                        skb->dev = pvc->frad;
+                       skb->protocol = htons(ETH_P_HDLC);
+                       skb_reset_network_header(skb);
                        dev_queue_xmit(skb);
                        return NETDEV_TX_OK;
                }
@@ -555,6 +557,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
        skb_put(skb, i);
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = dev;
+       skb->protocol = htons(ETH_P_HDLC);
        skb_reset_network_header(skb);
 
        dev_queue_xmit(skb);
@@ -1041,7 +1044,7 @@ static void pvc_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_DLCI;
        dev->flags = IFF_POINTOPOINT;
-       dev->hard_header_len = 10;
+       dev->hard_header_len = 0;
        dev->addr_len = 2;
        netif_keep_dst(dev);
 }
@@ -1093,6 +1096,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
        dev->mtu = HDLC_MAX_MTU;
        dev->min_mtu = 68;
        dev->max_mtu = HDLC_MAX_MTU;
+       dev->needed_headroom = 10;
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->ml_priv = pvc;
 
index 48ced39..64f8556 100644 (file)
@@ -251,6 +251,7 @@ static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code,
 
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = dev;
+       skb->protocol = htons(ETH_P_HDLC);
        skb_reset_network_header(skb);
        skb_queue_tail(&tx_queue, skb);
 }
@@ -383,11 +384,8 @@ static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id,
        }
 
        for (opt = data; len; len -= opt[1], opt += opt[1]) {
-               if (len < 2 || len < opt[1]) {
-                       dev->stats.rx_errors++;
-                       kfree(out);
-                       return; /* bad packet, drop silently */
-               }
+               if (len < 2 || opt[1] < 2 || len < opt[1])
+                       goto err_out;
 
                if (pid == PID_LCP)
                        switch (opt[0]) {
@@ -395,6 +393,8 @@ static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id,
                                continue; /* MRU always OK and > 1500 bytes? */
 
                        case LCP_OPTION_ACCM: /* async control character map */
+                               if (opt[1] < sizeof(valid_accm))
+                                       goto err_out;
                                if (!memcmp(opt, valid_accm,
                                            sizeof(valid_accm)))
                                        continue;
@@ -406,6 +406,8 @@ static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id,
                                }
                                break;
                        case LCP_OPTION_MAGIC:
+                               if (len < 6)
+                                       goto err_out;
                                if (opt[1] != 6 || (!opt[2] && !opt[3] &&
                                                    !opt[4] && !opt[5]))
                                        break; /* reject invalid magic number */
@@ -424,6 +426,11 @@ static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id,
                ppp_cp_event(dev, pid, RCR_GOOD, CP_CONF_ACK, id, req_len, data);
 
        kfree(out);
+       return;
+
+err_out:
+       dev->stats.rx_errors++;
+       kfree(out);
 }
 
 static int ppp_rx(struct sk_buff *skb)
index 732a6c1..b6be245 100644 (file)
@@ -198,8 +198,6 @@ static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
        struct net_device *dev;
        int size = skb->len;
 
-       skb->protocol = htons(ETH_P_X25);
-
        ptr = skb_push(skb, 2);
 
        *ptr++ = size % 256;
@@ -210,6 +208,8 @@ static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
 
        skb->dev = dev = lapbeth->ethdev;
 
+       skb->protocol = htons(ETH_P_DEC);
+
        skb_reset_network_header(skb);
 
        dev_hard_header(skb, dev, ETH_P_DEC, bcast_addr, NULL, 0);
index 7ee9805..c418767 100644 (file)
@@ -464,7 +464,6 @@ static int x25_asy_open(struct net_device *dev)
 {
        struct x25_asy *sl = netdev_priv(dev);
        unsigned long len;
-       int err;
 
        if (sl->tty == NULL)
                return -ENODEV;
@@ -490,14 +489,7 @@ static int x25_asy_open(struct net_device *dev)
        sl->xleft    = 0;
        sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */
 
-       netif_start_queue(dev);
-
-       /*
-        *      Now attach LAPB
-        */
-       err = lapb_register(dev, &x25_asy_callbacks);
-       if (err == LAPB_OK)
-               return 0;
+       return 0;
 
        /* Cleanup */
        kfree(sl->xbuff);
@@ -519,7 +511,6 @@ static int x25_asy_close(struct net_device *dev)
        if (sl->tty)
                clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
 
-       netif_stop_queue(dev);
        sl->rcount = 0;
        sl->xleft  = 0;
        spin_unlock(&sl->lock);
@@ -604,7 +595,6 @@ static int x25_asy_open_tty(struct tty_struct *tty)
 static void x25_asy_close_tty(struct tty_struct *tty)
 {
        struct x25_asy *sl = tty->disc_data;
-       int err;
 
        /* First make sure we're connected. */
        if (!sl || sl->magic != X25_ASY_MAGIC)
@@ -615,11 +605,6 @@ static void x25_asy_close_tty(struct tty_struct *tty)
                dev_close(sl->dev);
        rtnl_unlock();
 
-       err = lapb_unregister(sl->dev);
-       if (err != LAPB_OK)
-               pr_err("%s: lapb_unregister error: %d\n",
-                      __func__, err);
-
        tty->disc_data = NULL;
        sl->tty = NULL;
        x25_asy_free(sl);
@@ -722,15 +707,39 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
 
 static int x25_asy_open_dev(struct net_device *dev)
 {
+       int err;
        struct x25_asy *sl = netdev_priv(dev);
        if (sl->tty == NULL)
                return -ENODEV;
+
+       err = lapb_register(dev, &x25_asy_callbacks);
+       if (err != LAPB_OK)
+               return -ENOMEM;
+
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+static int x25_asy_close_dev(struct net_device *dev)
+{
+       int err;
+
+       netif_stop_queue(dev);
+
+       err = lapb_unregister(dev);
+       if (err != LAPB_OK)
+               pr_err("%s: lapb_unregister error: %d\n",
+                      __func__, err);
+
+       x25_asy_close(dev);
+
        return 0;
 }
 
 static const struct net_device_ops x25_asy_netdev_ops = {
        .ndo_open       = x25_asy_open_dev,
-       .ndo_stop       = x25_asy_close,
+       .ndo_stop       = x25_asy_close_dev,
        .ndo_start_xmit = x25_asy_xmit,
        .ndo_tx_timeout = x25_asy_timeout,
        .ndo_change_mtu = x25_asy_change_mtu,
index 3dd3b76..c0cfd9b 100644 (file)
@@ -87,15 +87,12 @@ static void handshake_zero(struct noise_handshake *handshake)
 
 void wg_noise_handshake_clear(struct noise_handshake *handshake)
 {
+       down_write(&handshake->lock);
        wg_index_hashtable_remove(
                        handshake->entry.peer->device->index_hashtable,
                        &handshake->entry);
-       down_write(&handshake->lock);
        handshake_zero(handshake);
        up_write(&handshake->lock);
-       wg_index_hashtable_remove(
-                       handshake->entry.peer->device->index_hashtable,
-                       &handshake->entry);
 }
 
 static struct noise_keypair *keypair_create(struct wg_peer *peer)
index e4deb33..f2783aa 100644 (file)
@@ -167,9 +167,13 @@ bool wg_index_hashtable_replace(struct index_hashtable *table,
                                struct index_hashtable_entry *old,
                                struct index_hashtable_entry *new)
 {
-       if (unlikely(hlist_unhashed(&old->index_hash)))
-               return false;
+       bool ret;
+
        spin_lock_bh(&table->lock);
+       ret = !hlist_unhashed(&old->index_hash);
+       if (unlikely(!ret))
+               goto out;
+
        new->index = old->index;
        hlist_replace_rcu(&old->index_hash, &new->index_hash);
 
@@ -180,8 +184,9 @@ bool wg_index_hashtable_replace(struct index_hashtable *table,
         * simply gets dropped, which isn't terrible.
         */
        INIT_HLIST_NODE(&old->index_hash);
+out:
        spin_unlock_bh(&table->lock);
-       return true;
+       return ret;
 }
 
 void wg_index_hashtable_remove(struct index_hashtable *table,
index e8712ad..3c07d1b 100644 (file)
@@ -664,9 +664,15 @@ static void pkt_align(struct sk_buff *p, int len, int align)
 /* To check if there's window offered */
 static bool data_ok(struct brcmf_sdio *bus)
 {
-       /* Reserve TXCTL_CREDITS credits for txctl */
-       return (bus->tx_max - bus->tx_seq) > TXCTL_CREDITS &&
-              ((bus->tx_max - bus->tx_seq) & 0x80) == 0;
+       u8 tx_rsv = 0;
+
+       /* Reserve TXCTL_CREDITS credits for txctl when it is ready to send */
+       if (bus->ctrl_frame_stat)
+               tx_rsv = TXCTL_CREDITS;
+
+       return (bus->tx_max - bus->tx_seq - tx_rsv) != 0 &&
+              ((bus->tx_max - bus->tx_seq - tx_rsv) & 0x80) == 0;
+
 }
 
 /* To check if there's window offered */
index 8047e30..d9f8bdb 100644 (file)
@@ -954,7 +954,7 @@ struct mwifiex_tkip_param {
 struct mwifiex_aes_param {
        u8 pn[WPA_PN_SIZE];
        __le16 key_len;
-       u8 key[WLAN_KEY_LEN_CCMP];
+       u8 key[WLAN_KEY_LEN_CCMP_256];
 } __packed;
 
 struct mwifiex_wapi_param {
index 962d8bf..119ccac 100644 (file)
@@ -619,7 +619,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
        key_v2 = &resp->params.key_material_v2;
 
        len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len);
-       if (len > WLAN_KEY_LEN_CCMP)
+       if (len > sizeof(key_v2->key_param_set.key_params.aes.key))
                return -EINVAL;
 
        if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
@@ -635,7 +635,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
                return 0;
 
        memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
-              WLAN_KEY_LEN_CCMP);
+              sizeof(key_v2->key_param_set.key_params.aes.key));
        priv->aes_key_v2.key_param_set.key_params.aes.key_len =
                                cpu_to_le16(len);
        memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
index fc1ebab..1f57b43 100644 (file)
@@ -460,7 +460,7 @@ void mt7615_init_device(struct mt7615_dev *dev)
        dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
        dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
        dev->mphy.sband_5g.sband.vht_cap.cap |=
-                       IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+                       IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
        mt7615_cap_dbdc_disable(dev);
        dev->phy.dfs_state = -1;
index d0cbb28..bd316db 100644 (file)
@@ -2128,7 +2128,8 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name)
                 sizeof(dev->mt76.hw->wiphy->fw_version),
                 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
 
-       if (!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) {
+       if (!is_mt7615(&dev->mt76) &&
+           !strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) {
                dev->fw_ver = MT7615_FIRMWARE_V2;
                dev->mcu_ops = &sta_update_ops;
        } else {
index e90d008..8d6ceb3 100644 (file)
@@ -699,8 +699,12 @@ void mt7915_unregister_device(struct mt7915_dev *dev)
        spin_lock_bh(&dev->token_lock);
        idr_for_each_entry(&dev->token, txwi, id) {
                mt7915_txp_skb_unmap(&dev->mt76, txwi);
-               if (txwi->skb)
-                       dev_kfree_skb_any(txwi->skb);
+               if (txwi->skb) {
+                       struct ieee80211_hw *hw;
+
+                       hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
+                       ieee80211_free_txskb(hw, txwi->skb);
+               }
                mt76_put_txwi(&dev->mt76, txwi);
        }
        spin_unlock_bh(&dev->token_lock);
index 6825afc..036207f 100644 (file)
@@ -841,7 +841,7 @@ mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,
        if (sta || !(info->flags & IEEE80211_TX_CTL_NO_ACK))
                mt7915_tx_status(sta, hw, info, NULL);
 
-       dev_kfree_skb(skb);
+       ieee80211_free_txskb(hw, skb);
 }
 
 void mt7915_txp_skb_unmap(struct mt76_dev *dev,
index 6aafff9..e013ebe 100644 (file)
@@ -671,9 +671,10 @@ bool qtnf_netdev_is_qtn(const struct net_device *ndev)
        return ndev->netdev_ops == &qtnf_netdev_ops;
 }
 
-static int qtnf_check_br_ports(struct net_device *dev, void *data)
+static int qtnf_check_br_ports(struct net_device *dev,
+                              struct netdev_nested_priv *priv)
 {
-       struct net_device *ndev = data;
+       struct net_device *ndev = (struct net_device *)priv->data;
 
        if (dev != ndev && netdev_port_same_parent_id(dev, ndev))
                return -ENOTSUPP;
@@ -686,6 +687,9 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb,
 {
        struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
        const struct netdev_notifier_changeupper_info *info;
+       struct netdev_nested_priv priv = {
+               .data = (void *)ndev,
+       };
        struct net_device *brdev;
        struct qtnf_vif *vif;
        struct qtnf_bus *bus;
@@ -725,7 +729,7 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb,
                } else {
                        ret = netdev_walk_all_lower_dev(brdev,
                                                        qtnf_check_br_ports,
-                                                       ndev);
+                                                       &priv);
                }
 
                break;
index 9acd8a4..f2609d5 100644 (file)
@@ -458,7 +458,6 @@ enum wl1271_cmd_key_type {
        KEY_TKIP = 2,
        KEY_AES  = 3,
        KEY_GEM  = 4,
-       KEY_IGTK  = 5,
 };
 
 struct wl1271_cmd_set_keys {
index 821ad1a..d2bbd51 100644 (file)
@@ -3559,9 +3559,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
        case WL1271_CIPHER_SUITE_GEM:
                key_type = KEY_GEM;
                break;
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-               key_type = KEY_IGTK;
-               break;
        default:
                wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
 
@@ -6231,7 +6228,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
                WLAN_CIPHER_SUITE_TKIP,
                WLAN_CIPHER_SUITE_CCMP,
                WL1271_CIPHER_SUITE_GEM,
-               WLAN_CIPHER_SUITE_AES_CMAC,
        };
 
        /* The tx descriptor buffer */
index 3ed9786..a44d49d 100644 (file)
@@ -73,6 +73,7 @@ config NVME_TCP
        depends on INET
        depends on BLK_DEV_NVME
        select NVME_FABRICS
+       select CRYPTO
        select CRYPTO_CRC32C
        help
          This provides support for the NVMe over Fabrics protocol using
index d543bc1..893e296 100644 (file)
@@ -3041,7 +3041,7 @@ static int nvme_get_effects_log(struct nvme_ctrl *ctrl, u8 csi,
        if (!cel)
                return -ENOMEM;
 
-       ret = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, 0, csi,
+       ret = nvme_get_log(ctrl, 0x00, NVME_LOG_CMD_EFFECTS, 0, csi,
                        &cel->log, sizeof(cel->log), 0);
        if (ret) {
                kfree(cel);
@@ -3236,8 +3236,11 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
        if (ret < 0)
                return ret;
 
-       if (!ctrl->identified)
-               nvme_hwmon_init(ctrl);
+       if (!ctrl->identified) {
+               ret = nvme_hwmon_init(ctrl);
+               if (ret < 0)
+                       return ret;
+       }
 
        ctrl->identified = true;
 
@@ -3261,10 +3264,26 @@ static int nvme_dev_open(struct inode *inode, struct file *file)
                return -EWOULDBLOCK;
        }
 
+       nvme_get_ctrl(ctrl);
+       if (!try_module_get(ctrl->ops->module)) {
+               nvme_put_ctrl(ctrl);
+               return -EINVAL;
+       }
+
        file->private_data = ctrl;
        return 0;
 }
 
+static int nvme_dev_release(struct inode *inode, struct file *file)
+{
+       struct nvme_ctrl *ctrl =
+               container_of(inode->i_cdev, struct nvme_ctrl, cdev);
+
+       module_put(ctrl->ops->module);
+       nvme_put_ctrl(ctrl);
+       return 0;
+}
+
 static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp)
 {
        struct nvme_ns *ns;
@@ -3327,6 +3346,7 @@ static long nvme_dev_ioctl(struct file *file, unsigned int cmd,
 static const struct file_operations nvme_dev_fops = {
        .owner          = THIS_MODULE,
        .open           = nvme_dev_open,
+       .release        = nvme_dev_release,
        .unlocked_ioctl = nvme_dev_ioctl,
        .compat_ioctl   = compat_ptr_ioctl,
 };
@@ -3525,10 +3545,6 @@ static ssize_t nvme_sysfs_delete(struct device *dev,
 {
        struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
 
-       /* Can't delete non-created controllers */
-       if (!ctrl->created)
-               return -EBUSY;
-
        if (device_remove_file_self(dev, attr))
                nvme_delete_ctrl_sync(ctrl);
        return count;
@@ -4403,7 +4419,6 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
                nvme_queue_scan(ctrl);
                nvme_start_queues(ctrl);
        }
-       ctrl->created = true;
 }
 EXPORT_SYMBOL_GPL(nvme_start_ctrl);
 
index 32f61fc..8575724 100644 (file)
@@ -565,10 +565,14 @@ bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
        struct nvme_request *req = nvme_req(rq);
 
        /*
-        * If we are in some state of setup or teardown only allow
-        * internally generated commands.
+        * currently we have a problem sending passthru commands
+        * on the admin_q if the controller is not LIVE because we can't
+        * make sure that they are going out after the admin connect,
+        * controller enable and/or other commands in the initialization
+        * sequence. until the controller will be LIVE, fail with
+        * BLK_STS_RESOURCE so that they will be rescheduled.
         */
-       if (!blk_rq_is_passthrough(rq) || (req->flags & NVME_REQ_USERCMD))
+       if (rq->q == ctrl->admin_q && (req->flags & NVME_REQ_USERCMD))
                return false;
 
        /*
@@ -577,7 +581,7 @@ bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
         */
        switch (ctrl->state) {
        case NVME_CTRL_CONNECTING:
-               if (nvme_is_fabrics(req->cmd) &&
+               if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) &&
                    req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
                        return true;
                break;
index a7f474d..e2e09e2 100644 (file)
@@ -2160,6 +2160,7 @@ nvme_fc_term_aen_ops(struct nvme_fc_ctrl *ctrl)
        struct nvme_fc_fcp_op *aen_op;
        int i;
 
+       cancel_work_sync(&ctrl->ctrl.async_event_work);
        aen_op = ctrl->aen_ops;
        for (i = 0; i < NVME_NR_AEN_COMMANDS; i++, aen_op++) {
                __nvme_fc_exit_request(ctrl, aen_op);
@@ -3670,12 +3671,14 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
        spin_lock_irqsave(&nvme_fc_lock, flags);
        list_for_each_entry(lport, &nvme_fc_lport_list, port_list) {
                if (lport->localport.node_name != laddr.nn ||
-                   lport->localport.port_name != laddr.pn)
+                   lport->localport.port_name != laddr.pn ||
+                   lport->localport.port_state != FC_OBJSTATE_ONLINE)
                        continue;
 
                list_for_each_entry(rport, &lport->endp_list, endp_list) {
                        if (rport->remoteport.node_name != raddr.nn ||
-                           rport->remoteport.port_name != raddr.pn)
+                           rport->remoteport.port_name != raddr.pn ||
+                           rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
                                continue;
 
                        /* if fail to get reference fall through. Will error */
index 412a6c9..552dbc0 100644 (file)
@@ -59,12 +59,8 @@ static int nvme_set_temp_thresh(struct nvme_ctrl *ctrl, int sensor, bool under,
 
 static int nvme_hwmon_get_smart_log(struct nvme_hwmon_data *data)
 {
-       int ret;
-
-       ret = nvme_get_log(data->ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0,
+       return nvme_get_log(data->ctrl, NVME_NSID_ALL, NVME_LOG_SMART, 0,
                           NVME_CSI_NVM, &data->log, sizeof(data->log), 0);
-
-       return ret <= 0 ? ret : -EIO;
 }
 
 static int nvme_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
@@ -225,7 +221,7 @@ static const struct hwmon_chip_info nvme_hwmon_chip_info = {
        .info   = nvme_hwmon_info,
 };
 
-void nvme_hwmon_init(struct nvme_ctrl *ctrl)
+int nvme_hwmon_init(struct nvme_ctrl *ctrl)
 {
        struct device *dev = ctrl->dev;
        struct nvme_hwmon_data *data;
@@ -234,7 +230,7 @@ void nvme_hwmon_init(struct nvme_ctrl *ctrl)
 
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
-               return;
+               return 0;
 
        data->ctrl = ctrl;
        mutex_init(&data->read_lock);
@@ -244,7 +240,7 @@ void nvme_hwmon_init(struct nvme_ctrl *ctrl)
                dev_warn(ctrl->device,
                        "Failed to read smart log (error %d)\n", err);
                devm_kfree(dev, data);
-               return;
+               return err;
        }
 
        hwmon = devm_hwmon_device_register_with_info(dev, "nvme", data,
@@ -254,4 +250,6 @@ void nvme_hwmon_init(struct nvme_ctrl *ctrl)
                dev_warn(dev, "Failed to instantiate hwmon device\n");
                devm_kfree(dev, data);
        }
+
+       return 0;
 }
index 2910f6c..2aaedfa 100644 (file)
@@ -307,7 +307,6 @@ struct nvme_ctrl {
        struct nvme_command ka_cmd;
        struct work_struct fw_act_work;
        unsigned long events;
-       bool created;
 
 #ifdef CONFIG_NVME_MULTIPATH
        /* asymmetric namespace access: */
@@ -828,9 +827,12 @@ static inline struct nvme_ns *nvme_get_ns_from_dev(struct device *dev)
 }
 
 #ifdef CONFIG_NVME_HWMON
-void nvme_hwmon_init(struct nvme_ctrl *ctrl);
+int nvme_hwmon_init(struct nvme_ctrl *ctrl);
 #else
-static inline void nvme_hwmon_init(struct nvme_ctrl *ctrl) { }
+static inline int nvme_hwmon_init(struct nvme_ctrl *ctrl)
+{
+       return 0;
+}
 #endif
 
 u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
index 899d2f4..8984796 100644 (file)
@@ -940,13 +940,6 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
        struct nvme_completion *cqe = &nvmeq->cqes[idx];
        struct request *req;
 
-       if (unlikely(cqe->command_id >= nvmeq->q_depth)) {
-               dev_warn(nvmeq->dev->ctrl.device,
-                       "invalid id %d completed on queue %d\n",
-                       cqe->command_id, le16_to_cpu(cqe->sq_id));
-               return;
-       }
-
        /*
         * AEN requests are special as they don't time out and can
         * survive any kind of queue freeze and often don't respond to
@@ -960,6 +953,13 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
        }
 
        req = blk_mq_tag_to_rq(nvme_queue_tagset(nvmeq), cqe->command_id);
+       if (unlikely(!req)) {
+               dev_warn(nvmeq->dev->ctrl.device,
+                       "invalid id %d completed on queue %d\n",
+                       cqe->command_id, le16_to_cpu(cqe->sq_id));
+               return;
+       }
+
        trace_nvme_sq(req, cqe->sq_head, nvmeq->sq_tail);
        if (!nvme_try_complete_req(req, cqe->status, cqe->result))
                nvme_pci_complete_rq(req);
@@ -3153,7 +3153,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_MEDIUM_PRIO_SQ |
-                               NVME_QUIRK_NO_TEMP_THRESH_CHANGE },
+                               NVME_QUIRK_NO_TEMP_THRESH_CHANGE |
+                               NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_VDEVICE(INTEL, 0xf1a6),   /* Intel 760p/Pro 7600p */
                .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
index 8e5ffe2..9e378d0 100644 (file)
@@ -835,6 +835,7 @@ static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
                blk_mq_free_tag_set(ctrl->ctrl.admin_tagset);
        }
        if (ctrl->async_event_sqe.data) {
+               cancel_work_sync(&ctrl->ctrl.async_event_work);
                nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
                                sizeof(struct nvme_command), DMA_TO_DEVICE);
                ctrl->async_event_sqe.data = NULL;
index 16851ae..d6a3e14 100644 (file)
@@ -913,12 +913,11 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
                else
                        flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
 
-               /* can't zcopy slab pages */
-               if (unlikely(PageSlab(page))) {
-                       ret = sock_no_sendpage(queue->sock, page, offset, len,
+               if (sendpage_ok(page)) {
+                       ret = kernel_sendpage(queue->sock, page, offset, len,
                                        flags);
                } else {
-                       ret = kernel_sendpage(queue->sock, page, offset, len,
+                       ret = sock_no_sendpage(queue->sock, page, offset, len,
                                        flags);
                }
                if (ret <= 0)
@@ -1596,6 +1595,7 @@ static struct blk_mq_tag_set *nvme_tcp_alloc_tagset(struct nvme_ctrl *nctrl,
 static void nvme_tcp_free_admin_queue(struct nvme_ctrl *ctrl)
 {
        if (to_tcp_ctrl(ctrl)->async_req.pdu) {
+               cancel_work_sync(&ctrl->async_event_work);
                nvme_tcp_free_async_req(to_tcp_ctrl(ctrl));
                to_tcp_ctrl(ctrl)->async_req.pdu = NULL;
        }
index 8bd7f65..dacfa74 100644 (file)
@@ -517,6 +517,7 @@ int nvmet_passthru_ctrl_enable(struct nvmet_subsys *subsys)
                subsys->ver = NVME_VS(1, 2, 1);
        }
 
+       __module_get(subsys->passthru_ctrl->ops->module);
        mutex_unlock(&subsys->lock);
        return 0;
 
@@ -531,6 +532,7 @@ static void __nvmet_passthru_ctrl_disable(struct nvmet_subsys *subsys)
 {
        if (subsys->passthru_ctrl) {
                xa_erase(&passthru_subsystems, subsys->passthru_ctrl->cntlid);
+               module_put(subsys->passthru_ctrl->ops->module);
                nvme_put_ctrl(subsys->passthru_ctrl);
        }
        subsys->passthru_ctrl = NULL;
index 0bb2fb3..9705059 100644 (file)
@@ -71,16 +71,13 @@ static void rockchip_pcie_update_txcredit_mui(struct rockchip_pcie *rockchip)
 static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip,
                                      struct pci_bus *bus, int dev)
 {
-       /* access only one slot on each root port */
-       if (pci_is_root_bus(bus) && dev > 0)
-               return 0;
-
        /*
-        * do not read more than one device on the bus directly attached
+        * Access only one slot on each root port.
+        * Do not read more than one device on the bus directly attached
         * to RC's downstream side.
         */
-       if (pci_is_root_bus(bus->parent) && dev > 0)
-               return 0;
+       if (pci_is_root_bus(bus) || pci_is_root_bus(bus->parent))
+               return dev == 0;
 
        return 1;
 }
index 71f257b..9061ece 100644 (file)
@@ -505,9 +505,9 @@ static int qcom_ipq806x_usb_phy_probe(struct platform_device *pdev)
        size = resource_size(res);
        phy_dwc3->base = devm_ioremap(phy_dwc3->dev, res->start, size);
 
-       if (IS_ERR(phy_dwc3->base)) {
+       if (!phy_dwc3->base) {
                dev_err(phy_dwc3->dev, "failed to map reg\n");
-               return PTR_ERR(phy_dwc3->base);
+               return -ENOMEM;
        }
 
        phy_dwc3->ref_clk = devm_clk_get(phy_dwc3->dev, "ref");
@@ -557,7 +557,6 @@ static struct platform_driver qcom_ipq806x_usb_phy_driver = {
        .probe          = qcom_ipq806x_usb_phy_probe,
        .driver         = {
                .name   = "qcom-ipq806x-usb-phy",
-               .owner  = THIS_MODULE,
                .of_match_table = qcom_ipq806x_usb_phy_table,
        },
 };
index 562053c..6e6f992 100644 (file)
@@ -604,8 +604,8 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf),
        QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1),
        QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0x1f),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f),
        QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6),
        QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf),
        QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0),
@@ -631,7 +631,6 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0),
        QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
        QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1),
-       QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0xa),
        QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1),
        QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
        QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1),
@@ -640,7 +639,6 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
        QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
        QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
-       QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x7),
 };
 
 static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = {
@@ -648,6 +646,8 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6),
        QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2),
        QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
+       QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36),
+       QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a),
 };
 
 static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = {
@@ -658,7 +658,6 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = {
        QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
        QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
        QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4),
-       QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x4),
 };
 
 static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = {
@@ -2046,6 +2045,9 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
        .pwrdn_ctrl             = SW_PWRDN,
 };
 
+static const char * const ipq8074_pciephy_clk_l[] = {
+       "aux", "cfg_ahb",
+};
 /* list of resets */
 static const char * const ipq8074_pciephy_reset_l[] = {
        "phy", "common",
@@ -2063,8 +2065,8 @@ static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
        .rx_tbl_num             = ARRAY_SIZE(ipq8074_pcie_rx_tbl),
        .pcs_tbl                = ipq8074_pcie_pcs_tbl,
        .pcs_tbl_num            = ARRAY_SIZE(ipq8074_pcie_pcs_tbl),
-       .clk_list               = NULL,
-       .num_clks               = 0,
+       .clk_list               = ipq8074_pciephy_clk_l,
+       .num_clks               = ARRAY_SIZE(ipq8074_pciephy_clk_l),
        .reset_list             = ipq8074_pciephy_reset_l,
        .num_resets             = ARRAY_SIZE(ipq8074_pciephy_reset_l),
        .vreg_list              = NULL,
index 4277f59..904b80a 100644 (file)
@@ -77,6 +77,8 @@
 #define QSERDES_COM_CORECLK_DIV_MODE1                  0x1bc
 
 /* Only for QMP V2 PHY - TX registers */
+#define QSERDES_TX_EMP_POST1_LVL                       0x018
+#define QSERDES_TX_SLEW_CNTL                           0x040
 #define QSERDES_TX_RES_CODE_LANE_OFFSET                        0x054
 #define QSERDES_TX_DEBUG_BUS_SEL                       0x064
 #define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    0x068
index a174b3c..819c49a 100644 (file)
@@ -725,8 +725,10 @@ static int serdes_am654_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
 
        phy = devm_phy_create(dev, NULL, &ops);
-       if (IS_ERR(phy))
-               return PTR_ERR(phy);
+       if (IS_ERR(phy)) {
+               ret = PTR_ERR(phy);
+               goto clk_err;
+       }
 
        phy_set_drvdata(phy, am654_phy);
        phy_provider = devm_of_phy_provider_register(dev, serdes_am654_xlate);
index cb2dd32..507f79d 100644 (file)
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/of_platform.h>
+#include <linux/sys_soc.h>
 
 #define USB2PHY_ANA_CONFIG1            0x4c
 #define USB2PHY_DISCON_BYP_LATCH       BIT(31)
 
+#define USB2PHY_CHRG_DET                       0x14
+#define USB2PHY_CHRG_DET_USE_CHG_DET_REG       BIT(29)
+#define USB2PHY_CHRG_DET_DIS_CHG_DET           BIT(28)
+
 /* SoC Specific USB2_OTG register definitions */
 #define AM654_USB2_OTG_PD              BIT(8)
 #define AM654_USB2_VBUS_DET_EN         BIT(5)
@@ -43,6 +48,7 @@
 #define OMAP_USB2_HAS_START_SRP                        BIT(0)
 #define OMAP_USB2_HAS_SET_VBUS                 BIT(1)
 #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT   BIT(2)
+#define OMAP_USB2_DISABLE_CHRG_DET             BIT(3)
 
 struct omap_usb {
        struct usb_phy          phy;
@@ -236,6 +242,13 @@ static int omap_usb_init(struct phy *x)
                omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val);
        }
 
+       if (phy->flags & OMAP_USB2_DISABLE_CHRG_DET) {
+               val = omap_usb_readl(phy->phy_base, USB2PHY_CHRG_DET);
+               val |= USB2PHY_CHRG_DET_USE_CHG_DET_REG |
+                      USB2PHY_CHRG_DET_DIS_CHG_DET;
+               omap_usb_writel(phy->phy_base, USB2PHY_CHRG_DET, val);
+       }
+
        return 0;
 }
 
@@ -329,6 +342,26 @@ static const struct of_device_id omap_usb2_id_table[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
 
+static void omap_usb2_init_errata(struct omap_usb *phy)
+{
+       static const struct soc_device_attribute am65x_sr10_soc_devices[] = {
+               { .family = "AM65X", .revision = "SR1.0" },
+               { /* sentinel */ }
+       };
+
+       /*
+        * Errata i2075: USB2PHY: USB2PHY Charger Detect is Enabled by
+        * Default Without VBUS Presence.
+        *
+        * AM654x SR1.0 has a silicon bug due to which D+ is pulled high after
+        * POR, which could cause enumeration failure with some USB hubs.
+        * Disabling the USB2_PHY Charger Detect function will put D+
+        * into the normal state.
+        */
+       if (soc_device_match(am65x_sr10_soc_devices))
+               phy->flags |= OMAP_USB2_DISABLE_CHRG_DET;
+}
+
 static int omap_usb2_probe(struct platform_device *pdev)
 {
        struct omap_usb *phy;
@@ -366,14 +399,14 @@ static int omap_usb2_probe(struct platform_device *pdev)
        phy->mask               = phy_data->mask;
        phy->power_on           = phy_data->power_on;
        phy->power_off          = phy_data->power_off;
+       phy->flags              = phy_data->flags;
 
-       if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(phy->phy_base))
-                       return PTR_ERR(phy->phy_base);
-               phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
-       }
+       omap_usb2_init_errata(phy);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(phy->phy_base))
+               return PTR_ERR(phy->phy_base);
 
        phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
                                                        "syscon-phy-power");
index 9ef2461..0652109 100644 (file)
@@ -58,6 +58,7 @@
 #define CHV_PADCTRL1_CFGLOCK           BIT(31)
 #define CHV_PADCTRL1_INVRXTX_SHIFT     4
 #define CHV_PADCTRL1_INVRXTX_MASK      GENMASK(7, 4)
+#define CHV_PADCTRL1_INVRXTX_TXDATA    BIT(7)
 #define CHV_PADCTRL1_INVRXTX_RXDATA    BIT(6)
 #define CHV_PADCTRL1_INVRXTX_TXENABLE  BIT(5)
 #define CHV_PADCTRL1_ODEN              BIT(3)
@@ -792,11 +793,22 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev,
 static void chv_gpio_clear_triggering(struct chv_pinctrl *pctrl,
                                      unsigned int offset)
 {
+       u32 invrxtx_mask = CHV_PADCTRL1_INVRXTX_MASK;
        u32 value;
 
+       /*
+        * One some devices the GPIO should output the inverted value from what
+        * device-drivers / ACPI code expects (inverted external buffer?). The
+        * BIOS makes this work by setting the CHV_PADCTRL1_INVRXTX_TXDATA flag,
+        * preserve this flag if the pin is already setup as GPIO.
+        */
+       value = chv_readl(pctrl, offset, CHV_PADCTRL0);
+       if (value & CHV_PADCTRL0_GPIOEN)
+               invrxtx_mask &= ~CHV_PADCTRL1_INVRXTX_TXDATA;
+
        value = chv_readl(pctrl, offset, CHV_PADCTRL1);
        value &= ~CHV_PADCTRL1_INTWAKECFG_MASK;
-       value &= ~CHV_PADCTRL1_INVRXTX_MASK;
+       value &= ~invrxtx_mask;
        chv_writel(pctrl, offset, CHV_PADCTRL1, value);
 }
 
index 2f3dfb5..35bbe59 100644 (file)
@@ -259,6 +259,10 @@ bool mtk_is_virt_gpio(struct mtk_pinctrl *hw, unsigned int gpio_n)
 
        desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
 
+       /* if the GPIO is not supported for eint mode */
+       if (desc->eint.eint_m == NO_EINT_SUPPORT)
+               return virt_gpio;
+
        if (desc->funcs && !desc->funcs[desc->eint.eint_m].name)
                virt_gpio = true;
 
index a767a05..48e2a6c 100644 (file)
@@ -414,7 +414,7 @@ static struct mvebu_mpp_mode mv98dx3236_mpp_modes[] = {
                 MPP_VAR_FUNCTION(0x1, "i2c0", "sck",        V_98DX3236_PLUS)),
        MPP_MODE(15,
                 MPP_VAR_FUNCTION(0x0, "gpio", NULL,         V_98DX3236_PLUS),
-                MPP_VAR_FUNCTION(0x4, "i2c0", "sda",        V_98DX3236_PLUS)),
+                MPP_VAR_FUNCTION(0x1, "i2c0", "sda",        V_98DX3236_PLUS)),
        MPP_MODE(16,
                 MPP_VAR_FUNCTION(0x0, "gpo", NULL,          V_98DX3236_PLUS),
                 MPP_VAR_FUNCTION(0x4, "dev", "oe",          V_98DX3236_PLUS)),
index a660f12..826df0d 100644 (file)
@@ -1308,7 +1308,7 @@ static const struct msm_pingroup sm8250_groups[] = {
        [178] = PINGROUP(178, WEST, _, _, _, _, _, _, _, _, _),
        [179] = PINGROUP(179, WEST, _, _, _, _, _, _, _, _, _),
        [180] = UFS_RESET(ufs_reset, 0xb8000),
-       [181] = SDC_PINGROUP(sdc2_clk, 0x7000, 14, 6),
+       [181] = SDC_PINGROUP(sdc2_clk, 0xb7000, 14, 6),
        [182] = SDC_PINGROUP(sdc2_cmd, 0xb7000, 11, 3),
        [183] = SDC_PINGROUP(sdc2_data, 0xb7000, 9, 0),
 };
index 190e4a6..f64b828 100644 (file)
@@ -439,7 +439,9 @@ static int olpc_ec_probe(struct platform_device *pdev)
                                                                &config);
        if (IS_ERR(ec->dcon_rdev)) {
                dev_err(&pdev->dev, "failed to register DCON regulator\n");
-               return PTR_ERR(ec->dcon_rdev);
+               err = PTR_ERR(ec->dcon_rdev);
+               kfree(ec);
+               return err;
        }
 
        ec->dbgfs_dir = olpc_ec_setup_debugfs();
index 40219bb..0d91d13 100644 (file)
@@ -469,6 +469,7 @@ config FUJITSU_LAPTOP
        depends on BACKLIGHT_CLASS_DEVICE
        depends on ACPI_VIDEO || ACPI_VIDEO = n
        select INPUT_SPARSEKMAP
+       select NEW_LEDS
        select LEDS_CLASS
        help
          This is a driver for laptops built by Fujitsu:
@@ -1112,6 +1113,7 @@ config LG_LAPTOP
        depends on ACPI_WMI
        depends on INPUT
        select INPUT_SPARSEKMAP
+       select NEW_LEDS
        select LEDS_CLASS
        help
         This driver adds support for hotkeys as well as control of keyboard
index b2e3d1e..1d9fbab 100644 (file)
@@ -115,6 +115,10 @@ static struct quirk_entry quirk_asus_vendor_backlight = {
        .wmi_backlight_set_devstate = true,
 };
 
+static struct quirk_entry quirk_asus_use_kbd_dock_devid = {
+       .use_kbd_dock_devid = true,
+};
+
 static int dmi_matched(const struct dmi_system_id *dmi)
 {
        pr_info("Identified laptop model '%s'\n", dmi->ident);
@@ -488,6 +492,34 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_vendor_backlight,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Asus Transformer T100TA / T100HA / T100CHI",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       /* Match *T100* */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T100"),
+               },
+               .driver_data = &quirk_asus_use_kbd_dock_devid,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Asus Transformer T101HA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T101HA"),
+               },
+               .driver_data = &quirk_asus_use_kbd_dock_devid,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Asus Transformer T200TA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"),
+               },
+               .driver_data = &quirk_asus_use_kbd_dock_devid,
+       },
        {},
 };
 
@@ -593,33 +625,9 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
        .detect_quirks = asus_nb_wmi_quirks,
 };
 
-static const struct dmi_system_id asus_nb_wmi_blacklist[] __initconst = {
-       {
-               /*
-                * asus-nb-wm adds no functionality. The T100TA has a detachable
-                * USB kbd, so no hotkeys and it has no WMI rfkill; and loading
-                * asus-nb-wm causes the camera LED to turn and _stay_ on.
-                */
-               .matches = {
-                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
-               },
-       },
-       {
-               /* The Asus T200TA has the same issue as the T100TA */
-               .matches = {
-                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"),
-               },
-       },
-       {} /* Terminating entry */
-};
 
 static int __init asus_nb_wmi_init(void)
 {
-       if (dmi_check_system(asus_nb_wmi_blacklist))
-               return -ENODEV;
-
        return asus_wmi_register_driver(&asus_nb_wmi_driver);
 }
 
index 8f4acdc..39e1a63 100644 (file)
@@ -365,12 +365,14 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
        if (err)
                goto err_free_dev;
 
-       result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK);
-       if (result >= 0) {
-               input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-               input_report_switch(asus->inputdev, SW_TABLET_MODE, !result);
-       } else if (result != -ENODEV) {
-               pr_err("Error checking for keyboard-dock: %d\n", result);
+       if (asus->driver->quirks->use_kbd_dock_devid) {
+               result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK);
+               if (result >= 0) {
+                       input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
+                       input_report_switch(asus->inputdev, SW_TABLET_MODE, !result);
+               } else if (result != -ENODEV) {
+                       pr_err("Error checking for keyboard-dock: %d\n", result);
+               }
        }
 
        err = input_register_device(asus->inputdev);
@@ -442,6 +444,7 @@ static int asus_wmi_battery_add(struct power_supply *battery)
         */
        if (strcmp(battery->desc->name, "BAT0") != 0 &&
            strcmp(battery->desc->name, "BAT1") != 0 &&
+           strcmp(battery->desc->name, "BATC") != 0 &&
            strcmp(battery->desc->name, "BATT") != 0)
                return -ENODEV;
 
@@ -2114,7 +2117,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
                return;
        }
 
-       if (code == NOTIFY_KBD_DOCK_CHANGE) {
+       if (asus->driver->quirks->use_kbd_dock_devid && code == NOTIFY_KBD_DOCK_CHANGE) {
                result = asus_wmi_get_devstate_simple(asus,
                                                      ASUS_WMI_DEVID_KBD_DOCK);
                if (result >= 0) {
index 4f31b68..1a95c17 100644 (file)
@@ -33,6 +33,7 @@ struct quirk_entry {
        bool wmi_backlight_native;
        bool wmi_backlight_set_devstate;
        bool wmi_force_als_set;
+       bool use_kbd_dock_devid;
        int wapf;
        /*
         * For machines with AMD graphic chips, it will send out WMI event
index e85d8e5..f5901b0 100644 (file)
@@ -167,20 +167,54 @@ static bool intel_vbtn_has_buttons(acpi_handle handle)
        return ACPI_SUCCESS(status);
 }
 
+/*
+ * There are several laptops (non 2-in-1) models out there which support VGBS,
+ * but simply always return 0, which we translate to SW_TABLET_MODE=1. This in
+ * turn causes userspace (libinput) to suppress events from the builtin
+ * keyboard and touchpad, making the laptop essentially unusable.
+ *
+ * Since the problem of wrongly reporting SW_TABLET_MODE=1 in combination
+ * with libinput, leads to a non-usable system. Where as OTOH many people will
+ * not even notice when SW_TABLET_MODE is not being reported, a DMI based allow
+ * list is used here. This list mainly matches on the chassis-type of 2-in-1s.
+ *
+ * There are also some 2-in-1s which use the intel-vbtn ACPI interface to report
+ * SW_TABLET_MODE with a chassis-type of 8 ("Portable") or 10 ("Notebook"),
+ * these are matched on a per model basis, since many normal laptops with a
+ * possible broken VGBS ACPI-method also use these chassis-types.
+ */
+static const struct dmi_system_id dmi_switches_allow_list[] = {
+       {
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */),
+               },
+       },
+       {
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Stream x360 Convertible PC 11"),
+               },
+       },
+       {} /* Array terminator */
+};
+
 static bool intel_vbtn_has_switches(acpi_handle handle)
 {
-       const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
        unsigned long long vgbs;
        acpi_status status;
 
-       /*
-        * Some normal laptops have a VGBS method despite being non-convertible
-        * and their VGBS method always returns 0, causing detect_tablet_mode()
-        * to report SW_TABLET_MODE=1 to userspace, which causes issues.
-        * These laptops have a DMI chassis_type of 9 ("Laptop"), do not report
-        * switches on any devices with a DMI chassis_type of 9.
-        */
-       if (chassis_type && strcmp(chassis_type, "9") == 0)
+       if (!dmi_check_system(dmi_switches_allow_list))
                return false;
 
        status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs);
index 7312818..7379768 100644 (file)
 
 static void intel_pmc_core_release(struct device *dev)
 {
-       /* Nothing to do. */
+       kfree(dev);
 }
 
-static struct platform_device pmc_core_device = {
-       .name = "intel_pmc_core",
-       .dev  = {
-               .release = intel_pmc_core_release,
-       },
-};
+static struct platform_device *pmc_core_device;
 
 /*
  * intel_pmc_core_platform_ids is the list of platforms where we want to
@@ -52,6 +47,8 @@ MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_platform_ids);
 
 static int __init pmc_core_platform_init(void)
 {
+       int retval;
+
        /* Skip creating the platform device if ACPI already has a device */
        if (acpi_dev_present("INT33A1", NULL, -1))
                return -ENODEV;
@@ -59,12 +56,23 @@ static int __init pmc_core_platform_init(void)
        if (!x86_match_cpu(intel_pmc_core_platform_ids))
                return -ENODEV;
 
-       return platform_device_register(&pmc_core_device);
+       pmc_core_device = kzalloc(sizeof(*pmc_core_device), GFP_KERNEL);
+       if (!pmc_core_device)
+               return -ENOMEM;
+
+       pmc_core_device->name = "intel_pmc_core";
+       pmc_core_device->dev.release = intel_pmc_core_release;
+
+       retval = platform_device_register(pmc_core_device);
+       if (retval)
+               kfree(pmc_core_device);
+
+       return retval;
 }
 
 static void __exit pmc_core_platform_exit(void)
 {
-       platform_device_unregister(&pmc_core_device);
+       platform_device_unregister(pmc_core_device);
 }
 
 module_init(pmc_core_platform_init);
index 8cf8c1b..1506ec0 100644 (file)
 #define MLXPLAT_CPLD_NR_NONE                   -1
 #define MLXPLAT_CPLD_PSU_DEFAULT_NR            10
 #define MLXPLAT_CPLD_PSU_MSNXXXX_NR            4
-#define MLXPLAT_CPLD_PSU_MSNXXXX_NR2           3
 #define MLXPLAT_CPLD_FAN1_DEFAULT_NR           11
 #define MLXPLAT_CPLD_FAN2_DEFAULT_NR           12
 #define MLXPLAT_CPLD_FAN3_DEFAULT_NR           13
@@ -347,6 +346,15 @@ static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
        },
 };
 
+static struct i2c_board_info mlxplat_mlxcpld_ext_pwr[] = {
+       {
+               I2C_BOARD_INFO("dps460", 0x5b),
+       },
+       {
+               I2C_BOARD_INFO("dps460", 0x5a),
+       },
+};
+
 static struct i2c_board_info mlxplat_mlxcpld_fan[] = {
        {
                I2C_BOARD_INFO("24c32", 0x50),
@@ -921,15 +929,15 @@ static struct mlxreg_core_data mlxplat_mlxcpld_ext_pwr_items_data[] = {
                .label = "pwr3",
                .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
                .mask = BIT(2),
-               .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0],
-               .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR2,
+               .hpdev.brdinfo = &mlxplat_mlxcpld_ext_pwr[0],
+               .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
        },
        {
                .label = "pwr4",
                .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
                .mask = BIT(3),
-               .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1],
-               .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR2,
+               .hpdev.brdinfo = &mlxplat_mlxcpld_ext_pwr[1],
+               .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
        },
 };
 
index 6aff6cf..c37349f 100644 (file)
@@ -32,7 +32,7 @@
 #define APU2_GPIO_REG_LED3             AMD_FCH_GPIO_REG_GPIO59_DEVSLP1
 #define APU2_GPIO_REG_MODESW           AMD_FCH_GPIO_REG_GPIO32_GE1
 #define APU2_GPIO_REG_SIMSWAP          AMD_FCH_GPIO_REG_GPIO33_GE2
-#define APU2_GPIO_REG_MPCIE2           AMD_FCH_GPIO_REG_GPIO59_DEVSLP0
+#define APU2_GPIO_REG_MPCIE2           AMD_FCH_GPIO_REG_GPIO55_DEVSLP0
 #define APU2_GPIO_REG_MPCIE3           AMD_FCH_GPIO_REG_GPIO51
 
 /* Order in which the GPIO lines are defined in the register list */
index 9c4df41..eae3579 100644 (file)
@@ -2569,7 +2569,7 @@ static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn,
  */
 static int hotkey_kthread(void *data)
 {
-       struct tp_nvram_state s[2];
+       struct tp_nvram_state s[2] = { 0 };
        u32 poll_mask, event_mask;
        unsigned int si, so;
        unsigned long t;
@@ -6829,8 +6829,10 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
        list_for_each_entry(child, &device->children, node) {
                acpi_status status = acpi_evaluate_object(child->handle, "_BCL",
                                                          NULL, &buffer);
-               if (ACPI_FAILURE(status))
+               if (ACPI_FAILURE(status)) {
+                       buffer.length = ACPI_ALLOCATE_BUFFER;
                        continue;
+               }
 
                obj = (union acpi_object *)buffer.pointer;
                if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
index 5c22301..dda60f8 100644 (file)
@@ -373,6 +373,23 @@ static const struct ts_dmi_data jumper_ezpad_mini3_data = {
        .properties     = jumper_ezpad_mini3_props,
 };
 
+static const struct property_entry mpman_converter9_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 8),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-mpman-converter9.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       { }
+};
+
+static const struct ts_dmi_data mpman_converter9_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = mpman_converter9_props,
+};
+
 static const struct property_entry mpman_mpwin895cl_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-min-x", 3),
        PROPERTY_ENTRY_U32("touchscreen-min-y", 9),
@@ -977,6 +994,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                },
        },
        {
+               /* MP Man Converter 9 */
+               .driver_data = (void *)&mpman_converter9_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
+               },
+       },
+       {
                /* MP Man MPWIN895CL */
                .driver_data = (void *)&mpman_mpwin895cl_data,
                .matches = {
index 6f55aae..983d75b 100644 (file)
@@ -1035,7 +1035,11 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
        X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L,         &rapl_defaults_core),
        X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE,           &rapl_defaults_core),
        X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L,         &rapl_defaults_core),
+       X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE,           &rapl_defaults_core),
+       X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE,          &rapl_defaults_core),
+       X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,           &rapl_defaults_core),
        X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,    &rapl_defaults_spr_server),
+       X86_MATCH_INTEL_FAM6_MODEL(LAKEFIELD,           &rapl_defaults_core),
 
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,     &rapl_defaults_byt),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,        &rapl_defaults_cht),
index e4c422d..b9f8514 100644 (file)
@@ -37,7 +37,7 @@ config RAPIDIO_ENABLE_RX_TX_PORTS
 config RAPIDIO_DMA_ENGINE
        bool "DMA Engine support for RapidIO"
        depends on RAPIDIO
-       select DMADEVICES
+       depends on DMADEVICES
        select DMA_ENGINE
        help
          Say Y here if you want to use DMA Engine frameork for RapidIO data
index 1bacb37..cd12241 100644 (file)
@@ -42,8 +42,9 @@
 
 #define AXP20X_DCDC2_V_OUT_MASK                GENMASK(5, 0)
 #define AXP20X_DCDC3_V_OUT_MASK                GENMASK(7, 0)
-#define AXP20X_LDO24_V_OUT_MASK                GENMASK(7, 4)
+#define AXP20X_LDO2_V_OUT_MASK         GENMASK(7, 4)
 #define AXP20X_LDO3_V_OUT_MASK         GENMASK(6, 0)
+#define AXP20X_LDO4_V_OUT_MASK         GENMASK(3, 0)
 #define AXP20X_LDO5_V_OUT_MASK         GENMASK(7, 4)
 
 #define AXP20X_PWR_OUT_EXTEN_MASK      BIT_MASK(0)
@@ -542,14 +543,14 @@ static const struct regulator_desc axp20x_regulators[] = {
                 AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_DCDC3_MASK),
        AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
        AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
-                AXP20X_LDO24_V_OUT, AXP20X_LDO24_V_OUT_MASK,
+                AXP20X_LDO24_V_OUT, AXP20X_LDO2_V_OUT_MASK,
                 AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO2_MASK),
        AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
                 AXP20X_LDO3_V_OUT, AXP20X_LDO3_V_OUT_MASK,
                 AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO3_MASK),
        AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in",
                        axp20x_ldo4_ranges, AXP20X_LDO4_V_OUT_NUM_VOLTAGES,
-                       AXP20X_LDO24_V_OUT, AXP20X_LDO24_V_OUT_MASK,
+                       AXP20X_LDO24_V_OUT, AXP20X_LDO4_V_OUT_MASK,
                        AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO4_MASK),
        AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
                    AXP20X_LDO5_V_OUT, AXP20X_LDO5_V_OUT_MASK,
index 3fd3599..7ff507e 100644 (file)
@@ -236,8 +236,8 @@ static bool regulator_supply_is_couple(struct regulator_dev *rdev)
 static void regulator_unlock_recursive(struct regulator_dev *rdev,
                                       unsigned int n_coupled)
 {
-       struct regulator_dev *c_rdev;
-       int i;
+       struct regulator_dev *c_rdev, *supply_rdev;
+       int i, supply_n_coupled;
 
        for (i = n_coupled; i > 0; i--) {
                c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
@@ -245,10 +245,13 @@ static void regulator_unlock_recursive(struct regulator_dev *rdev,
                if (!c_rdev)
                        continue;
 
-               if (c_rdev->supply && !regulator_supply_is_couple(c_rdev))
-                       regulator_unlock_recursive(
-                                       c_rdev->supply->rdev,
-                                       c_rdev->coupling_desc.n_coupled);
+               if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
+                       supply_rdev = c_rdev->supply->rdev;
+                       supply_n_coupled = supply_rdev->coupling_desc.n_coupled;
+
+                       regulator_unlock_recursive(supply_rdev,
+                                                  supply_n_coupled);
+               }
 
                regulator_unlock(c_rdev);
        }
@@ -1461,7 +1464,7 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
                                      const char *consumer_dev_name,
                                      const char *supply)
 {
-       struct regulator_map *node;
+       struct regulator_map *node, *new_node;
        int has_dev;
 
        if (supply == NULL)
@@ -1472,6 +1475,22 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
        else
                has_dev = 0;
 
+       new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
+       if (new_node == NULL)
+               return -ENOMEM;
+
+       new_node->regulator = rdev;
+       new_node->supply = supply;
+
+       if (has_dev) {
+               new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
+               if (new_node->dev_name == NULL) {
+                       kfree(new_node);
+                       return -ENOMEM;
+               }
+       }
+
+       mutex_lock(&regulator_list_mutex);
        list_for_each_entry(node, &regulator_map_list, list) {
                if (node->dev_name && consumer_dev_name) {
                        if (strcmp(node->dev_name, consumer_dev_name) != 0)
@@ -1489,26 +1508,19 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
                         node->regulator->desc->name,
                         supply,
                         dev_name(&rdev->dev), rdev_get_name(rdev));
-               return -EBUSY;
+               goto fail;
        }
 
-       node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
-       if (node == NULL)
-               return -ENOMEM;
-
-       node->regulator = rdev;
-       node->supply = supply;
-
-       if (has_dev) {
-               node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
-               if (node->dev_name == NULL) {
-                       kfree(node);
-                       return -ENOMEM;
-               }
-       }
+       list_add(&new_node->list, &regulator_map_list);
+       mutex_unlock(&regulator_list_mutex);
 
-       list_add(&node->list, &regulator_map_list);
        return 0;
+
+fail:
+       mutex_unlock(&regulator_list_mutex);
+       kfree(new_node->dev_name);
+       kfree(new_node);
+       return -EBUSY;
 }
 
 static void unset_regulator_supplies(struct regulator_dev *rdev)
@@ -1580,44 +1592,53 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                                          const char *supply_name)
 {
        struct regulator *regulator;
-       char buf[REG_STR_SIZE];
-       int err, size;
+       int err;
+
+       if (dev) {
+               char buf[REG_STR_SIZE];
+               int size;
+
+               size = snprintf(buf, REG_STR_SIZE, "%s-%s",
+                               dev->kobj.name, supply_name);
+               if (size >= REG_STR_SIZE)
+                       return NULL;
+
+               supply_name = kstrdup(buf, GFP_KERNEL);
+               if (supply_name == NULL)
+                       return NULL;
+       } else {
+               supply_name = kstrdup_const(supply_name, GFP_KERNEL);
+               if (supply_name == NULL)
+                       return NULL;
+       }
 
        regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
-       if (regulator == NULL)
+       if (regulator == NULL) {
+               kfree(supply_name);
                return NULL;
+       }
 
-       regulator_lock(rdev);
        regulator->rdev = rdev;
+       regulator->supply_name = supply_name;
+
+       regulator_lock(rdev);
        list_add(&regulator->list, &rdev->consumer_list);
+       regulator_unlock(rdev);
 
        if (dev) {
                regulator->dev = dev;
 
                /* Add a link to the device sysfs entry */
-               size = snprintf(buf, REG_STR_SIZE, "%s-%s",
-                               dev->kobj.name, supply_name);
-               if (size >= REG_STR_SIZE)
-                       goto overflow_err;
-
-               regulator->supply_name = kstrdup(buf, GFP_KERNEL);
-               if (regulator->supply_name == NULL)
-                       goto overflow_err;
-
                err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
-                                       buf);
+                                              supply_name);
                if (err) {
                        rdev_dbg(rdev, "could not add device link %s err %d\n",
                                  dev->kobj.name, err);
                        /* non-fatal */
                }
-       } else {
-               regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL);
-               if (regulator->supply_name == NULL)
-                       goto overflow_err;
        }
 
-       regulator->debugfs = debugfs_create_dir(regulator->supply_name,
+       regulator->debugfs = debugfs_create_dir(supply_name,
                                                rdev->debugfs);
        if (!regulator->debugfs) {
                rdev_dbg(rdev, "Failed to create debugfs directory\n");
@@ -1642,13 +1663,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
            _regulator_is_enabled(rdev))
                regulator->always_on = true;
 
-       regulator_unlock(rdev);
        return regulator;
-overflow_err:
-       list_del(&regulator->list);
-       kfree(regulator);
-       regulator_unlock(rdev);
-       return NULL;
 }
 
 static int _regulator_get_enable_time(struct regulator_dev *rdev)
@@ -2230,10 +2245,13 @@ EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
 static int regulator_ena_gpio_request(struct regulator_dev *rdev,
                                const struct regulator_config *config)
 {
-       struct regulator_enable_gpio *pin;
+       struct regulator_enable_gpio *pin, *new_pin;
        struct gpio_desc *gpiod;
 
        gpiod = config->ena_gpiod;
+       new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);
+
+       mutex_lock(&regulator_list_mutex);
 
        list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
                if (pin->gpiod == gpiod) {
@@ -2242,9 +2260,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
                }
        }
 
-       pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
-       if (pin == NULL)
+       if (new_pin == NULL) {
+               mutex_unlock(&regulator_list_mutex);
                return -ENOMEM;
+       }
+
+       pin = new_pin;
+       new_pin = NULL;
 
        pin->gpiod = gpiod;
        list_add(&pin->list, &regulator_ena_gpio_list);
@@ -2252,6 +2274,10 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
 update_ena_gpio_to_rdev:
        pin->request_count++;
        rdev->ena_pin = pin;
+
+       mutex_unlock(&regulator_list_mutex);
+       kfree(new_pin);
+
        return 0;
 }
 
@@ -2264,19 +2290,19 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
 
        /* Free the GPIO only in case of no use */
        list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
-               if (pin->gpiod == rdev->ena_pin->gpiod) {
-                       if (pin->request_count <= 1) {
-                               pin->request_count = 0;
-                               gpiod_put(pin->gpiod);
-                               list_del(&pin->list);
-                               kfree(pin);
-                               rdev->ena_pin = NULL;
-                               return;
-                       } else {
-                               pin->request_count--;
-                       }
-               }
+               if (pin != rdev->ena_pin)
+                       continue;
+
+               if (--pin->request_count)
+                       break;
+
+               gpiod_put(pin->gpiod);
+               list_del(&pin->list);
+               kfree(pin);
+               break;
        }
+
+       rdev->ena_pin = NULL;
 }
 
 /**
@@ -4949,13 +4975,9 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev)
                        return;
                }
 
-               regulator_lock(c_rdev);
-
                c_desc->coupled_rdevs[i] = c_rdev;
                c_desc->n_resolved++;
 
-               regulator_unlock(c_rdev);
-
                regulator_resolve_coupling(c_rdev);
        }
 }
@@ -5040,7 +5062,10 @@ static int regulator_init_coupling(struct regulator_dev *rdev)
        if (!of_check_coupling_data(rdev))
                return -EPERM;
 
+       mutex_lock(&regulator_list_mutex);
        rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
+       mutex_unlock(&regulator_list_mutex);
+
        if (IS_ERR(rdev->coupling_desc.coupler)) {
                err = PTR_ERR(rdev->coupling_desc.coupler);
                rdev_err(rdev, "failed to get coupler: %d\n", err);
@@ -5141,6 +5166,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                ret = -ENOMEM;
                goto rinse;
        }
+       device_initialize(&rdev->dev);
 
        /*
         * Duplicate the config so the driver could override it after
@@ -5148,9 +5174,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
         */
        config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
        if (config == NULL) {
-               kfree(rdev);
                ret = -ENOMEM;
-               goto rinse;
+               goto clean;
        }
 
        init_data = regulator_of_get_init_data(dev, regulator_desc, config,
@@ -5162,10 +5187,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
         * from a gpio extender or something else.
         */
        if (PTR_ERR(init_data) == -EPROBE_DEFER) {
-               kfree(config);
-               kfree(rdev);
                ret = -EPROBE_DEFER;
-               goto rinse;
+               goto clean;
        }
 
        /*
@@ -5206,9 +5229,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
        }
 
        if (config->ena_gpiod) {
-               mutex_lock(&regulator_list_mutex);
                ret = regulator_ena_gpio_request(rdev, config);
-               mutex_unlock(&regulator_list_mutex);
                if (ret != 0) {
                        rdev_err(rdev, "Failed to request enable GPIO: %d\n",
                                 ret);
@@ -5220,7 +5241,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
        }
 
        /* register with sysfs */
-       device_initialize(&rdev->dev);
        rdev->dev.class = &regulator_class;
        rdev->dev.parent = dev;
        dev_set_name(&rdev->dev, "regulator.%lu",
@@ -5248,27 +5268,22 @@ regulator_register(const struct regulator_desc *regulator_desc,
        if (ret < 0)
                goto wash;
 
-       mutex_lock(&regulator_list_mutex);
        ret = regulator_init_coupling(rdev);
-       mutex_unlock(&regulator_list_mutex);
        if (ret < 0)
                goto wash;
 
        /* add consumers devices */
        if (init_data) {
-               mutex_lock(&regulator_list_mutex);
                for (i = 0; i < init_data->num_consumer_supplies; i++) {
                        ret = set_consumer_device_supply(rdev,
                                init_data->consumer_supplies[i].dev_name,
                                init_data->consumer_supplies[i].supply);
                        if (ret < 0) {
-                               mutex_unlock(&regulator_list_mutex);
                                dev_err(dev, "Failed to set supply %s\n",
                                        init_data->consumer_supplies[i].supply);
                                goto unset_supplies;
                        }
                }
-               mutex_unlock(&regulator_list_mutex);
        }
 
        if (!rdev->desc->ops->get_voltage &&
@@ -5303,13 +5318,11 @@ wash:
        mutex_lock(&regulator_list_mutex);
        regulator_ena_gpio_free(rdev);
        mutex_unlock(&regulator_list_mutex);
-       put_device(&rdev->dev);
-       rdev = NULL;
 clean:
        if (dangling_of_gpiod)
                gpiod_put(config->ena_gpiod);
-       kfree(rdev);
        kfree(config);
+       put_device(&rdev->dev);
 rinse:
        if (dangling_cfg_gpiod)
                gpiod_put(cfg->ena_gpiod);
index 3117bbd..eb3fc1d 100644 (file)
@@ -170,6 +170,9 @@ static int cros_ec_regulator_init_info(struct device *dev,
        data->voltages_mV =
                devm_kmemdup(dev, resp.voltages_mv,
                             sizeof(u16) * data->num_voltages, GFP_KERNEL);
+       if (!data->voltages_mV)
+               return -ENOMEM;
+
        data->desc.n_voltages = data->num_voltages;
 
        /* Make sure the returned name is always a valid string */
index d54830e..142a70a 100644 (file)
@@ -182,7 +182,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 
                drvdata->enable_clock = devm_clk_get(dev, NULL);
                if (IS_ERR(drvdata->enable_clock)) {
-                       dev_err(dev, "Cant get enable-clock from devicetree\n");
+                       dev_err(dev, "Can't get enable-clock from devicetree\n");
                        return -ENOENT;
                }
        } else {
index 3234b11..990bd50 100644 (file)
@@ -279,7 +279,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
                return ret;
        }
 
-       drvdata->state                  = -EINVAL;
+       drvdata->state                  = -ENOTRECOVERABLE;
        drvdata->duty_cycle_table       = duty_cycle_table;
        drvdata->desc.ops = &pwm_regulator_voltage_table_ops;
        drvdata->desc.n_voltages        = length / sizeof(*duty_cycle_table);
index cbb7708..1a44e32 100644 (file)
@@ -40,6 +40,7 @@
 MODULE_LICENSE("GPL");
 
 static struct dasd_discipline dasd_fba_discipline;
+static void *dasd_fba_zero_page;
 
 struct dasd_fba_private {
        struct dasd_fba_characteristics rdc_data;
@@ -270,7 +271,7 @@ static void ccw_write_zero(struct ccw1 *ccw, int count)
        ccw->cmd_code = DASD_FBA_CCW_WRITE;
        ccw->flags |= CCW_FLAG_SLI;
        ccw->count = count;
-       ccw->cda = (__u32) (addr_t) page_to_phys(ZERO_PAGE(0));
+       ccw->cda = (__u32) (addr_t) dasd_fba_zero_page;
 }
 
 /*
@@ -830,6 +831,11 @@ dasd_fba_init(void)
        int ret;
 
        ASCEBC(dasd_fba_discipline.ebcname, 4);
+
+       dasd_fba_zero_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!dasd_fba_zero_page)
+               return -ENOMEM;
+
        ret = ccw_driver_register(&dasd_fba_driver);
        if (!ret)
                wait_for_device_probe();
@@ -841,6 +847,7 @@ static void __exit
 dasd_fba_cleanup(void)
 {
        ccw_driver_unregister(&dasd_fba_driver);
+       free_page((unsigned long)dasd_fba_zero_page);
 }
 
 module_init(dasd_fba_init);
index 4dbbfd8..f314936 100644 (file)
@@ -1449,7 +1449,8 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
                if (!reqcnt)
                        return -ENOMEM;
                zcrypt_perdev_reqcnt(reqcnt, AP_DEVICES);
-               if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt)))
+               if (copy_to_user((int __user *) arg, reqcnt,
+                                sizeof(u32) * AP_DEVICES))
                        rc = -EFAULT;
                kfree(reqcnt);
                return rc;
index 3f5b613..c793dca 100644 (file)
@@ -1692,9 +1692,9 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
        *nr_apqns = 0;
 
        /* fetch status of all crypto cards */
-       device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT,
-                                     sizeof(struct zcrypt_device_status_ext),
-                                     GFP_KERNEL);
+       device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT,
+                                      sizeof(struct zcrypt_device_status_ext),
+                                      GFP_KERNEL);
        if (!device_status)
                return -ENOMEM;
        zcrypt_device_status_mask_ext(device_status);
@@ -1762,7 +1762,7 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
                verify = 0;
        }
 
-       kfree(device_status);
+       kvfree(device_status);
        return rc;
 }
 EXPORT_SYMBOL(cca_findcard2);
index 3a94f6c..6384f7a 100644 (file)
@@ -284,11 +284,11 @@ static void qeth_l2_stop_card(struct qeth_card *card)
 
        if (card->state == CARD_STATE_SOFTSETUP) {
                qeth_clear_ipacmd_list(card);
-               qeth_drain_output_queues(card);
                card->state = CARD_STATE_DOWN;
        }
 
        qeth_qdio_clear_card(card, 0);
+       qeth_drain_output_queues(card);
        qeth_clear_working_pool_list(card);
        flush_workqueue(card->event_wq);
        qeth_flush_local_addrs(card);
index 4d46196..09ef518 100644 (file)
@@ -1168,11 +1168,11 @@ static void qeth_l3_stop_card(struct qeth_card *card)
        if (card->state == CARD_STATE_SOFTSETUP) {
                qeth_l3_clear_ip_htable(card, 1);
                qeth_clear_ipacmd_list(card);
-               qeth_drain_output_queues(card);
                card->state = CARD_STATE_DOWN;
        }
 
        qeth_qdio_clear_card(card, 0);
+       qeth_drain_output_queues(card);
        qeth_clear_working_pool_list(card);
        flush_workqueue(card->event_wq);
        qeth_flush_local_addrs(card);
index b5dd1ca..d10efb6 100644 (file)
@@ -736,6 +736,7 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
        struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
        struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
        struct sockaddr_in6 addr;
+       struct socket *sock;
        int rc;
 
        switch(param) {
@@ -747,13 +748,17 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
                        spin_unlock_bh(&conn->session->frwd_lock);
                        return -ENOTCONN;
                }
+               sock = tcp_sw_conn->sock;
+               sock_hold(sock->sk);
+               spin_unlock_bh(&conn->session->frwd_lock);
+
                if (param == ISCSI_PARAM_LOCAL_PORT)
-                       rc = kernel_getsockname(tcp_sw_conn->sock,
+                       rc = kernel_getsockname(sock,
                                                (struct sockaddr *)&addr);
                else
-                       rc = kernel_getpeername(tcp_sw_conn->sock,
+                       rc = kernel_getpeername(sock,
                                                (struct sockaddr *)&addr);
-               spin_unlock_bh(&conn->session->frwd_lock);
+               sock_put(sock->sk);
                if (rc < 0)
                        return rc;
 
@@ -775,6 +780,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
        struct iscsi_tcp_conn *tcp_conn;
        struct iscsi_sw_tcp_conn *tcp_sw_conn;
        struct sockaddr_in6 addr;
+       struct socket *sock;
        int rc;
 
        switch (param) {
@@ -789,16 +795,18 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
                        return -ENOTCONN;
                }
                tcp_conn = conn->dd_data;
-
                tcp_sw_conn = tcp_conn->dd_data;
-               if (!tcp_sw_conn->sock) {
+               sock = tcp_sw_conn->sock;
+               if (!sock) {
                        spin_unlock_bh(&session->frwd_lock);
                        return -ENOTCONN;
                }
+               sock_hold(sock->sk);
+               spin_unlock_bh(&session->frwd_lock);
 
-               rc = kernel_getsockname(tcp_sw_conn->sock,
+               rc = kernel_getsockname(sock,
                                        (struct sockaddr *)&addr);
-               spin_unlock_bh(&session->frwd_lock);
+               sock_put(sock->sk);
                if (rc < 0)
                        return rc;
 
index d8cbc9c..e67abb1 100644 (file)
@@ -634,8 +634,6 @@ free_fp:
        fc_frame_free(fp);
 out:
        kref_put(&rdata->kref, fc_rport_destroy);
-       if (!IS_ERR(fp))
-               fc_frame_free(fp);
 }
 
 /**
index 37e5d4e..83f14b2 100644 (file)
@@ -128,7 +128,7 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
         * coalescing neighboring slab objects into a single frag which
         * triggers one of hardened usercopy checks.
         */
-       if (!recv && page_count(sg_page(sg)) >= 1 && !PageSlab(sg_page(sg)))
+       if (!recv && sendpage_ok(sg_page(sg)))
                return;
 
        if (recv) {
index 6a521ba..a488798 100644 (file)
@@ -209,7 +209,10 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
                task->num_scatter = si;
        }
 
-       task->data_dir = qc->dma_dir;
+       if (qc->tf.protocol == ATA_PROT_NODATA)
+               task->data_dir = DMA_NONE;
+       else
+               task->data_dir = qc->dma_dir;
        task->scatter = qc->sg;
        task->ata_task.retry_count = 1;
        task->task_state_flags = SAS_TASK_STATE_PENDING;
index cd7c7d2..d0f9e90 100644 (file)
@@ -182,10 +182,11 @@ int sas_notify_lldd_dev_found(struct domain_device *dev)
                pr_warn("driver on host %s cannot handle device %016llx, error:%d\n",
                        dev_name(sas_ha->dev),
                        SAS_ADDR(dev->sas_addr), res);
+               return res;
        }
        set_bit(SAS_DEV_FOUND, &dev->state);
        kref_get(&dev->kref);
-       return res;
+       return 0;
 }
 
 
index 6aae61d..b609451 100644 (file)
@@ -3517,6 +3517,9 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
                                FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1));
        prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT);
        prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY);
+       prdf->reg_d1.desc_tags[1] = cpu_to_be32(ELS_DTAG_DELIVERY);
+       prdf->reg_d1.desc_tags[2] = cpu_to_be32(ELS_DTAG_PEER_CONGEST);
+       prdf->reg_d1.desc_tags[3] = cpu_to_be32(ELS_DTAG_CONGESTION);
 
        lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
                              "Issue RDF:       did:x%x",
@@ -4656,7 +4659,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 out:
        if (ndlp && NLP_CHK_NODE_ACT(ndlp) && shost) {
                spin_lock_irq(shost->host_lock);
-               ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
+               if (mbox)
+                       ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
+               ndlp->nlp_flag &= ~NLP_RM_DFLT_RPI;
                spin_unlock_irq(shost->host_lock);
 
                /* If the node is not being used by another discovery thread,
index d32c7e7..bb02fd8 100644 (file)
@@ -71,6 +71,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_vport *);
 static void lpfc_disc_flush_list(struct lpfc_vport *vport);
 static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
 static int lpfc_fcf_inuse(struct lpfc_hba *);
+static void lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
 
 void
 lpfc_terminate_rport_io(struct fc_rport *rport)
@@ -1138,11 +1139,13 @@ out:
        return;
 }
 
-
 void
 lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
        struct lpfc_vport *vport = pmb->vport;
+       LPFC_MBOXQ_t *sparam_mb;
+       struct lpfc_dmabuf *sparam_mp;
+       int rc;
 
        if (pmb->u.mb.mbxStatus)
                goto out;
@@ -1167,12 +1170,42 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        }
 
        /* Start discovery by sending a FLOGI. port_state is identically
-        * LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending
-        * the FLOGI is being deferred till after MBX_READ_SPARAM completes.
+        * LPFC_FLOGI while waiting for FLOGI cmpl.
         */
        if (vport->port_state != LPFC_FLOGI) {
-               if (!(phba->hba_flag & HBA_DEFER_FLOGI))
+               /* Issue MBX_READ_SPARAM to update CSPs before FLOGI if
+                * bb-credit recovery is in place.
+                */
+               if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
+                   !(phba->link_flag & LS_LOOPBACK_MODE)) {
+                       sparam_mb = mempool_alloc(phba->mbox_mem_pool,
+                                                 GFP_KERNEL);
+                       if (!sparam_mb)
+                               goto sparam_out;
+
+                       rc = lpfc_read_sparam(phba, sparam_mb, 0);
+                       if (rc) {
+                               mempool_free(sparam_mb, phba->mbox_mem_pool);
+                               goto sparam_out;
+                       }
+                       sparam_mb->vport = vport;
+                       sparam_mb->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
+                       rc = lpfc_sli_issue_mbox(phba, sparam_mb, MBX_NOWAIT);
+                       if (rc == MBX_NOT_FINISHED) {
+                               sparam_mp = (struct lpfc_dmabuf *)
+                                               sparam_mb->ctx_buf;
+                               lpfc_mbuf_free(phba, sparam_mp->virt,
+                                              sparam_mp->phys);
+                               kfree(sparam_mp);
+                               sparam_mb->ctx_buf = NULL;
+                               mempool_free(sparam_mb, phba->mbox_mem_pool);
+                               goto sparam_out;
+                       }
+
+                       phba->hba_flag |= HBA_DEFER_FLOGI;
+               }  else {
                        lpfc_initial_flogi(vport);
+               }
        } else {
                if (vport->fc_flag & FC_PT2PT)
                        lpfc_disc_start(vport);
@@ -1184,6 +1217,7 @@ out:
                         "0306 CONFIG_LINK mbxStatus error x%x "
                         "HBA state x%x\n",
                         pmb->u.mb.mbxStatus, vport->port_state);
+sparam_out:
        mempool_free(pmb, phba->mbox_mem_pool);
 
        lpfc_linkdown(phba);
@@ -3239,21 +3273,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
        lpfc_linkup(phba);
        sparam_mbox = NULL;
 
-       if (!(phba->hba_flag & HBA_FCOE_MODE)) {
-               cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!cfglink_mbox)
-                       goto out;
-               vport->port_state = LPFC_LOCAL_CFG_LINK;
-               lpfc_config_link(phba, cfglink_mbox);
-               cfglink_mbox->vport = vport;
-               cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
-               rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT);
-               if (rc == MBX_NOT_FINISHED) {
-                       mempool_free(cfglink_mbox, phba->mbox_mem_pool);
-                       goto out;
-               }
-       }
-
        sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!sparam_mbox)
                goto out;
@@ -3274,7 +3293,20 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                goto out;
        }
 
-       if (phba->hba_flag & HBA_FCOE_MODE) {
+       if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+               cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+               if (!cfglink_mbox)
+                       goto out;
+               vport->port_state = LPFC_LOCAL_CFG_LINK;
+               lpfc_config_link(phba, cfglink_mbox);
+               cfglink_mbox->vport = vport;
+               cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
+               rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT);
+               if (rc == MBX_NOT_FINISHED) {
+                       mempool_free(cfglink_mbox, phba->mbox_mem_pool);
+                       goto out;
+               }
+       } else {
                vport->port_state = LPFC_VPORT_UNKNOWN;
                /*
                 * Add the driver's default FCF record at FCF index 0 now. This
@@ -3331,10 +3363,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                }
                /* Reset FCF roundrobin bmask for new discovery */
                lpfc_sli4_clear_fcf_rr_bmask(phba);
-       } else {
-               if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
-                   !(phba->link_flag & LS_LOOPBACK_MODE))
-                       phba->hba_flag |= HBA_DEFER_FLOGI;
        }
 
        /* Prepare for LINK up registrations */
index c4ba827..12e4e76 100644 (file)
@@ -4800,7 +4800,7 @@ struct send_frame_wqe {
        uint32_t fc_hdr_wd5;           /* word 15 */
 };
 
-#define ELS_RDF_REG_TAG_CNT            1
+#define ELS_RDF_REG_TAG_CNT            4
 struct lpfc_els_rdf_reg_desc {
        struct fc_df_desc_fpin_reg      reg_desc;       /* descriptor header */
        __be32                          desc_tags[ELS_RDF_REG_TAG_CNT];
index c697259..ca25e54 100644 (file)
@@ -11376,7 +11376,6 @@ lpfc_irq_clear_aff(struct lpfc_hba_eq_hdl *eqhdl)
 {
        cpumask_clear(&eqhdl->aff_mask);
        irq_clear_status_flags(eqhdl->irq, IRQ_NO_BALANCING);
-       irq_set_affinity_hint(eqhdl->irq, &eqhdl->aff_mask);
 }
 
 /**
index 20adec4..c657abf 100644 (file)
@@ -20,7 +20,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "12.8.0.3"
+#define LPFC_DRIVER_VERSION "12.8.0.4"
 #define LPFC_DRIVER_NAME               "lpfc"
 
 /* Used for SLI 2/3 */
index 883cccb..b0c01cf 100644 (file)
@@ -3689,7 +3689,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget)
        instance = irq_ctx->instance;
 
        if (irq_ctx->irq_line_enable) {
-               disable_irq(irq_ctx->os_irq);
+               disable_irq_nosync(irq_ctx->os_irq);
                irq_ctx->irq_line_enable = false;
        }
 
index 5730f32..8062bd9 100644 (file)
@@ -1733,7 +1733,7 @@ _base_irqpoll(struct irq_poll *irqpoll, int budget)
        reply_q = container_of(irqpoll, struct adapter_reply_queue,
                        irqpoll);
        if (reply_q->irq_line_enable) {
-               disable_irq(reply_q->os_irq);
+               disable_irq_nosync(reply_q->os_irq);
                reply_q->irq_line_enable = false;
        }
        num_entries = _base_process_reply_queue(reply_q);
index 337e79d..9889bab 100644 (file)
@@ -818,7 +818,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
 
                res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
                if (res)
-                       return res;
+                       goto ex_err;
                ccb = &pm8001_ha->ccb_info[ccb_tag];
                ccb->device = pm8001_dev;
                ccb->ccb_tag = ccb_tag;
index 1bc090d..a165120 100644 (file)
@@ -1626,7 +1626,7 @@ typedef struct {
         */
        uint8_t  firmware_options[2];
 
-       uint16_t frame_payload_size;
+       __le16  frame_payload_size;
        __le16  max_iocb_allocation;
        __le16  execution_throttle;
        uint8_t  retry_count;
index 507919d..0bd04a6 100644 (file)
@@ -4603,18 +4603,18 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
                        nv->firmware_options[1] = BIT_7 | BIT_5;
                        nv->add_firmware_options[0] = BIT_5;
                        nv->add_firmware_options[1] = BIT_5 | BIT_4;
-                       nv->frame_payload_size = 2048;
+                       nv->frame_payload_size = cpu_to_le16(2048);
                        nv->special_options[1] = BIT_7;
                } else if (IS_QLA2200(ha)) {
                        nv->firmware_options[0] = BIT_2 | BIT_1;
                        nv->firmware_options[1] = BIT_7 | BIT_5;
                        nv->add_firmware_options[0] = BIT_5;
                        nv->add_firmware_options[1] = BIT_5 | BIT_4;
-                       nv->frame_payload_size = 1024;
+                       nv->frame_payload_size = cpu_to_le16(1024);
                } else if (IS_QLA2100(ha)) {
                        nv->firmware_options[0] = BIT_3 | BIT_1;
                        nv->firmware_options[1] = BIT_5;
-                       nv->frame_payload_size = 1024;
+                       nv->frame_payload_size = cpu_to_le16(1024);
                }
 
                nv->max_iocb_allocation = cpu_to_le16(256);
index 95018e6..16503e2 100644 (file)
@@ -2964,26 +2964,32 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
 
        if (sdkp->device->type == TYPE_ZBC) {
                /* Host-managed */
-               q->limits.zoned = BLK_ZONED_HM;
+               blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HM);
        } else {
                sdkp->zoned = (buffer[8] >> 4) & 3;
-               if (sdkp->zoned == 1 && !disk_has_partitions(sdkp->disk)) {
+               if (sdkp->zoned == 1) {
                        /* Host-aware */
-                       q->limits.zoned = BLK_ZONED_HA;
+                       blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HA);
                } else {
-                       /*
-                        * Treat drive-managed devices and host-aware devices
-                        * with partitions as regular block devices.
-                        */
-                       q->limits.zoned = BLK_ZONED_NONE;
-                       if (sdkp->zoned == 2 && sdkp->first_scan)
-                               sd_printk(KERN_NOTICE, sdkp,
-                                         "Drive-managed SMR disk\n");
+                       /* Regular disk or drive managed disk */
+                       blk_queue_set_zoned(sdkp->disk, BLK_ZONED_NONE);
                }
        }
-       if (blk_queue_is_zoned(q) && sdkp->first_scan)
+
+       if (!sdkp->first_scan)
+               goto out;
+
+       if (blk_queue_is_zoned(q)) {
                sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
                      q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware");
+       } else {
+               if (sdkp->zoned == 1)
+                       sd_printk(KERN_NOTICE, sdkp,
+                                 "Host-aware SMR disk used as regular disk\n");
+               else if (sdkp->zoned == 2)
+                       sd_printk(KERN_NOTICE, sdkp,
+                                 "Drive-managed SMR disk\n");
+       }
 
  out:
        kfree(buffer);
@@ -3404,10 +3410,6 @@ static int sd_probe(struct device *dev)
        sdkp->first_scan = 1;
        sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS;
 
-       error = sd_zbc_init_disk(sdkp);
-       if (error)
-               goto out_free_index;
-
        sd_revalidate_disk(gd);
 
        gd->flags = GENHD_FL_EXT_DEVT;
index 4933e7d..a3aad60 100644 (file)
@@ -215,7 +215,6 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp)
 
 #ifdef CONFIG_BLK_DEV_ZONED
 
-int sd_zbc_init_disk(struct scsi_disk *sdkp);
 void sd_zbc_release_disk(struct scsi_disk *sdkp);
 int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
 int sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
@@ -231,11 +230,6 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
 
 #else /* CONFIG_BLK_DEV_ZONED */
 
-static inline int sd_zbc_init_disk(struct scsi_disk *sdkp)
-{
-       return 0;
-}
-
 static inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {}
 
 static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
@@ -259,7 +253,7 @@ static inline blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
 static inline unsigned int sd_zbc_complete(struct scsi_cmnd *cmd,
                        unsigned int good_bytes, struct scsi_sense_hdr *sshdr)
 {
-       return 0;
+       return good_bytes;
 }
 
 static inline blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd,
index 0e94ff0..cf07b7f 100644 (file)
@@ -651,6 +651,28 @@ static void sd_zbc_print_zones(struct scsi_disk *sdkp)
                          sdkp->zone_blocks);
 }
 
+static int sd_zbc_init_disk(struct scsi_disk *sdkp)
+{
+       sdkp->zones_wp_offset = NULL;
+       spin_lock_init(&sdkp->zones_wp_offset_lock);
+       sdkp->rev_wp_offset = NULL;
+       mutex_init(&sdkp->rev_mutex);
+       INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
+       sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
+       if (!sdkp->zone_wp_update_buf)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void sd_zbc_release_disk(struct scsi_disk *sdkp)
+{
+       kvfree(sdkp->zones_wp_offset);
+       sdkp->zones_wp_offset = NULL;
+       kfree(sdkp->zone_wp_update_buf);
+       sdkp->zone_wp_update_buf = NULL;
+}
+
 static void sd_zbc_revalidate_zones_cb(struct gendisk *disk)
 {
        struct scsi_disk *sdkp = scsi_disk(disk);
@@ -667,7 +689,24 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
        u32 max_append;
        int ret = 0;
 
-       if (!sd_is_zoned(sdkp))
+       /*
+        * For all zoned disks, initialize zone append emulation data if not
+        * already done. This is necessary also for host-aware disks used as
+        * regular disks due to the presence of partitions as these partitions
+        * may be deleted and the disk zoned model changed back from
+        * BLK_ZONED_NONE to BLK_ZONED_HA.
+        */
+       if (sd_is_zoned(sdkp) && !sdkp->zone_wp_update_buf) {
+               ret = sd_zbc_init_disk(sdkp);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * There is nothing to do for regular disks, including host-aware disks
+        * that have partitions.
+        */
+       if (!blk_queue_is_zoned(q))
                return 0;
 
        /*
@@ -764,28 +803,3 @@ err:
 
        return ret;
 }
-
-int sd_zbc_init_disk(struct scsi_disk *sdkp)
-{
-       if (!sd_is_zoned(sdkp))
-               return 0;
-
-       sdkp->zones_wp_offset = NULL;
-       spin_lock_init(&sdkp->zones_wp_offset_lock);
-       sdkp->rev_wp_offset = NULL;
-       mutex_init(&sdkp->rev_mutex);
-       INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
-       sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
-       if (!sdkp->zone_wp_update_buf)
-               return -ENOMEM;
-
-       return 0;
-}
-
-void sd_zbc_release_disk(struct scsi_disk *sdkp)
-{
-       kvfree(sdkp->zones_wp_offset);
-       sdkp->zones_wp_offset = NULL;
-       kfree(sdkp->zone_wp_update_buf);
-       sdkp->zone_wp_update_buf = NULL;
-}
index e6e0fb9..da02016 100644 (file)
@@ -1372,7 +1372,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
                return ret;
        }
 
-       /* Read Instat 1, Instat 2 and Instat 3 registers */
+       /* Read Intstat 1, Intstat 2 and Intstat 3 registers */
        ret = sdw_read(slave, SDW_SCP_INT1);
        if (ret < 0) {
                dev_err(slave->bus->dev,
index 37290a7..6e36deb 100644 (file)
@@ -717,6 +717,7 @@ error:
        kfree(wbuf);
 error_1:
        kfree(wr_msg);
+       bus->defer_msg.msg = NULL;
        return ret;
 }
 
@@ -840,9 +841,10 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
 error:
        list_for_each_entry(m_rt, &stream->master_list, stream_node) {
                bus = m_rt->bus;
-
-               kfree(bus->defer_msg.msg->buf);
-               kfree(bus->defer_msg.msg);
+               if (bus->defer_msg.msg) {
+                       kfree(bus->defer_msg.msg->buf);
+                       kfree(bus->defer_msg.msg);
+               }
        }
 
 msg_unlock:
index 681d090..9cfa15e 100644 (file)
@@ -1295,7 +1295,7 @@ static const struct of_device_id bcm_qspi_of_match[] = {
        },
        {
                .compatible = "brcm,spi-bcm-qspi",
-               .data = &bcm_qspi_rev_data,
+               .data = &bcm_qspi_no_rev_data,
        },
        {
                .compatible = "brcm,spi-bcm7216-qspi",
index c45d76c..41986ac 100644 (file)
@@ -75,7 +75,7 @@
 #define DRV_NAME       "spi-bcm2835"
 
 /* define polling limits */
-unsigned int polling_limit_us = 30;
+static unsigned int polling_limit_us = 30;
 module_param(polling_limit_us, uint, 0664);
 MODULE_PARM_DESC(polling_limit_us,
                 "time in us to run a transfer in polling mode\n");
index 1c1a9d1..c6795c6 100644 (file)
@@ -907,14 +907,16 @@ static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata,
        struct dma_async_tx_descriptor *tx;
        dma_cookie_t cookie;
        dma_addr_t dma_dst;
+       struct device *ddev;
 
        if (!cqspi->rx_chan || !virt_addr_valid(buf)) {
                memcpy_fromio(buf, cqspi->ahb_base + from, len);
                return 0;
        }
 
-       dma_dst = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
-       if (dma_mapping_error(dev, dma_dst)) {
+       ddev = cqspi->rx_chan->device->dev;
+       dma_dst = dma_map_single(ddev, buf, len, DMA_FROM_DEVICE);
+       if (dma_mapping_error(ddev, dma_dst)) {
                dev_err(dev, "dma mapping failed\n");
                return -ENOMEM;
        }
@@ -948,7 +950,7 @@ static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata,
        }
 
 err_unmap:
-       dma_unmap_single(dev, dma_dst, len, DMA_FROM_DEVICE);
+       dma_unmap_single(ddev, dma_dst, len, DMA_FROM_DEVICE);
 
        return ret;
 }
@@ -1128,8 +1130,17 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi)
        return 0;
 }
 
+static const char *cqspi_get_name(struct spi_mem *mem)
+{
+       struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master);
+       struct device *dev = &cqspi->pdev->dev;
+
+       return devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), mem->spi->chip_select);
+}
+
 static const struct spi_controller_mem_ops cqspi_mem_ops = {
        .exec_op = cqspi_exec_mem_op,
+       .get_name = cqspi_get_name,
 };
 
 static int cqspi_setup_flash(struct cqspi_st *cqspi)
index 91c6aff..127323a 100644 (file)
@@ -174,17 +174,17 @@ static const struct fsl_dspi_devtype_data devtype_data[] = {
                .fifo_size              = 16,
        },
        [LS2080A] = {
-               .trans_mode             = DSPI_DMA_MODE,
+               .trans_mode             = DSPI_XSPI_MODE,
                .max_clock_factor       = 8,
                .fifo_size              = 4,
        },
        [LS2085A] = {
-               .trans_mode             = DSPI_DMA_MODE,
+               .trans_mode             = DSPI_XSPI_MODE,
                .max_clock_factor       = 8,
                .fifo_size              = 4,
        },
        [LX2160A] = {
-               .trans_mode             = DSPI_DMA_MODE,
+               .trans_mode             = DSPI_XSPI_MODE,
                .max_clock_factor       = 8,
                .fifo_size              = 4,
        },
@@ -1273,11 +1273,14 @@ static int dspi_probe(struct platform_device *pdev)
        void __iomem *base;
        bool big_endian;
 
-       ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi));
+       dspi = devm_kzalloc(&pdev->dev, sizeof(*dspi), GFP_KERNEL);
+       if (!dspi)
+               return -ENOMEM;
+
+       ctlr = spi_alloc_master(&pdev->dev, 0);
        if (!ctlr)
                return -ENOMEM;
 
-       dspi = spi_controller_get_devdata(ctlr);
        dspi->pdev = pdev;
        dspi->ctlr = ctlr;
 
@@ -1414,7 +1417,7 @@ poll_mode:
        if (dspi->devtype_data->trans_mode != DSPI_DMA_MODE)
                ctlr->ptp_sts_supported = true;
 
-       platform_set_drvdata(pdev, ctlr);
+       platform_set_drvdata(pdev, dspi);
 
        ret = spi_register_controller(ctlr);
        if (ret != 0) {
@@ -1437,8 +1440,7 @@ out_ctlr_put:
 
 static int dspi_remove(struct platform_device *pdev)
 {
-       struct spi_controller *ctlr = platform_get_drvdata(pdev);
-       struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
+       struct fsl_dspi *dspi = platform_get_drvdata(pdev);
 
        /* Disconnect from the SPI framework */
        spi_unregister_controller(dspi->ctlr);
index e605812..6d148ab 100644 (file)
@@ -564,13 +564,14 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
 static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
 {
        struct fsl_espi *espi = context_data;
-       u32 events;
+       u32 events, mask;
 
        spin_lock(&espi->lock);
 
        /* Get interrupt events(tx/rx) */
        events = fsl_espi_read_reg(espi, ESPI_SPIE);
-       if (!events) {
+       mask = fsl_espi_read_reg(espi, ESPI_SPIM);
+       if (!(events & mask)) {
                spin_unlock(&espi->lock);
                return IRQ_NONE;
        }
index 9522d1b..df981e5 100644 (file)
@@ -90,7 +90,7 @@ static struct spi_test spi_tests[] = {
        {
                .description    = "tx/rx-transfer - crossing PAGE_SIZE",
                .fill_option    = FILL_COUNT_8,
-               .iterate_len    = { ITERATE_MAX_LEN },
+               .iterate_len    = { ITERATE_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_rx_align = ITERATE_ALIGN,
                .transfer_count = 1,
index d4b33b3..3056428 100644 (file)
@@ -936,7 +936,11 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
        }
 
        if (sr & STM32H7_SPI_SR_SUSP) {
-               dev_warn(spi->dev, "Communication suspended\n");
+               static DEFINE_RATELIMIT_STATE(rs,
+                                             DEFAULT_RATELIMIT_INTERVAL * 10,
+                                             1);
+               if (__ratelimit(&rs))
+                       dev_dbg_ratelimited(spi->dev, "Communication suspended\n");
                if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0)))
                        stm32h7_spi_read_rxfifo(spi, false);
                /*
@@ -2060,7 +2064,7 @@ static int stm32_spi_resume(struct device *dev)
        }
 
        ret = pm_runtime_get_sync(dev);
-       if (ret) {
+       if (ret < 0) {
                dev_err(dev, "Unable to power device:%d\n", ret);
                return ret;
        }
index dc12af0..0cab239 100644 (file)
@@ -1327,8 +1327,6 @@ out:
        if (msg->status && ctlr->handle_err)
                ctlr->handle_err(ctlr, msg);
 
-       spi_res_release(ctlr, msg);
-
        spi_finalize_current_message(ctlr);
 
        return ret;
@@ -1725,6 +1723,13 @@ void spi_finalize_current_message(struct spi_controller *ctlr)
 
        spi_unmap_msg(ctlr, mesg);
 
+       /* In the prepare_messages callback the spi bus has the opportunity to
+        * split a transfer to smaller chunks.
+        * Release splited transfers here since spi_map_msg is done on the
+        * splited transfers.
+        */
+       spi_res_release(ctlr, mesg);
+
        if (ctlr->cur_msg_prepared && ctlr->unprepare_message) {
                ret = ctlr->unprepare_message(ctlr, mesg);
                if (ret) {
index 8b100a7..237531b 100644 (file)
@@ -173,8 +173,7 @@ static int gbaudio_remove_controls(struct snd_card *card, struct device *dev,
                id.index = control->index;
                kctl = snd_ctl_find_id(card, &id);
                if (!kctl) {
-                       dev_err(dev, "%d: Failed to find %s\n", err,
-                               control->name);
+                       dev_err(dev, "Failed to find %s\n", control->name);
                        continue;
                }
                err = snd_ctl_remove(card, kctl);
index 2f9fdbd..83b38ae 100644 (file)
@@ -456,6 +456,15 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol,
        val = ucontrol->value.integer.value[0] & mask;
        connect = !!val;
 
+       ret = gb_pm_runtime_get_sync(bundle);
+       if (ret)
+               return ret;
+
+       ret = gb_audio_gb_get_control(module->mgmt_connection, data->ctl_id,
+                                     GB_AUDIO_INVALID_INDEX, &gbvalue);
+       if (ret)
+               goto exit;
+
        /* update ucontrol */
        if (gbvalue.value.integer_value[0] != val) {
                for (wi = 0; wi < wlist->num_widgets; wi++) {
@@ -466,25 +475,17 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol,
                gbvalue.value.integer_value[0] =
                        cpu_to_le32(ucontrol->value.integer.value[0]);
 
-               ret = gb_pm_runtime_get_sync(bundle);
-               if (ret)
-                       return ret;
-
                ret = gb_audio_gb_set_control(module->mgmt_connection,
                                              data->ctl_id,
                                              GB_AUDIO_INVALID_INDEX, &gbvalue);
-
-               gb_pm_runtime_put_autosuspend(bundle);
-
-               if (ret) {
-                       dev_err_ratelimited(codec_dev,
-                                           "%d:Error in %s for %s\n", ret,
-                                           __func__, kcontrol->id.name);
-                       return ret;
-               }
        }
 
-       return 0;
+exit:
+       gb_pm_runtime_put_autosuspend(bundle);
+       if (ret)
+               dev_err_ratelimited(codec_dev, "%d:Error in %s for %s\n", ret,
+                                   __func__, kcontrol->id.name);
+       return ret;
 }
 
 #define SOC_DAPM_MIXER_GB(xname, kcount, data) \
index fa1bf8b..2720f73 100644 (file)
@@ -524,13 +524,8 @@ static void hfa384x_usb_defer(struct work_struct *data)
  */
 void hfa384x_create(struct hfa384x *hw, struct usb_device *usb)
 {
-       memset(hw, 0, sizeof(*hw));
        hw->usb = usb;
 
-       /* set up the endpoints */
-       hw->endp_in = usb_rcvbulkpipe(usb, 1);
-       hw->endp_out = usb_sndbulkpipe(usb, 2);
-
        /* Set up the waitq */
        init_waitqueue_head(&hw->cmdq);
 
index 456603f..4b08dc1 100644 (file)
@@ -61,23 +61,14 @@ static int prism2sta_probe_usb(struct usb_interface *interface,
                               const struct usb_device_id *id)
 {
        struct usb_device *dev;
-       const struct usb_endpoint_descriptor *epd;
-       const struct usb_host_interface *iface_desc = interface->cur_altsetting;
+       struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+       struct usb_host_interface *iface_desc = interface->cur_altsetting;
        struct wlandevice *wlandev = NULL;
        struct hfa384x *hw = NULL;
        int result = 0;
 
-       if (iface_desc->desc.bNumEndpoints != 2) {
-               result = -ENODEV;
-               goto failed;
-       }
-
-       result = -EINVAL;
-       epd = &iface_desc->endpoint[1].desc;
-       if (!usb_endpoint_is_bulk_in(epd))
-               goto failed;
-       epd = &iface_desc->endpoint[2].desc;
-       if (!usb_endpoint_is_bulk_out(epd))
+       result = usb_find_common_endpoints(iface_desc, &bulk_in, &bulk_out, NULL, NULL);
+       if (result)
                goto failed;
 
        dev = interface_to_usbdev(interface);
@@ -96,6 +87,8 @@ static int prism2sta_probe_usb(struct usb_interface *interface,
        }
 
        /* Initialize the hw data */
+       hw->endp_in = usb_rcvbulkpipe(dev, bulk_in->bEndpointAddress);
+       hw->endp_out = usb_sndbulkpipe(dev, bulk_out->bEndpointAddress);
        hfa384x_create(hw, dev);
        hw->wlandev = wlandev;
 
index cd045dc..7b56fe9 100644 (file)
@@ -1389,14 +1389,27 @@ static u32 iscsit_do_crypto_hash_sg(
        sg = cmd->first_data_sg;
        page_off = cmd->first_data_sg_off;
 
+       if (data_length && page_off) {
+               struct scatterlist first_sg;
+               u32 len = min_t(u32, data_length, sg->length - page_off);
+
+               sg_init_table(&first_sg, 1);
+               sg_set_page(&first_sg, sg_page(sg), len, sg->offset + page_off);
+
+               ahash_request_set_crypt(hash, &first_sg, NULL, len);
+               crypto_ahash_update(hash);
+
+               data_length -= len;
+               sg = sg_next(sg);
+       }
+
        while (data_length) {
-               u32 cur_len = min_t(u32, data_length, (sg->length - page_off));
+               u32 cur_len = min_t(u32, data_length, sg->length);
 
                ahash_request_set_crypt(hash, sg, NULL, cur_len);
                crypto_ahash_update(hash);
 
                data_length -= cur_len;
-               page_off = 0;
                /* iscsit_map_iovec has already checked for invalid sg pointers */
                sg = sg_next(sg);
        }
index 85748e3..893d1b4 100644 (file)
@@ -1149,7 +1149,7 @@ void iscsit_free_conn(struct iscsi_conn *conn)
 }
 
 void iscsi_target_login_sess_out(struct iscsi_conn *conn,
-               struct iscsi_np *np, bool zero_tsih, bool new_sess)
+                                bool zero_tsih, bool new_sess)
 {
        if (!new_sess)
                goto old_sess_out;
@@ -1167,7 +1167,6 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn,
        conn->sess = NULL;
 
 old_sess_out:
-       iscsi_stop_login_thread_timer(np);
        /*
         * If login negotiation fails check if the Time2Retain timer
         * needs to be restarted.
@@ -1407,8 +1406,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
 new_sess_out:
        new_sess = true;
 old_sess_out:
+       iscsi_stop_login_thread_timer(np);
        tpg_np = conn->tpg_np;
-       iscsi_target_login_sess_out(conn, np, zero_tsih, new_sess);
+       iscsi_target_login_sess_out(conn, zero_tsih, new_sess);
        new_sess = false;
 
        if (tpg) {
index 3b8e363..fc95e61 100644 (file)
@@ -22,8 +22,7 @@ extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
 extern void iscsit_free_conn(struct iscsi_conn *);
 extern int iscsit_start_kthreads(struct iscsi_conn *);
 extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
-extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
-                               bool, bool);
+extern void iscsi_target_login_sess_out(struct iscsi_conn *, bool, bool);
 extern int iscsi_target_login_thread(void *);
 extern void iscsi_handle_login_thread_timeout(struct timer_list *t);
 
index f88a52f..8b40f10 100644 (file)
@@ -535,12 +535,11 @@ static bool iscsi_target_sk_check_and_clear(struct iscsi_conn *conn, unsigned in
 
 static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login)
 {
-       struct iscsi_np *np = login->np;
        bool zero_tsih = login->zero_tsih;
 
        iscsi_remove_failed_auth_entry(conn);
        iscsi_target_nego_release(conn);
-       iscsi_target_login_sess_out(conn, np, zero_tsih, true);
+       iscsi_target_login_sess_out(conn, zero_tsih, true);
 }
 
 struct conn_timeout {
index 590eac2..ff26ab0 100644 (file)
@@ -1840,7 +1840,8 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
         * out unpacked_lun for the original se_cmd.
         */
        if (tm_type == TMR_ABORT_TASK && (flags & TARGET_SCF_LOOKUP_LUN_FROM_TAG)) {
-               if (!target_lookup_lun_from_tag(se_sess, tag, &unpacked_lun))
+               if (!target_lookup_lun_from_tag(se_sess, tag,
+                                               &se_cmd->orig_fe_lun))
                        goto failure;
        }
 
index 3ebca44..0c8471b 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/crc32.h>
+#include <linux/delay.h>
 #include <linux/property.h>
 #include <linux/slab.h>
 #include "tb.h"
@@ -389,8 +390,8 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
                struct tb_drom_entry_header *entry = (void *) (sw->drom + pos);
                if (pos + 1 == drom_size || pos + entry->len > drom_size
                                || !entry->len) {
-                       tb_sw_warn(sw, "drom buffer overrun, aborting\n");
-                       return -EIO;
+                       tb_sw_warn(sw, "DROM buffer overrun\n");
+                       return -EILSEQ;
                }
 
                switch (entry->type) {
@@ -526,7 +527,8 @@ int tb_drom_read(struct tb_switch *sw)
        u16 size;
        u32 crc;
        struct tb_drom_header *header;
-       int res;
+       int res, retries = 1;
+
        if (sw->drom)
                return 0;
 
@@ -612,7 +614,17 @@ parse:
                tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n",
                        header->device_rom_revision);
 
-       return tb_drom_parse_entries(sw);
+       res = tb_drom_parse_entries(sw);
+       /* If the DROM parsing fails, wait a moment and retry once */
+       if (res == -EILSEQ && retries--) {
+               tb_sw_warn(sw, "parsing DROM failed, retrying\n");
+               msleep(100);
+               res = tb_drom_read_n(sw, 0, sw->drom, size);
+               if (!res)
+                       goto parse;
+       }
+
+       return res;
 err:
        kfree(sw->drom);
        sw->drom = NULL;
index 3845db5..a921de9 100644 (file)
@@ -684,6 +684,7 @@ static int tb_init_port(struct tb_port *port)
                if (res == -ENODEV) {
                        tb_dbg(port->sw->tb, " Port %d: not implemented\n",
                               port->port);
+                       port->disabled = true;
                        return 0;
                }
                return res;
index a413d55..3c620a9 100644 (file)
@@ -186,7 +186,7 @@ struct tb_switch {
  * @cap_adap: Offset of the adapter specific capability (%0 if not present)
  * @cap_usb4: Offset to the USB4 port capability (%0 if not present)
  * @port: Port number on switch
- * @disabled: Disabled by eeprom
+ * @disabled: Disabled by eeprom or enabled but not implemented
  * @bonded: true if the port is bonded (two lanes combined as one)
  * @dual_link_port: If the switch is connected using two ports, points
  *                 to the other port.
index 1a7e849..829b6cc 100644 (file)
@@ -951,10 +951,18 @@ static void tb_usb3_reclaim_available_bandwidth(struct tb_tunnel *tunnel,
        int ret, max_rate, allocate_up, allocate_down;
 
        ret = usb4_usb3_port_actual_link_rate(tunnel->src_port);
-       if (ret <= 0) {
-               tb_tunnel_warn(tunnel, "tunnel is not up\n");
+       if (ret < 0) {
+               tb_tunnel_warn(tunnel, "failed to read actual link rate\n");
                return;
+       } else if (!ret) {
+               /* Use maximum link rate if the link valid is not set */
+               ret = usb4_usb3_port_max_link_rate(tunnel->src_port);
+               if (ret < 0) {
+                       tb_tunnel_warn(tunnel, "failed to read maximum link rate\n");
+                       return;
+               }
        }
+
        /*
         * 90% of the max rate can be allocated for isochronous
         * transfers.
index 3eb2d48..55bb7b8 100644 (file)
@@ -5566,6 +5566,17 @@ static const struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID,
                0, 0, pbn_wch384_4 },
 
+       /*
+        * Realtek RealManage
+        */
+       {       PCI_VENDOR_ID_REALTEK, 0x816a,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_b0_1_115200 },
+
+       {       PCI_VENDOR_ID_REALTEK, 0x816b,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_b0_1_115200 },
+
        /* Fintek PCI serial cards */
        { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
        { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
index f797c97..124524e 100644 (file)
@@ -1916,24 +1916,12 @@ static inline bool uart_console_enabled(struct uart_port *port)
        return uart_console(port) && (port->cons->flags & CON_ENABLED);
 }
 
-static void __uart_port_spin_lock_init(struct uart_port *port)
+static void uart_port_spin_lock_init(struct uart_port *port)
 {
        spin_lock_init(&port->lock);
        lockdep_set_class(&port->lock, &port_lock_key);
 }
 
-/*
- * Ensure that the serial console lock is initialised early.
- * If this port is a console, then the spinlock is already initialised.
- */
-static inline void uart_port_spin_lock_init(struct uart_port *port)
-{
-       if (uart_console(port))
-               return;
-
-       __uart_port_spin_lock_init(port);
-}
-
 #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
 /**
  *     uart_console_write - write a console message to a serial port
@@ -2086,7 +2074,15 @@ uart_set_options(struct uart_port *port, struct console *co,
        struct ktermios termios;
        static struct ktermios dummy;
 
-       uart_port_spin_lock_init(port);
+       /*
+        * Ensure that the serial-console lock is initialised early.
+        *
+        * Note that the console-enabled check is needed because of kgdboc,
+        * which can end up calling uart_set_options() for an already enabled
+        * console via tty_find_polling_driver() and uart_poll_init().
+        */
+       if (!uart_console_enabled(port) && !port->console_reinit)
+               uart_port_spin_lock_init(port);
 
        memset(&termios, 0, sizeof(struct ktermios));
 
@@ -2379,13 +2375,6 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
                uart_change_pm(state, UART_PM_STATE_ON);
 
                /*
-                * If this driver supports console, and it hasn't been
-                * successfully registered yet, initialise spin lock for it.
-                */
-               if (port->cons && !(port->cons->flags & CON_ENABLED))
-                       __uart_port_spin_lock_init(port);
-
-               /*
                 * Ensure that the modem control lines are de-activated.
                 * keep the DTR setting that is set in uart_set_options()
                 * We probably don't need a spinlock around this, but
@@ -2801,10 +2790,12 @@ static ssize_t console_store(struct device *dev,
                if (oldconsole && !newconsole) {
                        ret = unregister_console(uport->cons);
                } else if (!oldconsole && newconsole) {
-                       if (uart_console(uport))
+                       if (uart_console(uport)) {
+                               uport->console_reinit = 1;
                                register_console(uport->cons);
-                       else
+                       } else {
                                ret = -ENOENT;
+                       }
                }
        } else {
                ret = -ENXIO;
@@ -2900,7 +2891,12 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
                goto out;
        }
 
-       uart_port_spin_lock_init(uport);
+       /*
+        * If this port is in use as a console then the spinlock is already
+        * initialised.
+        */
+       if (!uart_console_enabled(uport))
+               uart_port_spin_lock_init(uport);
 
        if (uport->cons && uport->dev)
                of_console_check(uport->dev->of_node, uport->cons->name, uport->line);
index 084c48c..67cbd42 100644 (file)
@@ -827,6 +827,11 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, lo
        if (rv < 0)
                return rv;
 
+       if (!usblp->present) {
+               count = -ENODEV;
+               goto done;
+       }
+
        if ((avail = usblp->rstatus) < 0) {
                printk(KERN_ERR "usblp%d: error %d reading from printer\n",
                    usblp->minor, (int)avail);
index 7e73e98..b351962 100644 (file)
@@ -269,8 +269,30 @@ static int usb_probe_device(struct device *dev)
        if (error)
                return error;
 
+       /* Probe the USB device with the driver in hand, but only
+        * defer to a generic driver in case the current USB
+        * device driver has an id_table or a match function; i.e.,
+        * when the device driver was explicitly matched against
+        * a device.
+        *
+        * If the device driver does not have either of these,
+        * then we assume that it can bind to any device and is
+        * not truly a more specialized/non-generic driver, so a
+        * return value of -ENODEV should not force the device
+        * to be handled by the generic USB driver, as there
+        * can still be another, more specialized, device driver.
+        *
+        * This accommodates the usbip driver.
+        *
+        * TODO: What if, in the future, there are multiple
+        * specialized USB device drivers for a particular device?
+        * In such cases, there is a need to try all matching
+        * specialised device drivers prior to setting the
+        * use_generic_driver bit.
+        */
        error = udriver->probe(udev);
-       if (error == -ENODEV && udriver != &usb_generic_driver) {
+       if (error == -ENODEV && udriver != &usb_generic_driver &&
+           (udriver->id_table || udriver->match)) {
                udev->use_generic_driver = 1;
                return -EPROBE_DEFER;
        }
@@ -831,14 +853,17 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
                udev = to_usb_device(dev);
                udrv = to_usb_device_driver(drv);
 
-               if (udrv->id_table &&
-                   usb_device_match_id(udev, udrv->id_table) != NULL) {
-                       return 1;
-               }
+               if (udrv->id_table)
+                       return usb_device_match_id(udev, udrv->id_table) != NULL;
 
                if (udrv->match)
                        return udrv->match(udev);
-               return 0;
+
+               /* If the device driver under consideration does not have a
+                * id_table or a match function, then let the driver's probe
+                * function decide.
+                */
+               return 1;
 
        } else if (is_usb_interface(dev)) {
                struct usb_interface *intf;
@@ -905,26 +930,19 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
        return 0;
 }
 
-static bool is_dev_usb_generic_driver(struct device *dev)
-{
-       struct usb_device_driver *udd = dev->driver ?
-               to_usb_device_driver(dev->driver) : NULL;
-
-       return udd == &usb_generic_driver;
-}
-
 static int __usb_bus_reprobe_drivers(struct device *dev, void *data)
 {
        struct usb_device_driver *new_udriver = data;
        struct usb_device *udev;
        int ret;
 
-       if (!is_dev_usb_generic_driver(dev))
+       /* Don't reprobe if current driver isn't usb_generic_driver */
+       if (dev->driver != &usb_generic_driver.drvwrap.driver)
                return 0;
 
        udev = to_usb_device(dev);
        if (usb_device_match_id(udev, new_udriver->id_table) == NULL &&
-           (!new_udriver->match || new_udriver->match(udev) != 0))
+           (!new_udriver->match || new_udriver->match(udev) == 0))
                return 0;
 
        ret = device_reprobe(dev);
index 6197938..ae1de9c 100644 (file)
@@ -1205,6 +1205,34 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
        }
 }
 
+/*
+ * usb_disable_device_endpoints -- Disable all endpoints for a device
+ * @dev: the device whose endpoints are being disabled
+ * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
+ */
+static void usb_disable_device_endpoints(struct usb_device *dev, int skip_ep0)
+{
+       struct usb_hcd *hcd = bus_to_hcd(dev->bus);
+       int i;
+
+       if (hcd->driver->check_bandwidth) {
+               /* First pass: Cancel URBs, leave endpoint pointers intact. */
+               for (i = skip_ep0; i < 16; ++i) {
+                       usb_disable_endpoint(dev, i, false);
+                       usb_disable_endpoint(dev, i + USB_DIR_IN, false);
+               }
+               /* Remove endpoints from the host controller internal state */
+               mutex_lock(hcd->bandwidth_mutex);
+               usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+               mutex_unlock(hcd->bandwidth_mutex);
+       }
+       /* Second pass: remove endpoint pointers */
+       for (i = skip_ep0; i < 16; ++i) {
+               usb_disable_endpoint(dev, i, true);
+               usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+       }
+}
+
 /**
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
@@ -1218,7 +1246,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
 void usb_disable_device(struct usb_device *dev, int skip_ep0)
 {
        int i;
-       struct usb_hcd *hcd = bus_to_hcd(dev->bus);
 
        /* getting rid of interfaces will disconnect
         * any drivers bound to them (a key side effect)
@@ -1264,22 +1291,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 
        dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
                skip_ep0 ? "non-ep0" : "all");
-       if (hcd->driver->check_bandwidth) {
-               /* First pass: Cancel URBs, leave endpoint pointers intact. */
-               for (i = skip_ep0; i < 16; ++i) {
-                       usb_disable_endpoint(dev, i, false);
-                       usb_disable_endpoint(dev, i + USB_DIR_IN, false);
-               }
-               /* Remove endpoints from the host controller internal state */
-               mutex_lock(hcd->bandwidth_mutex);
-               usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
-               mutex_unlock(hcd->bandwidth_mutex);
-               /* Second pass: remove endpoint pointers */
-       }
-       for (i = skip_ep0; i < 16; ++i) {
-               usb_disable_endpoint(dev, i, true);
-               usb_disable_endpoint(dev, i + USB_DIR_IN, true);
-       }
+
+       usb_disable_device_endpoints(dev, skip_ep0);
 }
 
 /**
@@ -1522,6 +1535,9 @@ EXPORT_SYMBOL_GPL(usb_set_interface);
  * The caller must own the device lock.
  *
  * Return: Zero on success, else a negative error code.
+ *
+ * If this routine fails the device will probably be in an unusable state
+ * with endpoints disabled, and interfaces only partially enabled.
  */
 int usb_reset_configuration(struct usb_device *dev)
 {
@@ -1537,10 +1553,7 @@ int usb_reset_configuration(struct usb_device *dev)
         * calls during probe() are fine
         */
 
-       for (i = 1; i < 16; ++i) {
-               usb_disable_endpoint(dev, i, true);
-               usb_disable_endpoint(dev, i + USB_DIR_IN, true);
-       }
+       usb_disable_device_endpoints(dev, 1); /* skip ep0*/
 
        config = dev->actconfig;
        retval = 0;
@@ -1553,34 +1566,10 @@ int usb_reset_configuration(struct usb_device *dev)
                mutex_unlock(hcd->bandwidth_mutex);
                return -ENOMEM;
        }
-       /* Make sure we have enough bandwidth for each alternate setting 0 */
-       for (i = 0; i < config->desc.bNumInterfaces; i++) {
-               struct usb_interface *intf = config->interface[i];
-               struct usb_host_interface *alt;
 
-               alt = usb_altnum_to_altsetting(intf, 0);
-               if (!alt)
-                       alt = &intf->altsetting[0];
-               if (alt != intf->cur_altsetting)
-                       retval = usb_hcd_alloc_bandwidth(dev, NULL,
-                                       intf->cur_altsetting, alt);
-               if (retval < 0)
-                       break;
-       }
-       /* If not, reinstate the old alternate settings */
+       /* xHCI adds all endpoints in usb_hcd_alloc_bandwidth */
+       retval = usb_hcd_alloc_bandwidth(dev, config, NULL, NULL);
        if (retval < 0) {
-reset_old_alts:
-               for (i--; i >= 0; i--) {
-                       struct usb_interface *intf = config->interface[i];
-                       struct usb_host_interface *alt;
-
-                       alt = usb_altnum_to_altsetting(intf, 0);
-                       if (!alt)
-                               alt = &intf->altsetting[0];
-                       if (alt != intf->cur_altsetting)
-                               usb_hcd_alloc_bandwidth(dev, NULL,
-                                               alt, intf->cur_altsetting);
-               }
                usb_enable_lpm(dev);
                mutex_unlock(hcd->bandwidth_mutex);
                return retval;
@@ -1589,8 +1578,12 @@ reset_old_alts:
                        USB_REQ_SET_CONFIGURATION, 0,
                        config->desc.bConfigurationValue, 0,
                        NULL, 0, USB_CTRL_SET_TIMEOUT);
-       if (retval < 0)
-               goto reset_old_alts;
+       if (retval < 0) {
+               usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+               usb_enable_lpm(dev);
+               mutex_unlock(hcd->bandwidth_mutex);
+               return retval;
+       }
        mutex_unlock(hcd->bandwidth_mutex);
 
        /* re-init hc/hcd interface/endpoint state */
index f232914..10574fa 100644 (file)
@@ -397,6 +397,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Generic RTL8153 based ethernet adapters */
        { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM },
 
+       /* SONiX USB DEVICE Touchpad */
+       { USB_DEVICE(0x0c45, 0x7056), .driver_info =
+                       USB_QUIRK_IGNORE_REMOTE_WAKEUP },
+
        /* Action Semiconductor flash disk */
        { USB_DEVICE(0x10d6, 0x2200), .driver_info =
                        USB_QUIRK_STRING_FETCH_255 },
index a2ca38e..8d13419 100644 (file)
@@ -889,7 +889,11 @@ read_descriptors(struct file *filp, struct kobject *kobj,
        size_t srclen, n;
        int cfgno;
        void *src;
+       int retval;
 
+       retval = usb_lock_device_interruptible(udev);
+       if (retval < 0)
+               return -EINTR;
        /* The binary attribute begins with the device descriptor.
         * Following that are the raw descriptor entries for all the
         * configurations (config plus subsidiary descriptors).
@@ -914,6 +918,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
                        off -= srclen;
                }
        }
+       usb_unlock_device(udev);
        return count - nleft;
 }
 
index 88b75b5..1f7f4d8 100644 (file)
@@ -737,13 +737,13 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
                goto err_disable_clks;
        }
 
-       ret = reset_control_deassert(priv->reset);
+       ret = reset_control_reset(priv->reset);
        if (ret)
-               goto err_assert_reset;
+               goto err_disable_clks;
 
        ret = dwc3_meson_g12a_get_phys(priv);
        if (ret)
-               goto err_assert_reset;
+               goto err_disable_clks;
 
        ret = priv->drvdata->setup_regmaps(priv, base);
        if (ret)
@@ -752,7 +752,7 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
        if (priv->vbus) {
                ret = regulator_enable(priv->vbus);
                if (ret)
-                       goto err_assert_reset;
+                       goto err_disable_clks;
        }
 
        /* Get dr_mode */
@@ -765,13 +765,13 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
 
        ret = priv->drvdata->usb_init(priv);
        if (ret)
-               goto err_assert_reset;
+               goto err_disable_clks;
 
        /* Init PHYs */
        for (i = 0 ; i < PHY_COUNT ; ++i) {
                ret = phy_init(priv->phys[i]);
                if (ret)
-                       goto err_assert_reset;
+                       goto err_disable_clks;
        }
 
        /* Set PHY Power */
@@ -809,9 +809,6 @@ err_phys_exit:
        for (i = 0 ; i < PHY_COUNT ; ++i)
                phy_exit(priv->phys[i]);
 
-err_assert_reset:
-       reset_control_assert(priv->reset);
-
 err_disable_clks:
        clk_bulk_disable_unprepare(priv->drvdata->num_clks,
                                   priv->drvdata->clks);
index b4206b0..1f63875 100644 (file)
@@ -1189,7 +1189,6 @@ static int ncm_unwrap_ntb(struct gether *port,
        const struct ndp_parser_opts *opts = ncm->parser_opts;
        unsigned        crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
        int             dgram_counter;
-       bool            ndp_after_header;
 
        /* dwSignature */
        if (get_unaligned_le32(tmp) != opts->nth_sign) {
@@ -1216,7 +1215,6 @@ static int ncm_unwrap_ntb(struct gether *port,
        }
 
        ndp_index = get_ncm(&tmp, opts->ndp_index);
-       ndp_after_header = false;
 
        /* Run through all the NDP's in the NTB */
        do {
@@ -1232,8 +1230,6 @@ static int ncm_unwrap_ntb(struct gether *port,
                             ndp_index);
                        goto err;
                }
-               if (ndp_index == opts->nth_size)
-                       ndp_after_header = true;
 
                /*
                 * walk through NDP
@@ -1312,37 +1308,13 @@ static int ncm_unwrap_ntb(struct gether *port,
                        index2 = get_ncm(&tmp, opts->dgram_item_len);
                        dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
 
-                       if (index2 == 0 || dg_len2 == 0)
-                               break;
-
                        /* wDatagramIndex[1] */
-                       if (ndp_after_header) {
-                               if (index2 < opts->nth_size + opts->ndp_size) {
-                                       INFO(port->func.config->cdev,
-                                            "Bad index: %#X\n", index2);
-                                       goto err;
-                               }
-                       } else {
-                               if (index2 < opts->nth_size + opts->dpe_size) {
-                                       INFO(port->func.config->cdev,
-                                            "Bad index: %#X\n", index2);
-                                       goto err;
-                               }
-                       }
                        if (index2 > block_len - opts->dpe_size) {
                                INFO(port->func.config->cdev,
                                     "Bad index: %#X\n", index2);
                                goto err;
                        }
 
-                       /* wDatagramLength[1] */
-                       if ((dg_len2 < 14 + crc_len) ||
-                                       (dg_len2 > frame_max)) {
-                               INFO(port->func.config->cdev,
-                                    "Bad dgram length: %#X\n", dg_len);
-                               goto err;
-                       }
-
                        /*
                         * Copy the data into a new skb.
                         * This ensures the truesize is correct
@@ -1359,6 +1331,8 @@ static int ncm_unwrap_ntb(struct gether *port,
                        ndp_len -= 2 * (opts->dgram_item_len * 2);
 
                        dgram_counter++;
+                       if (index2 == 0 || dg_len2 == 0)
+                               break;
                } while (ndp_len > 2 * (opts->dgram_item_len * 2));
        } while (ndp_index);
 
index 6257be4..3575b72 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
index ce0eaf7..087402a 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 /*-------------------------------------------------------------------------*/
-#include <linux/usb/otg.h>
 
 #define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
index 871cdcc..9823bb4 100644 (file)
@@ -713,6 +713,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_MTIUSBCONVERTER_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
index e837352..b5ca17a 100644 (file)
 #define XSENS_AWINDA_DONGLE_PID 0x0102
 #define XSENS_MTW_PID          0x0200  /* Xsens MTw */
 #define XSENS_MTDEVBOARD_PID   0x0300  /* Motion Tracker Development Board */
+#define XSENS_MTIUSBCONVERTER_PID      0x0301  /* MTi USB converter */
 #define XSENS_CONVERTER_PID    0xD00D  /* Xsens USB-serial converter */
 
 /* Xsens devices using FTDI VID */
index 89b3192..0c6f160 100644 (file)
@@ -1094,14 +1094,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
          .driver_info = RSVD(1) | RSVD(3) },
        /* Quectel products using Quectel vendor ID */
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
-         .driver_info = RSVD(4) },
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
-         .driver_info = RSVD(4) },
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95),
-         .driver_info = RSVD(4) },
-       { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
-         .driver_info = RSVD(4) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0xff, 0xff),
+         .driver_info = NUMEP2 },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
@@ -1819,6 +1823,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9003, 0xff) },   /* Simcom SIM7500/SIM7600 MBIM mode */
        { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9011, 0xff),     /* Simcom SIM7500/SIM7600 RNDIS mode */
          .driver_info = RSVD(7) },
+       { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9205, 0xff) },   /* Simcom SIM7070/SIM7080/SIM7090 AT+ECM mode */
+       { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9206, 0xff) },   /* Simcom SIM7070/SIM7080/SIM7090 AT-only mode */
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) },
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D),
index 08f9296..8183504 100644 (file)
@@ -662,8 +662,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
        if (devinfo->resetting) {
                cmnd->result = DID_ERROR << 16;
                cmnd->scsi_done(cmnd);
-               spin_unlock_irqrestore(&devinfo->lock, flags);
-               return 0;
+               goto zombie;
        }
 
        /* Find a free uas-tag */
@@ -699,6 +698,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
                cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
 
        err = uas_submit_urbs(cmnd, devinfo);
+       /*
+        * in case of fatal errors the SCSI layer is peculiar
+        * a command that has finished is a success for the purpose
+        * of queueing, no matter how fatal the error
+        */
+       if (err == -ENODEV) {
+               cmnd->result = DID_ERROR << 16;
+               cmnd->scsi_done(cmnd);
+               goto zombie;
+       }
        if (err) {
                /* If we did nothing, give up now */
                if (cmdinfo->state & SUBMIT_STATUS_URB) {
@@ -709,6 +718,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
        }
 
        devinfo->cmnd[idx] = cmnd;
+zombie:
        spin_unlock_irqrestore(&devinfo->lock, flags);
        return 0;
 }
index e4021e1..676b525 100644 (file)
@@ -61,14 +61,11 @@ enum {
 
 #define PMC_USB_ALTMODE_ORI_SHIFT      1
 #define PMC_USB_ALTMODE_UFP_SHIFT      3
-#define PMC_USB_ALTMODE_ORI_AUX_SHIFT  4
-#define PMC_USB_ALTMODE_ORI_HSL_SHIFT  5
 
 /* DP specific Mode Data bits */
 #define PMC_USB_ALTMODE_DP_MODE_SHIFT  8
 
 /* TBT specific Mode Data bits */
-#define PMC_USB_ALTMODE_HPD_HIGH       BIT(14)
 #define PMC_USB_ALTMODE_TBT_TYPE       BIT(17)
 #define PMC_USB_ALTMODE_CABLE_TYPE     BIT(18)
 #define PMC_USB_ALTMODE_ACTIVE_LINK    BIT(20)
@@ -128,13 +125,19 @@ static int hsl_orientation(struct pmc_usb_port *port)
 static int pmc_usb_command(struct pmc_usb_port *port, u8 *msg, u32 len)
 {
        u8 response[4];
+       int ret;
 
        /*
         * Error bit will always be 0 with the USBC command.
-        * Status can be checked from the response message.
+        * Status can be checked from the response message if the
+        * function intel_scu_ipc_dev_command succeeds.
         */
-       intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg, len,
-                                 response, sizeof(response));
+       ret = intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg,
+                                       len, response, sizeof(response));
+
+       if (ret)
+               return ret;
+
        if (response[2] & PMC_USB_RESP_STATUS_FAILURE) {
                if (response[2] & PMC_USB_RESP_STATUS_FATAL)
                        return -EIO;
@@ -179,15 +182,9 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
        req.mode_data = (port->orientation - 1) << PMC_USB_ALTMODE_ORI_SHIFT;
        req.mode_data |= (port->role - 1) << PMC_USB_ALTMODE_UFP_SHIFT;
 
-       req.mode_data |= sbu_orientation(port) << PMC_USB_ALTMODE_ORI_AUX_SHIFT;
-       req.mode_data |= hsl_orientation(port) << PMC_USB_ALTMODE_ORI_HSL_SHIFT;
-
        req.mode_data |= (state->mode - TYPEC_STATE_MODAL) <<
                         PMC_USB_ALTMODE_DP_MODE_SHIFT;
 
-       if (data->status & DP_STATUS_HPD_STATE)
-               req.mode_data |= PMC_USB_ALTMODE_HPD_HIGH;
-
        ret = pmc_usb_command(port, (void *)&req, sizeof(req));
        if (ret)
                return ret;
@@ -212,9 +209,6 @@ pmc_usb_mux_tbt(struct pmc_usb_port *port, struct typec_mux_state *state)
        req.mode_data = (port->orientation - 1) << PMC_USB_ALTMODE_ORI_SHIFT;
        req.mode_data |= (port->role - 1) << PMC_USB_ALTMODE_UFP_SHIFT;
 
-       req.mode_data |= sbu_orientation(port) << PMC_USB_ALTMODE_ORI_AUX_SHIFT;
-       req.mode_data |= hsl_orientation(port) << PMC_USB_ALTMODE_ORI_HSL_SHIFT;
-
        if (TBT_ADAPTER(data->device_mode) == TBT_ADAPTER_TBT3)
                req.mode_data |= PMC_USB_ALTMODE_TBT_TYPE;
 
@@ -497,6 +491,7 @@ err_remove_ports:
        for (i = 0; i < pmc->num_ports; i++) {
                typec_switch_unregister(pmc->port[i].typec_sw);
                typec_mux_unregister(pmc->port[i].typec_mux);
+               usb_role_switch_unregister(pmc->port[i].usb_sw);
        }
 
        return ret;
@@ -510,6 +505,7 @@ static int pmc_usb_remove(struct platform_device *pdev)
        for (i = 0; i < pmc->num_ports; i++) {
                typec_switch_unregister(pmc->port[i].typec_sw);
                typec_mux_unregister(pmc->port[i].typec_mux);
+               usb_role_switch_unregister(pmc->port[i].usb_sw);
        }
 
        return 0;
index e680fcf..758b988 100644 (file)
@@ -216,14 +216,18 @@ void ucsi_altmode_update_active(struct ucsi_connector *con)
                                            con->partner_altmode[i] == altmode);
 }
 
-static u8 ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid)
+static int ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid)
 {
        u8 mode = 1;
        int i;
 
-       for (i = 0; alt[i]; i++)
+       for (i = 0; alt[i]; i++) {
+               if (i > MODE_DISCOVERY_MAX)
+                       return -ERANGE;
+
                if (alt[i]->svid == svid)
                        mode++;
+       }
 
        return mode;
 }
@@ -258,8 +262,11 @@ static int ucsi_register_altmode(struct ucsi_connector *con,
                        goto err;
                }
 
-               desc->mode = ucsi_altmode_next_mode(con->port_altmode,
-                                                   desc->svid);
+               ret = ucsi_altmode_next_mode(con->port_altmode, desc->svid);
+               if (ret < 0)
+                       return ret;
+
+               desc->mode = ret;
 
                switch (desc->svid) {
                case USB_TYPEC_DP_SID:
@@ -292,8 +299,11 @@ static int ucsi_register_altmode(struct ucsi_connector *con,
                        goto err;
                }
 
-               desc->mode = ucsi_altmode_next_mode(con->partner_altmode,
-                                                   desc->svid);
+               ret = ucsi_altmode_next_mode(con->partner_altmode, desc->svid);
+               if (ret < 0)
+                       return ret;
+
+               desc->mode = ret;
 
                alt = typec_partner_register_altmode(con->partner, desc);
                if (IS_ERR(alt)) {
index 9fc4f33..fbfe8f5 100644 (file)
@@ -78,7 +78,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
        if (ret)
                goto out_clear_bit;
 
-       if (!wait_for_completion_timeout(&ua->complete, msecs_to_jiffies(5000)))
+       if (!wait_for_completion_timeout(&ua->complete, 60 * HZ))
                ret = -ETIMEDOUT;
 
 out_clear_bit:
@@ -112,11 +112,15 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
 
 static int ucsi_acpi_probe(struct platform_device *pdev)
 {
+       struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
        struct ucsi_acpi *ua;
        struct resource *res;
        acpi_status status;
        int ret;
 
+       if (adev->dep_unmet)
+               return -EPROBE_DEFER;
+
        ua = devm_kzalloc(&pdev->dev, sizeof(*ua), GFP_KERNEL);
        if (!ua)
                return -ENOMEM;
index 9d7d642..2305d42 100644 (file)
@@ -461,11 +461,6 @@ static void stub_disconnect(struct usb_device *udev)
        return;
 }
 
-static bool usbip_match(struct usb_device *udev)
-{
-       return true;
-}
-
 #ifdef CONFIG_PM
 
 /* These functions need usb_port_suspend and usb_port_resume,
@@ -491,7 +486,6 @@ struct usb_device_driver stub_driver = {
        .name           = "usbip-host",
        .probe          = stub_probe,
        .disconnect     = stub_disconnect,
-       .match          = usbip_match,
 #ifdef CONFIG_PM
        .suspend        = stub_suspend,
        .resume         = stub_resume,
index 4271c40..d7d32b6 100644 (file)
@@ -30,9 +30,7 @@ config IFCVF
          be called ifcvf.
 
 config MLX5_VDPA
-       bool "MLX5 VDPA support library for ConnectX devices"
-       depends on MLX5_CORE
-       default n
+       bool
        help
          Support library for Mellanox VDPA drivers. Provides code that is
          common for all types of VDPA drivers. The following drivers are planned:
@@ -40,7 +38,8 @@ config MLX5_VDPA
 
 config MLX5_VDPA_NET
        tristate "vDPA driver for ConnectX devices"
-       depends on MLX5_VDPA
+       select MLX5_VDPA
+       depends on MLX5_CORE
        default n
        help
          VDPA network driver for ConnectX6 and newer. Provides offloading
index 70676a6..74264e5 100644 (file)
@@ -1133,15 +1133,17 @@ static void suspend_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *m
        if (!mvq->initialized)
                return;
 
-       if (query_virtqueue(ndev, mvq, &attr)) {
-               mlx5_vdpa_warn(&ndev->mvdev, "failed to query virtqueue\n");
-               return;
-       }
        if (mvq->fw_state != MLX5_VIRTIO_NET_Q_OBJECT_STATE_RDY)
                return;
 
        if (modify_virtqueue(ndev, mvq, MLX5_VIRTIO_NET_Q_OBJECT_STATE_SUSPEND))
                mlx5_vdpa_warn(&ndev->mvdev, "modify to suspend failed\n");
+
+       if (query_virtqueue(ndev, mvq, &attr)) {
+               mlx5_vdpa_warn(&ndev->mvdev, "failed to query virtqueue\n");
+               return;
+       }
+       mvq->avail_idx = attr.available_index;
 }
 
 static void suspend_vqs(struct mlx5_vdpa_net *ndev)
@@ -1411,8 +1413,14 @@ static int mlx5_vdpa_get_vq_state(struct vdpa_device *vdev, u16 idx, struct vdpa
        struct mlx5_virtq_attr attr;
        int err;
 
-       if (!mvq->initialized)
-               return -EAGAIN;
+       /* If the virtq object was destroyed, use the value saved at
+        * the last minute of suspend_vq. This caters for userspace
+        * that cares about emulating the index after vq is stopped.
+        */
+       if (!mvq->initialized) {
+               state->avail_index = mvq->avail_idx;
+               return 0;
+       }
 
        err = query_virtqueue(ndev, mvq, &attr);
        if (err) {
index 34aec4b..0fd3f87 100644 (file)
@@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(vhost_iotlb_free);
  * vhost_iotlb_itree_first - return the first overlapped range
  * @iotlb: the IOTLB
  * @start: start of IOVA range
- * @end: end of IOVA range
+ * @last: last byte in IOVA range
  */
 struct vhost_iotlb_map *
 vhost_iotlb_itree_first(struct vhost_iotlb *iotlb, u64 start, u64 last)
@@ -162,7 +162,7 @@ EXPORT_SYMBOL_GPL(vhost_iotlb_itree_first);
  * vhost_iotlb_itree_next - return the next overlapped range
  * @map: the starting map node
  * @start: start of IOVA range
- * @end: end of IOVA range
+ * @last: last byte IOVA range
  */
 struct vhost_iotlb_map *
 vhost_iotlb_itree_next(struct vhost_iotlb_map *map, u64 start, u64 last)
index 3fab94f..62a9bb0 100644 (file)
@@ -353,8 +353,6 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
        struct vdpa_callback cb;
        struct vhost_virtqueue *vq;
        struct vhost_vring_state s;
-       u64 __user *featurep = argp;
-       u64 features;
        u32 idx;
        long r;
 
@@ -381,18 +379,6 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
 
                vq->last_avail_idx = vq_state.avail_index;
                break;
-       case VHOST_GET_BACKEND_FEATURES:
-               features = VHOST_VDPA_BACKEND_FEATURES;
-               if (copy_to_user(featurep, &features, sizeof(features)))
-                       return -EFAULT;
-               return 0;
-       case VHOST_SET_BACKEND_FEATURES:
-               if (copy_from_user(&features, featurep, sizeof(features)))
-                       return -EFAULT;
-               if (features & ~VHOST_VDPA_BACKEND_FEATURES)
-                       return -EOPNOTSUPP;
-               vhost_set_backend_features(&v->vdev, features);
-               return 0;
        }
 
        r = vhost_vring_ioctl(&v->vdev, cmd, argp);
@@ -440,8 +426,20 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
        struct vhost_vdpa *v = filep->private_data;
        struct vhost_dev *d = &v->vdev;
        void __user *argp = (void __user *)arg;
+       u64 __user *featurep = argp;
+       u64 features;
        long r;
 
+       if (cmd == VHOST_SET_BACKEND_FEATURES) {
+               r = copy_from_user(&features, featurep, sizeof(features));
+               if (r)
+                       return r;
+               if (features & ~VHOST_VDPA_BACKEND_FEATURES)
+                       return -EOPNOTSUPP;
+               vhost_set_backend_features(&v->vdev, features);
+               return 0;
+       }
+
        mutex_lock(&d->mutex);
 
        switch (cmd) {
@@ -476,6 +474,10 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
        case VHOST_VDPA_SET_CONFIG_CALL:
                r = vhost_vdpa_set_config_call(v, argp);
                break;
+       case VHOST_GET_BACKEND_FEATURES:
+               features = VHOST_VDPA_BACKEND_FEATURES;
+               r = copy_to_user(featurep, &features, sizeof(features));
+               break;
        default:
                r = vhost_dev_ioctl(&v->vdev, cmd, argp);
                if (r == -ENOIOCTLCMD)
@@ -563,6 +565,9 @@ static int vhost_vdpa_map(struct vhost_vdpa *v,
                              perm_to_iommu_flags(perm));
        }
 
+       if (r)
+               vhost_iotlb_del_range(dev->iotlb, iova, iova + size - 1);
+
        return r;
 }
 
@@ -590,21 +595,19 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
        struct vhost_dev *dev = &v->vdev;
        struct vhost_iotlb *iotlb = dev->iotlb;
        struct page **page_list;
-       unsigned long list_size = PAGE_SIZE / sizeof(struct page *);
+       struct vm_area_struct **vmas;
        unsigned int gup_flags = FOLL_LONGTERM;
-       unsigned long npages, cur_base, map_pfn, last_pfn = 0;
-       unsigned long locked, lock_limit, pinned, i;
+       unsigned long map_pfn, last_pfn = 0;
+       unsigned long npages, lock_limit;
+       unsigned long i, nmap = 0;
        u64 iova = msg->iova;
+       long pinned;
        int ret = 0;
 
        if (vhost_iotlb_itree_first(iotlb, msg->iova,
                                    msg->iova + msg->size - 1))
                return -EEXIST;
 
-       page_list = (struct page **) __get_free_page(GFP_KERNEL);
-       if (!page_list)
-               return -ENOMEM;
-
        if (msg->perm & VHOST_ACCESS_WO)
                gup_flags |= FOLL_WRITE;
 
@@ -612,61 +615,86 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
        if (!npages)
                return -EINVAL;
 
+       page_list = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
+       vmas = kvmalloc_array(npages, sizeof(struct vm_area_struct *),
+                             GFP_KERNEL);
+       if (!page_list || !vmas) {
+               ret = -ENOMEM;
+               goto free;
+       }
+
        mmap_read_lock(dev->mm);
 
-       locked = atomic64_add_return(npages, &dev->mm->pinned_vm);
        lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
-
-       if (locked > lock_limit) {
+       if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) {
                ret = -ENOMEM;
-               goto out;
+               goto unlock;
        }
 
-       cur_base = msg->uaddr & PAGE_MASK;
-       iova &= PAGE_MASK;
+       pinned = pin_user_pages(msg->uaddr & PAGE_MASK, npages, gup_flags,
+                               page_list, vmas);
+       if (npages != pinned) {
+               if (pinned < 0) {
+                       ret = pinned;
+               } else {
+                       unpin_user_pages(page_list, pinned);
+                       ret = -ENOMEM;
+               }
+               goto unlock;
+       }
 
-       while (npages) {
-               pinned = min_t(unsigned long, npages, list_size);
-               ret = pin_user_pages(cur_base, pinned,
-                                    gup_flags, page_list, NULL);
-               if (ret != pinned)
-                       goto out;
-
-               if (!last_pfn)
-                       map_pfn = page_to_pfn(page_list[0]);
-
-               for (i = 0; i < ret; i++) {
-                       unsigned long this_pfn = page_to_pfn(page_list[i]);
-                       u64 csize;
-
-                       if (last_pfn && (this_pfn != last_pfn + 1)) {
-                               /* Pin a contiguous chunk of memory */
-                               csize = (last_pfn - map_pfn + 1) << PAGE_SHIFT;
-                               if (vhost_vdpa_map(v, iova, csize,
-                                                  map_pfn << PAGE_SHIFT,
-                                                  msg->perm))
-                                       goto out;
-                               map_pfn = this_pfn;
-                               iova += csize;
+       iova &= PAGE_MASK;
+       map_pfn = page_to_pfn(page_list[0]);
+
+       /* One more iteration to avoid extra vdpa_map() call out of loop. */
+       for (i = 0; i <= npages; i++) {
+               unsigned long this_pfn;
+               u64 csize;
+
+               /* The last chunk may have no valid PFN next to it */
+               this_pfn = i < npages ? page_to_pfn(page_list[i]) : -1UL;
+
+               if (last_pfn && (this_pfn == -1UL ||
+                                this_pfn != last_pfn + 1)) {
+                       /* Pin a contiguous chunk of memory */
+                       csize = last_pfn - map_pfn + 1;
+                       ret = vhost_vdpa_map(v, iova, csize << PAGE_SHIFT,
+                                            map_pfn << PAGE_SHIFT,
+                                            msg->perm);
+                       if (ret) {
+                               /*
+                                * Unpin the rest chunks of memory on the
+                                * flight with no corresponding vdpa_map()
+                                * calls having been made yet. On the other
+                                * hand, vdpa_unmap() in the failure path
+                                * is in charge of accounting the number of
+                                * pinned pages for its own.
+                                * This asymmetrical pattern of accounting
+                                * is for efficiency to pin all pages at
+                                * once, while there is no other callsite
+                                * of vdpa_map() than here above.
+                                */
+                               unpin_user_pages(&page_list[nmap],
+                                                npages - nmap);
+                               goto out;
                        }
-
-                       last_pfn = this_pfn;
+                       atomic64_add(csize, &dev->mm->pinned_vm);
+                       nmap += csize;
+                       iova += csize << PAGE_SHIFT;
+                       map_pfn = this_pfn;
                }
-
-               cur_base += ret << PAGE_SHIFT;
-               npages -= ret;
+               last_pfn = this_pfn;
        }
 
-       /* Pin the rest chunk */
-       ret = vhost_vdpa_map(v, iova, (last_pfn - map_pfn + 1) << PAGE_SHIFT,
-                            map_pfn << PAGE_SHIFT, msg->perm);
+       WARN_ON(nmap != npages);
 out:
-       if (ret) {
+       if (ret)
                vhost_vdpa_unmap(v, msg->iova, msg->size);
-               atomic64_sub(npages, &dev->mm->pinned_vm);
-       }
+unlock:
        mmap_read_unlock(dev->mm);
-       free_page((unsigned long)page_list);
+free:
+       kvfree(vmas);
+       kvfree(page_list);
        return ret;
 }
 
@@ -808,6 +836,7 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
 
 err_init_iotlb:
        vhost_dev_cleanup(&v->vdev);
+       kfree(vqs);
 err:
        atomic_dec(&v->opened);
        return r;
index b45519c..9ad45e1 100644 (file)
@@ -1290,6 +1290,11 @@ static bool vq_access_ok(struct vhost_virtqueue *vq, unsigned int num,
                         vring_used_t __user *used)
 
 {
+       /* If an IOTLB device is present, the vring addresses are
+        * GIOVAs. Access validation occurs at prefetch time. */
+       if (vq->iotlb)
+               return true;
+
        return access_ok(desc, vhost_get_desc_size(vq, num)) &&
               access_ok(avail, vhost_get_avail_size(vq, num)) &&
               access_ok(used, vhost_get_used_size(vq, num));
@@ -1365,6 +1370,20 @@ bool vhost_log_access_ok(struct vhost_dev *dev)
 }
 EXPORT_SYMBOL_GPL(vhost_log_access_ok);
 
+static bool vq_log_used_access_ok(struct vhost_virtqueue *vq,
+                                 void __user *log_base,
+                                 bool log_used,
+                                 u64 log_addr)
+{
+       /* If an IOTLB device is present, log_addr is a GIOVA that
+        * will never be logged by log_used(). */
+       if (vq->iotlb)
+               return true;
+
+       return !log_used || log_access_ok(log_base, log_addr,
+                                         vhost_get_used_size(vq, vq->num));
+}
+
 /* Verify access for write logging. */
 /* Caller should have vq mutex and device mutex */
 static bool vq_log_access_ok(struct vhost_virtqueue *vq,
@@ -1372,8 +1391,7 @@ static bool vq_log_access_ok(struct vhost_virtqueue *vq,
 {
        return vq_memory_access_ok(log_base, vq->umem,
                                   vhost_has_feature(vq, VHOST_F_LOG_ALL)) &&
-               (!vq->log_used || log_access_ok(log_base, vq->log_addr,
-                                 vhost_get_used_size(vq, vq->num)));
+               vq_log_used_access_ok(vq, log_base, vq->log_used, vq->log_addr);
 }
 
 /* Can we start vq? */
@@ -1383,10 +1401,6 @@ bool vhost_vq_access_ok(struct vhost_virtqueue *vq)
        if (!vq_log_access_ok(vq, vq->log_base))
                return false;
 
-       /* Access validation occurs at prefetch time with IOTLB */
-       if (vq->iotlb)
-               return true;
-
        return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used);
 }
 EXPORT_SYMBOL_GPL(vhost_vq_access_ok);
@@ -1516,10 +1530,9 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
                        return -EINVAL;
 
                /* Also validate log access for used ring if enabled. */
-               if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
-                       !log_access_ok(vq->log_base, a.log_guest_addr,
-                               sizeof *vq->used +
-                               vq->num * sizeof *vq->used->ring))
+               if (!vq_log_used_access_ok(vq, vq->log_base,
+                               a.flags & (0x1 << VHOST_VRING_F_LOG),
+                               a.log_guest_addr))
                        return -EINVAL;
        }
 
index 5e850cc..39deb22 100644 (file)
@@ -22,52 +22,6 @@ config VGA_CONSOLE
 
          Say Y.
 
-config VGACON_SOFT_SCROLLBACK
-       bool "Enable Scrollback Buffer in System RAM"
-       depends on VGA_CONSOLE
-       default n
-       help
-        The scrollback buffer of the standard VGA console is located in
-        the VGA RAM.  The size of this RAM is fixed and is quite small.
-        If you require a larger scrollback buffer, this can be placed in
-        System RAM which is dynamically allocated during initialization.
-        Placing the scrollback buffer in System RAM will slightly slow
-        down the console.
-
-        If you want this feature, say 'Y' here and enter the amount of
-        RAM to allocate for this buffer.  If unsure, say 'N'.
-
-config VGACON_SOFT_SCROLLBACK_SIZE
-       int "Scrollback Buffer Size (in KB)"
-       depends on VGACON_SOFT_SCROLLBACK
-       range 1 1024
-       default "64"
-       help
-         Enter the amount of System RAM to allocate for scrollback
-         buffers of VGA consoles. Each 64KB will give you approximately
-         16 80x25 screenfuls of scrollback buffer.
-
-config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
-       bool "Persistent Scrollback History for each console by default"
-       depends on VGACON_SOFT_SCROLLBACK
-       default n
-       help
-         Say Y here if the scrollback history should persist by default when
-         switching between consoles. Otherwise, the scrollback history will be
-         flushed each time the console is switched. This feature can also be
-         enabled using the boot command line parameter
-         'vgacon.scrollback_persistent=1'.
-
-         This feature might break your tool of choice to flush the scrollback
-         buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
-         will be broken, which might cause security issues.
-         You can use the escape sequence \e[3J instead if this feature is
-         activated.
-
-         Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
-         created tty device.
-         So if you use a RAM-constrained system, say N here.
-
 config MDA_CONSOLE
        depends on !M68K && !PARISC && ISA
        tristate "MDA text console (dual-headed)"
index 72f146d..cd51b7a 100644 (file)
 
 #define FONT_DATA ((unsigned char *)font_vga_8x16.data)
 
-/* borrowed from fbcon.c */
-#define REFCOUNT(fd)   (((int *)(fd))[-1])
-#define FNTSIZE(fd)    (((int *)(fd))[-2])
-#define FNTCHARCNT(fd) (((int *)(fd))[-3])
-#define FONT_EXTRA_WORDS 3
-
 static unsigned char *font_data[MAX_NR_CONSOLES];
 
 static struct newport_regs *npregs;
@@ -522,6 +516,7 @@ static int newport_set_font(int unit, struct console_font *op)
        FNTSIZE(new_data) = size;
        FNTCHARCNT(new_data) = op->charcount;
        REFCOUNT(new_data) = 0; /* usage counter */
+       FNTSUM(new_data) = 0;
 
        p = new_data;
        for (i = 0; i < op->charcount; i++) {
index a52bb37..17876f0 100644 (file)
@@ -165,214 +165,6 @@ static inline void vga_set_mem_top(struct vc_data *c)
        write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
 }
 
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
-/* software scrollback */
-struct vgacon_scrollback_info {
-       void *data;
-       int tail;
-       int size;
-       int rows;
-       int cnt;
-       int cur;
-       int save;
-       int restore;
-};
-
-static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-static bool scrollback_persistent = \
-       IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
-module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
-MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
-
-static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
-{
-       struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
-
-       if (scrollback->data && reset_size > 0)
-               memset(scrollback->data, 0, reset_size);
-
-       scrollback->cnt  = 0;
-       scrollback->tail = 0;
-       scrollback->cur  = 0;
-}
-
-static void vgacon_scrollback_init(int vc_num)
-{
-       int pitch = vga_video_num_columns * 2;
-       size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
-       int rows = size / pitch;
-       void *data;
-
-       data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
-                            GFP_NOWAIT);
-
-       vgacon_scrollbacks[vc_num].data = data;
-       vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
-
-       vgacon_scrollback_cur->rows = rows - 1;
-       vgacon_scrollback_cur->size = rows * pitch;
-
-       vgacon_scrollback_reset(vc_num, size);
-}
-
-static void vgacon_scrollback_switch(int vc_num)
-{
-       if (!scrollback_persistent)
-               vc_num = 0;
-
-       if (!vgacon_scrollbacks[vc_num].data) {
-               vgacon_scrollback_init(vc_num);
-       } else {
-               if (scrollback_persistent) {
-                       vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
-               } else {
-                       size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
-
-                       vgacon_scrollback_reset(vc_num, size);
-               }
-       }
-}
-
-static void vgacon_scrollback_startup(void)
-{
-       vgacon_scrollback_cur = &vgacon_scrollbacks[0];
-       vgacon_scrollback_init(0);
-}
-
-static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
-{
-       void *p;
-
-       if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
-           c->vc_num != fg_console)
-               return;
-
-       p = (void *) (c->vc_origin + t * c->vc_size_row);
-
-       while (count--) {
-               if ((vgacon_scrollback_cur->tail + c->vc_size_row) >
-                   vgacon_scrollback_cur->size)
-                       vgacon_scrollback_cur->tail = 0;
-
-               scr_memcpyw(vgacon_scrollback_cur->data +
-                           vgacon_scrollback_cur->tail,
-                           p, c->vc_size_row);
-
-               vgacon_scrollback_cur->cnt++;
-               p += c->vc_size_row;
-               vgacon_scrollback_cur->tail += c->vc_size_row;
-
-               if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
-                       vgacon_scrollback_cur->tail = 0;
-
-               if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
-                       vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
-
-               vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
-       }
-}
-
-static void vgacon_restore_screen(struct vc_data *c)
-{
-       c->vc_origin = c->vc_visible_origin;
-       vgacon_scrollback_cur->save = 0;
-
-       if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
-               scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
-                           c->vc_screenbuf_size > vga_vram_size ?
-                           vga_vram_size : c->vc_screenbuf_size);
-               vgacon_scrollback_cur->restore = 1;
-               vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
-       }
-}
-
-static void vgacon_scrolldelta(struct vc_data *c, int lines)
-{
-       int start, end, count, soff;
-
-       if (!lines) {
-               vgacon_restore_screen(c);
-               return;
-       }
-
-       if (!vgacon_scrollback_cur->data)
-               return;
-
-       if (!vgacon_scrollback_cur->save) {
-               vgacon_cursor(c, CM_ERASE);
-               vgacon_save_screen(c);
-               c->vc_origin = (unsigned long)c->vc_screenbuf;
-               vgacon_scrollback_cur->save = 1;
-       }
-
-       vgacon_scrollback_cur->restore = 0;
-       start = vgacon_scrollback_cur->cur + lines;
-       end = start + abs(lines);
-
-       if (start < 0)
-               start = 0;
-
-       if (start > vgacon_scrollback_cur->cnt)
-               start = vgacon_scrollback_cur->cnt;
-
-       if (end < 0)
-               end = 0;
-
-       if (end > vgacon_scrollback_cur->cnt)
-               end = vgacon_scrollback_cur->cnt;
-
-       vgacon_scrollback_cur->cur = start;
-       count = end - start;
-       soff = vgacon_scrollback_cur->tail -
-               ((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
-       soff -= count * c->vc_size_row;
-
-       if (soff < 0)
-               soff += vgacon_scrollback_cur->size;
-
-       count = vgacon_scrollback_cur->cnt - start;
-
-       if (count > c->vc_rows)
-               count = c->vc_rows;
-
-       if (count) {
-               int copysize;
-
-               int diff = c->vc_rows - count;
-               void *d = (void *) c->vc_visible_origin;
-               void *s = (void *) c->vc_screenbuf;
-
-               count *= c->vc_size_row;
-               /* how much memory to end of buffer left? */
-               copysize = min(count, vgacon_scrollback_cur->size - soff);
-               scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
-               d += copysize;
-               count -= copysize;
-
-               if (count) {
-                       scr_memcpyw(d, vgacon_scrollback_cur->data, count);
-                       d += count;
-               }
-
-               if (diff)
-                       scr_memcpyw(d, s, diff * c->vc_size_row);
-       } else
-               vgacon_cursor(c, CM_MOVE);
-}
-
-static void vgacon_flush_scrollback(struct vc_data *c)
-{
-       size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
-
-       vgacon_scrollback_reset(c->vc_num, size);
-}
-#else
-#define vgacon_scrollback_startup(...) do { } while (0)
-#define vgacon_scrollback_init(...)    do { } while (0)
-#define vgacon_scrollback_update(...)  do { } while (0)
-#define vgacon_scrollback_switch(...)  do { } while (0)
-
 static void vgacon_restore_screen(struct vc_data *c)
 {
        if (c->vc_origin != c->vc_visible_origin)
@@ -386,11 +178,6 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        vga_set_mem_top(c);
 }
 
-static void vgacon_flush_scrollback(struct vc_data *c)
-{
-}
-#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
-
 static const char *vgacon_startup(void)
 {
        const char *display_desc = NULL;
@@ -573,10 +360,7 @@ static const char *vgacon_startup(void)
        vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
        vgacon_yres = vga_scan_lines;
 
-       if (!vga_init_done) {
-               vgacon_scrollback_startup();
-               vga_init_done = true;
-       }
+       vga_init_done = true;
 
        return display_desc;
 }
@@ -869,7 +653,6 @@ static int vgacon_switch(struct vc_data *c)
                        vgacon_doresize(c, c->vc_cols, c->vc_rows);
        }
 
-       vgacon_scrollback_switch(c->vc_num);
        return 0;               /* Redrawing not needed */
 }
 
@@ -1386,7 +1169,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
        oldo = c->vc_origin;
        delta = lines * c->vc_size_row;
        if (dir == SM_UP) {
-               vgacon_scrollback_update(c, t, lines);
                if (c->vc_scr_end + delta >= vga_vram_end) {
                        scr_memcpyw((u16 *) vga_vram_base,
                                    (u16 *) (oldo + delta),
@@ -1450,7 +1232,6 @@ const struct consw vga_con = {
        .con_save_screen = vgacon_save_screen,
        .con_build_attr = vgacon_build_attr,
        .con_invert_region = vgacon_invert_region,
-       .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
index b2c9dd4..402e854 100644 (file)
@@ -272,6 +272,26 @@ config FB_PM2_FIFO_DISCONNECT
        help
          Support the Permedia2 FIFO disconnect feature.
 
+config FB_ARMCLCD
+       tristate "ARM PrimeCell PL110 support"
+       depends on ARM || ARM64 || COMPILE_TEST
+       depends on FB && ARM_AMBA && HAS_IOMEM
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select FB_MODE_HELPERS if OF
+       select VIDEOMODE_HELPERS if OF
+       select BACKLIGHT_CLASS_DEVICE if OF
+       help
+         This framebuffer device driver is for the ARM PrimeCell PL110
+         Colour LCD controller.  ARM PrimeCells provide the building
+         blocks for System on a Chip devices.
+
+         If you want to compile this as a module (=code which can be
+         inserted into and removed from the running kernel), say M
+         here and read <file:Documentation/kbuild/modules.rst>.  The module
+         will be called amba-clcd.
+
 config FB_ACORN
        bool "Acorn VIDC support"
        depends on (FB = y) && ARM && ARCH_ACORN
index cad4fb6..a0705b9 100644 (file)
@@ -75,6 +75,7 @@ obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_ATMEL)           += atmel_lcdfb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
+obj-$(CONFIG_FB_ARMCLCD)         += amba-clcd.o
 obj-$(CONFIG_FB_GOLDFISH)         += goldfishfb.o
 obj-$(CONFIG_FB_68328)            += 68328fb.o
 obj-$(CONFIG_FB_GBE)              += gbefb.o
diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c
new file mode 100644 (file)
index 0000000..b7682de
--- /dev/null
@@ -0,0 +1,986 @@
+/*
+ *  linux/drivers/video/amba-clcd.c
+ *
+ * Copyright (C) 2001 ARM Limited, by David A Rusling
+ * Updated to 2.5, Deep Blue Solutions Ltd.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ *  ARM PrimeCell PL110 Color LCD Controller
+ */
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/backlight.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+#define to_clcd(info)  container_of(info, struct clcd_fb, fb)
+
+/* This is limited to 16 characters when displayed by X startup */
+static const char *clcd_name = "CLCD FB";
+
+/*
+ * Unfortunately, the enable/disable functions may be called either from
+ * process or IRQ context, and we _need_ to delay.  This is _not_ good.
+ */
+static inline void clcdfb_sleep(unsigned int ms)
+{
+       if (in_atomic()) {
+               mdelay(ms);
+       } else {
+               msleep(ms);
+       }
+}
+
+static inline void clcdfb_set_start(struct clcd_fb *fb)
+{
+       unsigned long ustart = fb->fb.fix.smem_start;
+       unsigned long lstart;
+
+       ustart += fb->fb.var.yoffset * fb->fb.fix.line_length;
+       lstart = ustart + fb->fb.var.yres * fb->fb.fix.line_length / 2;
+
+       writel(ustart, fb->regs + CLCD_UBAS);
+       writel(lstart, fb->regs + CLCD_LBAS);
+}
+
+static void clcdfb_disable(struct clcd_fb *fb)
+{
+       u32 val;
+
+       if (fb->board->disable)
+               fb->board->disable(fb);
+
+       if (fb->panel->backlight) {
+               fb->panel->backlight->props.power = FB_BLANK_POWERDOWN;
+               backlight_update_status(fb->panel->backlight);
+       }
+
+       val = readl(fb->regs + fb->off_cntl);
+       if (val & CNTL_LCDPWR) {
+               val &= ~CNTL_LCDPWR;
+               writel(val, fb->regs + fb->off_cntl);
+
+               clcdfb_sleep(20);
+       }
+       if (val & CNTL_LCDEN) {
+               val &= ~CNTL_LCDEN;
+               writel(val, fb->regs + fb->off_cntl);
+       }
+
+       /*
+        * Disable CLCD clock source.
+        */
+       if (fb->clk_enabled) {
+               fb->clk_enabled = false;
+               clk_disable(fb->clk);
+       }
+}
+
+static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
+{
+       /*
+        * Enable the CLCD clock source.
+        */
+       if (!fb->clk_enabled) {
+               fb->clk_enabled = true;
+               clk_enable(fb->clk);
+       }
+
+       /*
+        * Bring up by first enabling..
+        */
+       cntl |= CNTL_LCDEN;
+       writel(cntl, fb->regs + fb->off_cntl);
+
+       clcdfb_sleep(20);
+
+       /*
+        * and now apply power.
+        */
+       cntl |= CNTL_LCDPWR;
+       writel(cntl, fb->regs + fb->off_cntl);
+
+       /*
+        * Turn on backlight
+        */
+       if (fb->panel->backlight) {
+               fb->panel->backlight->props.power = FB_BLANK_UNBLANK;
+               backlight_update_status(fb->panel->backlight);
+       }
+
+       /*
+        * finally, enable the interface.
+        */
+       if (fb->board->enable)
+               fb->board->enable(fb);
+}
+
+static int
+clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+       u32 caps;
+       int ret = 0;
+
+       if (fb->panel->caps && fb->board->caps)
+               caps = fb->panel->caps & fb->board->caps;
+       else {
+               /* Old way of specifying what can be used */
+               caps = fb->panel->cntl & CNTL_BGR ?
+                       CLCD_CAP_BGR : CLCD_CAP_RGB;
+               /* But mask out 444 modes as they weren't supported */
+               caps &= ~CLCD_CAP_444;
+       }
+
+       /* Only TFT panels can do RGB888/BGR888 */
+       if (!(fb->panel->cntl & CNTL_LCDTFT))
+               caps &= ~CLCD_CAP_888;
+
+       memset(&var->transp, 0, sizeof(var->transp));
+
+       var->red.msb_right = 0;
+       var->green.msb_right = 0;
+       var->blue.msb_right = 0;
+
+       switch (var->bits_per_pixel) {
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               /* If we can't do 5551, reject */
+               caps &= CLCD_CAP_5551;
+               if (!caps) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               var->red.length         = var->bits_per_pixel;
+               var->red.offset         = 0;
+               var->green.length       = var->bits_per_pixel;
+               var->green.offset       = 0;
+               var->blue.length        = var->bits_per_pixel;
+               var->blue.offset        = 0;
+               break;
+
+       case 16:
+               /* If we can't do 444, 5551 or 565, reject */
+               if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               /*
+                * Green length can be 4, 5 or 6 depending whether
+                * we're operating in 444, 5551 or 565 mode.
+                */
+               if (var->green.length == 4 && caps & CLCD_CAP_444)
+                       caps &= CLCD_CAP_444;
+               if (var->green.length == 5 && caps & CLCD_CAP_5551)
+                       caps &= CLCD_CAP_5551;
+               else if (var->green.length == 6 && caps & CLCD_CAP_565)
+                       caps &= CLCD_CAP_565;
+               else {
+                       /*
+                        * PL110 officially only supports RGB555,
+                        * but may be wired up to allow RGB565.
+                        */
+                       if (caps & CLCD_CAP_565) {
+                               var->green.length = 6;
+                               caps &= CLCD_CAP_565;
+                       } else if (caps & CLCD_CAP_5551) {
+                               var->green.length = 5;
+                               caps &= CLCD_CAP_5551;
+                       } else {
+                               var->green.length = 4;
+                               caps &= CLCD_CAP_444;
+                       }
+               }
+
+               if (var->green.length >= 5) {
+                       var->red.length = 5;
+                       var->blue.length = 5;
+               } else {
+                       var->red.length = 4;
+                       var->blue.length = 4;
+               }
+               break;
+       case 32:
+               /* If we can't do 888, reject */
+               caps &= CLCD_CAP_888;
+               if (!caps) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       /*
+        * >= 16bpp displays have separate colour component bitfields
+        * encoded in the pixel data.  Calculate their position from
+        * the bitfield length defined above.
+        */
+       if (ret == 0 && var->bits_per_pixel >= 16) {
+               bool bgr, rgb;
+
+               bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
+               rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
+
+               if (!bgr && !rgb)
+                       /*
+                        * The requested format was not possible, try just
+                        * our capabilities.  One of BGR or RGB must be
+                        * supported.
+                        */
+                       bgr = caps & CLCD_CAP_BGR;
+
+               if (bgr) {
+                       var->blue.offset = 0;
+                       var->green.offset = var->blue.offset + var->blue.length;
+                       var->red.offset = var->green.offset + var->green.length;
+               } else {
+                       var->red.offset = 0;
+                       var->green.offset = var->red.offset + var->red.length;
+                       var->blue.offset = var->green.offset + var->green.length;
+               }
+       }
+
+       return ret;
+}
+
+static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+       int ret = -EINVAL;
+
+       if (fb->board->check)
+               ret = fb->board->check(fb, var);
+
+       if (ret == 0 &&
+           var->xres_virtual * var->bits_per_pixel / 8 *
+           var->yres_virtual > fb->fb.fix.smem_len)
+               ret = -EINVAL;
+
+       if (ret == 0)
+               ret = clcdfb_set_bitfields(fb, var);
+
+       return ret;
+}
+
+static int clcdfb_set_par(struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+       struct clcd_regs regs;
+
+       fb->fb.fix.line_length = fb->fb.var.xres_virtual *
+                                fb->fb.var.bits_per_pixel / 8;
+
+       if (fb->fb.var.bits_per_pixel <= 8)
+               fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+       else
+               fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+
+       fb->board->decode(fb, &regs);
+
+       clcdfb_disable(fb);
+
+       writel(regs.tim0, fb->regs + CLCD_TIM0);
+       writel(regs.tim1, fb->regs + CLCD_TIM1);
+       writel(regs.tim2, fb->regs + CLCD_TIM2);
+       writel(regs.tim3, fb->regs + CLCD_TIM3);
+
+       clcdfb_set_start(fb);
+
+       clk_set_rate(fb->clk, (1000000000 / regs.pixclock) * 1000);
+
+       fb->clcd_cntl = regs.cntl;
+
+       clcdfb_enable(fb, regs.cntl);
+
+#ifdef DEBUG
+       printk(KERN_INFO
+              "CLCD: Registers set to\n"
+              "  %08x %08x %08x %08x\n"
+              "  %08x %08x %08x %08x\n",
+               readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
+               readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
+               readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
+               readl(fb->regs + fb->off_ienb), readl(fb->regs + fb->off_cntl));
+#endif
+
+       return 0;
+}
+
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
+{
+       unsigned int mask = (1 << bf->length) - 1;
+
+       return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+/*
+ *  Set a single color register. The values supplied have a 16 bit
+ *  magnitude.  Return != 0 for invalid regno.
+ */
+static int
+clcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+                unsigned int blue, unsigned int transp, struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+
+       if (regno < 16)
+               fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+                                 convert_bitfield(blue, &fb->fb.var.blue) |
+                                 convert_bitfield(green, &fb->fb.var.green) |
+                                 convert_bitfield(red, &fb->fb.var.red);
+
+       if (fb->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
+               int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
+               u32 val, mask, newval;
+
+               newval  = (red >> 11)  & 0x001f;
+               newval |= (green >> 6) & 0x03e0;
+               newval |= (blue >> 1)  & 0x7c00;
+
+               /*
+                * 3.2.11: if we're configured for big endian
+                * byte order, the palette entries are swapped.
+                */
+               if (fb->clcd_cntl & CNTL_BEBO)
+                       regno ^= 1;
+
+               if (regno & 1) {
+                       newval <<= 16;
+                       mask = 0x0000ffff;
+               } else {
+                       mask = 0xffff0000;
+               }
+
+               val = readl(fb->regs + hw_reg) & mask;
+               writel(val | newval, fb->regs + hw_reg);
+       }
+
+       return regno > 255;
+}
+
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+ *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+ *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+ *  and powerdown modes on hardware that supports disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+static int clcdfb_blank(int blank_mode, struct fb_info *info)
+{
+       struct clcd_fb *fb = to_clcd(info);
+
+       if (blank_mode != 0) {
+               clcdfb_disable(fb);
+       } else {
+               clcdfb_enable(fb, fb->clcd_cntl);
+       }
+       return 0;
+}
+
+static int clcdfb_mmap(struct fb_info *info,
+                      struct vm_area_struct *vma)
+{
+       struct clcd_fb *fb = to_clcd(info);
+       unsigned long len, off = vma->vm_pgoff << PAGE_SHIFT;
+       int ret = -EINVAL;
+
+       len = info->fix.smem_len;
+
+       if (off <= len && vma->vm_end - vma->vm_start <= len - off &&
+           fb->board->mmap)
+               ret = fb->board->mmap(fb, vma);
+
+       return ret;
+}
+
+static const struct fb_ops clcdfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = clcdfb_check_var,
+       .fb_set_par     = clcdfb_set_par,
+       .fb_setcolreg   = clcdfb_setcolreg,
+       .fb_blank       = clcdfb_blank,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_mmap        = clcdfb_mmap,
+};
+
+static int clcdfb_register(struct clcd_fb *fb)
+{
+       int ret;
+
+       /*
+        * ARM PL111 always has IENB at 0x1c; it's only PL110
+        * which is reversed on some platforms.
+        */
+       if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
+               fb->off_ienb = CLCD_PL111_IENB;
+               fb->off_cntl = CLCD_PL111_CNTL;
+       } else {
+               fb->off_ienb = CLCD_PL110_IENB;
+               fb->off_cntl = CLCD_PL110_CNTL;
+       }
+
+       fb->clk = clk_get(&fb->dev->dev, NULL);
+       if (IS_ERR(fb->clk)) {
+               ret = PTR_ERR(fb->clk);
+               goto out;
+       }
+
+       ret = clk_prepare(fb->clk);
+       if (ret)
+               goto free_clk;
+
+       fb->fb.device           = &fb->dev->dev;
+
+       fb->fb.fix.mmio_start   = fb->dev->res.start;
+       fb->fb.fix.mmio_len     = resource_size(&fb->dev->res);
+
+       fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len);
+       if (!fb->regs) {
+               printk(KERN_ERR "CLCD: unable to remap registers\n");
+               ret = -ENOMEM;
+               goto clk_unprep;
+       }
+
+       fb->fb.fbops            = &clcdfb_ops;
+       fb->fb.flags            = FBINFO_FLAG_DEFAULT;
+       fb->fb.pseudo_palette   = fb->cmap;
+
+       strncpy(fb->fb.fix.id, clcd_name, sizeof(fb->fb.fix.id));
+       fb->fb.fix.type         = FB_TYPE_PACKED_PIXELS;
+       fb->fb.fix.type_aux     = 0;
+       fb->fb.fix.xpanstep     = 0;
+       fb->fb.fix.ypanstep     = 0;
+       fb->fb.fix.ywrapstep    = 0;
+       fb->fb.fix.accel        = FB_ACCEL_NONE;
+
+       fb->fb.var.xres         = fb->panel->mode.xres;
+       fb->fb.var.yres         = fb->panel->mode.yres;
+       fb->fb.var.xres_virtual = fb->panel->mode.xres;
+       fb->fb.var.yres_virtual = fb->panel->mode.yres;
+       fb->fb.var.bits_per_pixel = fb->panel->bpp;
+       fb->fb.var.grayscale    = fb->panel->grayscale;
+       fb->fb.var.pixclock     = fb->panel->mode.pixclock;
+       fb->fb.var.left_margin  = fb->panel->mode.left_margin;
+       fb->fb.var.right_margin = fb->panel->mode.right_margin;
+       fb->fb.var.upper_margin = fb->panel->mode.upper_margin;
+       fb->fb.var.lower_margin = fb->panel->mode.lower_margin;
+       fb->fb.var.hsync_len    = fb->panel->mode.hsync_len;
+       fb->fb.var.vsync_len    = fb->panel->mode.vsync_len;
+       fb->fb.var.sync         = fb->panel->mode.sync;
+       fb->fb.var.vmode        = fb->panel->mode.vmode;
+       fb->fb.var.activate     = FB_ACTIVATE_NOW;
+       fb->fb.var.nonstd       = 0;
+       fb->fb.var.height       = fb->panel->height;
+       fb->fb.var.width        = fb->panel->width;
+       fb->fb.var.accel_flags  = 0;
+
+       fb->fb.monspecs.hfmin   = 0;
+       fb->fb.monspecs.hfmax   = 100000;
+       fb->fb.monspecs.vfmin   = 0;
+       fb->fb.monspecs.vfmax   = 400;
+       fb->fb.monspecs.dclkmin = 1000000;
+       fb->fb.monspecs.dclkmax = 100000000;
+
+       /*
+        * Make sure that the bitfields are set appropriately.
+        */
+       clcdfb_set_bitfields(fb, &fb->fb.var);
+
+       /*
+        * Allocate colourmap.
+        */
+       ret = fb_alloc_cmap(&fb->fb.cmap, 256, 0);
+       if (ret)
+               goto unmap;
+
+       /*
+        * Ensure interrupts are disabled.
+        */
+       writel(0, fb->regs + fb->off_ienb);
+
+       fb_set_var(&fb->fb, &fb->fb.var);
+
+       dev_info(&fb->dev->dev, "%s hardware, %s display\n",
+                fb->board->name, fb->panel->mode.name);
+
+       ret = register_framebuffer(&fb->fb);
+       if (ret == 0)
+               goto out;
+
+       printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
+
+       fb_dealloc_cmap(&fb->fb.cmap);
+ unmap:
+       iounmap(fb->regs);
+ clk_unprep:
+       clk_unprepare(fb->clk);
+ free_clk:
+       clk_put(fb->clk);
+ out:
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
+               struct clcd_panel *clcd_panel)
+{
+       int err;
+       struct display_timing timing;
+       struct videomode video;
+
+       err = of_get_display_timing(node, "panel-timing", &timing);
+       if (err) {
+               pr_err("%pOF: problems parsing panel-timing (%d)\n", node, err);
+               return err;
+       }
+
+       videomode_from_timing(&timing, &video);
+
+       err = fb_videomode_from_videomode(&video, &clcd_panel->mode);
+       if (err)
+               return err;
+
+       /* Set up some inversion flags */
+       if (timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+               clcd_panel->tim2 |= TIM2_IPC;
+       else if (!(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE))
+               /*
+                * To preserve backwards compatibility, the IPC (inverted
+                * pixel clock) flag needs to be set on any display that
+                * doesn't explicitly specify that the pixel clock is
+                * active on the negative or positive edge.
+                */
+               clcd_panel->tim2 |= TIM2_IPC;
+
+       if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW)
+               clcd_panel->tim2 |= TIM2_IHS;
+
+       if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW)
+               clcd_panel->tim2 |= TIM2_IVS;
+
+       if (timing.flags & DISPLAY_FLAGS_DE_LOW)
+               clcd_panel->tim2 |= TIM2_IOE;
+
+       return 0;
+}
+
+static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode)
+{
+       return snprintf(buf, size, "%ux%u@%u", mode->xres, mode->yres,
+                       mode->refresh);
+}
+
+static int clcdfb_of_get_backlight(struct device *dev,
+                                  struct clcd_panel *clcd_panel)
+{
+       struct backlight_device *backlight;
+
+       /* Look up the optional backlight device */
+       backlight = devm_of_find_backlight(dev);
+       if (IS_ERR(backlight))
+               return PTR_ERR(backlight);
+
+       clcd_panel->backlight = backlight;
+       return 0;
+}
+
+static int clcdfb_of_get_mode(struct device *dev, struct device_node *panel,
+                             struct clcd_panel *clcd_panel)
+{
+       int err;
+       struct fb_videomode *mode;
+       char *name;
+       int len;
+
+       /* Only directly connected DPI panels supported for now */
+       if (of_device_is_compatible(panel, "panel-dpi"))
+               err = clcdfb_of_get_dpi_panel_mode(panel, clcd_panel);
+       else
+               err = -ENOENT;
+       if (err)
+               return err;
+       mode = &clcd_panel->mode;
+
+       len = clcdfb_snprintf_mode(NULL, 0, mode);
+       name = devm_kzalloc(dev, len + 1, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
+
+       clcdfb_snprintf_mode(name, len + 1, mode);
+       mode->name = name;
+
+       return 0;
+}
+
+static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
+{
+       static struct {
+               unsigned int part;
+               u32 r0, g0, b0;
+               u32 caps;
+       } panels[] = {
+               { 0x110, 1,  7, 13, CLCD_CAP_5551 },
+               { 0x110, 0,  8, 16, CLCD_CAP_888 },
+               { 0x110, 16, 8, 0,  CLCD_CAP_888 },
+               { 0x111, 4, 14, 20, CLCD_CAP_444 },
+               { 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 },
+               { 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 |
+                                   CLCD_CAP_565 },
+               { 0x111, 0,  8, 16, CLCD_CAP_444 | CLCD_CAP_5551 |
+                                   CLCD_CAP_565 | CLCD_CAP_888 },
+       };
+       int i;
+
+       /* Bypass pixel clock divider */
+       fb->panel->tim2 |= TIM2_BCD;
+
+       /* TFT display, vert. comp. interrupt at the start of the back porch */
+       fb->panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1);
+
+       fb->panel->caps = 0;
+
+       /* Match the setup with known variants */
+       for (i = 0; i < ARRAY_SIZE(panels) && !fb->panel->caps; i++) {
+               if (amba_part(fb->dev) != panels[i].part)
+                       continue;
+               if (g0 != panels[i].g0)
+                       continue;
+               if (r0 == panels[i].r0 && b0 == panels[i].b0)
+                       fb->panel->caps = panels[i].caps;
+       }
+
+       /*
+        * If we actually physically connected the R lines to B and
+        * vice versa
+        */
+       if (r0 != 0 && b0 == 0)
+               fb->panel->bgr_connection = true;
+
+       return fb->panel->caps ? 0 : -EINVAL;
+}
+
+static int clcdfb_of_init_display(struct clcd_fb *fb)
+{
+       struct device_node *endpoint, *panel;
+       int err;
+       unsigned int bpp;
+       u32 max_bandwidth;
+       u32 tft_r0b0g0[3];
+
+       fb->panel = devm_kzalloc(&fb->dev->dev, sizeof(*fb->panel), GFP_KERNEL);
+       if (!fb->panel)
+               return -ENOMEM;
+
+       /*
+        * Fetch the panel endpoint.
+        */
+       endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node, NULL);
+       if (!endpoint)
+               return -ENODEV;
+
+       panel = of_graph_get_remote_port_parent(endpoint);
+       if (!panel)
+               return -ENODEV;
+
+       err = clcdfb_of_get_backlight(&fb->dev->dev, fb->panel);
+       if (err)
+               return err;
+
+       err = clcdfb_of_get_mode(&fb->dev->dev, panel, fb->panel);
+       if (err)
+               return err;
+
+       err = of_property_read_u32(fb->dev->dev.of_node, "max-memory-bandwidth",
+                       &max_bandwidth);
+       if (!err) {
+               /*
+                * max_bandwidth is in bytes per second and pixclock in
+                * pico-seconds, so the maximum allowed bits per pixel is
+                *   8 * max_bandwidth / (PICOS2KHZ(pixclock) * 1000)
+                * Rearrange this calculation to avoid overflow and then ensure
+                * result is a valid format.
+                */
+               bpp = max_bandwidth / (1000 / 8)
+                       / PICOS2KHZ(fb->panel->mode.pixclock);
+               bpp = rounddown_pow_of_two(bpp);
+               if (bpp > 32)
+                       bpp = 32;
+       } else
+               bpp = 32;
+       fb->panel->bpp = bpp;
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       fb->panel->cntl |= CNTL_BEBO;
+#endif
+       fb->panel->width = -1;
+       fb->panel->height = -1;
+
+       if (of_property_read_u32_array(endpoint,
+                       "arm,pl11x,tft-r0g0b0-pads",
+                       tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0)
+               return -ENOENT;
+
+       return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
+                                       tft_r0b0g0[1],  tft_r0b0g0[2]);
+}
+
+static int clcdfb_of_vram_setup(struct clcd_fb *fb)
+{
+       int err;
+       struct device_node *memory;
+       u64 size;
+
+       err = clcdfb_of_init_display(fb);
+       if (err)
+               return err;
+
+       memory = of_parse_phandle(fb->dev->dev.of_node, "memory-region", 0);
+       if (!memory)
+               return -ENODEV;
+
+       fb->fb.screen_base = of_iomap(memory, 0);
+       if (!fb->fb.screen_base)
+               return -ENOMEM;
+
+       fb->fb.fix.smem_start = of_translate_address(memory,
+                       of_get_address(memory, 0, &size, NULL));
+       fb->fb.fix.smem_len = size;
+
+       return 0;
+}
+
+static int clcdfb_of_vram_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       unsigned long off, user_size, kernel_size;
+
+
+       off = vma->vm_pgoff << PAGE_SHIFT;
+       user_size = vma->vm_end - vma->vm_start;
+       kernel_size = fb->fb.fix.smem_len;
+
+       if (off >= kernel_size || user_size > (kernel_size - off))
+               return -ENXIO;
+
+       return remap_pfn_range(vma, vma->vm_start,
+                       __phys_to_pfn(fb->fb.fix.smem_start) + vma->vm_pgoff,
+                       user_size,
+                       pgprot_writecombine(vma->vm_page_prot));
+}
+
+static void clcdfb_of_vram_remove(struct clcd_fb *fb)
+{
+       iounmap(fb->fb.screen_base);
+}
+
+static int clcdfb_of_dma_setup(struct clcd_fb *fb)
+{
+       unsigned long framesize;
+       dma_addr_t dma;
+       int err;
+
+       err = clcdfb_of_init_display(fb);
+       if (err)
+               return err;
+
+       framesize = PAGE_ALIGN(fb->panel->mode.xres * fb->panel->mode.yres *
+                       fb->panel->bpp / 8);
+       fb->fb.screen_base = dma_alloc_coherent(&fb->dev->dev, framesize,
+                       &dma, GFP_KERNEL);
+       if (!fb->fb.screen_base)
+               return -ENOMEM;
+
+       fb->fb.fix.smem_start = dma;
+       fb->fb.fix.smem_len = framesize;
+
+       return 0;
+}
+
+static int clcdfb_of_dma_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
+                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+}
+
+static void clcdfb_of_dma_remove(struct clcd_fb *fb)
+{
+       dma_free_coherent(&fb->dev->dev, fb->fb.fix.smem_len,
+                       fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
+{
+       struct clcd_board *board = devm_kzalloc(&dev->dev, sizeof(*board),
+                       GFP_KERNEL);
+       struct device_node *node = dev->dev.of_node;
+
+       if (!board)
+               return NULL;
+
+       board->name = of_node_full_name(node);
+       board->caps = CLCD_CAP_ALL;
+       board->check = clcdfb_check;
+       board->decode = clcdfb_decode;
+       if (of_find_property(node, "memory-region", NULL)) {
+               board->setup = clcdfb_of_vram_setup;
+               board->mmap = clcdfb_of_vram_mmap;
+               board->remove = clcdfb_of_vram_remove;
+       } else {
+               board->setup = clcdfb_of_dma_setup;
+               board->mmap = clcdfb_of_dma_mmap;
+               board->remove = clcdfb_of_dma_remove;
+       }
+
+       return board;
+}
+#else
+static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
+{
+       return NULL;
+}
+#endif
+
+static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
+{
+       struct clcd_board *board = dev_get_platdata(&dev->dev);
+       struct clcd_fb *fb;
+       int ret;
+
+       if (!board)
+               board = clcdfb_of_get_board(dev);
+
+       if (!board)
+               return -EINVAL;
+
+       ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto out;
+
+       ret = amba_request_regions(dev, NULL);
+       if (ret) {
+               printk(KERN_ERR "CLCD: unable to reserve regs region\n");
+               goto out;
+       }
+
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb) {
+               ret = -ENOMEM;
+               goto free_region;
+       }
+
+       fb->dev = dev;
+       fb->board = board;
+
+       dev_info(&fb->dev->dev, "PL%03x designer %02x rev%u at 0x%08llx\n",
+               amba_part(dev), amba_manf(dev), amba_rev(dev),
+               (unsigned long long)dev->res.start);
+
+       ret = fb->board->setup(fb);
+       if (ret)
+               goto free_fb;
+
+       ret = clcdfb_register(fb);
+       if (ret == 0) {
+               amba_set_drvdata(dev, fb);
+               goto out;
+       }
+
+       fb->board->remove(fb);
+ free_fb:
+       kfree(fb);
+ free_region:
+       amba_release_regions(dev);
+ out:
+       return ret;
+}
+
+static int clcdfb_remove(struct amba_device *dev)
+{
+       struct clcd_fb *fb = amba_get_drvdata(dev);
+
+       clcdfb_disable(fb);
+       unregister_framebuffer(&fb->fb);
+       if (fb->fb.cmap.len)
+               fb_dealloc_cmap(&fb->fb.cmap);
+       iounmap(fb->regs);
+       clk_unprepare(fb->clk);
+       clk_put(fb->clk);
+
+       fb->board->remove(fb);
+
+       kfree(fb);
+
+       amba_release_regions(dev);
+
+       return 0;
+}
+
+static const struct amba_id clcdfb_id_table[] = {
+       {
+               .id     = 0x00041110,
+               .mask   = 0x000ffffe,
+       },
+       { 0, 0 },
+};
+
+MODULE_DEVICE_TABLE(amba, clcdfb_id_table);
+
+static struct amba_driver clcd_driver = {
+       .drv            = {
+               .name   = "clcd-pl11x",
+       },
+       .probe          = clcdfb_probe,
+       .remove         = clcdfb_remove,
+       .id_table       = clcdfb_id_table,
+};
+
+static int __init amba_clcdfb_init(void)
+{
+       if (fb_get_options("ambafb", NULL))
+               return -ENODEV;
+
+       return amba_driver_register(&clcd_driver);
+}
+
+module_init(amba_clcdfb_init);
+
+static void __exit amba_clcdfb_exit(void)
+{
+       amba_driver_unregister(&clcd_driver);
+}
+
+module_exit(amba_clcdfb_exit);
+
+MODULE_DESCRIPTION("ARM PrimeCell PL110 CLCD core driver");
+MODULE_LICENSE("GPL");
index 4e6cbc2..9725ecd 100644 (file)
@@ -234,7 +234,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
 }
 
 static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
-                      int softback_lines, int fg, int bg)
+                      int fg, int bg)
 {
        struct fb_cursor cursor;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -247,15 +247,6 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 
        cursor.set = 0;
 
-       if (softback_lines) {
-               if (y + softback_lines >= vc->vc_rows) {
-                       mode = CM_ERASE;
-                       ops->cursor_flash = 0;
-                       return;
-               } else
-                       y += softback_lines;
-       }
-
        c = scr_readw((u16 *) vc->vc_pos);
        attribute = get_attribute(info, c);
        src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
index 6616783..8c7bd0a 100644 (file)
@@ -122,12 +122,6 @@ static int logo_lines;
 /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
    enums.  */
 static int logo_shown = FBCON_LOGO_CANSHOW;
-/* Software scrollback */
-static int fbcon_softback_size = 32768;
-static unsigned long softback_buf, softback_curr;
-static unsigned long softback_in;
-static unsigned long softback_top, softback_end;
-static int softback_lines;
 /* console mappings */
 static int first_fb_vc;
 static int last_fb_vc = MAX_NR_CONSOLES - 1;
@@ -167,8 +161,6 @@ static int margin_color;
 
 static const struct consw fb_con;
 
-#define CM_SOFTBACK    (8)
-
 #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
 
 static int fbcon_set_origin(struct vc_data *);
@@ -373,18 +365,6 @@ static int get_color(struct vc_data *vc, struct fb_info *info,
        return color;
 }
 
-static void fbcon_update_softback(struct vc_data *vc)
-{
-       int l = fbcon_softback_size / vc->vc_size_row;
-
-       if (l > 5)
-               softback_end = softback_buf + l * vc->vc_size_row;
-       else
-               /* Smaller scrollback makes no sense, and 0 would screw
-                  the operation totally */
-               softback_top = 0;
-}
-
 static void fb_flashcursor(struct work_struct *work)
 {
        struct fb_info *info = container_of(work, struct fb_info, queue);
@@ -414,7 +394,7 @@ static void fb_flashcursor(struct work_struct *work)
        c = scr_readw((u16 *) vc->vc_pos);
        mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
                CM_ERASE : CM_DRAW;
-       ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
+       ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
                    get_color(vc, info, c, 0));
        console_unlock();
 }
@@ -471,13 +451,7 @@ static int __init fb_console_setup(char *this_opt)
                }
                
                if (!strncmp(options, "scrollback:", 11)) {
-                       options += 11;
-                       if (*options) {
-                               fbcon_softback_size = simple_strtoul(options, &options, 0);
-                               if (*options == 'k' || *options == 'K') {
-                                       fbcon_softback_size *= 1024;
-                               }
-                       }
+                       pr_warn("Ignoring scrollback size option\n");
                        continue;
                }
                
@@ -1022,31 +996,6 @@ static const char *fbcon_startup(void)
 
        set_blitting_type(vc, info);
 
-       if (info->fix.type != FB_TYPE_TEXT) {
-               if (fbcon_softback_size) {
-                       if (!softback_buf) {
-                               softback_buf =
-                                   (unsigned long)
-                                   kvmalloc(fbcon_softback_size,
-                                           GFP_KERNEL);
-                               if (!softback_buf) {
-                                       fbcon_softback_size = 0;
-                                       softback_top = 0;
-                               }
-                       }
-               } else {
-                       if (softback_buf) {
-                               kvfree((void *) softback_buf);
-                               softback_buf = 0;
-                               softback_top = 0;
-                       }
-               }
-               if (softback_buf)
-                       softback_in = softback_top = softback_curr =
-                           softback_buf;
-               softback_lines = 0;
-       }
-
        /* Setup default font */
        if (!p->fontdata && !vc->vc_font.data) {
                if (!fontname[0] || !(font = find_font(fontname)))
@@ -1220,9 +1169,6 @@ static void fbcon_init(struct vc_data *vc, int init)
        if (logo)
                fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
 
-       if (vc == svc && softback_buf)
-               fbcon_update_softback(vc);
-
        if (ops->rotate_font && ops->rotate_font(info, vc)) {
                ops->rotate = FB_ROTATE_UR;
                set_blitting_type(vc, info);
@@ -1385,7 +1331,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       int y;
        int c = scr_readw((u16 *) vc->vc_pos);
 
        ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
@@ -1399,16 +1344,8 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
                fbcon_add_cursor_timer(info);
 
        ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
-       if (mode & CM_SOFTBACK) {
-               mode &= ~CM_SOFTBACK;
-               y = softback_lines;
-       } else {
-               if (softback_lines)
-                       fbcon_set_origin(vc);
-               y = 0;
-       }
 
-       ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
+       ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
                    get_color(vc, info, c, 0));
 }
 
@@ -1479,8 +1416,6 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
 
        if (con_is_visible(vc)) {
                update_screen(vc);
-               if (softback_buf)
-                       fbcon_update_softback(vc);
        }
 }
 
@@ -1618,99 +1553,6 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
        scrollback_current = 0;
 }
 
-static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
-                                 long delta)
-{
-       int count = vc->vc_rows;
-       unsigned short *d, *s;
-       unsigned long n;
-       int line = 0;
-
-       d = (u16 *) softback_curr;
-       if (d == (u16 *) softback_in)
-               d = (u16 *) vc->vc_origin;
-       n = softback_curr + delta * vc->vc_size_row;
-       softback_lines -= delta;
-       if (delta < 0) {
-               if (softback_curr < softback_top && n < softback_buf) {
-                       n += softback_end - softback_buf;
-                       if (n < softback_top) {
-                               softback_lines -=
-                                   (softback_top - n) / vc->vc_size_row;
-                               n = softback_top;
-                       }
-               } else if (softback_curr >= softback_top
-                          && n < softback_top) {
-                       softback_lines -=
-                           (softback_top - n) / vc->vc_size_row;
-                       n = softback_top;
-               }
-       } else {
-               if (softback_curr > softback_in && n >= softback_end) {
-                       n += softback_buf - softback_end;
-                       if (n > softback_in) {
-                               n = softback_in;
-                               softback_lines = 0;
-                       }
-               } else if (softback_curr <= softback_in && n > softback_in) {
-                       n = softback_in;
-                       softback_lines = 0;
-               }
-       }
-       if (n == softback_curr)
-               return;
-       softback_curr = n;
-       s = (u16 *) softback_curr;
-       if (s == (u16 *) softback_in)
-               s = (u16 *) vc->vc_origin;
-       while (count--) {
-               unsigned short *start;
-               unsigned short *le;
-               unsigned short c;
-               int x = 0;
-               unsigned short attr = 1;
-
-               start = s;
-               le = advance_row(s, 1);
-               do {
-                       c = scr_readw(s);
-                       if (attr != (c & 0xff00)) {
-                               attr = c & 0xff00;
-                               if (s > start) {
-                                       fbcon_putcs(vc, start, s - start,
-                                                   line, x);
-                                       x += s - start;
-                                       start = s;
-                               }
-                       }
-                       if (c == scr_readw(d)) {
-                               if (s > start) {
-                                       fbcon_putcs(vc, start, s - start,
-                                                   line, x);
-                                       x += s - start + 1;
-                                       start = s + 1;
-                               } else {
-                                       x++;
-                                       start++;
-                               }
-                       }
-                       s++;
-                       d++;
-               } while (s < le);
-               if (s > start)
-                       fbcon_putcs(vc, start, s - start, line, x);
-               line++;
-               if (d == (u16 *) softback_end)
-                       d = (u16 *) softback_buf;
-               if (d == (u16 *) softback_in)
-                       d = (u16 *) vc->vc_origin;
-               if (s == (u16 *) softback_end)
-                       s = (u16 *) softback_buf;
-               if (s == (u16 *) softback_in)
-                       s = (u16 *) vc->vc_origin;
-       }
-}
-
 static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
                              int line, int count, int dy)
 {
@@ -1850,31 +1692,6 @@ static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
        }
 }
 
-static inline void fbcon_softback_note(struct vc_data *vc, int t,
-                                      int count)
-{
-       unsigned short *p;
-
-       if (vc->vc_num != fg_console)
-               return;
-       p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
-
-       while (count) {
-               scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
-               count--;
-               p = advance_row(p, 1);
-               softback_in += vc->vc_size_row;
-               if (softback_in == softback_end)
-                       softback_in = softback_buf;
-               if (softback_in == softback_top) {
-                       softback_top += vc->vc_size_row;
-                       if (softback_top == softback_end)
-                               softback_top = softback_buf;
-               }
-       }
-       softback_curr = softback_in;
-}
-
 static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                enum con_scroll dir, unsigned int count)
 {
@@ -1897,8 +1714,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
        case SM_UP:
                if (count > vc->vc_rows)        /* Maximum realistic size */
                        count = vc->vc_rows;
-               if (softback_top)
-                       fbcon_softback_note(vc, t, count);
                if (logo_shown >= 0)
                        goto redraw_up;
                switch (p->scrollmode) {
@@ -2203,7 +2018,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
        struct fb_var_screeninfo var = info->var;
        int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
 
-       if (ops->p && ops->p->userfont && FNTSIZE(vc->vc_font.data)) {
+       if (p->userfont && FNTSIZE(vc->vc_font.data)) {
                int size;
                int pitch = PITCH(vc->vc_font.width);
 
@@ -2269,14 +2084,6 @@ static int fbcon_switch(struct vc_data *vc)
        info = registered_fb[con2fb_map[vc->vc_num]];
        ops = info->fbcon_par;
 
-       if (softback_top) {
-               if (softback_lines)
-                       fbcon_set_origin(vc);
-               softback_top = softback_curr = softback_in = softback_buf;
-               softback_lines = 0;
-               fbcon_update_softback(vc);
-       }
-
        if (logo_shown >= 0) {
                struct vc_data *conp2 = vc_cons[logo_shown].d;
 
@@ -2492,6 +2299,9 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
 
        if (font->width <= 8) {
                j = vc->vc_font.height;
+               if (font->charcount * j > FNTSIZE(fontdata))
+                       return -EINVAL;
+
                for (i = 0; i < font->charcount; i++) {
                        memcpy(data, fontdata, j);
                        memset(data + j, 0, 32 - j);
@@ -2500,6 +2310,9 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
                }
        } else if (font->width <= 16) {
                j = vc->vc_font.height * 2;
+               if (font->charcount * j > FNTSIZE(fontdata))
+                       return -EINVAL;
+
                for (i = 0; i < font->charcount; i++) {
                        memcpy(data, fontdata, j);
                        memset(data + j, 0, 64 - j);
@@ -2507,6 +2320,9 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
                        fontdata += j;
                }
        } else if (font->width <= 24) {
+               if (font->charcount * (vc->vc_font.height * sizeof(u32)) > FNTSIZE(fontdata))
+                       return -EINVAL;
+
                for (i = 0; i < font->charcount; i++) {
                        for (j = 0; j < vc->vc_font.height; j++) {
                                *data++ = fontdata[0];
@@ -2519,6 +2335,9 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
                }
        } else {
                j = vc->vc_font.height * 4;
+               if (font->charcount * j > FNTSIZE(fontdata))
+                       return -EINVAL;
+
                for (i = 0; i < font->charcount; i++) {
                        memcpy(data, fontdata, j);
                        memset(data + j, 0, 128 - j);
@@ -2600,9 +2419,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
        int cnt;
        char *old_data = NULL;
 
-       if (con_is_visible(vc) && softback_lines)
-               fbcon_set_origin(vc);
-
        resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
        if (p->userfont)
                old_data = vc->vc_font.data;
@@ -2628,8 +2444,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
                cols /= w;
                rows /= h;
                vc_resize(vc, cols, rows);
-               if (con_is_visible(vc) && softback_buf)
-                       fbcon_update_softback(vc);
        } else if (con_is_visible(vc)
                   && vc->vc_mode == KD_TEXT) {
                fbcon_clear_margins(vc, 0);
@@ -2788,19 +2602,7 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
 
 static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
 {
-       unsigned long p;
-       int line;
-       
-       if (vc->vc_num != fg_console || !softback_lines)
-               return (u16 *) (vc->vc_origin + offset);
-       line = offset / vc->vc_size_row;
-       if (line >= softback_lines)
-               return (u16 *) (vc->vc_origin + offset -
-                               softback_lines * vc->vc_size_row);
-       p = softback_curr + offset;
-       if (p >= softback_end)
-               p += softback_buf - softback_end;
-       return (u16 *) p;
+       return (u16 *) (vc->vc_origin + offset);
 }
 
 static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
@@ -2814,22 +2616,7 @@ static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
 
                x = offset % vc->vc_cols;
                y = offset / vc->vc_cols;
-               if (vc->vc_num == fg_console)
-                       y += softback_lines;
                ret = pos + (vc->vc_cols - x) * 2;
-       } else if (vc->vc_num == fg_console && softback_lines) {
-               unsigned long offset = pos - softback_curr;
-
-               if (pos < softback_curr)
-                       offset += softback_end - softback_buf;
-               offset /= 2;
-               x = offset % vc->vc_cols;
-               y = offset / vc->vc_cols;
-               ret = pos + (vc->vc_cols - x) * 2;
-               if (ret == softback_end)
-                       ret = softback_buf;
-               if (ret == softback_in)
-                       ret = vc->vc_origin;
        } else {
                /* Should not happen */
                x = y = 0;
@@ -2857,106 +2644,11 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
                        a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
                            (((a) & 0x0700) << 4);
                scr_writew(a, p++);
-               if (p == (u16 *) softback_end)
-                       p = (u16 *) softback_buf;
-               if (p == (u16 *) softback_in)
-                       p = (u16 *) vc->vc_origin;
-       }
-}
-
-static void fbcon_scrolldelta(struct vc_data *vc, int lines)
-{
-       struct fb_info *info = registered_fb[con2fb_map[fg_console]];
-       struct fbcon_ops *ops = info->fbcon_par;
-       struct fbcon_display *disp = &fb_display[fg_console];
-       int offset, limit, scrollback_old;
-
-       if (softback_top) {
-               if (vc->vc_num != fg_console)
-                       return;
-               if (vc->vc_mode != KD_TEXT || !lines)
-                       return;
-               if (logo_shown >= 0) {
-                       struct vc_data *conp2 = vc_cons[logo_shown].d;
-
-                       if (conp2->vc_top == logo_lines
-                           && conp2->vc_bottom == conp2->vc_rows)
-                               conp2->vc_top = 0;
-                       if (logo_shown == vc->vc_num) {
-                               unsigned long p, q;
-                               int i;
-
-                               p = softback_in;
-                               q = vc->vc_origin +
-                                   logo_lines * vc->vc_size_row;
-                               for (i = 0; i < logo_lines; i++) {
-                                       if (p == softback_top)
-                                               break;
-                                       if (p == softback_buf)
-                                               p = softback_end;
-                                       p -= vc->vc_size_row;
-                                       q -= vc->vc_size_row;
-                                       scr_memcpyw((u16 *) q, (u16 *) p,
-                                                   vc->vc_size_row);
-                               }
-                               softback_in = softback_curr = p;
-                               update_region(vc, vc->vc_origin,
-                                             logo_lines * vc->vc_cols);
-                       }
-                       logo_shown = FBCON_LOGO_CANSHOW;
-               }
-               fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
-               fbcon_redraw_softback(vc, disp, lines);
-               fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
-               return;
        }
-
-       if (!scrollback_phys_max)
-               return;
-
-       scrollback_old = scrollback_current;
-       scrollback_current -= lines;
-       if (scrollback_current < 0)
-               scrollback_current = 0;
-       else if (scrollback_current > scrollback_max)
-               scrollback_current = scrollback_max;
-       if (scrollback_current == scrollback_old)
-               return;
-
-       if (fbcon_is_inactive(vc, info))
-               return;
-
-       fbcon_cursor(vc, CM_ERASE);
-
-       offset = disp->yscroll - scrollback_current;
-       limit = disp->vrows;
-       switch (disp->scrollmode) {
-       case SCROLL_WRAP_MOVE:
-               info->var.vmode |= FB_VMODE_YWRAP;
-               break;
-       case SCROLL_PAN_MOVE:
-       case SCROLL_PAN_REDRAW:
-               limit -= vc->vc_rows;
-               info->var.vmode &= ~FB_VMODE_YWRAP;
-               break;
-       }
-       if (offset < 0)
-               offset += limit;
-       else if (offset >= limit)
-               offset -= limit;
-
-       ops->var.xoffset = 0;
-       ops->var.yoffset = offset * vc->vc_font.height;
-       ops->update_start(info);
-
-       if (!scrollback_current)
-               fbcon_cursor(vc, CM_DRAW);
 }
 
 static int fbcon_set_origin(struct vc_data *vc)
 {
-       if (softback_lines)
-               fbcon_scrolldelta(vc, softback_lines);
        return 0;
 }
 
@@ -3020,8 +2712,6 @@ static void fbcon_modechanged(struct fb_info *info)
 
                fbcon_set_palette(vc, color_table);
                update_screen(vc);
-               if (softback_buf)
-                       fbcon_update_softback(vc);
        }
 }
 
@@ -3432,7 +3122,6 @@ static const struct consw fb_con = {
        .con_font_default       = fbcon_set_def_font,
        .con_font_copy          = fbcon_copy_font,
        .con_set_palette        = fbcon_set_palette,
-       .con_scrolldelta        = fbcon_scrolldelta,
        .con_set_origin         = fbcon_set_origin,
        .con_invert_region      = fbcon_invert_region,
        .con_screen_pos         = fbcon_screen_pos,
@@ -3667,9 +3356,6 @@ static void fbcon_exit(void)
        }
 #endif
 
-       kvfree((void *)softback_buf);
-       softback_buf = 0UL;
-
        for_each_registered_fb(i) {
                int pending = 0;
 
index 20dea85..9315b36 100644 (file)
@@ -62,7 +62,7 @@ struct fbcon_ops {
        void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
                              int color, int bottom_only);
        void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
-                      int softback_lines, int fg, int bg);
+                      int fg, int bg);
        int  (*update_start)(struct fb_info *info);
        int  (*rotate_font)(struct fb_info *info, struct vc_data *vc);
        struct fb_var_screeninfo var;  /* copy of the current fb_var_screeninfo */
@@ -152,13 +152,6 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
 #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
 #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
 
-/* Font */
-#define REFCOUNT(fd)   (((int *)(fd))[-1])
-#define FNTSIZE(fd)    (((int *)(fd))[-2])
-#define FNTCHARCNT(fd) (((int *)(fd))[-3])
-#define FNTSUM(fd)     (((int *)(fd))[-4])
-#define FONT_EXTRA_WORDS 4
-
     /*
      *  Scroll Method
      */
index 5b17713..bbd869e 100644 (file)
@@ -219,7 +219,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
 }
 
 static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
-                      int softback_lines, int fg, int bg)
+                      int fg, int bg)
 {
        struct fb_cursor cursor;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -236,15 +236,6 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 
        cursor.set = 0;
 
-       if (softback_lines) {
-               if (y + softback_lines >= vc->vc_rows) {
-                       mode = CM_ERASE;
-                       ops->cursor_flash = 0;
-                       return;
-               } else
-                       y += softback_lines;
-       }
-
        c = scr_readw((u16 *) vc->vc_pos);
        attribute = get_attribute(info, c);
        src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
index 894d01a..a34cbe8 100644 (file)
@@ -202,7 +202,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
 }
 
 static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
-                     int softback_lines, int fg, int bg)
+                     int fg, int bg)
 {
        struct fb_cursor cursor;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -219,15 +219,6 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 
        cursor.set = 0;
 
-       if (softback_lines) {
-               if (y + softback_lines >= vc->vc_rows) {
-                       mode = CM_ERASE;
-                       ops->cursor_flash = 0;
-                       return;
-               } else
-                       y += softback_lines;
-       }
-
        c = scr_readw((u16 *) vc->vc_pos);
        attribute = get_attribute(info, c);
        src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
index c0d4452..ac72d4f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/fb.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
+#include <linux/font.h>
 #include <asm/types.h>
 #include "fbcon.h"
 #include "fbcon_rotate.h"
index 01b87f2..199cbc7 100644 (file)
@@ -249,7 +249,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
 }
 
 static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
-                     int softback_lines, int fg, int bg)
+                     int fg, int bg)
 {
        struct fb_cursor cursor;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -267,15 +267,6 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
 
        cursor.set = 0;
 
-       if (softback_lines) {
-               if (y + softback_lines >= vc->vc_rows) {
-                       mode = CM_ERASE;
-                       ops->cursor_flash = 0;
-                       return;
-               } else
-                       y += softback_lines;
-       }
-
        c = scr_readw((u16 *) vc->vc_pos);
        attribute = get_attribute(info, c);
        src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
index 1dfaff0..628fe5e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/fb.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
+#include <linux/font.h>
 #include <asm/types.h>
 #include "fbcon.h"
 
@@ -80,7 +81,7 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
 }
 
 static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
-                       int softback_lines, int fg, int bg)
+                       int fg, int bg)
 {
        struct fb_tilecursor cursor;
        int use_sw = vc->vc_cursor_type & CUR_SW;
index a20eeb8..578d354 100644 (file)
@@ -1121,7 +1121,7 @@ static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *i
         char oldop = setop(0);
         char oldsr = setsr(0);
         char oldmask = selectmask();
-        const char *cdat = image->data;
+       const unsigned char *cdat = image->data;
        u32 dx = image->dx;
         char __iomem *where;
         int y;
index 90b8f56..6f02c18 100644 (file)
@@ -92,6 +92,8 @@ static bool (*pirq_needs_eoi)(unsigned irq);
 /* Xen will never allocate port zero for any purpose. */
 #define VALID_EVTCHN(chn)      ((chn) != 0)
 
+static struct irq_info *legacy_info_ptrs[NR_IRQS_LEGACY];
+
 static struct irq_chip xen_dynamic_chip;
 static struct irq_chip xen_percpu_chip;
 static struct irq_chip xen_pirq_chip;
@@ -156,7 +158,18 @@ int get_evtchn_to_irq(evtchn_port_t evtchn)
 /* Get info for IRQ */
 struct irq_info *info_for_irq(unsigned irq)
 {
-       return irq_get_chip_data(irq);
+       if (irq < nr_legacy_irqs())
+               return legacy_info_ptrs[irq];
+       else
+               return irq_get_chip_data(irq);
+}
+
+static void set_info_for_irq(unsigned int irq, struct irq_info *info)
+{
+       if (irq < nr_legacy_irqs())
+               legacy_info_ptrs[irq] = info;
+       else
+               irq_set_chip_data(irq, info);
 }
 
 /* Constructors for packed IRQ information. */
@@ -377,7 +390,7 @@ static void xen_irq_init(unsigned irq)
        info->type = IRQT_UNBOUND;
        info->refcnt = -1;
 
-       irq_set_chip_data(irq, info);
+       set_info_for_irq(irq, info);
 
        list_add_tail(&info->list, &xen_irq_list_head);
 }
@@ -426,14 +439,14 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi)
 
 static void xen_free_irq(unsigned irq)
 {
-       struct irq_info *info = irq_get_chip_data(irq);
+       struct irq_info *info = info_for_irq(irq);
 
        if (WARN_ON(!info))
                return;
 
        list_del(&info->list);
 
-       irq_set_chip_data(irq, NULL);
+       set_info_for_irq(irq, NULL);
 
        WARN_ON(info->refcnt > 0);
 
@@ -603,7 +616,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
 static void __unbind_from_irq(unsigned int irq)
 {
        evtchn_port_t evtchn = evtchn_from_irq(irq);
-       struct irq_info *info = irq_get_chip_data(irq);
+       struct irq_info *info = info_for_irq(irq);
 
        if (info->refcnt > 0) {
                info->refcnt--;
@@ -1108,7 +1121,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
 
 void unbind_from_irqhandler(unsigned int irq, void *dev_id)
 {
-       struct irq_info *info = irq_get_chip_data(irq);
+       struct irq_info *info = info_for_irq(irq);
 
        if (WARN_ON(!info))
                return;
@@ -1142,7 +1155,7 @@ int evtchn_make_refcounted(evtchn_port_t evtchn)
        if (irq == -1)
                return -ENOENT;
 
-       info = irq_get_chip_data(irq);
+       info = info_for_irq(irq);
 
        if (!info)
                return -ENOENT;
@@ -1170,7 +1183,7 @@ int evtchn_get(evtchn_port_t evtchn)
        if (irq == -1)
                goto done;
 
-       info = irq_get_chip_data(irq);
+       info = info_for_irq(irq);
 
        if (!info)
                goto done;
index 1d13d2e..0fe8844 100644 (file)
@@ -810,14 +810,32 @@ void afs_evict_inode(struct inode *inode)
 
 static void afs_setattr_success(struct afs_operation *op)
 {
-       struct inode *inode = &op->file[0].vnode->vfs_inode;
+       struct afs_vnode_param *vp = &op->file[0];
+       struct inode *inode = &vp->vnode->vfs_inode;
+       loff_t old_i_size = i_size_read(inode);
+
+       op->setattr.old_i_size = old_i_size;
+       afs_vnode_commit_status(op, vp);
+       /* inode->i_size has now been changed. */
+
+       if (op->setattr.attr->ia_valid & ATTR_SIZE) {
+               loff_t size = op->setattr.attr->ia_size;
+               if (size > old_i_size)
+                       pagecache_isize_extended(inode, old_i_size, size);
+       }
+}
+
+static void afs_setattr_edit_file(struct afs_operation *op)
+{
+       struct afs_vnode_param *vp = &op->file[0];
+       struct inode *inode = &vp->vnode->vfs_inode;
 
-       afs_vnode_commit_status(op, &op->file[0]);
        if (op->setattr.attr->ia_valid & ATTR_SIZE) {
-               loff_t i_size = inode->i_size, size = op->setattr.attr->ia_size;
-               if (size > i_size)
-                       pagecache_isize_extended(inode, i_size, size);
-               truncate_pagecache(inode, size);
+               loff_t size = op->setattr.attr->ia_size;
+               loff_t i_size = op->setattr.old_i_size;
+
+               if (size < i_size)
+                       truncate_pagecache(inode, size);
        }
 }
 
@@ -825,6 +843,7 @@ static const struct afs_operation_ops afs_setattr_operation = {
        .issue_afs_rpc  = afs_fs_setattr,
        .issue_yfs_rpc  = yfs_fs_setattr,
        .success        = afs_setattr_success,
+       .edit_dir       = afs_setattr_edit_file,
 };
 
 /*
@@ -863,11 +882,16 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
        if (S_ISREG(vnode->vfs_inode.i_mode))
                filemap_write_and_wait(vnode->vfs_inode.i_mapping);
 
+       /* Prevent any new writebacks from starting whilst we do this. */
+       down_write(&vnode->validate_lock);
+
        op = afs_alloc_operation(((attr->ia_valid & ATTR_FILE) ?
                                  afs_file_key(attr->ia_file) : NULL),
                                 vnode->volume);
-       if (IS_ERR(op))
-               return PTR_ERR(op);
+       if (IS_ERR(op)) {
+               ret = PTR_ERR(op);
+               goto out_unlock;
+       }
 
        afs_op_set_vnode(op, 0, vnode);
        op->setattr.attr = attr;
@@ -880,5 +904,10 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
        op->file[0].update_ctime = 1;
 
        op->ops = &afs_setattr_operation;
-       return afs_do_sync_operation(op);
+       ret = afs_do_sync_operation(op);
+
+out_unlock:
+       up_write(&vnode->validate_lock);
+       _leave(" = %d", ret);
+       return ret;
 }
index 18042b7..e5f0446 100644 (file)
@@ -812,6 +812,7 @@ struct afs_operation {
                } store;
                struct {
                        struct iattr    *attr;
+                       loff_t          old_i_size;
                } setattr;
                struct afs_acl  *acl;
                struct yfs_acl  *yacl;
index 4b2265c..da12abd 100644 (file)
@@ -738,11 +738,21 @@ static int afs_writepages_region(struct address_space *mapping,
 int afs_writepages(struct address_space *mapping,
                   struct writeback_control *wbc)
 {
+       struct afs_vnode *vnode = AFS_FS_I(mapping->host);
        pgoff_t start, end, next;
        int ret;
 
        _enter("");
 
+       /* We have to be careful as we can end up racing with setattr()
+        * truncating the pagecache since the caller doesn't take a lock here
+        * to prevent it.
+        */
+       if (wbc->sync_mode == WB_SYNC_ALL)
+               down_read(&vnode->validate_lock);
+       else if (!down_read_trylock(&vnode->validate_lock))
+               return 0;
+
        if (wbc->range_cyclic) {
                start = mapping->writeback_index;
                end = -1;
@@ -762,6 +772,7 @@ int afs_writepages(struct address_space *mapping,
                ret = afs_writepages_region(mapping, wbc, start, end, &next);
        }
 
+       up_read(&vnode->validate_lock);
        _leave(" = %d", ret);
        return ret;
 }
index 74c886f..5ced859 100644 (file)
@@ -53,7 +53,7 @@ static int autofs_write(struct autofs_sb_info *sbi,
 
        mutex_lock(&sbi->pipe_mutex);
        while (bytes) {
-               wr = kernel_write(file, data, bytes, &file->f_pos);
+               wr = __kernel_write(file, data, bytes, NULL);
                if (wr <= 0)
                        break;
                data += wr;
index db93909..e4a1c6a 100644 (file)
@@ -599,6 +599,37 @@ static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info)
        wake_up(&fs_info->dev_replace.replace_wait);
 }
 
+/*
+ * When finishing the device replace, before swapping the source device with the
+ * target device we must update the chunk allocation state in the target device,
+ * as it is empty because replace works by directly copying the chunks and not
+ * through the normal chunk allocation path.
+ */
+static int btrfs_set_target_alloc_state(struct btrfs_device *srcdev,
+                                       struct btrfs_device *tgtdev)
+{
+       struct extent_state *cached_state = NULL;
+       u64 start = 0;
+       u64 found_start;
+       u64 found_end;
+       int ret = 0;
+
+       lockdep_assert_held(&srcdev->fs_info->chunk_mutex);
+
+       while (!find_first_extent_bit(&srcdev->alloc_state, start,
+                                     &found_start, &found_end,
+                                     CHUNK_ALLOCATED, &cached_state)) {
+               ret = set_extent_bits(&tgtdev->alloc_state, found_start,
+                                     found_end, CHUNK_ALLOCATED);
+               if (ret)
+                       break;
+               start = found_end + 1;
+       }
+
+       free_extent_state(cached_state);
+       return ret;
+}
+
 static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
                                       int scrub_ret)
 {
@@ -673,8 +704,14 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        dev_replace->time_stopped = ktime_get_real_seconds();
        dev_replace->item_needs_writeback = 1;
 
-       /* replace old device with new one in mapping tree */
+       /*
+        * Update allocation state in the new device and replace the old device
+        * with the new one in the mapping tree.
+        */
        if (!scrub_ret) {
+               scrub_ret = btrfs_set_target_alloc_state(src_device, tgt_device);
+               if (scrub_ret)
+                       goto error;
                btrfs_dev_replace_update_device_in_mapping_tree(fs_info,
                                                                src_device,
                                                                tgt_device);
@@ -685,6 +722,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
                                 btrfs_dev_name(src_device),
                                 src_device->devid,
                                 rcu_str_deref(tgt_device->name), scrub_ret);
+error:
                up_write(&dev_replace->rwsem);
                mutex_unlock(&fs_info->chunk_mutex);
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
@@ -745,7 +783,9 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        /* replace the sysfs entry */
        btrfs_sysfs_remove_devices_dir(fs_info->fs_devices, src_device);
        btrfs_sysfs_update_devid(tgt_device);
-       btrfs_rm_dev_replace_free_srcdev(src_device);
+       if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &src_device->dev_state))
+               btrfs_scratch_superblocks(fs_info, src_device->bdev,
+                                         src_device->name->str);
 
        /* write back the superblocks */
        trans = btrfs_start_transaction(root, 0);
@@ -754,6 +794,8 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
 
        mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
 
+       btrfs_rm_dev_replace_free_srcdev(src_device);
+
        return 0;
 }
 
index f6bba7e..9f72b09 100644 (file)
@@ -636,16 +636,15 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
        csum_tree_block(eb, result);
 
        if (memcmp_extent_buffer(eb, result, 0, csum_size)) {
-               u32 val;
-               u32 found = 0;
-
-               memcpy(&found, result, csum_size);
+               u8 val[BTRFS_CSUM_SIZE] = { 0 };
 
                read_extent_buffer(eb, &val, 0, csum_size);
                btrfs_warn_rl(fs_info,
-               "%s checksum verify failed on %llu wanted %x found %x level %d",
+       "%s checksum verify failed on %llu wanted " CSUM_FMT " found " CSUM_FMT " level %d",
                              fs_info->sb->s_id, eb->start,
-                             val, found, btrfs_header_level(eb));
+                             CSUM_FMT_VALUE(csum_size, val),
+                             CSUM_FMT_VALUE(csum_size, result),
+                             btrfs_header_level(eb));
                ret = -EUCLEAN;
                goto err;
        }
@@ -3418,6 +3417,8 @@ fail_block_groups:
        btrfs_put_block_group_cache(fs_info);
 
 fail_tree_roots:
+       if (fs_info->data_reloc_root)
+               btrfs_drop_and_free_fs_root(fs_info, fs_info->data_reloc_root);
        free_root_pointers(fs_info, true);
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
 
index e9eedc0..780b9c9 100644 (file)
@@ -400,12 +400,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
                        if (type == BTRFS_SHARED_BLOCK_REF_KEY) {
                                ASSERT(eb->fs_info);
                                /*
-                                * Every shared one has parent tree
-                                * block, which must be aligned to
-                                * nodesize.
+                                * Every shared one has parent tree block,
+                                * which must be aligned to sector size.
                                 */
                                if (offset &&
-                                   IS_ALIGNED(offset, eb->fs_info->nodesize))
+                                   IS_ALIGNED(offset, eb->fs_info->sectorsize))
                                        return type;
                        }
                } else if (is_data == BTRFS_REF_TYPE_DATA) {
@@ -414,12 +413,11 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
                        if (type == BTRFS_SHARED_DATA_REF_KEY) {
                                ASSERT(eb->fs_info);
                                /*
-                                * Every shared one has parent tree
-                                * block, which must be aligned to
-                                * nodesize.
+                                * Every shared one has parent tree block,
+                                * which must be aligned to sector size.
                                 */
                                if (offset &&
-                                   IS_ALIGNED(offset, eb->fs_info->nodesize))
+                                   IS_ALIGNED(offset, eb->fs_info->sectorsize))
                                        return type;
                        }
                } else {
@@ -429,8 +427,9 @@ int btrfs_get_extent_inline_ref_type(const struct extent_buffer *eb,
        }
 
        btrfs_print_leaf((struct extent_buffer *)eb);
-       btrfs_err(eb->fs_info, "eb %llu invalid extent inline ref type %d",
-                 eb->start, type);
+       btrfs_err(eb->fs_info,
+                 "eb %llu iref 0x%lx invalid extent inline ref type %d",
+                 eb->start, (unsigned long)iref, type);
        WARN_ON(1);
 
        return BTRFS_REF_TYPE_INVALID;
index ac45f02..2d9109d 100644 (file)
@@ -2193,7 +2193,8 @@ static noinline int search_ioctl(struct inode *inode,
        key.offset = sk->min_offset;
 
        while (1) {
-               ret = fault_in_pages_writeable(ubuf, *buf_size - sk_offset);
+               ret = fault_in_pages_writeable(ubuf + sk_offset,
+                                              *buf_size - sk_offset);
                if (ret)
                        break;
 
index 61f44e7..80567c1 100644 (file)
@@ -95,9 +95,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
                         * offset is supposed to be a tree block which
                         * must be aligned to nodesize.
                         */
-                       if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
-                               pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n",
-                                       offset, (unsigned long long)eb->fs_info->nodesize);
+                       if (!IS_ALIGNED(offset, eb->fs_info->sectorsize))
+                               pr_info(
+                       "\t\t\t(parent %llu not aligned to sectorsize %u)\n",
+                                       offset, eb->fs_info->sectorsize);
                        break;
                case BTRFS_EXTENT_DATA_REF_KEY:
                        dref = (struct btrfs_extent_data_ref *)(&iref->offset);
@@ -112,8 +113,9 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
                         * must be aligned to nodesize.
                         */
                        if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
-                               pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n",
-                                    offset, (unsigned long long)eb->fs_info->nodesize);
+                               pr_info(
+                       "\t\t\t(parent %llu not aligned to sectorsize %u)\n",
+                                    offset, eb->fs_info->sectorsize);
                        break;
                default:
                        pr_cont("(extent %llu has INVALID ref type %d)\n",
index c8df2ed..5be3006 100644 (file)
@@ -1170,10 +1170,12 @@ int btrfs_sysfs_remove_devices_dir(struct btrfs_fs_devices *fs_devices,
                                          disk_kobj->name);
                }
 
-               kobject_del(&one_device->devid_kobj);
-               kobject_put(&one_device->devid_kobj);
+               if (one_device->devid_kobj.state_initialized) {
+                       kobject_del(&one_device->devid_kobj);
+                       kobject_put(&one_device->devid_kobj);
 
-               wait_for_completion(&one_device->kobj_unregister);
+                       wait_for_completion(&one_device->kobj_unregister);
+               }
 
                return 0;
        }
@@ -1186,10 +1188,12 @@ int btrfs_sysfs_remove_devices_dir(struct btrfs_fs_devices *fs_devices,
                        sysfs_remove_link(fs_devices->devices_kobj,
                                          disk_kobj->name);
                }
-               kobject_del(&one_device->devid_kobj);
-               kobject_put(&one_device->devid_kobj);
+               if (one_device->devid_kobj.state_initialized) {
+                       kobject_del(&one_device->devid_kobj);
+                       kobject_put(&one_device->devid_kobj);
 
-               wait_for_completion(&one_device->kobj_unregister);
+                       wait_for_completion(&one_device->kobj_unregister);
+               }
        }
 
        return 0;
index 20c6ac1..d2fc292 100644 (file)
@@ -1636,6 +1636,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        pending->snap = btrfs_get_new_fs_root(fs_info, objectid, pending->anon_dev);
        if (IS_ERR(pending->snap)) {
                ret = PTR_ERR(pending->snap);
+               pending->snap = NULL;
                btrfs_abort_transaction(trans, ret);
                goto fail;
        }
index 214856c..1997a7d 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/bio.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
@@ -1998,9 +1999,9 @@ static u64 btrfs_num_devices(struct btrfs_fs_info *fs_info)
        return num_devices;
 }
 
-static void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
-                                     struct block_device *bdev,
-                                     const char *device_path)
+void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
+                              struct block_device *bdev,
+                              const char *device_path)
 {
        struct btrfs_super_block *disk_super;
        int copy_num;
@@ -2223,11 +2224,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
        struct btrfs_fs_info *fs_info = srcdev->fs_info;
        struct btrfs_fs_devices *fs_devices = srcdev->fs_devices;
 
-       if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &srcdev->dev_state)) {
-               /* zero out the old super if it is writable */
-               btrfs_scratch_superblocks(fs_info, srcdev->bdev,
-                                         srcdev->name->str);
-       }
+       mutex_lock(&uuid_mutex);
 
        btrfs_close_bdev(srcdev);
        synchronize_rcu();
@@ -2257,6 +2254,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
                close_fs_devices(fs_devices);
                free_fs_devices(fs_devices);
        }
+       mutex_unlock(&uuid_mutex);
 }
 
 void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
@@ -6484,8 +6482,17 @@ static struct btrfs_device *add_missing_dev(struct btrfs_fs_devices *fs_devices,
                                            u64 devid, u8 *dev_uuid)
 {
        struct btrfs_device *device;
+       unsigned int nofs_flag;
 
+       /*
+        * We call this under the chunk_mutex, so we want to use NOFS for this
+        * allocation, however we don't want to change btrfs_alloc_device() to
+        * always do NOFS because we use it in a lot of other GFP_KERNEL safe
+        * places.
+        */
+       nofs_flag = memalloc_nofs_save();
        device = btrfs_alloc_device(NULL, &devid, dev_uuid);
+       memalloc_nofs_restore(nofs_flag);
        if (IS_ERR(device))
                return device;
 
index 5eea939..302c923 100644 (file)
@@ -573,6 +573,9 @@ void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info);
 void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info);
 bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info,
                                        struct btrfs_device *failing_dev);
+void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
+                              struct block_device *bdev,
+                              const char *device_path);
 
 int btrfs_bg_type_to_factor(u64 flags);
 const char *btrfs_bg_type_to_raid_name(u64 flags);
index 3989d08..1f75b25 100644 (file)
@@ -1017,6 +1017,8 @@ handle_mnt_opt:
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
                rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, true,
                                       full_path, fid);
+               if (rc == -EREMOTE)
+                       rc = 0;
                if (rc) {
                        cifs_dbg(FYI, "%s: Get mode from SID failed. rc=%d\n",
                                 __func__, rc);
@@ -1025,6 +1027,8 @@ handle_mnt_opt:
        } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                rc = cifs_acl_to_fattr(cifs_sb, &fattr, *inode, false,
                                       full_path, fid);
+               if (rc == -EREMOTE)
+                       rc = 0;
                if (rc) {
                        cifs_dbg(FYI, "%s: Getting ACL failed with error: %d\n",
                                 __func__, rc);
index b167d2d..a768a09 100644 (file)
@@ -177,7 +177,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
                goto out;
 
        if (!fops_get(real_fops)) {
-#ifdef MODULE
+#ifdef CONFIG_MODULES
                if (real_fops->owner &&
                    real_fops->owner->state == MODULE_STATE_GOING)
                        goto out;
@@ -312,7 +312,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
                goto out;
 
        if (!fops_get(real_fops)) {
-#ifdef MODULE
+#ifdef CONFIG_MODULES
                if (real_fops->owner &&
                    real_fops->owner->state == MODULE_STATE_GOING)
                        goto out;
index 8107e06..4df6112 100644 (file)
@@ -218,8 +218,7 @@ struct eventpoll {
        struct file *file;
 
        /* used to optimize loop detection check */
-       struct list_head visited_list_link;
-       int visited;
+       u64 gen;
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
        /* used to track busy poll napi_id */
@@ -274,6 +273,8 @@ static long max_user_watches __read_mostly;
  */
 static DEFINE_MUTEX(epmutex);
 
+static u64 loop_check_gen = 0;
+
 /* Used to check for epoll file descriptor inclusion loops */
 static struct nested_calls poll_loop_ncalls;
 
@@ -283,9 +284,6 @@ static struct kmem_cache *epi_cache __read_mostly;
 /* Slab cache used to allocate "struct eppoll_entry" */
 static struct kmem_cache *pwq_cache __read_mostly;
 
-/* Visited nodes during ep_loop_check(), so we can unset them when we finish */
-static LIST_HEAD(visited_list);
-
 /*
  * List of files with newly added links, where we may need to limit the number
  * of emanating paths. Protected by the epmutex.
@@ -1450,7 +1448,7 @@ static int reverse_path_check(void)
 
 static int ep_create_wakeup_source(struct epitem *epi)
 {
-       const char *name;
+       struct name_snapshot n;
        struct wakeup_source *ws;
 
        if (!epi->ep->ws) {
@@ -1459,8 +1457,9 @@ static int ep_create_wakeup_source(struct epitem *epi)
                        return -ENOMEM;
        }
 
-       name = epi->ffd.file->f_path.dentry->d_name.name;
-       ws = wakeup_source_register(NULL, name);
+       take_dentry_name_snapshot(&n, epi->ffd.file->f_path.dentry);
+       ws = wakeup_source_register(NULL, n.name.name);
+       release_dentry_name_snapshot(&n);
 
        if (!ws)
                return -ENOMEM;
@@ -1522,6 +1521,22 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
                RCU_INIT_POINTER(epi->ws, NULL);
        }
 
+       /* Add the current item to the list of active epoll hook for this file */
+       spin_lock(&tfile->f_lock);
+       list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links);
+       spin_unlock(&tfile->f_lock);
+
+       /*
+        * Add the current item to the RB tree. All RB tree operations are
+        * protected by "mtx", and ep_insert() is called with "mtx" held.
+        */
+       ep_rbtree_insert(ep, epi);
+
+       /* now check if we've created too many backpaths */
+       error = -EINVAL;
+       if (full_check && reverse_path_check())
+               goto error_remove_epi;
+
        /* Initialize the poll table using the queue callback */
        epq.epi = epi;
        init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
@@ -1544,22 +1559,6 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
        if (epi->nwait < 0)
                goto error_unregister;
 
-       /* Add the current item to the list of active epoll hook for this file */
-       spin_lock(&tfile->f_lock);
-       list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links);
-       spin_unlock(&tfile->f_lock);
-
-       /*
-        * Add the current item to the RB tree. All RB tree operations are
-        * protected by "mtx", and ep_insert() is called with "mtx" held.
-        */
-       ep_rbtree_insert(ep, epi);
-
-       /* now check if we've created too many backpaths */
-       error = -EINVAL;
-       if (full_check && reverse_path_check())
-               goto error_remove_epi;
-
        /* We have to drop the new item inside our item list to keep track of it */
        write_lock_irq(&ep->lock);
 
@@ -1588,6 +1587,8 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
 
        return 0;
 
+error_unregister:
+       ep_unregister_pollwait(ep, epi);
 error_remove_epi:
        spin_lock(&tfile->f_lock);
        list_del_rcu(&epi->fllink);
@@ -1595,9 +1596,6 @@ error_remove_epi:
 
        rb_erase_cached(&epi->rbn, &ep->rbr);
 
-error_unregister:
-       ep_unregister_pollwait(ep, epi);
-
        /*
         * We need to do this because an event could have been arrived on some
         * allocated wait queue. Note that we don't care about the ep->ovflist
@@ -1972,13 +1970,12 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
        struct epitem *epi;
 
        mutex_lock_nested(&ep->mtx, call_nests + 1);
-       ep->visited = 1;
-       list_add(&ep->visited_list_link, &visited_list);
+       ep->gen = loop_check_gen;
        for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
                epi = rb_entry(rbp, struct epitem, rbn);
                if (unlikely(is_file_epoll(epi->ffd.file))) {
                        ep_tovisit = epi->ffd.file->private_data;
-                       if (ep_tovisit->visited)
+                       if (ep_tovisit->gen == loop_check_gen)
                                continue;
                        error = ep_call_nested(&poll_loop_ncalls,
                                        ep_loop_check_proc, epi->ffd.file,
@@ -2019,18 +2016,8 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
  */
 static int ep_loop_check(struct eventpoll *ep, struct file *file)
 {
-       int ret;
-       struct eventpoll *ep_cur, *ep_next;
-
-       ret = ep_call_nested(&poll_loop_ncalls,
+       return ep_call_nested(&poll_loop_ncalls,
                              ep_loop_check_proc, file, ep, current);
-       /* clear visited list */
-       list_for_each_entry_safe(ep_cur, ep_next, &visited_list,
-                                                       visited_list_link) {
-               ep_cur->visited = 0;
-               list_del(&ep_cur->visited_list_link);
-       }
-       return ret;
 }
 
 static void clear_tfile_check_list(void)
@@ -2195,11 +2182,13 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
                goto error_tgt_fput;
        if (op == EPOLL_CTL_ADD) {
                if (!list_empty(&f.file->f_ep_links) ||
+                               ep->gen == loop_check_gen ||
                                                is_file_epoll(tf.file)) {
                        mutex_unlock(&ep->mtx);
                        error = epoll_mutex_lock(&epmutex, 0, nonblock);
                        if (error)
                                goto error_tgt_fput;
+                       loop_check_gen++;
                        full_check = 1;
                        if (is_file_epoll(tf.file)) {
                                error = -ELOOP;
@@ -2263,6 +2252,7 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
 error_tgt_fput:
        if (full_check) {
                clear_tfile_check_list();
+               loop_check_gen++;
                mutex_unlock(&epmutex);
        }
 
index 03d0824..5a2f119 100644 (file)
@@ -17,7 +17,6 @@
 #include "exfat_raw.h"
 #include "exfat_fs.h"
 
-#define EXFAT_CACHE_VALID      0
 #define EXFAT_MAX_CACHE                16
 
 struct exfat_cache {
@@ -61,16 +60,6 @@ void exfat_cache_shutdown(void)
        kmem_cache_destroy(exfat_cachep);
 }
 
-void exfat_cache_init_inode(struct inode *inode)
-{
-       struct exfat_inode_info *ei = EXFAT_I(inode);
-
-       spin_lock_init(&ei->cache_lru_lock);
-       ei->nr_caches = 0;
-       ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
-       INIT_LIST_HEAD(&ei->cache_lru);
-}
-
 static inline struct exfat_cache *exfat_cache_alloc(void)
 {
        return kmem_cache_alloc(exfat_cachep, GFP_NOFS);
index 95d717f..c013fe9 100644 (file)
@@ -248,6 +248,8 @@ struct exfat_sb_info {
        struct rcu_head rcu;
 };
 
+#define EXFAT_CACHE_VALID      0
+
 /*
  * EXFAT file system inode in-memory data
  */
@@ -428,7 +430,6 @@ extern const struct dentry_operations exfat_utf8_dentry_ops;
 /* cache.c */
 int exfat_cache_init(void);
 void exfat_cache_shutdown(void);
-void exfat_cache_init_inode(struct inode *inode);
 void exfat_cache_inval_inode(struct inode *inode);
 int exfat_get_cluster(struct inode *inode, unsigned int cluster,
                unsigned int *fclus, unsigned int *dclus,
index 7f90204..a6de17c 100644 (file)
@@ -611,8 +611,6 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
        ei->i_crtime = info->crtime;
        inode->i_atime = info->atime;
 
-       exfat_cache_init_inode(inode);
-
        return 0;
 }
 
index e73f20f..c94ac23 100644 (file)
@@ -578,7 +578,8 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
        i_pos = exfat_make_i_pos(&info);
        inode = exfat_build_inode(sb, &info, i_pos);
-       if (IS_ERR(inode))
+       err = PTR_ERR_OR_ZERO(inode);
+       if (err)
                goto unlock;
 
        inode_inc_iversion(inode);
@@ -745,10 +746,9 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
 
        i_pos = exfat_make_i_pos(&info);
        inode = exfat_build_inode(sb, &info, i_pos);
-       if (IS_ERR(inode)) {
-               err = PTR_ERR(inode);
+       err = PTR_ERR_OR_ZERO(inode);
+       if (err)
                goto unlock;
-       }
 
        i_mode = inode->i_mode;
        alias = d_find_alias(inode);
@@ -890,10 +890,9 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        i_pos = exfat_make_i_pos(&info);
        inode = exfat_build_inode(sb, &info, i_pos);
-       if (IS_ERR(inode)) {
-               err = PTR_ERR(inode);
+       err = PTR_ERR_OR_ZERO(inode);
+       if (err)
                goto unlock;
-       }
 
        inode_inc_iversion(inode);
        inode->i_mtime = inode->i_atime = inode->i_ctime =
index 3b6a165..60b941b 100644 (file)
@@ -376,7 +376,6 @@ static int exfat_read_root(struct inode *inode)
        inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
                current_time(inode);
        exfat_truncate_atime(&inode->i_atime);
-       exfat_cache_init_inode(inode);
        return 0;
 }
 
@@ -763,6 +762,10 @@ static void exfat_inode_init_once(void *foo)
 {
        struct exfat_inode_info *ei = (struct exfat_inode_info *)foo;
 
+       spin_lock_init(&ei->cache_lru_lock);
+       ei->nr_caches = 0;
+       ei->cache_valid_id = EXFAT_CACHE_VALID + 1;
+       INIT_LIST_HEAD(&ei->cache_lru);
        INIT_HLIST_NODE(&ei->i_hash_fat);
        inode_init_once(&ei->vfs_inode);
 }
index ed2bca0..73683e5 100644 (file)
@@ -3550,6 +3550,9 @@ static int check_direct_IO(struct inode *inode, struct iov_iter *iter,
        unsigned long align = offset | iov_iter_alignment(iter);
        struct block_device *bdev = inode->i_sb->s_bdev;
 
+       if (iov_iter_rw(iter) == READ && offset >= i_size_read(inode))
+               return 1;
+
        if (align & blocksize_mask) {
                if (bdev)
                        blkbits = blksize_bits(bdev_logical_block_size(bdev));
index 3ad7bdb..cb1b5b6 100644 (file)
@@ -2373,6 +2373,9 @@ static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
        if (unlikely(nid >= nm_i->max_nid))
                nid = 0;
 
+       if (unlikely(nid % NAT_ENTRY_PER_BLOCK))
+               nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK;
+
        /* Enough entries */
        if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
                return 0;
index a65d357..e247a5e 100644 (file)
@@ -799,7 +799,7 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
 
                if (__is_large_section(sbi)) {
                        unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
-                       unsigned short valid_blocks =
+                       block_t valid_blocks =
                                get_valid_blocks(sbi, segno, true);
 
                        f2fs_bug_on(sbi, unlikely(!valid_blocks ||
@@ -815,7 +815,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
                enum dirty_type dirty_type)
 {
        struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
-       unsigned short valid_blocks;
+       block_t valid_blocks;
 
        if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type]))
                dirty_i->nr_dirty[dirty_type]--;
@@ -4316,8 +4316,8 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi)
        struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
        struct free_segmap_info *free_i = FREE_I(sbi);
        unsigned int segno = 0, offset = 0, secno;
-       unsigned short valid_blocks;
-       unsigned short blks_per_sec = BLKS_PER_SEC(sbi);
+       block_t valid_blocks;
+       block_t blks_per_sec = BLKS_PER_SEC(sbi);
 
        while (1) {
                /* find dirty segment based on free segmap */
index 1492271..58b27e4 100644 (file)
@@ -2184,7 +2184,7 @@ static int __init start_dirtytime_writeback(void)
 __initcall(start_dirtytime_writeback);
 
 int dirtytime_interval_handler(struct ctl_table *table, int write,
-                              void __user *buffer, size_t *lenp, loff_t *ppos)
+                              void *buffer, size_t *lenp, loff_t *ppos)
 {
        int ret;
 
index 6611ef3..43c165e 100644 (file)
@@ -3091,11 +3091,10 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        ssize_t ret = 0;
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
-       bool async_dio = ff->fc->async_dio;
        loff_t pos = 0;
        struct inode *inode;
        loff_t i_size;
-       size_t count = iov_iter_count(iter);
+       size_t count = iov_iter_count(iter), shortened = 0;
        loff_t offset = iocb->ki_pos;
        struct fuse_io_priv *io;
 
@@ -3103,17 +3102,9 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        inode = file->f_mapping->host;
        i_size = i_size_read(inode);
 
-       if ((iov_iter_rw(iter) == READ) && (offset > i_size))
+       if ((iov_iter_rw(iter) == READ) && (offset >= i_size))
                return 0;
 
-       /* optimization for short read */
-       if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) {
-               if (offset >= i_size)
-                       return 0;
-               iov_iter_truncate(iter, fuse_round_up(ff->fc, i_size - offset));
-               count = iov_iter_count(iter);
-       }
-
        io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
        if (!io)
                return -ENOMEM;
@@ -3129,15 +3120,22 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
         * By default, we want to optimize all I/Os with async request
         * submission to the client filesystem if supported.
         */
-       io->async = async_dio;
+       io->async = ff->fc->async_dio;
        io->iocb = iocb;
        io->blocking = is_sync_kiocb(iocb);
 
+       /* optimization for short read */
+       if (io->async && !io->write && offset + count > i_size) {
+               iov_iter_truncate(iter, fuse_round_up(ff->fc, i_size - offset));
+               shortened = count - iov_iter_count(iter);
+               count -= shortened;
+       }
+
        /*
         * We cannot asynchronously extend the size of a file.
         * In such case the aio will behave exactly like sync io.
         */
-       if ((offset + count > i_size) && iov_iter_rw(iter) == WRITE)
+       if ((offset + count > i_size) && io->write)
                io->blocking = true;
 
        if (io->async && io->blocking) {
@@ -3155,6 +3153,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        } else {
                ret = __fuse_direct_read(io, iter, &pos);
        }
+       iov_iter_reexpand(iter, iov_iter_count(iter) + shortened);
 
        if (io->async) {
                bool blocking = io->blocking;
index 3790c7f..aae0ef2 100644 (file)
@@ -1753,6 +1753,9 @@ static int io_req_task_work_add(struct io_kiocb *req, struct callback_head *cb,
        struct io_ring_ctx *ctx = req->ctx;
        int ret, notify;
 
+       if (tsk->flags & PF_EXITING)
+               return -ESRCH;
+
        /*
         * SQPOLL kernel thread doesn't need notification, just a wakeup. For
         * all other cases, use TWA_SIGNAL unconditionally to ensure we're
@@ -1787,8 +1790,10 @@ static void __io_req_task_cancel(struct io_kiocb *req, int error)
 static void io_req_task_cancel(struct callback_head *cb)
 {
        struct io_kiocb *req = container_of(cb, struct io_kiocb, task_work);
+       struct io_ring_ctx *ctx = req->ctx;
 
        __io_req_task_cancel(req, -ECANCELED);
+       percpu_ref_put(&ctx->refs);
 }
 
 static void __io_req_task_submit(struct io_kiocb *req)
@@ -2010,6 +2015,12 @@ static inline unsigned int io_put_rw_kbuf(struct io_kiocb *req)
 
 static inline bool io_run_task_work(void)
 {
+       /*
+        * Not safe to run on exiting task, and the task_work handling will
+        * not add work to such a task.
+        */
+       if (unlikely(current->flags & PF_EXITING))
+               return false;
        if (current->task_works) {
                __set_current_state(TASK_RUNNING);
                task_work_run();
@@ -2283,13 +2294,17 @@ static bool io_resubmit_prep(struct io_kiocb *req, int error)
                goto end_req;
        }
 
-       ret = io_import_iovec(rw, req, &iovec, &iter, false);
-       if (ret < 0)
-               goto end_req;
-       ret = io_setup_async_rw(req, iovec, inline_vecs, &iter, false);
-       if (!ret)
+       if (!req->io) {
+               ret = io_import_iovec(rw, req, &iovec, &iter, false);
+               if (ret < 0)
+                       goto end_req;
+               ret = io_setup_async_rw(req, iovec, inline_vecs, &iter, false);
+               if (!ret)
+                       return true;
+               kfree(iovec);
+       } else {
                return true;
-       kfree(iovec);
+       }
 end_req:
        req_set_fail_links(req);
        io_req_complete(req, ret);
@@ -3034,6 +3049,7 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode,
        if (!wake_page_match(wpq, key))
                return 0;
 
+       req->rw.kiocb.ki_flags &= ~IOCB_WAITQ;
        list_del_init(&wait->entry);
 
        init_task_work(&req->task_work, io_req_task_submit);
@@ -3091,6 +3107,7 @@ static bool io_rw_should_retry(struct io_kiocb *req)
        wait->wait.flags = 0;
        INIT_LIST_HEAD(&wait->wait.entry);
        kiocb->ki_flags |= IOCB_WAITQ;
+       kiocb->ki_flags &= ~IOCB_NOWAIT;
        kiocb->ki_waitq = wait;
 
        io_get_req_task(req);
@@ -3115,6 +3132,7 @@ static int io_read(struct io_kiocb *req, bool force_nonblock,
        struct iov_iter __iter, *iter = &__iter;
        ssize_t io_size, ret, ret2;
        size_t iov_count;
+       bool no_async;
 
        if (req->io)
                iter = &req->io->rw.iter;
@@ -3132,7 +3150,8 @@ static int io_read(struct io_kiocb *req, bool force_nonblock,
                kiocb->ki_flags &= ~IOCB_NOWAIT;
 
        /* If the file doesn't support async, just async punt */
-       if (force_nonblock && !io_file_supports_async(req->file, READ))
+       no_async = force_nonblock && !io_file_supports_async(req->file, READ);
+       if (no_async)
                goto copy_iov;
 
        ret = rw_verify_area(READ, req->file, io_kiocb_ppos(kiocb), iov_count);
@@ -3155,10 +3174,8 @@ static int io_read(struct io_kiocb *req, bool force_nonblock,
                        goto done;
                /* some cases will consume bytes even on error returns */
                iov_iter_revert(iter, iov_count - iov_iter_count(iter));
-               ret = io_setup_async_rw(req, iovec, inline_vecs, iter, false);
-               if (ret)
-                       goto out_free;
-               return -EAGAIN;
+               ret = 0;
+               goto copy_iov;
        } else if (ret < 0) {
                /* make sure -ERESTARTSYS -> -EINTR is done */
                goto done;
@@ -3176,6 +3193,8 @@ copy_iov:
                ret = ret2;
                goto out_free;
        }
+       if (no_async)
+               return -EAGAIN;
        /* it's copied and will be cleaned with ->io */
        iovec = NULL;
        /* now use our persistent iterator, if we aren't already */
@@ -3508,8 +3527,6 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
        const char __user *fname;
        int ret;
 
-       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
-               return -EINVAL;
        if (unlikely(sqe->ioprio || sqe->buf_index))
                return -EINVAL;
        if (unlikely(req->flags & REQ_F_FIXED_FILE))
@@ -3536,6 +3553,8 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        u64 flags, mode;
 
+       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
+               return -EINVAL;
        if (req->flags & REQ_F_NEED_CLEANUP)
                return 0;
        mode = READ_ONCE(sqe->len);
@@ -3550,6 +3569,8 @@ static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        size_t len;
        int ret;
 
+       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
+               return -EINVAL;
        if (req->flags & REQ_F_NEED_CLEANUP)
                return 0;
        how = u64_to_user_ptr(READ_ONCE(sqe->addr2));
@@ -3767,7 +3788,7 @@ static int io_epoll_ctl_prep(struct io_kiocb *req,
 #if defined(CONFIG_EPOLL)
        if (sqe->ioprio || sqe->buf_index)
                return -EINVAL;
-       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL)))
                return -EINVAL;
 
        req->epoll.epfd = READ_ONCE(sqe->fd);
@@ -3882,7 +3903,7 @@ static int io_fadvise(struct io_kiocb *req, bool force_nonblock)
 
 static int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
-       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL | IORING_SETUP_SQPOLL)))
                return -EINVAL;
        if (sqe->ioprio || sqe->buf_index)
                return -EINVAL;
@@ -4724,6 +4745,8 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode,
        if (mask && !(mask & poll->events))
                return 0;
 
+       list_del_init(&wait->entry);
+
        if (poll && poll->head) {
                bool done;
 
@@ -5399,6 +5422,8 @@ static int io_async_cancel(struct io_kiocb *req)
 static int io_files_update_prep(struct io_kiocb *req,
                                const struct io_uring_sqe *sqe)
 {
+       if (unlikely(req->ctx->flags & IORING_SETUP_SQPOLL))
+               return -EINVAL;
        if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT)))
                return -EINVAL;
        if (sqe->ioprio || sqe->rw_flags)
@@ -5449,6 +5474,8 @@ static int io_req_defer_prep(struct io_kiocb *req,
        if (unlikely(ret))
                return ret;
 
+       io_prep_async_work(req);
+
        switch (req->opcode) {
        case IORING_OP_NOP:
                break;
@@ -5646,6 +5673,11 @@ static void __io_clean_op(struct io_kiocb *req)
                        io_put_file(req, req->splice.file_in,
                                    (req->splice.flags & SPLICE_F_FD_IN_FIXED));
                        break;
+               case IORING_OP_OPENAT:
+               case IORING_OP_OPENAT2:
+                       if (req->open.filename)
+                               putname(req->open.filename);
+                       break;
                }
                req->flags &= ~REQ_F_NEED_CLEANUP;
        }
@@ -6323,9 +6355,6 @@ static void io_submit_state_start(struct io_submit_state *state,
                                  struct io_ring_ctx *ctx, unsigned int max_ios)
 {
        blk_start_plug(&state->plug);
-#ifdef CONFIG_BLOCK
-       state->plug.nowait = true;
-#endif
        state->comp.nr = 0;
        INIT_LIST_HEAD(&state->comp.list);
        state->comp.ctx = ctx;
@@ -8180,6 +8209,8 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
                /* cancel this request, or head link requests */
                io_attempt_cancel(ctx, cancel_req);
                io_put_req(cancel_req);
+               /* cancellations _may_ trigger task work */
+               io_run_task_work();
                schedule();
                finish_wait(&ctx->inflight_wait, &wait);
        }
@@ -8385,11 +8416,19 @@ static int io_uring_show_cred(int id, void *p, void *data)
 
 static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
 {
+       bool has_lock;
        int i;
 
-       mutex_lock(&ctx->uring_lock);
+       /*
+        * Avoid ABBA deadlock between the seq lock and the io_uring mutex,
+        * since fdinfo case grabs it in the opposite direction of normal use
+        * cases. If we fail to get the lock, we just don't iterate any
+        * structures that could be going away outside the io_uring mutex.
+        */
+       has_lock = mutex_trylock(&ctx->uring_lock);
+
        seq_printf(m, "UserFiles:\t%u\n", ctx->nr_user_files);
-       for (i = 0; i < ctx->nr_user_files; i++) {
+       for (i = 0; has_lock && i < ctx->nr_user_files; i++) {
                struct fixed_file_table *table;
                struct file *f;
 
@@ -8401,13 +8440,13 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
                        seq_printf(m, "%5u: <none>\n", i);
        }
        seq_printf(m, "UserBufs:\t%u\n", ctx->nr_user_bufs);
-       for (i = 0; i < ctx->nr_user_bufs; i++) {
+       for (i = 0; has_lock && i < ctx->nr_user_bufs; i++) {
                struct io_mapped_ubuf *buf = &ctx->user_bufs[i];
 
                seq_printf(m, "%5u: 0x%llx/%u\n", i, buf->ubuf,
                                                (unsigned int) buf->len);
        }
-       if (!idr_is_empty(&ctx->personality_idr)) {
+       if (has_lock && !idr_is_empty(&ctx->personality_idr)) {
                seq_printf(m, "Personalities:\n");
                idr_for_each(&ctx->personality_idr, io_uring_show_cred, m);
        }
@@ -8422,7 +8461,8 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
                                        req->task->task_works != NULL);
        }
        spin_unlock_irq(&ctx->completion_lock);
-       mutex_unlock(&ctx->uring_lock);
+       if (has_lock)
+               mutex_unlock(&ctx->uring_lock);
 }
 
 static void io_uring_show_fdinfo(struct seq_file *m, struct file *f)
index e732580..cb52db9 100644 (file)
@@ -579,6 +579,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
        xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
 
        do {
+               if (entry->label)
+                       entry->label->len = NFS4_MAXLABELLEN;
+
                status = xdr_decode(desc, entry, &stream);
                if (status != 0) {
                        if (status == -EAGAIN)
index ff8965d..a163533 100644 (file)
@@ -715,7 +715,7 @@ nfs4_ff_layout_stat_io_end_write(struct rpc_task *task,
 }
 
 static void
-ff_layout_mark_ds_unreachable(struct pnfs_layout_segment *lseg, int idx)
+ff_layout_mark_ds_unreachable(struct pnfs_layout_segment *lseg, u32 idx)
 {
        struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
 
@@ -724,7 +724,7 @@ ff_layout_mark_ds_unreachable(struct pnfs_layout_segment *lseg, int idx)
 }
 
 static void
-ff_layout_mark_ds_reachable(struct pnfs_layout_segment *lseg, int idx)
+ff_layout_mark_ds_reachable(struct pnfs_layout_segment *lseg, u32 idx)
 {
        struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
 
@@ -734,14 +734,14 @@ ff_layout_mark_ds_reachable(struct pnfs_layout_segment *lseg, int idx)
 
 static struct nfs4_pnfs_ds *
 ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg,
-                            int start_idx, int *best_idx,
+                            u32 start_idx, u32 *best_idx,
                             bool check_device)
 {
        struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg);
        struct nfs4_ff_layout_mirror *mirror;
        struct nfs4_pnfs_ds *ds;
        bool fail_return = false;
-       int idx;
+       u32 idx;
 
        /* mirrors are initially sorted by efficiency */
        for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) {
@@ -766,21 +766,21 @@ ff_layout_choose_ds_for_read(struct pnfs_layout_segment *lseg,
 
 static struct nfs4_pnfs_ds *
 ff_layout_choose_any_ds_for_read(struct pnfs_layout_segment *lseg,
-                                int start_idx, int *best_idx)
+                                u32 start_idx, u32 *best_idx)
 {
        return ff_layout_choose_ds_for_read(lseg, start_idx, best_idx, false);
 }
 
 static struct nfs4_pnfs_ds *
 ff_layout_choose_valid_ds_for_read(struct pnfs_layout_segment *lseg,
-                                  int start_idx, int *best_idx)
+                                  u32 start_idx, u32 *best_idx)
 {
        return ff_layout_choose_ds_for_read(lseg, start_idx, best_idx, true);
 }
 
 static struct nfs4_pnfs_ds *
 ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
-                                 int start_idx, int *best_idx)
+                                 u32 start_idx, u32 *best_idx)
 {
        struct nfs4_pnfs_ds *ds;
 
@@ -791,7 +791,8 @@ ff_layout_choose_best_ds_for_read(struct pnfs_layout_segment *lseg,
 }
 
 static struct nfs4_pnfs_ds *
-ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio, int *best_idx)
+ff_layout_get_ds_for_read(struct nfs_pageio_descriptor *pgio,
+                         u32 *best_idx)
 {
        struct pnfs_layout_segment *lseg = pgio->pg_lseg;
        struct nfs4_pnfs_ds *ds;
@@ -837,7 +838,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
        struct nfs_pgio_mirror *pgm;
        struct nfs4_ff_layout_mirror *mirror;
        struct nfs4_pnfs_ds *ds;
-       int ds_idx;
+       u32 ds_idx, i;
 
 retry:
        ff_layout_pg_check_layout(pgio, req);
@@ -863,14 +864,14 @@ retry:
                goto retry;
        }
 
-       mirror = FF_LAYOUT_COMP(pgio->pg_lseg, ds_idx);
+       for (i = 0; i < pgio->pg_mirror_count; i++) {
+               mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i);
+               pgm = &pgio->pg_mirrors[i];
+               pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
+       }
 
        pgio->pg_mirror_idx = ds_idx;
 
-       /* read always uses only one mirror - idx 0 for pgio layer */
-       pgm = &pgio->pg_mirrors[0];
-       pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
-
        if (NFS_SERVER(pgio->pg_inode)->flags &
                        (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR))
                pgio->pg_maxretrans = io_maxretrans;
@@ -894,7 +895,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        struct nfs4_ff_layout_mirror *mirror;
        struct nfs_pgio_mirror *pgm;
        struct nfs4_pnfs_ds *ds;
-       int i;
+       u32 i;
 
 retry:
        ff_layout_pg_check_layout(pgio, req);
@@ -1038,7 +1039,7 @@ static void ff_layout_reset_write(struct nfs_pgio_header *hdr, bool retry_pnfs)
 static void ff_layout_resend_pnfs_read(struct nfs_pgio_header *hdr)
 {
        u32 idx = hdr->pgio_mirror_idx + 1;
-       int new_idx = 0;
+       u32 new_idx = 0;
 
        if (ff_layout_choose_any_ds_for_read(hdr->lseg, idx + 1, &new_idx))
                ff_layout_send_layouterror(hdr->lseg);
@@ -1075,7 +1076,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
                                           struct nfs4_state *state,
                                           struct nfs_client *clp,
                                           struct pnfs_layout_segment *lseg,
-                                          int idx)
+                                          u32 idx)
 {
        struct pnfs_layout_hdr *lo = lseg->pls_layout;
        struct inode *inode = lo->plh_inode;
@@ -1149,7 +1150,7 @@ reset:
 /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */
 static int ff_layout_async_handle_error_v3(struct rpc_task *task,
                                           struct pnfs_layout_segment *lseg,
-                                          int idx)
+                                          u32 idx)
 {
        struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
 
@@ -1184,7 +1185,7 @@ static int ff_layout_async_handle_error(struct rpc_task *task,
                                        struct nfs4_state *state,
                                        struct nfs_client *clp,
                                        struct pnfs_layout_segment *lseg,
-                                       int idx)
+                                       u32 idx)
 {
        int vers = clp->cl_nfs_mod->rpc_vers->number;
 
@@ -1211,7 +1212,7 @@ static int ff_layout_async_handle_error(struct rpc_task *task,
 }
 
 static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg,
-                                       int idx, u64 offset, u64 length,
+                                       u32 idx, u64 offset, u64 length,
                                        u32 *op_status, int opnum, int error)
 {
        struct nfs4_ff_layout_mirror *mirror;
@@ -1809,7 +1810,7 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
        loff_t offset = hdr->args.offset;
        int vers;
        struct nfs_fh *fh;
-       int idx = hdr->pgio_mirror_idx;
+       u32 idx = hdr->pgio_mirror_idx;
 
        mirror = FF_LAYOUT_COMP(lseg, idx);
        ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true);
index 142225f..2b2211d 100644 (file)
@@ -356,7 +356,15 @@ static ssize_t _nfs42_proc_copy(struct file *src,
 
        truncate_pagecache_range(dst_inode, pos_dst,
                                 pos_dst + res->write_res.count);
-
+       spin_lock(&dst_inode->i_lock);
+       NFS_I(dst_inode)->cache_validity |= (NFS_INO_REVAL_PAGECACHE |
+                       NFS_INO_REVAL_FORCED | NFS_INO_INVALID_SIZE |
+                       NFS_INO_INVALID_ATTR | NFS_INO_INVALID_DATA);
+       spin_unlock(&dst_inode->i_lock);
+       spin_lock(&src_inode->i_lock);
+       NFS_I(src_inode)->cache_validity |= (NFS_INO_REVAL_PAGECACHE |
+                       NFS_INO_REVAL_FORCED | NFS_INO_INVALID_ATIME);
+       spin_unlock(&src_inode->i_lock);
        status = res->write_res.count;
 out:
        if (args->sync)
index f8946b9..6e95c85 100644 (file)
@@ -3293,8 +3293,10 @@ static int _nfs4_do_setattr(struct inode *inode,
 
        /* Servers should only apply open mode checks for file size changes */
        truncate = (arg->iap->ia_valid & ATTR_SIZE) ? true : false;
-       if (!truncate)
+       if (!truncate) {
+               nfs4_inode_make_writeable(inode);
                goto zero_stateid;
+       }
 
        if (nfs4_copy_delegation_stateid(inode, FMODE_WRITE, &arg->stateid, &delegation_cred)) {
                /* Use that stateid */
@@ -7298,7 +7300,12 @@ int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state,
        err = nfs4_set_lock_state(state, fl);
        if (err != 0)
                return err;
-       err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
+       do {
+               err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
+               if (err != -NFS4ERR_DELAY)
+                       break;
+               ssleep(1);
+       } while (err == -NFS4ERR_DELAY);
        return nfs4_handle_delegation_recall_error(server, state, stateid, fl, err);
 }
 
index 60dbee4..117db82 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -106,25 +106,6 @@ void pipe_double_lock(struct pipe_inode_info *pipe1,
        }
 }
 
-/* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct pipe_inode_info *pipe)
-{
-       DEFINE_WAIT(rdwait);
-       DEFINE_WAIT(wrwait);
-
-       /*
-        * Pipes are system-local resources, so sleeping on them
-        * is considered a noninteractive wait:
-        */
-       prepare_to_wait(&pipe->rd_wait, &rdwait, TASK_INTERRUPTIBLE);
-       prepare_to_wait(&pipe->wr_wait, &wrwait, TASK_INTERRUPTIBLE);
-       pipe_unlock(pipe);
-       schedule();
-       finish_wait(&pipe->rd_wait, &rdwait);
-       finish_wait(&pipe->wr_wait, &wrwait);
-       pipe_lock(pipe);
-}
-
 static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
                                  struct pipe_buffer *buf)
 {
@@ -1035,12 +1016,52 @@ SYSCALL_DEFINE1(pipe, int __user *, fildes)
        return do_pipe2(fildes, 0);
 }
 
+/*
+ * This is the stupid "wait for pipe to be readable or writable"
+ * model.
+ *
+ * See pipe_read/write() for the proper kind of exclusive wait,
+ * but that requires that we wake up any other readers/writers
+ * if we then do not end up reading everything (ie the whole
+ * "wake_next_reader/writer" logic in pipe_read/write()).
+ */
+void pipe_wait_readable(struct pipe_inode_info *pipe)
+{
+       pipe_unlock(pipe);
+       wait_event_interruptible(pipe->rd_wait, pipe_readable(pipe));
+       pipe_lock(pipe);
+}
+
+void pipe_wait_writable(struct pipe_inode_info *pipe)
+{
+       pipe_unlock(pipe);
+       wait_event_interruptible(pipe->wr_wait, pipe_writable(pipe));
+       pipe_lock(pipe);
+}
+
+/*
+ * This depends on both the wait (here) and the wakeup (wake_up_partner)
+ * holding the pipe lock, so "*cnt" is stable and we know a wakeup cannot
+ * race with the count check and waitqueue prep.
+ *
+ * Normally in order to avoid races, you'd do the prepare_to_wait() first,
+ * then check the condition you're waiting for, and only then sleep. But
+ * because of the pipe lock, we can check the condition before being on
+ * the wait queue.
+ *
+ * We use the 'rd_wait' waitqueue for pipe partner waiting.
+ */
 static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
 {
+       DEFINE_WAIT(rdwait);
        int cur = *cnt;
 
        while (cur == *cnt) {
-               pipe_wait(pipe);
+               prepare_to_wait(&pipe->rd_wait, &rdwait, TASK_INTERRUPTIBLE);
+               pipe_unlock(pipe);
+               schedule();
+               finish_wait(&pipe->rd_wait, &rdwait);
+               pipe_lock(pipe);
                if (signal_pending(current))
                        break;
        }
@@ -1050,7 +1071,6 @@ static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
 static void wake_up_partner(struct pipe_inode_info *pipe)
 {
        wake_up_interruptible_all(&pipe->rd_wait);
-       wake_up_interruptible_all(&pipe->wr_wait);
 }
 
 static int fifo_open(struct inode *inode, struct file *filp)
index 5db58b8..d342818 100644 (file)
@@ -538,6 +538,14 @@ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t
        inc_syscw(current);
        return ret;
 }
+/*
+ * This "EXPORT_SYMBOL_GPL()" is more of a "EXPORT_SYMBOL_DONTUSE()",
+ * but autofs is one of the few internal kernel users that actually
+ * wants this _and_ can be built as a module. So we need to export
+ * this symbol for autofs, even though it really isn't appropriate
+ * for any other kernel modules.
+ */
+EXPORT_SYMBOL_GPL(__kernel_write);
 
 ssize_t kernel_write(struct file *file, const void *buf, size_t count,
                            loff_t *pos)
index d7c8a7c..ce75aec 100644 (file)
@@ -526,6 +526,22 @@ static int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_des
        return 1;
 }
 
+/* We know we have a pipe buffer, but maybe it's empty? */
+static inline bool eat_empty_buffer(struct pipe_inode_info *pipe)
+{
+       unsigned int tail = pipe->tail;
+       unsigned int mask = pipe->ring_size - 1;
+       struct pipe_buffer *buf = &pipe->bufs[tail & mask];
+
+       if (unlikely(!buf->len)) {
+               pipe_buf_release(pipe, buf);
+               pipe->tail = tail+1;
+               return true;
+       }
+
+       return false;
+}
+
 /**
  * splice_from_pipe_next - wait for some data to splice from
  * @pipe:      pipe to splice from
@@ -545,6 +561,7 @@ static int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_des
        if (signal_pending(current))
                return -ERESTARTSYS;
 
+repeat:
        while (pipe_empty(pipe->head, pipe->tail)) {
                if (!pipe->writers)
                        return 0;
@@ -563,9 +580,12 @@ static int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_des
                        sd->need_wakeup = false;
                }
 
-               pipe_wait(pipe);
+               pipe_wait_readable(pipe);
        }
 
+       if (eat_empty_buffer(pipe))
+               goto repeat;
+
        return 1;
 }
 
@@ -1077,7 +1097,7 @@ static int wait_for_space(struct pipe_inode_info *pipe, unsigned flags)
                        return -EAGAIN;
                if (signal_pending(current))
                        return -ERESTARTSYS;
-               pipe_wait(pipe);
+               pipe_wait_writable(pipe);
        }
 }
 
@@ -1454,7 +1474,7 @@ static int ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
                        ret = -EAGAIN;
                        break;
                }
-               pipe_wait(pipe);
+               pipe_wait_readable(pipe);
        }
 
        pipe_unlock(pipe);
@@ -1493,7 +1513,7 @@ static int opipe_prep(struct pipe_inode_info *pipe, unsigned int flags)
                        ret = -ERESTARTSYS;
                        break;
                }
-               pipe_wait(pipe);
+               pipe_wait_writable(pipe);
        }
 
        pipe_unlock(pipe);
index 8fe03b4..25aade3 100644 (file)
@@ -384,7 +384,7 @@ fail_nomem:
 
 static int vboxsf_parse_monolithic(struct fs_context *fc, void *data)
 {
-       char *options = data;
+       unsigned char *options = data;
 
        if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 &&
                       options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 &&
index 5430feb..7636bc7 100644 (file)
 #define BTF                                                            \
        .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) {                           \
                __start_BTF = .;                                        \
-               *(.BTF)                                                 \
+               KEEP(*(.BTF))                                           \
                __stop_BTF = .;                                         \
        }                                                               \
        . = ALIGN(4);                                                   \
index 887954c..732f327 100644 (file)
@@ -588,7 +588,7 @@ struct drm_dsc_picture_parameter_set {
  * This structure represents the DSC PPS infoframe required to send the Picture
  * Parameter Set metadata required before enabling VESA Display Stream
  * Compression. This is based on the DP Secondary Data Packet structure and
- * comprises of SDP Header as defined &struct struct dp_sdp_header in drm_dp_helper.h
+ * comprises of SDP Header as defined &struct dp_sdp_header in drm_dp_helper.h
  * and PPS payload defined in &struct drm_dsc_picture_parameter_set.
  *
  * @pps_header: Header for PPS as per DP SDP header format of type
index 1e4cdc6..64ae25c 100644 (file)
@@ -958,7 +958,7 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
 acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
                                           u32 val_a, u32 val_b);
 
-#ifdef CONFIG_X86
+#ifndef CONFIG_IA64
 void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
 #else
 static inline void arch_reserve_mem_area(acpi_physical_address addr,
diff --git a/include/linux/amba/clcd-regs.h b/include/linux/amba/clcd-regs.h
new file mode 100644 (file)
index 0000000..421b0fa
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * David A Rusling
+ *
+ * Copyright (C) 2001 ARM Limited
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef AMBA_CLCD_REGS_H
+#define AMBA_CLCD_REGS_H
+
+/*
+ * CLCD Controller Internal Register addresses
+ */
+#define CLCD_TIM0              0x00000000
+#define CLCD_TIM1              0x00000004
+#define CLCD_TIM2              0x00000008
+#define CLCD_TIM3              0x0000000c
+#define CLCD_UBAS              0x00000010
+#define CLCD_LBAS              0x00000014
+
+#define CLCD_PL110_IENB                0x00000018
+#define CLCD_PL110_CNTL                0x0000001c
+#define CLCD_PL110_STAT                0x00000020
+#define CLCD_PL110_INTR        0x00000024
+#define CLCD_PL110_UCUR                0x00000028
+#define CLCD_PL110_LCUR                0x0000002C
+
+#define CLCD_PL111_CNTL                0x00000018
+#define CLCD_PL111_IENB                0x0000001c
+#define CLCD_PL111_RIS         0x00000020
+#define CLCD_PL111_MIS         0x00000024
+#define CLCD_PL111_ICR         0x00000028
+#define CLCD_PL111_UCUR                0x0000002c
+#define CLCD_PL111_LCUR                0x00000030
+
+#define CLCD_PALL              0x00000200
+#define CLCD_PALETTE           0x00000200
+
+#define TIM2_PCD_LO_MASK       GENMASK(4, 0)
+#define TIM2_PCD_LO_BITS       5
+#define TIM2_CLKSEL            (1 << 5)
+#define TIM2_ACB_MASK          GENMASK(10, 6)
+#define TIM2_IVS               (1 << 11)
+#define TIM2_IHS               (1 << 12)
+#define TIM2_IPC               (1 << 13)
+#define TIM2_IOE               (1 << 14)
+#define TIM2_BCD               (1 << 26)
+#define TIM2_PCD_HI_MASK       GENMASK(31, 27)
+#define TIM2_PCD_HI_BITS       5
+#define TIM2_PCD_HI_SHIFT      27
+
+#define CNTL_LCDEN             (1 << 0)
+#define CNTL_LCDBPP1           (0 << 1)
+#define CNTL_LCDBPP2           (1 << 1)
+#define CNTL_LCDBPP4           (2 << 1)
+#define CNTL_LCDBPP8           (3 << 1)
+#define CNTL_LCDBPP16          (4 << 1)
+#define CNTL_LCDBPP16_565      (6 << 1)
+#define CNTL_LCDBPP16_444      (7 << 1)
+#define CNTL_LCDBPP24          (5 << 1)
+#define CNTL_LCDBW             (1 << 4)
+#define CNTL_LCDTFT            (1 << 5)
+#define CNTL_LCDMONO8          (1 << 6)
+#define CNTL_LCDDUAL           (1 << 7)
+#define CNTL_BGR               (1 << 8)
+#define CNTL_BEBO              (1 << 9)
+#define CNTL_BEPO              (1 << 10)
+#define CNTL_LCDPWR            (1 << 11)
+#define CNTL_LCDVCOMP(x)       ((x) << 12)
+#define CNTL_LDMAFIFOTIME      (1 << 15)
+#define CNTL_WATERMARK         (1 << 16)
+
+/* ST Microelectronics variant bits */
+#define CNTL_ST_1XBPP_444      0x0
+#define CNTL_ST_1XBPP_5551     (1 << 17)
+#define CNTL_ST_1XBPP_565      (1 << 18)
+#define CNTL_ST_CDWID_12       0x0
+#define CNTL_ST_CDWID_16       (1 << 19)
+#define CNTL_ST_CDWID_18       (1 << 20)
+#define CNTL_ST_CDWID_24       ((1 << 19)|(1 << 20))
+#define CNTL_ST_CEAEN          (1 << 21)
+#define CNTL_ST_LCDBPP24_PACKED        (6 << 1)
+
+#endif /* AMBA_CLCD_REGS_H */
diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h
new file mode 100644 (file)
index 0000000..b6e0cbe
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * linux/include/asm-arm/hardware/amba_clcd.h -- Integrator LCD panel.
+ *
+ * David A Rusling
+ *
+ * Copyright (C) 2001 ARM Limited
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+#include <linux/fb.h>
+#include <linux/amba/clcd-regs.h>
+
+enum {
+       /* individual formats */
+       CLCD_CAP_RGB444         = (1 << 0),
+       CLCD_CAP_RGB5551        = (1 << 1),
+       CLCD_CAP_RGB565         = (1 << 2),
+       CLCD_CAP_RGB888         = (1 << 3),
+       CLCD_CAP_BGR444         = (1 << 4),
+       CLCD_CAP_BGR5551        = (1 << 5),
+       CLCD_CAP_BGR565         = (1 << 6),
+       CLCD_CAP_BGR888         = (1 << 7),
+
+       /* connection layouts */
+       CLCD_CAP_444            = CLCD_CAP_RGB444 | CLCD_CAP_BGR444,
+       CLCD_CAP_5551           = CLCD_CAP_RGB5551 | CLCD_CAP_BGR5551,
+       CLCD_CAP_565            = CLCD_CAP_RGB565 | CLCD_CAP_BGR565,
+       CLCD_CAP_888            = CLCD_CAP_RGB888 | CLCD_CAP_BGR888,
+
+       /* red/blue ordering */
+       CLCD_CAP_RGB            = CLCD_CAP_RGB444 | CLCD_CAP_RGB5551 |
+                                 CLCD_CAP_RGB565 | CLCD_CAP_RGB888,
+       CLCD_CAP_BGR            = CLCD_CAP_BGR444 | CLCD_CAP_BGR5551 |
+                                 CLCD_CAP_BGR565 | CLCD_CAP_BGR888,
+
+       CLCD_CAP_ALL            = CLCD_CAP_BGR | CLCD_CAP_RGB,
+};
+
+struct backlight_device;
+
+struct clcd_panel {
+       struct fb_videomode     mode;
+       signed short            width;  /* width in mm */
+       signed short            height; /* height in mm */
+       u32                     tim2;
+       u32                     tim3;
+       u32                     cntl;
+       u32                     caps;
+       unsigned int            bpp:8,
+                               fixedtimings:1,
+                               grayscale:1;
+       unsigned int            connector;
+       struct backlight_device *backlight;
+       /*
+        * If the B/R lines are switched between the CLCD
+        * and the panel we need to know this and not try to
+        * compensate with the BGR bit in the control register.
+        */
+       bool                    bgr_connection;
+};
+
+struct clcd_regs {
+       u32                     tim0;
+       u32                     tim1;
+       u32                     tim2;
+       u32                     tim3;
+       u32                     cntl;
+       unsigned long           pixclock;
+};
+
+struct clcd_fb;
+
+/*
+ * the board-type specific routines
+ */
+struct clcd_board {
+       const char *name;
+
+       /*
+        * Optional.  Hardware capability flags.
+        */
+       u32     caps;
+
+       /*
+        * Optional.  Check whether the var structure is acceptable
+        * for this display.
+        */
+       int     (*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var);
+
+       /*
+        * Compulsory.  Decode fb->fb.var into regs->*.  In the case of
+        * fixed timing, set regs->* to the register values required.
+        */
+       void    (*decode)(struct clcd_fb *fb, struct clcd_regs *regs);
+
+       /*
+        * Optional.  Disable any extra display hardware.
+        */
+       void    (*disable)(struct clcd_fb *);
+
+       /*
+        * Optional.  Enable any extra display hardware.
+        */
+       void    (*enable)(struct clcd_fb *);
+
+       /*
+        * Setup platform specific parts of CLCD driver
+        */
+       int     (*setup)(struct clcd_fb *);
+
+       /*
+        * mmap the framebuffer memory
+        */
+       int     (*mmap)(struct clcd_fb *, struct vm_area_struct *);
+
+       /*
+        * Remove platform specific parts of CLCD driver
+        */
+       void    (*remove)(struct clcd_fb *);
+};
+
+struct amba_device;
+struct clk;
+
+/* this data structure describes each frame buffer device we find */
+struct clcd_fb {
+       struct fb_info          fb;
+       struct amba_device      *dev;
+       struct clk              *clk;
+       struct clcd_panel       *panel;
+       struct clcd_board       *board;
+       void                    *board_data;
+       void __iomem            *regs;
+       u16                     off_ienb;
+       u16                     off_cntl;
+       u32                     clcd_cntl;
+       u32                     cmap[16];
+       bool                    clk_enabled;
+};
+
+static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
+{
+       struct fb_var_screeninfo *var = &fb->fb.var;
+       u32 val, cpl;
+
+       /*
+        * Program the CLCD controller registers and start the CLCD
+        */
+       val = ((var->xres / 16) - 1) << 2;
+       val |= (var->hsync_len - 1) << 8;
+       val |= (var->right_margin - 1) << 16;
+       val |= (var->left_margin - 1) << 24;
+       regs->tim0 = val;
+
+       val = var->yres;
+       if (fb->panel->cntl & CNTL_LCDDUAL)
+               val /= 2;
+       val -= 1;
+       val |= (var->vsync_len - 1) << 10;
+       val |= var->lower_margin << 16;
+       val |= var->upper_margin << 24;
+       regs->tim1 = val;
+
+       val = fb->panel->tim2;
+       val |= var->sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
+       val |= var->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
+
+       cpl = var->xres_virtual;
+       if (fb->panel->cntl & CNTL_LCDTFT)        /* TFT */
+               /* / 1 */;
+       else if (!var->grayscale)                 /* STN color */
+               cpl = cpl * 8 / 3;
+       else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */
+               cpl /= 8;
+       else                                      /* STN monochrome, 4bit */
+               cpl /= 4;
+
+       regs->tim2 = val | ((cpl - 1) << 16);
+
+       regs->tim3 = fb->panel->tim3;
+
+       val = fb->panel->cntl;
+       if (var->grayscale)
+               val |= CNTL_LCDBW;
+
+       if (fb->panel->caps && fb->board->caps && var->bits_per_pixel >= 16) {
+               /*
+                * if board and panel supply capabilities, we can support
+                * changing BGR/RGB depending on supplied parameters. Here
+                * we switch to what the framebuffer is providing if need
+                * be, so if the framebuffer is BGR but the display connection
+                * is RGB (first case) we switch it around. Vice versa mutatis
+                * mutandis if the framebuffer is RGB but the display connection
+                * is BGR, we flip it around.
+                */
+               if (var->red.offset == 0)
+                       val &= ~CNTL_BGR;
+               else
+                       val |= CNTL_BGR;
+               if (fb->panel->bgr_connection)
+                       val ^= CNTL_BGR;
+       }
+
+       switch (var->bits_per_pixel) {
+       case 1:
+               val |= CNTL_LCDBPP1;
+               break;
+       case 2:
+               val |= CNTL_LCDBPP2;
+               break;
+       case 4:
+               val |= CNTL_LCDBPP4;
+               break;
+       case 8:
+               val |= CNTL_LCDBPP8;
+               break;
+       case 16:
+               /*
+                * PL110 cannot choose between 5551 and 565 modes in its
+                * control register.  It is possible to use 565 with
+                * custom external wiring.
+                */
+               if (amba_part(fb->dev) == 0x110 ||
+                   var->green.length == 5)
+                       val |= CNTL_LCDBPP16;
+               else if (var->green.length == 6)
+                       val |= CNTL_LCDBPP16_565;
+               else
+                       val |= CNTL_LCDBPP16_444;
+               break;
+       case 32:
+               val |= CNTL_LCDBPP24;
+               break;
+       }
+
+       regs->cntl = val;
+       regs->pixclock = var->pixclock;
+}
+
+static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+       var->xres_virtual = var->xres = (var->xres + 15) & ~15;
+       var->yres_virtual = var->yres = (var->yres + 1) & ~1;
+
+#define CHECK(e,l,h) (var->e < l || var->e > h)
+       if (CHECK(right_margin, (5+1), 256) ||  /* back porch */
+           CHECK(left_margin, (5+1), 256) ||   /* front porch */
+           CHECK(hsync_len, (5+1), 256) ||
+           var->xres > 4096 ||
+           var->lower_margin > 255 ||          /* back porch */
+           var->upper_margin > 255 ||          /* front porch */
+           var->vsync_len > 32 ||
+           var->yres > 1024)
+               return -EINVAL;
+#undef CHECK
+
+       /* single panel mode: PCD = max(PCD, 1) */
+       /* dual panel mode: PCD = max(PCD, 5) */
+
+       /*
+        * You can't change the grayscale setting, and
+        * we can only do non-interlaced video.
+        */
+       if (var->grayscale != fb->fb.var.grayscale ||
+           (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+               return -EINVAL;
+
+#define CHECK(e) (var->e != fb->fb.var.e)
+       if (fb->panel->fixedtimings &&
+           (CHECK(xres)                ||
+            CHECK(yres)                ||
+            CHECK(bits_per_pixel)      ||
+            CHECK(pixclock)            ||
+            CHECK(left_margin)         ||
+            CHECK(right_margin)        ||
+            CHECK(upper_margin)        ||
+            CHECK(lower_margin)        ||
+            CHECK(hsync_len)           ||
+            CHECK(vsync_len)           ||
+            CHECK(sync)))
+               return -EINVAL;
+#undef CHECK
+
+       var->nonstd = 0;
+       var->accel_flags = 0;
+
+       return 0;
+}
index 4ecf4fe..b3fc5d3 100644 (file)
@@ -497,13 +497,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 bb5636c..868e11f 100644 (file)
@@ -352,6 +352,8 @@ struct queue_limits {
 typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx,
                               void *data);
 
+void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model);
+
 #ifdef CONFIG_BLK_DEV_ZONED
 
 #define BLK_ALL_ZONES  ((unsigned int)-1)
index 3215023..bf9181c 100644 (file)
@@ -142,7 +142,6 @@ enum cpuhp_state {
        /* Must be the last timer callback */
        CPUHP_AP_DUMMY_TIMER_STARTING,
        CPUHP_AP_ARM_XEN_STARTING,
-       CPUHP_AP_ARM_KVMPV_STARTING,
        CPUHP_AP_ARM_CORESIGHT_STARTING,
        CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
        CPUHP_AP_ARM64_ISNDEP_STARTING,
index 75895e6..6175c77 100644 (file)
@@ -82,6 +82,7 @@ struct cpuidle_state {
 #define CPUIDLE_FLAG_UNUSABLE          BIT(3) /* avoid using this state */
 #define CPUIDLE_FLAG_OFF               BIT(4) /* disable this state by default */
 #define CPUIDLE_FLAG_TLB_FLUSHED       BIT(5) /* idle-state flushes TLBs */
+#define CPUIDLE_FLAG_RCU_IDLE          BIT(6) /* idle-state takes care of RCU */
 
 struct cpuidle_device_kobj;
 struct cpuidle_state_kobj;
index 6904d4e..43b39ab 100644 (file)
@@ -58,6 +58,8 @@ static inline void set_dax_synchronous(struct dax_device *dax_dev)
 {
        __set_dax_synchronous(dax_dev);
 }
+bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
+               int blocksize, sector_t start, sector_t len);
 /*
  * Check if given mapping is supported by the file / underlying device.
  */
@@ -104,6 +106,12 @@ static inline bool dax_synchronous(struct dax_device *dax_dev)
 static inline void set_dax_synchronous(struct dax_device *dax_dev)
 {
 }
+static inline bool dax_supported(struct dax_device *dax_dev,
+               struct block_device *bdev, int blocksize, sector_t start,
+               sector_t len)
+{
+       return false;
+}
 static inline bool daxdev_mapping_supported(struct vm_area_struct *vma,
                                struct dax_device *dax_dev)
 {
@@ -189,14 +197,23 @@ static inline void dax_unlock_page(struct page *page, dax_entry_t cookie)
 }
 #endif
 
+#if IS_ENABLED(CONFIG_DAX)
 int dax_read_lock(void);
 void dax_read_unlock(int id);
+#else
+static inline int dax_read_lock(void)
+{
+       return 0;
+}
+
+static inline void dax_read_unlock(int id)
+{
+}
+#endif /* CONFIG_DAX */
 bool dax_alive(struct dax_device *dax_dev);
 void *dax_get_private(struct dax_device *dax_dev);
 long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
                void **kaddr, pfn_t *pfn);
-bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
-               int blocksize, sector_t start, sector_t len);
 size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
                size_t bytes, struct iov_iter *i);
 size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
index ca18da4..9e6ea89 100644 (file)
@@ -454,6 +454,7 @@ struct dev_links_info {
  * @pm_domain: Provide callbacks that are executed during system suspend,
  *             hibernation, system resume and during runtime PM transitions
  *             along with subsystem-level and driver-level callbacks.
+ * @em_pd:     device's energy model performance domain
  * @pins:      For device pin management.
  *             See Documentation/driver-api/pinctl.rst for details.
  * @msi_list:  Hosts MSI descriptors
index aa9ff9e..8aa0c7c 100644 (file)
@@ -49,6 +49,10 @@ struct _ddebug {
 
 
 #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
+
+/* exported for module authors to exercise >control */
+int dynamic_debug_exec_queries(const char *query, const char *modname);
+
 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
                                const char *modname);
 extern int ddebug_remove_module(const char *mod_name);
@@ -105,7 +109,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
        static_branch_unlikely(&descriptor.key.dd_key_false)
 #endif
 
-#else /* !HAVE_JUMP_LABEL */
+#else /* !CONFIG_JUMP_LABEL */
 
 #define _DPRINTK_KEY_INIT
 
@@ -117,7 +121,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
        unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
 #endif
 
-#endif
+#endif /* CONFIG_JUMP_LABEL */
 
 #define __dynamic_func_call(id, fmt, func, ...) do {   \
        DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);         \
@@ -172,10 +176,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
                                   KERN_DEBUG, prefix_str, prefix_type, \
                                   rowsize, groupsize, buf, len, ascii)
 
-#else
+#else /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/printk.h>
 
 static inline int ddebug_add_module(struct _ddebug *tab, unsigned int n,
                                    const char *modname)
@@ -210,6 +215,13 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
                print_hex_dump(KERN_DEBUG, prefix_str, prefix_type,     \
                                rowsize, groupsize, buf, len, ascii);   \
        } while (0)
-#endif
+
+static inline int dynamic_debug_exec_queries(const char *query, const char *modname)
+{
+       pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n");
+       return 0;
+}
+
+#endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 #endif
index 57eac52..a97a12b 100644 (file)
@@ -8,8 +8,8 @@
 #define EFI_EMBEDDED_FW_PREFIX_LEN             8
 
 /*
- * This struct and efi_embedded_fw_list are private to the efi-embedded fw
- * implementation they are in this header for use by lib/test_firmware.c only!
+ * This struct is private to the efi-embedded fw implementation.
+ * They are in this header for use by lib/test_firmware.c only!
  */
 struct efi_embedded_fw {
        struct list_head list;
@@ -18,8 +18,6 @@ struct efi_embedded_fw {
        size_t length;
 };
 
-extern struct list_head efi_embedded_fw_list;
-
 /**
  * struct efi_embedded_fw_desc - This struct is used by the EFI embedded-fw
  *                               code to search for embedded firmwares.
index 51b91c8..59faa80 100644 (file)
@@ -59,4 +59,17 @@ extern const struct font_desc *get_default_font(int xres, int yres,
 /* Max. length for the name of a predefined font */
 #define MAX_FONT_NAME  32
 
+/* Extra word getters */
+#define REFCOUNT(fd)   (((int *)(fd))[-1])
+#define FNTSIZE(fd)    (((int *)(fd))[-2])
+#define FNTCHARCNT(fd) (((int *)(fd))[-3])
+#define FNTSUM(fd)     (((int *)(fd))[-4])
+
+#define FONT_EXTRA_WORDS 4
+
+struct font_data {
+       unsigned int extra[FONT_EXTRA_WORDS];
+       const unsigned char data[];
+} __packed;
+
 #endif /* _VIDEO_FONT_H */
index 2eab6d5..aab0ffc 100644 (file)
@@ -120,7 +120,7 @@ static inline bool fs_validate_description(const char *name,
 #define fsparam_u32oct(NAME, OPT) \
                        __fsparam(fs_param_is_u32, NAME, OPT, 0, (void *)8)
 #define fsparam_u32hex(NAME, OPT) \
-                       __fsparam(fs_param_is_u32_hex, NAME, OPT, 0, (void *16))
+                       __fsparam(fs_param_is_u32_hex, NAME, OPT, 0, (void *)16)
 #define fsparam_s32(NAME, OPT) __fsparam(fs_param_is_s32, NAME, OPT, 0, NULL)
 #define fsparam_u64(NAME, OPT) __fsparam(fs_param_is_u64, NAME, OPT, 0, NULL)
 #define fsparam_enum(NAME, OPT, array) __fsparam(fs_param_is_enum, NAME, OPT, 0, array)
index ce2c06f..e5c2d5c 100644 (file)
@@ -85,8 +85,7 @@ static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *val
 extern int ftrace_enabled;
 extern int
 ftrace_enable_sysctl(struct ctl_table *table, int write,
-                    void __user *buffer, size_t *lenp,
-                    loff_t *ppos);
+                    void *buffer, size_t *lenp, loff_t *ppos);
 
 struct ftrace_ops;
 
index d030717..7c522fd 100644 (file)
 #define I2C_PCA_CON_SI         0x08 /* Serial Interrupt */
 #define I2C_PCA_CON_CR         0x07 /* Clock Rate (MASK) */
 
+/**
+ * struct pca_i2c_bus_settings - The configured PCA i2c bus settings
+ * @mode: Configured i2c bus mode
+ * @tlow: Configured SCL LOW period
+ * @thi: Configured SCL HIGH period
+ * @clock_freq: The configured clock frequency
+ */
+struct pca_i2c_bus_settings {
+       int mode;
+       int tlow;
+       int thi;
+       int clock_freq;
+};
+
 struct i2c_algo_pca_data {
        void                            *data;  /* private low level data */
        void (*write_byte)              (void *data, int reg, int val);
@@ -64,6 +78,7 @@ struct i2c_algo_pca_data {
         * For PCA9665, use the frequency you want here. */
        unsigned int                    i2c_clock;
        unsigned int                    chip;
+       struct pca_i2c_bus_settings             bus_settings;
 };
 
 int i2c_pca_add_bus(struct i2c_adapter *);
index 9be1bff..8aab327 100644 (file)
@@ -373,6 +373,8 @@ void unregister_kretprobes(struct kretprobe **rps, int num);
 void kprobe_flush_task(struct task_struct *tk);
 void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
 
+void kprobe_free_init_mem(void);
+
 int disable_kprobe(struct kprobe *kp);
 int enable_kprobe(struct kprobe *kp);
 
@@ -435,6 +437,9 @@ static inline void unregister_kretprobes(struct kretprobe **rps, int num)
 static inline void kprobe_flush_task(struct task_struct *tk)
 {
 }
+static inline void kprobe_free_init_mem(void)
+{
+}
 static inline int disable_kprobe(struct kprobe *kp)
 {
        return -ENOSYS;
index a230767..05e3c2f 100644 (file)
@@ -749,25 +749,46 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
                              gpa_t gpa, unsigned long len);
 
-#define __kvm_put_guest(kvm, gfn, offset, value, type)                 \
+#define __kvm_get_guest(kvm, gfn, offset, v)                           \
 ({                                                                     \
        unsigned long __addr = gfn_to_hva(kvm, gfn);                    \
-       type __user *__uaddr = (type __user *)(__addr + offset);        \
+       typeof(v) __user *__uaddr = (typeof(__uaddr))(__addr + offset); \
        int __ret = -EFAULT;                                            \
                                                                        \
        if (!kvm_is_error_hva(__addr))                                  \
-               __ret = put_user(value, __uaddr);                       \
+               __ret = get_user(v, __uaddr);                           \
+       __ret;                                                          \
+})
+
+#define kvm_get_guest(kvm, gpa, v)                                     \
+({                                                                     \
+       gpa_t __gpa = gpa;                                              \
+       struct kvm *__kvm = kvm;                                        \
+                                                                       \
+       __kvm_get_guest(__kvm, __gpa >> PAGE_SHIFT,                     \
+                       offset_in_page(__gpa), v);                      \
+})
+
+#define __kvm_put_guest(kvm, gfn, offset, v)                           \
+({                                                                     \
+       unsigned long __addr = gfn_to_hva(kvm, gfn);                    \
+       typeof(v) __user *__uaddr = (typeof(__uaddr))(__addr + offset); \
+       int __ret = -EFAULT;                                            \
+                                                                       \
+       if (!kvm_is_error_hva(__addr))                                  \
+               __ret = put_user(v, __uaddr);                           \
        if (!__ret)                                                     \
                mark_page_dirty(kvm, gfn);                              \
        __ret;                                                          \
 })
 
-#define kvm_put_guest(kvm, gpa, value, type)                           \
+#define kvm_put_guest(kvm, gpa, v)                                     \
 ({                                                                     \
        gpa_t __gpa = gpa;                                              \
        struct kvm *__kvm = kvm;                                        \
+                                                                       \
        __kvm_put_guest(__kvm, __gpa >> PAGE_SHIFT,                     \
-                       offset_in_page(__gpa), (value), type);          \
+                       offset_in_page(__gpa), v);                      \
 })
 
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
index c145de0..372100c 100644 (file)
@@ -767,6 +767,8 @@ struct mlx5_cmd_work_ent {
        u64                     ts2;
        u16                     op;
        bool                    polling;
+       /* Track the max comp handlers */
+       refcount_t              refcnt;
 };
 
 struct mlx5_pas {
@@ -933,6 +935,7 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
 int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
                          void *out, int out_size);
 void mlx5_cmd_mbox_status(void *out, u8 *status, u32 *syndrome);
+bool mlx5_cmd_is_down(struct mlx5_core_dev *dev);
 
 int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type);
 int mlx5_cmd_alloc_uar(struct mlx5_core_dev *dev, u32 *uarn);
index ca6e6a8..16b799a 100644 (file)
@@ -41,6 +41,8 @@ struct writeback_control;
 struct bdi_writeback;
 struct pt_regs;
 
+extern int sysctl_page_lock_unfairness;
+
 void init_mm_internals(void);
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES     /* Don't use mapnrs, do it properly */
@@ -1644,7 +1646,7 @@ struct mmu_notifier_range;
 void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                unsigned long end, unsigned long floor, unsigned long ceiling);
 int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
-                       struct vm_area_struct *vma);
+                   struct vm_area_struct *vma, struct vm_area_struct *new);
 int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                   struct mmu_notifier_range *range,
                   pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
@@ -2414,7 +2416,7 @@ extern int __meminit __early_pfn_to_nid(unsigned long pfn,
 
 extern void set_dma_reserve(unsigned long new_dma_reserve);
 extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long,
-               enum memmap_context, struct vmem_altmap *);
+               enum meminit_context, struct vmem_altmap *);
 extern void setup_per_zone_wmarks(void);
 extern int __meminit init_per_zone_wmark_min(void);
 extern void mem_init(void);
index 496c3ff..ed028af 100644 (file)
@@ -436,6 +436,16 @@ struct mm_struct {
                 */
                atomic_t mm_count;
 
+               /**
+                * @has_pinned: Whether this mm has pinned any pages.  This can
+                * be either replaced in the future by @pinned_vm when it
+                * becomes stable, or grow into a counter on its own. We're
+                * aggresive on this bit now - even if the pinned pages were
+                * unpinned later on, we'll still keep this bit set for the
+                * lifecycle of this mm just for simplicity.
+                */
+               atomic_t has_pinned;
+
 #ifdef CONFIG_MMU
                atomic_long_t pgtables_bytes;   /* PTE page table pages */
 #endif
index 8379432..0f7a4ff 100644 (file)
@@ -824,10 +824,15 @@ bool zone_watermark_ok(struct zone *z, unsigned int order,
                unsigned int alloc_flags);
 bool zone_watermark_ok_safe(struct zone *z, unsigned int order,
                unsigned long mark, int highest_zoneidx);
-enum memmap_context {
-       MEMMAP_EARLY,
-       MEMMAP_HOTPLUG,
+/*
+ * Memory initialization context, use to differentiate memory added by
+ * the platform statically or via memory hotplug interface.
+ */
+enum meminit_context {
+       MEMINIT_EARLY,
+       MEMINIT_HOTPLUG,
 };
+
 extern void init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
                                     unsigned long size);
 
index d48ff11..ae713c8 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/rcupdate.h>
 #include <linux/once.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
 #include <linux/sockptr.h>
 
 #include <uapi/linux/net.h>
@@ -286,6 +287,21 @@ do {                                                                       \
 #define net_get_random_once_wait(buf, nbytes)                  \
        get_random_once_wait((buf), (nbytes))
 
+/*
+ * E.g. XFS meta- & log-data is in slab pages, or bcache meta
+ * data pages, or other high order pages allocated by
+ * __get_free_pages() without __GFP_COMP, which have a page_count
+ * of 0 and/or have PageSlab() set. We cannot use send_page for
+ * those, as that does get_page(); put_page(); and would cause
+ * either a VM_BUG directly, or __page_cache_release a page that
+ * would actually still be referenced by someone, leading to some
+ * obscure delayed Oops somewhere else.
+ */
+static inline bool sendpage_ok(struct page *page)
+{
+       return !PageSlab(page) && page_count(page) >= 1;
+}
+
 int kernel_sendmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec,
                   size_t num, size_t len);
 int kernel_sendmsg_locked(struct sock *sk, struct msghdr *msg,
index 2cc3cf8..0b17c43 100644 (file)
@@ -193,7 +193,7 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
 #define NETIF_F_GSO_MASK       (__NETIF_F_BIT(NETIF_F_GSO_LAST + 1) - \
                __NETIF_F_BIT(NETIF_F_GSO_SHIFT))
 
-/* List of IP checksum features. Note that NETIF_F_ HW_CSUM should not be
+/* List of IP checksum features. Note that NETIF_F_HW_CSUM should not be
  * set in features when NETIF_F_IP_CSUM or NETIF_F_IPV6_CSUM are set--
  * this would be contradictory
  */
index b0e303f..18dec08 100644 (file)
@@ -1784,6 +1784,7 @@ enum netdev_priv_flags {
  *                             the watchdog (see dev_watchdog())
  *     @watchdog_timer:        List of timers
  *
+ *     @proto_down_reason:     reason a netdev interface is held down
  *     @pcpu_refcnt:           Number of references to this device
  *     @todo_list:             Delayed register/unregister
  *     @link_watch_list:       XXX: need comments on this one
@@ -1848,6 +1849,12 @@ enum netdev_priv_flags {
  *     @udp_tunnel_nic_info:   static structure describing the UDP tunnel
  *                             offload capabilities of the device
  *     @udp_tunnel_nic:        UDP tunnel offload state
+ *     @xdp_state:             stores info on attached XDP BPF programs
+ *
+ *     @nested_level:  Used as as a parameter of spin_lock_nested() of
+ *                     dev->addr_list_lock.
+ *     @unlink_list:   As netif_addr_lock() can be called recursively,
+ *                     keep a list of interfaces to be deleted.
  *
  *     FIXME: cleanup struct net_device such that network protocol info
  *     moves out.
@@ -1953,6 +1960,7 @@ struct net_device {
        unsigned short          type;
        unsigned short          hard_header_len;
        unsigned char           min_header_len;
+       unsigned char           name_assign_type;
 
        unsigned short          needed_headroom;
        unsigned short          needed_tailroom;
@@ -1963,12 +1971,12 @@ struct net_device {
        unsigned char           addr_len;
        unsigned char           upper_level;
        unsigned char           lower_level;
+
        unsigned short          neigh_priv_len;
        unsigned short          dev_id;
        unsigned short          dev_port;
        spinlock_t              addr_list_lock;
-       unsigned char           name_assign_type;
-       bool                    uc_promisc;
+
        struct netdev_hw_addr_list      uc;
        struct netdev_hw_addr_list      mc;
        struct netdev_hw_addr_list      dev_addrs;
@@ -1976,8 +1984,15 @@ struct net_device {
 #ifdef CONFIG_SYSFS
        struct kset             *queues_kset;
 #endif
+#ifdef CONFIG_LOCKDEP
+       struct list_head        unlink_list;
+#endif
        unsigned int            promiscuity;
        unsigned int            allmulti;
+       bool                    uc_promisc;
+#ifdef CONFIG_LOCKDEP
+       unsigned char           nested_level;
+#endif
 
 
        /* Protocol-specific pointers */
@@ -4258,17 +4273,23 @@ static inline void netif_tx_disable(struct net_device *dev)
 
 static inline void netif_addr_lock(struct net_device *dev)
 {
-       spin_lock(&dev->addr_list_lock);
-}
+       unsigned char nest_level = 0;
 
-static inline void netif_addr_lock_nested(struct net_device *dev)
-{
-       spin_lock_nested(&dev->addr_list_lock, dev->lower_level);
+#ifdef CONFIG_LOCKDEP
+       nest_level = dev->nested_level;
+#endif
+       spin_lock_nested(&dev->addr_list_lock, nest_level);
 }
 
 static inline void netif_addr_lock_bh(struct net_device *dev)
 {
-       spin_lock_bh(&dev->addr_list_lock);
+       unsigned char nest_level = 0;
+
+#ifdef CONFIG_LOCKDEP
+       nest_level = dev->nested_level;
+#endif
+       local_bh_disable();
+       spin_lock_nested(&dev->addr_list_lock, nest_level);
 }
 
 static inline void netif_addr_unlock(struct net_device *dev)
@@ -4453,12 +4474,38 @@ extern int              dev_rx_weight;
 extern int             dev_tx_weight;
 extern int             gro_normal_batch;
 
+enum {
+       NESTED_SYNC_IMM_BIT,
+       NESTED_SYNC_TODO_BIT,
+};
+
+#define __NESTED_SYNC_BIT(bit) ((u32)1 << (bit))
+#define __NESTED_SYNC(name)    __NESTED_SYNC_BIT(NESTED_SYNC_ ## name ## _BIT)
+
+#define NESTED_SYNC_IMM                __NESTED_SYNC(IMM)
+#define NESTED_SYNC_TODO       __NESTED_SYNC(TODO)
+
+struct netdev_nested_priv {
+       unsigned char flags;
+       void *data;
+};
+
 bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev);
 struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
                                                     struct list_head **iter);
 struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
                                                     struct list_head **iter);
 
+#ifdef CONFIG_LOCKDEP
+static LIST_HEAD(net_unlink_list);
+
+static inline void net_unlink_todo(struct net_device *dev)
+{
+       if (list_empty(&dev->unlink_list))
+               list_add_tail(&dev->unlink_list, &net_unlink_list);
+}
+#endif
+
 /* iterate through upper list, must be called under RCU read lock */
 #define netdev_for_each_upper_dev_rcu(dev, updev, iter) \
        for (iter = &(dev)->adj_list.upper, \
@@ -4468,8 +4515,8 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 
 int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *upper_dev,
-                                           void *data),
-                                 void *data);
+                                           struct netdev_nested_priv *priv),
+                                 struct netdev_nested_priv *priv);
 
 bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
                                  struct net_device *upper_dev);
@@ -4506,12 +4553,12 @@ struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
                                             struct list_head **iter);
 int netdev_walk_all_lower_dev(struct net_device *dev,
                              int (*fn)(struct net_device *lower_dev,
-                                       void *data),
-                             void *data);
+                                       struct netdev_nested_priv *priv),
+                             struct netdev_nested_priv *priv);
 int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *lower_dev,
-                                           void *data),
-                                 void *data);
+                                           struct netdev_nested_priv *priv),
+                                 struct netdev_nested_priv *priv);
 
 void *netdev_adjacent_get_private(struct list_head *adj_list);
 void *netdev_lower_get_first_private_rcu(struct net_device *dev);
index 9408f32..69cb46f 100644 (file)
@@ -1611,8 +1611,8 @@ struct nfs_pgio_header {
        __u64                   mds_offset;     /* Filelayout dense stripe */
        struct nfs_page_array   page_array;
        struct nfs_client       *ds_clp;        /* pNFS data server */
-       int                     ds_commit_idx;  /* ds index if ds_clp is set */
-       int                     pgio_mirror_idx;/* mirror index in pgio layer */
+       u32                     ds_commit_idx;  /* ds index if ds_clp is set */
+       u32                     pgio_mirror_idx;/* mirror index in pgio layer */
 };
 
 struct nfs_mds_commit_info {
index 4866f32..014ba3a 100644 (file)
@@ -99,11 +99,13 @@ extern struct node *node_devices[];
 typedef  void (*node_registration_func_t)(struct node *);
 
 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_NUMA)
-extern int link_mem_sections(int nid, unsigned long start_pfn,
-                            unsigned long end_pfn);
+int link_mem_sections(int nid, unsigned long start_pfn,
+                     unsigned long end_pfn,
+                     enum meminit_context context);
 #else
 static inline int link_mem_sections(int nid, unsigned long start_pfn,
-                                   unsigned long end_pfn)
+                                   unsigned long end_pfn,
+                                   enum meminit_context context)
 {
        return 0;
 }
@@ -128,7 +130,8 @@ static inline int register_one_node(int nid)
                if (error)
                        return error;
                /* link memory sections under this node */
-               error = link_mem_sections(nid, start_pfn, end_pfn);
+               error = link_mem_sections(nid, start_pfn, end_pfn,
+                                         MEMINIT_EARLY);
        }
 
        return error;
index 5e033fe..5fda40f 100644 (file)
@@ -60,7 +60,7 @@ static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
         * anything we did within this RCU-sched read-size critical section.
         */
        if (likely(rcu_sync_is_idle(&sem->rss)))
-               __this_cpu_inc(*sem->read_count);
+               this_cpu_inc(*sem->read_count);
        else
                __percpu_down_read(sem, false); /* Unconditional memory barrier */
        /*
@@ -79,7 +79,7 @@ static inline bool percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
         * Same as in percpu_down_read().
         */
        if (likely(rcu_sync_is_idle(&sem->rss)))
-               __this_cpu_inc(*sem->read_count);
+               this_cpu_inc(*sem->read_count);
        else
                ret = __percpu_down_read(sem, true); /* Unconditional memory barrier */
        preempt_enable();
@@ -103,7 +103,7 @@ static inline void percpu_up_read(struct percpu_rw_semaphore *sem)
         * Same as in percpu_down_read().
         */
        if (likely(rcu_sync_is_idle(&sem->rss))) {
-               __this_cpu_dec(*sem->read_count);
+               this_cpu_dec(*sem->read_count);
        } else {
                /*
                 * slowpath; reader will only ever wake a single blocked
@@ -115,7 +115,7 @@ static inline void percpu_up_read(struct percpu_rw_semaphore *sem)
                 * aggregate zero, as that is the only time it matters) they
                 * will also see our critical section.
                 */
-               __this_cpu_dec(*sem->read_count);
+               this_cpu_dec(*sem->read_count);
                rcuwait_wake_up(&sem->writer);
        }
        preempt_enable();
index e8cbc2e..90654cb 100644 (file)
@@ -1427,6 +1427,16 @@ typedef unsigned int pgtbl_mod_mask;
 #define mm_pmd_folded(mm)      __is_defined(__PAGETABLE_PMD_FOLDED)
 #endif
 
+#ifndef p4d_offset_lockless
+#define p4d_offset_lockless(pgdp, pgd, address) p4d_offset(&(pgd), address)
+#endif
+#ifndef pud_offset_lockless
+#define pud_offset_lockless(p4dp, p4d, address) pud_offset(&(p4d), address)
+#endif
+#ifndef pmd_offset_lockless
+#define pmd_offset_lockless(pudp, pud, address) pmd_offset(&(pud), address)
+#endif
+
 /*
  * p?d_leaf() - true if this entry is a final mapping to a physical address.
  * This differs from p?d_huge() by the fact that they are always available (if
index 50afd0d..5d2705f 100644 (file)
@@ -240,8 +240,9 @@ extern unsigned int pipe_max_size;
 extern unsigned long pipe_user_pages_hard;
 extern unsigned long pipe_user_pages_soft;
 
-/* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct pipe_inode_info *pipe);
+/* Wait for a pipe to be readable/writable while dropping the pipe lock */
+void pipe_wait_readable(struct pipe_inode_info *);
+void pipe_wait_writable(struct pipe_inode_info *);
 
 struct pipe_inode_info *alloc_pipe_info(void);
 void free_pipe_info(struct pipe_inode_info *);
index 9e46678..255d51c 100644 (file)
@@ -19,7 +19,7 @@
 #define AMD_FCH_GPIO_REG_GPIO49                0x40
 #define AMD_FCH_GPIO_REG_GPIO50                0x41
 #define AMD_FCH_GPIO_REG_GPIO51                0x42
-#define AMD_FCH_GPIO_REG_GPIO59_DEVSLP0        0x43
+#define AMD_FCH_GPIO_REG_GPIO55_DEVSLP0        0x43
 #define AMD_FCH_GPIO_REG_GPIO57                0x44
 #define AMD_FCH_GPIO_REG_GPIO58                0x45
 #define AMD_FCH_GPIO_REG_GPIO59_DEVSLP1        0x46
index 4537f57..3d557bb 100644 (file)
@@ -44,19 +44,18 @@ struct powercap_control_type_ops {
 };
 
 /**
- * struct powercap_control_type- Defines a powercap control_type
- * @name:              name of control_type
+ * struct powercap_control_type - Defines a powercap control_type
  * @dev:               device for this control_type
  * @idr:               idr to have unique id for its child
- * @root_node:         Root holding power zones for this control_type
+ * @nr_zones:          counter for number of zones of this type
  * @ops:               Pointer to callback struct
- * @node_lock:         mutex for control type
+ * @lock:              mutex for control type
  * @allocated:         This is possible that client owns the memory
  *                     used by this structure. In this case
  *                     this flag is set to false by framework to
  *                     prevent deallocation during release process.
  *                     Otherwise this flag is set to true.
- * @ctrl_inst:         link to the control_type list
+ * @node:              linked-list node
  *
  * Defines powercap control_type. This acts as a container for power
  * zones, which use same method to control power. E.g. RAPL, RAPL-PCI etc.
@@ -129,7 +128,7 @@ struct powercap_zone_ops {
  *                     this flag is set to false by framework to
  *                     prevent deallocation during release process.
  *                     Otherwise this flag is set to true.
- * @constraint_ptr:    List of constraints for this zone.
+ * @constraints:       List of constraints for this zone.
  *
  * This defines a power zone instance. The fields of this structure are
  * private, and should not be used by client drivers.
index cd6a5c7..cdd73af 100644 (file)
@@ -623,6 +623,7 @@ struct qed_dev_info {
 #define QED_MFW_VERSION_3_OFFSET       24
 
        u32             flash_size;
+       bool            b_arfs_capable;
        bool            b_inter_pf_switch;
        bool            tx_switching;
        bool            rdma_supported;
index 01fc4d9..8a99279 100644 (file)
@@ -248,6 +248,7 @@ struct uart_port {
 
        unsigned char           hub6;                   /* this should be in the 8250 driver */
        unsigned char           suspended;
+       unsigned char           console_reinit;
        const char              *name;                  /* port name */
        struct attribute_group  *attr_group;            /* port specific attributes */
        const struct attribute_group **tty_groups;      /* all attributes (serial core use only) */
index ed9bea9..04a18e0 100644 (file)
@@ -3223,8 +3223,9 @@ static inline int skb_padto(struct sk_buff *skb, unsigned int len)
  *     is untouched. Otherwise it is extended. Returns zero on
  *     success. The skb is freed on error if @free_on_error is true.
  */
-static inline int __skb_put_padto(struct sk_buff *skb, unsigned int len,
-                                 bool free_on_error)
+static inline int __must_check __skb_put_padto(struct sk_buff *skb,
+                                              unsigned int len,
+                                              bool free_on_error)
 {
        unsigned int size = skb->len;
 
@@ -3247,7 +3248,7 @@ static inline int __skb_put_padto(struct sk_buff *skb, unsigned int len,
  *     is untouched. Otherwise it is extended. Returns zero on
  *     success. The skb is freed on error.
  */
-static inline int skb_put_padto(struct sk_buff *skb, unsigned int len)
+static inline int __must_check skb_put_padto(struct sk_buff *skb, unsigned int len)
 {
        return __skb_put_padto(skb, len, true);
 }
index 3d5c327..a59db2f 100644 (file)
@@ -25,7 +25,7 @@ static inline void stackleak_task_init(struct task_struct *t)
 
 #ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
 int stack_erasing_sysctl(struct ctl_table *table, int write,
-                       void __user *buffer, size_t *lenp, loff_t *ppos);
+                       void *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
 #else /* !CONFIG_GCC_PLUGIN_STACKLEAK */
index 91220ac..7557c10 100644 (file)
@@ -312,6 +312,11 @@ static inline void __mod_zone_page_state(struct zone *zone,
 static inline void __mod_node_page_state(struct pglist_data *pgdat,
                        enum node_stat_item item, int delta)
 {
+       if (vmstat_item_in_bytes(item)) {
+               VM_WARN_ON_ONCE(delta & (PAGE_SIZE - 1));
+               delta >>= PAGE_SHIFT;
+       }
+
        node_page_state_add(delta, pgdat, item);
 }
 
index 898c890..27fb99c 100644 (file)
@@ -21,6 +21,7 @@ int default_wake_function(struct wait_queue_entry *wq_entry, unsigned mode, int
 #define WQ_FLAG_WOKEN          0x02
 #define WQ_FLAG_BOOKMARK       0x04
 #define WQ_FLAG_CUSTOM         0x08
+#define WQ_FLAG_DONE           0x10
 
 /*
  * A single wait-queue entry structure:
index 52ef920..bbb3f26 100644 (file)
@@ -744,8 +744,6 @@ void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
  * vb2_core_reqbufs() - Initiate streaming.
  * @q:         pointer to &struct vb2_queue with videobuf2 queue.
  * @memory:    memory type, as defined by &enum vb2_memory.
- * @flags:     auxiliary queue/buffer management flags. Currently, the only
- *             used flag is %V4L2_FLAG_MEMORY_NON_CONSISTENT.
  * @count:     requested buffer count.
  *
  * Videobuf2 core helper to implement VIDIOC_REQBUF() operation. It is called
@@ -770,13 +768,12 @@ void vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
  * Return: returns zero on success; an error code otherwise.
  */
 int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
-                   unsigned int flags, unsigned int *count);
+                   unsigned int *count);
 
 /**
  * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
  * @q: pointer to &struct vb2_queue with videobuf2 queue.
  * @memory: memory type, as defined by &enum vb2_memory.
- * @flags: auxiliary queue/buffer management flags.
  * @count: requested buffer count.
  * @requested_planes: number of planes requested.
  * @requested_sizes: array with the size of the planes.
@@ -794,7 +791,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
  * Return: returns zero on success; an error code otherwise.
  */
 int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
-                        unsigned int flags, unsigned int *count,
+                        unsigned int *count,
                         unsigned int requested_planes,
                         const unsigned int requested_sizes[]);
 
index cb382a8..8721492 100644 (file)
@@ -166,8 +166,6 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
                              struct nlattr *est, struct tc_action **a,
                              const struct tc_action_ops *ops, int bind,
                              u32 flags);
-void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
-
 void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
 int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
                        struct tc_action **a, int bind);
index 929d3ca..b2531df 100644 (file)
@@ -116,6 +116,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
        fl4->saddr = saddr;
        fl4->fl4_dport = dport;
        fl4->fl4_sport = sport;
+       fl4->flowi4_multipath_hash = 0;
 }
 
 /* Reset some input parameters after previous lookup */
index 6e5f1e1..8899d74 100644 (file)
@@ -138,6 +138,7 @@ genl_dumpit_info(struct netlink_callback *cb)
  * @cmd: command identifier
  * @internal_flags: flags used by the family
  * @flags: flags
+ * @validate: validation flags from enum genl_validate_flags
  * @doit: standard command callback
  * @start: start callback for dumps
  * @dumpit: callback for dumpers
index b09c48d..2a52787 100644 (file)
@@ -436,12 +436,18 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
                                                    bool forwarding)
 {
        struct net *net = dev_net(dst->dev);
+       unsigned int mtu;
 
        if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
            ip_mtu_locked(dst) ||
            !forwarding)
                return dst_mtu(dst);
 
+       /* 'forwarding = true' case should always honour route mtu */
+       mtu = dst_metric_raw(dst, RTAX_MTU);
+       if (mtu)
+               return mtu;
+
        return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
 }
 
index c0411f1..271620f 100644 (file)
@@ -726,7 +726,6 @@ static inline int __nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
  * @hdrlen: length of family specific header
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
- * @validate: validation strictness
  * @extack: extended ACK report struct
  *
  * See nla_parse()
@@ -824,7 +823,6 @@ static inline int nla_validate_deprecated(const struct nlattr *head, int len,
  * @len: length of attribute stream
  * @maxtype: maximum attribute type to be expected
  * @policy: validation policy
- * @validate: validation strictness
  * @extack: extended ACK report struct
  *
  * Validates all attributes in the specified attribute stream against the
@@ -1936,7 +1934,8 @@ void nla_get_range_signed(const struct nla_policy *pt,
 int netlink_policy_dump_start(const struct nla_policy *policy,
                              unsigned int maxtype,
                              unsigned long *state);
-bool netlink_policy_dump_loop(unsigned long *state);
+bool netlink_policy_dump_loop(unsigned long state);
 int netlink_policy_dump_write(struct sk_buff *skb, unsigned long state);
+void netlink_policy_dump_free(unsigned long state);
 
 #endif
index a1a8d45..6c0806b 100644 (file)
@@ -8,6 +8,7 @@ struct netns_nftables {
        struct list_head        tables;
        struct list_head        commit_list;
        struct list_head        module_list;
+       struct list_head        notify_list;
        struct mutex            commit_mutex;
        unsigned int            base_seq;
        u8                      gencursor;
index b33f1ae..0bdff38 100644 (file)
@@ -226,12 +226,14 @@ struct sctp_sock {
                data_ready_signalled:1;
 
        atomic_t pd_mode;
+
+       /* Fields after this point will be skipped on copies, like on accept
+        * and peeloff operations
+        */
+
        /* Receive to here while partial delivery is in effect. */
        struct sk_buff_head pd_lobby;
 
-       /* These must be the last fields, as they will skipped on copies,
-        * like on accept and peeloff operations
-        */
        struct list_head auto_asconf_list;
        int do_auto_asconf;
 };
index 3a41627..08537aa 100644 (file)
@@ -121,6 +121,9 @@ struct vxlanhdr_gbp {
 #define VXLAN_GBP_POLICY_APPLIED       (BIT(3) << 16)
 #define VXLAN_GBP_ID_MASK              (0xFFFF)
 
+#define VXLAN_GBP_MASK (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED | \
+                       VXLAN_GBP_ID_MASK)
+
 /*
  * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
index 2737d24..9e806c7 100644 (file)
@@ -1773,21 +1773,17 @@ static inline unsigned int xfrm_replay_state_esn_len(struct xfrm_replay_state_es
 static inline int xfrm_replay_clone(struct xfrm_state *x,
                                     struct xfrm_state *orig)
 {
-       x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
+
+       x->replay_esn = kmemdup(orig->replay_esn,
+                               xfrm_replay_state_esn_len(orig->replay_esn),
                                GFP_KERNEL);
        if (!x->replay_esn)
                return -ENOMEM;
-
-       x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
-       x->replay_esn->replay_window = orig->replay_esn->replay_window;
-
-       x->preplay_esn = kmemdup(x->replay_esn,
-                                xfrm_replay_state_esn_len(x->replay_esn),
+       x->preplay_esn = kmemdup(orig->preplay_esn,
+                                xfrm_replay_state_esn_len(orig->preplay_esn),
                                 GFP_KERNEL);
-       if (!x->preplay_esn) {
-               kfree(x->replay_esn);
+       if (!x->preplay_esn)
                return -ENOMEM;
-       }
 
        return 0;
 }
index da369b1..0ac4e7f 100644 (file)
@@ -566,6 +566,7 @@ struct ocelot_port {
        u8                              ptp_cmd;
        struct sk_buff_head             tx_skbs;
        u8                              ts_id;
+       spinlock_t                      ts_id_lock;
 
        phy_interface_t                 phy_mode;
 
@@ -677,6 +678,7 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
 int ocelot_init(struct ocelot *ocelot);
 void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);
+void ocelot_deinit_port(struct ocelot *ocelot, int port);
 
 /* DSA callbacks */
 void ocelot_port_enable(struct ocelot *ocelot, int port,
index 841c6ec..1669481 100644 (file)
 #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_M                 GENMASK(18, 16)
 #define ANA_SG_CONFIG_REG_3_LIST_LENGTH_X(x)              (((x) & GENMASK(18, 16)) >> 16)
 #define ANA_SG_CONFIG_REG_3_GATE_ENABLE                   BIT(20)
-#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)                   (((x) << 24) & GENMASK(27, 24))
-#define ANA_SG_CONFIG_REG_3_INIT_IPS_M                    GENMASK(27, 24)
-#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x)                 (((x) & GENMASK(27, 24)) >> 24)
-#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE               BIT(28)
+#define ANA_SG_CONFIG_REG_3_INIT_IPS(x)                   (((x) << 21) & GENMASK(24, 21))
+#define ANA_SG_CONFIG_REG_3_INIT_IPS_M                    GENMASK(24, 21)
+#define ANA_SG_CONFIG_REG_3_INIT_IPS_X(x)                 (((x) & GENMASK(24, 21)) >> 21)
+#define ANA_SG_CONFIG_REG_3_INIT_GATE_STATE               BIT(25)
 
 #define ANA_SG_GCL_GS_CONFIG_RSZ                          0x4
 
index 5e3919f..fc4fcac 100644 (file)
@@ -1193,6 +1193,8 @@ struct snd_soc_pcm_runtime {
             ((i) < (rtd)->num_cpus + (rtd)->num_codecs) &&             \
                     ((dai) = (rtd)->dais[i]);                          \
             (i)++)
+#define for_each_rtd_dais_rollback(rtd, i, dai)                \
+       for (; (--(i) >= 0) && ((dai) = (rtd)->dais[i]);)
 
 void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
 
@@ -1361,6 +1363,8 @@ void snd_soc_unregister_dai(struct snd_soc_dai *dai);
 
 struct snd_soc_dai *snd_soc_find_dai(
        const struct snd_soc_dai_link_component *dlc);
+struct snd_soc_dai *snd_soc_find_dai_with_mutex(
+       const struct snd_soc_dai_link_component *dlc);
 
 #include <sound/soc-dai.h>
 
index 5dcd24c..72ba36b 100644 (file)
@@ -79,6 +79,7 @@ enum {
        ETHTOOL_MSG_TSINFO_GET_REPLY,
        ETHTOOL_MSG_CABLE_TEST_NTF,
        ETHTOOL_MSG_CABLE_TEST_TDR_NTF,
+       ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
 
        /* add new constants above here */
        __ETHTOOL_MSG_KERNEL_CNT,
index f6d8603..7d8eced 100644 (file)
@@ -790,9 +790,10 @@ struct kvm_ppc_resize_hpt {
 #define KVM_VM_PPC_HV 1
 #define KVM_VM_PPC_PR 2
 
-/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */
-#define KVM_VM_MIPS_TE         0
+/* on MIPS, 0 indicates auto, 1 forces VZ ASE, 2 forces trap & emulate */
+#define KVM_VM_MIPS_AUTO       0
 #define KVM_VM_MIPS_VZ         1
+#define KVM_VM_MIPS_TE         2
 
 #define KVM_S390_SIE_PAGE_OFFSET 1
 
@@ -1035,6 +1036,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_LAST_CPU 184
 #define KVM_CAP_SMALLER_MAXPHYADDR 185
 #define KVM_CAP_S390_DIAG318 186
+#define KVM_CAP_STEAL_TIME 187
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index 4accfa7..8f8dc7a 100644 (file)
@@ -51,11 +51,11 @@ enum rxrpc_cmsg_type {
        RXRPC_BUSY              = 6,    /* -r: server busy received [terminal] */
        RXRPC_LOCAL_ERROR       = 7,    /* -r: local error generated [terminal] */
        RXRPC_NEW_CALL          = 8,    /* -r: [Service] new incoming call notification */
-       RXRPC_ACCEPT            = 9,    /* s-: [Service] accept request */
        RXRPC_EXCLUSIVE_CALL    = 10,   /* s-: Call should be on exclusive connection */
        RXRPC_UPGRADE_SERVICE   = 11,   /* s-: Request service upgrade for client call */
        RXRPC_TX_LENGTH         = 12,   /* s-: Total length of Tx data */
        RXRPC_SET_CALL_TIMEOUT  = 13,   /* s-: Set one or more call timeouts */
+       RXRPC_CHARGE_ACCEPT     = 14,   /* s-: Charge the accept pool with a user call ID */
        RXRPC__SUPPORTED
 };
 
index cee9f8e..f84e7bc 100644 (file)
@@ -288,6 +288,7 @@ enum
        LINUX_MIB_TCPTIMEOUTREHASH,             /* TCPTimeoutRehash */
        LINUX_MIB_TCPDUPLICATEDATAREHASH,       /* TCPDuplicateDataRehash */
        LINUX_MIB_TCPDSACKRECVSEGS,             /* TCPDSACKRecvSegs */
+       LINUX_MIB_TCPDSACKIGNOREDDUBIOUS,       /* TCPDSACKIgnoredDubious */
        __LINUX_MIB_MAX
 };
 
index c7b70ff..235db77 100644 (file)
@@ -191,8 +191,6 @@ enum v4l2_memory {
        V4L2_MEMORY_DMABUF           = 4,
 };
 
-#define V4L2_FLAG_MEMORY_NON_CONSISTENT                (1 << 0)
-
 /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
 enum v4l2_colorspace {
        /*
@@ -949,10 +947,7 @@ struct v4l2_requestbuffers {
        __u32                   type;           /* enum v4l2_buf_type */
        __u32                   memory;         /* enum v4l2_memory */
        __u32                   capabilities;
-       union {
-               __u32           flags;
-               __u32           reserved[1];
-       };
+       __u32                   reserved[1];
 };
 
 /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */
@@ -2456,9 +2451,6 @@ struct v4l2_dbg_chip_info {
  * @memory:    enum v4l2_memory; buffer memory type
  * @format:    frame format, for which buffers are requested
  * @capabilities: capabilities of this buffer type.
- * @flags:     additional buffer management attributes (ignored unless the
- *             queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability
- *             and configured for MMAP streaming I/O).
  * @reserved:  future extensions
  */
 struct v4l2_create_buffers {
@@ -2467,8 +2459,7 @@ struct v4l2_create_buffers {
        __u32                   memory;
        struct v4l2_format      format;
        __u32                   capabilities;
-       __u32                   flags;
-       __u32                   reserved[6];
+       __u32                   reserved[7];
 };
 
 /*
index 39df751..ac1b654 100644 (file)
@@ -83,6 +83,9 @@ static inline unsigned long bfn_to_pfn(unsigned long bfn)
        })
 #define gfn_to_virt(m)         (__va(gfn_to_pfn(m) << XEN_PAGE_SHIFT))
 
+#define percpu_to_gfn(v)       \
+       (pfn_to_gfn(per_cpu_ptr_to_phys(v) >> XEN_PAGE_SHIFT))
+
 /* Only used in PV code. But ARM guests are always HVM. */
 static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr)
 {
index ae78fb6..e880b4e 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/nmi.h>
 #include <linux/percpu.h>
 #include <linux/kmod.h>
+#include <linux/kprobes.h>
 #include <linux/vmalloc.h>
 #include <linux/kernel_stat.h>
 #include <linux/start_kernel.h>
@@ -303,7 +304,7 @@ static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
 
 #ifdef CONFIG_BOOT_CONFIG
 
-char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
+static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
 
 #define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
 
@@ -1402,6 +1403,7 @@ static int __ref kernel_init(void *unused)
        kernel_init_freeable();
        /* need to finish all async __init code before freeing the memory */
        async_synchronize_full();
+       kprobe_free_init_mem();
        ftrace_free_init_mem();
        free_initmem();
        mark_readonly();
index 78dfff6..7df28a4 100644 (file)
@@ -1622,7 +1622,6 @@ struct bpf_iter_seq_hash_map_info {
        struct bpf_map *map;
        struct bpf_htab *htab;
        void *percpu_value_buf; // non-zero means percpu hash
-       unsigned long flags;
        u32 bucket_id;
        u32 skip_elems;
 };
@@ -1632,7 +1631,6 @@ bpf_hash_map_seq_find_next(struct bpf_iter_seq_hash_map_info *info,
                           struct htab_elem *prev_elem)
 {
        const struct bpf_htab *htab = info->htab;
-       unsigned long flags = info->flags;
        u32 skip_elems = info->skip_elems;
        u32 bucket_id = info->bucket_id;
        struct hlist_nulls_head *head;
@@ -1656,19 +1654,18 @@ bpf_hash_map_seq_find_next(struct bpf_iter_seq_hash_map_info *info,
 
                /* not found, unlock and go to the next bucket */
                b = &htab->buckets[bucket_id++];
-               htab_unlock_bucket(htab, b, flags);
+               rcu_read_unlock();
                skip_elems = 0;
        }
 
        for (i = bucket_id; i < htab->n_buckets; i++) {
                b = &htab->buckets[i];
-               flags = htab_lock_bucket(htab, b);
+               rcu_read_lock();
 
                count = 0;
                head = &b->head;
                hlist_nulls_for_each_entry_rcu(elem, n, head, hash_node) {
                        if (count >= skip_elems) {
-                               info->flags = flags;
                                info->bucket_id = i;
                                info->skip_elems = count;
                                return elem;
@@ -1676,7 +1673,7 @@ bpf_hash_map_seq_find_next(struct bpf_iter_seq_hash_map_info *info,
                        count++;
                }
 
-               htab_unlock_bucket(htab, b, flags);
+               rcu_read_unlock();
                skip_elems = 0;
        }
 
@@ -1754,14 +1751,10 @@ static int bpf_hash_map_seq_show(struct seq_file *seq, void *v)
 
 static void bpf_hash_map_seq_stop(struct seq_file *seq, void *v)
 {
-       struct bpf_iter_seq_hash_map_info *info = seq->private;
-
        if (!v)
                (void)__bpf_hash_map_seq_show(seq, NULL);
        else
-               htab_unlock_bucket(info->htab,
-                                  &info->htab->buckets[info->bucket_id],
-                                  info->flags);
+               rcu_read_unlock();
 }
 
 static int bpf_iter_init_hash_map(void *priv_data,
index fb878ba..18f4969 100644 (file)
@@ -226,10 +226,12 @@ static void *map_seq_next(struct seq_file *m, void *v, loff_t *pos)
        else
                prev_key = key;
 
+       rcu_read_lock();
        if (map->ops->map_get_next_key(map, prev_key, key)) {
                map_iter(m)->done = true;
-               return NULL;
+               key = NULL;
        }
+       rcu_read_unlock();
        return key;
 }
 
index 3b49577..11b3380 100644 (file)
@@ -30,15 +30,15 @@ static struct kobject *btf_kobj;
 
 static int __init btf_vmlinux_init(void)
 {
-       if (!__start_BTF)
+       bin_attr_btf_vmlinux.size = __stop_BTF - __start_BTF;
+
+       if (!__start_BTF || bin_attr_btf_vmlinux.size == 0)
                return 0;
 
        btf_kobj = kobject_create_and_add("btf", kernel_kobj);
        if (!btf_kobj)
                return -ENOMEM;
 
-       bin_attr_btf_vmlinux.size = __stop_BTF - __start_BTF;
-
        return sysfs_create_bin_file(btf_kobj, &bin_attr_btf_vmlinux);
 }
 
index 47e74f0..fba52d9 100644 (file)
@@ -5667,8 +5667,8 @@ static void scalar32_min_max_or(struct bpf_reg_state *dst_reg,
        bool src_known = tnum_subreg_is_const(src_reg->var_off);
        bool dst_known = tnum_subreg_is_const(dst_reg->var_off);
        struct tnum var32_off = tnum_subreg(dst_reg->var_off);
-       s32 smin_val = src_reg->smin_value;
-       u32 umin_val = src_reg->umin_value;
+       s32 smin_val = src_reg->s32_min_value;
+       u32 umin_val = src_reg->u32_min_value;
 
        /* Assuming scalar64_min_max_or will be called so it is safe
         * to skip updating register for known case.
@@ -5691,8 +5691,8 @@ static void scalar32_min_max_or(struct bpf_reg_state *dst_reg,
                /* ORing two positives gives a positive, so safe to
                 * cast result into s64.
                 */
-               dst_reg->s32_min_value = dst_reg->umin_value;
-               dst_reg->s32_max_value = dst_reg->umax_value;
+               dst_reg->s32_min_value = dst_reg->u32_min_value;
+               dst_reg->s32_max_value = dst_reg->u32_max_value;
        }
 }
 
index 1868359..6fdb610 100644 (file)
@@ -60,13 +60,15 @@ static long syscall_trace_enter(struct pt_regs *regs, long syscall,
                        return ret;
        }
 
+       /* Either of the above might have changed the syscall number */
+       syscall = syscall_get_nr(current, regs);
+
        if (unlikely(ti_work & _TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, syscall);
 
        syscall_enter_audit(regs, syscall);
 
-       /* The above might have changed the syscall number */
-       return ret ? : syscall_get_nr(current, regs);
+       return ret ? : syscall;
 }
 
 static __always_inline long
index 49677d6..da8d360 100644 (file)
@@ -589,7 +589,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
 
                mm->map_count++;
                if (!(tmp->vm_flags & VM_WIPEONFORK))
-                       retval = copy_page_range(mm, oldmm, mpnt);
+                       retval = copy_page_range(mm, oldmm, mpnt, tmp);
 
                if (tmp->vm_ops && tmp->vm_ops->open)
                        tmp->vm_ops->open(tmp);
@@ -1011,6 +1011,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
        mm_pgtables_bytes_init(mm);
        mm->map_count = 0;
        mm->locked_vm = 0;
+       atomic_set(&mm->has_pinned, 0);
        atomic64_set(&mm->pinned_vm, 0);
        memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
        spin_lock_init(&mm->page_table_lock);
index bb4b680..3110c77 100644 (file)
@@ -4,7 +4,6 @@ menu "GCOV-based kernel profiling"
 config GCOV_KERNEL
        bool "Enable gcov-based kernel profiling"
        depends on DEBUG_FS
-       depends on !CC_IS_GCC || GCC_VERSION < 100000
        select CONSTRUCTORS if !UML
        default n
        help
index 908fdf5..53c67c8 100644 (file)
@@ -19,7 +19,9 @@
 #include <linux/vmalloc.h>
 #include "gcov.h"
 
-#if (__GNUC__ >= 7)
+#if (__GNUC__ >= 10)
+#define GCOV_COUNTERS                  8
+#elif (__GNUC__ >= 7)
 #define GCOV_COUNTERS                  9
 #elif (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
 #define GCOV_COUNTERS                  10
index 287b263..e995541 100644 (file)
@@ -2140,6 +2140,9 @@ static void kill_kprobe(struct kprobe *p)
 
        lockdep_assert_held(&kprobe_mutex);
 
+       if (WARN_ON_ONCE(kprobe_gone(p)))
+               return;
+
        p->flags |= KPROBE_FLAG_GONE;
        if (kprobe_aggrprobe(p)) {
                /*
@@ -2159,9 +2162,10 @@ static void kill_kprobe(struct kprobe *p)
 
        /*
         * The module is going away. We should disarm the kprobe which
-        * is using ftrace.
+        * is using ftrace, because ftrace framework is still available at
+        * MODULE_STATE_GOING notification.
         */
-       if (kprobe_ftrace(p))
+       if (kprobe_ftrace(p) && !kprobe_disabled(p) && !kprobes_all_disarmed)
                disarm_kprobe_ftrace(p);
 }
 
@@ -2419,7 +2423,10 @@ static int kprobes_module_callback(struct notifier_block *nb,
        mutex_lock(&kprobe_mutex);
        for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
                head = &kprobe_table[i];
-               hlist_for_each_entry(p, head, hlist)
+               hlist_for_each_entry(p, head, hlist) {
+                       if (kprobe_gone(p))
+                               continue;
+
                        if (within_module_init((unsigned long)p->addr, mod) ||
                            (checkcore &&
                             within_module_core((unsigned long)p->addr, mod))) {
@@ -2436,6 +2443,7 @@ static int kprobes_module_callback(struct notifier_block *nb,
                                 */
                                kill_kprobe(p);
                        }
+               }
        }
        if (val == MODULE_STATE_GOING)
                remove_module_kprobe_blacklist(mod);
@@ -2452,6 +2460,28 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+void kprobe_free_init_mem(void)
+{
+       void *start = (void *)(&__init_begin);
+       void *end = (void *)(&__init_end);
+       struct hlist_head *head;
+       struct kprobe *p;
+       int i;
+
+       mutex_lock(&kprobe_mutex);
+
+       /* Kill all kprobes on initmem */
+       for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
+               head = &kprobe_table[i];
+               hlist_for_each_entry(p, head, hlist) {
+                       if (start <= (void *)p->addr && (void *)p->addr < end)
+                               kill_kprobe(p);
+               }
+       }
+
+       mutex_unlock(&kprobe_mutex);
+}
+
 static int __init init_kprobes(void)
 {
        int i, err = 0;
index 54b74fa..2facbbd 100644 (file)
@@ -3969,13 +3969,18 @@ static int separate_irq_context(struct task_struct *curr,
 static int mark_lock(struct task_struct *curr, struct held_lock *this,
                             enum lock_usage_bit new_bit)
 {
-       unsigned int new_mask = 1 << new_bit, ret = 1;
+       unsigned int old_mask, new_mask, ret = 1;
 
        if (new_bit >= LOCK_USAGE_STATES) {
                DEBUG_LOCKS_WARN_ON(1);
                return 0;
        }
 
+       if (new_bit == LOCK_USED && this->read)
+               new_bit = LOCK_USED_READ;
+
+       new_mask = 1 << new_bit;
+
        /*
         * If already set then do not dirty the cacheline,
         * nor do any checks:
@@ -3988,13 +3993,22 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
        /*
         * Make sure we didn't race:
         */
-       if (unlikely(hlock_class(this)->usage_mask & new_mask)) {
-               graph_unlock();
-               return 1;
-       }
+       if (unlikely(hlock_class(this)->usage_mask & new_mask))
+               goto unlock;
 
+       old_mask = hlock_class(this)->usage_mask;
        hlock_class(this)->usage_mask |= new_mask;
 
+       /*
+        * Save one usage_traces[] entry and map both LOCK_USED and
+        * LOCK_USED_READ onto the same entry.
+        */
+       if (new_bit == LOCK_USED || new_bit == LOCK_USED_READ) {
+               if (old_mask & (LOCKF_USED | LOCKF_USED_READ))
+                       goto unlock;
+               new_bit = LOCK_USED;
+       }
+
        if (!(hlock_class(this)->usage_traces[new_bit] = save_trace()))
                return 0;
 
@@ -4008,6 +4022,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
                        return 0;
        }
 
+unlock:
        graph_unlock();
 
        /*
@@ -4942,12 +4957,20 @@ static void verify_lock_unused(struct lockdep_map *lock, struct held_lock *hlock
 {
 #ifdef CONFIG_PROVE_LOCKING
        struct lock_class *class = look_up_lock_class(lock, subclass);
+       unsigned long mask = LOCKF_USED;
 
        /* if it doesn't have a class (yet), it certainly hasn't been used yet */
        if (!class)
                return;
 
-       if (!(class->usage_mask & LOCK_USED))
+       /*
+        * READ locks only conflict with USED, such that if we only ever use
+        * READ locks, there is no deadlock possible -- RCU.
+        */
+       if (!hlock->read)
+               mask |= LOCKF_USED_READ;
+
+       if (!(class->usage_mask & mask))
                return;
 
        hlock->class_idx = class - lock_classes;
index baca699..b0be156 100644 (file)
@@ -19,6 +19,7 @@ enum lock_usage_bit {
 #include "lockdep_states.h"
 #undef LOCKDEP_STATE
        LOCK_USED,
+       LOCK_USED_READ,
        LOCK_USAGE_STATES
 };
 
@@ -40,6 +41,7 @@ enum {
 #include "lockdep_states.h"
 #undef LOCKDEP_STATE
        __LOCKF(USED)
+       __LOCKF(USED_READ)
 };
 
 #define LOCKDEP_STATE(__STATE) LOCKF_ENABLED_##__STATE |
index 8bbafe3..70a32a5 100644 (file)
@@ -45,7 +45,7 @@ EXPORT_SYMBOL_GPL(percpu_free_rwsem);
 
 static bool __percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
 {
-       __this_cpu_inc(*sem->read_count);
+       this_cpu_inc(*sem->read_count);
 
        /*
         * Due to having preemption disabled the decrement happens on
@@ -71,7 +71,7 @@ static bool __percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
        if (likely(!atomic_read_acquire(&sem->block)))
                return true;
 
-       __this_cpu_dec(*sem->read_count);
+       this_cpu_dec(*sem->read_count);
 
        /* Prod writer to re-evaluate readers_active_check() */
        rcuwait_wake_up(&sem->writer);
index 16cb894..d4d3ba6 100644 (file)
@@ -215,12 +215,13 @@ int padata_do_parallel(struct padata_shell *ps,
        padata->pd = pd;
        padata->cb_cpu = *cb_cpu;
 
-       rcu_read_unlock_bh();
-
        spin_lock(&padata_works_lock);
        padata->seq_nr = ++pd->seq_nr;
        pw = padata_work_alloc();
        spin_unlock(&padata_works_lock);
+
+       rcu_read_unlock_bh();
+
        if (pw) {
                padata_work_init(pw, padata_parallel_worker, padata, 0);
                queue_work(pinst->parallel_wq, &pw->pw_work);
index 835e2df..05d3e13 100644 (file)
@@ -590,7 +590,7 @@ void exit_tasks_rcu_finish(void) __releases(&tasks_rcu_exit_srcu)
 }
 
 #else /* #ifdef CONFIG_TASKS_RCU */
-static void show_rcu_tasks_classic_gp_kthread(void) { }
+static inline void show_rcu_tasks_classic_gp_kthread(void) { }
 void exit_tasks_rcu_start(void) { }
 void exit_tasks_rcu_finish(void) { exit_tasks_rcu_finish_trace(current); }
 #endif /* #else #ifdef CONFIG_TASKS_RCU */
index 8ce77d9..f78ee75 100644 (file)
@@ -673,6 +673,7 @@ void rcu_idle_enter(void)
        lockdep_assert_irqs_disabled();
        rcu_eqs_enter(false);
 }
+EXPORT_SYMBOL_GPL(rcu_idle_enter);
 
 #ifdef CONFIG_NO_HZ_FULL
 /**
@@ -886,6 +887,7 @@ void rcu_idle_exit(void)
        rcu_eqs_exit(false);
        local_irq_restore(flags);
 }
+EXPORT_SYMBOL_GPL(rcu_idle_exit);
 
 #ifdef CONFIG_NO_HZ_FULL
 /**
index 3ee59ce..676d4af 100644 (file)
@@ -1109,13 +1109,18 @@ out:
 }
 
 #ifdef CONFIG_SECCOMP_FILTER
-static int seccomp_notify_release(struct inode *inode, struct file *file)
+static void seccomp_notify_free(struct seccomp_filter *filter)
+{
+       kfree(filter->notif);
+       filter->notif = NULL;
+}
+
+static void seccomp_notify_detach(struct seccomp_filter *filter)
 {
-       struct seccomp_filter *filter = file->private_data;
        struct seccomp_knotif *knotif;
 
        if (!filter)
-               return 0;
+               return;
 
        mutex_lock(&filter->notify_lock);
 
@@ -1139,9 +1144,15 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
                complete(&knotif->ready);
        }
 
-       kfree(filter->notif);
-       filter->notif = NULL;
+       seccomp_notify_free(filter);
        mutex_unlock(&filter->notify_lock);
+}
+
+static int seccomp_notify_release(struct inode *inode, struct file *file)
+{
+       struct seccomp_filter *filter = file->private_data;
+
+       seccomp_notify_detach(filter);
        __put_seccomp_filter(filter);
        return 0;
 }
@@ -1488,7 +1499,7 @@ static struct file *init_listener(struct seccomp_filter *filter)
 
 out_notif:
        if (IS_ERR(ret))
-               kfree(filter->notif);
+               seccomp_notify_free(filter);
 out:
        return ret;
 }
@@ -1581,6 +1592,7 @@ out_put_fd:
                        listener_f->private_data = NULL;
                        fput(listener_f);
                        put_unused_fd(listener);
+                       seccomp_notify_detach(prepared);
                } else {
                        fd_install(listener, listener_f);
                        ret = listener;
index a8fc9ae..ce161a8 100644 (file)
@@ -20,7 +20,7 @@
 static DEFINE_STATIC_KEY_FALSE(stack_erasing_bypass);
 
 int stack_erasing_sysctl(struct ctl_table *table, int write,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
+                       void *buffer, size_t *lenp, loff_t *ppos)
 {
        int ret = 0;
        int state = !static_branch_unlikely(&stack_erasing_bypass);
index 09e70ee..afad085 100644 (file)
@@ -2912,6 +2912,14 @@ static struct ctl_table vm_table[] = {
                .proc_handler   = percpu_pagelist_fraction_sysctl_handler,
                .extra1         = SYSCTL_ZERO,
        },
+       {
+               .procname       = "page_lock_unfairness",
+               .data           = &sysctl_page_lock_unfairness,
+               .maxlen         = sizeof(sysctl_page_lock_unfairness),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = SYSCTL_ZERO,
+       },
 #ifdef CONFIG_MMU
        {
                .procname       = "max_map_count",
index 2754412..5414539 100644 (file)
@@ -2782,6 +2782,7 @@ static void ftrace_remove_trampoline_from_kallsyms(struct ftrace_ops *ops)
 {
        lockdep_assert_held(&ftrace_lock);
        list_del_rcu(&ops->list);
+       synchronize_rcu();
 }
 
 /*
@@ -2862,6 +2863,8 @@ int ftrace_startup(struct ftrace_ops *ops, int command)
                __unregister_ftrace_function(ops);
                ftrace_start_up--;
                ops->flags &= ~FTRACE_OPS_FL_ENABLED;
+               if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
+                       ftrace_trampoline_free(ops);
                return ret;
        }
 
@@ -6990,16 +6993,14 @@ static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip,
 {
        int bit;
 
-       if ((op->flags & FTRACE_OPS_FL_RCU) && !rcu_is_watching())
-               return;
-
        bit = trace_test_and_set_recursion(TRACE_LIST_START, TRACE_LIST_MAX);
        if (bit < 0)
                return;
 
        preempt_disable_notrace();
 
-       op->func(ip, parent_ip, op, regs);
+       if (!(op->flags & FTRACE_OPS_FL_RCU) || rcu_is_watching())
+               op->func(ip, parent_ip, op, regs);
 
        preempt_enable_notrace();
        trace_clear_recursion(bit);
@@ -7531,8 +7532,7 @@ static bool is_permanent_ops_registered(void)
 
 int
 ftrace_enable_sysctl(struct ctl_table *table, int write,
-                    void __user *buffer, size_t *lenp,
-                    loff_t *ppos)
+                    void *buffer, size_t *lenp, loff_t *ppos)
 {
        int ret = -ENODEV;
 
index f40d850..d3e5de7 100644 (file)
@@ -3546,13 +3546,15 @@ struct trace_entry *trace_find_next_entry(struct trace_iterator *iter,
        if (iter->ent && iter->ent != iter->temp) {
                if ((!iter->temp || iter->temp_size < iter->ent_size) &&
                    !WARN_ON_ONCE(iter->temp == static_temp_buf)) {
-                       kfree(iter->temp);
-                       iter->temp = kmalloc(iter->ent_size, GFP_KERNEL);
-                       if (!iter->temp)
+                       void *temp;
+                       temp = kmalloc(iter->ent_size, GFP_KERNEL);
+                       if (!temp)
                                return NULL;
+                       kfree(iter->temp);
+                       iter->temp = temp;
+                       iter->temp_size = iter->ent_size;
                }
                memcpy(iter->temp, iter->ent, iter->ent_size);
-               iter->temp_size = iter->ent_size;
                iter->ent = iter->temp;
        }
        entry = __find_next_entry(iter, ent_cpu, NULL, ent_ts);
@@ -3782,14 +3784,14 @@ unsigned long trace_total_entries(struct trace_array *tr)
 
 static void print_lat_help_header(struct seq_file *m)
 {
-       seq_puts(m, "#                  _------=> CPU#            \n"
-                   "#                 / _-----=> irqs-off        \n"
-                   "#                | / _----=> need-resched    \n"
-                   "#                || / _---=> hardirq/softirq \n"
-                   "#                ||| / _--=> preempt-depth   \n"
-                   "#                |||| /     delay            \n"
-                   "#  cmd     pid   ||||| time  |   caller      \n"
-                   "#     \\   /      |||||  \\    |   /         \n");
+       seq_puts(m, "#                    _------=> CPU#            \n"
+                   "#                   / _-----=> irqs-off        \n"
+                   "#                  | / _----=> need-resched    \n"
+                   "#                  || / _---=> hardirq/softirq \n"
+                   "#                  ||| / _--=> preempt-depth   \n"
+                   "#                  |||| /     delay            \n"
+                   "#  cmd     pid     ||||| time  |   caller      \n"
+                   "#     \\   /        |||||  \\    |   /         \n");
 }
 
 static void print_event_info(struct array_buffer *buf, struct seq_file *m)
@@ -3810,26 +3812,26 @@ static void print_func_help_header(struct array_buffer *buf, struct seq_file *m,
 
        print_event_info(buf, m);
 
-       seq_printf(m, "#           TASK-PID   %s  CPU#   TIMESTAMP  FUNCTION\n", tgid ? "TGID     " : "");
-       seq_printf(m, "#              | |     %s    |       |         |\n",      tgid ? "  |      " : "");
+       seq_printf(m, "#           TASK-PID    %s CPU#     TIMESTAMP  FUNCTION\n", tgid ? "   TGID   " : "");
+       seq_printf(m, "#              | |      %s   |         |         |\n",      tgid ? "     |    " : "");
 }
 
 static void print_func_help_header_irq(struct array_buffer *buf, struct seq_file *m,
                                       unsigned int flags)
 {
        bool tgid = flags & TRACE_ITER_RECORD_TGID;
-       const char *space = "          ";
-       int prec = tgid ? 10 : 2;
+       const char *space = "            ";
+       int prec = tgid ? 12 : 2;
 
        print_event_info(buf, m);
 
-       seq_printf(m, "#                          %.*s  _-----=> irqs-off\n", prec, space);
-       seq_printf(m, "#                          %.*s / _----=> need-resched\n", prec, space);
-       seq_printf(m, "#                          %.*s| / _---=> hardirq/softirq\n", prec, space);
-       seq_printf(m, "#                          %.*s|| / _--=> preempt-depth\n", prec, space);
-       seq_printf(m, "#                          %.*s||| /     delay\n", prec, space);
-       seq_printf(m, "#           TASK-PID %.*sCPU#  ||||    TIMESTAMP  FUNCTION\n", prec, "   TGID   ");
-       seq_printf(m, "#              | |   %.*s  |   ||||       |         |\n", prec, "     |    ");
+       seq_printf(m, "#                            %.*s  _-----=> irqs-off\n", prec, space);
+       seq_printf(m, "#                            %.*s / _----=> need-resched\n", prec, space);
+       seq_printf(m, "#                            %.*s| / _---=> hardirq/softirq\n", prec, space);
+       seq_printf(m, "#                            %.*s|| / _--=> preempt-depth\n", prec, space);
+       seq_printf(m, "#                            %.*s||| /     delay\n", prec, space);
+       seq_printf(m, "#           TASK-PID  %.*s CPU#  ||||   TIMESTAMP  FUNCTION\n", prec, "     TGID   ");
+       seq_printf(m, "#              | |    %.*s   |   ||||      |         |\n", prec, "       |    ");
 }
 
 void
index 0b93354..1b2ef64 100644 (file)
@@ -3865,7 +3865,6 @@ static int parse_var_defs(struct hist_trigger_data *hist_data)
 
                        s = kstrdup(field_str, GFP_KERNEL);
                        if (!s) {
-                               kfree(hist_data->attrs->var_defs.name[n_vars]);
                                ret = -ENOMEM;
                                goto free;
                        }
index 4d18935..000e9dc 100644 (file)
@@ -497,7 +497,7 @@ lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
 
        trace_find_cmdline(entry->pid, comm);
 
-       trace_seq_printf(s, "%8.8s-%-5d %3d",
+       trace_seq_printf(s, "%8.8s-%-7d %3d",
                         comm, entry->pid, cpu);
 
        return trace_print_lat_fmt(s, entry);
@@ -588,15 +588,15 @@ int trace_print_context(struct trace_iterator *iter)
 
        trace_find_cmdline(entry->pid, comm);
 
-       trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
+       trace_seq_printf(s, "%16s-%-7d ", comm, entry->pid);
 
        if (tr->trace_flags & TRACE_ITER_RECORD_TGID) {
                unsigned int tgid = trace_find_tgid(entry->pid);
 
                if (!tgid)
-                       trace_seq_printf(s, "(-----) ");
+                       trace_seq_printf(s, "(-------) ");
                else
-                       trace_seq_printf(s, "(%5d) ", tgid);
+                       trace_seq_printf(s, "(%7d) ", tgid);
        }
 
        trace_seq_printf(s, "[%03d] ", iter->cpu);
@@ -636,7 +636,7 @@ int trace_print_lat_context(struct trace_iterator *iter)
                trace_find_cmdline(entry->pid, comm);
 
                trace_seq_printf(
-                       s, "%16s %5d %3d %d %08x %08lx ",
+                       s, "%16s %7d %3d %d %08x %08lx ",
                        comm, entry->pid, iter->cpu, entry->flags,
                        entry->preempt_count, iter->idx);
        } else {
@@ -917,7 +917,7 @@ static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
        S = task_index_to_char(field->prev_state);
        trace_find_cmdline(field->next_pid, comm);
        trace_seq_printf(&iter->seq,
-                        " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
+                        " %7d:%3d:%c %s [%03d] %7d:%3d:%c %s\n",
                         field->prev_pid,
                         field->prev_prio,
                         S, delim,
index f10073e..f493804 100644 (file)
@@ -102,14 +102,14 @@ NOKPROBE_SYMBOL(trace_hardirqs_on_caller);
 
 __visible void trace_hardirqs_off_caller(unsigned long caller_addr)
 {
+       lockdep_hardirqs_off(CALLER_ADDR0);
+
        if (!this_cpu_read(tracing_irq_cpu)) {
                this_cpu_write(tracing_irq_cpu, 1);
                tracer_hardirqs_off(CALLER_ADDR0, caller_addr);
                if (!in_nmi())
                        trace_irq_disable_rcuidle(CALLER_ADDR0, caller_addr);
        }
-
-       lockdep_hardirqs_off(CALLER_ADDR0);
 }
 EXPORT_SYMBOL(trace_hardirqs_off_caller);
 NOKPROBE_SYMBOL(trace_hardirqs_off_caller);
index fcf3ee8..3f64661 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/cred.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
+#include <linux/fs_struct.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
 #include <linux/mount.h>
@@ -72,6 +73,14 @@ static int call_usermodehelper_exec_async(void *data)
        spin_unlock_irq(&current->sighand->siglock);
 
        /*
+        * Initial kernel threads share ther FS with init, in order to
+        * get the init root directory. But we've now created a new
+        * thread that is going to execve a user process and has its own
+        * 'struct fs_struct'. Reset umask to the default.
+        */
+       current->fs->umask = 0022;
+
+       /*
         * Our parent (unbound workqueue) runs with elevated scheduling
         * priority. Avoid propagating that into the userspace child.
         */
index e068c3c..0c781f9 100644 (file)
@@ -520,8 +520,8 @@ config DEBUG_FS_ALLOW_NONE
 endchoice
 
 source "lib/Kconfig.kgdb"
-
 source "lib/Kconfig.ubsan"
+source "lib/Kconfig.kcsan"
 
 endmenu
 
@@ -1620,8 +1620,6 @@ config PROVIDE_OHCI1394_DMA_INIT
 
 source "samples/Kconfig"
 
-source "lib/Kconfig.kcsan"
-
 config ARCH_HAS_DEVMEM_IS_ALLOWED
        bool
 
index 2c905a9..649ed44 100644 (file)
@@ -31,6 +31,8 @@ static size_t xbc_data_size __initdata;
 static struct xbc_node *last_parent __initdata;
 static const char *xbc_err_msg __initdata;
 static int xbc_err_pos __initdata;
+static int open_brace[XBC_DEPTH_MAX] __initdata;
+static int brace_index __initdata;
 
 static int __init xbc_parse_error(const char *msg, const char *p)
 {
@@ -431,27 +433,27 @@ static char *skip_spaces_until_newline(char *p)
        return p;
 }
 
-static int __init __xbc_open_brace(void)
+static int __init __xbc_open_brace(char *p)
 {
-       /* Mark the last key as open brace */
-       last_parent->next = XBC_NODE_MAX;
+       /* Push the last key as open brace */
+       open_brace[brace_index++] = xbc_node_index(last_parent);
+       if (brace_index >= XBC_DEPTH_MAX)
+               return xbc_parse_error("Exceed max depth of braces", p);
 
        return 0;
 }
 
 static int __init __xbc_close_brace(char *p)
 {
-       struct xbc_node *node;
-
-       if (!last_parent || last_parent->next != XBC_NODE_MAX)
+       brace_index--;
+       if (!last_parent || brace_index < 0 ||
+           (open_brace[brace_index] != xbc_node_index(last_parent)))
                return xbc_parse_error("Unexpected closing brace", p);
 
-       node = last_parent;
-       node->next = 0;
-       do {
-               node = xbc_node_get_parent(node);
-       } while (node && node->next != XBC_NODE_MAX);
-       last_parent = node;
+       if (brace_index == 0)
+               last_parent = NULL;
+       else
+               last_parent = &xbc_nodes[open_brace[brace_index - 1]];
 
        return 0;
 }
@@ -492,8 +494,8 @@ static int __init __xbc_parse_value(char **__v, char **__n)
                        break;
                }
                if (strchr(",;\n#}", c)) {
-                       v = strim(v);
                        *p++ = '\0';
+                       v = strim(v);
                        break;
                }
        }
@@ -661,7 +663,7 @@ static int __init xbc_open_brace(char **k, char *n)
                return ret;
        *k = n;
 
-       return __xbc_open_brace();
+       return __xbc_open_brace(n - 1);
 }
 
 static int __init xbc_close_brace(char **k, char *n)
@@ -681,6 +683,13 @@ static int __init xbc_verify_tree(void)
        int i, depth, len, wlen;
        struct xbc_node *n, *m;
 
+       /* Brace closing */
+       if (brace_index) {
+               n = &xbc_nodes[open_brace[brace_index]];
+               return xbc_parse_error("Brace is not closed",
+                                       xbc_node_get_data(n));
+       }
+
        /* Empty tree */
        if (xbc_node_num == 0) {
                xbc_parse_error("Empty config", xbc_data);
@@ -745,6 +754,7 @@ void __init xbc_destroy_all(void)
        xbc_node_num = 0;
        memblock_free(__pa(xbc_nodes), sizeof(struct xbc_node) * XBC_NODE_MAX);
        xbc_nodes = NULL;
+       brace_index = 0;
 }
 
 /**
index 1d012e5..2d4dfd4 100644 (file)
@@ -353,8 +353,7 @@ static int check_set(const char **dest, char *src, char *name)
 
 /*
  * Parse words[] as a ddebug query specification, which is a series
- * of (keyword, value) pairs or combined keyword=value terms,
- * chosen from these possibilities:
+ * of (keyword, value) pairs chosen from these possibilities:
  *
  * func <function-name>
  * file <full-pathname>
@@ -373,34 +372,22 @@ static int ddebug_parse_query(char *words[], int nwords,
        unsigned int i;
        int rc = 0;
        char *fline;
-       char *keyword, *arg;
+
+       /* check we have an even number of words */
+       if (nwords % 2 != 0) {
+               pr_err("expecting pairs of match-spec <value>\n");
+               return -EINVAL;
+       }
 
        if (modname)
                /* support $modname.dyndbg=<multiple queries> */
                query->module = modname;
 
-       for (i = 0; i < nwords; i++) {
-               /* accept keyword=arg */
-               vpr_info("%d w:%s\n", i, words[i]);
-
-               keyword = words[i];
-               arg = strchr(keyword, '=');
-               if (arg) {
-                       *arg++ = '\0';
-               } else {
-                       i++; /* next word is arg */
-                       if (!(i < nwords)) {
-                               pr_err("missing arg to keyword: %s\n", keyword);
-                               return -EINVAL;
-                       }
-                       arg = words[i];
-               }
-               vpr_info("%d key:%s arg:%s\n", i, keyword, arg);
-
-               if (!strcmp(keyword, "func")) {
-                       rc = check_set(&query->function, arg, "func");
-               } else if (!strcmp(keyword, "file")) {
-                       if (check_set(&query->filename, arg, "file"))
+       for (i = 0; i < nwords; i += 2) {
+               if (!strcmp(words[i], "func")) {
+                       rc = check_set(&query->function, words[i+1], "func");
+               } else if (!strcmp(words[i], "file")) {
+                       if (check_set(&query->filename, words[i+1], "file"))
                                return -EINVAL;
 
                        /* tail :$info is function or line-range */
@@ -416,18 +403,18 @@ static int ddebug_parse_query(char *words[], int nwords,
                                if (parse_linerange(query, fline))
                                        return -EINVAL;
                        }
-               } else if (!strcmp(keyword, "module")) {
-                       rc = check_set(&query->module, arg, "module");
-               } else if (!strcmp(keyword, "format")) {
-                       string_unescape_inplace(arg, UNESCAPE_SPACE |
+               } else if (!strcmp(words[i], "module")) {
+                       rc = check_set(&query->module, words[i+1], "module");
+               } else if (!strcmp(words[i], "format")) {
+                       string_unescape_inplace(words[i+1], UNESCAPE_SPACE |
                                                            UNESCAPE_OCTAL |
                                                            UNESCAPE_SPECIAL);
-                       rc = check_set(&query->format, arg, "format");
-               } else if (!strcmp(keyword, "line")) {
-                       if (parse_linerange(query, arg))
+                       rc = check_set(&query->format, words[i+1], "format");
+               } else if (!strcmp(words[i], "line")) {
+                       if (parse_linerange(query, words[i+1]))
                                return -EINVAL;
                } else {
-                       pr_err("unknown keyword \"%s\"\n", keyword);
+                       pr_err("unknown keyword \"%s\"\n", words[i]);
                        return -EINVAL;
                }
                if (rc)
@@ -525,7 +512,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
    last error or number of matching callsites.  Module name is either
    in param (for boot arg) or perhaps in query string.
 */
-int ddebug_exec_queries(char *query, const char *modname)
+static int ddebug_exec_queries(char *query, const char *modname)
 {
        char *split;
        int i, errs = 0, exitcode = 0, rc, nfound = 0;
@@ -557,7 +544,30 @@ int ddebug_exec_queries(char *query, const char *modname)
                return exitcode;
        return nfound;
 }
-EXPORT_SYMBOL_GPL(ddebug_exec_queries);
+
+/**
+ * dynamic_debug_exec_queries - select and change dynamic-debug prints
+ * @query: query-string described in admin-guide/dynamic-debug-howto
+ * @modname: string containing module name, usually &module.mod_name
+ *
+ * This uses the >/proc/dynamic_debug/control reader, allowing module
+ * authors to modify their dynamic-debug callsites. The modname is
+ * canonically struct module.mod_name, but can also be null or a
+ * module-wildcard, for example: "drm*".
+ */
+int dynamic_debug_exec_queries(const char *query, const char *modname)
+{
+       int rc;
+       char *qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL);
+
+       if (!query)
+               return -ENOMEM;
+
+       rc = ddebug_exec_queries(qry, modname);
+       kfree(qry);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
 
 #define PREFIX_SIZE 64
 
@@ -947,7 +957,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
        list_add(&dt->link, &ddebug_tables);
        mutex_unlock(&ddebug_lock);
 
-       v2pr_info("%u debug prints in module %s\n", n, dt->mod_name);
+       v2pr_info("%3u debug prints in module %s\n", n, dt->mod_name);
        return 0;
 }
 
index 532f0ff..0e2deac 100644 (file)
@@ -8,8 +8,8 @@
 
 #define FONTDATAMAX 9216
 
-static const unsigned char fontdata_10x18[FONTDATAMAX] = {
-
+static struct font_data fontdata_10x18 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, 0x00, /* 0000000000 */
        0x00, 0x00, /* 0000000000 */
@@ -5129,8 +5129,7 @@ static const unsigned char fontdata_10x18[FONTDATAMAX] = {
        0x00, 0x00, /* 0000000000 */
        0x00, 0x00, /* 0000000000 */
        0x00, 0x00, /* 0000000000 */
-
-};
+} };
 
 
 const struct font_desc font_10x18 = {
@@ -5138,7 +5137,7 @@ const struct font_desc font_10x18 = {
        .name   = "10x18",
        .width  = 10,
        .height = 18,
-       .data   = fontdata_10x18,
+       .data   = fontdata_10x18.data,
 #ifdef __sparc__
        .pref   = 5,
 #else
index 09b2cc0..87da8ac 100644 (file)
@@ -1,8 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/font.h>
 
-static const unsigned char fontdata_6x10[] = {
+#define FONTDATAMAX 2560
 
+static struct font_data fontdata_6x10 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3074,14 +3076,13 @@ static const unsigned char fontdata_6x10[] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
-
-};
+} };
 
 const struct font_desc font_6x10 = {
        .idx    = FONT6x10_IDX,
        .name   = "6x10",
        .width  = 6,
        .height = 10,
-       .data   = fontdata_6x10,
+       .data   = fontdata_6x10.data,
        .pref   = 0,
 };
index d7136c3..5e975df 100644 (file)
@@ -9,8 +9,8 @@
 
 #define FONTDATAMAX (11*256)
 
-static const unsigned char fontdata_6x11[FONTDATAMAX] = {
-
+static struct font_data fontdata_6x11 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3338,8 +3338,7 @@ static const unsigned char fontdata_6x11[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
-
-};
+} };
 
 
 const struct font_desc font_vga_6x11 = {
@@ -3347,7 +3346,7 @@ const struct font_desc font_vga_6x11 = {
        .name   = "ProFont6x11",
        .width  = 6,
        .height = 11,
-       .data   = fontdata_6x11,
+       .data   = fontdata_6x11.data,
        /* Try avoiding this font if possible unless on MAC */
        .pref   = -2000,
 };
index 89752d0..86d298f 100644 (file)
@@ -8,8 +8,8 @@
 
 #define FONTDATAMAX 3584
 
-static const unsigned char fontdata_7x14[FONTDATAMAX] = {
-
+static struct font_data fontdata_7x14 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -4105,8 +4105,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
-
-};
+} };
 
 
 const struct font_desc font_7x14 = {
@@ -4114,6 +4113,6 @@ const struct font_desc font_7x14 = {
        .name   = "7x14",
        .width  = 7,
        .height = 14,
-       .data   = fontdata_7x14,
+       .data   = fontdata_7x14.data,
        .pref   = 0,
 };
index b7ab1f5..37cedd3 100644 (file)
@@ -10,8 +10,8 @@
 
 #define FONTDATAMAX 4096
 
-static const unsigned char fontdata_8x16[FONTDATAMAX] = {
-
+static struct font_data fontdata_8x16 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4619,8 +4619,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
-
-};
+} };
 
 
 const struct font_desc font_vga_8x16 = {
@@ -4628,7 +4627,7 @@ const struct font_desc font_vga_8x16 = {
        .name   = "VGA8x16",
        .width  = 8,
        .height = 16,
-       .data   = fontdata_8x16,
+       .data   = fontdata_8x16.data,
        .pref   = 0,
 };
 EXPORT_SYMBOL(font_vga_8x16);
index 2328ebc..8ab6955 100644 (file)
@@ -9,8 +9,8 @@
 
 #define FONTDATAMAX 2048
 
-static const unsigned char fontdata_8x8[FONTDATAMAX] = {
-
+static struct font_data fontdata_8x8 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2570,8 +2570,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
-
-};
+} };
 
 
 const struct font_desc font_vga_8x8 = {
@@ -2579,6 +2578,6 @@ const struct font_desc font_vga_8x8 = {
        .name   = "VGA8x8",
        .width  = 8,
        .height = 8,
-       .data   = fontdata_8x8,
+       .data   = fontdata_8x8.data,
        .pref   = 0,
 };
index 0ff0e85..069b3e8 100644 (file)
@@ -3,7 +3,10 @@
 
 #include <linux/font.h>
 
-static const unsigned char acorndata_8x8[] = {
+#define FONTDATAMAX 2048
+
+static struct font_data acorndata_8x8 = {
+{ 0, 0, FONTDATAMAX, 0 }, {
 /* 00 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
 /* 01 */  0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
 /* 02 */  0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
@@ -260,14 +263,14 @@ static const unsigned char acorndata_8x8[] = {
 /* FD */  0x38, 0x04, 0x18, 0x20, 0x3c, 0x00, 0x00, 0x00,
 /* FE */  0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
 /* FF */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+} };
 
 const struct font_desc font_acorn_8x8 = {
        .idx    = ACORN8x8_IDX,
        .name   = "Acorn8x8",
        .width  = 8,
        .height = 8,
-       .data   = acorndata_8x8,
+       .data   = acorndata_8x8.data,
 #ifdef CONFIG_ARCH_ACORN
        .pref   = 20,
 #else
index 838caa1..1449876 100644 (file)
@@ -43,8 +43,8 @@ __END__;
 
 #define FONTDATAMAX 1536
 
-static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
-
+static struct font_data fontdata_mini_4x6 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /*{*/
                /*   Char 0: ' '  */
        0xee,   /*=  [*** ]       */
@@ -2145,14 +2145,14 @@ static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
        0xee,   /*=   [*** ]        */
        0x00,   /*=   [    ]        */
        /*}*/
-};
+} };
 
 const struct font_desc font_mini_4x6 = {
        .idx    = MINI4x6_IDX,
        .name   = "MINI4x6",
        .width  = 4,
        .height = 6,
-       .data   = fontdata_mini_4x6,
+       .data   = fontdata_mini_4x6.data,
        .pref   = 3,
 };
 
index b15d3c3..32d6555 100644 (file)
@@ -14,8 +14,8 @@
 
 #define FONTDATAMAX 2048
 
-static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
-
+static struct font_data fontdata_pearl8x8 = {
+   { 0, 0, FONTDATAMAX, 0 }, {
    /* 0 0x00 '^@' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2575,14 +2575,13 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
-
-};
+} };
 
 const struct font_desc font_pearl_8x8 = {
        .idx    = PEARL8x8_IDX,
        .name   = "PEARL8x8",
        .width  = 8,
        .height = 8,
-       .data   = fontdata_pearl8x8,
+       .data   = fontdata_pearl8x8.data,
        .pref   = 2,
 };
index 955d6ee..641a6b4 100644 (file)
@@ -3,8 +3,8 @@
 
 #define FONTDATAMAX 11264
 
-static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
-
+static struct font_data fontdata_sun12x22 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        /* 0 0x00 '^@' */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
@@ -6148,8 +6148,7 @@ static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
        0x00, 0x00, /* 000000000000 */
-
-};
+} };
 
 
 const struct font_desc font_sun_12x22 = {
@@ -6157,7 +6156,7 @@ const struct font_desc font_sun_12x22 = {
        .name   = "SUN12x22",
        .width  = 12,
        .height = 22,
-       .data   = fontdata_sun12x22,
+       .data   = fontdata_sun12x22.data,
 #ifdef __sparc__
        .pref   = 5,
 #else
index 03d71e5..193fe6d 100644 (file)
@@ -3,7 +3,8 @@
 
 #define FONTDATAMAX 4096
 
-static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
+static struct font_data fontdata_sun8x16 = {
+{ 0, 0, FONTDATAMAX, 0 }, {
 /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
@@ -260,14 +261,14 @@ static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
 /* */ 0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-};
+} };
 
 const struct font_desc font_sun_8x16 = {
        .idx    = SUN8x16_IDX,
        .name   = "SUN8x16",
        .width  = 8,
        .height = 16,
-       .data   = fontdata_sun8x16,
+       .data   = fontdata_sun8x16.data,
 #ifdef __sparc__
        .pref   = 10,
 #else
index 3f0cf1c..91b9c28 100644 (file)
@@ -4,8 +4,8 @@
 
 #define FONTDATAMAX 16384
 
-static const unsigned char fontdata_ter16x32[FONTDATAMAX] = {
-
+static struct font_data fontdata_ter16x32 = {
+       { 0, 0, FONTDATAMAX, 0 }, {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x7f, 0xfc,
        0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c, 0x70, 0x1c,
@@ -2054,8 +2054,7 @@ static const unsigned char fontdata_ter16x32[FONTDATAMAX] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 255 */
-
-};
+} };
 
 
 const struct font_desc font_ter_16x32 = {
@@ -2063,7 +2062,7 @@ const struct font_desc font_ter_16x32 = {
        .name   = "TER16x32",
        .width  = 16,
        .height = 32,
-       .data   = fontdata_ter16x32,
+       .data   = fontdata_ter16x32.data,
 #ifdef __sparc__
        .pref   = 5,
 #else
index 3afb939..ea53b30 100644 (file)
@@ -604,9 +604,6 @@ static void __kobject_del(struct kobject *kobj)
        struct kernfs_node *sd;
        const struct kobj_type *ktype;
 
-       if (!kobj)
-               return;
-
        sd = kobj->sd;
        ktype = get_ktype(kobj);
 
@@ -637,8 +634,12 @@ static void __kobject_del(struct kobject *kobj)
  */
 void kobject_del(struct kobject *kobj)
 {
-       struct kobject *parent = kobj->parent;
+       struct kobject *parent;
+
+       if (!kobj)
+               return;
 
+       parent = kobj->parent;
        __kobject_del(kobj);
        kobject_put(parent);
 }
index 77c85b5..be5cfa5 100644 (file)
@@ -2,6 +2,7 @@
 /* identifiers for device / performance-differentiated memory regions */
 #include <linux/idr.h>
 #include <linux/types.h>
+#include <linux/memregion.h>
 
 static DEFINE_IDA(memregion_ids);
 
index 9323453..dfb9981 100644 (file)
@@ -49,7 +49,7 @@ static inline void prandom_state_selftest(void)
 }
 #endif
 
-DEFINE_PER_CPU(struct rnd_state, net_rand_state);
+DEFINE_PER_CPU(struct rnd_state, net_rand_state)  __latent_entropy;
 
 /**
  *     prandom_u32_state - seeded pseudo-random number generator.
index 6012c38..4288e01 100644 (file)
@@ -272,6 +272,30 @@ ssize_t strscpy_pad(char *dest, const char *src, size_t count)
 }
 EXPORT_SYMBOL(strscpy_pad);
 
+/**
+ * stpcpy - copy a string from src to dest returning a pointer to the new end
+ *          of dest, including src's %NUL-terminator. May overrun dest.
+ * @dest: pointer to end of string being copied into. Must be large enough
+ *        to receive copy.
+ * @src: pointer to the beginning of string being copied from. Must not overlap
+ *       dest.
+ *
+ * stpcpy differs from strcpy in a key way: the return value is a pointer
+ * to the new %NUL-terminating character in @dest. (For strcpy, the return
+ * value is a pointer to the start of @dest). This interface is considered
+ * unsafe as it doesn't perform bounds checking of the inputs. As such it's
+ * not recommended for usage. Instead, its definition is provided in case
+ * the compiler lowers other libcalls to stpcpy.
+ */
+char *stpcpy(char *__restrict__ dest, const char *__restrict__ src);
+char *stpcpy(char *__restrict__ dest, const char *__restrict__ src)
+{
+       while ((*dest++ = *src++) != '\0')
+               /* nothing */;
+       return --dest;
+}
+EXPORT_SYMBOL(stpcpy);
+
 #ifndef __HAVE_ARCH_STRCAT
 /**
  * strcat - Append one %NUL-terminated string to another
index 9fee2b9..06c9550 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/vmalloc.h>
 #include <linux/efi_embedded_fw.h>
 
+MODULE_IMPORT_NS(TEST_FIRMWARE);
+
 #define TEST_FIRMWARE_NAME     "test-firmware.bin"
 #define TEST_FIRMWARE_NUM_REQS 4
 #define TEST_FIRMWARE_BUF_SIZE SZ_1K
@@ -489,6 +491,9 @@ out:
 static DEVICE_ATTR_WO(trigger_request);
 
 #ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
+extern struct list_head efi_embedded_fw_list;
+extern bool efi_embedded_fw_checked;
+
 static ssize_t trigger_request_platform_store(struct device *dev,
                                              struct device_attribute *attr,
                                              const char *buf, size_t count)
@@ -501,6 +506,7 @@ static ssize_t trigger_request_platform_store(struct device *dev,
        };
        struct efi_embedded_fw efi_embedded_fw;
        const struct firmware *firmware = NULL;
+       bool saved_efi_embedded_fw_checked;
        char *name;
        int rc;
 
@@ -513,6 +519,8 @@ static ssize_t trigger_request_platform_store(struct device *dev,
        efi_embedded_fw.data = (void *)test_data;
        efi_embedded_fw.length = sizeof(test_data);
        list_add(&efi_embedded_fw.list, &efi_embedded_fw_list);
+       saved_efi_embedded_fw_checked = efi_embedded_fw_checked;
+       efi_embedded_fw_checked = true;
 
        pr_info("loading '%s'\n", name);
        rc = firmware_request_platform(&firmware, name, dev);
@@ -530,6 +538,7 @@ static ssize_t trigger_request_platform_store(struct device *dev,
        rc = count;
 
 out:
+       efi_embedded_fw_checked = saved_efi_embedded_fw_checked;
        release_firmware(firmware);
        list_del(&efi_embedded_fw.list);
        kfree(name);
index c5a6fef..76c607e 100644 (file)
@@ -434,7 +434,7 @@ static int __init test_rhltable(unsigned int entries)
                } else {
                        if (WARN(err != -ENOENT, "removed non-existent element, error %d not %d",
                                 err, -ENOENT))
-                       continue;
+                               continue;
                }
        }
 
index 1aaea26..99c49ee 100644 (file)
@@ -988,9 +988,43 @@ void __init pagecache_init(void)
        page_writeback_init();
 }
 
+/*
+ * The page wait code treats the "wait->flags" somewhat unusually, because
+ * we have multiple different kinds of waits, not just the usual "exclusive"
+ * one.
+ *
+ * We have:
+ *
+ *  (a) no special bits set:
+ *
+ *     We're just waiting for the bit to be released, and when a waker
+ *     calls the wakeup function, we set WQ_FLAG_WOKEN and wake it up,
+ *     and remove it from the wait queue.
+ *
+ *     Simple and straightforward.
+ *
+ *  (b) WQ_FLAG_EXCLUSIVE:
+ *
+ *     The waiter is waiting to get the lock, and only one waiter should
+ *     be woken up to avoid any thundering herd behavior. We'll set the
+ *     WQ_FLAG_WOKEN bit, wake it up, and remove it from the wait queue.
+ *
+ *     This is the traditional exclusive wait.
+ *
+ *  (c) WQ_FLAG_EXCLUSIVE | WQ_FLAG_CUSTOM:
+ *
+ *     The waiter is waiting to get the bit, and additionally wants the
+ *     lock to be transferred to it for fair lock behavior. If the lock
+ *     cannot be taken, we stop walking the wait queue without waking
+ *     the waiter.
+ *
+ *     This is the "fair lock handoff" case, and in addition to setting
+ *     WQ_FLAG_WOKEN, we set WQ_FLAG_DONE to let the waiter easily see
+ *     that it now has the lock.
+ */
 static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync, void *arg)
 {
-       int ret;
+       unsigned int flags;
        struct wait_page_key *key = arg;
        struct wait_page_queue *wait_page
                = container_of(wait, struct wait_page_queue, wait);
@@ -999,35 +1033,44 @@ static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync,
                return 0;
 
        /*
-        * If it's an exclusive wait, we get the bit for it, and
-        * stop walking if we can't.
-        *
-        * If it's a non-exclusive wait, then the fact that this
-        * wake function was called means that the bit already
-        * was cleared, and we don't care if somebody then
-        * re-took it.
+        * If it's a lock handoff wait, we get the bit for it, and
+        * stop walking (and do not wake it up) if we can't.
         */
-       ret = 0;
-       if (wait->flags & WQ_FLAG_EXCLUSIVE) {
-               if (test_and_set_bit(key->bit_nr, &key->page->flags))
+       flags = wait->flags;
+       if (flags & WQ_FLAG_EXCLUSIVE) {
+               if (test_bit(key->bit_nr, &key->page->flags))
                        return -1;
-               ret = 1;
+               if (flags & WQ_FLAG_CUSTOM) {
+                       if (test_and_set_bit(key->bit_nr, &key->page->flags))
+                               return -1;
+                       flags |= WQ_FLAG_DONE;
+               }
        }
-       wait->flags |= WQ_FLAG_WOKEN;
 
+       /*
+        * We are holding the wait-queue lock, but the waiter that
+        * is waiting for this will be checking the flags without
+        * any locking.
+        *
+        * So update the flags atomically, and wake up the waiter
+        * afterwards to avoid any races. This store-release pairs
+        * with the load-acquire in wait_on_page_bit_common().
+        */
+       smp_store_release(&wait->flags, flags | WQ_FLAG_WOKEN);
        wake_up_state(wait->private, mode);
 
        /*
         * Ok, we have successfully done what we're waiting for,
         * and we can unconditionally remove the wait entry.
         *
-        * Note that this has to be the absolute last thing we do,
-        * since after list_del_init(&wait->entry) the wait entry
+        * Note that this pairs with the "finish_wait()" in the
+        * waiter, and has to be the absolute last thing we do.
+        * After this list_del_init(&wait->entry) the wait entry
         * might be de-allocated and the process might even have
         * exited.
         */
        list_del_init_careful(&wait->entry);
-       return ret;
+       return (flags & WQ_FLAG_EXCLUSIVE) != 0;
 }
 
 static void wake_up_page_bit(struct page *page, int bit_nr)
@@ -1107,8 +1150,8 @@ enum behavior {
 };
 
 /*
- * Attempt to check (or get) the page bit, and mark the
- * waiter woken if successful.
+ * Attempt to check (or get) the page bit, and mark us done
+ * if successful.
  */
 static inline bool trylock_page_bit_common(struct page *page, int bit_nr,
                                        struct wait_queue_entry *wait)
@@ -1119,13 +1162,17 @@ static inline bool trylock_page_bit_common(struct page *page, int bit_nr,
        } else if (test_bit(bit_nr, &page->flags))
                return false;
 
-       wait->flags |= WQ_FLAG_WOKEN;
+       wait->flags |= WQ_FLAG_WOKEN | WQ_FLAG_DONE;
        return true;
 }
 
+/* How many times do we accept lock stealing from under a waiter? */
+int sysctl_page_lock_unfairness = 5;
+
 static inline int wait_on_page_bit_common(wait_queue_head_t *q,
        struct page *page, int bit_nr, int state, enum behavior behavior)
 {
+       int unfairness = sysctl_page_lock_unfairness;
        struct wait_page_queue wait_page;
        wait_queue_entry_t *wait = &wait_page.wait;
        bool thrashing = false;
@@ -1143,11 +1190,18 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
        }
 
        init_wait(wait);
-       wait->flags = behavior == EXCLUSIVE ? WQ_FLAG_EXCLUSIVE : 0;
        wait->func = wake_page_function;
        wait_page.page = page;
        wait_page.bit_nr = bit_nr;
 
+repeat:
+       wait->flags = 0;
+       if (behavior == EXCLUSIVE) {
+               wait->flags = WQ_FLAG_EXCLUSIVE;
+               if (--unfairness < 0)
+                       wait->flags |= WQ_FLAG_CUSTOM;
+       }
+
        /*
         * Do one last check whether we can get the
         * page bit synchronously.
@@ -1170,27 +1224,63 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
 
        /*
         * From now on, all the logic will be based on
-        * the WQ_FLAG_WOKEN flag, and the and the page
-        * bit testing (and setting) will be - or has
-        * already been - done by the wake function.
+        * the WQ_FLAG_WOKEN and WQ_FLAG_DONE flag, to
+        * see whether the page bit testing has already
+        * been done by the wake function.
         *
         * We can drop our reference to the page.
         */
        if (behavior == DROP)
                put_page(page);
 
+       /*
+        * Note that until the "finish_wait()", or until
+        * we see the WQ_FLAG_WOKEN flag, we need to
+        * be very careful with the 'wait->flags', because
+        * we may race with a waker that sets them.
+        */
        for (;;) {
+               unsigned int flags;
+
                set_current_state(state);
 
-               if (signal_pending_state(state, current))
+               /* Loop until we've been woken or interrupted */
+               flags = smp_load_acquire(&wait->flags);
+               if (!(flags & WQ_FLAG_WOKEN)) {
+                       if (signal_pending_state(state, current))
+                               break;
+
+                       io_schedule();
+                       continue;
+               }
+
+               /* If we were non-exclusive, we're done */
+               if (behavior != EXCLUSIVE)
                        break;
 
-               if (wait->flags & WQ_FLAG_WOKEN)
+               /* If the waker got the lock for us, we're done */
+               if (flags & WQ_FLAG_DONE)
                        break;
 
-               io_schedule();
+               /*
+                * Otherwise, if we're getting the lock, we need to
+                * try to get it ourselves.
+                *
+                * And if that fails, we'll have to retry this all.
+                */
+               if (unlikely(test_and_set_bit(bit_nr, &page->flags)))
+                       goto repeat;
+
+               wait->flags |= WQ_FLAG_DONE;
+               break;
        }
 
+       /*
+        * If a signal happened, this 'finish_wait()' may remove the last
+        * waiter from the wait-queues, but the PageWaiters bit will remain
+        * set. That's ok. The next wakeup will take care of it, and trying
+        * to do it here would be difficult and prone to races.
+        */
        finish_wait(q, wait);
 
        if (thrashing) {
@@ -1200,12 +1290,20 @@ static inline int wait_on_page_bit_common(wait_queue_head_t *q,
        }
 
        /*
-        * A signal could leave PageWaiters set. Clearing it here if
-        * !waitqueue_active would be possible (by open-coding finish_wait),
-        * but still fail to catch it in the case of wait hash collision. We
-        * already can fail to clear wait hash collision cases, so don't
-        * bother with signals either.
+        * NOTE! The wait->flags weren't stable until we've done the
+        * 'finish_wait()', and we could have exited the loop above due
+        * to a signal, and had a wakeup event happen after the signal
+        * test but before the 'finish_wait()'.
+        *
+        * So only after the finish_wait() can we reliably determine
+        * if we got woken up or not, so we can now figure out the final
+        * return value based on that state without races.
+        *
+        * Also note that WQ_FLAG_WOKEN is sufficient for a non-exclusive
+        * waiter, but an exclusive one requires WQ_FLAG_DONE.
         */
+       if (behavior == EXCLUSIVE)
+               return wait->flags & WQ_FLAG_DONE ? 0 : -EINTR;
 
        return wait->flags & WQ_FLAG_WOKEN ? 0 : -EINTR;
 }
@@ -2267,7 +2365,11 @@ readpage:
                }
 
                if (!PageUptodate(page)) {
-                       error = lock_page_killable(page);
+                       if (iocb->ki_flags & IOCB_WAITQ)
+                               error = lock_page_async(page, iocb->ki_waitq);
+                       else
+                               error = lock_page_killable(page);
+
                        if (unlikely(error))
                                goto readpage_error;
                        if (!PageUptodate(page)) {
index e5739a1..e869c63 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1255,6 +1255,9 @@ static __always_inline long __get_user_pages_locked(struct mm_struct *mm,
                BUG_ON(*locked != 1);
        }
 
+       if (flags & FOLL_PIN)
+               atomic_set(&mm->has_pinned, 1);
+
        /*
         * FOLL_PIN and FOLL_GET are mutually exclusive. Traditional behavior
         * is to set FOLL_GET if the caller wants pages[] filled in (but has
@@ -2485,13 +2488,13 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr,
        return 1;
 }
 
-static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
+static int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr, unsigned long end,
                unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        pmd_t *pmdp;
 
-       pmdp = pmd_offset(&pud, addr);
+       pmdp = pmd_offset_lockless(pudp, pud, addr);
        do {
                pmd_t pmd = READ_ONCE(*pmdp);
 
@@ -2528,13 +2531,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
        return 1;
 }
 
-static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end,
+static int gup_pud_range(p4d_t *p4dp, p4d_t p4d, unsigned long addr, unsigned long end,
                         unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        pud_t *pudp;
 
-       pudp = pud_offset(&p4d, addr);
+       pudp = pud_offset_lockless(p4dp, p4d, addr);
        do {
                pud_t pud = READ_ONCE(*pudp);
 
@@ -2549,20 +2552,20 @@ static int gup_pud_range(p4d_t p4d, unsigned long addr, unsigned long end,
                        if (!gup_huge_pd(__hugepd(pud_val(pud)), addr,
                                         PUD_SHIFT, next, flags, pages, nr))
                                return 0;
-               } else if (!gup_pmd_range(pud, addr, next, flags, pages, nr))
+               } else if (!gup_pmd_range(pudp, pud, addr, next, flags, pages, nr))
                        return 0;
        } while (pudp++, addr = next, addr != end);
 
        return 1;
 }
 
-static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end,
+static int gup_p4d_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr, unsigned long end,
                         unsigned int flags, struct page **pages, int *nr)
 {
        unsigned long next;
        p4d_t *p4dp;
 
-       p4dp = p4d_offset(&pgd, addr);
+       p4dp = p4d_offset_lockless(pgdp, pgd, addr);
        do {
                p4d_t p4d = READ_ONCE(*p4dp);
 
@@ -2574,7 +2577,7 @@ static int gup_p4d_range(pgd_t pgd, unsigned long addr, unsigned long end,
                        if (!gup_huge_pd(__hugepd(p4d_val(p4d)), addr,
                                         P4D_SHIFT, next, flags, pages, nr))
                                return 0;
-               } else if (!gup_pud_range(p4d, addr, next, flags, pages, nr))
+               } else if (!gup_pud_range(p4dp, p4d, addr, next, flags, pages, nr))
                        return 0;
        } while (p4dp++, addr = next, addr != end);
 
@@ -2602,7 +2605,7 @@ static void gup_pgd_range(unsigned long addr, unsigned long end,
                        if (!gup_huge_pd(__hugepd(pgd_val(pgd)), addr,
                                         PGDIR_SHIFT, next, flags, pages, nr))
                                return;
-               } else if (!gup_p4d_range(pgd, addr, next, flags, pages, nr))
+               } else if (!gup_p4d_range(pgdp, pgd, addr, next, flags, pages, nr))
                        return;
        } while (pgdp++, addr = next, addr != end);
 }
@@ -2660,6 +2663,9 @@ static int internal_get_user_pages_fast(unsigned long start, int nr_pages,
                                       FOLL_FAST_ONLY)))
                return -EINVAL;
 
+       if (gup_flags & FOLL_PIN)
+               atomic_set(&current->mm->has_pinned, 1);
+
        if (!(gup_flags & FOLL_FAST_ONLY))
                might_lock_read(&current->mm->mmap_lock);
 
index 7ff29cc..da39777 100644 (file)
@@ -1074,6 +1074,24 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 
        src_page = pmd_page(pmd);
        VM_BUG_ON_PAGE(!PageHead(src_page), src_page);
+
+       /*
+        * If this page is a potentially pinned page, split and retry the fault
+        * with smaller page size.  Normally this should not happen because the
+        * userspace should use MADV_DONTFORK upon pinned regions.  This is a
+        * best effort that the pinned pages won't be replaced by another
+        * random page during the coming copy-on-write.
+        */
+       if (unlikely(is_cow_mapping(vma->vm_flags) &&
+                    atomic_read(&src_mm->has_pinned) &&
+                    page_maybe_dma_pinned(src_page))) {
+               pte_free(dst_mm, pgtable);
+               spin_unlock(src_ptl);
+               spin_unlock(dst_ptl);
+               __split_huge_pmd(vma, src_pmd, addr, false, NULL);
+               return -EAGAIN;
+       }
+
        get_page(src_page);
        page_dup_rmap(src_page, true);
        add_mm_counter(dst_mm, MM_ANONPAGES, HPAGE_PMD_NR);
@@ -1177,6 +1195,16 @@ int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                /* No huge zero pud yet */
        }
 
+       /* Please refer to comments in copy_huge_pmd() */
+       if (unlikely(is_cow_mapping(vma->vm_flags) &&
+                    atomic_read(&src_mm->has_pinned) &&
+                    page_maybe_dma_pinned(pud_page(pud)))) {
+               spin_unlock(src_ptl);
+               spin_unlock(dst_ptl);
+               __split_huge_pud(vma, src_pud, addr);
+               return -EAGAIN;
+       }
+
        pudp_set_wrprotect(src_mm, addr, src_pud);
        pud = pud_mkold(pud_wrprotect(pud));
        set_pud_at(dst_mm, addr, dst_pud, pud);
@@ -2022,7 +2050,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
                put_page(page);
                add_mm_counter(mm, mm_counter_file(page), -HPAGE_PMD_NR);
                return;
-       } else if (is_huge_zero_pmd(*pmd)) {
+       } else if (pmd_trans_huge(*pmd) && is_huge_zero_pmd(*pmd)) {
                /*
                 * FIXME: Do we want to invalidate secondary mmu by calling
                 * mmu_notifier_invalidate_range() see comments below inside
@@ -2116,30 +2144,34 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
                pte = pte_offset_map(&_pmd, addr);
                BUG_ON(!pte_none(*pte));
                set_pte_at(mm, addr, pte, entry);
-               atomic_inc(&page[i]._mapcount);
-               pte_unmap(pte);
-       }
-
-       /*
-        * Set PG_double_map before dropping compound_mapcount to avoid
-        * false-negative page_mapped().
-        */
-       if (compound_mapcount(page) > 1 && !TestSetPageDoubleMap(page)) {
-               for (i = 0; i < HPAGE_PMD_NR; i++)
+               if (!pmd_migration)
                        atomic_inc(&page[i]._mapcount);
+               pte_unmap(pte);
        }
 
-       lock_page_memcg(page);
-       if (atomic_add_negative(-1, compound_mapcount_ptr(page))) {
-               /* Last compound_mapcount is gone. */
-               __dec_lruvec_page_state(page, NR_ANON_THPS);
-               if (TestClearPageDoubleMap(page)) {
-                       /* No need in mapcount reference anymore */
+       if (!pmd_migration) {
+               /*
+                * Set PG_double_map before dropping compound_mapcount to avoid
+                * false-negative page_mapped().
+                */
+               if (compound_mapcount(page) > 1 &&
+                   !TestSetPageDoubleMap(page)) {
                        for (i = 0; i < HPAGE_PMD_NR; i++)
-                               atomic_dec(&page[i]._mapcount);
+                               atomic_inc(&page[i]._mapcount);
+               }
+
+               lock_page_memcg(page);
+               if (atomic_add_negative(-1, compound_mapcount_ptr(page))) {
+                       /* Last compound_mapcount is gone. */
+                       __dec_lruvec_page_state(page, NR_ANON_THPS);
+                       if (TestClearPageDoubleMap(page)) {
+                               /* No need in mapcount reference anymore */
+                               for (i = 0; i < HPAGE_PMD_NR; i++)
+                                       atomic_dec(&page[i]._mapcount);
+                       }
                }
+               unlock_page_memcg(page);
        }
-       unlock_page_memcg(page);
 
        smp_wmb(); /* make pte visible before pmd */
        pmd_populate(mm, pmd, pgtable);
index 235f55d..9afccc3 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2586,6 +2586,10 @@ struct page *ksm_might_need_to_copy(struct page *page,
                return page;            /* let do_swap_page report the error */
 
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
+       if (new_page && mem_cgroup_charge(new_page, vma->vm_mm, GFP_KERNEL)) {
+               put_page(new_page);
+               new_page = NULL;
+       }
        if (new_page) {
                copy_user_highpage(new_page, page, address, vma);
 
index d4aa5f7..0e0d610 100644 (file)
@@ -381,9 +381,9 @@ huge_unlock:
                return 0;
        }
 
+regular_page:
        if (pmd_trans_unstable(pmd))
                return 0;
-regular_page:
 #endif
        tlb_change_page_size(tlb, PAGE_SIZE);
        orig_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
index cfa6cba..6877c76 100644 (file)
@@ -1538,9 +1538,9 @@ static char *memory_stat_format(struct mem_cgroup *memcg)
                       memcg_page_state(memcg, WORKINGSET_ACTIVATE_ANON));
        seq_buf_printf(&s, "workingset_activate_file %lu\n",
                       memcg_page_state(memcg, WORKINGSET_ACTIVATE_FILE));
-       seq_buf_printf(&s, "workingset_restore %lu\n",
+       seq_buf_printf(&s, "workingset_restore_anon %lu\n",
                       memcg_page_state(memcg, WORKINGSET_RESTORE_ANON));
-       seq_buf_printf(&s, "workingset_restore %lu\n",
+       seq_buf_printf(&s, "workingset_restore_file %lu\n",
                       memcg_page_state(memcg, WORKINGSET_RESTORE_FILE));
        seq_buf_printf(&s, "workingset_nodereclaim %lu\n",
                       memcg_page_state(memcg, WORKINGSET_NODERECLAIM));
index 469af37..eeae590 100644 (file)
@@ -695,84 +695,185 @@ out:
  * covered by this vma.
  */
 
-static inline unsigned long
-copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+static unsigned long
+copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma,
                unsigned long addr, int *rss)
 {
        unsigned long vm_flags = vma->vm_flags;
        pte_t pte = *src_pte;
        struct page *page;
+       swp_entry_t entry = pte_to_swp_entry(pte);
+
+       if (likely(!non_swap_entry(entry))) {
+               if (swap_duplicate(entry) < 0)
+                       return entry.val;
+
+               /* make sure dst_mm is on swapoff's mmlist. */
+               if (unlikely(list_empty(&dst_mm->mmlist))) {
+                       spin_lock(&mmlist_lock);
+                       if (list_empty(&dst_mm->mmlist))
+                               list_add(&dst_mm->mmlist,
+                                               &src_mm->mmlist);
+                       spin_unlock(&mmlist_lock);
+               }
+               rss[MM_SWAPENTS]++;
+       } else if (is_migration_entry(entry)) {
+               page = migration_entry_to_page(entry);
 
-       /* pte contains position in swap or file, so copy. */
-       if (unlikely(!pte_present(pte))) {
-               swp_entry_t entry = pte_to_swp_entry(pte);
-
-               if (likely(!non_swap_entry(entry))) {
-                       if (swap_duplicate(entry) < 0)
-                               return entry.val;
-
-                       /* make sure dst_mm is on swapoff's mmlist. */
-                       if (unlikely(list_empty(&dst_mm->mmlist))) {
-                               spin_lock(&mmlist_lock);
-                               if (list_empty(&dst_mm->mmlist))
-                                       list_add(&dst_mm->mmlist,
-                                                       &src_mm->mmlist);
-                               spin_unlock(&mmlist_lock);
-                       }
-                       rss[MM_SWAPENTS]++;
-               } else if (is_migration_entry(entry)) {
-                       page = migration_entry_to_page(entry);
-
-                       rss[mm_counter(page)]++;
-
-                       if (is_write_migration_entry(entry) &&
-                                       is_cow_mapping(vm_flags)) {
-                               /*
-                                * COW mappings require pages in both
-                                * parent and child to be set to read.
-                                */
-                               make_migration_entry_read(&entry);
-                               pte = swp_entry_to_pte(entry);
-                               if (pte_swp_soft_dirty(*src_pte))
-                                       pte = pte_swp_mksoft_dirty(pte);
-                               if (pte_swp_uffd_wp(*src_pte))
-                                       pte = pte_swp_mkuffd_wp(pte);
-                               set_pte_at(src_mm, addr, src_pte, pte);
-                       }
-               } else if (is_device_private_entry(entry)) {
-                       page = device_private_entry_to_page(entry);
+               rss[mm_counter(page)]++;
 
+               if (is_write_migration_entry(entry) &&
+                               is_cow_mapping(vm_flags)) {
                        /*
-                        * Update rss count even for unaddressable pages, as
-                        * they should treated just like normal pages in this
-                        * respect.
-                        *
-                        * We will likely want to have some new rss counters
-                        * for unaddressable pages, at some point. But for now
-                        * keep things as they are.
+                        * COW mappings require pages in both
+                        * parent and child to be set to read.
                         */
-                       get_page(page);
-                       rss[mm_counter(page)]++;
-                       page_dup_rmap(page, false);
+                       make_migration_entry_read(&entry);
+                       pte = swp_entry_to_pte(entry);
+                       if (pte_swp_soft_dirty(*src_pte))
+                               pte = pte_swp_mksoft_dirty(pte);
+                       if (pte_swp_uffd_wp(*src_pte))
+                               pte = pte_swp_mkuffd_wp(pte);
+                       set_pte_at(src_mm, addr, src_pte, pte);
+               }
+       } else if (is_device_private_entry(entry)) {
+               page = device_private_entry_to_page(entry);
 
-                       /*
-                        * We do not preserve soft-dirty information, because so
-                        * far, checkpoint/restore is the only feature that
-                        * requires that. And checkpoint/restore does not work
-                        * when a device driver is involved (you cannot easily
-                        * save and restore device driver state).
-                        */
-                       if (is_write_device_private_entry(entry) &&
-                           is_cow_mapping(vm_flags)) {
-                               make_device_private_entry_read(&entry);
-                               pte = swp_entry_to_pte(entry);
-                               if (pte_swp_uffd_wp(*src_pte))
-                                       pte = pte_swp_mkuffd_wp(pte);
-                               set_pte_at(src_mm, addr, src_pte, pte);
-                       }
+               /*
+                * Update rss count even for unaddressable pages, as
+                * they should treated just like normal pages in this
+                * respect.
+                *
+                * We will likely want to have some new rss counters
+                * for unaddressable pages, at some point. But for now
+                * keep things as they are.
+                */
+               get_page(page);
+               rss[mm_counter(page)]++;
+               page_dup_rmap(page, false);
+
+               /*
+                * We do not preserve soft-dirty information, because so
+                * far, checkpoint/restore is the only feature that
+                * requires that. And checkpoint/restore does not work
+                * when a device driver is involved (you cannot easily
+                * save and restore device driver state).
+                */
+               if (is_write_device_private_entry(entry) &&
+                   is_cow_mapping(vm_flags)) {
+                       make_device_private_entry_read(&entry);
+                       pte = swp_entry_to_pte(entry);
+                       if (pte_swp_uffd_wp(*src_pte))
+                               pte = pte_swp_mkuffd_wp(pte);
+                       set_pte_at(src_mm, addr, src_pte, pte);
                }
-               goto out_set_pte;
+       }
+       set_pte_at(dst_mm, addr, dst_pte, pte);
+       return 0;
+}
+
+/*
+ * Copy a present and normal page if necessary.
+ *
+ * NOTE! The usual case is that this doesn't need to do
+ * anything, and can just return a positive value. That
+ * will let the caller know that it can just increase
+ * the page refcount and re-use the pte the traditional
+ * way.
+ *
+ * But _if_ we need to copy it because it needs to be
+ * pinned in the parent (and the child should get its own
+ * copy rather than just a reference to the same page),
+ * we'll do that here and return zero to let the caller
+ * know we're done.
+ *
+ * And if we need a pre-allocated page but don't yet have
+ * one, return a negative error to let the preallocation
+ * code know so that it can do so outside the page table
+ * lock.
+ */
+static inline int
+copy_present_page(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+               pte_t *dst_pte, pte_t *src_pte,
+               struct vm_area_struct *vma, struct vm_area_struct *new,
+               unsigned long addr, int *rss, struct page **prealloc,
+               pte_t pte, struct page *page)
+{
+       struct page *new_page;
+
+       if (!is_cow_mapping(vma->vm_flags))
+               return 1;
+
+       /*
+        * What we want to do is to check whether this page may
+        * have been pinned by the parent process.  If so,
+        * instead of wrprotect the pte on both sides, we copy
+        * the page immediately so that we'll always guarantee
+        * the pinned page won't be randomly replaced in the
+        * future.
+        *
+        * The page pinning checks are just "has this mm ever
+        * seen pinning", along with the (inexact) check of
+        * the page count. That might give false positives for
+        * for pinning, but it will work correctly.
+        */
+       if (likely(!atomic_read(&src_mm->has_pinned)))
+               return 1;
+       if (likely(!page_maybe_dma_pinned(page)))
+               return 1;
+
+       new_page = *prealloc;
+       if (!new_page)
+               return -EAGAIN;
+
+       /*
+        * We have a prealloc page, all good!  Take it
+        * over and copy the page & arm it.
+        */
+       *prealloc = NULL;
+       copy_user_highpage(new_page, page, addr, vma);
+       __SetPageUptodate(new_page);
+       page_add_new_anon_rmap(new_page, new, addr, false);
+       lru_cache_add_inactive_or_unevictable(new_page, new);
+       rss[mm_counter(new_page)]++;
+
+       /* All done, just insert the new page copy in the child */
+       pte = mk_pte(new_page, new->vm_page_prot);
+       pte = maybe_mkwrite(pte_mkdirty(pte), new);
+       set_pte_at(dst_mm, addr, dst_pte, pte);
+       return 0;
+}
+
+/*
+ * Copy one pte.  Returns 0 if succeeded, or -EAGAIN if one preallocated page
+ * is required to copy this pte.
+ */
+static inline int
+copy_present_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+               pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma,
+               struct vm_area_struct *new,
+               unsigned long addr, int *rss, struct page **prealloc)
+{
+       unsigned long vm_flags = vma->vm_flags;
+       pte_t pte = *src_pte;
+       struct page *page;
+
+       page = vm_normal_page(vma, addr, pte);
+       if (page) {
+               int retval;
+
+               retval = copy_present_page(dst_mm, src_mm,
+                       dst_pte, src_pte,
+                       vma, new,
+                       addr, rss, prealloc,
+                       pte, page);
+               if (retval <= 0)
+                       return retval;
+
+               get_page(page);
+               page_dup_rmap(page, false);
+               rss[mm_counter(page)]++;
        }
 
        /*
@@ -800,35 +901,51 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        if (!(vm_flags & VM_UFFD_WP))
                pte = pte_clear_uffd_wp(pte);
 
-       page = vm_normal_page(vma, addr, pte);
-       if (page) {
-               get_page(page);
-               page_dup_rmap(page, false);
-               rss[mm_counter(page)]++;
-       }
-
-out_set_pte:
        set_pte_at(dst_mm, addr, dst_pte, pte);
        return 0;
 }
 
+static inline struct page *
+page_copy_prealloc(struct mm_struct *src_mm, struct vm_area_struct *vma,
+                  unsigned long addr)
+{
+       struct page *new_page;
+
+       new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, addr);
+       if (!new_page)
+               return NULL;
+
+       if (mem_cgroup_charge(new_page, src_mm, GFP_KERNEL)) {
+               put_page(new_page);
+               return NULL;
+       }
+       cgroup_throttle_swaprate(new_page, GFP_KERNEL);
+
+       return new_page;
+}
+
 static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                   pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma,
+                  struct vm_area_struct *new,
                   unsigned long addr, unsigned long end)
 {
        pte_t *orig_src_pte, *orig_dst_pte;
        pte_t *src_pte, *dst_pte;
        spinlock_t *src_ptl, *dst_ptl;
-       int progress = 0;
+       int progress, ret = 0;
        int rss[NR_MM_COUNTERS];
        swp_entry_t entry = (swp_entry_t){0};
+       struct page *prealloc = NULL;
 
 again:
+       progress = 0;
        init_rss_vec(rss);
 
        dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
-       if (!dst_pte)
-               return -ENOMEM;
+       if (!dst_pte) {
+               ret = -ENOMEM;
+               goto out;
+       }
        src_pte = pte_offset_map(src_pmd, addr);
        src_ptl = pte_lockptr(src_mm, src_pmd);
        spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
@@ -851,10 +968,34 @@ again:
                        progress++;
                        continue;
                }
-               entry.val = copy_one_pte(dst_mm, src_mm, dst_pte, src_pte,
+               if (unlikely(!pte_present(*src_pte))) {
+                       entry.val = copy_nonpresent_pte(dst_mm, src_mm,
+                                                       dst_pte, src_pte,
                                                        vma, addr, rss);
-               if (entry.val)
+                       if (entry.val)
+                               break;
+                       progress += 8;
+                       continue;
+               }
+               /* copy_present_pte() will clear `*prealloc' if consumed */
+               ret = copy_present_pte(dst_mm, src_mm, dst_pte, src_pte,
+                                      vma, new, addr, rss, &prealloc);
+               /*
+                * If we need a pre-allocated page for this pte, drop the
+                * locks, allocate, and try again.
+                */
+               if (unlikely(ret == -EAGAIN))
                        break;
+               if (unlikely(prealloc)) {
+                       /*
+                        * pre-alloc page cannot be reused by next time so as
+                        * to strictly follow mempolicy (e.g., alloc_page_vma()
+                        * will allocate page according to address).  This
+                        * could only happen if one pinned pte changed.
+                        */
+                       put_page(prealloc);
+                       prealloc = NULL;
+               }
                progress += 8;
        } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
 
@@ -866,17 +1007,30 @@ again:
        cond_resched();
 
        if (entry.val) {
-               if (add_swap_count_continuation(entry, GFP_KERNEL) < 0)
+               if (add_swap_count_continuation(entry, GFP_KERNEL) < 0) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               entry.val = 0;
+       } else if (ret) {
+               WARN_ON_ONCE(ret != -EAGAIN);
+               prealloc = page_copy_prealloc(src_mm, vma, addr);
+               if (!prealloc)
                        return -ENOMEM;
-               progress = 0;
+               /* We've captured and resolved the error. Reset, try again. */
+               ret = 0;
        }
        if (addr != end)
                goto again;
-       return 0;
+out:
+       if (unlikely(prealloc))
+               put_page(prealloc);
+       return ret;
 }
 
 static inline int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                pud_t *dst_pud, pud_t *src_pud, struct vm_area_struct *vma,
+               struct vm_area_struct *new,
                unsigned long addr, unsigned long end)
 {
        pmd_t *src_pmd, *dst_pmd;
@@ -903,7 +1057,7 @@ static inline int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct *src
                if (pmd_none_or_clear_bad(src_pmd))
                        continue;
                if (copy_pte_range(dst_mm, src_mm, dst_pmd, src_pmd,
-                                               vma, addr, next))
+                                  vma, new, addr, next))
                        return -ENOMEM;
        } while (dst_pmd++, src_pmd++, addr = next, addr != end);
        return 0;
@@ -911,6 +1065,7 @@ static inline int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct *src
 
 static inline int copy_pud_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                p4d_t *dst_p4d, p4d_t *src_p4d, struct vm_area_struct *vma,
+               struct vm_area_struct *new,
                unsigned long addr, unsigned long end)
 {
        pud_t *src_pud, *dst_pud;
@@ -937,7 +1092,7 @@ static inline int copy_pud_range(struct mm_struct *dst_mm, struct mm_struct *src
                if (pud_none_or_clear_bad(src_pud))
                        continue;
                if (copy_pmd_range(dst_mm, src_mm, dst_pud, src_pud,
-                                               vma, addr, next))
+                                  vma, new, addr, next))
                        return -ENOMEM;
        } while (dst_pud++, src_pud++, addr = next, addr != end);
        return 0;
@@ -945,6 +1100,7 @@ static inline int copy_pud_range(struct mm_struct *dst_mm, struct mm_struct *src
 
 static inline int copy_p4d_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                pgd_t *dst_pgd, pgd_t *src_pgd, struct vm_area_struct *vma,
+               struct vm_area_struct *new,
                unsigned long addr, unsigned long end)
 {
        p4d_t *src_p4d, *dst_p4d;
@@ -959,14 +1115,14 @@ static inline int copy_p4d_range(struct mm_struct *dst_mm, struct mm_struct *src
                if (p4d_none_or_clear_bad(src_p4d))
                        continue;
                if (copy_pud_range(dst_mm, src_mm, dst_p4d, src_p4d,
-                                               vma, addr, next))
+                                  vma, new, addr, next))
                        return -ENOMEM;
        } while (dst_p4d++, src_p4d++, addr = next, addr != end);
        return 0;
 }
 
 int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
-               struct vm_area_struct *vma)
+                   struct vm_area_struct *vma, struct vm_area_struct *new)
 {
        pgd_t *src_pgd, *dst_pgd;
        unsigned long next;
@@ -1021,7 +1177,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                if (pgd_none_or_clear_bad(src_pgd))
                        continue;
                if (unlikely(copy_p4d_range(dst_mm, src_mm, dst_pgd, src_pgd,
-                                           vma, addr, next))) {
+                                           vma, new, addr, next))) {
                        ret = -ENOMEM;
                        break;
                }
@@ -2955,8 +3111,8 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
                 * page count reference, and the page is locked,
                 * it's dark out, and we're wearing sunglasses. Hit it.
                 */
-               wp_page_reuse(vmf);
                unlock_page(page);
+               wp_page_reuse(vmf);
                return VM_FAULT_WRITE;
        } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
                                        (VM_WRITE|VM_SHARED))) {
index e9d5ab5..ce3e73e 100644 (file)
@@ -729,7 +729,7 @@ void __ref move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
         * are reserved so nobody should be touching them so we should be safe
         */
        memmap_init_zone(nr_pages, nid, zone_idx(zone), start_pfn,
-                       MEMMAP_HOTPLUG, altmap);
+                        MEMINIT_HOTPLUG, altmap);
 
        set_zone_contiguous(zone);
 }
@@ -1080,7 +1080,8 @@ int __ref add_memory_resource(int nid, struct resource *res)
        }
 
        /* link memory sections under this node.*/
-       ret = link_mem_sections(nid, PFN_DOWN(start), PFN_UP(start + size - 1));
+       ret = link_mem_sections(nid, PFN_DOWN(start), PFN_UP(start + size - 1),
+                               MEMINIT_HOTPLUG);
        BUG_ON(ret);
 
        /* create new memmap entry */
@@ -1575,6 +1576,20 @@ static int __ref __offline_pages(unsigned long start_pfn,
                /* check again */
                ret = walk_system_ram_range(start_pfn, end_pfn - start_pfn,
                                            NULL, check_pages_isolated_cb);
+               /*
+                * per-cpu pages are drained in start_isolate_page_range, but if
+                * there are still pages that are not free, make sure that we
+                * drain again, because when we isolated range we might
+                * have raced with another thread that was adding pages to pcp
+                * list.
+                *
+                * Forward progress should be still guaranteed because
+                * pages on the pcp list can only belong to MOVABLE_ZONE
+                * because has_unmovable_pages explicitly checks for
+                * PageBuddy on freed pages on other zones.
+                */
+               if (ret)
+                       drain_all_pages(zone);
        } while (ret);
 
        /* Ok, all of our target is isolated.
index 941b893..04a98bb 100644 (file)
@@ -668,7 +668,8 @@ void migrate_page_states(struct page *newpage, struct page *page)
 
        copy_page_owner(page, newpage);
 
-       mem_cgroup_migrate(page, newpage);
+       if (!PageHuge(page))
+               mem_cgroup_migrate(page, newpage);
 }
 EXPORT_SYMBOL(migrate_page_states);
 
@@ -1445,7 +1446,7 @@ retry:
                         * Capture required information that might get lost
                         * during migration.
                         */
-                       is_thp = PageTransHuge(page);
+                       is_thp = PageTransHuge(page) && !PageHuge(page);
                        nr_subpages = thp_nr_pages(page);
                        cond_resched();
 
@@ -1471,7 +1472,7 @@ retry:
                                 * we encounter them after the rest of the list
                                 * is processed.
                                 */
-                               if (PageTransHuge(page) && !PageHuge(page)) {
+                               if (is_thp) {
                                        lock_page(page);
                                        rc = split_huge_page_to_list(page, from);
                                        unlock_page(page);
@@ -1480,8 +1481,7 @@ retry:
                                                nr_thp_split++;
                                                goto retry;
                                        }
-                               }
-                               if (is_thp) {
+
                                        nr_thp_failed++;
                                        nr_failed += nr_subpages;
                                        goto out;
index 93ca2bf..884b121 100644 (file)
@@ -58,11 +58,14 @@ EXPORT_SYMBOL(can_do_mlock);
  */
 void clear_page_mlock(struct page *page)
 {
+       int nr_pages;
+
        if (!TestClearPageMlocked(page))
                return;
 
-       mod_zone_page_state(page_zone(page), NR_MLOCK, -thp_nr_pages(page));
-       count_vm_event(UNEVICTABLE_PGCLEARED);
+       nr_pages = thp_nr_pages(page);
+       mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
+       count_vm_events(UNEVICTABLE_PGCLEARED, nr_pages);
        /*
         * The previous TestClearPageMlocked() corresponds to the smp_mb()
         * in __pagevec_lru_add_fn().
@@ -76,7 +79,7 @@ void clear_page_mlock(struct page *page)
                 * We lost the race. the page already moved to evictable list.
                 */
                if (PageUnevictable(page))
-                       count_vm_event(UNEVICTABLE_PGSTRANDED);
+                       count_vm_events(UNEVICTABLE_PGSTRANDED, nr_pages);
        }
 }
 
@@ -93,9 +96,10 @@ void mlock_vma_page(struct page *page)
        VM_BUG_ON_PAGE(PageCompound(page) && PageDoubleMap(page), page);
 
        if (!TestSetPageMlocked(page)) {
-               mod_zone_page_state(page_zone(page), NR_MLOCK,
-                                   thp_nr_pages(page));
-               count_vm_event(UNEVICTABLE_PGMLOCKED);
+               int nr_pages = thp_nr_pages(page);
+
+               mod_zone_page_state(page_zone(page), NR_MLOCK, nr_pages);
+               count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages);
                if (!isolate_lru_page(page))
                        putback_lru_page(page);
        }
@@ -138,7 +142,7 @@ static void __munlock_isolated_page(struct page *page)
 
        /* Did try_to_unlock() succeed or punt? */
        if (!PageMlocked(page))
-               count_vm_event(UNEVICTABLE_PGMUNLOCKED);
+               count_vm_events(UNEVICTABLE_PGMUNLOCKED, thp_nr_pages(page));
 
        putback_lru_page(page);
 }
@@ -154,10 +158,12 @@ static void __munlock_isolated_page(struct page *page)
  */
 static void __munlock_isolation_failed(struct page *page)
 {
+       int nr_pages = thp_nr_pages(page);
+
        if (PageUnevictable(page))
-               __count_vm_event(UNEVICTABLE_PGSTRANDED);
+               __count_vm_events(UNEVICTABLE_PGSTRANDED, nr_pages);
        else
-               __count_vm_event(UNEVICTABLE_PGMUNLOCKED);
+               __count_vm_events(UNEVICTABLE_PGMUNLOCKED, nr_pages);
 }
 
 /**
index fab5e97..6866533 100644 (file)
@@ -3367,9 +3367,16 @@ struct page *rmqueue(struct zone *preferred_zone,
        struct page *page;
 
        if (likely(order == 0)) {
-               page = rmqueue_pcplist(preferred_zone, zone, gfp_flags,
+               /*
+                * MIGRATE_MOVABLE pcplist could have the pages on CMA area and
+                * we need to skip it when CMA area isn't allowed.
+                */
+               if (!IS_ENABLED(CONFIG_CMA) || alloc_flags & ALLOC_CMA ||
+                               migratetype != MIGRATE_MOVABLE) {
+                       page = rmqueue_pcplist(preferred_zone, zone, gfp_flags,
                                        migratetype, alloc_flags);
-               goto out;
+                       goto out;
+               }
        }
 
        /*
@@ -3381,7 +3388,13 @@ struct page *rmqueue(struct zone *preferred_zone,
 
        do {
                page = NULL;
-               if (alloc_flags & ALLOC_HARDER) {
+               /*
+                * order-0 request can reach here when the pcplist is skipped
+                * due to non-CMA allocation context. HIGHATOMIC area is
+                * reserved for high-order atomic allocation, so order-0
+                * request should skip it.
+                */
+               if (order > 0 && alloc_flags & ALLOC_HARDER) {
                        page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);
                        if (page)
                                trace_mm_page_alloc_zone_locked(page, order, migratetype);
@@ -5975,7 +5988,7 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn)
  * done. Non-atomic initialization, single-pass.
  */
 void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
-               unsigned long start_pfn, enum memmap_context context,
+               unsigned long start_pfn, enum meminit_context context,
                struct vmem_altmap *altmap)
 {
        unsigned long pfn, end_pfn = start_pfn + size;
@@ -6007,7 +6020,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                 * There can be holes in boot-time mem_map[]s handed to this
                 * function.  They do not exist on hotplugged memory.
                 */
-               if (context == MEMMAP_EARLY) {
+               if (context == MEMINIT_EARLY) {
                        if (overlap_memmap_init(zone, &pfn))
                                continue;
                        if (defer_init(nid, pfn, end_pfn))
@@ -6016,7 +6029,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 
                page = pfn_to_page(pfn);
                __init_single_page(page, pfn, zone, nid);
-               if (context == MEMMAP_HOTPLUG)
+               if (context == MEMINIT_HOTPLUG)
                        __SetPageReserved(page);
 
                /*
@@ -6099,7 +6112,7 @@ void __ref memmap_init_zone_device(struct zone *zone,
                 * check here not to call set_pageblock_migratetype() against
                 * pfn out of zone.
                 *
-                * Please note that MEMMAP_HOTPLUG path doesn't clear memmap
+                * Please note that MEMINIT_HOTPLUG path doesn't clear memmap
                 * because this is done early in section_activate()
                 */
                if (!(pfn & (pageblock_nr_pages - 1))) {
@@ -6137,7 +6150,7 @@ void __meminit __weak memmap_init(unsigned long size, int nid,
                if (end_pfn > start_pfn) {
                        size = end_pfn - start_pfn;
                        memmap_init_zone(size, nid, zone, start_pfn,
-                                        MEMMAP_EARLY, NULL);
+                                        MEMINIT_EARLY, NULL);
                }
        }
 }
index 242c031..63a3db1 100644 (file)
@@ -170,6 +170,14 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages)
  * pageblocks we may have modified and return -EBUSY to caller. This
  * prevents two threads from simultaneously working on overlapping ranges.
  *
+ * Please note that there is no strong synchronization with the page allocator
+ * either. Pages might be freed while their page blocks are marked ISOLATED.
+ * In some cases pages might still end up on pcp lists and that would allow
+ * for their allocation even when they are in fact isolated already. Depending
+ * on how strong of a guarantee the caller needs drain_all_pages might be needed
+ * (e.g. __offline_pages will need to call it after check for isolated range for
+ * a next retry).
+ *
  * Return: the number of isolated pageblocks on success and -EBUSY if any part
  * of range cannot be isolated.
  */
index f470962..1ed1a34 100644 (file)
@@ -1316,7 +1316,7 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
 
        /* allocate chunk */
        alloc_size = sizeof(struct pcpu_chunk) +
-               BITS_TO_LONGS(region_size >> PAGE_SHIFT);
+               BITS_TO_LONGS(region_size >> PAGE_SHIFT) * sizeof(unsigned long);
        chunk = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
        if (!chunk)
                panic("%s: Failed to allocate %zu bytes\n", __func__,
index 271548c..8e2b35b 100644 (file)
@@ -279,11 +279,13 @@ static int shmem_reserve_inode(struct super_block *sb, ino_t *inop)
 
        if (!(sb->s_flags & SB_KERNMOUNT)) {
                spin_lock(&sbinfo->stat_lock);
-               if (!sbinfo->free_inodes) {
-                       spin_unlock(&sbinfo->stat_lock);
-                       return -ENOSPC;
+               if (sbinfo->max_inodes) {
+                       if (!sbinfo->free_inodes) {
+                               spin_unlock(&sbinfo->stat_lock);
+                               return -ENOSPC;
+                       }
+                       sbinfo->free_inodes--;
                }
-               sbinfo->free_inodes--;
                if (inop) {
                        ino = sbinfo->next_ino++;
                        if (unlikely(is_zero_ino(ino)))
index 3160dff..f658e86 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1632,6 +1632,10 @@ static void slab_destroy(struct kmem_cache *cachep, struct page *page)
                kmem_cache_free(cachep->freelist_cache, freelist);
 }
 
+/*
+ * Update the size of the caches before calling slabs_destroy as it may
+ * recursively call kfree.
+ */
 static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list)
 {
        struct page *page, *n;
@@ -2153,8 +2157,8 @@ static void do_drain(void *arg)
        spin_lock(&n->list_lock);
        free_block(cachep, ac->entry, ac->avail, node, &list);
        spin_unlock(&n->list_lock);
-       slabs_destroy(cachep, &list);
        ac->avail = 0;
+       slabs_destroy(cachep, &list);
 }
 
 static void drain_cpu_caches(struct kmem_cache *cachep)
@@ -3402,9 +3406,9 @@ free_done:
        }
 #endif
        spin_unlock(&n->list_lock);
-       slabs_destroy(cachep, &list);
        ac->avail -= batchcount;
        memmove(ac->entry, &(ac->entry[batchcount]), sizeof(void *)*ac->avail);
+       slabs_destroy(cachep, &list);
 }
 
 /*
index d4177ae..6d35740 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1413,10 +1413,6 @@ slab_flags_t kmem_cache_flags(unsigned int object_size,
        char *next_block;
        slab_flags_t block_flags;
 
-       /* If slub_debug = 0, it folds into the if conditional. */
-       if (!slub_debug_string)
-               return flags | slub_debug;
-
        len = strlen(name);
        next_block = slub_debug_string;
        /* Go through all blocks of debug options, see if any matches our slab's name */
@@ -1450,7 +1446,7 @@ slab_flags_t kmem_cache_flags(unsigned int object_size,
                }
        }
 
-       return slub_debug;
+       return flags | slub_debug;
 }
 #else /* !CONFIG_SLUB_DEBUG */
 static inline void setup_object_debug(struct kmem_cache *s,
index d16d65d..e7bdf09 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -494,14 +494,14 @@ void lru_cache_add_inactive_or_unevictable(struct page *page,
 
        unevictable = (vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) == VM_LOCKED;
        if (unlikely(unevictable) && !TestSetPageMlocked(page)) {
+               int nr_pages = thp_nr_pages(page);
                /*
                 * We use the irq-unsafe __mod_zone_page_stat because this
                 * counter is not modified from interrupt context, and the pte
                 * lock is held(spinlock), which implies preemption disabled.
                 */
-               __mod_zone_page_state(page_zone(page), NR_MLOCK,
-                                   thp_nr_pages(page));
-               count_vm_event(UNEVICTABLE_PGMLOCKED);
+               __mod_zone_page_state(page_zone(page), NR_MLOCK, nr_pages);
+               count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages);
        }
        lru_cache_add(page);
 }
index 12f59e6..debc941 100644 (file)
@@ -1078,7 +1078,7 @@ start_over:
                        goto nextsi;
                }
                if (size == SWAPFILE_CLUSTER) {
-                       if (!(si->flags & SWP_FS))
+                       if (si->flags & SWP_BLKDEV)
                                n_ret = swap_alloc_cluster(si, swp_entries);
                } else
                        n_ret = scan_swap_map_slots(si, SWAP_HAS_CACHE,
index 9727dd8..466fc31 100644 (file)
@@ -4268,8 +4268,14 @@ void check_move_unevictable_pages(struct pagevec *pvec)
        for (i = 0; i < pvec->nr; i++) {
                struct page *page = pvec->pages[i];
                struct pglist_data *pagepgdat = page_pgdat(page);
+               int nr_pages;
+
+               if (PageTransTail(page))
+                       continue;
+
+               nr_pages = thp_nr_pages(page);
+               pgscanned += nr_pages;
 
-               pgscanned++;
                if (pagepgdat != pgdat) {
                        if (pgdat)
                                spin_unlock_irq(&pgdat->lru_lock);
@@ -4288,7 +4294,7 @@ void check_move_unevictable_pages(struct pagevec *pvec)
                        ClearPageUnevictable(page);
                        del_page_from_lru_list(page, lruvec, LRU_UNEVICTABLE);
                        add_page_to_lru_list(page, lruvec, lru);
-                       pgrescued++;
+                       pgrescued += nr_pages;
                }
        }
 
index 8500f56..c350ab6 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/lockdep.h>
 #include <linux/netdevice.h>
 #include <linux/netlink.h>
+#include <linux/preempt.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
 #include <linux/seq_file.h>
@@ -83,11 +84,12 @@ static inline u32 batadv_choose_claim(const void *data, u32 size)
  */
 static inline u32 batadv_choose_backbone_gw(const void *data, u32 size)
 {
-       const struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data;
+       const struct batadv_bla_backbone_gw *gw;
        u32 hash = 0;
 
-       hash = jhash(&claim->addr, sizeof(claim->addr), hash);
-       hash = jhash(&claim->vid, sizeof(claim->vid), hash);
+       gw = (struct batadv_bla_backbone_gw *)data;
+       hash = jhash(&gw->orig, sizeof(gw->orig), hash);
+       hash = jhash(&gw->vid, sizeof(gw->vid), hash);
 
        return hash % size;
 }
@@ -1579,13 +1581,16 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 }
 
 /**
- * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
+ * batadv_bla_check_duplist() - Check if a frame is in the broadcast dup.
  * @bat_priv: the bat priv with all the soft interface information
- * @skb: contains the bcast_packet to be checked
+ * @skb: contains the multicast packet to be checked
+ * @payload_ptr: pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ * @orig: originator mac address, NULL if unknown
  *
- * check if it is on our broadcast list. Another gateway might
- * have sent the same packet because it is connected to the same backbone,
- * so we have to remove this duplicate.
+ * Check if it is on our broadcast list. Another gateway might have sent the
+ * same packet because it is connected to the same backbone, so we have to
+ * remove this duplicate.
  *
  * This is performed by checking the CRC, which will tell us
  * with a good chance that it is the same packet. If it is furthermore
@@ -1594,19 +1599,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  *
  * Return: true if a packet is in the duplicate list, false otherwise.
  */
-bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-                                   struct sk_buff *skb)
+static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv,
+                                    struct sk_buff *skb, u8 *payload_ptr,
+                                    const u8 *orig)
 {
-       int i, curr;
-       __be32 crc;
-       struct batadv_bcast_packet *bcast_packet;
        struct batadv_bcast_duplist_entry *entry;
        bool ret = false;
-
-       bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       int i, curr;
+       __be32 crc;
 
        /* calculate the crc ... */
-       crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
+       crc = batadv_skb_crc32(skb, payload_ptr);
 
        spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
 
@@ -1625,8 +1628,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                if (entry->crc != crc)
                        continue;
 
-               if (batadv_compare_eth(entry->orig, bcast_packet->orig))
-                       continue;
+               /* are the originators both known and not anonymous? */
+               if (orig && !is_zero_ether_addr(orig) &&
+                   !is_zero_ether_addr(entry->orig)) {
+                       /* If known, check if the new frame came from
+                        * the same originator:
+                        * We are safe to take identical frames from the
+                        * same orig, if known, as multiplications in
+                        * the mesh are detected via the (orig, seqno) pair.
+                        * So we can be a bit more liberal here and allow
+                        * identical frames from the same orig which the source
+                        * host might have sent multiple times on purpose.
+                        */
+                       if (batadv_compare_eth(entry->orig, orig))
+                               continue;
+               }
 
                /* this entry seems to match: same crc, not too old,
                 * and from another gw. therefore return true to forbid it.
@@ -1642,7 +1658,14 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
        entry = &bat_priv->bla.bcast_duplist[curr];
        entry->crc = crc;
        entry->entrytime = jiffies;
-       ether_addr_copy(entry->orig, bcast_packet->orig);
+
+       /* known originator */
+       if (orig)
+               ether_addr_copy(entry->orig, orig);
+       /* anonymous originator */
+       else
+               eth_zero_addr(entry->orig);
+
        bat_priv->bla.bcast_duplist_curr = curr;
 
 out:
@@ -1652,6 +1675,48 @@ out:
 }
 
 /**
+ * batadv_bla_check_ucast_duplist() - Check if a frame is in the broadcast dup.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: contains the multicast packet to be checked, decapsulated from a
+ *  unicast_packet
+ *
+ * Check if it is on our broadcast list. Another gateway might have sent the
+ * same packet because it is connected to the same backbone, so we have to
+ * remove this duplicate.
+ *
+ * Return: true if a packet is in the duplicate list, false otherwise.
+ */
+static bool batadv_bla_check_ucast_duplist(struct batadv_priv *bat_priv,
+                                          struct sk_buff *skb)
+{
+       return batadv_bla_check_duplist(bat_priv, skb, (u8 *)skb->data, NULL);
+}
+
+/**
+ * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: contains the bcast_packet to be checked
+ *
+ * Check if it is on our broadcast list. Another gateway might have sent the
+ * same packet because it is connected to the same backbone, so we have to
+ * remove this duplicate.
+ *
+ * Return: true if a packet is in the duplicate list, false otherwise.
+ */
+bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
+                                   struct sk_buff *skb)
+{
+       struct batadv_bcast_packet *bcast_packet;
+       u8 *payload_ptr;
+
+       bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       payload_ptr = (u8 *)(bcast_packet + 1);
+
+       return batadv_bla_check_duplist(bat_priv, skb, payload_ptr,
+                                       bcast_packet->orig);
+}
+
+/**
  * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for
  *  the VLAN identified by vid.
  * @bat_priv: the bat priv with all the soft interface information
@@ -1812,7 +1877,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: the frame to be checked
  * @vid: the VLAN ID of the frame
- * @is_bcast: the packet came in a broadcast packet type.
+ * @packet_type: the batman packet type this frame came in
  *
  * batadv_bla_rx avoidance checks if:
  *  * we have to race for a claim
@@ -1824,7 +1889,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
  * further process the skb.
  */
 bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
-                  unsigned short vid, bool is_bcast)
+                  unsigned short vid, int packet_type)
 {
        struct batadv_bla_backbone_gw *backbone_gw;
        struct ethhdr *ethhdr;
@@ -1846,9 +1911,32 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
                goto handled;
 
        if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
-               /* don't allow broadcasts while requests are in flight */
-               if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
-                       goto handled;
+               /* don't allow multicast packets while requests are in flight */
+               if (is_multicast_ether_addr(ethhdr->h_dest))
+                       /* Both broadcast flooding or multicast-via-unicasts
+                        * delivery might send to multiple backbone gateways
+                        * sharing the same LAN and therefore need to coordinate
+                        * which backbone gateway forwards into the LAN,
+                        * by claiming the payload source address.
+                        *
+                        * Broadcast flooding and multicast-via-unicasts
+                        * delivery use the following two batman packet types.
+                        * Note: explicitly exclude BATADV_UNICAST_4ADDR,
+                        * as the DHCP gateway feature will send explicitly
+                        * to only one BLA gateway, so the claiming process
+                        * should be avoided there.
+                        */
+                       if (packet_type == BATADV_BCAST ||
+                           packet_type == BATADV_UNICAST)
+                               goto handled;
+
+       /* potential duplicates from foreign BLA backbone gateways via
+        * multicast-in-unicast packets
+        */
+       if (is_multicast_ether_addr(ethhdr->h_dest) &&
+           packet_type == BATADV_UNICAST &&
+           batadv_bla_check_ucast_duplist(bat_priv, skb))
+               goto handled;
 
        ether_addr_copy(search_claim.addr, ethhdr->h_source);
        search_claim.vid = vid;
@@ -1883,13 +1971,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
                goto allow;
        }
 
-       /* if it is a broadcast ... */
-       if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
+       /* if it is a multicast ... */
+       if (is_multicast_ether_addr(ethhdr->h_dest) &&
+           (packet_type == BATADV_BCAST || packet_type == BATADV_UNICAST)) {
                /* ... drop it. the responsible gateway is in charge.
                 *
-                * We need to check is_bcast because with the gateway
+                * We need to check packet type because with the gateway
                 * feature, broadcasts (like DHCP requests) may be sent
-                * using a unicast packet type.
+                * using a unicast 4 address packet type. See comment above.
                 */
                goto handled;
        } else {
index 41edb2c..a81c41b 100644 (file)
@@ -35,7 +35,7 @@ static inline bool batadv_bla_is_loopdetect_mac(const uint8_t *mac)
 
 #ifdef CONFIG_BATMAN_ADV_BLA
 bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
-                  unsigned short vid, bool is_bcast);
+                  unsigned short vid, int packet_type);
 bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
                   unsigned short vid);
 bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
@@ -66,7 +66,7 @@ bool batadv_bla_check_claim(struct batadv_priv *bat_priv, u8 *addr,
 
 static inline bool batadv_bla_rx(struct batadv_priv *bat_priv,
                                 struct sk_buff *skb, unsigned short vid,
-                                bool is_bcast)
+                                int packet_type)
 {
        return false;
 }
index bdc4a1f..ca24a2e 100644 (file)
@@ -51,6 +51,7 @@
 #include <uapi/linux/batadv_packet.h>
 #include <uapi/linux/batman_adv.h>
 
+#include "bridge_loop_avoidance.h"
 #include "hard-interface.h"
 #include "hash.h"
 #include "log.h"
@@ -1435,6 +1436,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
 }
 
 /**
+ * batadv_mcast_forw_send_orig() - send a multicast packet to an originator
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the multicast packet to send
+ * @vid: the vlan identifier
+ * @orig_node: the originator to send the packet to
+ *
+ * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
+ */
+int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
+                               struct sk_buff *skb,
+                               unsigned short vid,
+                               struct batadv_orig_node *orig_node)
+{
+       /* Avoid sending multicast-in-unicast packets to other BLA
+        * gateways - they already got the frame from the LAN side
+        * we share with them.
+        * TODO: Refactor to take BLA into account earlier, to avoid
+        * reducing the mcast_fanout count.
+        */
+       if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid)) {
+               dev_kfree_skb(skb);
+               return NET_XMIT_SUCCESS;
+       }
+
+       return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0,
+                                      orig_node, vid);
+}
+
+/**
  * batadv_mcast_forw_tt() - forwards a packet to multicast listeners
  * @bat_priv: the bat priv with all the soft interface information
  * @skb: the multicast packet to transmit
@@ -1471,8 +1501,8 @@ batadv_mcast_forw_tt(struct batadv_priv *bat_priv, struct sk_buff *skb,
                        break;
                }
 
-               batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
-                                       orig_entry->orig_node, vid);
+               batadv_mcast_forw_send_orig(bat_priv, newskb, vid,
+                                           orig_entry->orig_node);
        }
        rcu_read_unlock();
 
@@ -1513,8 +1543,7 @@ batadv_mcast_forw_want_all_ipv4(struct batadv_priv *bat_priv,
                        break;
                }
 
-               batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
-                                       orig_node, vid);
+               batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
        }
        rcu_read_unlock();
        return ret;
@@ -1551,8 +1580,7 @@ batadv_mcast_forw_want_all_ipv6(struct batadv_priv *bat_priv,
                        break;
                }
 
-               batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
-                                       orig_node, vid);
+               batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
        }
        rcu_read_unlock();
        return ret;
@@ -1618,8 +1646,7 @@ batadv_mcast_forw_want_all_rtr4(struct batadv_priv *bat_priv,
                        break;
                }
 
-               batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
-                                       orig_node, vid);
+               batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
        }
        rcu_read_unlock();
        return ret;
@@ -1656,8 +1683,7 @@ batadv_mcast_forw_want_all_rtr6(struct batadv_priv *bat_priv,
                        break;
                }
 
-               batadv_send_skb_unicast(bat_priv, newskb, BATADV_UNICAST, 0,
-                                       orig_node, vid);
+               batadv_mcast_forw_send_orig(bat_priv, newskb, vid, orig_node);
        }
        rcu_read_unlock();
        return ret;
index ebf8259..3e114bc 100644 (file)
@@ -46,6 +46,11 @@ enum batadv_forw_mode
 batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
                       struct batadv_orig_node **mcast_single_orig);
 
+int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
+                               struct sk_buff *skb,
+                               unsigned short vid,
+                               struct batadv_orig_node *orig_node);
+
 int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
                           unsigned short vid);
 
@@ -72,6 +77,16 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
 }
 
 static inline int
+batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
+                           struct sk_buff *skb,
+                           unsigned short vid,
+                           struct batadv_orig_node *orig_node)
+{
+       kfree_skb(skb);
+       return NET_XMIT_DROP;
+}
+
+static inline int
 batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
                       unsigned short vid)
 {
index 27cdf5e..9e5c71e 100644 (file)
@@ -826,6 +826,10 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
        vid = batadv_get_vid(skb, hdr_len);
        ethhdr = (struct ethhdr *)(skb->data + hdr_len);
 
+       /* do not reroute multicast frames in a unicast header */
+       if (is_multicast_ether_addr(ethhdr->h_dest))
+               return true;
+
        /* check if the destination client was served by this node and it is now
         * roaming. In this case, it means that the node has got a ROAM_ADV
         * message and that it knows the new destination in the mesh to re-route
index 23833a0..cdde943 100644 (file)
@@ -364,9 +364,8 @@ send:
                                goto dropped;
                        ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
                } else if (mcast_single_orig) {
-                       ret = batadv_send_skb_unicast(bat_priv, skb,
-                                                     BATADV_UNICAST, 0,
-                                                     mcast_single_orig, vid);
+                       ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid,
+                                                         mcast_single_orig);
                } else if (forw_mode == BATADV_FORW_SOME) {
                        ret = batadv_mcast_forw_send(bat_priv, skb, vid);
                } else {
@@ -425,10 +424,10 @@ void batadv_interface_rx(struct net_device *soft_iface,
        struct vlan_ethhdr *vhdr;
        struct ethhdr *ethhdr;
        unsigned short vid;
-       bool is_bcast;
+       int packet_type;
 
        batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
-       is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
+       packet_type = batadv_bcast_packet->packet_type;
 
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
@@ -471,7 +470,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
        /* Let the bridge loop avoidance check the packet. If will
         * not handle it, we can safely push it up.
         */
-       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
+       if (batadv_bla_rx(bat_priv, skb, vid, packet_type))
                goto out;
 
        if (orig_node)
index b18cdf0..dfec65e 100644 (file)
@@ -88,9 +88,10 @@ static void br_arp_send(struct net_bridge *br, struct net_bridge_port *p,
        }
 }
 
-static int br_chk_addr_ip(struct net_device *dev, void *data)
+static int br_chk_addr_ip(struct net_device *dev,
+                         struct netdev_nested_priv *priv)
 {
-       __be32 ip = *(__be32 *)data;
+       __be32 ip = *(__be32 *)priv->data;
        struct in_device *in_dev;
        __be32 addr = 0;
 
@@ -107,11 +108,15 @@ static int br_chk_addr_ip(struct net_device *dev, void *data)
 
 static bool br_is_local_ip(struct net_device *dev, __be32 ip)
 {
-       if (br_chk_addr_ip(dev, &ip))
+       struct netdev_nested_priv priv = {
+               .data = (void *)&ip,
+       };
+
+       if (br_chk_addr_ip(dev, &priv))
                return true;
 
        /* check if ip is configured on upper dev */
-       if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip, &ip))
+       if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip, &priv))
                return true;
 
        return false;
@@ -361,9 +366,10 @@ static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
        }
 }
 
-static int br_chk_addr_ip6(struct net_device *dev, void *data)
+static int br_chk_addr_ip6(struct net_device *dev,
+                          struct netdev_nested_priv *priv)
 {
-       struct in6_addr *addr = (struct in6_addr *)data;
+       struct in6_addr *addr = (struct in6_addr *)priv->data;
 
        if (ipv6_chk_addr(dev_net(dev), addr, dev, 0))
                return 1;
@@ -374,11 +380,15 @@ static int br_chk_addr_ip6(struct net_device *dev, void *data)
 static bool br_is_local_ip6(struct net_device *dev, struct in6_addr *addr)
 
 {
-       if (br_chk_addr_ip6(dev, addr))
+       struct netdev_nested_priv priv = {
+               .data = (void *)addr,
+       };
+
+       if (br_chk_addr_ip6(dev, &priv))
                return true;
 
        /* check if ip is configured on upper dev */
-       if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip6, addr))
+       if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip6, &priv))
                return true;
 
        return false;
index 9db504b..32ac834 100644 (file)
@@ -413,6 +413,8 @@ void br_fdb_delete_by_port(struct net_bridge *br,
 
                if (!do_all)
                        if (test_bit(BR_FDB_STATIC, &f->flags) ||
+                           (test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &f->flags) &&
+                            !test_bit(BR_FDB_OFFLOADED, &f->flags)) ||
                            (vid && f->key.vlan_id != vid))
                                continue;
 
index 147d525..da310f0 100644 (file)
@@ -380,6 +380,7 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                          u32 filter_mask, const struct net_device *dev)
 {
        u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+       struct nlattr *af = NULL;
        struct net_bridge *br;
        struct ifinfomsg *hdr;
        struct nlmsghdr *nlh;
@@ -423,11 +424,18 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                nla_nest_end(skb, nest);
        }
 
+       if (filter_mask & (RTEXT_FILTER_BRVLAN |
+                          RTEXT_FILTER_BRVLAN_COMPRESSED |
+                          RTEXT_FILTER_MRP)) {
+               af = nla_nest_start_noflag(skb, IFLA_AF_SPEC);
+               if (!af)
+                       goto nla_put_failure;
+       }
+
        /* Check if  the VID information is requested */
        if ((filter_mask & RTEXT_FILTER_BRVLAN) ||
            (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
                struct net_bridge_vlan_group *vg;
-               struct nlattr *af;
                int err;
 
                /* RCU needed because of the VLAN locking rules (rcu || rtnl) */
@@ -441,11 +449,6 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                        rcu_read_unlock();
                        goto done;
                }
-               af = nla_nest_start_noflag(skb, IFLA_AF_SPEC);
-               if (!af) {
-                       rcu_read_unlock();
-                       goto nla_put_failure;
-               }
                if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
                        err = br_fill_ifvlaninfo_compressed(skb, vg);
                else
@@ -456,32 +459,25 @@ static int br_fill_ifinfo(struct sk_buff *skb,
                rcu_read_unlock();
                if (err)
                        goto nla_put_failure;
-
-               nla_nest_end(skb, af);
        }
 
        if (filter_mask & RTEXT_FILTER_MRP) {
-               struct nlattr *af;
                int err;
 
                if (!br_mrp_enabled(br) || port)
                        goto done;
 
-               af = nla_nest_start_noflag(skb, IFLA_AF_SPEC);
-               if (!af)
-                       goto nla_put_failure;
-
                rcu_read_lock();
                err = br_mrp_fill_info(skb, br);
                rcu_read_unlock();
 
                if (err)
                        goto nla_put_failure;
-
-               nla_nest_end(skb, af);
        }
 
 done:
+       if (af)
+               nla_nest_end(skb, af);
        nlmsg_end(skb, nlh);
        return 0;
 
index f9092c7..ee87800 100644 (file)
@@ -1288,11 +1288,13 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
        }
 }
 
-static int __br_vlan_get_pvid(const struct net_device *dev,
-                             struct net_bridge_port *p, u16 *p_pvid)
+int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid)
 {
        struct net_bridge_vlan_group *vg;
+       struct net_bridge_port *p;
 
+       ASSERT_RTNL();
+       p = br_port_get_check_rtnl(dev);
        if (p)
                vg = nbp_vlan_group(p);
        else if (netif_is_bridge_master(dev))
@@ -1303,18 +1305,23 @@ static int __br_vlan_get_pvid(const struct net_device *dev,
        *p_pvid = br_get_pvid(vg);
        return 0;
 }
-
-int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid)
-{
-       ASSERT_RTNL();
-
-       return __br_vlan_get_pvid(dev, br_port_get_check_rtnl(dev), p_pvid);
-}
 EXPORT_SYMBOL_GPL(br_vlan_get_pvid);
 
 int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid)
 {
-       return __br_vlan_get_pvid(dev, br_port_get_check_rcu(dev), p_pvid);
+       struct net_bridge_vlan_group *vg;
+       struct net_bridge_port *p;
+
+       p = br_port_get_check_rcu(dev);
+       if (p)
+               vg = nbp_vlan_group_rcu(p);
+       else if (netif_is_bridge_master(dev))
+               vg = br_vlan_group_rcu(netdev_priv(dev));
+       else
+               return -EINVAL;
+
+       *p_pvid = br_get_pvid(vg);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);
 
@@ -1353,7 +1360,7 @@ static int br_vlan_is_bind_vlan_dev(const struct net_device *dev)
 }
 
 static int br_vlan_is_bind_vlan_dev_fn(struct net_device *dev,
-                                      __always_unused void *data)
+                              __always_unused struct netdev_nested_priv *priv)
 {
        return br_vlan_is_bind_vlan_dev(dev);
 }
@@ -1376,9 +1383,9 @@ struct br_vlan_bind_walk_data {
 };
 
 static int br_vlan_match_bind_vlan_dev_fn(struct net_device *dev,
-                                         void *data_in)
+                                         struct netdev_nested_priv *priv)
 {
-       struct br_vlan_bind_walk_data *data = data_in;
+       struct br_vlan_bind_walk_data *data = priv->data;
        int found = 0;
 
        if (br_vlan_is_bind_vlan_dev(dev) &&
@@ -1396,10 +1403,13 @@ br_vlan_get_upper_bind_vlan_dev(struct net_device *dev, u16 vid)
        struct br_vlan_bind_walk_data data = {
                .vid = vid,
        };
+       struct netdev_nested_priv priv = {
+               .data = (void *)&data,
+       };
 
        rcu_read_lock();
        netdev_walk_all_upper_dev_rcu(dev, br_vlan_match_bind_vlan_dev_fn,
-                                     &data);
+                                     &priv);
        rcu_read_unlock();
 
        return data.result;
@@ -1480,9 +1490,9 @@ struct br_vlan_link_state_walk_data {
 };
 
 static int br_vlan_link_state_change_fn(struct net_device *vlan_dev,
-                                       void *data_in)
+                                       struct netdev_nested_priv *priv)
 {
-       struct br_vlan_link_state_walk_data *data = data_in;
+       struct br_vlan_link_state_walk_data *data = priv->data;
 
        if (br_vlan_is_bind_vlan_dev(vlan_dev))
                br_vlan_set_vlan_dev_state(data->br, vlan_dev);
@@ -1496,10 +1506,13 @@ static void br_vlan_link_state_change(struct net_device *dev,
        struct br_vlan_link_state_walk_data data = {
                .br = br
        };
+       struct netdev_nested_priv priv = {
+               .data = (void *)&data,
+       };
 
        rcu_read_lock();
        netdev_walk_all_upper_dev_rcu(dev, br_vlan_link_state_change_fn,
-                                     &data);
+                                     &priv);
        rcu_read_unlock();
 }
 
index bdfd66b..d4d7a0e 100644 (file)
@@ -575,7 +575,7 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
         * coalescing neighboring slab objects into a single frag which
         * triggers one of hardened usercopy checks.
         */
-       if (page_count(page) >= 1 && !PageSlab(page))
+       if (sendpage_ok(page))
                sendpage = sock->ops->sendpage;
        else
                sendpage = sock_no_sendpage;
index 4086d33..4906b44 100644 (file)
@@ -6812,9 +6812,10 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev,
        return NULL;
 }
 
-static int ____netdev_has_upper_dev(struct net_device *upper_dev, void *data)
+static int ____netdev_has_upper_dev(struct net_device *upper_dev,
+                                   struct netdev_nested_priv *priv)
 {
-       struct net_device *dev = data;
+       struct net_device *dev = (struct net_device *)priv->data;
 
        return upper_dev == dev;
 }
@@ -6831,10 +6832,14 @@ static int ____netdev_has_upper_dev(struct net_device *upper_dev, void *data)
 bool netdev_has_upper_dev(struct net_device *dev,
                          struct net_device *upper_dev)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)upper_dev,
+       };
+
        ASSERT_RTNL();
 
        return netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
-                                            upper_dev);
+                                            &priv);
 }
 EXPORT_SYMBOL(netdev_has_upper_dev);
 
@@ -6851,8 +6856,12 @@ EXPORT_SYMBOL(netdev_has_upper_dev);
 bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
                                  struct net_device *upper_dev)
 {
+       struct netdev_nested_priv priv = {
+               .data = (void *)upper_dev,
+       };
+
        return !!netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
-                                              upper_dev);
+                                              &priv);
 }
 EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu);
 
@@ -6997,8 +7006,8 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
 
 static int __netdev_walk_all_upper_dev(struct net_device *dev,
                                       int (*fn)(struct net_device *dev,
-                                                void *data),
-                                      void *data)
+                                        struct netdev_nested_priv *priv),
+                                      struct netdev_nested_priv *priv)
 {
        struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
        struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
@@ -7010,7 +7019,7 @@ static int __netdev_walk_all_upper_dev(struct net_device *dev,
 
        while (1) {
                if (now != dev) {
-                       ret = fn(now, data);
+                       ret = fn(now, priv);
                        if (ret)
                                return ret;
                }
@@ -7046,8 +7055,8 @@ static int __netdev_walk_all_upper_dev(struct net_device *dev,
 
 int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *dev,
-                                           void *data),
-                                 void *data)
+                                           struct netdev_nested_priv *priv),
+                                 struct netdev_nested_priv *priv)
 {
        struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
        struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
@@ -7058,7 +7067,7 @@ int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
 
        while (1) {
                if (now != dev) {
-                       ret = fn(now, data);
+                       ret = fn(now, priv);
                        if (ret)
                                return ret;
                }
@@ -7094,10 +7103,15 @@ EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
 static bool __netdev_has_upper_dev(struct net_device *dev,
                                   struct net_device *upper_dev)
 {
+       struct netdev_nested_priv priv = {
+               .flags = 0,
+               .data = (void *)upper_dev,
+       };
+
        ASSERT_RTNL();
 
        return __netdev_walk_all_upper_dev(dev, ____netdev_has_upper_dev,
-                                          upper_dev);
+                                          &priv);
 }
 
 /**
@@ -7215,8 +7229,8 @@ static struct net_device *__netdev_next_lower_dev(struct net_device *dev,
 
 int netdev_walk_all_lower_dev(struct net_device *dev,
                              int (*fn)(struct net_device *dev,
-                                       void *data),
-                             void *data)
+                                       struct netdev_nested_priv *priv),
+                             struct netdev_nested_priv *priv)
 {
        struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
        struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
@@ -7227,7 +7241,7 @@ int netdev_walk_all_lower_dev(struct net_device *dev,
 
        while (1) {
                if (now != dev) {
-                       ret = fn(now, data);
+                       ret = fn(now, priv);
                        if (ret)
                                return ret;
                }
@@ -7262,8 +7276,8 @@ EXPORT_SYMBOL_GPL(netdev_walk_all_lower_dev);
 
 static int __netdev_walk_all_lower_dev(struct net_device *dev,
                                       int (*fn)(struct net_device *dev,
-                                                void *data),
-                                      void *data)
+                                        struct netdev_nested_priv *priv),
+                                      struct netdev_nested_priv *priv)
 {
        struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
        struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
@@ -7275,7 +7289,7 @@ static int __netdev_walk_all_lower_dev(struct net_device *dev,
 
        while (1) {
                if (now != dev) {
-                       ret = fn(now, data);
+                       ret = fn(now, priv);
                        if (ret)
                                return ret;
                }
@@ -7364,22 +7378,34 @@ static u8 __netdev_lower_depth(struct net_device *dev)
        return max_depth;
 }
 
-static int __netdev_update_upper_level(struct net_device *dev, void *data)
+static int __netdev_update_upper_level(struct net_device *dev,
+                                      struct netdev_nested_priv *__unused)
 {
        dev->upper_level = __netdev_upper_depth(dev) + 1;
        return 0;
 }
 
-static int __netdev_update_lower_level(struct net_device *dev, void *data)
+static int __netdev_update_lower_level(struct net_device *dev,
+                                      struct netdev_nested_priv *priv)
 {
        dev->lower_level = __netdev_lower_depth(dev) + 1;
+
+#ifdef CONFIG_LOCKDEP
+       if (!priv)
+               return 0;
+
+       if (priv->flags & NESTED_SYNC_IMM)
+               dev->nested_level = dev->lower_level - 1;
+       if (priv->flags & NESTED_SYNC_TODO)
+               net_unlink_todo(dev);
+#endif
        return 0;
 }
 
 int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *dev,
-                                           void *data),
-                                 void *data)
+                                           struct netdev_nested_priv *priv),
+                                 struct netdev_nested_priv *priv)
 {
        struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
        struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
@@ -7390,7 +7416,7 @@ int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
 
        while (1) {
                if (now != dev) {
-                       ret = fn(now, data);
+                       ret = fn(now, priv);
                        if (ret)
                                return ret;
                }
@@ -7650,6 +7676,7 @@ static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
 static int __netdev_upper_dev_link(struct net_device *dev,
                                   struct net_device *upper_dev, bool master,
                                   void *upper_priv, void *upper_info,
+                                  struct netdev_nested_priv *priv,
                                   struct netlink_ext_ack *extack)
 {
        struct netdev_notifier_changeupper_info changeupper_info = {
@@ -7706,9 +7733,9 @@ static int __netdev_upper_dev_link(struct net_device *dev,
        __netdev_update_upper_level(dev, NULL);
        __netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
 
-       __netdev_update_lower_level(upper_dev, NULL);
+       __netdev_update_lower_level(upper_dev, priv);
        __netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level,
-                                   NULL);
+                                   priv);
 
        return 0;
 
@@ -7733,8 +7760,13 @@ int netdev_upper_dev_link(struct net_device *dev,
                          struct net_device *upper_dev,
                          struct netlink_ext_ack *extack)
 {
+       struct netdev_nested_priv priv = {
+               .flags = NESTED_SYNC_IMM | NESTED_SYNC_TODO,
+               .data = NULL,
+       };
+
        return __netdev_upper_dev_link(dev, upper_dev, false,
-                                      NULL, NULL, extack);
+                                      NULL, NULL, &priv, extack);
 }
 EXPORT_SYMBOL(netdev_upper_dev_link);
 
@@ -7757,21 +7789,19 @@ int netdev_master_upper_dev_link(struct net_device *dev,
                                 void *upper_priv, void *upper_info,
                                 struct netlink_ext_ack *extack)
 {
+       struct netdev_nested_priv priv = {
+               .flags = NESTED_SYNC_IMM | NESTED_SYNC_TODO,
+               .data = NULL,
+       };
+
        return __netdev_upper_dev_link(dev, upper_dev, true,
-                                      upper_priv, upper_info, extack);
+                                      upper_priv, upper_info, &priv, extack);
 }
 EXPORT_SYMBOL(netdev_master_upper_dev_link);
 
-/**
- * netdev_upper_dev_unlink - Removes a link to upper device
- * @dev: device
- * @upper_dev: new upper device
- *
- * Removes a link to device which is upper to this one. The caller must hold
- * the RTNL lock.
- */
-void netdev_upper_dev_unlink(struct net_device *dev,
-                            struct net_device *upper_dev)
+static void __netdev_upper_dev_unlink(struct net_device *dev,
+                                     struct net_device *upper_dev,
+                                     struct netdev_nested_priv *priv)
 {
        struct netdev_notifier_changeupper_info changeupper_info = {
                .info = {
@@ -7796,9 +7826,28 @@ void netdev_upper_dev_unlink(struct net_device *dev,
        __netdev_update_upper_level(dev, NULL);
        __netdev_walk_all_lower_dev(dev, __netdev_update_upper_level, NULL);
 
-       __netdev_update_lower_level(upper_dev, NULL);
+       __netdev_update_lower_level(upper_dev, priv);
        __netdev_walk_all_upper_dev(upper_dev, __netdev_update_lower_level,
-                                   NULL);
+                                   priv);
+}
+
+/**
+ * netdev_upper_dev_unlink - Removes a link to upper device
+ * @dev: device
+ * @upper_dev: new upper device
+ *
+ * Removes a link to device which is upper to this one. The caller must hold
+ * the RTNL lock.
+ */
+void netdev_upper_dev_unlink(struct net_device *dev,
+                            struct net_device *upper_dev)
+{
+       struct netdev_nested_priv priv = {
+               .flags = NESTED_SYNC_TODO,
+               .data = NULL,
+       };
+
+       __netdev_upper_dev_unlink(dev, upper_dev, &priv);
 }
 EXPORT_SYMBOL(netdev_upper_dev_unlink);
 
@@ -7834,6 +7883,10 @@ int netdev_adjacent_change_prepare(struct net_device *old_dev,
                                   struct net_device *dev,
                                   struct netlink_ext_ack *extack)
 {
+       struct netdev_nested_priv priv = {
+               .flags = 0,
+               .data = NULL,
+       };
        int err;
 
        if (!new_dev)
@@ -7841,8 +7894,8 @@ int netdev_adjacent_change_prepare(struct net_device *old_dev,
 
        if (old_dev && new_dev != old_dev)
                netdev_adjacent_dev_disable(dev, old_dev);
-
-       err = netdev_upper_dev_link(new_dev, dev, extack);
+       err = __netdev_upper_dev_link(new_dev, dev, false, NULL, NULL, &priv,
+                                     extack);
        if (err) {
                if (old_dev && new_dev != old_dev)
                        netdev_adjacent_dev_enable(dev, old_dev);
@@ -7857,6 +7910,11 @@ void netdev_adjacent_change_commit(struct net_device *old_dev,
                                   struct net_device *new_dev,
                                   struct net_device *dev)
 {
+       struct netdev_nested_priv priv = {
+               .flags = NESTED_SYNC_IMM | NESTED_SYNC_TODO,
+               .data = NULL,
+       };
+
        if (!new_dev || !old_dev)
                return;
 
@@ -7864,7 +7922,7 @@ void netdev_adjacent_change_commit(struct net_device *old_dev,
                return;
 
        netdev_adjacent_dev_enable(dev, old_dev);
-       netdev_upper_dev_unlink(old_dev, dev);
+       __netdev_upper_dev_unlink(old_dev, dev, &priv);
 }
 EXPORT_SYMBOL(netdev_adjacent_change_commit);
 
@@ -7872,13 +7930,18 @@ void netdev_adjacent_change_abort(struct net_device *old_dev,
                                  struct net_device *new_dev,
                                  struct net_device *dev)
 {
+       struct netdev_nested_priv priv = {
+               .flags = 0,
+               .data = NULL,
+       };
+
        if (!new_dev)
                return;
 
        if (old_dev && new_dev != old_dev)
                netdev_adjacent_dev_enable(dev, old_dev);
 
-       netdev_upper_dev_unlink(new_dev, dev);
+       __netdev_upper_dev_unlink(new_dev, dev, &priv);
 }
 EXPORT_SYMBOL(netdev_adjacent_change_abort);
 
@@ -8647,7 +8710,7 @@ int dev_get_port_parent_id(struct net_device *dev,
                if (!first.id_len)
                        first = *ppid;
                else if (memcmp(&first, ppid, sizeof(*ppid)))
-                       return -ENODATA;
+                       return -EOPNOTSUPP;
        }
 
        return err;
@@ -10062,6 +10125,19 @@ static void netdev_wait_allrefs(struct net_device *dev)
 void netdev_run_todo(void)
 {
        struct list_head list;
+#ifdef CONFIG_LOCKDEP
+       struct list_head unlink_list;
+
+       list_replace_init(&net_unlink_list, &unlink_list);
+
+       while (!list_empty(&unlink_list)) {
+               struct net_device *dev = list_first_entry(&unlink_list,
+                                                         struct net_device,
+                                                         unlink_list);
+               list_del(&dev->unlink_list);
+               dev->nested_level = dev->lower_level - 1;
+       }
+#endif
 
        /* Snapshot list, allow later requests */
        list_replace_init(&net_todo_list, &list);
@@ -10274,6 +10350,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        dev->gso_max_segs = GSO_MAX_SEGS;
        dev->upper_level = 1;
        dev->lower_level = 1;
+#ifdef CONFIG_LOCKDEP
+       dev->nested_level = 0;
+       INIT_LIST_HEAD(&dev->unlink_list);
+#endif
 
        INIT_LIST_HEAD(&dev->napi_list);
        INIT_LIST_HEAD(&dev->unreg_list);
index 54cd568..fa1c37e 100644 (file)
@@ -637,7 +637,7 @@ int dev_uc_sync(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
-       netif_addr_lock_nested(to);
+       netif_addr_lock(to);
        err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
@@ -667,7 +667,7 @@ int dev_uc_sync_multiple(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
-       netif_addr_lock_nested(to);
+       netif_addr_lock(to);
        err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
@@ -700,7 +700,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from)
         * larger.
         */
        netif_addr_lock_bh(from);
-       netif_addr_lock_nested(to);
+       netif_addr_lock(to);
        __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
        __dev_set_rx_mode(to);
        netif_addr_unlock(to);
@@ -867,7 +867,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
-       netif_addr_lock_nested(to);
+       netif_addr_lock(to);
        err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
@@ -897,7 +897,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from)
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
-       netif_addr_lock_nested(to);
+       netif_addr_lock(to);
        err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
@@ -922,7 +922,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
 
        /* See the above comments inside dev_uc_unsync(). */
        netif_addr_lock_bh(from);
-       netif_addr_lock_nested(to);
+       netif_addr_lock(to);
        __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
        __dev_set_rx_mode(to);
        netif_addr_unlock(to);
index d6b6ced..0c01bd8 100644 (file)
@@ -144,7 +144,7 @@ static void dst_destroy_rcu(struct rcu_head *head)
 
 /* Operations to mark dst as DEAD and clean up the net device referenced
  * by dst:
- * 1. put the dst under loopback interface and discard all tx/rx packets
+ * 1. put the dst under blackhole interface and discard all tx/rx packets
  *    on this route.
  * 2. release the net_device
  * This function should be called when removing routes from the fib tree
index 51678a5..7bcfb16 100644 (file)
@@ -16,7 +16,7 @@
 #include <net/ip_tunnels.h>
 #include <linux/indirect_call_wrapper.h>
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+#if defined(CONFIG_IPV6) && defined(CONFIG_IPV6_MULTIPLE_TABLES)
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 #define INDIRECT_CALL_MT(f, f2, f1, ...) \
        INDIRECT_CALL_INET(f, f2, f1, __VA_ARGS__)
index 1f647ab..b5f3faa 100644 (file)
@@ -4838,6 +4838,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
        fl4.saddr = params->ipv4_src;
        fl4.fl4_sport = params->sport;
        fl4.fl4_dport = params->dport;
+       fl4.flowi4_multipath_hash = 0;
 
        if (flags & BPF_FIB_LOOKUP_DIRECT) {
                u32 tbid = l3mdev_fib_table_rcu(dev) ? : RT_TABLE_MAIN;
@@ -7065,8 +7066,6 @@ static int bpf_gen_ld_abs(const struct bpf_insn *orig,
        bool indirect = BPF_MODE(orig->code) == BPF_IND;
        struct bpf_insn *insn = insn_buf;
 
-       /* We're guaranteed here that CTX is in R6. */
-       *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_CTX);
        if (!indirect) {
                *insn++ = BPF_MOV64_IMM(BPF_REG_2, orig->imm);
        } else {
@@ -7074,6 +7073,8 @@ static int bpf_gen_ld_abs(const struct bpf_insn *orig,
                if (orig->imm)
                        *insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, orig->imm);
        }
+       /* We're guaranteed here that CTX is in R6. */
+       *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_CTX);
 
        switch (BPF_SIZE(orig->code)) {
        case BPF_B:
@@ -9522,7 +9523,7 @@ BPF_CALL_1(bpf_skc_to_tcp6_sock, struct sock *, sk)
         * trigger an explicit type generation here.
         */
        BTF_TYPE_EMIT(struct tcp6_sock);
-       if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP &&
+       if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP &&
            sk->sk_family == AF_INET6)
                return (unsigned long)sk;
 
@@ -9540,7 +9541,7 @@ const struct bpf_func_proto bpf_skc_to_tcp6_sock_proto = {
 
 BPF_CALL_1(bpf_skc_to_tcp_sock, struct sock *, sk)
 {
-       if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
+       if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
                return (unsigned long)sk;
 
        return (unsigned long)NULL;
@@ -9557,13 +9558,19 @@ const struct bpf_func_proto bpf_skc_to_tcp_sock_proto = {
 
 BPF_CALL_1(bpf_skc_to_tcp_timewait_sock, struct sock *, sk)
 {
+       /* BTF types for tcp_timewait_sock and inet_timewait_sock are not
+        * generated if CONFIG_INET=n. Trigger an explicit generation here.
+        */
+       BTF_TYPE_EMIT(struct inet_timewait_sock);
+       BTF_TYPE_EMIT(struct tcp_timewait_sock);
+
 #ifdef CONFIG_INET
-       if (sk->sk_prot == &tcp_prot && sk->sk_state == TCP_TIME_WAIT)
+       if (sk && sk->sk_prot == &tcp_prot && sk->sk_state == TCP_TIME_WAIT)
                return (unsigned long)sk;
 #endif
 
 #if IS_BUILTIN(CONFIG_IPV6)
-       if (sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_TIME_WAIT)
+       if (sk && sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_TIME_WAIT)
                return (unsigned long)sk;
 #endif
 
@@ -9582,12 +9589,12 @@ const struct bpf_func_proto bpf_skc_to_tcp_timewait_sock_proto = {
 BPF_CALL_1(bpf_skc_to_tcp_request_sock, struct sock *, sk)
 {
 #ifdef CONFIG_INET
-       if (sk->sk_prot == &tcp_prot  && sk->sk_state == TCP_NEW_SYN_RECV)
+       if (sk && sk->sk_prot == &tcp_prot && sk->sk_state == TCP_NEW_SYN_RECV)
                return (unsigned long)sk;
 #endif
 
 #if IS_BUILTIN(CONFIG_IPV6)
-       if (sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_NEW_SYN_RECV)
+       if (sk && sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_NEW_SYN_RECV)
                return (unsigned long)sk;
 #endif
 
@@ -9609,7 +9616,7 @@ BPF_CALL_1(bpf_skc_to_udp6_sock, struct sock *, sk)
         * trigger an explicit type generation here.
         */
        BTF_TYPE_EMIT(struct udp6_sock);
-       if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_UDP &&
+       if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_UDP &&
            sk->sk_type == SOCK_DGRAM && sk->sk_family == AF_INET6)
                return (unsigned long)sk;
 
index dcd61ac..944ab21 100644 (file)
@@ -251,10 +251,10 @@ int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp)
        if (refcount_read(&net->count) == 0)
                return NETNSA_NSID_NOT_ASSIGNED;
 
-       spin_lock(&net->nsid_lock);
+       spin_lock_bh(&net->nsid_lock);
        id = __peernet2id(net, peer);
        if (id >= 0) {
-               spin_unlock(&net->nsid_lock);
+               spin_unlock_bh(&net->nsid_lock);
                return id;
        }
 
@@ -264,12 +264,12 @@ int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp)
         * just been idr_remove()'d from there in cleanup_net().
         */
        if (!maybe_get_net(peer)) {
-               spin_unlock(&net->nsid_lock);
+               spin_unlock_bh(&net->nsid_lock);
                return NETNSA_NSID_NOT_ASSIGNED;
        }
 
        id = alloc_netid(net, peer, -1);
-       spin_unlock(&net->nsid_lock);
+       spin_unlock_bh(&net->nsid_lock);
 
        put_net(peer);
        if (id < 0)
@@ -534,20 +534,20 @@ static void unhash_nsid(struct net *net, struct net *last)
        for_each_net(tmp) {
                int id;
 
-               spin_lock(&tmp->nsid_lock);
+               spin_lock_bh(&tmp->nsid_lock);
                id = __peernet2id(tmp, net);
                if (id >= 0)
                        idr_remove(&tmp->netns_ids, id);
-               spin_unlock(&tmp->nsid_lock);
+               spin_unlock_bh(&tmp->nsid_lock);
                if (id >= 0)
                        rtnl_net_notifyid(tmp, RTM_DELNSID, id, 0, NULL,
                                          GFP_KERNEL);
                if (tmp == last)
                        break;
        }
-       spin_lock(&net->nsid_lock);
+       spin_lock_bh(&net->nsid_lock);
        idr_destroy(&net->netns_ids);
-       spin_unlock(&net->nsid_lock);
+       spin_unlock_bh(&net->nsid_lock);
 }
 
 static LLIST_HEAD(cleanup_list);
@@ -760,9 +760,9 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
                return PTR_ERR(peer);
        }
 
-       spin_lock(&net->nsid_lock);
+       spin_lock_bh(&net->nsid_lock);
        if (__peernet2id(net, peer) >= 0) {
-               spin_unlock(&net->nsid_lock);
+               spin_unlock_bh(&net->nsid_lock);
                err = -EEXIST;
                NL_SET_BAD_ATTR(extack, nla);
                NL_SET_ERR_MSG(extack,
@@ -771,7 +771,7 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
        }
 
        err = alloc_netid(net, peer, nsid);
-       spin_unlock(&net->nsid_lock);
+       spin_unlock_bh(&net->nsid_lock);
        if (err >= 0) {
                rtnl_net_notifyid(net, RTM_NEWNSID, err, NETLINK_CB(skb).portid,
                                  nlh, GFP_KERNEL);
index 6faf73d..2b48cb0 100644 (file)
@@ -5622,7 +5622,7 @@ int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
        lse->label_stack_entry = mpls_lse;
        skb_postpush_rcsum(skb, lse, MPLS_HLEN);
 
-       if (ethernet)
+       if (ethernet && mac_len >= ETH_HLEN)
                skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto);
        skb->protocol = mpls_proto;
 
@@ -5662,7 +5662,7 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,
        skb_reset_mac_header(skb);
        skb_set_network_header(skb, mac_len);
 
-       if (ethernet) {
+       if (ethernet && mac_len >= ETH_HLEN) {
                struct ethhdr *hdr;
 
                /* use mpls_hdr() to get ethertype to account for VLANs. */
index 84dde5a..16014ad 100644 (file)
@@ -1426,6 +1426,7 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
 {
        const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
        struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
+       int prio;
        int err;
 
        if (!ops)
@@ -1475,6 +1476,13 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
                struct dcbnl_buffer *buffer =
                        nla_data(ieee[DCB_ATTR_DCB_BUFFER]);
 
+               for (prio = 0; prio < ARRAY_SIZE(buffer->prio2buffer); prio++) {
+                       if (buffer->prio2buffer[prio] >= DCBX_MAX_BUFFERS) {
+                               err = -EINVAL;
+                               goto err;
+                       }
+               }
+
                err = ops->dcbnl_setbuffer(netdev, buffer);
                if (err)
                        goto err;
index 9af1a2d..16e5f98 100644 (file)
@@ -1799,15 +1799,27 @@ int dsa_slave_create(struct dsa_port *port)
 
        dsa_slave_notify(slave_dev, DSA_PORT_REGISTER);
 
-       ret = register_netdev(slave_dev);
+       rtnl_lock();
+
+       ret = register_netdevice(slave_dev);
        if (ret) {
                netdev_err(master, "error %d registering interface %s\n",
                           ret, slave_dev->name);
+               rtnl_unlock();
                goto out_phy;
        }
 
+       ret = netdev_upper_dev_link(master, slave_dev, NULL);
+
+       rtnl_unlock();
+
+       if (ret)
+               goto out_unregister;
+
        return 0;
 
+out_unregister:
+       unregister_netdev(slave_dev);
 out_phy:
        rtnl_lock();
        phylink_disconnect_phy(p->dp->pl);
@@ -1824,16 +1836,18 @@ out_free:
 
 void dsa_slave_destroy(struct net_device *slave_dev)
 {
+       struct net_device *master = dsa_slave_to_master(slave_dev);
        struct dsa_port *dp = dsa_slave_to_port(slave_dev);
        struct dsa_slave_priv *p = netdev_priv(slave_dev);
 
        netif_carrier_off(slave_dev);
        rtnl_lock();
+       netdev_upper_dev_unlink(master, slave_dev);
+       unregister_netdevice(slave_dev);
        phylink_disconnect_phy(dp->pl);
        rtnl_unlock();
 
        dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER);
-       unregister_netdev(slave_dev);
        phylink_destroy(dp->pl);
        gro_cells_destroy(&p->gcells);
        free_percpu(p->stats64);
index 42f327c..b4fc05c 100644 (file)
@@ -160,11 +160,14 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
        packing(injection, &qos_class, 19,  17, OCELOT_TAG_LEN, PACK, 0);
 
        if (ocelot->ptp && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+               struct sk_buff *clone = DSA_SKB_CB(skb)->clone;
+
                rew_op = ocelot_port->ptp_cmd;
-               if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
-                       rew_op |= (ocelot_port->ts_id  % 4) << 3;
-                       ocelot_port->ts_id++;
-               }
+               /* Retrieve timestamp ID populated inside skb->cb[0] of the
+                * clone by ocelot_port_add_txtstamp_skb
+                */
+               if (ocelot_port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
+                       rew_op |= clone->cb[0] << 3;
 
                packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0);
        }
index 5c20727..0c3f54b 100644 (file)
@@ -866,7 +866,7 @@ static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
        [ETHNL_MCGRP_MONITOR] = { .name = ETHTOOL_MCGRP_MONITOR_NAME },
 };
 
-static struct genl_family ethtool_genl_family = {
+static struct genl_family ethtool_genl_family __ro_after_init = {
        .name           = ETHTOOL_GENL_NAME,
        .version        = ETHTOOL_GENL_VERSION,
        .netnsok        = true,
index 84f2328..d93bf2d 100644 (file)
@@ -200,7 +200,7 @@ int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info)
        reply_len = ret + ethnl_reply_header_size();
 
        rskb = ethnl_reply_init(reply_len, req_info.dev,
-                               ETHTOOL_MSG_TUNNEL_INFO_GET,
+                               ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
                                ETHTOOL_A_TUNNEL_INFO_HEADER,
                                info, &reply_payload);
        if (!rskb) {
@@ -273,7 +273,7 @@ int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
                                goto cont;
 
                        ehdr = ethnl_dump_put(skb, cb,
-                                             ETHTOOL_MSG_TUNNEL_INFO_GET);
+                                             ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY);
                        if (!ehdr) {
                                ret = -EMSGSIZE;
                                goto out;
index 06c3cd9..0e4681c 100644 (file)
@@ -76,7 +76,7 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
                proto = nla_get_u8(data[IFLA_HSR_PROTOCOL]);
 
        if (proto >= HSR_PROTOCOL_MAX) {
-               NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol\n");
+               NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol");
                return -EINVAL;
        }
 
@@ -84,14 +84,14 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
                proto_version = HSR_V0;
        } else {
                if (proto == HSR_PROTOCOL_PRP) {
-                       NL_SET_ERR_MSG_MOD(extack, "PRP version unsupported\n");
+                       NL_SET_ERR_MSG_MOD(extack, "PRP version unsupported");
                        return -EINVAL;
                }
 
                proto_version = nla_get_u8(data[IFLA_HSR_VERSION]);
                if (proto_version > HSR_V1) {
                        NL_SET_ERR_MSG_MOD(extack,
-                                          "Only HSR version 0/1 supported\n");
+                                          "Only HSR version 0/1 supported");
                        return -EINVAL;
                }
        }
index 4107949..86a23e4 100644 (file)
@@ -362,6 +362,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
        fl4.flowi4_tun_key.tun_id = 0;
        fl4.flowi4_flags = 0;
        fl4.flowi4_uid = sock_net_uid(net, NULL);
+       fl4.flowi4_multipath_hash = 0;
 
        no_addr = idev->ifa_list == NULL;
 
index 4a98dd7..f1bd95f 100644 (file)
@@ -186,8 +186,8 @@ errout:
 }
 EXPORT_SYMBOL_GPL(inet_diag_msg_attrs_fill);
 
-static void inet_diag_parse_attrs(const struct nlmsghdr *nlh, int hdrlen,
-                                 struct nlattr **req_nlas)
+static int inet_diag_parse_attrs(const struct nlmsghdr *nlh, int hdrlen,
+                                struct nlattr **req_nlas)
 {
        struct nlattr *nla;
        int remaining;
@@ -195,9 +195,13 @@ static void inet_diag_parse_attrs(const struct nlmsghdr *nlh, int hdrlen,
        nlmsg_for_each_attr(nla, nlh, hdrlen, remaining) {
                int type = nla_type(nla);
 
+               if (type == INET_DIAG_REQ_PROTOCOL && nla_len(nla) != sizeof(u32))
+                       return -EINVAL;
+
                if (type < __INET_DIAG_REQ_MAX)
                        req_nlas[type] = nla;
        }
+       return 0;
 }
 
 static int inet_diag_get_protocol(const struct inet_diag_req_v2 *req,
@@ -574,7 +578,10 @@ static int inet_diag_cmd_exact(int cmd, struct sk_buff *in_skb,
        int err, protocol;
 
        memset(&dump_data, 0, sizeof(dump_data));
-       inet_diag_parse_attrs(nlh, hdrlen, dump_data.req_nlas);
+       err = inet_diag_parse_attrs(nlh, hdrlen, dump_data.req_nlas);
+       if (err)
+               return err;
+
        protocol = inet_diag_get_protocol(req, &dump_data);
 
        handler = inet_diag_lock_handler(protocol);
@@ -1180,8 +1187,11 @@ static int __inet_diag_dump_start(struct netlink_callback *cb, int hdrlen)
        if (!cb_data)
                return -ENOMEM;
 
-       inet_diag_parse_attrs(nlh, hdrlen, cb_data->req_nlas);
-
+       err = inet_diag_parse_attrs(nlh, hdrlen, cb_data->req_nlas);
+       if (err) {
+               kfree(cb_data);
+               return err;
+       }
        nla = cb_data->inet_diag_nla_bc;
        if (nla) {
                err = inet_diag_bc_audit(nla, skb);
index 61f802d..e6f2ada 100644 (file)
@@ -74,6 +74,7 @@
 #include <net/icmp.h>
 #include <net/checksum.h>
 #include <net/inetpeer.h>
+#include <net/inet_ecn.h>
 #include <net/lwtunnel.h>
 #include <linux/bpf-cgroup.h>
 #include <linux/igmp.h>
@@ -1703,7 +1704,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
        if (IS_ERR(rt))
                return;
 
-       inet_sk(sk)->tos = arg->tos;
+       inet_sk(sk)->tos = arg->tos & ~INET_ECN_MASK;
 
        sk->sk_protocol = ip_hdr(skb)->protocol;
        sk->sk_bound_dev_if = arg->bound_dev_if;
index 75c6013..b2ea1a8 100644 (file)
@@ -554,6 +554,7 @@ static int ip_tun_parse_opts_vxlan(struct nlattr *attr,
 
                attr = tb[LWTUNNEL_IP_OPT_VXLAN_GBP];
                md->gbp = nla_get_u32(attr);
+               md->gbp &= VXLAN_GBP_MASK;
                info->key.tun_flags |= TUNNEL_VXLAN_OPT;
        }
 
index 49daaed..f687abb 100644 (file)
@@ -490,6 +490,7 @@ static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
        .priority       =       0,
 };
 
+#if IS_ENABLED(CONFIG_IPV6)
 static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
        .handler        =       vti_rcv_tunnel,
        .cb_handler     =       vti_rcv_cb,
@@ -497,6 +498,7 @@ static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
        .priority       =       0,
 };
 #endif
+#endif
 
 static int __net_init vti_init_net(struct net *net)
 {
index 1074df7..8d5e169 100644 (file)
@@ -293,6 +293,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TcpTimeoutRehash", LINUX_MIB_TCPTIMEOUTREHASH),
        SNMP_MIB_ITEM("TcpDuplicateDataRehash", LINUX_MIB_TCPDUPLICATEDATAREHASH),
        SNMP_MIB_ITEM("TCPDSACKRecvSegs", LINUX_MIB_TCPDSACKRECVSEGS),
+       SNMP_MIB_ITEM("TCPDSACKIgnoredDubious", LINUX_MIB_TCPDSACKIGNOREDDUBIOUS),
        SNMP_MIB_SENTINEL
 };
 
index 8ca6bca..58642b2 100644 (file)
@@ -786,8 +786,10 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
                        neigh_event_send(n, NULL);
                } else {
                        if (fib_lookup(net, fl4, &res, 0) == 0) {
-                               struct fib_nh_common *nhc = FIB_RES_NHC(res);
+                               struct fib_nh_common *nhc;
 
+                               fib_select_path(net, &res, fl4, skb);
+                               nhc = FIB_RES_NHC(res);
                                update_or_create_fnhe(nhc, fl4->daddr, new_gw,
                                                0, false,
                                                jiffies + ip_rt_gc_timeout);
@@ -1013,6 +1015,7 @@ out:      kfree_skb(skb);
 static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 {
        struct dst_entry *dst = &rt->dst;
+       struct net *net = dev_net(dst->dev);
        u32 old_mtu = ipv4_mtu(dst);
        struct fib_result res;
        bool lock = false;
@@ -1033,9 +1036,11 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
                return;
 
        rcu_read_lock();
-       if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
-               struct fib_nh_common *nhc = FIB_RES_NHC(res);
+       if (fib_lookup(net, fl4, &res, 0) == 0) {
+               struct fib_nh_common *nhc;
 
+               fib_select_path(net, &res, fl4, NULL);
+               nhc = FIB_RES_NHC(res);
                update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock,
                                      jiffies + ip_rt_mtu_expires);
        }
@@ -2147,6 +2152,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        fl4.flowi4_uid = sock_net_uid(net, NULL);
+       fl4.flowi4_multipath_hash = 0;
 
        if (fib4_rules_early_flow_dissect(net, skb, &fl4, &_flkeys)) {
                flkeys = &_flkeys;
@@ -2667,8 +2673,6 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
        fib_select_path(net, res, fl4, skb);
 
        dev_out = FIB_RES_DEV(*res);
-       fl4->flowi4_oif = dev_out->ifindex;
-
 
 make_route:
        rth = __mkroute_output(res, fl4, orig_oif, dev_out, flags);
index f0794f0..e037566 100644 (file)
@@ -214,7 +214,7 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
                sock_rps_save_rxhash(child, skb);
 
                if (rsk_drop_req(req)) {
-                       refcount_set(&req->rsk_refcnt, 2);
+                       reqsk_put(req);
                        return child;
                }
 
index 31f3b85..2135ee7 100644 (file)
@@ -970,7 +970,8 @@ ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
        long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
 
        if (IS_ENABLED(CONFIG_DEBUG_VM) &&
-           WARN_ONCE(PageSlab(page), "page must not be a Slab one"))
+           WARN_ONCE(!sendpage_ok(page),
+                     "page must not be a Slab one and have page_count > 0"))
                return -EINVAL;
 
        /* Wait for a connection to finish. One exception is TCP Fast Open
index 184ea55..b1ce205 100644 (file)
@@ -885,21 +885,34 @@ struct tcp_sacktag_state {
        struct rate_sample *rate;
 };
 
-/* Take a notice that peer is sending D-SACKs */
+/* Take a notice that peer is sending D-SACKs. Skip update of data delivery
+ * and spurious retransmission information if this DSACK is unlikely caused by
+ * sender's action:
+ * - DSACKed sequence range is larger than maximum receiver's window.
+ * - Total no. of DSACKed segments exceed the total no. of retransmitted segs.
+ */
 static u32 tcp_dsack_seen(struct tcp_sock *tp, u32 start_seq,
                          u32 end_seq, struct tcp_sacktag_state *state)
 {
        u32 seq_len, dup_segs = 1;
 
-       if (before(start_seq, end_seq)) {
-               seq_len = end_seq - start_seq;
-               if (seq_len > tp->mss_cache)
-                       dup_segs = DIV_ROUND_UP(seq_len, tp->mss_cache);
-       }
+       if (!before(start_seq, end_seq))
+               return 0;
+
+       seq_len = end_seq - start_seq;
+       /* Dubious DSACK: DSACKed range greater than maximum advertised rwnd */
+       if (seq_len > tp->max_window)
+               return 0;
+       if (seq_len > tp->mss_cache)
+               dup_segs = DIV_ROUND_UP(seq_len, tp->mss_cache);
+
+       tp->dsack_dups += dup_segs;
+       /* Skip the DSACK if dup segs weren't retransmitted by sender */
+       if (tp->dsack_dups > tp->total_retrans)
+               return 0;
 
        tp->rx_opt.sack_ok |= TCP_DSACK_SEEN;
        tp->rack.dsack_seen = 1;
-       tp->dsack_dups += dup_segs;
 
        state->flag |= FLAG_DSACKING_ACK;
        /* A spurious retransmission is delivered */
@@ -1153,6 +1166,11 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb,
        }
 
        dup_segs = tcp_dsack_seen(tp, start_seq_0, end_seq_0, state);
+       if (!dup_segs) {        /* Skip dubious DSACK */
+               NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKIGNOREDDUBIOUS);
+               return false;
+       }
+
        NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDSACKRECVSEGS, dup_segs);
 
        /* D-SACK for already forgotten data... Do dumb counting. */
index 5084333..592c739 100644 (file)
@@ -1788,12 +1788,12 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
 
        __skb_pull(skb, hdrlen);
        if (skb_try_coalesce(tail, skb, &fragstolen, &delta)) {
-               thtail->window = th->window;
-
                TCP_SKB_CB(tail)->end_seq = TCP_SKB_CB(skb)->end_seq;
 
-               if (after(TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(tail)->ack_seq))
+               if (likely(!before(TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(tail)->ack_seq))) {
                        TCP_SKB_CB(tail)->ack_seq = TCP_SKB_CB(skb)->ack_seq;
+                       thtail->window = th->window;
+               }
 
                /* We have to update both TCP_SKB_CB(tail)->tcp_flags and
                 * thtail->fin, so that the fast path in tcp_rcv_established()
index 76bff79..747f56e 100644 (file)
@@ -303,6 +303,7 @@ config IPV6_SEG6_LWTUNNEL
 config IPV6_SEG6_HMAC
        bool "IPv6: Segment Routing HMAC support"
        depends on IPV6
+       select CRYPTO
        select CRYPTO_HMAC
        select CRYPTO_SHA1
        select CRYPTO_SHA256
index 25a90f3..4a664ad 100644 (file)
@@ -1993,14 +1993,19 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
 /* Need to own table->tb6_lock */
 int fib6_del(struct fib6_info *rt, struct nl_info *info)
 {
-       struct fib6_node *fn = rcu_dereference_protected(rt->fib6_node,
-                                   lockdep_is_held(&rt->fib6_table->tb6_lock));
-       struct fib6_table *table = rt->fib6_table;
        struct net *net = info->nl_net;
        struct fib6_info __rcu **rtp;
        struct fib6_info __rcu **rtp_next;
+       struct fib6_table *table;
+       struct fib6_node *fn;
+
+       if (rt == net->ipv6.fib6_null_entry)
+               return -ENOENT;
 
-       if (!fn || rt == net->ipv6.fib6_null_entry)
+       table = rt->fib6_table;
+       fn = rcu_dereference_protected(rt->fib6_node,
+                                      lockdep_is_held(&table->tb6_lock));
+       if (!fn)
                return -ENOENT;
 
        WARN_ON(!(fn->fn_flags & RTN_RTINFO));
index 5e7e25e..fb075d9 100644 (file)
@@ -4202,7 +4202,7 @@ static struct fib6_info *rt6_add_route_info(struct net *net,
                .fc_nlinfo.nl_net = net,
        };
 
-       cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO,
+       cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO;
        cfg.fc_dst = *prefix;
        cfg.fc_gateway = *gwaddr;
 
index 3149730..26d2f8b 100644 (file)
@@ -560,7 +560,9 @@ static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat,
        if (rate->idx < 0 || !rate->count)
                return -1;
 
-       if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+       if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+               stat->bw = RATE_INFO_BW_160;
+       else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
                stat->bw = RATE_INFO_BW_80;
        else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
                stat->bw = RATE_INFO_BW_40;
@@ -668,20 +670,26 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
                 * This will not be very accurate, but much better than simply
                 * assuming un-aggregated tx in all cases.
                 */
-               if (duration > 400) /* <= VHT20 MCS2 1S */
+               if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
                        agg_shift = 1;
-               else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */
+               else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
                        agg_shift = 2;
-               else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */
+               else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
                        agg_shift = 3;
-               else
+               else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
                        agg_shift = 4;
+               else if (stat.encoding != RX_ENC_HE ||
+                        duration > 20 * 1024) /* <= HE40 MCS6 2S */
+                       agg_shift = 5;
+               else
+                       agg_shift = 6;
 
                duration *= len;
                duration /= AVG_PKT_SIZE;
                duration /= 1024;
+               duration += (overhead >> agg_shift);
 
-               return duration + (overhead >> agg_shift);
+               return max_t(u32, duration, 4);
        }
 
        if (!conf)
index ac87030..2e400b0 100644 (file)
@@ -4861,6 +4861,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_supported_band *sband;
        struct cfg80211_chan_def chandef;
        bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
+       bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ;
        struct ieee80211_bss *bss = (void *)cbss->priv;
        int ret;
        u32 i;
@@ -4879,7 +4880,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
        }
 
-       if (!sband->vht_cap.vht_supported && !is_6ghz) {
+       if (!sband->vht_cap.vht_supported && is_5ghz) {
                ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
                ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
        }
index 836cde5..a959ebf 100644 (file)
@@ -451,7 +451,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        else if (status->bw == RATE_INFO_BW_5)
                channel_flags |= IEEE80211_CHAN_QUARTER;
 
-       if (status->band == NL80211_BAND_5GHZ)
+       if (status->band == NL80211_BAND_5GHZ ||
+           status->band == NL80211_BAND_6GHZ)
                channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ;
        else if (status->encoding != RX_ENC_LEGACY)
                channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
index c8504ff..8d3bfc0 100644 (file)
@@ -3353,9 +3353,10 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
                he_chandef.center_freq1 =
                        ieee80211_channel_to_frequency(he_6ghz_oper->ccfs0,
                                                       NL80211_BAND_6GHZ);
-               he_chandef.center_freq2 =
-                       ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1,
-                                                      NL80211_BAND_6GHZ);
+               if (support_80_80 || support_160)
+                       he_chandef.center_freq2 =
+                               ieee80211_channel_to_frequency(he_6ghz_oper->ccfs1,
+                                                              NL80211_BAND_6GHZ);
        }
 
        if (!cfg80211_chandef_valid(&he_chandef)) {
index 9c6045f..d1b64d0 100644 (file)
@@ -168,10 +168,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
        /* take some capabilities as-is */
        cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info);
        vht_cap->cap = cap_info;
-       vht_cap->cap &= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
-                       IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
-                       IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
-                       IEEE80211_VHT_CAP_RXLDPC |
+       vht_cap->cap &= IEEE80211_VHT_CAP_RXLDPC |
                        IEEE80211_VHT_CAP_VHT_TXOP_PS |
                        IEEE80211_VHT_CAP_HTC_VHT |
                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
@@ -180,6 +177,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
                        IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
                        IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
 
+       vht_cap->cap |= min_t(u32, cap_info & IEEE80211_VHT_CAP_MAX_MPDU_MASK,
+                             own_cap.cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK);
+
        /* and some based on our own capabilities */
        switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
        case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
index ab52811..c829e4a 100644 (file)
@@ -34,11 +34,11 @@ void ieee802154_xmit_worker(struct work_struct *work)
        if (res)
                goto err_tx;
 
-       ieee802154_xmit_complete(&local->hw, skb, false);
-
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += skb->len;
 
+       ieee802154_xmit_complete(&local->hw, skb, false);
+
        return;
 
 err_tx:
@@ -78,6 +78,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
 
        /* async is priority, otherwise sync is fallback */
        if (local->ops->xmit_async) {
+               unsigned int len = skb->len;
+
                ret = drv_xmit_async(local, skb);
                if (ret) {
                        ieee802154_wake_queue(&local->hw);
@@ -85,7 +87,7 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
                }
 
                dev->stats.tx_packets++;
-               dev->stats.tx_bytes += skb->len;
+               dev->stats.tx_bytes += len;
        } else {
                local->tx_skb = skb;
                queue_work(local->workqueue, &local->tx_work);
index 7fa822b..888bbbb 100644 (file)
@@ -451,7 +451,10 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
 static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
                                 struct sk_buff *skb, struct mptcp_ext *ext)
 {
-       u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq);
+       /* The write_seq value has already been incremented, so the actual
+        * sequence number for the DATA_FIN is one less.
+        */
+       u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq) - 1;
 
        if (!ext->use_map || !skb->len) {
                /* RFC6824 requires a DSS mapping with specific values
@@ -460,10 +463,7 @@ static void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
                ext->data_fin = 1;
                ext->use_map = 1;
                ext->dsn64 = 1;
-               /* The write_seq value has already been incremented, so
-                * the actual sequence number for the DATA_FIN is one less.
-                */
-               ext->data_seq = data_fin_tx_seq - 1;
+               ext->data_seq = data_fin_tx_seq;
                ext->subflow_seq = 0;
                ext->data_len = 1;
        } else if (ext->data_seq + ext->data_len == data_fin_tx_seq) {
@@ -518,11 +518,11 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
 
        if (subflow->use_64bit_ack) {
                ack_size = TCPOLEN_MPTCP_DSS_ACK64;
-               opts->ext_copy.data_ack = msk->ack_seq;
+               opts->ext_copy.data_ack = READ_ONCE(msk->ack_seq);
                opts->ext_copy.ack64 = 1;
        } else {
                ack_size = TCPOLEN_MPTCP_DSS_ACK32;
-               opts->ext_copy.data_ack32 = (uint32_t)(msk->ack_seq);
+               opts->ext_copy.data_ack32 = (uint32_t)READ_ONCE(msk->ack_seq);
                opts->ext_copy.ack64 = 0;
        }
        opts->ext_copy.use_ack = 1;
@@ -782,7 +782,7 @@ static void update_una(struct mptcp_sock *msk,
        }
 }
 
-bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq)
+bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit)
 {
        /* Skip if DATA_FIN was already received.
         * If updating simultaneously with the recvmsg loop, values
@@ -792,7 +792,8 @@ bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq)
        if (READ_ONCE(msk->rcv_data_fin) || !READ_ONCE(msk->first))
                return false;
 
-       WRITE_ONCE(msk->rcv_data_fin_seq, data_fin_seq);
+       WRITE_ONCE(msk->rcv_data_fin_seq,
+                  expand_ack(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
        WRITE_ONCE(msk->rcv_data_fin, 1);
 
        return true;
@@ -875,7 +876,7 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
         */
        if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
                if (mp_opt.data_fin && mp_opt.data_len == 1 &&
-                   mptcp_update_rcv_data_fin(msk, mp_opt.data_seq) &&
+                   mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64) &&
                    schedule_work(&msk->work))
                        sock_hold(subflow->conn);
 
index c8820c4..770da36 100644 (file)
@@ -66,6 +66,16 @@ static bool addresses_equal(const struct mptcp_addr_info *a,
        return a->port == b->port;
 }
 
+static bool address_zero(const struct mptcp_addr_info *addr)
+{
+       struct mptcp_addr_info zero;
+
+       memset(&zero, 0, sizeof(zero));
+       zero.family = addr->family;
+
+       return addresses_equal(addr, &zero, false);
+}
+
 static void local_address(const struct sock_common *skc,
                          struct mptcp_addr_info *addr)
 {
@@ -171,9 +181,9 @@ static void check_work_pending(struct mptcp_sock *msk)
 
 static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
 {
+       struct mptcp_addr_info remote = { 0 };
        struct sock *sk = (struct sock *)msk;
        struct mptcp_pm_addr_entry *local;
-       struct mptcp_addr_info remote;
        struct pm_nl_pernet *pernet;
 
        pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
@@ -323,10 +333,13 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
         * addr
         */
        local_address((struct sock_common *)msk, &msk_local);
-       local_address((struct sock_common *)msk, &skc_local);
+       local_address((struct sock_common *)skc, &skc_local);
        if (addresses_equal(&msk_local, &skc_local, false))
                return 0;
 
+       if (address_zero(&skc_local))
+               return 0;
+
        pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
 
        rcu_read_lock();
@@ -341,7 +354,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
                return ret;
 
        /* address not found, add to local list */
-       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
        if (!entry)
                return -ENOMEM;
 
index 365ba96..5d747c6 100644 (file)
@@ -123,7 +123,7 @@ static void __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
 
        skb_ext_reset(skb);
        skb_orphan(skb);
-       msk->ack_seq += copy_len;
+       WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
 
        tail = skb_peek_tail(&sk->sk_receive_queue);
        if (offset == 0 && tail) {
@@ -261,7 +261,7 @@ static void mptcp_check_data_fin(struct sock *sk)
        if (mptcp_pending_data_fin(sk, &rcv_data_fin_seq)) {
                struct mptcp_subflow_context *subflow;
 
-               msk->ack_seq++;
+               WRITE_ONCE(msk->ack_seq, msk->ack_seq + 1);
                WRITE_ONCE(msk->rcv_data_fin, 0);
 
                sk->sk_shutdown |= RCV_SHUTDOWN;
@@ -1720,7 +1720,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
                msk->remote_key = mp_opt->sndr_key;
                mptcp_crypto_key_sha(msk->remote_key, NULL, &ack_seq);
                ack_seq++;
-               msk->ack_seq = ack_seq;
+               WRITE_ONCE(msk->ack_seq, ack_seq);
        }
 
        sock_reset_flag(nsk, SOCK_RCU_FREE);
@@ -2072,7 +2072,7 @@ bool mptcp_finish_join(struct sock *sk)
        parent_sock = READ_ONCE(parent->sk_socket);
        if (parent_sock && !sk->sk_socket)
                mptcp_sock_graft(sk, parent_sock);
-       subflow->map_seq = msk->ack_seq;
+       subflow->map_seq = READ_ONCE(msk->ack_seq);
        return true;
 }
 
index 60b27d4..20f04ac 100644 (file)
@@ -387,7 +387,7 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk);
 bool mptcp_finish_join(struct sock *sk);
 void mptcp_data_acked(struct sock *sk);
 void mptcp_subflow_eof(struct sock *sk);
-bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq);
+bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);
 
 void __init mptcp_token_init(void);
 static inline void mptcp_token_init_request(struct request_sock *req)
index e8cac26..6f035af 100644 (file)
@@ -731,7 +731,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
 
        if (mpext->data_fin == 1) {
                if (data_len == 1) {
-                       mptcp_update_rcv_data_fin(msk, mpext->data_seq);
+                       bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,
+                                                                mpext->dsn64);
                        pr_debug("DATA_FIN with no payload seq=%llu", mpext->data_seq);
                        if (subflow->map_valid) {
                                /* A DATA_FIN might arrive in a DSS
@@ -742,11 +743,23 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
                                skb_ext_del(skb, SKB_EXT_MPTCP);
                                return MAPPING_OK;
                        } else {
+                               if (updated && schedule_work(&msk->work))
+                                       sock_hold((struct sock *)msk);
+
                                return MAPPING_DATA_FIN;
                        }
                } else {
-                       mptcp_update_rcv_data_fin(msk, mpext->data_seq + data_len);
-                       pr_debug("DATA_FIN with mapping seq=%llu", mpext->data_seq + data_len);
+                       u64 data_fin_seq = mpext->data_seq + data_len - 1;
+
+                       /* If mpext->data_seq is a 32-bit value, data_fin_seq
+                        * must also be limited to 32 bits.
+                        */
+                       if (!mpext->dsn64)
+                               data_fin_seq &= GENMASK_ULL(31, 0);
+
+                       mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
+                       pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d",
+                                data_fin_seq, mpext->dsn64);
                }
 
                /* Adjust for DATA_FIN using 1 byte of sequence space */
@@ -1063,6 +1076,7 @@ int __mptcp_subflow_connect(struct sock *sk, int ifindex,
        struct mptcp_sock *msk = mptcp_sk(sk);
        struct mptcp_subflow_context *subflow;
        struct sockaddr_storage addr;
+       int remote_id = remote->id;
        int local_id = loc->id;
        struct socket *sf;
        struct sock *ssk;
@@ -1107,10 +1121,11 @@ int __mptcp_subflow_connect(struct sock *sk, int ifindex,
                goto failed;
 
        mptcp_crypto_key_sha(subflow->remote_key, &remote_token, NULL);
-       pr_debug("msk=%p remote_token=%u local_id=%d", msk, remote_token,
-                local_id);
+       pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d", msk,
+                remote_token, local_id, remote_id);
        subflow->remote_token = remote_token;
        subflow->local_id = local_id;
+       subflow->remote_id = remote_id;
        subflow->request_join = 1;
        subflow->request_bkup = 1;
        mptcp_info2sockaddr(remote, &addr);
@@ -1347,6 +1362,7 @@ static void subflow_ulp_clone(const struct request_sock *req,
                new_ctx->fully_established = 1;
                new_ctx->backup = subflow_req->backup;
                new_ctx->local_id = subflow_req->local_id;
+               new_ctx->remote_id = subflow_req->remote_id;
                new_ctx->token = subflow_req->token;
                new_ctx->thmac = subflow_req->thmac;
        }
index 832eabe..c3a4214 100644 (file)
@@ -851,7 +851,6 @@ static int ctnetlink_done(struct netlink_callback *cb)
 }
 
 struct ctnetlink_filter {
-       u_int32_t cta_flags;
        u8 family;
 
        u_int32_t orig_flags;
@@ -906,10 +905,6 @@ static int ctnetlink_parse_tuple_filter(const struct nlattr * const cda[],
                                         struct nf_conntrack_zone *zone,
                                         u_int32_t flags);
 
-/* applied on filters */
-#define CTA_FILTER_F_CTA_MARK                  (1 << 0)
-#define CTA_FILTER_F_CTA_MARK_MASK             (1 << 1)
-
 static struct ctnetlink_filter *
 ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
 {
@@ -930,14 +925,10 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
 #ifdef CONFIG_NF_CONNTRACK_MARK
        if (cda[CTA_MARK]) {
                filter->mark.val = ntohl(nla_get_be32(cda[CTA_MARK]));
-               filter->cta_flags |= CTA_FILTER_FLAG(CTA_MARK);
-
-               if (cda[CTA_MARK_MASK]) {
+               if (cda[CTA_MARK_MASK])
                        filter->mark.mask = ntohl(nla_get_be32(cda[CTA_MARK_MASK]));
-                       filter->cta_flags |= CTA_FILTER_FLAG(CTA_MARK_MASK);
-               } else {
+               else
                        filter->mark.mask = 0xffffffff;
-               }
        } else if (cda[CTA_MARK_MASK]) {
                err = -EINVAL;
                goto err_filter;
@@ -1117,11 +1108,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
        }
 
 #ifdef CONFIG_NF_CONNTRACK_MARK
-       if ((filter->cta_flags & CTA_FILTER_FLAG(CTA_MARK_MASK)) &&
-           (ct->mark & filter->mark.mask) != filter->mark.val)
-               goto ignore_entry;
-       else if ((filter->cta_flags & CTA_FILTER_FLAG(CTA_MARK)) &&
-                ct->mark != filter->mark.val)
+       if ((ct->mark & filter->mark.mask) != filter->mark.val)
                goto ignore_entry;
 #endif
 
@@ -1404,7 +1391,8 @@ ctnetlink_parse_tuple_filter(const struct nlattr * const cda[],
        if (err < 0)
                return err;
 
-
+       if (l3num != NFPROTO_IPV4 && l3num != NFPROTO_IPV6)
+               return -EOPNOTSUPP;
        tuple->src.l3num = l3num;
 
        if (flags & CTA_FILTER_FLAG(CTA_IP_DST) ||
index 95f7998..47e9319 100644 (file)
@@ -565,6 +565,7 @@ static int nf_ct_netns_inet_get(struct net *net)
        int err;
 
        err = nf_ct_netns_do_get(net, NFPROTO_IPV4);
+#if IS_ENABLED(CONFIG_IPV6)
        if (err < 0)
                goto err1;
        err = nf_ct_netns_do_get(net, NFPROTO_IPV6);
@@ -575,6 +576,7 @@ static int nf_ct_netns_inet_get(struct net *net)
 err2:
        nf_ct_netns_put(net, NFPROTO_IPV4);
 err1:
+#endif
        return err;
 }
 
index b7dc1cb..4603b66 100644 (file)
@@ -684,6 +684,18 @@ nla_put_failure:
        return -1;
 }
 
+struct nftnl_skb_parms {
+       bool report;
+};
+#define NFT_CB(skb)    (*(struct nftnl_skb_parms*)&((skb)->cb))
+
+static void nft_notify_enqueue(struct sk_buff *skb, bool report,
+                              struct list_head *notify_list)
+{
+       NFT_CB(skb).report = report;
+       list_add_tail(&skb->list, notify_list);
+}
+
 static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
 {
        struct sk_buff *skb;
@@ -715,8 +727,7 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
                goto err;
        }
 
-       nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
-                      ctx->report, GFP_KERNEL);
+       nft_notify_enqueue(skb, ctx->report, &ctx->net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -1468,8 +1479,7 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
                goto err;
        }
 
-       nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
-                      ctx->report, GFP_KERNEL);
+       nft_notify_enqueue(skb, ctx->report, &ctx->net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -2807,8 +2817,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
-                      ctx->report, GFP_KERNEL);
+       nft_notify_enqueue(skb, ctx->report, &ctx->net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -3837,8 +3846,7 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nfnetlink_send(skb, ctx->net, portid, NFNLGRP_NFTABLES, ctx->report,
-                      gfp_flags);
+       nft_notify_enqueue(skb, ctx->report, &ctx->net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -4959,8 +4967,7 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, ctx->report,
-                      GFP_KERNEL);
+       nft_notify_enqueue(skb, ctx->report, &ctx->net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -6275,7 +6282,7 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
                goto err;
        }
 
-       nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
+       nft_notify_enqueue(skb, report, &net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -7085,8 +7092,7 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
                goto err;
        }
 
-       nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES,
-                      ctx->report, GFP_KERNEL);
+       nft_notify_enqueue(skb, ctx->report, &ctx->net->nft.notify_list);
        return;
 err:
        nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
@@ -7695,6 +7701,41 @@ static void nf_tables_commit_release(struct net *net)
        mutex_unlock(&net->nft.commit_mutex);
 }
 
+static void nft_commit_notify(struct net *net, u32 portid)
+{
+       struct sk_buff *batch_skb = NULL, *nskb, *skb;
+       unsigned char *data;
+       int len;
+
+       list_for_each_entry_safe(skb, nskb, &net->nft.notify_list, list) {
+               if (!batch_skb) {
+new_batch:
+                       batch_skb = skb;
+                       len = NLMSG_GOODSIZE - skb->len;
+                       list_del(&skb->list);
+                       continue;
+               }
+               len -= skb->len;
+               if (len > 0 && NFT_CB(skb).report == NFT_CB(batch_skb).report) {
+                       data = skb_put(batch_skb, skb->len);
+                       memcpy(data, skb->data, skb->len);
+                       list_del(&skb->list);
+                       kfree_skb(skb);
+                       continue;
+               }
+               nfnetlink_send(batch_skb, net, portid, NFNLGRP_NFTABLES,
+                              NFT_CB(batch_skb).report, GFP_KERNEL);
+               goto new_batch;
+       }
+
+       if (batch_skb) {
+               nfnetlink_send(batch_skb, net, portid, NFNLGRP_NFTABLES,
+                              NFT_CB(batch_skb).report, GFP_KERNEL);
+       }
+
+       WARN_ON_ONCE(!list_empty(&net->nft.notify_list));
+}
+
 static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 {
        struct nft_trans *trans, *next;
@@ -7897,6 +7938,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                }
        }
 
+       nft_commit_notify(net, NETLINK_CB(skb).portid);
        nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
        nf_tables_commit_release(net);
 
@@ -8721,6 +8763,7 @@ static int __net_init nf_tables_init_net(struct net *net)
        INIT_LIST_HEAD(&net->nft.tables);
        INIT_LIST_HEAD(&net->nft.commit_list);
        INIT_LIST_HEAD(&net->nft.module_list);
+       INIT_LIST_HEAD(&net->nft.notify_list);
        mutex_init(&net->nft.commit_mutex);
        net->nft.base_seq = 1;
        net->nft.validate_state = NFT_VALIDATE_SKIP;
@@ -8737,6 +8780,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
        mutex_unlock(&net->nft.commit_mutex);
        WARN_ON_ONCE(!list_empty(&net->nft.tables));
        WARN_ON_ONCE(!list_empty(&net->nft.module_list));
+       WARN_ON_ONCE(!list_empty(&net->nft.notify_list));
 }
 
 static struct pernet_operations nf_tables_net_ops = {
index 7bc6537..b37bd02 100644 (file)
@@ -147,11 +147,11 @@ nft_meta_get_eval_skugid(enum nft_meta_keys key,
 
        switch (key) {
        case NFT_META_SKUID:
-               *dest = from_kuid_munged(&init_user_ns,
+               *dest = from_kuid_munged(sock_net(sk)->user_ns,
                                         sock->file->f_cred->fsuid);
                break;
        case NFT_META_SKGID:
-               *dest = from_kgid_munged(&init_user_ns,
+               *dest = from_kgid_munged(sock_net(sk)->user_ns,
                                         sock->file->f_cred->fsgid);
                break;
        default:
index 1eb65a7..c4b4d33 100644 (file)
@@ -1079,7 +1079,7 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
        if (err)
                return err;
 
-       while (netlink_policy_dump_loop(&cb->args[1])) {
+       while (netlink_policy_dump_loop(cb->args[1])) {
                void *hdr;
                struct nlattr *nest;
 
@@ -1113,6 +1113,12 @@ nla_put_failure:
        return skb->len;
 }
 
+static int ctrl_dumppolicy_done(struct netlink_callback *cb)
+{
+       netlink_policy_dump_free(cb->args[1]);
+       return 0;
+}
+
 static const struct genl_ops genl_ctrl_ops[] = {
        {
                .cmd            = CTRL_CMD_GETFAMILY,
@@ -1123,6 +1129,7 @@ static const struct genl_ops genl_ctrl_ops[] = {
        {
                .cmd            = CTRL_CMD_GETPOLICY,
                .dumpit         = ctrl_dumppolicy,
+               .done           = ctrl_dumppolicy_done,
        },
 };
 
index 641ffbd..0176b59 100644 (file)
@@ -84,7 +84,6 @@ int netlink_policy_dump_start(const struct nla_policy *policy,
        unsigned int policy_idx;
        int err;
 
-       /* also returns 0 if "*_state" is our ERR_PTR() end marker */
        if (*_state)
                return 0;
 
@@ -140,21 +139,11 @@ static bool netlink_policy_dump_finished(struct nl_policy_dump *state)
               !state->policies[state->policy_idx].policy;
 }
 
-bool netlink_policy_dump_loop(unsigned long *_state)
+bool netlink_policy_dump_loop(unsigned long _state)
 {
-       struct nl_policy_dump *state = (void *)*_state;
-
-       if (IS_ERR(state))
-               return false;
-
-       if (netlink_policy_dump_finished(state)) {
-               kfree(state);
-               /* store end marker instead of freed state */
-               *_state = (unsigned long)ERR_PTR(-ENOENT);
-               return false;
-       }
+       struct nl_policy_dump *state = (void *)_state;
 
-       return true;
+       return !netlink_policy_dump_finished(state);
 }
 
 int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
@@ -309,3 +298,10 @@ nla_put_failure:
        nla_nest_cancel(skb, policy);
        return -ENOBUFS;
 }
+
+void netlink_policy_dump_free(unsigned long _state)
+{
+       struct nl_policy_dump *state = (void *)_state;
+
+       kfree(state);
+}
index a3f1204..12d42ab 100644 (file)
@@ -905,15 +905,19 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
        }
        err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);
 
-       if (err == NF_ACCEPT &&
-           ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
-               if (maniptype == NF_NAT_MANIP_SRC)
-                       maniptype = NF_NAT_MANIP_DST;
-               else
-                       maniptype = NF_NAT_MANIP_SRC;
-
-               err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
-                                        maniptype);
+       if (err == NF_ACCEPT && ct->status & IPS_DST_NAT) {
+               if (ct->status & IPS_SRC_NAT) {
+                       if (maniptype == NF_NAT_MANIP_SRC)
+                               maniptype = NF_NAT_MANIP_DST;
+                       else
+                               maniptype = NF_NAT_MANIP_SRC;
+
+                       err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
+                                                maniptype);
+               } else if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
+                       err = ovs_ct_nat_execute(skb, ct, ctinfo, NULL,
+                                                NF_NAT_MANIP_SRC);
+               }
        }
 
        /* Mark NAT done if successful and update the flow key. */
index d8252fd..b8559c8 100644 (file)
@@ -199,17 +199,30 @@ static int announce_servers(struct sockaddr_qrtr *sq)
        if (!node)
                return 0;
 
+       rcu_read_lock();
        /* Announce the list of servers registered in this node */
        radix_tree_for_each_slot(slot, &node->servers, &iter, 0) {
                srv = radix_tree_deref_slot(slot);
+               if (!srv)
+                       continue;
+               if (radix_tree_deref_retry(srv)) {
+                       slot = radix_tree_iter_retry(&iter);
+                       continue;
+               }
+               slot = radix_tree_iter_resume(slot, &iter);
+               rcu_read_unlock();
 
                ret = service_announce_new(sq, srv);
                if (ret < 0) {
                        pr_err("failed to announce new service\n");
                        return ret;
                }
+
+               rcu_read_lock();
        }
 
+       rcu_read_unlock();
+
        return 0;
 }
 
@@ -344,11 +357,22 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
        if (!node)
                return 0;
 
+       rcu_read_lock();
        /* Advertise removal of this client to all servers of remote node */
        radix_tree_for_each_slot(slot, &node->servers, &iter, 0) {
                srv = radix_tree_deref_slot(slot);
+               if (!srv)
+                       continue;
+               if (radix_tree_deref_retry(srv)) {
+                       slot = radix_tree_iter_retry(&iter);
+                       continue;
+               }
+               slot = radix_tree_iter_resume(slot, &iter);
+               rcu_read_unlock();
                server_del(node, srv->port);
+               rcu_read_lock();
        }
+       rcu_read_unlock();
 
        /* Advertise the removal of this client to all local servers */
        local_node = node_get(qrtr_ns.local_node);
@@ -359,8 +383,17 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
        pkt.cmd = cpu_to_le32(QRTR_TYPE_BYE);
        pkt.client.node = cpu_to_le32(from->sq_node);
 
+       rcu_read_lock();
        radix_tree_for_each_slot(slot, &local_node->servers, &iter, 0) {
                srv = radix_tree_deref_slot(slot);
+               if (!srv)
+                       continue;
+               if (radix_tree_deref_retry(srv)) {
+                       slot = radix_tree_iter_retry(&iter);
+                       continue;
+               }
+               slot = radix_tree_iter_resume(slot, &iter);
+               rcu_read_unlock();
 
                sq.sq_family = AF_QIPCRTR;
                sq.sq_node = srv->node;
@@ -374,8 +407,11 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
                        pr_err("failed to send bye cmd\n");
                        return ret;
                }
+               rcu_read_lock();
        }
 
+       rcu_read_unlock();
+
        return 0;
 }
 
@@ -434,8 +470,17 @@ static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
        pkt.client.node = cpu_to_le32(node_id);
        pkt.client.port = cpu_to_le32(port);
 
+       rcu_read_lock();
        radix_tree_for_each_slot(slot, &local_node->servers, &iter, 0) {
                srv = radix_tree_deref_slot(slot);
+               if (!srv)
+                       continue;
+               if (radix_tree_deref_retry(srv)) {
+                       slot = radix_tree_iter_retry(&iter);
+                       continue;
+               }
+               slot = radix_tree_iter_resume(slot, &iter);
+               rcu_read_unlock();
 
                sq.sq_family = AF_QIPCRTR;
                sq.sq_node = srv->node;
@@ -449,8 +494,11 @@ static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
                        pr_err("failed to send del client cmd\n");
                        return ret;
                }
+               rcu_read_lock();
        }
 
+       rcu_read_unlock();
+
        return 0;
 }
 
@@ -554,20 +602,40 @@ static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
        filter.service = service;
        filter.instance = instance;
 
+       rcu_read_lock();
        radix_tree_for_each_slot(node_slot, &nodes, &node_iter, 0) {
                node = radix_tree_deref_slot(node_slot);
+               if (!node)
+                       continue;
+               if (radix_tree_deref_retry(node)) {
+                       node_slot = radix_tree_iter_retry(&node_iter);
+                       continue;
+               }
+               node_slot = radix_tree_iter_resume(node_slot, &node_iter);
 
                radix_tree_for_each_slot(srv_slot, &node->servers,
                                         &srv_iter, 0) {
                        struct qrtr_server *srv;
 
                        srv = radix_tree_deref_slot(srv_slot);
+                       if (!srv)
+                               continue;
+                       if (radix_tree_deref_retry(srv)) {
+                               srv_slot = radix_tree_iter_retry(&srv_iter);
+                               continue;
+                       }
+
                        if (!server_match(srv, &filter))
                                continue;
 
+                       srv_slot = radix_tree_iter_resume(srv_slot, &srv_iter);
+
+                       rcu_read_unlock();
                        lookup_notify(from, srv, true);
+                       rcu_read_lock();
                }
        }
+       rcu_read_unlock();
 
        /* Empty notification, to indicate end of listing */
        lookup_notify(from, NULL, true);
index 90c558f..957aa92 100644 (file)
@@ -332,8 +332,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
 {
        struct qrtr_hdr_v1 *hdr;
        size_t len = skb->len;
-       int rc = -ENODEV;
-       int confirm_rx;
+       int rc, confirm_rx;
 
        confirm_rx = qrtr_tx_wait(node, to->sq_node, to->sq_port, type);
        if (confirm_rx < 0) {
@@ -357,15 +356,17 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
        hdr->size = cpu_to_le32(len);
        hdr->confirm_rx = !!confirm_rx;
 
-       skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
-
-       mutex_lock(&node->ep_lock);
-       if (node->ep)
-               rc = node->ep->xmit(node->ep, skb);
-       else
-               kfree_skb(skb);
-       mutex_unlock(&node->ep_lock);
+       rc = skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
 
+       if (!rc) {
+               mutex_lock(&node->ep_lock);
+               rc = -ENODEV;
+               if (node->ep)
+                       rc = node->ep->xmit(node->ep, skb);
+               else
+                       kfree_skb(skb);
+               mutex_unlock(&node->ep_lock);
+       }
        /* Need to ensure that a subsequent message carries the otherwise lost
         * confirm_rx flag if we dropped this one */
        if (rc && confirm_rx)
index 884cff7..97aebb5 100644 (file)
@@ -518,7 +518,6 @@ enum rxrpc_call_state {
        RXRPC_CALL_CLIENT_RECV_REPLY,   /* - client receiving reply phase */
        RXRPC_CALL_SERVER_PREALLOC,     /* - service preallocation */
        RXRPC_CALL_SERVER_SECURING,     /* - server securing request connection */
-       RXRPC_CALL_SERVER_ACCEPTING,    /* - server accepting request */
        RXRPC_CALL_SERVER_RECV_REQUEST, /* - server receiving request */
        RXRPC_CALL_SERVER_ACK_REQUEST,  /* - server pending ACK of request */
        RXRPC_CALL_SERVER_SEND_REPLY,   /* - server sending reply */
@@ -714,8 +713,8 @@ struct rxrpc_ack_summary {
 enum rxrpc_command {
        RXRPC_CMD_SEND_DATA,            /* send data message */
        RXRPC_CMD_SEND_ABORT,           /* request abort generation */
-       RXRPC_CMD_ACCEPT,               /* [server] accept incoming call */
        RXRPC_CMD_REJECT_BUSY,          /* [server] reject a call as busy */
+       RXRPC_CMD_CHARGE_ACCEPT,        /* [server] charge accept preallocation */
 };
 
 struct rxrpc_call_params {
@@ -755,9 +754,7 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *,
                                           struct rxrpc_sock *,
                                           struct sk_buff *);
 void rxrpc_accept_incoming_calls(struct rxrpc_local *);
-struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *, unsigned long,
-                                    rxrpc_notify_rx_t);
-int rxrpc_reject_call(struct rxrpc_sock *);
+int rxrpc_user_charge_accept(struct rxrpc_sock *, unsigned long);
 
 /*
  * call_event.c
index ef16056..8df1964 100644 (file)
@@ -39,8 +39,9 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
                                      unsigned int debug_id)
 {
        const void *here = __builtin_return_address(0);
-       struct rxrpc_call *call;
+       struct rxrpc_call *call, *xcall;
        struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
+       struct rb_node *parent, **pp;
        int max, tmp;
        unsigned int size = RXRPC_BACKLOG_MAX;
        unsigned int head, tail, call_head, call_tail;
@@ -94,7 +95,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
        }
 
        /* Now it gets complicated, because calls get registered with the
-        * socket here, particularly if a user ID is preassigned by the user.
+        * socket here, with a user ID preassigned by the user.
         */
        call = rxrpc_alloc_call(rx, gfp, debug_id);
        if (!call)
@@ -107,34 +108,33 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
                         here, (const void *)user_call_ID);
 
        write_lock(&rx->call_lock);
-       if (user_attach_call) {
-               struct rxrpc_call *xcall;
-               struct rb_node *parent, **pp;
-
-               /* Check the user ID isn't already in use */
-               pp = &rx->calls.rb_node;
-               parent = NULL;
-               while (*pp) {
-                       parent = *pp;
-                       xcall = rb_entry(parent, struct rxrpc_call, sock_node);
-                       if (user_call_ID < xcall->user_call_ID)
-                               pp = &(*pp)->rb_left;
-                       else if (user_call_ID > xcall->user_call_ID)
-                               pp = &(*pp)->rb_right;
-                       else
-                               goto id_in_use;
-               }
 
-               call->user_call_ID = user_call_ID;
-               call->notify_rx = notify_rx;
+       /* Check the user ID isn't already in use */
+       pp = &rx->calls.rb_node;
+       parent = NULL;
+       while (*pp) {
+               parent = *pp;
+               xcall = rb_entry(parent, struct rxrpc_call, sock_node);
+               if (user_call_ID < xcall->user_call_ID)
+                       pp = &(*pp)->rb_left;
+               else if (user_call_ID > xcall->user_call_ID)
+                       pp = &(*pp)->rb_right;
+               else
+                       goto id_in_use;
+       }
+
+       call->user_call_ID = user_call_ID;
+       call->notify_rx = notify_rx;
+       if (user_attach_call) {
                rxrpc_get_call(call, rxrpc_call_got_kernel);
                user_attach_call(call, user_call_ID);
-               rxrpc_get_call(call, rxrpc_call_got_userid);
-               rb_link_node(&call->sock_node, parent, pp);
-               rb_insert_color(&call->sock_node, &rx->calls);
-               set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
        }
 
+       rxrpc_get_call(call, rxrpc_call_got_userid);
+       rb_link_node(&call->sock_node, parent, pp);
+       rb_insert_color(&call->sock_node, &rx->calls);
+       set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
+
        list_add(&call->sock_link, &rx->sock_calls);
 
        write_unlock(&rx->call_lock);
@@ -157,11 +157,8 @@ id_in_use:
 }
 
 /*
- * Preallocate sufficient service connections, calls and peers to cover the
- * entire backlog of a socket.  When a new call comes in, if we don't have
- * sufficient of each available, the call gets rejected as busy or ignored.
- *
- * The backlog is replenished when a connection is accepted or rejected.
+ * Allocate the preallocation buffers for incoming service calls.  These must
+ * be charged manually.
  */
 int rxrpc_service_prealloc(struct rxrpc_sock *rx, gfp_t gfp)
 {
@@ -174,13 +171,6 @@ int rxrpc_service_prealloc(struct rxrpc_sock *rx, gfp_t gfp)
                rx->backlog = b;
        }
 
-       if (rx->discard_new_call)
-               return 0;
-
-       while (rxrpc_service_prealloc_one(rx, b, NULL, NULL, 0, gfp,
-                                         atomic_inc_return(&rxrpc_debug_id)) == 0)
-               ;
-
        return 0;
 }
 
@@ -333,6 +323,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
        rxrpc_see_call(call);
        call->conn = conn;
        call->security = conn->security;
+       call->security_ix = conn->security_ix;
        call->peer = rxrpc_get_peer(conn->params.peer);
        call->cong_cwnd = call->peer->cong_cwnd;
        return call;
@@ -402,8 +393,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
 
        if (rx->notify_new_call)
                rx->notify_new_call(&rx->sk, call, call->user_call_ID);
-       else
-               sk_acceptq_added(&rx->sk);
 
        spin_lock(&conn->state_lock);
        switch (conn->state) {
@@ -415,12 +404,8 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
 
        case RXRPC_CONN_SERVICE:
                write_lock(&call->state_lock);
-               if (call->state < RXRPC_CALL_COMPLETE) {
-                       if (rx->discard_new_call)
-                               call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
-                       else
-                               call->state = RXRPC_CALL_SERVER_ACCEPTING;
-               }
+               if (call->state < RXRPC_CALL_COMPLETE)
+                       call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
                write_unlock(&call->state_lock);
                break;
 
@@ -440,9 +425,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
 
        rxrpc_send_ping(call, skb);
 
-       if (call->state == RXRPC_CALL_SERVER_ACCEPTING)
-               rxrpc_notify_socket(call);
-
        /* We have to discard the prealloc queue's ref here and rely on a
         * combination of the RCU read lock and refs held either by the socket
         * (recvmsg queue, to-be-accepted queue or user ID tree) or the kernel
@@ -460,187 +442,18 @@ no_call:
 }
 
 /*
- * handle acceptance of a call by userspace
- * - assign the user call ID to the call at the front of the queue
- * - called with the socket locked.
+ * Charge up socket with preallocated calls, attaching user call IDs.
  */
-struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *rx,
-                                    unsigned long user_call_ID,
-                                    rxrpc_notify_rx_t notify_rx)
-       __releases(&rx->sk.sk_lock.slock)
-       __acquires(call->user_mutex)
+int rxrpc_user_charge_accept(struct rxrpc_sock *rx, unsigned long user_call_ID)
 {
-       struct rxrpc_call *call;
-       struct rb_node *parent, **pp;
-       int ret;
-
-       _enter(",%lx", user_call_ID);
-
-       ASSERT(!irqs_disabled());
-
-       write_lock(&rx->call_lock);
-
-       if (list_empty(&rx->to_be_accepted)) {
-               write_unlock(&rx->call_lock);
-               release_sock(&rx->sk);
-               kleave(" = -ENODATA [empty]");
-               return ERR_PTR(-ENODATA);
-       }
-
-       /* check the user ID isn't already in use */
-       pp = &rx->calls.rb_node;
-       parent = NULL;
-       while (*pp) {
-               parent = *pp;
-               call = rb_entry(parent, struct rxrpc_call, sock_node);
-
-               if (user_call_ID < call->user_call_ID)
-                       pp = &(*pp)->rb_left;
-               else if (user_call_ID > call->user_call_ID)
-                       pp = &(*pp)->rb_right;
-               else
-                       goto id_in_use;
-       }
-
-       /* Dequeue the first call and check it's still valid.  We gain
-        * responsibility for the queue's reference.
-        */
-       call = list_entry(rx->to_be_accepted.next,
-                         struct rxrpc_call, accept_link);
-       write_unlock(&rx->call_lock);
-
-       /* We need to gain the mutex from the interrupt handler without
-        * upsetting lockdep, so we have to release it there and take it here.
-        * We are, however, still holding the socket lock, so other accepts
-        * must wait for us and no one can add the user ID behind our backs.
-        */
-       if (mutex_lock_interruptible(&call->user_mutex) < 0) {
-               release_sock(&rx->sk);
-               kleave(" = -ERESTARTSYS");
-               return ERR_PTR(-ERESTARTSYS);
-       }
-
-       write_lock(&rx->call_lock);
-       list_del_init(&call->accept_link);
-       sk_acceptq_removed(&rx->sk);
-       rxrpc_see_call(call);
-
-       /* Find the user ID insertion point. */
-       pp = &rx->calls.rb_node;
-       parent = NULL;
-       while (*pp) {
-               parent = *pp;
-               call = rb_entry(parent, struct rxrpc_call, sock_node);
-
-               if (user_call_ID < call->user_call_ID)
-                       pp = &(*pp)->rb_left;
-               else if (user_call_ID > call->user_call_ID)
-                       pp = &(*pp)->rb_right;
-               else
-                       BUG();
-       }
-
-       write_lock_bh(&call->state_lock);
-       switch (call->state) {
-       case RXRPC_CALL_SERVER_ACCEPTING:
-               call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
-               break;
-       case RXRPC_CALL_COMPLETE:
-               ret = call->error;
-               goto out_release;
-       default:
-               BUG();
-       }
-
-       /* formalise the acceptance */
-       call->notify_rx = notify_rx;
-       call->user_call_ID = user_call_ID;
-       rxrpc_get_call(call, rxrpc_call_got_userid);
-       rb_link_node(&call->sock_node, parent, pp);
-       rb_insert_color(&call->sock_node, &rx->calls);
-       if (test_and_set_bit(RXRPC_CALL_HAS_USERID, &call->flags))
-               BUG();
-
-       write_unlock_bh(&call->state_lock);
-       write_unlock(&rx->call_lock);
-       rxrpc_notify_socket(call);
-       rxrpc_service_prealloc(rx, GFP_KERNEL);
-       release_sock(&rx->sk);
-       _leave(" = %p{%d}", call, call->debug_id);
-       return call;
-
-out_release:
-       _debug("release %p", call);
-       write_unlock_bh(&call->state_lock);
-       write_unlock(&rx->call_lock);
-       rxrpc_release_call(rx, call);
-       rxrpc_put_call(call, rxrpc_call_put);
-       goto out;
-
-id_in_use:
-       ret = -EBADSLT;
-       write_unlock(&rx->call_lock);
-out:
-       rxrpc_service_prealloc(rx, GFP_KERNEL);
-       release_sock(&rx->sk);
-       _leave(" = %d", ret);
-       return ERR_PTR(ret);
-}
-
-/*
- * Handle rejection of a call by userspace
- * - reject the call at the front of the queue
- */
-int rxrpc_reject_call(struct rxrpc_sock *rx)
-{
-       struct rxrpc_call *call;
-       bool abort = false;
-       int ret;
-
-       _enter("");
-
-       ASSERT(!irqs_disabled());
-
-       write_lock(&rx->call_lock);
-
-       if (list_empty(&rx->to_be_accepted)) {
-               write_unlock(&rx->call_lock);
-               return -ENODATA;
-       }
-
-       /* Dequeue the first call and check it's still valid.  We gain
-        * responsibility for the queue's reference.
-        */
-       call = list_entry(rx->to_be_accepted.next,
-                         struct rxrpc_call, accept_link);
-       list_del_init(&call->accept_link);
-       sk_acceptq_removed(&rx->sk);
-       rxrpc_see_call(call);
+       struct rxrpc_backlog *b = rx->backlog;
 
-       write_lock_bh(&call->state_lock);
-       switch (call->state) {
-       case RXRPC_CALL_SERVER_ACCEPTING:
-               __rxrpc_abort_call("REJ", call, 1, RX_USER_ABORT, -ECONNABORTED);
-               abort = true;
-               fallthrough;
-       case RXRPC_CALL_COMPLETE:
-               ret = call->error;
-               goto out_discard;
-       default:
-               BUG();
-       }
+       if (rx->sk.sk_state == RXRPC_CLOSE)
+               return -ESHUTDOWN;
 
-out_discard:
-       write_unlock_bh(&call->state_lock);
-       write_unlock(&rx->call_lock);
-       if (abort) {
-               rxrpc_send_abort_packet(call);
-               rxrpc_release_call(rx, call);
-               rxrpc_put_call(call, rxrpc_call_put);
-       }
-       rxrpc_service_prealloc(rx, GFP_KERNEL);
-       _leave(" = %d", ret);
-       return ret;
+       return rxrpc_service_prealloc_one(rx, b, NULL, NULL, user_call_ID,
+                                         GFP_KERNEL,
+                                         atomic_inc_return(&rxrpc_debug_id));
 }
 
 /*
index a40fae0..ed49769 100644 (file)
@@ -23,7 +23,6 @@ const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = {
        [RXRPC_CALL_CLIENT_RECV_REPLY]          = "ClRcvRpl",
        [RXRPC_CALL_SERVER_PREALLOC]            = "SvPrealc",
        [RXRPC_CALL_SERVER_SECURING]            = "SvSecure",
-       [RXRPC_CALL_SERVER_ACCEPTING]           = "SvAccept",
        [RXRPC_CALL_SERVER_RECV_REQUEST]        = "SvRcvReq",
        [RXRPC_CALL_SERVER_ACK_REQUEST]         = "SvAckReq",
        [RXRPC_CALL_SERVER_SEND_REPLY]          = "SvSndRpl",
@@ -352,9 +351,7 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx,
        call->call_id           = sp->hdr.callNumber;
        call->service_id        = sp->hdr.serviceId;
        call->cid               = sp->hdr.cid;
-       call->state             = RXRPC_CALL_SERVER_ACCEPTING;
-       if (sp->hdr.securityIndex > 0)
-               call->state     = RXRPC_CALL_SERVER_SECURING;
+       call->state             = RXRPC_CALL_SERVER_SECURING;
        call->cong_tstamp       = skb->tstamp;
 
        /* Set the channel for this call.  We don't get channel_lock as we're
index 447f55c..64ace29 100644 (file)
@@ -269,7 +269,7 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
        if (call) {
                write_lock_bh(&call->state_lock);
                if (call->state == RXRPC_CALL_SERVER_SECURING) {
-                       call->state = RXRPC_CALL_SERVER_ACCEPTING;
+                       call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
                        rxrpc_notify_socket(call);
                }
                write_unlock_bh(&call->state_lock);
@@ -340,18 +340,18 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
                        return ret;
 
                spin_lock(&conn->channel_lock);
-               spin_lock(&conn->state_lock);
+               spin_lock_bh(&conn->state_lock);
 
                if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
                        conn->state = RXRPC_CONN_SERVICE;
-                       spin_unlock(&conn->state_lock);
+                       spin_unlock_bh(&conn->state_lock);
                        for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
                                rxrpc_call_is_secure(
                                        rcu_dereference_protected(
                                                conn->channels[loop].call,
                                                lockdep_is_held(&conn->channel_lock)));
                } else {
-                       spin_unlock(&conn->state_lock);
+                       spin_unlock_bh(&conn->state_lock);
                }
 
                spin_unlock(&conn->channel_lock);
index 94c3df3..2e8bd3b 100644 (file)
@@ -903,7 +903,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
 
        _enter("");
 
-       if (optlen <= 0 || optlen > PAGE_SIZE - 1)
+       if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
                return -EINVAL;
 
        description = memdup_sockptr_nul(optval, optlen);
@@ -940,7 +940,7 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
        if (IS_ERR(description))
                return PTR_ERR(description);
 
-       key = request_key_net(&key_type_keyring, description, sock_net(&rx->sk), NULL);
+       key = request_key(&key_type_keyring, description, NULL);
        if (IS_ERR(key)) {
                kfree(description);
                _leave(" = %ld", PTR_ERR(key));
@@ -1072,7 +1072,7 @@ static long rxrpc_read(const struct key *key,
 
                switch (token->security_index) {
                case RXRPC_SECURITY_RXKAD:
-                       toksize += 9 * 4;       /* viceid, kvno, key*2 + len, begin,
+                       toksize += 8 * 4;       /* viceid, kvno, key*2, begin,
                                                 * end, primary, tktlen */
                        toksize += RND(token->kad->ticket_len);
                        break;
@@ -1107,7 +1107,8 @@ static long rxrpc_read(const struct key *key,
                        break;
 
                default: /* we have a ticket we can't encode */
-                       BUG();
+                       pr_err("Unsupported key token type (%u)\n",
+                              token->security_index);
                        continue;
                }
 
@@ -1138,6 +1139,14 @@ static long rxrpc_read(const struct key *key,
                        memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));    \
                xdr += (_l + 3) >> 2;                                   \
        } while(0)
+#define ENCODE_BYTES(l, s)                                             \
+       do {                                                            \
+               u32 _l = (l);                                           \
+               memcpy(xdr, (s), _l);                                   \
+               if (_l & 3)                                             \
+                       memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));    \
+               xdr += (_l + 3) >> 2;                                   \
+       } while(0)
 #define ENCODE64(x)                                    \
        do {                                            \
                __be64 y = cpu_to_be64(x);              \
@@ -1165,7 +1174,7 @@ static long rxrpc_read(const struct key *key,
                case RXRPC_SECURITY_RXKAD:
                        ENCODE(token->kad->vice_id);
                        ENCODE(token->kad->kvno);
-                       ENCODE_DATA(8, token->kad->session_key);
+                       ENCODE_BYTES(8, token->kad->session_key);
                        ENCODE(token->kad->start);
                        ENCODE(token->kad->expiry);
                        ENCODE(token->kad->primary_flag);
@@ -1215,7 +1224,6 @@ static long rxrpc_read(const struct key *key,
                        break;
 
                default:
-                       BUG();
                        break;
                }
 
index c4684dd..2c84285 100644 (file)
@@ -179,37 +179,6 @@ static int rxrpc_recvmsg_term(struct rxrpc_call *call, struct msghdr *msg)
 }
 
 /*
- * Pass back notification of a new call.  The call is added to the
- * to-be-accepted list.  This means that the next call to be accepted might not
- * be the last call seen awaiting acceptance, but unless we leave this on the
- * front of the queue and block all other messages until someone gives us a
- * user_ID for it, there's not a lot we can do.
- */
-static int rxrpc_recvmsg_new_call(struct rxrpc_sock *rx,
-                                 struct rxrpc_call *call,
-                                 struct msghdr *msg, int flags)
-{
-       int tmp = 0, ret;
-
-       ret = put_cmsg(msg, SOL_RXRPC, RXRPC_NEW_CALL, 0, &tmp);
-
-       if (ret == 0 && !(flags & MSG_PEEK)) {
-               _debug("to be accepted");
-               write_lock_bh(&rx->recvmsg_lock);
-               list_del_init(&call->recvmsg_link);
-               write_unlock_bh(&rx->recvmsg_lock);
-
-               rxrpc_get_call(call, rxrpc_call_got);
-               write_lock(&rx->call_lock);
-               list_add_tail(&call->accept_link, &rx->to_be_accepted);
-               write_unlock(&rx->call_lock);
-       }
-
-       trace_rxrpc_recvmsg(call, rxrpc_recvmsg_to_be_accepted, 1, 0, 0, ret);
-       return ret;
-}
-
-/*
  * End the packet reception phase.
  */
 static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
@@ -630,9 +599,6 @@ try_again:
        }
 
        switch (READ_ONCE(call->state)) {
-       case RXRPC_CALL_SERVER_ACCEPTING:
-               ret = rxrpc_recvmsg_new_call(rx, call, msg, flags);
-               break;
        case RXRPC_CALL_CLIENT_RECV_REPLY:
        case RXRPC_CALL_SERVER_RECV_REQUEST:
        case RXRPC_CALL_SERVER_ACK_REQUEST:
@@ -728,7 +694,7 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
               call->debug_id, rxrpc_call_states[call->state],
               iov_iter_count(iter), want_more);
 
-       ASSERTCMP(call->state, !=, RXRPC_CALL_SERVER_ACCEPTING);
+       ASSERTCMP(call->state, !=, RXRPC_CALL_SERVER_SECURING);
 
        mutex_lock(&call->user_mutex);
 
index 0824e10..d27140c 100644 (file)
@@ -530,10 +530,10 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
                                return -EINVAL;
                        break;
 
-               case RXRPC_ACCEPT:
+               case RXRPC_CHARGE_ACCEPT:
                        if (p->command != RXRPC_CMD_SEND_DATA)
                                return -EINVAL;
-                       p->command = RXRPC_CMD_ACCEPT;
+                       p->command = RXRPC_CMD_CHARGE_ACCEPT;
                        if (len != 0)
                                return -EINVAL;
                        break;
@@ -659,16 +659,12 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
        if (ret < 0)
                goto error_release_sock;
 
-       if (p.command == RXRPC_CMD_ACCEPT) {
+       if (p.command == RXRPC_CMD_CHARGE_ACCEPT) {
                ret = -EINVAL;
                if (rx->sk.sk_state != RXRPC_SERVER_LISTENING)
                        goto error_release_sock;
-               call = rxrpc_accept_call(rx, p.call.user_call_ID, NULL);
-               /* The socket is now unlocked. */
-               if (IS_ERR(call))
-                       return PTR_ERR(call);
-               ret = 0;
-               goto out_put_unlock;
+               ret = rxrpc_user_charge_accept(rx, p.call.user_call_ID);
+               goto error_release_sock;
        }
 
        call = rxrpc_find_call_by_user_ID(rx, p.call.user_call_ID);
@@ -690,7 +686,6 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                case RXRPC_CALL_CLIENT_AWAIT_CONN:
                case RXRPC_CALL_SERVER_PREALLOC:
                case RXRPC_CALL_SERVER_SECURING:
-               case RXRPC_CALL_SERVER_ACCEPTING:
                        rxrpc_put_call(call, rxrpc_call_put);
                        ret = -EBUSY;
                        goto error_release_sock;
index 063d8aa..798430e 100644 (file)
@@ -235,6 +235,8 @@ static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
                index++;
                if (index < s_i)
                        continue;
+               if (IS_ERR(p))
+                       continue;
 
                if (jiffy_since &&
                    time_after(jiffy_since,
@@ -307,6 +309,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
 
        mutex_lock(&idrinfo->lock);
        idr_for_each_entry_ul(idr, p, tmp, id) {
+               if (IS_ERR(p))
+                       continue;
                ret = tcf_idr_release_unsafe(p);
                if (ret == ACT_P_DELETED) {
                        module_put(ops->owner);
@@ -467,17 +471,6 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
 }
 EXPORT_SYMBOL(tcf_idr_create_from_flags);
 
-void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
-{
-       struct tcf_idrinfo *idrinfo = tn->idrinfo;
-
-       mutex_lock(&idrinfo->lock);
-       /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
-       WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
-       mutex_unlock(&idrinfo->lock);
-}
-EXPORT_SYMBOL(tcf_idr_insert);
-
 /* Cleanup idr index that was allocated but not initialized. */
 
 void tcf_idr_cleanup(struct tc_action_net *tn, u32 index)
@@ -731,13 +724,6 @@ int tcf_action_destroy(struct tc_action *actions[], int bind)
        return ret;
 }
 
-static int tcf_action_destroy_1(struct tc_action *a, int bind)
-{
-       struct tc_action *actions[] = { a, NULL };
-
-       return tcf_action_destroy(actions, bind);
-}
-
 static int tcf_action_put(struct tc_action *p)
 {
        return __tcf_action_put(p, false);
@@ -902,6 +888,26 @@ static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
        [TCA_ACT_HW_STATS]      = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY),
 };
 
+static void tcf_idr_insert_many(struct tc_action *actions[])
+{
+       int i;
+
+       for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
+               struct tc_action *a = actions[i];
+               struct tcf_idrinfo *idrinfo;
+
+               if (!a)
+                       continue;
+               idrinfo = a->idrinfo;
+               mutex_lock(&idrinfo->lock);
+               /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc if
+                * it is just created, otherwise this is just a nop.
+                */
+               idr_replace(&idrinfo->action_idr, a, a->tcfa_index);
+               mutex_unlock(&idrinfo->lock);
+       }
+}
+
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
                                    struct nlattr *nla, struct nlattr *est,
                                    char *name, int ovr, int bind,
@@ -1002,13 +1008,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
        if (err != ACT_P_CREATED)
                module_put(a_o->owner);
 
-       if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN) &&
-           !rcu_access_pointer(a->goto_chain)) {
-               tcf_action_destroy_1(a, bind);
-               NL_SET_ERR_MSG(extack, "can't use goto chain with NULL chain");
-               return ERR_PTR(-EINVAL);
-       }
-
        return a;
 
 err_mod:
@@ -1051,6 +1050,11 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
                actions[i - 1] = act;
        }
 
+       /* We have to commit them all together, because if any error happened in
+        * between, we could not handle the failure gracefully.
+        */
+       tcf_idr_insert_many(actions);
+
        *attr_size = tcf_action_full_attrs_size(sz);
        return i - 1;
 
index 54d5652..a4c7ba3 100644 (file)
@@ -365,9 +365,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (res == ACT_P_CREATED) {
-               tcf_idr_insert(tn, *act);
-       } else {
+       if (res != ACT_P_CREATED) {
                /* make sure the program being replaced is no longer executing */
                synchronize_rcu();
                tcf_bpf_cfg_cleanup(&old);
index f901421..e19885d 100644 (file)
@@ -139,7 +139,6 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
                ci->net = net;
                ci->zone = parm->zone;
 
-               tcf_idr_insert(tn, *a);
                ret = ACT_P_CREATED;
        } else if (ret > 0) {
                ci = to_connmark(*a);
index f5826e4..4fa4fcb 100644 (file)
@@ -110,9 +110,6 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
        if (params_new)
                kfree_rcu(params_new, rcu);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
-
        return ret;
 put_chain:
        if (goto_ch)
index 2c36191..a780afd 100644 (file)
@@ -1297,8 +1297,6 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
                tcf_chain_put_by_act(goto_ch);
        if (params)
                call_rcu(&params->rcu, tcf_ct_params_free);
-       if (res == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
 
        return res;
 
index b5042f3..6084300 100644 (file)
@@ -269,9 +269,6 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
        if (cp_new)
                kfree_rcu(cp_new, rcu);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
-
        return ret;
 
 put_chain:
index 410e3bb..73c3926 100644 (file)
@@ -140,8 +140,6 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 release_idr:
        tcf_idr_release(*a, bind);
index 1fb8d42..7c0771d 100644 (file)
@@ -437,9 +437,6 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
-
        return ret;
 
 chain_put:
index c1fcd85..a2ddea0 100644 (file)
@@ -436,6 +436,25 @@ static void tcf_ife_cleanup(struct tc_action *a)
                kfree_rcu(p, rcu);
 }
 
+static int load_metalist(struct nlattr **tb, bool rtnl_held)
+{
+       int i;
+
+       for (i = 1; i < max_metacnt; i++) {
+               if (tb[i]) {
+                       void *val = nla_data(tb[i]);
+                       int len = nla_len(tb[i]);
+                       int rc;
+
+                       rc = load_metaops_and_vet(i, val, len, rtnl_held);
+                       if (rc != 0)
+                               return rc;
+               }
+       }
+
+       return 0;
+}
+
 static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
                             bool exists, bool rtnl_held)
 {
@@ -449,10 +468,6 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
                        val = nla_data(tb[i]);
                        len = nla_len(tb[i]);
 
-                       rc = load_metaops_and_vet(i, val, len, rtnl_held);
-                       if (rc != 0)
-                               return rc;
-
                        rc = add_metainfo(ife, i, val, len, exists);
                        if (rc)
                                return rc;
@@ -509,6 +524,21 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        if (!p)
                return -ENOMEM;
 
+       if (tb[TCA_IFE_METALST]) {
+               err = nla_parse_nested_deprecated(tb2, IFE_META_MAX,
+                                                 tb[TCA_IFE_METALST], NULL,
+                                                 NULL);
+               if (err) {
+                       kfree(p);
+                       return err;
+               }
+               err = load_metalist(tb2, rtnl_held);
+               if (err) {
+                       kfree(p);
+                       return err;
+               }
+       }
+
        index = parm->index;
        err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (err < 0) {
@@ -570,15 +600,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        }
 
        if (tb[TCA_IFE_METALST]) {
-               err = nla_parse_nested_deprecated(tb2, IFE_META_MAX,
-                                                 tb[TCA_IFE_METALST], NULL,
-                                                 NULL);
-               if (err)
-                       goto metadata_parse_err;
                err = populate_metalist(ife, tb2, exists, rtnl_held);
                if (err)
                        goto metadata_parse_err;
-
        } else {
                /* if no passed metadata allow list or passed allow-all
                 * then here we process by adding as many supported metadatum
@@ -603,9 +627,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        if (p)
                kfree_rcu(p, rcu);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
-
        return ret;
 metadata_parse_err:
        if (goto_ch)
index 400a2cf..8dc3bec 100644 (file)
@@ -189,8 +189,6 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
        ipt->tcfi_t     = t;
        ipt->tcfi_hook  = hook;
        spin_unlock_bh(&ipt->tcf_lock);
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 
 err3:
index b270531..e24b7e2 100644 (file)
@@ -194,8 +194,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                spin_lock(&mirred_list_lock);
                list_add(&m->tcfm_list, &mirred_list);
                spin_unlock(&mirred_list_lock);
-
-               tcf_idr_insert(tn, *a);
        }
 
        return ret;
index 8118e26..e298ec3 100644 (file)
@@ -273,8 +273,6 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
        if (p)
                kfree_rcu(p, rcu);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 put_chain:
        if (goto_ch)
index 855a6fa..1ebd2a8 100644 (file)
@@ -93,9 +93,6 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
-
        return ret;
 release_idr:
        tcf_idr_release(*a, bind);
index c158bfe..b453044 100644 (file)
@@ -238,8 +238,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        spin_unlock_bh(&p->tcf_lock);
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 
 put_chain:
index 0b431d4..8d8452b 100644 (file)
@@ -201,8 +201,6 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        if (new)
                kfree_rcu(new, rcu);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 
 failure:
index 5e2df59..3ebf9ed 100644 (file)
@@ -116,8 +116,6 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 put_chain:
        if (goto_ch)
index 9813ca4..a4f3d0f 100644 (file)
@@ -157,8 +157,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                        goto release_idr;
        }
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 put_chain:
        if (goto_ch)
index d065238..e5f3fb8 100644 (file)
@@ -225,8 +225,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 put_chain:
        if (goto_ch)
index 39e6d94..81a1c67 100644 (file)
@@ -190,8 +190,6 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 put_chain:
        if (goto_ch)
index 536c4bc..a229751 100644 (file)
@@ -156,6 +156,7 @@ tunnel_key_copy_vxlan_opt(const struct nlattr *nla, void *dst, int dst_len,
                struct vxlan_metadata *md = dst;
 
                md->gbp = nla_get_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]);
+               md->gbp &= VXLAN_GBP_MASK;
        }
 
        return sizeof(struct vxlan_metadata);
@@ -536,9 +537,6 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        if (goto_ch)
                tcf_chain_put_by_act(goto_ch);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
-
        return ret;
 
 put_chain:
index a5ff9f6..163b038 100644 (file)
@@ -229,8 +229,6 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        if (p)
                kfree_rcu(p, rcu);
 
-       if (ret == ACT_P_CREATED)
-               tcf_idr_insert(tn, *a);
        return ret;
 put_chain:
        if (goto_ch)
index a4f7ef1..fed18fd 100644 (file)
@@ -1175,8 +1175,10 @@ static int fl_set_vxlan_opt(const struct nlattr *nla, struct fl_flow_key *key,
                return -EINVAL;
        }
 
-       if (tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP])
+       if (tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP]) {
                md->gbp = nla_get_u32(tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP]);
+               md->gbp &= VXLAN_GBP_MASK;
+       }
 
        return sizeof(*md);
 }
@@ -1221,6 +1223,7 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
                }
                if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]) {
                        nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX];
+                       memset(&md->u, 0x00, sizeof(md->u));
                        md->u.index = nla_get_be32(nla);
                }
        } else if (md->version == 2) {
index 265a61d..54c4172 100644 (file)
@@ -1131,24 +1131,10 @@ EXPORT_SYMBOL(dev_activate);
 
 static void qdisc_deactivate(struct Qdisc *qdisc)
 {
-       bool nolock = qdisc->flags & TCQ_F_NOLOCK;
-
        if (qdisc->flags & TCQ_F_BUILTIN)
                return;
-       if (test_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state))
-               return;
-
-       if (nolock)
-               spin_lock_bh(&qdisc->seqlock);
-       spin_lock_bh(qdisc_lock(qdisc));
 
        set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
-
-       qdisc_reset(qdisc);
-
-       spin_unlock_bh(qdisc_lock(qdisc));
-       if (nolock)
-               spin_unlock_bh(&qdisc->seqlock);
 }
 
 static void dev_deactivate_queue(struct net_device *dev,
@@ -1165,6 +1151,30 @@ static void dev_deactivate_queue(struct net_device *dev,
        }
 }
 
+static void dev_reset_queue(struct net_device *dev,
+                           struct netdev_queue *dev_queue,
+                           void *_unused)
+{
+       struct Qdisc *qdisc;
+       bool nolock;
+
+       qdisc = dev_queue->qdisc_sleeping;
+       if (!qdisc)
+               return;
+
+       nolock = qdisc->flags & TCQ_F_NOLOCK;
+
+       if (nolock)
+               spin_lock_bh(&qdisc->seqlock);
+       spin_lock_bh(qdisc_lock(qdisc));
+
+       qdisc_reset(qdisc);
+
+       spin_unlock_bh(qdisc_lock(qdisc));
+       if (nolock)
+               spin_unlock_bh(&qdisc->seqlock);
+}
+
 static bool some_qdisc_is_busy(struct net_device *dev)
 {
        unsigned int i;
@@ -1213,12 +1223,20 @@ void dev_deactivate_many(struct list_head *head)
                dev_watchdog_down(dev);
        }
 
-       /* Wait for outstanding qdisc-less dev_queue_xmit calls.
+       /* Wait for outstanding qdisc-less dev_queue_xmit calls or
+        * outstanding qdisc enqueuing calls.
         * This is avoided if all devices are in dismantle phase :
         * Caller will call synchronize_net() for us
         */
        synchronize_net();
 
+       list_for_each_entry(dev, head, close_list) {
+               netdev_for_each_tx_queue(dev, dev_reset_queue, NULL);
+
+               if (dev_ingress_queue(dev))
+                       dev_reset_queue(dev, dev_ingress_queue(dev), NULL);
+       }
+
        /* Wait for outstanding qdisc_run calls. */
        list_for_each_entry(dev, head, close_list) {
                while (some_qdisc_is_busy(dev)) {
index fe53c1e..b0ad768 100644 (file)
@@ -777,9 +777,11 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_TXTIME_DELAY]               = { .type = NLA_U32 },
 };
 
-static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
+static int fill_sched_entry(struct taprio_sched *q, struct nlattr **tb,
+                           struct sched_entry *entry,
                            struct netlink_ext_ack *extack)
 {
+       int min_duration = length_to_duration(q, ETH_ZLEN);
        u32 interval = 0;
 
        if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
@@ -794,7 +796,10 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
                interval = nla_get_u32(
                        tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL]);
 
-       if (interval == 0) {
+       /* The interval should allow at least the minimum ethernet
+        * frame to go out.
+        */
+       if (interval < min_duration) {
                NL_SET_ERR_MSG(extack, "Invalid interval for schedule entry");
                return -EINVAL;
        }
@@ -804,8 +809,9 @@ static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
        return 0;
 }
 
-static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry,
-                            int index, struct netlink_ext_ack *extack)
+static int parse_sched_entry(struct taprio_sched *q, struct nlattr *n,
+                            struct sched_entry *entry, int index,
+                            struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = { };
        int err;
@@ -819,10 +825,10 @@ static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry,
 
        entry->index = index;
 
-       return fill_sched_entry(tb, entry, extack);
+       return fill_sched_entry(q, tb, entry, extack);
 }
 
-static int parse_sched_list(struct nlattr *list,
+static int parse_sched_list(struct taprio_sched *q, struct nlattr *list,
                            struct sched_gate_list *sched,
                            struct netlink_ext_ack *extack)
 {
@@ -847,7 +853,7 @@ static int parse_sched_list(struct nlattr *list,
                        return -ENOMEM;
                }
 
-               err = parse_sched_entry(n, entry, i, extack);
+               err = parse_sched_entry(q, n, entry, i, extack);
                if (err < 0) {
                        kfree(entry);
                        return err;
@@ -862,7 +868,7 @@ static int parse_sched_list(struct nlattr *list,
        return i;
 }
 
-static int parse_taprio_schedule(struct nlattr **tb,
+static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
                                 struct sched_gate_list *new,
                                 struct netlink_ext_ack *extack)
 {
@@ -883,8 +889,8 @@ static int parse_taprio_schedule(struct nlattr **tb,
                new->cycle_time = nla_get_s64(tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]);
 
        if (tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST])
-               err = parse_sched_list(
-                       tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST], new, extack);
+               err = parse_sched_list(q, tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST],
+                                      new, extack);
        if (err < 0)
                return err;
 
@@ -1473,7 +1479,7 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
                goto free_sched;
        }
 
-       err = parse_taprio_schedule(tb, new_admin, extack);
+       err = parse_taprio_schedule(q, tb, new_admin, extack);
        if (err < 0)
                goto free_sched;
 
index 9e289c7..7e59d8a 100644 (file)
@@ -494,6 +494,7 @@ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp)
 out_err:
        /* Clean up any successful allocations */
        sctp_auth_destroy_hmacs(ep->auth_hmacs);
+       ep->auth_hmacs = NULL;
        return -ENOMEM;
 }
 
index 836615f..53d0a41 100644 (file)
@@ -9220,13 +9220,10 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
 static inline void sctp_copy_descendant(struct sock *sk_to,
                                        const struct sock *sk_from)
 {
-       int ancestor_size = sizeof(struct inet_sock) +
-                           sizeof(struct sctp_sock) -
-                           offsetof(struct sctp_sock, pd_lobby);
-
-       if (sk_from->sk_family == PF_INET6)
-               ancestor_size += sizeof(struct ipv6_pinfo);
+       size_t ancestor_size = sizeof(struct inet_sock);
 
+       ancestor_size += sk_from->sk_prot->obj_size;
+       ancestor_size -= offsetof(struct sctp_sock, pd_lobby);
        __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size);
 }
 
index 0c01446..58cac2d 100644 (file)
@@ -3638,9 +3638,11 @@ EXPORT_SYMBOL(kernel_getpeername);
 int kernel_sendpage(struct socket *sock, struct page *page, int offset,
                    size_t size, int flags)
 {
-       if (sock->ops->sendpage)
+       if (sock->ops->sendpage) {
+               /* Warn in case the improper page to zero-copy send */
+               WARN_ONCE(!sendpage_ok(page), "improper page for zero-copy send");
                return sock->ops->sendpage(sock, page, offset, size, flags);
-
+       }
        return sock_no_sendpage(sock, page, offset, size, flags);
 }
 EXPORT_SYMBOL(kernel_sendpage);
index c27123e..4a67685 100644 (file)
@@ -982,8 +982,8 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
        p = xdr_inline_decode(xdr, len);
        if (unlikely(p == NULL))
                goto out_fail;
-       dprintk("RPC: %5u RPCB_%s reply: %s\n", req->rq_task->tk_pid,
-                       req->rq_task->tk_msg.rpc_proc->p_name, (char *)p);
+       dprintk("RPC: %5u RPCB_%s reply: %*pE\n", req->rq_task->tk_pid,
+                       req->rq_task->tk_msg.rpc_proc->p_name, len, (char *)p);
 
        if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len,
                                sap, sizeof(address)) == 0)
index d5805fa..c2752e2 100644 (file)
@@ -228,7 +228,7 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
 static void svc_flush_bvec(const struct bio_vec *bvec, size_t size, size_t seek)
 {
        struct bvec_iter bi = {
-               .bi_size        = size,
+               .bi_size        = size + seek,
        };
        struct bio_vec bv;
 
index 3f86d03..ad6e2e4 100644 (file)
@@ -933,6 +933,8 @@ static void rpcrdma_req_reset(struct rpcrdma_req *req)
 
        rpcrdma_regbuf_dma_unmap(req->rl_sendbuf);
        rpcrdma_regbuf_dma_unmap(req->rl_recvbuf);
+
+       frwr_reset(req);
 }
 
 /* ASSUMPTION: the rb_allreqs list is stable for the duration,
index 865f3e0..23d8685 100644 (file)
@@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
  *     @val: value passed unmodified to notifier function
  *     @dev: port device
  *     @info: notifier information data
- *
+ *     @extack: netlink extended ack
  *     Call all network notifier blocks.
  */
 int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
index 588c2d2..b1fcd2a 100644 (file)
@@ -273,8 +273,8 @@ static struct tipc_member *tipc_group_find_node(struct tipc_group *grp,
        return NULL;
 }
 
-static void tipc_group_add_to_tree(struct tipc_group *grp,
-                                  struct tipc_member *m)
+static int tipc_group_add_to_tree(struct tipc_group *grp,
+                                 struct tipc_member *m)
 {
        u64 nkey, key = (u64)m->node << 32 | m->port;
        struct rb_node **n, *parent = NULL;
@@ -291,10 +291,11 @@ static void tipc_group_add_to_tree(struct tipc_group *grp,
                else if (key > nkey)
                        n = &(*n)->rb_right;
                else
-                       return;
+                       return -EEXIST;
        }
        rb_link_node(&m->tree_node, parent, n);
        rb_insert_color(&m->tree_node, &grp->members);
+       return 0;
 }
 
 static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
@@ -302,6 +303,7 @@ static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
                                                    u32 instance, int state)
 {
        struct tipc_member *m;
+       int ret;
 
        m = kzalloc(sizeof(*m), GFP_ATOMIC);
        if (!m)
@@ -314,8 +316,12 @@ static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
        m->port = port;
        m->instance = instance;
        m->bc_acked = grp->bc_snd_nxt - 1;
+       ret = tipc_group_add_to_tree(grp, m);
+       if (ret < 0) {
+               kfree(m);
+               return NULL;
+       }
        grp->member_cnt++;
-       tipc_group_add_to_tree(grp, m);
        tipc_nlist_add(&grp->dests, m->node);
        m->state = state;
        return m;
index b736255..cef38a9 100644 (file)
@@ -532,7 +532,8 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
  * tipc_link_bc_create - create new link to be used for broadcast
  * @net: pointer to associated network namespace
  * @mtu: mtu to be used initially if no peers
- * @window: send window to be used
+ * @min_win: minimal send window to be used by link
+ * @max_win: maximal send window to be used by link
  * @inputq: queue to put messages ready for delivery
  * @namedq: queue to put binding table update messages ready for delivery
  * @link: return value, pointer to put the created link
index 848fae6..52e93ba 100644 (file)
@@ -150,7 +150,8 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
        if (fragid == FIRST_FRAGMENT) {
                if (unlikely(head))
                        goto err;
-               if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
+               frag = skb_unshare(frag, GFP_ATOMIC);
+               if (unlikely(!frag))
                        goto err;
                head = *headbuf = frag;
                *buf = NULL;
index ebd280e..11b27dd 100644 (file)
@@ -2771,10 +2771,7 @@ static int tipc_shutdown(struct socket *sock, int how)
 
        trace_tipc_sk_shutdown(sk, NULL, TIPC_DUMP_ALL, " ");
        __tipc_shutdown(sock, TIPC_CONN_SHUTDOWN);
-       if (tipc_sk_type_connectionless(sk))
-               sk->sk_shutdown = SHUTDOWN_MASK;
-       else
-               sk->sk_shutdown = SEND_SHUTDOWN;
+       sk->sk_shutdown = SHUTDOWN_MASK;
 
        if (sk->sk_state == TIPC_DISCONNECTING) {
                /* Discard any unreceived messages */
index 9a3d9fe..95ab554 100644 (file)
@@ -2143,10 +2143,15 @@ 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);
        struct tls_rec *rec, *tmp;
+       int pending;
 
        /* Wait for any pending async encryptions to complete */
-       smp_store_mb(ctx->async_notify, true);
-       if (atomic_read(&ctx->encrypt_pending))
+       spin_lock_bh(&ctx->encrypt_compl_lock);
+       ctx->async_notify = true;
+       pending = atomic_read(&ctx->encrypt_pending);
+       spin_unlock_bh(&ctx->encrypt_compl_lock);
+
+       if (pending)
                crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
 
        tls_tx_records(sk, -1);
index faf7485..27026f5 100644 (file)
@@ -217,6 +217,7 @@ config LIB80211_CRYPT_WEP
 
 config LIB80211_CRYPT_CCMP
        tristate
+       select CRYPTO
        select CRYPTO_AES
        select CRYPTO_CCM
 
index 2c9e9a2..7fd45f6 100644 (file)
@@ -4172,6 +4172,9 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       if (key.idx < 0)
+               return -EINVAL;
+
        if (info->attrs[NL80211_ATTR_MAC])
                mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
index 4a9ff9e..6fa99df 100644 (file)
@@ -95,7 +95,7 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
                /* see 802.11ax D6.1 27.3.23.2 */
                if (chan == 2)
                        return MHZ_TO_KHZ(5935);
-               if (chan <= 253)
+               if (chan <= 233)
                        return MHZ_TO_KHZ(5950 + chan * 5);
                break;
        case NL80211_BAND_60GHZ:
index e97db37..b010bfd 100644 (file)
@@ -303,10 +303,10 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
 
 static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 {
+       u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom;
        bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
-       u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
        u64 npgs, addr = mr->addr, size = mr->len;
-       unsigned int chunks, chunks_per_page;
+       unsigned int chunks, chunks_rem;
        int err;
 
        if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
@@ -336,19 +336,18 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        if ((addr + size) < addr)
                return -EINVAL;
 
-       npgs = size >> PAGE_SHIFT;
+       npgs = div_u64_rem(size, PAGE_SIZE, &npgs_rem);
+       if (npgs_rem)
+               npgs++;
        if (npgs > U32_MAX)
                return -EINVAL;
 
-       chunks = (unsigned int)div_u64(size, chunk_size);
+       chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem);
        if (chunks == 0)
                return -EINVAL;
 
-       if (!unaligned_chunks) {
-               chunks_per_page = PAGE_SIZE / chunk_size;
-               if (chunks < chunks_per_page || chunks % chunks_per_page)
-                       return -EINVAL;
-       }
+       if (!unaligned_chunks && chunks_rem)
+               return -EINVAL;
 
        if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
                return -EINVAL;
index c323162..6c5e09e 100644 (file)
@@ -377,15 +377,30 @@ static int xsk_generic_xmit(struct sock *sk)
                skb_shinfo(skb)->destructor_arg = (void *)(long)desc.addr;
                skb->destructor = xsk_destruct_skb;
 
+               /* Hinder dev_direct_xmit from freeing the packet and
+                * therefore completing it in the destructor
+                */
+               refcount_inc(&skb->users);
                err = dev_direct_xmit(skb, xs->queue_id);
+               if  (err == NETDEV_TX_BUSY) {
+                       /* Tell user-space to retry the send */
+                       skb->destructor = sock_wfree;
+                       /* Free skb without triggering the perf drop trace */
+                       consume_skb(skb);
+                       err = -EAGAIN;
+                       goto out;
+               }
+
                xskq_cons_release(xs->tx);
                /* Ignore NET_XMIT_CN as packet might have been sent */
-               if (err == NET_XMIT_DROP || err == NETDEV_TX_BUSY) {
+               if (err == NET_XMIT_DROP) {
                        /* SKB completed but not sent */
+                       kfree_skb(skb);
                        err = -EBUSY;
                        goto out;
                }
 
+               consume_skb(skb);
                sent_frame = true;
        }
 
index 827ccdf..1f08ebf 100644 (file)
@@ -29,8 +29,12 @@ static void handle_nonesp(struct espintcp_ctx *ctx, struct sk_buff *skb,
 
 static void handle_esp(struct sk_buff *skb, struct sock *sk)
 {
+       struct tcp_skb_cb *tcp_cb = (struct tcp_skb_cb *)skb->cb;
+
        skb_reset_transport_header(skb);
-       memset(skb->cb, 0, sizeof(skb->cb));
+
+       /* restore IP CB, we need at least IP6CB->nhoff */
+       memmove(skb->cb, &tcp_cb->header, sizeof(tcp_cb->header));
 
        rcu_read_lock();
        skb->dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
index eb81819..a8f6611 100644 (file)
@@ -303,7 +303,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
        }
 
        mtu = dst_mtu(dst);
-       if (!skb->ignore_df && skb->len > mtu) {
+       if (skb->len > mtu) {
                skb_dst_update_pmtu_no_confirm(skb, mtu);
 
                if (skb->protocol == htons(ETH_P_IPV6)) {
index 69520ad..efc89a9 100644 (file)
@@ -1019,7 +1019,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
         */
        if (x->km.state == XFRM_STATE_VALID) {
                if ((x->sel.family &&
-                    !xfrm_selector_match(&x->sel, fl, x->sel.family)) ||
+                    (x->sel.family != family ||
+                     !xfrm_selector_match(&x->sel, fl, family))) ||
                    !security_xfrm_state_pol_flow_match(x, pol, fl))
                        return;
 
@@ -1032,7 +1033,9 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
                *acq_in_progress = 1;
        } else if (x->km.state == XFRM_STATE_ERROR ||
                   x->km.state == XFRM_STATE_EXPIRED) {
-               if (xfrm_selector_match(&x->sel, fl, x->sel.family) &&
+               if ((!x->sel.family ||
+                    (x->sel.family == family &&
+                     xfrm_selector_match(&x->sel, fl, family))) &&
                    security_xfrm_state_pol_flow_match(x, pol, fl))
                        *error = -ESRCH;
        }
@@ -1072,7 +1075,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
                    tmpl->mode == x->props.mode &&
                    tmpl->id.proto == x->id.proto &&
                    (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
-                       xfrm_state_look_at(pol, x, fl, encap_family,
+                       xfrm_state_look_at(pol, x, fl, family,
                                           &best, &acquire_in_progress, &error);
        }
        if (best || acquire_in_progress)
@@ -1089,7 +1092,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
                    tmpl->mode == x->props.mode &&
                    tmpl->id.proto == x->id.proto &&
                    (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
-                       xfrm_state_look_at(pol, x, fl, encap_family,
+                       xfrm_state_look_at(pol, x, fl, family,
                                           &best, &acquire_in_progress, &error);
        }
 
@@ -1441,6 +1444,30 @@ out:
 EXPORT_SYMBOL(xfrm_state_add);
 
 #ifdef CONFIG_XFRM_MIGRATE
+static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *security)
+{
+       struct xfrm_user_sec_ctx *uctx;
+       int size = sizeof(*uctx) + security->ctx_len;
+       int err;
+
+       uctx = kmalloc(size, GFP_KERNEL);
+       if (!uctx)
+               return -ENOMEM;
+
+       uctx->exttype = XFRMA_SEC_CTX;
+       uctx->len = size;
+       uctx->ctx_doi = security->ctx_doi;
+       uctx->ctx_alg = security->ctx_alg;
+       uctx->ctx_len = security->ctx_len;
+       memcpy(uctx + 1, security->ctx_str, security->ctx_len);
+       err = security_xfrm_state_alloc(x, uctx);
+       kfree(uctx);
+       if (err)
+               return err;
+
+       return 0;
+}
+
 static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
                                           struct xfrm_encap_tmpl *encap)
 {
@@ -1497,6 +1524,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
                        goto error;
        }
 
+       if (orig->security)
+               if (clone_security(x, orig->security))
+                       goto error;
+
        if (orig->coaddr) {
                x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
                                    GFP_KERNEL);
@@ -1510,6 +1541,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
        }
 
        memcpy(&x->mark, &orig->mark, sizeof(x->mark));
+       memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
 
        if (xfrm_init_state(x) < 0)
                goto error;
@@ -1521,7 +1553,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
        x->tfcpad = orig->tfcpad;
        x->replay_maxdiff = orig->replay_maxdiff;
        x->replay_maxage = orig->replay_maxage;
-       x->curlft.add_time = orig->curlft.add_time;
+       memcpy(&x->curlft, &orig->curlft, sizeof(x->curlft));
        x->km.state = orig->km.state;
        x->km.seq = orig->km.seq;
        x->replay = orig->replay;
index a698ece..4852bf4 100644 (file)
@@ -9,7 +9,7 @@ dtc-objs        := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
 dtc-objs       += dtc-lexer.lex.o dtc-parser.tab.o
 
 # Source files need to get at the userspace version of libfdt_env.h to compile
-HOST_EXTRACFLAGS := -I $(srctree)/$(src)/libfdt
+HOST_EXTRACFLAGS += -I $(srctree)/$(src)/libfdt
 
 ifeq ($(shell pkg-config --exists yaml-0.1 2>/dev/null && echo yes),)
 ifneq ($(CHECK_DT_BINDING)$(CHECK_DTBS),)
index 0096cd9..7ecd2cc 100644 (file)
@@ -82,6 +82,7 @@ static char *sym_name(const struct sym_entry *s)
 
 static bool is_ignored_symbol(const char *name, char type)
 {
+       /* Symbol names that exactly match to the following are ignored.*/
        static const char * const ignored_symbols[] = {
                /*
                 * Symbols which vary between passes. Passes 1 and 2 must have
@@ -104,6 +105,7 @@ static bool is_ignored_symbol(const char *name, char type)
                NULL
        };
 
+       /* Symbol names that begin with the following are ignored.*/
        static const char * const ignored_prefixes[] = {
                "$",                    /* local symbols for ARM, MIPS, etc. */
                ".LASANPC",             /* s390 kasan local symbols */
@@ -113,6 +115,7 @@ static bool is_ignored_symbol(const char *name, char type)
                NULL
        };
 
+       /* Symbol names that end with the following are ignored.*/
        static const char * const ignored_suffixes[] = {
                "_from_arm",            /* arm */
                "_from_thumb",          /* arm */
@@ -120,9 +123,15 @@ static bool is_ignored_symbol(const char *name, char type)
                NULL
        };
 
+       /* Symbol names that contain the following are ignored.*/
+       static const char * const ignored_matches[] = {
+               ".long_branch.",        /* ppc stub */
+               ".plt_branch.",         /* ppc stub */
+               NULL
+       };
+
        const char * const *p;
 
-       /* Exclude symbols which vary between passes. */
        for (p = ignored_symbols; *p; p++)
                if (!strcmp(name, *p))
                        return true;
@@ -138,6 +147,11 @@ static bool is_ignored_symbol(const char *name, char type)
                        return true;
        }
 
+       for (p = ignored_matches; *p; p++) {
+               if (strstr(name, *p))
+                       return true;
+       }
+
        if (type == 'U' || type == 'u')
                return true;
        /* exclude debugging symbols */
index d4ca829..8454649 100644 (file)
@@ -66,23 +66,6 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
                fprintf(stderr, "Error in writing or end of file.\n");
 }
 
-/* menu.c */
-void _menu_init(void);
-void menu_warn(struct menu *menu, const char *fmt, ...);
-struct menu *menu_add_menu(void);
-void menu_end_menu(void);
-void menu_add_entry(struct symbol *sym);
-void menu_add_dep(struct expr *dep);
-void menu_add_visibility(struct expr *dep);
-struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
-void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
-void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
-void menu_add_option_modules(void);
-void menu_add_option_defconfig_list(void);
-void menu_add_option_allnoconfig_y(void);
-void menu_finalize(struct menu *parent);
-void menu_set_type(int type);
-
 /* util.c */
 struct file *file_lookup(const char *name);
 void *xmalloc(size_t size);
@@ -109,6 +92,36 @@ void str_append(struct gstr *gs, const char *s);
 void str_printf(struct gstr *gs, const char *fmt, ...);
 const char *str_get(struct gstr *gs);
 
+/* menu.c */
+void _menu_init(void);
+void menu_warn(struct menu *menu, const char *fmt, ...);
+struct menu *menu_add_menu(void);
+void menu_end_menu(void);
+void menu_add_entry(struct symbol *sym);
+void menu_add_dep(struct expr *dep);
+void menu_add_visibility(struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
+void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+void menu_add_option_modules(void);
+void menu_add_option_defconfig_list(void);
+void menu_add_option_allnoconfig_y(void);
+void menu_finalize(struct menu *parent);
+void menu_set_type(int type);
+
+extern struct menu rootmenu;
+
+bool menu_is_empty(struct menu *menu);
+bool menu_is_visible(struct menu *menu);
+bool menu_has_prompt(struct menu *menu);
+const char *menu_get_prompt(struct menu *menu);
+struct menu *menu_get_root_menu(struct menu *menu);
+struct menu *menu_get_parent_menu(struct menu *menu);
+bool menu_has_help(struct menu *menu);
+const char *menu_get_help(struct menu *menu);
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
+void menu_get_ext_help(struct menu *menu, struct gstr *help);
+
 /* symbol.c */
 void sym_clear_all_valid(void);
 struct symbol *sym_choice_default(struct symbol *sym);
index f9ab982..9e81be3 100644 (file)
@@ -12,20 +12,6 @@ bool conf_get_changed(void);
 void conf_set_changed_callback(void (*fn)(void));
 void conf_set_message_callback(void (*fn)(const char *s));
 
-/* menu.c */
-extern struct menu rootmenu;
-
-bool menu_is_empty(struct menu *menu);
-bool menu_is_visible(struct menu *menu);
-bool menu_has_prompt(struct menu *menu);
-const char * menu_get_prompt(struct menu *menu);
-struct menu * menu_get_root_menu(struct menu *menu);
-struct menu * menu_get_parent_menu(struct menu *menu);
-bool menu_has_help(struct menu *menu);
-const char * menu_get_help(struct menu *menu);
-struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
-void menu_get_ext_help(struct menu *menu, struct gstr *help);
-
 /* symbol.c */
 extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
 
index 8638785..8ce624a 100644 (file)
@@ -1108,6 +1108,11 @@ void ConfigInfoView::menuInfo(void)
                if (showDebug())
                        stream << debug_info(sym);
 
+               struct gstr help_gstr = str_new();
+
+               menu_get_ext_help(_menu, &help_gstr);
+               stream << print_filter(str_get(&help_gstr));
+               str_free(&help_gstr);
        } else if (_menu->prompt) {
                stream << "<big><b>";
                stream << print_filter(_menu->prompt->text);
@@ -1119,11 +1124,11 @@ void ConfigInfoView::menuInfo(void)
                                           expr_print_help, &stream, E_NONE);
                                stream << "<br><br>";
                        }
+
+                       stream << "defined at " << _menu->file->name << ":"
+                              << _menu->lineno << "<br><br>";
                }
        }
-       if (showDebug())
-               stream << "defined at " << _menu->file->name << ":"
-                      << _menu->lineno << "<br><br>";
 
        setText(info);
 }
@@ -1276,7 +1281,7 @@ void ConfigInfoView::clicked(const QUrl &url)
        }
 
        free(result);
-       delete data;
+       delete[] data;
 }
 
 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
index f253681..feb2efa 100644 (file)
@@ -589,7 +589,7 @@ explictly||explicitly
 expresion||expression
 exprimental||experimental
 extened||extended
-exteneded||extended||extended
+exteneded||extended
 extensability||extensibility
 extention||extension
 extenstion||extension
index 32d3f53..850f4cc 100755 (executable)
@@ -26,7 +26,11 @@ else
 fi
 
 # ignore userspace tools
-ignore="$ignore ( -path ${tree}tools ) -prune -o"
+if [ -n "$COMPILED_SOURCE" ]; then
+       ignore="$ignore ( -path ./tools ) -prune -o"
+else
+       ignore="$ignore ( -path ${tree}tools ) -prune -o"
+fi
 
 # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH
 if [ "${ALLSOURCE_ARCHS}" = "" ]; then
@@ -92,7 +96,7 @@ all_sources()
 all_compiled_sources()
 {
        realpath -es $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) \
-               include/generated/autoconf.h $(find -name "*.cmd" -exec \
+               include/generated/autoconf.h $(find $ignore -name "*.cmd" -exec \
                grep -Poh '(?(?=^source_.* \K).*|(?=^  \K\S).*(?= \\))' {} \+ |
                awk '!a[$0]++') | sort -u
 }
index 43ab0ad..04375df 100644 (file)
@@ -354,7 +354,8 @@ static bool match_exception_partial(struct list_head *exceptions, short type,
 {
        struct dev_exception_item *ex;
 
-       list_for_each_entry_rcu(ex, exceptions, list) {
+       list_for_each_entry_rcu(ex, exceptions, list,
+                               lockdep_is_held(&devcgroup_mutex)) {
                if ((type & DEVCG_DEV_BLOCK) && !(ex->type & DEVCG_DEV_BLOCK))
                        continue;
                if ((type & DEVCG_DEV_CHAR) && !(ex->type & DEVCG_DEV_CHAR))
index 496dcde..9790f51 100644 (file)
@@ -343,7 +343,7 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
        struct hpi_message hm;
        struct hpi_response hr;
        struct hpi_adapter adapter;
-       struct hpi_pci pci;
+       struct hpi_pci pci = { 0 };
 
        memset(&adapter, 0, sizeof(adapter));
 
@@ -499,7 +499,7 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
        return 0;
 
 err:
-       for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
+       while (--idx >= 0) {
                if (pci.ap_mem_base[idx]) {
                        iounmap(pci.ap_mem_base[idx]);
                        pci.ap_mem_base[idx] = NULL;
index c521a1f..d4f17b4 100644 (file)
@@ -2475,7 +2475,6 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
-       SND_PCI_QUIRK(0x1462, 0x9c37, "MSI X570-A PRO", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
@@ -3428,7 +3427,11 @@ static void alc256_shutup(struct hda_codec *codec)
 
        /* 3k pull low control for Headset jack. */
        /* NOTE: call this before clearing the pin, otherwise codec stalls */
-       alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
+       /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
+        * when booting with headset plugged. So skip setting it for the codec alc257
+        */
+       if (codec->core.vendor_id != 0x10ec0257)
+               alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
 
        if (!spec->no_shutup_pins)
                snd_hda_codec_write(codec, hp_pin, 0,
@@ -5993,6 +5996,40 @@ static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
                snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
 }
 
+
+static void alc294_gx502_toggle_output(struct hda_codec *codec,
+                                       struct hda_jack_callback *cb)
+{
+       /* The Windows driver sets the codec up in a very different way where
+        * it appears to leave 0x10 = 0x8a20 set. For Linux we need to toggle it
+        */
+       if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
+               alc_write_coef_idx(codec, 0x10, 0x8a20);
+       else
+               alc_write_coef_idx(codec, 0x10, 0x0a20);
+}
+
+static void alc294_fixup_gx502_hp(struct hda_codec *codec,
+                                       const struct hda_fixup *fix, int action)
+{
+       /* Pin 0x21: headphones/headset mic */
+       if (!is_jack_detectable(codec, 0x21))
+               return;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               snd_hda_jack_detect_enable_callback(codec, 0x21,
+                               alc294_gx502_toggle_output);
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               /* Make sure to start in a correct state, i.e. if
+                * headphones have been plugged in before powering up the system
+                */
+               alc294_gx502_toggle_output(codec, NULL);
+               break;
+       }
+}
+
 static void  alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
                              const struct hda_fixup *fix, int action)
 {
@@ -6017,6 +6054,7 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
 #include "hp_x360_helper.c"
 
 enum {
+       ALC269_FIXUP_GPIO2,
        ALC269_FIXUP_SONY_VAIO,
        ALC275_FIXUP_SONY_VAIO_GPIO2,
        ALC269_FIXUP_DELL_M101Z,
@@ -6173,6 +6211,9 @@ enum {
        ALC285_FIXUP_THINKPAD_HEADSET_JACK,
        ALC294_FIXUP_ASUS_HPE,
        ALC294_FIXUP_ASUS_COEF_1B,
+       ALC294_FIXUP_ASUS_GX502_HP,
+       ALC294_FIXUP_ASUS_GX502_PINS,
+       ALC294_FIXUP_ASUS_GX502_VERBS,
        ALC285_FIXUP_HP_GPIO_LED,
        ALC285_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_MUTE_LED,
@@ -6191,9 +6232,14 @@ enum {
        ALC269_FIXUP_LEMOTE_A1802,
        ALC269_FIXUP_LEMOTE_A190X,
        ALC256_FIXUP_INTEL_NUC8_RUGGED,
+       ALC255_FIXUP_XIAOMI_HEADSET_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
+       [ALC269_FIXUP_GPIO2] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_gpio2,
+       },
        [ALC269_FIXUP_SONY_VAIO] = {
                .type = HDA_FIXUP_PINCTLS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -7013,6 +7059,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC233_FIXUP_LENOVO_MULTI_CODECS] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc233_alc662_fixup_lenovo_dual_codecs,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_GPIO2
        },
        [ALC233_FIXUP_ACER_HEADSET_MIC] = {
                .type = HDA_FIXUP_VERBS,
@@ -7338,6 +7386,33 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
        },
+       [ALC294_FIXUP_ASUS_GX502_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11050 }, /* front HP mic */
+                       { 0x1a, 0x01a11830 }, /* rear external mic */
+                       { 0x21, 0x03211020 }, /* front HP out */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_GX502_VERBS
+       },
+       [ALC294_FIXUP_ASUS_GX502_VERBS] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* set 0x15 to HP-OUT ctrl */
+                       { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+                       /* unmute the 0x15 amp */
+                       { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_GX502_HP
+       },
+       [ALC294_FIXUP_ASUS_GX502_HP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc294_fixup_gx502_hp,
+       },
        [ALC294_FIXUP_ASUS_COEF_1B] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -7527,6 +7602,16 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MODE
        },
+       [ALC255_FIXUP_XIAOMI_HEADSET_MIC] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC289_FIXUP_ASUS_GA401
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7711,6 +7796,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
        SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
+       SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
        SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
        SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
@@ -7823,6 +7909,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI),
        SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101),
        SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
+       SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
        SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE),
        SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802),
@@ -8000,6 +8087,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
        {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
        {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
+       {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
        {}
 };
 #define ALC225_STANDARD_PINS \
index 5fe7247..e4675cf 100644 (file)
@@ -838,8 +838,8 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
 
        /* Regmap Initialization */
        regmap = devm_regmap_init_sdw(slave, &max98373_sdw_regmap);
-       if (!regmap)
-               return -EINVAL;
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
 
        return max98373_init(slave, regmap);
 }
index 5e445fe..821e739 100644 (file)
@@ -306,6 +306,13 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
        struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(dai->component);
        int ret;
 
+       /*
+        * Some sound card sets 0 Hz as reset,
+        * but it is impossible to set. Ignore it here
+        */
+       if (freq == 0)
+               return 0;
+
        if (freq > PCM3168A_MAX_SYSCLK)
                return -EINVAL;
 
index b0ba0d2..56e952a 100644 (file)
@@ -684,8 +684,8 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
 
        /* Regmap Initialization */
        regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap);
-       if (!regmap)
-               return -EINVAL;
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
 
        rt1308_sdw_init(&slave->dev, regmap, slave);
 
index 4d14048..1d24bf0 100644 (file)
@@ -452,8 +452,8 @@ static int rt700_sdw_probe(struct sdw_slave *slave,
 
        /* Regmap Initialization */
        sdw_regmap = devm_regmap_init_sdw(slave, &rt700_sdw_regmap);
-       if (!sdw_regmap)
-               return -EINVAL;
+       if (IS_ERR(sdw_regmap))
+               return PTR_ERR(sdw_regmap);
 
        regmap = devm_regmap_init(&slave->dev, NULL,
                &slave->dev, &rt700_regmap);
index 45b9289..7efff13 100644 (file)
@@ -452,8 +452,8 @@ static int rt711_sdw_probe(struct sdw_slave *slave,
 
        /* Regmap Initialization */
        sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap);
-       if (!sdw_regmap)
-               return -EINVAL;
+       if (IS_ERR(sdw_regmap))
+               return PTR_ERR(sdw_regmap);
 
        regmap = devm_regmap_init(&slave->dev, NULL,
                &slave->dev, &rt711_regmap);
index d11b23d..68a3673 100644 (file)
@@ -527,8 +527,8 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
 
        /* Regmap Initialization */
        sdw_regmap = devm_regmap_init_sdw(slave, &rt715_sdw_regmap);
-       if (!sdw_regmap)
-               return -EINVAL;
+       if (IS_ERR(sdw_regmap))
+               return PTR_ERR(sdw_regmap);
 
        regmap = devm_regmap_init(&slave->dev, NULL, &slave->dev,
                &rt715_regmap);
index 5cd50d8..8efe206 100644 (file)
@@ -842,6 +842,18 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
        if (ret)
                goto out;
 
+       if (adcx140->supply_areg == NULL)
+               sleep_cfg_val |= ADCX140_AREG_INTERNAL;
+
+       ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
+       if (ret) {
+               dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
+               goto out;
+       }
+
+       /* 8.4.3: Wait >= 1ms after entering active mode. */
+       usleep_range(1000, 100000);
+
        pdm_count = device_property_count_u32(adcx140->dev,
                                              "ti,pdm-edge-select");
        if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) {
@@ -889,18 +901,6 @@ static int adcx140_codec_probe(struct snd_soc_component *component)
        if (ret)
                goto out;
 
-       if (adcx140->supply_areg == NULL)
-               sleep_cfg_val |= ADCX140_AREG_INTERNAL;
-
-       ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
-       if (ret) {
-               dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
-               goto out;
-       }
-
-       /* 8.4.3: Wait >= 1ms after entering active mode. */
-       usleep_range(1000, 100000);
-
        ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG,
                                ADCX140_MIC_BIAS_VAL_MSK |
                                ADCX140_MIC_BIAS_VREF_MSK, bias_cfg);
@@ -980,6 +980,8 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
        if (!adcx140)
                return -ENOMEM;
 
+       adcx140->dev = &i2c->dev;
+
        adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev,
                                                      "reset", GPIOD_OUT_LOW);
        if (IS_ERR(adcx140->gpio_reset))
@@ -1007,7 +1009,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c,
                        ret);
                return ret;
        }
-       adcx140->dev = &i2c->dev;
+
        i2c_set_clientdata(i2c, adcx140);
 
        return devm_snd_soc_register_component(&i2c->dev,
index 038be66..fc9ea19 100644 (file)
@@ -3514,6 +3514,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
                return -EINVAL;
        }
 
+       pm_runtime_get_sync(component->dev);
+
        switch (micbias) {
        case 1:
                micdet = &wm8994->micdet[0];
@@ -3561,6 +3563,8 @@ int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
 
        snd_soc_dapm_sync(dapm);
 
+       pm_runtime_put(component->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@@ -3932,6 +3936,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
                return -EINVAL;
        }
 
+       pm_runtime_get_sync(component->dev);
+
        if (jack) {
                snd_soc_dapm_force_enable_pin(dapm, "CLK_SYS");
                snd_soc_dapm_sync(dapm);
@@ -4000,6 +4006,8 @@ int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *
                snd_soc_dapm_sync(dapm);
        }
 
+       pm_runtime_put(component->dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm8958_mic_detect);
@@ -4193,11 +4201,13 @@ static int wm8994_component_probe(struct snd_soc_component *component)
                        wm8994->hubs.dcs_readback_mode = 2;
                        break;
                }
+               wm8994->hubs.micd_scthr = true;
                break;
 
        case WM8958:
                wm8994->hubs.dcs_readback_mode = 1;
                wm8994->hubs.hp_startup_mode = 1;
+               wm8994->hubs.micd_scthr = true;
 
                switch (control->revision) {
                case 0:
index 891effe..0c88184 100644 (file)
@@ -1223,6 +1223,9 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component,
                snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
                                    WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
 
+       if (!hubs->micd_scthr)
+               return 0;
+
        snd_soc_component_update_bits(component, WM8993_MICBIAS,
                            WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
                            WM8993_MICB1_LVL | WM8993_MICB2_LVL,
index 4b8e5f0..988b29e 100644 (file)
@@ -27,6 +27,7 @@ struct wm_hubs_data {
        int hp_startup_mode;
        int series_startup;
        int no_series_update;
+       bool micd_scthr;
 
        bool no_cache_dac_hp_direct;
        struct list_head dcs_cache;
index b1cac7a..fba2c79 100644 (file)
@@ -333,6 +333,17 @@ static int sst_media_open(struct snd_pcm_substream *substream,
        if (ret_val < 0)
                goto out_power_up;
 
+       /*
+        * Make sure the period to be multiple of 1ms to align the
+        * design of firmware. Apply same rule to buffer size to make
+        * sure alsa could always find a value for period size
+        * regardless the buffer size given by user space.
+        */
+       snd_pcm_hw_constraint_step(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 48);
+       snd_pcm_hw_constraint_step(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 48);
+
        /* Make sure, that the period size is always even */
        snd_pcm_hw_constraint_step(substream->runtime, 0,
                           SNDRV_PCM_HW_PARAM_PERIODS, 2);
index 479992f..fc20274 100644 (file)
@@ -591,6 +591,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_SSP0_AIF1 |
                                        BYT_RT5640_MCLK_EN),
        },
+       {       /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
+               },
+               .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+                                       BYT_RT5640_MONO_SPEAKER |
+                                       BYT_RT5640_SSP0_AIF1 |
+                                       BYT_RT5640_MCLK_EN),
+       },
        {
                /* MPMAN MPWIN895CL */
                .matches = {
index ca49000..bc50eda 100644 (file)
@@ -181,7 +181,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
        struct snd_soc_dai *dai;
 
        for_each_card_rtds(card, rtd) {
-               if (!strstr(rtd->dai_link->codecs->name, "ehdaudio"))
+               if (!strstr(rtd->dai_link->codecs->name, "ehdaudio0D0"))
                        continue;
                dai = asoc_rtd_to_codec(rtd, 0);
                hda_pvt = snd_soc_component_get_drvdata(dai->component);
index 1a69615..b6e63ea 100644 (file)
@@ -66,6 +66,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
        int j;
        int ret = 0;
 
+       /* set spk pin by playback only */
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               return 0;
+
        for_each_rtd_codec_dais(rtd, j, codec_dai) {
                struct snd_soc_component *component = codec_dai->component;
                struct snd_soc_dapm_context *dapm =
@@ -86,9 +90,6 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd)
                case SNDRV_PCM_TRIGGER_STOP:
                case SNDRV_PCM_TRIGGER_SUSPEND:
                case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-                       /* Make sure no streams are active before disable pin */
-                       if (snd_soc_dai_active(codec_dai) != 1)
-                               break;
                        ret = snd_soc_dapm_disable_pin(dapm, pin_name);
                        if (!ret)
                                snd_soc_dapm_sync(dapm);
index de80e19..88c3f63 100644 (file)
@@ -243,92 +243,45 @@ static irqreturn_t hsw_irq(int irq, void *context)
        return ret;
 }
 
-#define CSR_DEFAULT_VALUE 0x8480040E
-#define ISC_DEFAULT_VALUE 0x0
-#define ISD_DEFAULT_VALUE 0x0
-#define IMC_DEFAULT_VALUE 0x7FFF0003
-#define IMD_DEFAULT_VALUE 0x7FFF0003
-#define IPCC_DEFAULT_VALUE 0x0
-#define IPCD_DEFAULT_VALUE 0x0
-#define CLKCTL_DEFAULT_VALUE 0x7FF
-#define CSR2_DEFAULT_VALUE 0x0
-#define LTR_CTRL_DEFAULT_VALUE 0x0
-#define HMD_CTRL_DEFAULT_VALUE 0x0
-
-static void hsw_set_shim_defaults(struct sst_dsp *sst)
-{
-       sst_dsp_shim_write_unlocked(sst, SST_CSR, CSR_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_ISRX, ISC_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_ISRD, ISD_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_IMRX, IMC_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_IMRD, IMD_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_IPCX, IPCC_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_IPCD, IPCD_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_CLKCTL, CLKCTL_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_CSR2, CSR2_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_LTRC, LTR_CTRL_DEFAULT_VALUE);
-       sst_dsp_shim_write_unlocked(sst, SST_HMDC, HMD_CTRL_DEFAULT_VALUE);
-}
-
-/* all clock-gating minus DCLCGE and DTCGE */
-#define SST_VDRTCL2_CG_OTHER   0xB7D
-
 static void hsw_set_dsp_D3(struct sst_dsp *sst)
 {
+       u32 val;
        u32 reg;
 
-       /* disable clock core gating */
+       /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg &= ~(SST_VDRTCL2_DCLCGE);
+       reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-       /* stall, reset and set 24MHz XOSC */
-       sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
-                       SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST,
-                       SST_CSR_24MHZ_LPCS | SST_CSR_STALL | SST_CSR_RST);
-
-       /* DRAM power gating all */
-       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
-       reg |= SST_VDRTCL0_ISRAMPGE_MASK |
-               SST_VDRTCL0_DSRAMPGE_MASK;
-       reg &= ~(SST_VDRTCL0_D3SRAMPGD);
-       reg |= SST_VDRTCL0_D3PGD;
-       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
-       udelay(50);
+       /* enable power gating and switch off DRAM & IRAM blocks */
+       val = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+       val |= SST_VDRTCL0_DSRAMPGE_MASK |
+               SST_VDRTCL0_ISRAMPGE_MASK;
+       val &= ~(SST_VDRTCL0_D3PGD | SST_VDRTCL0_D3SRAMPGD);
+       writel(val, sst->addr.pci_cfg + SST_VDRTCTL0);
 
-       /* PLL shutdown enable */
-       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg |= SST_VDRTCL2_APLLSE_MASK;
-       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+       /* switch off audio PLL */
+       val = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
+       val |= SST_VDRTCL2_APLLSE_MASK;
+       writel(val, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-       /* disable MCLK */
+       /* disable MCLK(clkctl.smos = 0) */
        sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
-                       SST_CLKCTL_MASK, 0);
-
-       /* switch clock gating */
-       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg |= SST_VDRTCL2_CG_OTHER;
-       reg &= ~(SST_VDRTCL2_DTCGE);
-       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
-       /* enable DTCGE separatelly */
-       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg |= SST_VDRTCL2_DTCGE;
-       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+               SST_CLKCTL_MASK, 0);
 
-       /* set shim defaults */
-       hsw_set_shim_defaults(sst);
-
-       /* set D3 */
-       reg = readl(sst->addr.pci_cfg + SST_PMCS);
-       reg |= SST_PMCS_PS_MASK;
-       writel(reg, sst->addr.pci_cfg + SST_PMCS);
+       /* Set D3 state, delay 50 us */
+       val = readl(sst->addr.pci_cfg + SST_PMCS);
+       val |= SST_PMCS_PS_MASK;
+       writel(val, sst->addr.pci_cfg + SST_PMCS);
        udelay(50);
 
-       /* enable clock core gating */
+       /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg |= SST_VDRTCL2_DCLCGE;
+       reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+
        udelay(50);
+
 }
 
 static void hsw_reset(struct sst_dsp *sst)
@@ -346,62 +299,75 @@ static void hsw_reset(struct sst_dsp *sst)
                SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL);
 }
 
-/* recommended CSR state for power-up */
-#define SST_CSR_D0_MASK (0x18A09C0C | SST_CSR_DCS_MASK)
-
 static int hsw_set_dsp_D0(struct sst_dsp *sst)
 {
-       u32 reg;
+       int tries = 10;
+       u32 reg, fw_dump_bit;
 
-       /* disable clock core gating */
+       /* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg &= ~(SST_VDRTCL2_DCLCGE);
+       reg &= ~(SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE);
        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-       /* switch clock gating */
-       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg |= SST_VDRTCL2_CG_OTHER;
-       reg &= ~(SST_VDRTCL2_DTCGE);
-       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
+       /* Disable D3PG (VDRTCTL0.D3PGD = 1) */
+       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+       reg |= SST_VDRTCL0_D3PGD;
+       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
 
-       /* set D0 */
+       /* Set D0 state */
        reg = readl(sst->addr.pci_cfg + SST_PMCS);
-       reg &= ~(SST_PMCS_PS_MASK);
+       reg &= ~SST_PMCS_PS_MASK;
        writel(reg, sst->addr.pci_cfg + SST_PMCS);
 
-       /* DRAM power gating none */
-       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
-       reg &= ~(SST_VDRTCL0_ISRAMPGE_MASK |
-               SST_VDRTCL0_DSRAMPGE_MASK);
-       reg |= SST_VDRTCL0_D3SRAMPGD;
-       reg |= SST_VDRTCL0_D3PGD;
-       writel(reg, sst->addr.pci_cfg + SST_VDRTCTL0);
-       mdelay(10);
+       /* check that ADSP shim is enabled */
+       while (tries--) {
+               reg = readl(sst->addr.pci_cfg + SST_PMCS) & SST_PMCS_PS_MASK;
+               if (reg == 0)
+                       goto finish;
+
+               msleep(1);
+       }
+
+       return -ENODEV;
 
-       /* set shim defaults */
-       hsw_set_shim_defaults(sst);
+finish:
+       /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */
+       sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
+               SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0);
+
+       /* stall DSP core, set clk to 192/96Mhz */
+       sst_dsp_shim_update_bits_unlocked(sst,
+               SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK,
+               SST_CSR_STALL | SST_CSR_DCS(4));
 
-       /* restore MCLK */
+       /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
        sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL,
-                       SST_CLKCTL_MASK, SST_CLKCTL_MASK);
+               SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0,
+               SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0);
 
-       /* PLL shutdown disable */
+       /* Stall and reset core, set CSR */
+       hsw_reset(sst);
+
+       /* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg &= ~(SST_VDRTCL2_APLLSE_MASK);
+       reg |= SST_VDRTCL2_DCLCGE | SST_VDRTCL2_DTCGE;
        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-       sst_dsp_shim_update_bits_unlocked(sst, SST_CSR,
-                       SST_CSR_D0_MASK, SST_CSR_SBCS0 | SST_CSR_SBCS1 |
-                       SST_CSR_STALL | SST_CSR_DCS(4));
        udelay(50);
 
-       /* enable clock core gating */
+       /* switch on audio PLL */
        reg = readl(sst->addr.pci_cfg + SST_VDRTCTL2);
-       reg |= SST_VDRTCL2_DCLCGE;
+       reg &= ~SST_VDRTCL2_APLLSE_MASK;
        writel(reg, sst->addr.pci_cfg + SST_VDRTCTL2);
 
-       /* clear reset */
-       sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_RST, 0);
+       /* set default power gating control, enable power gating control for all blocks. that is,
+       can't be accessed, please enable each block before accessing. */
+       reg = readl(sst->addr.pci_cfg + SST_VDRTCTL0);
+       reg |= SST_VDRTCL0_DSRAMPGE_MASK | SST_VDRTCL0_ISRAMPGE_MASK;
+       /* for D0, always enable the block(DSRAM[0]) used for FW dump */
+       fw_dump_bit = 1 << SST_VDRTCL0_DSRAMPGE_SHIFT;
+       writel(reg & ~fw_dump_bit, sst->addr.pci_cfg + SST_VDRTCTL0);
+
 
        /* disable DMA finish function for SSP0 & SSP1 */
        sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1,
@@ -418,6 +384,12 @@ static int hsw_set_dsp_D0(struct sst_dsp *sst)
        sst_dsp_shim_update_bits(sst, SST_IMRD, (SST_IMRD_DONE | SST_IMRD_BUSY |
                                SST_IMRD_SSP0 | SST_IMRD_DMAC), 0x0);
 
+       /* clear IPC registers */
+       sst_dsp_shim_write(sst, SST_IPCX, 0x0);
+       sst_dsp_shim_write(sst, SST_IPCD, 0x0);
+       sst_dsp_shim_write(sst, 0x80, 0x6);
+       sst_dsp_shim_write(sst, 0xe0, 0x300a);
+
        return 0;
 }
 
@@ -443,6 +415,11 @@ static void hsw_sleep(struct sst_dsp *sst)
 {
        dev_dbg(sst->dev, "HSW_PM dsp runtime suspend\n");
 
+       /* put DSP into reset and stall */
+       sst_dsp_shim_update_bits(sst, SST_CSR,
+               SST_CSR_24MHZ_LPCS | SST_CSR_RST | SST_CSR_STALL,
+               SST_CSR_RST | SST_CSR_STALL | SST_CSR_24MHZ_LPCS);
+
        hsw_set_dsp_D3(sst);
        dev_dbg(sst->dev, "HSW_PM dsp runtime suspend exit\n");
 }
index e711abc..d6adf7e 100644 (file)
@@ -18,6 +18,7 @@
 #define CTRL0_TODDR_SEL_RESAMPLE       BIT(30)
 #define CTRL0_TODDR_EXT_SIGNED         BIT(29)
 #define CTRL0_TODDR_PP_MODE            BIT(28)
+#define CTRL0_TODDR_SYNC_CH            BIT(27)
 #define CTRL0_TODDR_TYPE_MASK          GENMASK(15, 13)
 #define CTRL0_TODDR_TYPE(x)            ((x) << 13)
 #define CTRL0_TODDR_MSB_POS_MASK       GENMASK(12, 8)
@@ -189,10 +190,31 @@ static const struct axg_fifo_match_data axg_toddr_match_data = {
        .dai_drv                = &axg_toddr_dai_drv
 };
 
+static int g12a_toddr_dai_startup(struct snd_pcm_substream *substream,
+                                struct snd_soc_dai *dai)
+{
+       struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai);
+       int ret;
+
+       ret = axg_toddr_dai_startup(substream, dai);
+       if (ret)
+               return ret;
+
+       /*
+        * Make sure the first channel ends up in the at beginning of the output
+        * As weird as it looks, without this the first channel may be misplaced
+        * in memory, with a random shift of 2 channels.
+        */
+       regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_SYNC_CH,
+                          CTRL0_TODDR_SYNC_CH);
+
+       return 0;
+}
+
 static const struct snd_soc_dai_ops g12a_toddr_ops = {
        .prepare        = g12a_toddr_dai_prepare,
        .hw_params      = axg_toddr_dai_hw_params,
-       .startup        = axg_toddr_dai_startup,
+       .startup        = g12a_toddr_dai_startup,
        .shutdown       = axg_toddr_dai_shutdown,
 };
 
index 083413a..575e2ae 100644 (file)
@@ -143,6 +143,7 @@ static int apq8016_sbc_platform_probe(struct platform_device *pdev)
 
        card = &data->card;
        card->dev = dev;
+       card->owner = THIS_MODULE;
        card->dapm_widgets = apq8016_sbc_dapm_widgets;
        card->num_dapm_widgets = ARRAY_SIZE(apq8016_sbc_dapm_widgets);
 
index 2535496..1a69bae 100644 (file)
@@ -114,6 +114,7 @@ static int apq8096_platform_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        card->dev = dev;
+       card->owner = THIS_MODULE;
        dev_set_drvdata(dev, card);
        ret = qcom_snd_parse_of(card);
        if (ret)
index 5194d90..fd69cf8 100644 (file)
@@ -52,8 +52,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
 
        for_each_child_of_node(dev->of_node, np) {
                dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
-               if (!dlc)
-                       return -ENOMEM;
+               if (!dlc) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
 
                link->cpus      = &dlc[0];
                link->platforms = &dlc[1];
index 0d10fba..ab1bf23 100644 (file)
@@ -555,6 +555,7 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
        card->dapm_widgets = sdm845_snd_widgets;
        card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
        card->dev = dev;
+       card->owner = THIS_MODULE;
        dev_set_drvdata(dev, card);
        ret = qcom_snd_parse_of(card);
        if (ret)
index c0c388d..80c9cf2 100644 (file)
@@ -96,6 +96,7 @@ static int storm_platform_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        card->dev = &pdev->dev;
+       card->owner = THIS_MODULE;
 
        ret = snd_soc_of_parse_card_name(card, "qcom,model");
        if (ret) {
index 663e383..0544376 100644 (file)
@@ -834,6 +834,19 @@ struct snd_soc_dai *snd_soc_find_dai(
 }
 EXPORT_SYMBOL_GPL(snd_soc_find_dai);
 
+struct snd_soc_dai *snd_soc_find_dai_with_mutex(
+       const struct snd_soc_dai_link_component *dlc)
+{
+       struct snd_soc_dai *dai;
+
+       mutex_lock(&client_mutex);
+       dai = snd_soc_find_dai(dlc);
+       mutex_unlock(&client_mutex);
+
+       return dai;
+}
+EXPORT_SYMBOL_GPL(snd_soc_find_dai_with_mutex);
+
 static int soc_dai_link_sanity_check(struct snd_soc_card *card,
                                     struct snd_soc_dai_link *link)
 {
index 91a2551..0dbd312 100644 (file)
@@ -412,14 +412,14 @@ void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
                supported_codec = false;
 
                for_each_link_cpus(dai_link, i, cpu) {
-                       dai = snd_soc_find_dai(cpu);
+                       dai = snd_soc_find_dai_with_mutex(cpu);
                        if (dai && snd_soc_dai_stream_valid(dai, direction)) {
                                supported_cpu = true;
                                break;
                        }
                }
                for_each_link_codecs(dai_link, i, codec) {
-                       dai = snd_soc_find_dai(codec);
+                       dai = snd_soc_find_dai_with_mutex(codec);
                        if (dai && snd_soc_dai_stream_valid(dai, direction)) {
                                supported_codec = true;
                                break;
index 00ac1cb..4c9d4cd 100644 (file)
@@ -812,7 +812,7 @@ dynamic:
        return 0;
 
 config_err:
-       for_each_rtd_dais(rtd, i, dai)
+       for_each_rtd_dais_rollback(rtd, i, dai)
                snd_soc_dai_shutdown(dai, substream);
 
        snd_soc_link_shutdown(substream);
index 5c47de9..57feb47 100644 (file)
@@ -446,12 +446,12 @@ static const struct snd_soc_dai_ops ams_delta_dai_ops = {
 /* Will be used if the codec ever has its own digital_mute function */
 static int ams_delta_startup(struct snd_pcm_substream *substream)
 {
-       return ams_delta_digital_mute(NULL, 0, substream->stream);
+       return ams_delta_mute(NULL, 0, substream->stream);
 }
 
 static void ams_delta_shutdown(struct snd_pcm_substream *substream)
 {
-       ams_delta_digital_mute(NULL, 1, substream->stream);
+       ams_delta_mute(NULL, 1, substream->stream);
 }
 
 
index 5b43e9e..c369c81 100644 (file)
@@ -371,7 +371,6 @@ static const struct usbmix_name_map asus_rog_map[] = {
 };
 
 static const struct usbmix_name_map lenovo_p620_rear_map[] = {
-       { 19, NULL, 2 }, /* FU, Volume */
        { 19, NULL, 12 }, /* FU, Input Gain Pad */
        {}
 };
index 75bbdc6..892296d 100644 (file)
@@ -1678,12 +1678,13 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
            && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
                msleep(20);
 
-       /* Zoom R16/24, Logitech H650e, Jabra 550a, Kingston HyperX needs a tiny
-        * delay here, otherwise requests like get/set frequency return as
-        * failed despite actually succeeding.
+       /* Zoom R16/24, Logitech H650e/H570e, Jabra 550a, Kingston HyperX
+        *  needs a tiny delay here, otherwise requests like get/set
+        *  frequency return as failed despite actually succeeding.
         */
        if ((chip->usb_id == USB_ID(0x1686, 0x00dd) ||
             chip->usb_id == USB_ID(0x046d, 0x0a46) ||
+            chip->usb_id == USB_ID(0x046d, 0x0a56) ||
             chip->usb_id == USB_ID(0x0b0e, 0x0349) ||
             chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
            (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
index 56284b9..d295e40 100755 (executable)
@@ -137,6 +137,31 @@ $BOOTCONF $INITRD > $TEMPCONF
 cat $TEMPCONF
 xpass grep \'\"string\"\' $TEMPCONF
 
+echo "Repeat same-key tree"
+cat > $TEMPCONF << EOF
+foo
+bar
+foo { buz }
+EOF
+echo > $INITRD
+
+xpass $BOOTCONF -a $TEMPCONF $INITRD
+$BOOTCONF $INITRD > $OUTFILE
+xpass grep -q "bar" $OUTFILE
+
+
+echo "Remove/keep tailing spaces"
+cat > $TEMPCONF << EOF
+foo = val     # comment
+bar = "val2 " # comment
+EOF
+echo > $INITRD
+
+xpass $BOOTCONF -a $TEMPCONF $INITRD
+$BOOTCONF $INITRD > $OUTFILE
+xfail grep -q val[[:space:]] $OUTFILE
+xpass grep -q val2[[:space:]] $OUTFILE
+
 echo "=== expected failure cases ==="
 for i in samples/bad-* ; do
   xfail $BOOTCONF -a $i $INITRD
index 0a6d09a..39bb322 100644 (file)
@@ -38,7 +38,7 @@ FEATURE_TESTS = libbfd disassembler-four-args
 FEATURE_DISPLAY = libbfd disassembler-four-args
 
 check_feat := 1
-NON_CHECK_FEAT_TARGETS := clean bpftool_clean runqslower_clean
+NON_CHECK_FEAT_TARGETS := clean bpftool_clean runqslower_clean resolve_btfids_clean
 ifdef MAKECMDGOALS
 ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
   check_feat := 0
@@ -89,7 +89,7 @@ $(OUTPUT)bpf_exp.lex.c: $(OUTPUT)bpf_exp.yacc.c
 $(OUTPUT)bpf_exp.yacc.o: $(OUTPUT)bpf_exp.yacc.c
 $(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.lex.c
 
-clean: bpftool_clean runqslower_clean
+clean: bpftool_clean runqslower_clean resolve_btfids_clean
        $(call QUIET_CLEAN, bpf-progs)
        $(Q)$(RM) -r -- $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
               $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
index 8462690..4828913 100644 (file)
@@ -25,7 +25,7 @@ endif
 
 LIBBPF = $(LIBBPF_PATH)libbpf.a
 
-BPFTOOL_VERSION := $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
+BPFTOOL_VERSION ?= $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
 
 $(LIBBPF): FORCE
        $(if $(LIBBPF_OUTPUT),@mkdir -p $(LIBBPF_OUTPUT))
index a88cd44..fe8eb53 100644 (file)
@@ -80,6 +80,7 @@ libbpf-clean:
 clean: libsubcmd-clean libbpf-clean fixdep-clean
        $(call msg,CLEAN,$(BINARY))
        $(Q)$(RM) -f $(BINARY); \
+       $(RM) -rf $(if $(OUTPUT),$(OUTPUT),.)/feature; \
        find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o -or -name \*.o.cmd -or -name \*.o.d | xargs $(RM)
 
 tags:
index 3d0d823..7d66876 100644 (file)
@@ -135,7 +135,7 @@ struct in_addr {
  * this socket to prevent accepting spoofed ones.
  */
 #define IP_PMTUDISC_INTERFACE          4
-/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get
+/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get
  * fragmented if they exeed the interface mtu
  */
 #define IP_PMTUDISC_OMIT               5
index f6d8603..7d8eced 100644 (file)
@@ -790,9 +790,10 @@ struct kvm_ppc_resize_hpt {
 #define KVM_VM_PPC_HV 1
 #define KVM_VM_PPC_PR 2
 
-/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */
-#define KVM_VM_MIPS_TE         0
+/* on MIPS, 0 indicates auto, 1 forces VZ ASE, 2 forces trap & emulate */
+#define KVM_VM_MIPS_AUTO       0
 #define KVM_VM_MIPS_VZ         1
+#define KVM_VM_MIPS_TE         2
 
 #define KVM_S390_SIE_PAGE_OFFSET 1
 
@@ -1035,6 +1036,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_LAST_CPU 184
 #define KVM_CAP_SMALLER_MAXPHYADDR 185
 #define KVM_CAP_S390_DIAG318 186
+#define KVM_CAP_STEAL_TIME 187
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index 0f25713..7703f01 100644 (file)
@@ -130,7 +130,7 @@ static int io_uring_register_files(struct submitter *s)
                                        s->nr_files);
 }
 
-static int gettid(void)
+static int lk_gettid(void)
 {
        return syscall(__NR_gettid);
 }
@@ -281,7 +281,7 @@ static void *submitter_fn(void *data)
        struct io_sq_ring *ring = &s->sq_ring;
        int ret, prepped;
 
-       printf("submitter=%d\n", gettid());
+       printf("submitter=%d\n", lk_gettid());
 
        srand48_r(pthread_self(), &s->rand);
 
index bf8ed13..9ae8f4e 100644 (file)
@@ -59,7 +59,7 @@ FEATURE_USER = .libbpf
 FEATURE_TESTS = libelf libelf-mmap zlib bpf reallocarray
 FEATURE_DISPLAY = libelf zlib bpf
 
-INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
+INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/include/uapi
 FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES)
 
 check_feat := 1
@@ -152,6 +152,7 @@ GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \
                           awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
                           sort -u | wc -l)
 VERSIONED_SYM_COUNT = $(shell readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
+                             awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
                              grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
 
 CMD_TARGETS = $(LIB_TARGET) $(PC_FILE)
@@ -219,6 +220,7 @@ check_abi: $(OUTPUT)libbpf.so
                    awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'|  \
                    sort -u > $(OUTPUT)libbpf_global_syms.tmp;           \
                readelf --dyn-syms --wide $(OUTPUT)libbpf.so |           \
+                   awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'|  \
                    grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 |             \
                    sort -u > $(OUTPUT)libbpf_versioned_syms.tmp;        \
                diff -u $(OUTPUT)libbpf_global_syms.tmp                  \
index 7dfca70..6bdbc38 100644 (file)
@@ -659,6 +659,12 @@ struct btf *btf__parse_raw(const char *path)
                err = -EIO;
                goto err_out;
        }
+       if (magic == __bswap_16(BTF_MAGIC)) {
+               /* non-native endian raw BTF */
+               pr_warn("non-native BTF endianness is not supported\n");
+               err = -LIBBPF_ERRNO__ENDIAN;
+               goto err_out;
+       }
        if (magic != BTF_MAGIC) {
                /* definitely not a raw BTF */
                err = -EPROTO;
index 0ad0b04..e493d60 100644 (file)
@@ -5203,8 +5203,8 @@ static int bpf_object__collect_map_relos(struct bpf_object *obj,
        int i, j, nrels, new_sz;
        const struct btf_var_secinfo *vi = NULL;
        const struct btf_type *sec, *var, *def;
+       struct bpf_map *map = NULL, *targ_map;
        const struct btf_member *member;
-       struct bpf_map *map, *targ_map;
        const char *name, *mname;
        Elf_Data *symbols;
        unsigned int moff;
@@ -6925,7 +6925,7 @@ static const struct bpf_sec_def section_defs[] = {
                                                BPF_XDP_DEVMAP),
        BPF_EAPROG_SEC("xdp_cpumap/",           BPF_PROG_TYPE_XDP,
                                                BPF_XDP_CPUMAP),
-       BPF_EAPROG_SEC("xdp",                   BPF_PROG_TYPE_XDP,
+       BPF_APROG_SEC("xdp",                    BPF_PROG_TYPE_XDP,
                                                BPF_XDP),
        BPF_PROG_SEC("perf_event",              BPF_PROG_TYPE_PERF_EVENT),
        BPF_PROG_SEC("lwt_in",                  BPF_PROG_TYPE_LWT_IN),
index e034a8f..90a6689 100644 (file)
@@ -619,7 +619,7 @@ static int add_jump_destinations(struct objtool_file *file)
                if (!is_static_jump(insn))
                        continue;
 
-               if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET)
+               if (insn->offset == FAKE_JUMP_OFFSET)
                        continue;
 
                reloc = find_reloc_by_dest_range(file->elf, insn->sec,
index 71d830d..cecce93 100644 (file)
@@ -66,11 +66,10 @@ static void fdpair(int fds[2])
 /* Block until we're ready to go */
 static void ready(int ready_out, int wakefd)
 {
-       char dummy;
        struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
 
        /* Tell them we're ready. */
-       if (write(ready_out, &dummy, 1) != 1)
+       if (write(ready_out, "R", 1) != 1)
                err(EXIT_FAILURE, "CLIENT: ready write");
 
        /* Wait for "GO" signal */
@@ -85,6 +84,7 @@ static void *sender(struct sender_context *ctx)
        unsigned int i, j;
 
        ready(ctx->ready_out, ctx->wakefd);
+       memset(data, 'S', sizeof(data));
 
        /* Now pump to every receiver. */
        for (i = 0; i < nr_loops; i++) {
index 7e1aa82..653b11b 100644 (file)
@@ -61,7 +61,7 @@
   {
     "EventName": "ex_ret_brn_ind_misp",
     "EventCode": "0xca",
-    "BriefDescription": "Retired Indirect Branch Instructions Mispredicted.",
+    "BriefDescription": "Retired Indirect Branch Instructions Mispredicted."
   },
   {
     "EventName": "ex_ret_mmx_fp_instr.sse_instr",
index de89e5a..4b75183 100644 (file)
   {
     "EventName": "ex_ret_fus_brnch_inst",
     "EventCode": "0x1d0",
-    "BriefDescription": "Retired Fused Instructions. The number of fuse-branch instructions retired per cycle. The number of events logged per cycle can vary from 0-8.",
+    "BriefDescription": "Retired Fused Instructions. The number of fuse-branch instructions retired per cycle. The number of events logged per cycle can vary from 0-8."
   }
 ]
index 6cd4081..a36f49f 100644 (file)
@@ -49,6 +49,7 @@ Following tests are defined (with perf commands):
   perf record --call-graph fp kill              (test-record-graph-fp)
   perf record --group -e cycles,instructions kill (test-record-group)
   perf record -e '{cycles,instructions}' kill   (test-record-group1)
+  perf record -e '{cycles/period=1/,instructions/period=2/}:S' kill (test-record-group2)
   perf record -D kill                           (test-record-no-delay)
   perf record -i kill                           (test-record-no-inherit)
   perf record -n kill                           (test-record-no-samples)
diff --git a/tools/perf/tests/attr/test-record-group2 b/tools/perf/tests/attr/test-record-group2
new file mode 100644 (file)
index 0000000..6b9f8d1
--- /dev/null
@@ -0,0 +1,29 @@
+[config]
+command = record
+args    = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1
+ret     = 1
+
+[event-1:base-record]
+fd=1
+group_fd=-1
+config=0|1
+sample_period=1234000
+sample_type=87
+read_format=12
+inherit=0
+freq=0
+
+[event-2:base-record]
+fd=2
+group_fd=1
+config=0|1
+sample_period=6789000
+sample_type=87
+read_format=12
+disabled=0
+inherit=0
+mmap=0
+comm=0
+freq=0
+enable_on_exec=0
+task=0
index da8ec1e..cc9fbce 100644 (file)
@@ -45,10 +45,13 @@ volatile long the_var;
 #if defined (__x86_64__)
 extern void __test_function(volatile long *ptr);
 asm (
+       ".pushsection .text;"
        ".globl __test_function\n"
+       ".type __test_function, @function;"
        "__test_function:\n"
        "incq (%rdi)\n"
-       "ret\n");
+       "ret\n"
+       ".popsection\n");
 #else
 static void __test_function(volatile long *ptr)
 {
index 23db8ac..cd7331a 100644 (file)
@@ -153,8 +153,10 @@ static int __compute_metric(const char *name, struct value *vals,
                return -ENOMEM;
 
        cpus = perf_cpu_map__new("0");
-       if (!cpus)
+       if (!cpus) {
+               evlist__delete(evlist);
                return -ENOMEM;
+       }
 
        perf_evlist__set_maps(&evlist->core, cpus, NULL);
 
@@ -163,10 +165,11 @@ static int __compute_metric(const char *name, struct value *vals,
                                             false, false,
                                             &metric_events);
        if (err)
-               return err;
+               goto out;
 
-       if (perf_evlist__alloc_stats(evlist, false))
-               return -1;
+       err = perf_evlist__alloc_stats(evlist, false);
+       if (err)
+               goto out;
 
        /* Load the runtime stats with given numbers for events. */
        runtime_stat__init(&st);
@@ -178,13 +181,14 @@ static int __compute_metric(const char *name, struct value *vals,
        if (name2 && ratio2)
                *ratio2 = compute_single(&metric_events, evlist, &st, name2);
 
+out:
        /* ... clenup. */
        metricgroup__rblist_exit(&metric_events);
        runtime_stat__exit(&st);
        perf_evlist__free_stats(evlist);
        perf_cpu_map__put(cpus);
        evlist__delete(evlist);
-       return 0;
+       return err;
 }
 
 static int compute_metric(const char *name, struct value *vals, double *ratio)
index eb19f9a..d3517a7 100644 (file)
@@ -274,6 +274,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count)
        int res = 0;
        bool use_uncore_table;
        struct pmu_events_map *map = __test_pmu_get_events_map();
+       struct perf_pmu_alias *a, *tmp;
 
        if (!map)
                return -1;
@@ -347,6 +348,10 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count)
                          pmu_name, alias->name);
        }
 
+       list_for_each_entry_safe(a, tmp, &aliases, list) {
+               list_del(&a->list);
+               perf_pmu_free_alias(a);
+       }
        free(pmu);
        return res;
 }
index 5c11fe2..714e683 100644 (file)
@@ -173,6 +173,7 @@ int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
                ret = 0;
        } while (0);
 
+       perf_pmu__del_formats(&formats);
        test_format_dir_put(format);
        return ret;
 }
index e3fa3bf..c0768c6 100644 (file)
@@ -946,6 +946,10 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target)
 
        perf_evlist__set_maps(&evlist->core, cpus, threads);
 
+       /* as evlist now has references, put count here */
+       perf_cpu_map__put(cpus);
+       perf_thread_map__put(threads);
+
        return 0;
 
 out_delete_threads:
@@ -1273,11 +1277,12 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist)
                goto out_put;
 
        perf_evlist__set_maps(&evlist->core, cpus, threads);
-out:
-       return err;
+
+       perf_thread_map__put(threads);
 out_put:
        perf_cpu_map__put(cpus);
-       goto out;
+out:
+       return err;
 }
 
 int evlist__open(struct evlist *evlist)
index fd86500..459b51e 100644 (file)
@@ -976,16 +976,20 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
         * We default some events to have a default interval. But keep
         * it a weak assumption overridable by the user.
         */
-       if (!attr->sample_period || (opts->user_freq != UINT_MAX ||
-                                    opts->user_interval != ULLONG_MAX)) {
+       if (!attr->sample_period) {
                if (opts->freq) {
-                       evsel__set_sample_bit(evsel, PERIOD);
                        attr->freq              = 1;
                        attr->sample_freq       = opts->freq;
                } else {
                        attr->sample_period = opts->default_interval;
                }
        }
+       /*
+        * If attr->freq was set (here or earlier), ask for period
+        * to be sampled.
+        */
+       if (attr->freq)
+               evsel__set_sample_bit(evsel, PERIOD);
 
        if (opts->no_samples)
                attr->sample_freq = 0;
index 8831b96..ab5030f 100644 (file)
@@ -85,6 +85,7 @@ static void metric_event_delete(struct rblist *rblist __maybe_unused,
 
        list_for_each_entry_safe(expr, tmp, &me->head, nd) {
                free(expr->metric_refs);
+               free(expr->metric_events);
                free(expr);
        }
 
@@ -316,6 +317,7 @@ static int metricgroup__setup_events(struct list_head *groups,
                        if (!metric_refs) {
                                ret = -ENOMEM;
                                free(metric_events);
+                               free(expr);
                                break;
                        }
 
@@ -530,6 +532,9 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
                                                continue;
                                        strlist__add(me->metrics, s);
                                }
+
+                               if (!raw)
+                                       free(s);
                        }
                        free(omg);
                }
@@ -667,7 +672,6 @@ static int __add_metric(struct list_head *metric_list,
                m->has_constraint = metric_no_group || metricgroup__has_constraint(pe);
                INIT_LIST_HEAD(&m->metric_refs);
                m->metric_refs_cnt = 0;
-               *mp = m;
 
                parent = expr_ids__alloc(ids);
                if (!parent) {
@@ -680,6 +684,7 @@ static int __add_metric(struct list_head *metric_list,
                        free(m);
                        return -ENOMEM;
                }
+               *mp = m;
        } else {
                /*
                 * We got here for the referenced metric, via the
@@ -714,8 +719,11 @@ static int __add_metric(struct list_head *metric_list,
         * all the metric's IDs and add it to the parent context.
         */
        if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) {
-               expr__ctx_clear(&m->pctx);
-               free(m);
+               if (m->metric_refs_cnt == 0) {
+                       expr__ctx_clear(&m->pctx);
+                       free(m);
+                       *mp = NULL;
+               }
                return -EINVAL;
        }
 
@@ -934,7 +942,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
 
                ret = add_metric(&list, pe, metric_no_group, &m, NULL, &ids);
                if (ret)
-                       return ret;
+                       goto out;
 
                /*
                 * Process any possible referenced metrics
@@ -943,12 +951,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
                ret = resolve_metric(metric_no_group,
                                     &list, map, &ids);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
        /* End of pmu events. */
-       if (!has_match)
-               return -EINVAL;
+       if (!has_match) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        list_for_each_entry(m, &list, nd) {
                if (events->len > 0)
@@ -963,9 +973,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
                }
        }
 
+out:
+       /*
+        * add to metric_list so that they can be released
+        * even if it's failed
+        */
        list_splice(&list, metric_list);
        expr_ids__exit(&ids);
-       return 0;
+       return ret;
 }
 
 static int metricgroup__add_metric_list(const char *list, bool metric_no_group,
@@ -1040,7 +1055,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str,
        ret = metricgroup__add_metric_list(str, metric_no_group,
                                           &extra_events, &metric_list, map);
        if (ret)
-               return ret;
+               goto out;
        pr_debug("adding %s\n", extra_events.buf);
        bzero(&parse_error, sizeof(parse_error));
        ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu);
@@ -1048,11 +1063,11 @@ static int parse_groups(struct evlist *perf_evlist, const char *str,
                parse_events_print_error(&parse_error, extra_events.buf);
                goto out;
        }
-       strbuf_release(&extra_events);
        ret = metricgroup__setup_events(&metric_list, metric_no_merge,
                                        perf_evlist, metric_events);
 out:
        metricgroup__free_metrics(&metric_list);
+       strbuf_release(&extra_events);
        return ret;
 }
 
index c4d2394..667cbca 100644 (file)
@@ -411,7 +411,7 @@ static int add_event_tool(struct list_head *list, int *idx,
                return -ENOMEM;
        evsel->tool_event = tool_event;
        if (tool_event == PERF_TOOL_DURATION_TIME)
-               evsel->unit = strdup("ns");
+               evsel->unit = "ns";
        return 0;
 }
 
index f1688e1..d41caeb 100644 (file)
@@ -274,7 +274,7 @@ static void perf_pmu_update_alias(struct perf_pmu_alias *old,
 }
 
 /* Delete an alias entry. */
-static void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
+void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
 {
        zfree(&newalias->name);
        zfree(&newalias->desc);
@@ -1354,6 +1354,17 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
                set_bit(b, bits);
 }
 
+void perf_pmu__del_formats(struct list_head *formats)
+{
+       struct perf_pmu_format *fmt, *tmp;
+
+       list_for_each_entry_safe(fmt, tmp, formats, list) {
+               list_del(&fmt->list);
+               free(fmt->name);
+               free(fmt);
+       }
+}
+
 static int sub_non_neg(int a, int b)
 {
        if (b > a)
index 44ccbdb..a64e9c9 100644 (file)
@@ -94,6 +94,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
                         int config, unsigned long *bits);
 void perf_pmu__set_format(unsigned long *bits, long from, long to);
 int perf_pmu__format_parse(char *dir, struct list_head *head);
+void perf_pmu__del_formats(struct list_head *formats);
 
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
@@ -113,6 +114,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
 
 struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
 bool pmu_uncore_alias_match(const char *pmu_name, const char *name);
+void perf_pmu_free_alias(struct perf_pmu_alias *alias);
 
 int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
 
index a4cc115..ea9aa1d 100644 (file)
@@ -2,6 +2,7 @@
 #include "debug.h"
 #include "evlist.h"
 #include "evsel.h"
+#include "evsel_config.h"
 #include "parse-events.h"
 #include <errno.h>
 #include <limits.h>
@@ -33,11 +34,24 @@ static struct evsel *evsel__read_sampler(struct evsel *evsel, struct evlist *evl
        return leader;
 }
 
+static u64 evsel__config_term_mask(struct evsel *evsel)
+{
+       struct evsel_config_term *term;
+       struct list_head *config_terms = &evsel->config_terms;
+       u64 term_types = 0;
+
+       list_for_each_entry(term, config_terms, list) {
+               term_types |= 1 << term->type;
+       }
+       return term_types;
+}
+
 static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist)
 {
        struct perf_event_attr *attr = &evsel->core.attr;
        struct evsel *leader = evsel->leader;
        struct evsel *read_sampler;
+       u64 term_types, freq_mask;
 
        if (!leader->sample_read)
                return;
@@ -47,16 +61,20 @@ static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *ev
        if (evsel == read_sampler)
                return;
 
+       term_types = evsel__config_term_mask(evsel);
        /*
-        * Disable sampling for all group members other than the leader in
-        * case the leader 'leads' the sampling, except when the leader is an
-        * AUX area event, in which case the 2nd event in the group is the one
-        * that 'leads' the sampling.
+        * Disable sampling for all group members except those with explicit
+        * config terms or the leader. In the case of an AUX area event, the 2nd
+        * event in the group is the one that 'leads' the sampling.
         */
-       attr->freq           = 0;
-       attr->sample_freq    = 0;
-       attr->sample_period  = 0;
-       attr->write_backward = 0;
+       freq_mask = (1 << EVSEL__CONFIG_TERM_FREQ) | (1 << EVSEL__CONFIG_TERM_PERIOD);
+       if ((term_types & freq_mask) == 0) {
+               attr->freq           = 0;
+               attr->sample_freq    = 0;
+               attr->sample_period  = 0;
+       }
+       if ((term_types & (1 << EVSEL__CONFIG_TERM_OVERWRITE)) == 0)
+               attr->write_backward = 0;
 
        /*
         * We don't get a sample for slave events, we make them when delivering
index e1ba6c1..924b54d 100644 (file)
@@ -517,7 +517,7 @@ static void print_l1_dcache_misses(struct perf_stat_config *config,
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
+       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache accesses", ratio);
 }
 
 static void print_l1_icache_misses(struct perf_stat_config *config,
@@ -538,7 +538,7 @@ static void print_l1_icache_misses(struct perf_stat_config *config,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
+       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache accesses", ratio);
 }
 
 static void print_dtlb_cache_misses(struct perf_stat_config *config,
@@ -558,7 +558,7 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
+       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache accesses", ratio);
 }
 
 static void print_itlb_cache_misses(struct perf_stat_config *config,
@@ -578,7 +578,7 @@ static void print_itlb_cache_misses(struct perf_stat_config *config,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
+       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache accesses", ratio);
 }
 
 static void print_ll_cache_misses(struct perf_stat_config *config,
@@ -598,7 +598,7 @@ static void print_ll_cache_misses(struct perf_stat_config *config,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
+       out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache accesses", ratio);
 }
 
 /*
@@ -853,14 +853,16 @@ static void generic_metric(struct perf_stat_config *config,
 double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st)
 {
        struct expr_parse_ctx pctx;
-       double ratio;
+       double ratio = 0.0;
 
        if (prepare_metric(mexp->metric_events, mexp->metric_refs, &pctx, cpu, st) < 0)
-               return 0.;
+               goto out;
 
        if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1))
-               return 0.;
+               ratio = 0.0;
 
+out:
+       expr__ctx_clear(&pctx);
        return ratio;
 }
 
@@ -918,7 +920,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
                        print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
                else
-                       print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
+                       print_metric(config, ctxp, NULL, NULL, "of all L1-dcache accesses", 0);
        } else if (
                evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
                evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
@@ -928,7 +930,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
                        print_l1_icache_misses(config, cpu, evsel, avg, out, st);
                else
-                       print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
+                       print_metric(config, ctxp, NULL, NULL, "of all L1-icache accesses", 0);
        } else if (
                evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
                evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
@@ -938,7 +940,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
                        print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
                else
-                       print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
+                       print_metric(config, ctxp, NULL, NULL, "of all dTLB cache accesses", 0);
        } else if (
                evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
                evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
@@ -948,7 +950,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
                        print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
                else
-                       print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
+                       print_metric(config, ctxp, NULL, NULL, "of all iTLB cache accesses", 0);
        } else if (
                evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
                evsel->core.attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
@@ -958,7 +960,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
                        print_ll_cache_misses(config, cpu, evsel, avg, out, st);
                else
-                       print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0);
+                       print_metric(config, ctxp, NULL, NULL, "of all LL-cache accesses", 0);
        } else if (evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
                total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
 
index 07ddbfd..6dfce3f 100644 (file)
@@ -47,7 +47,10 @@ int dump_bpf_hash_map(struct bpf_iter__bpf_map_elem *ctx)
        __u32 seq_num = ctx->meta->seq_num;
        struct bpf_map *map = ctx->map;
        struct key_t *key = ctx->key;
+       struct key_t tmp_key;
        __u64 *val = ctx->value;
+       __u64 tmp_val = 0;
+       int ret;
 
        if (in_test_mode) {
                /* test mode is used by selftests to
@@ -61,6 +64,18 @@ int dump_bpf_hash_map(struct bpf_iter__bpf_map_elem *ctx)
                if (key == (void *)0 || val == (void *)0)
                        return 0;
 
+               /* update the value and then delete the <key, value> pair.
+                * it should not impact the existing 'val' which is still
+                * accessible under rcu.
+                */
+               __builtin_memcpy(&tmp_key, key, sizeof(struct key_t));
+               ret = bpf_map_update_elem(&hashmap1, &tmp_key, &tmp_val, 0);
+               if (ret)
+                       return 0;
+               ret = bpf_map_delete_elem(&hashmap1, &tmp_key);
+               if (ret)
+                       return 0;
+
                key_sum_a += key->a;
                key_sum_b += key->b;
                key_sum_c += key->c;
index b8d14f9..2fc6b3a 100644 (file)
@@ -73,7 +73,7 @@ int main(void)
        int i;
        /* Instruction lengths starting at ss_start */
        int ss_size[4] = {
-               3,              /* xor */
+               2,              /* xor */
                2,              /* cpuid */
                5,              /* mov */
                2,              /* rdmsr */
index 7c38a90..8a2fe6d 100755 (executable)
@@ -1175,6 +1175,51 @@ kci_test_neigh_get()
        echo "PASS: neigh get"
 }
 
+kci_test_bridge_parent_id()
+{
+       local ret=0
+       sysfsnet=/sys/bus/netdevsim/devices/netdevsim
+       probed=false
+
+       if [ ! -w /sys/bus/netdevsim/new_device ] ; then
+               modprobe -q netdevsim
+               check_err $?
+               if [ $ret -ne 0 ]; then
+                       echo "SKIP: bridge_parent_id can't load netdevsim"
+                       return $ksft_skip
+               fi
+               probed=true
+       fi
+
+       echo "10 1" > /sys/bus/netdevsim/new_device
+       while [ ! -d ${sysfsnet}10 ] ; do :; done
+       echo "20 1" > /sys/bus/netdevsim/new_device
+       while [ ! -d ${sysfsnet}20 ] ; do :; done
+       udevadm settle
+       dev10=`ls ${sysfsnet}10/net/`
+       dev20=`ls ${sysfsnet}20/net/`
+
+       ip link add name test-bond0 type bond mode 802.3ad
+       ip link set dev $dev10 master test-bond0
+       ip link set dev $dev20 master test-bond0
+       ip link add name test-br0 type bridge
+       ip link set dev test-bond0 master test-br0
+       check_err $?
+
+       # clean up any leftovers
+       ip link del dev test-br0
+       ip link del dev test-bond0
+       echo 20 > /sys/bus/netdevsim/del_device
+       echo 10 > /sys/bus/netdevsim/del_device
+       $probed && rmmod netdevsim
+
+       if [ $ret -ne 0 ]; then
+               echo "FAIL: bridge_parent_id"
+               return 1
+       fi
+       echo "PASS: bridge_parent_id"
+}
+
 kci_test_rtnl()
 {
        local ret=0
@@ -1224,6 +1269,8 @@ kci_test_rtnl()
        check_err $?
        kci_test_neigh_get
        check_err $?
+       kci_test_bridge_parent_id
+       check_err $?
 
        kci_del_dummy
        return $ret
index e0cf8eb..30b71b1 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <unistd.h>
 
 #include <asm/cputable.h>
 
@@ -18,9 +19,13 @@ int test_prot_sao(void)
 {
        char *p;
 
-       /* SAO was introduced in 2.06 and removed in 3.1 */
+       /*
+        * SAO was introduced in 2.06 and removed in 3.1. It's disabled in
+        * guests/LPARs by default, so also skip if we are running in a guest.
+        */
        SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06) ||
-               have_hwcap2(PPC_FEATURE2_ARCH_3_1));
+               have_hwcap2(PPC_FEATURE2_ARCH_3_1) ||
+               access("/proc/device-tree/rtas/ibm,hypertas-functions", F_OK) == 0);
 
        /*
         * Ensure we can ask for PROT_SAO.
index 7656c7c..0e73a16 100644 (file)
@@ -13,6 +13,7 @@ DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
 
 TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS)
 
+TEST_FILES := settings
 
 include ../lib.mk
 
diff --git a/tools/testing/selftests/timers/settings b/tools/testing/selftests/timers/settings
new file mode 100644 (file)
index 0000000..e7b9417
--- /dev/null
@@ -0,0 +1 @@
+timeout=0
index 6af9519..312889e 100644 (file)
@@ -83,7 +83,7 @@ int main(int argc, char **argv)
        }
 
        if (shift)
-               printf("%u kB hugepages\n", 1 << shift);
+               printf("%u kB hugepages\n", 1 << (shift - 10));
        else
                printf("Default size hugepages\n");
        printf("Mapping %lu Mbytes\n", (unsigned long)length >> 20);
index 67cd0b8..cf88233 100644 (file)
@@ -4332,7 +4332,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
                               struct kvm_io_device *dev)
 {
-       int i;
+       int i, j;
        struct kvm_io_bus *new_bus, *bus;
 
        bus = kvm_get_bus(kvm, bus_idx);
@@ -4349,17 +4349,20 @@ void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
 
        new_bus = kmalloc(struct_size(bus, range, bus->dev_count - 1),
                          GFP_KERNEL_ACCOUNT);
-       if (!new_bus)  {
+       if (new_bus) {
+               memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range));
+               new_bus->dev_count--;
+               memcpy(new_bus->range + i, bus->range + i + 1,
+                      (new_bus->dev_count - i) * sizeof(struct kvm_io_range));
+       } else {
                pr_err("kvm: failed to shrink bus, removing it completely\n");
-               goto broken;
+               for (j = 0; j < bus->dev_count; j++) {
+                       if (j == i)
+                               continue;
+                       kvm_iodevice_destructor(bus->range[j].dev);
+               }
        }
 
-       memcpy(new_bus, bus, sizeof(*bus) + i * sizeof(struct kvm_io_range));
-       new_bus->dev_count--;
-       memcpy(new_bus->range + i, bus->range + i + 1,
-              (new_bus->dev_count - i) * sizeof(struct kvm_io_range));
-
-broken:
        rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
        synchronize_srcu_expedited(&kvm->srcu);
        kfree(bus);